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

ccwgroup: Unify parsing for group attribute.

Instead of having each driver for ccwgroup slave device parsing the
input itself and calling ccwgroup_create(), introduce a new function
ccwgroup_create_from_string() and handle parsing inside the ccwgroup
core.

Signed-off-by: Ursula Braun <braunu@de.ibm.com>
Signed-off-by: Frank Blaschka <frank.blaschka@de.ibm.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>

authored by

Ursula Braun and committed by
Jeff Garzik
022b660a 8bbf8440

+82 -64
+75 -21
drivers/s390/cio/ccwgroup.c
··· 153 153 return 0; 154 154 } 155 155 156 + static int __get_next_bus_id(const char **buf, char *bus_id) 157 + { 158 + int rc, len; 159 + char *start, *end; 160 + 161 + start = (char *)*buf; 162 + end = strchr(start, ','); 163 + if (!end) { 164 + /* Last entry. Strip trailing newline, if applicable. */ 165 + end = strchr(start, '\n'); 166 + if (end) 167 + *end = '\0'; 168 + len = strlen(start) + 1; 169 + } else { 170 + len = end - start + 1; 171 + end++; 172 + } 173 + if (len < BUS_ID_SIZE) { 174 + strlcpy(bus_id, start, len); 175 + rc = 0; 176 + } else 177 + rc = -EINVAL; 178 + *buf = end; 179 + return rc; 180 + } 181 + 182 + static int __is_valid_bus_id(char bus_id[BUS_ID_SIZE]) 183 + { 184 + int cssid, ssid, devno; 185 + 186 + /* Must be of form %x.%x.%04x */ 187 + if (sscanf(bus_id, "%x.%1x.%04x", &cssid, &ssid, &devno) != 3) 188 + return 0; 189 + return 1; 190 + } 191 + 156 192 /** 157 - * ccwgroup_create() - create and register a ccw group device 193 + * ccwgroup_create_from_string() - create and register a ccw group device 158 194 * @root: parent device for the new device 159 195 * @creator_id: identifier of creating driver 160 196 * @cdrv: ccw driver of slave devices 161 - * @argc: number of slave devices 162 - * @argv: bus ids of slave devices 197 + * @num_devices: number of slave devices 198 + * @buf: buffer containing comma separated bus ids of slave devices 163 199 * 164 200 * Create and register a new ccw group device as a child of @root. Slave 165 - * devices are obtained from the list of bus ids given in @argv[] and must all 201 + * devices are obtained from the list of bus ids given in @buf and must all 166 202 * belong to @cdrv. 167 203 * Returns: 168 204 * %0 on success and an error code on failure. 169 205 * Context: 170 206 * non-atomic 171 207 */ 172 - int ccwgroup_create(struct device *root, unsigned int creator_id, 173 - struct ccw_driver *cdrv, int argc, char *argv[]) 208 + int ccwgroup_create_from_string(struct device *root, unsigned int creator_id, 209 + struct ccw_driver *cdrv, int num_devices, 210 + const char *buf) 174 211 { 175 212 struct ccwgroup_device *gdev; 176 - int i; 177 - int rc; 213 + int rc, i; 214 + char tmp_bus_id[BUS_ID_SIZE]; 215 + const char *curr_buf; 178 216 179 - if (argc > 256) /* disallow dumb users */ 180 - return -EINVAL; 181 - 182 - gdev = kzalloc(sizeof(*gdev) + argc*sizeof(gdev->cdev[0]), GFP_KERNEL); 217 + gdev = kzalloc(sizeof(*gdev) + num_devices * sizeof(gdev->cdev[0]), 218 + GFP_KERNEL); 183 219 if (!gdev) 184 220 return -ENOMEM; 185 221 186 222 atomic_set(&gdev->onoff, 0); 187 223 mutex_init(&gdev->reg_mutex); 188 224 mutex_lock(&gdev->reg_mutex); 189 - for (i = 0; i < argc; i++) { 190 - gdev->cdev[i] = get_ccwdev_by_busid(cdrv, argv[i]); 191 - 192 - /* all devices have to be of the same type in 193 - * order to be grouped */ 225 + curr_buf = buf; 226 + for (i = 0; i < num_devices && curr_buf; i++) { 227 + rc = __get_next_bus_id(&curr_buf, tmp_bus_id); 228 + if (rc != 0) 229 + goto error; 230 + if (!__is_valid_bus_id(tmp_bus_id)) { 231 + rc = -EINVAL; 232 + goto error; 233 + } 234 + gdev->cdev[i] = get_ccwdev_by_busid(cdrv, tmp_bus_id); 235 + /* 236 + * All devices have to be of the same type in 237 + * order to be grouped. 238 + */ 194 239 if (!gdev->cdev[i] 195 240 || gdev->cdev[i]->id.driver_info != 196 241 gdev->cdev[0]->id.driver_info) { ··· 249 204 } 250 205 dev_set_drvdata(&gdev->cdev[i]->dev, gdev); 251 206 } 252 - 207 + /* Check for sufficient number of bus ids. */ 208 + if (i < num_devices && !curr_buf) { 209 + rc = -EINVAL; 210 + goto error; 211 + } 212 + /* Check for trailing stuff. */ 213 + if (i == num_devices && strlen(curr_buf) > 0) { 214 + rc = -EINVAL; 215 + goto error; 216 + } 253 217 gdev->creator_id = creator_id; 254 - gdev->count = argc; 218 + gdev->count = num_devices; 255 219 gdev->dev.bus = &ccwgroup_bus_type; 256 220 gdev->dev.parent = root; 257 221 gdev->dev.release = ccwgroup_release; ··· 288 234 device_remove_file(&gdev->dev, &dev_attr_ungroup); 289 235 device_unregister(&gdev->dev); 290 236 error: 291 - for (i = 0; i < argc; i++) 237 + for (i = 0; i < num_devices; i++) 292 238 if (gdev->cdev[i]) { 293 239 if (dev_get_drvdata(&gdev->cdev[i]->dev) == gdev) 294 240 dev_set_drvdata(&gdev->cdev[i]->dev, NULL); ··· 298 244 put_device(&gdev->dev); 299 245 return rc; 300 246 } 247 + EXPORT_SYMBOL(ccwgroup_create_from_string); 301 248 302 249 static int __init 303 250 init_ccwgroup (void) ··· 574 519 MODULE_LICENSE("GPL"); 575 520 EXPORT_SYMBOL(ccwgroup_driver_register); 576 521 EXPORT_SYMBOL(ccwgroup_driver_unregister); 577 - EXPORT_SYMBOL(ccwgroup_create); 578 522 EXPORT_SYMBOL(ccwgroup_probe_ccwdev); 579 523 EXPORT_SYMBOL(ccwgroup_remove_ccwdev);
+2 -18
drivers/s390/net/cu3088.c
··· 62 62 static ssize_t 63 63 group_write(struct device_driver *drv, const char *buf, size_t count) 64 64 { 65 - const char *start, *end; 66 - char bus_ids[2][BUS_ID_SIZE], *argv[2]; 67 - int i; 68 65 int ret; 69 66 struct ccwgroup_driver *cdrv; 70 67 71 68 cdrv = to_ccwgroupdrv(drv); 72 69 if (!cdrv) 73 70 return -EINVAL; 74 - start = buf; 75 - for (i=0; i<2; i++) { 76 - static const char delim[] = {',', '\n'}; 77 - int len; 78 - 79 - if (!(end = strchr(start, delim[i]))) 80 - return -EINVAL; 81 - len = min_t(ptrdiff_t, BUS_ID_SIZE, end - start + 1); 82 - strlcpy (bus_ids[i], start, len); 83 - argv[i] = bus_ids[i]; 84 - start = end + 1; 85 - } 86 - 87 - ret = ccwgroup_create(cu3088_root_dev, cdrv->driver_id, 88 - &cu3088_driver, 2, argv); 71 + ret = ccwgroup_create_from_string(cu3088_root_dev, cdrv->driver_id, 72 + &cu3088_driver, 2, buf); 89 73 90 74 return (ret == 0) ? count : ret; 91 75 }
+2 -21
drivers/s390/net/qeth_core_main.c
··· 3827 3827 static int qeth_core_driver_group(const char *buf, struct device *root_dev, 3828 3828 unsigned long driver_id) 3829 3829 { 3830 - const char *start, *end; 3831 - char bus_ids[3][BUS_ID_SIZE], *argv[3]; 3832 - int i; 3833 - 3834 - start = buf; 3835 - for (i = 0; i < 3; i++) { 3836 - static const char delim[] = { ',', ',', '\n' }; 3837 - int len; 3838 - 3839 - end = strchr(start, delim[i]); 3840 - if (!end) 3841 - return -EINVAL; 3842 - len = min_t(ptrdiff_t, BUS_ID_SIZE, end - start); 3843 - strncpy(bus_ids[i], start, len); 3844 - bus_ids[i][len] = '\0'; 3845 - start = end + 1; 3846 - argv[i] = bus_ids[i]; 3847 - } 3848 - 3849 - return (ccwgroup_create(root_dev, driver_id, 3850 - &qeth_ccw_driver, 3, argv)); 3830 + return ccwgroup_create_from_string(root_dev, driver_id, 3831 + &qeth_ccw_driver, 3, buf); 3851 3832 } 3852 3833 3853 3834 int qeth_core_hardsetup_card(struct qeth_card *card)
+3 -4
include/asm-s390/ccwgroup.h
··· 57 57 58 58 extern int ccwgroup_driver_register (struct ccwgroup_driver *cdriver); 59 59 extern void ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver); 60 - extern int ccwgroup_create (struct device *root, 61 - unsigned int creator_id, 62 - struct ccw_driver *gdrv, 63 - int argc, char *argv[]); 60 + int ccwgroup_create_from_string(struct device *root, unsigned int creator_id, 61 + struct ccw_driver *cdrv, int num_devices, 62 + const char *buf); 64 63 65 64 extern int ccwgroup_probe_ccwdev(struct ccw_device *cdev); 66 65 extern void ccwgroup_remove_ccwdev(struct ccw_device *cdev);