Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netdevsim: move max vf config to dev

max_vfs is a strange little beast because the file
hangs off of nsim's debugfs, but it configures a field
in the bus device. Move it to dev.c, let's look at it
as if the device driver was imposing VF limit based
on FW info (like pci_sriov_set_totalvfs()).

Again, when moving refactor the function not to hold
the vfs lock pointlessly while parsing the input.
Wrap the access from the read side in READ_ONCE()
to appease concurrency checkers. Do not check if
return value from snprintf() is negative...

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Jakub Kicinski and committed by
David S. Miller
a3353ec3 1c401078

+64 -82
-75
drivers/net/netdevsim/bus.c
··· 57 57 __ATTR(sriov_numvfs, 0664, nsim_bus_dev_numvfs_show, 58 58 nsim_bus_dev_numvfs_store); 59 59 60 - ssize_t nsim_bus_dev_max_vfs_read(struct file *file, 61 - char __user *data, 62 - size_t count, loff_t *ppos) 63 - { 64 - struct nsim_dev *nsim_dev = file->private_data; 65 - struct nsim_bus_dev *nsim_bus_dev = nsim_dev->nsim_bus_dev; 66 - char buf[11]; 67 - ssize_t len; 68 - 69 - len = snprintf(buf, sizeof(buf), "%u\n", nsim_bus_dev->max_vfs); 70 - if (len < 0) 71 - return len; 72 - 73 - return simple_read_from_buffer(data, count, ppos, buf, len); 74 - } 75 - 76 - ssize_t nsim_bus_dev_max_vfs_write(struct file *file, 77 - const char __user *data, 78 - size_t count, loff_t *ppos) 79 - { 80 - struct nsim_dev *nsim_dev = file->private_data; 81 - struct nsim_bus_dev *nsim_bus_dev = nsim_dev->nsim_bus_dev; 82 - struct nsim_vf_config *vfconfigs; 83 - ssize_t ret; 84 - char buf[10]; 85 - u32 val; 86 - 87 - if (*ppos != 0) 88 - return 0; 89 - 90 - if (count >= sizeof(buf)) 91 - return -ENOSPC; 92 - 93 - mutex_lock(&nsim_dev->vfs_lock); 94 - /* Reject if VFs are configured */ 95 - if (nsim_bus_dev->num_vfs) { 96 - ret = -EBUSY; 97 - goto unlock; 98 - } 99 - 100 - ret = copy_from_user(buf, data, count); 101 - if (ret) { 102 - ret = -EFAULT; 103 - goto unlock; 104 - } 105 - 106 - buf[count] = '\0'; 107 - ret = kstrtouint(buf, 10, &val); 108 - if (ret) { 109 - ret = -EIO; 110 - goto unlock; 111 - } 112 - 113 - /* max_vfs limited by the maximum number of provided port indexes */ 114 - if (val > NSIM_DEV_VF_PORT_INDEX_MAX - NSIM_DEV_VF_PORT_INDEX_BASE) { 115 - ret = -ERANGE; 116 - goto unlock; 117 - } 118 - 119 - vfconfigs = kcalloc(val, sizeof(struct nsim_vf_config), GFP_KERNEL | __GFP_NOWARN); 120 - if (!vfconfigs) { 121 - ret = -ENOMEM; 122 - goto unlock; 123 - } 124 - 125 - kfree(nsim_dev->vfconfigs); 126 - nsim_dev->vfconfigs = vfconfigs; 127 - nsim_bus_dev->max_vfs = val; 128 - *ppos += count; 129 - ret = count; 130 - unlock: 131 - mutex_unlock(&nsim_dev->vfs_lock); 132 - return ret; 133 - } 134 - 135 60 static ssize_t 136 61 new_port_store(struct device *dev, struct device_attribute *attr, 137 62 const char *buf, size_t count)
+64
drivers/net/netdevsim/dev.c
··· 227 227 .owner = THIS_MODULE, 228 228 }; 229 229 230 + static ssize_t nsim_bus_dev_max_vfs_read(struct file *file, char __user *data, 231 + size_t count, loff_t *ppos) 232 + { 233 + struct nsim_dev *nsim_dev = file->private_data; 234 + char buf[11]; 235 + ssize_t len; 236 + 237 + len = scnprintf(buf, sizeof(buf), "%u\n", 238 + READ_ONCE(nsim_dev->nsim_bus_dev->max_vfs)); 239 + 240 + return simple_read_from_buffer(data, count, ppos, buf, len); 241 + } 242 + 243 + static ssize_t nsim_bus_dev_max_vfs_write(struct file *file, 244 + const char __user *data, 245 + size_t count, loff_t *ppos) 246 + { 247 + struct nsim_vf_config *vfconfigs; 248 + struct nsim_dev *nsim_dev; 249 + char buf[10]; 250 + ssize_t ret; 251 + u32 val; 252 + 253 + if (*ppos != 0) 254 + return 0; 255 + 256 + if (count >= sizeof(buf)) 257 + return -ENOSPC; 258 + 259 + ret = copy_from_user(buf, data, count); 260 + if (ret) 261 + return -EFAULT; 262 + buf[count] = '\0'; 263 + 264 + ret = kstrtouint(buf, 10, &val); 265 + if (ret) 266 + return -EINVAL; 267 + 268 + /* max_vfs limited by the maximum number of provided port indexes */ 269 + if (val > NSIM_DEV_VF_PORT_INDEX_MAX - NSIM_DEV_VF_PORT_INDEX_BASE) 270 + return -ERANGE; 271 + 272 + vfconfigs = kcalloc(val, sizeof(struct nsim_vf_config), 273 + GFP_KERNEL | __GFP_NOWARN); 274 + if (!vfconfigs) 275 + return -ENOMEM; 276 + 277 + nsim_dev = file->private_data; 278 + mutex_lock(&nsim_dev->vfs_lock); 279 + /* Reject if VFs are configured */ 280 + if (nsim_dev_get_vfs(nsim_dev)) { 281 + ret = -EBUSY; 282 + } else { 283 + swap(nsim_dev->vfconfigs, vfconfigs); 284 + WRITE_ONCE(nsim_dev->nsim_bus_dev->max_vfs, val); 285 + *ppos += count; 286 + ret = count; 287 + } 288 + mutex_unlock(&nsim_dev->vfs_lock); 289 + 290 + kfree(vfconfigs); 291 + return ret; 292 + } 293 + 230 294 static const struct file_operations nsim_dev_max_vfs_fops = { 231 295 .open = simple_open, 232 296 .read = nsim_bus_dev_max_vfs_read,
-7
drivers/net/netdevsim/netdevsim.h
··· 317 317 u64 nsim_fib_get_val(struct nsim_fib_data *fib_data, 318 318 enum nsim_resource_id res_id, bool max); 319 319 320 - ssize_t nsim_bus_dev_max_vfs_read(struct file *file, 321 - char __user *data, 322 - size_t count, loff_t *ppos); 323 - ssize_t nsim_bus_dev_max_vfs_write(struct file *file, 324 - const char __user *data, 325 - size_t count, loff_t *ppos); 326 - 327 320 static inline bool nsim_dev_port_is_pf(struct nsim_dev_port *nsim_dev_port) 328 321 { 329 322 return nsim_dev_port->port_type == NSIM_DEV_PORT_TYPE_PF;