diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/firewire/fw-device.c | 93 |
1 files changed, 36 insertions, 57 deletions
diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c index a834221b7588..59451f524fc3 100644 --- a/drivers/firewire/fw-device.c +++ b/drivers/firewire/fw-device.c | |||
@@ -138,9 +138,6 @@ fw_unit_uevent(struct device *dev, char **envp, int num_envp, | |||
138 | int length = 0; | 138 | int length = 0; |
139 | int i = 0; | 139 | int i = 0; |
140 | 140 | ||
141 | if (!is_fw_unit(dev)) | ||
142 | goto out; | ||
143 | |||
144 | get_modalias(unit, modalias, sizeof modalias); | 141 | get_modalias(unit, modalias, sizeof modalias); |
145 | 142 | ||
146 | if (add_uevent_var(envp, num_envp, &i, | 143 | if (add_uevent_var(envp, num_envp, &i, |
@@ -148,7 +145,6 @@ fw_unit_uevent(struct device *dev, char **envp, int num_envp, | |||
148 | "MODALIAS=%s", modalias)) | 145 | "MODALIAS=%s", modalias)) |
149 | return -ENOMEM; | 146 | return -ENOMEM; |
150 | 147 | ||
151 | out: | ||
152 | envp[i] = NULL; | 148 | envp[i] = NULL; |
153 | 149 | ||
154 | return 0; | 150 | return 0; |
@@ -157,7 +153,6 @@ fw_unit_uevent(struct device *dev, char **envp, int num_envp, | |||
157 | struct bus_type fw_bus_type = { | 153 | struct bus_type fw_bus_type = { |
158 | .name = "firewire", | 154 | .name = "firewire", |
159 | .match = fw_unit_match, | 155 | .match = fw_unit_match, |
160 | .uevent = fw_unit_uevent, | ||
161 | }; | 156 | }; |
162 | EXPORT_SYMBOL(fw_bus_type); | 157 | EXPORT_SYMBOL(fw_bus_type); |
163 | 158 | ||
@@ -199,8 +194,8 @@ int fw_device_enable_phys_dma(struct fw_device *device) | |||
199 | EXPORT_SYMBOL(fw_device_enable_phys_dma); | 194 | EXPORT_SYMBOL(fw_device_enable_phys_dma); |
200 | 195 | ||
201 | static ssize_t | 196 | static ssize_t |
202 | show_modalias_attribute(struct device *dev, | 197 | modalias_show(struct device *dev, |
203 | struct device_attribute *attr, char *buf) | 198 | struct device_attribute *attr, char *buf) |
204 | { | 199 | { |
205 | struct fw_unit *unit = fw_unit(dev); | 200 | struct fw_unit *unit = fw_unit(dev); |
206 | int length; | 201 | int length; |
@@ -211,41 +206,37 @@ show_modalias_attribute(struct device *dev, | |||
211 | return length + 1; | 206 | return length + 1; |
212 | } | 207 | } |
213 | 208 | ||
214 | static struct device_attribute modalias_attribute = { | ||
215 | .attr = { .name = "modalias", .mode = S_IRUGO, }, | ||
216 | .show = show_modalias_attribute, | ||
217 | }; | ||
218 | |||
219 | static ssize_t | 209 | static ssize_t |
220 | show_config_rom_attribute(struct device *dev, | 210 | rom_index_show(struct device *dev, |
221 | struct device_attribute *attr, char *buf) | 211 | struct device_attribute *attr, char *buf) |
222 | { | 212 | { |
223 | struct fw_device *device = fw_device(dev); | 213 | struct fw_device *device = fw_device(dev->parent); |
224 | 214 | struct fw_unit *unit = fw_unit(dev); | |
225 | memcpy(buf, device->config_rom, device->config_rom_length * 4); | ||
226 | 215 | ||
227 | return device->config_rom_length * 4; | 216 | return snprintf(buf, PAGE_SIZE, "%d\n", |
217 | (int)(unit->directory - device->config_rom)); | ||
228 | } | 218 | } |
229 | 219 | ||
230 | static struct device_attribute config_rom_attribute = { | 220 | static struct device_attribute fw_unit_attributes[] = { |
231 | .attr = {.name = "config_rom", .mode = S_IRUGO,}, | 221 | __ATTR_RO(modalias), |
232 | .show = show_config_rom_attribute, | 222 | __ATTR_RO(rom_index), |
223 | __ATTR_NULL, | ||
233 | }; | 224 | }; |
234 | 225 | ||
235 | static ssize_t | 226 | static ssize_t |
236 | show_rom_index_attribute(struct device *dev, | 227 | config_rom_show(struct device *dev, |
237 | struct device_attribute *attr, char *buf) | 228 | struct device_attribute *attr, char *buf) |
238 | { | 229 | { |
239 | struct fw_device *device = fw_device(dev->parent); | 230 | struct fw_device *device = fw_device(dev); |
240 | struct fw_unit *unit = fw_unit(dev); | ||
241 | 231 | ||
242 | return snprintf(buf, PAGE_SIZE, "%d\n", | 232 | memcpy(buf, device->config_rom, device->config_rom_length * 4); |
243 | (int)(unit->directory - device->config_rom)); | 233 | |
234 | return device->config_rom_length * 4; | ||
244 | } | 235 | } |
245 | 236 | ||
246 | static struct device_attribute rom_index_attribute = { | 237 | static struct device_attribute fw_device_attributes[] = { |
247 | .attr = { .name = "rom_index", .mode = S_IRUGO, }, | 238 | __ATTR_RO(config_rom), |
248 | .show = show_rom_index_attribute, | 239 | __ATTR_NULL, |
249 | }; | 240 | }; |
250 | 241 | ||
251 | struct read_quadlet_callback_data { | 242 | struct read_quadlet_callback_data { |
@@ -370,9 +361,15 @@ static void fw_unit_release(struct device *dev) | |||
370 | kfree(unit); | 361 | kfree(unit); |
371 | } | 362 | } |
372 | 363 | ||
364 | static struct device_type fw_unit_type = { | ||
365 | .attrs = fw_unit_attributes, | ||
366 | .uevent = fw_unit_uevent, | ||
367 | .release = fw_unit_release, | ||
368 | }; | ||
369 | |||
373 | static int is_fw_unit(struct device *dev) | 370 | static int is_fw_unit(struct device *dev) |
374 | { | 371 | { |
375 | return dev->release == fw_unit_release; | 372 | return dev->type == &fw_unit_type; |
376 | } | 373 | } |
377 | 374 | ||
378 | static void create_units(struct fw_device *device) | 375 | static void create_units(struct fw_device *device) |
@@ -397,7 +394,7 @@ static void create_units(struct fw_device *device) | |||
397 | 394 | ||
398 | unit->directory = ci.p + value - 1; | 395 | unit->directory = ci.p + value - 1; |
399 | unit->device.bus = &fw_bus_type; | 396 | unit->device.bus = &fw_bus_type; |
400 | unit->device.release = fw_unit_release; | 397 | unit->device.type = &fw_unit_type; |
401 | unit->device.parent = &device->device; | 398 | unit->device.parent = &device->device; |
402 | snprintf(unit->device.bus_id, sizeof unit->device.bus_id, | 399 | snprintf(unit->device.bus_id, sizeof unit->device.bus_id, |
403 | "%s.%d", device->device.bus_id, i++); | 400 | "%s.%d", device->device.bus_id, i++); |
@@ -406,27 +403,12 @@ static void create_units(struct fw_device *device) | |||
406 | kfree(unit); | 403 | kfree(unit); |
407 | continue; | 404 | continue; |
408 | } | 405 | } |
409 | |||
410 | if (device_create_file(&unit->device, &modalias_attribute) < 0) { | ||
411 | device_unregister(&unit->device); | ||
412 | kfree(unit); | ||
413 | } | ||
414 | |||
415 | if (device_create_file(&unit->device, &rom_index_attribute) < 0) { | ||
416 | device_unregister(&unit->device); | ||
417 | kfree(unit); | ||
418 | } | ||
419 | } | 406 | } |
420 | } | 407 | } |
421 | 408 | ||
422 | static int shutdown_unit(struct device *device, void *data) | 409 | static int shutdown_unit(struct device *device, void *data) |
423 | { | 410 | { |
424 | struct fw_unit *unit = fw_unit(device); | 411 | device_unregister(device); |
425 | |||
426 | if (is_fw_unit(device)) { | ||
427 | device_remove_file(&unit->device, &modalias_attribute); | ||
428 | device_unregister(&unit->device); | ||
429 | } | ||
430 | 412 | ||
431 | return 0; | 413 | return 0; |
432 | } | 414 | } |
@@ -456,11 +438,15 @@ static void fw_device_shutdown(struct work_struct *work) | |||
456 | up_write(&fw_bus_type.subsys.rwsem); | 438 | up_write(&fw_bus_type.subsys.rwsem); |
457 | 439 | ||
458 | fw_device_cdev_remove(device); | 440 | fw_device_cdev_remove(device); |
459 | device_remove_file(&device->device, &config_rom_attribute); | ||
460 | device_for_each_child(&device->device, NULL, shutdown_unit); | 441 | device_for_each_child(&device->device, NULL, shutdown_unit); |
461 | device_unregister(&device->device); | 442 | device_unregister(&device->device); |
462 | } | 443 | } |
463 | 444 | ||
445 | static struct device_type fw_device_type = { | ||
446 | .attrs = fw_device_attributes, | ||
447 | .release = fw_device_release, | ||
448 | }; | ||
449 | |||
464 | /* These defines control the retry behavior for reading the config | 450 | /* These defines control the retry behavior for reading the config |
465 | * rom. It shouldn't be necessary to tweak these; if the device | 451 | * rom. It shouldn't be necessary to tweak these; if the device |
466 | * doesn't respond to a config rom read within 10 seconds, it's not | 452 | * doesn't respond to a config rom read within 10 seconds, it's not |
@@ -507,7 +493,7 @@ static void fw_device_init(struct work_struct *work) | |||
507 | goto error; | 493 | goto error; |
508 | 494 | ||
509 | device->device.bus = &fw_bus_type; | 495 | device->device.bus = &fw_bus_type; |
510 | device->device.release = fw_device_release; | 496 | device->device.type = &fw_device_type; |
511 | device->device.parent = device->card->device; | 497 | device->device.parent = device->card->device; |
512 | device->device.devt = MKDEV(fw_cdev_major, minor); | 498 | device->device.devt = MKDEV(fw_cdev_major, minor); |
513 | snprintf(device->device.bus_id, sizeof device->device.bus_id, | 499 | snprintf(device->device.bus_id, sizeof device->device.bus_id, |
@@ -518,11 +504,6 @@ static void fw_device_init(struct work_struct *work) | |||
518 | goto error_with_cdev; | 504 | goto error_with_cdev; |
519 | } | 505 | } |
520 | 506 | ||
521 | if (device_create_file(&device->device, &config_rom_attribute) < 0) { | ||
522 | fw_error("Failed to create config rom file.\n"); | ||
523 | goto error_with_device; | ||
524 | } | ||
525 | |||
526 | create_units(device); | 507 | create_units(device); |
527 | 508 | ||
528 | /* Transition the device to running state. If it got pulled | 509 | /* Transition the device to running state. If it got pulled |
@@ -549,8 +530,6 @@ static void fw_device_init(struct work_struct *work) | |||
549 | 530 | ||
550 | return; | 531 | return; |
551 | 532 | ||
552 | error_with_device: | ||
553 | device_del(&device->device); | ||
554 | error_with_cdev: | 533 | error_with_cdev: |
555 | down_write(&fw_bus_type.subsys.rwsem); | 534 | down_write(&fw_bus_type.subsys.rwsem); |
556 | idr_remove(&fw_device_idr, minor); | 535 | idr_remove(&fw_device_idr, minor); |