diff options
author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-07-24 16:53:15 -0400 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-07-24 16:53:15 -0400 |
commit | 08da591e14cf87247ec09b17c350235157a92fc3 (patch) | |
tree | d00a02154071c7013c31bc8dd1d3c12c86d5daca | |
parent | 6cdf6eb357c2681596b7b1672b92396ba82333d4 (diff) |
ide: add ide_device_{get,put}() helpers
* Add 'struct ide_host *host' field to ide_hwif_t and set it
in ide_host_alloc_all().
* Add ide_device_{get,put}() helpers loosely based on SCSI's
scsi_device_{get,put}() ones.
* Convert IDE device drivers to use ide_device_{get,put}().
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
-rw-r--r-- | drivers/ide/ide-cd.c | 12 | ||||
-rw-r--r-- | drivers/ide/ide-disk.c | 12 | ||||
-rw-r--r-- | drivers/ide/ide-floppy.c | 12 | ||||
-rw-r--r-- | drivers/ide/ide-probe.c | 2 | ||||
-rw-r--r-- | drivers/ide/ide-tape.c | 12 | ||||
-rw-r--r-- | drivers/ide/ide.c | 47 | ||||
-rw-r--r-- | drivers/scsi/ide-scsi.c | 8 | ||||
-rw-r--r-- | include/linux/ide.h | 7 |
8 files changed, 99 insertions, 13 deletions
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 4e73aeee4053..8f253e5f26a8 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c | |||
@@ -57,23 +57,29 @@ static DEFINE_MUTEX(idecd_ref_mutex); | |||
57 | #define ide_cd_g(disk) \ | 57 | #define ide_cd_g(disk) \ |
58 | container_of((disk)->private_data, struct cdrom_info, driver) | 58 | container_of((disk)->private_data, struct cdrom_info, driver) |
59 | 59 | ||
60 | static void ide_cd_release(struct kref *); | ||
61 | |||
60 | static struct cdrom_info *ide_cd_get(struct gendisk *disk) | 62 | static struct cdrom_info *ide_cd_get(struct gendisk *disk) |
61 | { | 63 | { |
62 | struct cdrom_info *cd = NULL; | 64 | struct cdrom_info *cd = NULL; |
63 | 65 | ||
64 | mutex_lock(&idecd_ref_mutex); | 66 | mutex_lock(&idecd_ref_mutex); |
65 | cd = ide_cd_g(disk); | 67 | cd = ide_cd_g(disk); |
66 | if (cd) | 68 | if (cd) { |
67 | kref_get(&cd->kref); | 69 | kref_get(&cd->kref); |
70 | if (ide_device_get(cd->drive)) { | ||
71 | kref_put(&cd->kref, ide_cd_release); | ||
72 | cd = NULL; | ||
73 | } | ||
74 | } | ||
68 | mutex_unlock(&idecd_ref_mutex); | 75 | mutex_unlock(&idecd_ref_mutex); |
69 | return cd; | 76 | return cd; |
70 | } | 77 | } |
71 | 78 | ||
72 | static void ide_cd_release(struct kref *); | ||
73 | |||
74 | static void ide_cd_put(struct cdrom_info *cd) | 79 | static void ide_cd_put(struct cdrom_info *cd) |
75 | { | 80 | { |
76 | mutex_lock(&idecd_ref_mutex); | 81 | mutex_lock(&idecd_ref_mutex); |
82 | ide_device_put(cd->drive); | ||
77 | kref_put(&cd->kref, ide_cd_release); | 83 | kref_put(&cd->kref, ide_cd_release); |
78 | mutex_unlock(&idecd_ref_mutex); | 84 | mutex_unlock(&idecd_ref_mutex); |
79 | } | 85 | } |
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index df5fe5756871..28d85b410f7c 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c | |||
@@ -56,23 +56,29 @@ static DEFINE_MUTEX(idedisk_ref_mutex); | |||
56 | #define ide_disk_g(disk) \ | 56 | #define ide_disk_g(disk) \ |
57 | container_of((disk)->private_data, struct ide_disk_obj, driver) | 57 | container_of((disk)->private_data, struct ide_disk_obj, driver) |
58 | 58 | ||
59 | static void ide_disk_release(struct kref *); | ||
60 | |||
59 | static struct ide_disk_obj *ide_disk_get(struct gendisk *disk) | 61 | static struct ide_disk_obj *ide_disk_get(struct gendisk *disk) |
60 | { | 62 | { |
61 | struct ide_disk_obj *idkp = NULL; | 63 | struct ide_disk_obj *idkp = NULL; |
62 | 64 | ||
63 | mutex_lock(&idedisk_ref_mutex); | 65 | mutex_lock(&idedisk_ref_mutex); |
64 | idkp = ide_disk_g(disk); | 66 | idkp = ide_disk_g(disk); |
65 | if (idkp) | 67 | if (idkp) { |
66 | kref_get(&idkp->kref); | 68 | kref_get(&idkp->kref); |
69 | if (ide_device_get(idkp->drive)) { | ||
70 | kref_put(&idkp->kref, ide_disk_release); | ||
71 | idkp = NULL; | ||
72 | } | ||
73 | } | ||
67 | mutex_unlock(&idedisk_ref_mutex); | 74 | mutex_unlock(&idedisk_ref_mutex); |
68 | return idkp; | 75 | return idkp; |
69 | } | 76 | } |
70 | 77 | ||
71 | static void ide_disk_release(struct kref *); | ||
72 | |||
73 | static void ide_disk_put(struct ide_disk_obj *idkp) | 78 | static void ide_disk_put(struct ide_disk_obj *idkp) |
74 | { | 79 | { |
75 | mutex_lock(&idedisk_ref_mutex); | 80 | mutex_lock(&idedisk_ref_mutex); |
81 | ide_device_put(idkp->drive); | ||
76 | kref_put(&idkp->kref, ide_disk_release); | 82 | kref_put(&idkp->kref, ide_disk_release); |
77 | mutex_unlock(&idedisk_ref_mutex); | 83 | mutex_unlock(&idedisk_ref_mutex); |
78 | } | 84 | } |
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 3d8e6dd0f41e..ca11a26746f1 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c | |||
@@ -158,23 +158,29 @@ static DEFINE_MUTEX(idefloppy_ref_mutex); | |||
158 | #define ide_floppy_g(disk) \ | 158 | #define ide_floppy_g(disk) \ |
159 | container_of((disk)->private_data, struct ide_floppy_obj, driver) | 159 | container_of((disk)->private_data, struct ide_floppy_obj, driver) |
160 | 160 | ||
161 | static void idefloppy_cleanup_obj(struct kref *); | ||
162 | |||
161 | static struct ide_floppy_obj *ide_floppy_get(struct gendisk *disk) | 163 | static struct ide_floppy_obj *ide_floppy_get(struct gendisk *disk) |
162 | { | 164 | { |
163 | struct ide_floppy_obj *floppy = NULL; | 165 | struct ide_floppy_obj *floppy = NULL; |
164 | 166 | ||
165 | mutex_lock(&idefloppy_ref_mutex); | 167 | mutex_lock(&idefloppy_ref_mutex); |
166 | floppy = ide_floppy_g(disk); | 168 | floppy = ide_floppy_g(disk); |
167 | if (floppy) | 169 | if (floppy) { |
168 | kref_get(&floppy->kref); | 170 | kref_get(&floppy->kref); |
171 | if (ide_device_get(floppy->drive)) { | ||
172 | kref_put(&floppy->kref, idefloppy_cleanup_obj); | ||
173 | floppy = NULL; | ||
174 | } | ||
175 | } | ||
169 | mutex_unlock(&idefloppy_ref_mutex); | 176 | mutex_unlock(&idefloppy_ref_mutex); |
170 | return floppy; | 177 | return floppy; |
171 | } | 178 | } |
172 | 179 | ||
173 | static void idefloppy_cleanup_obj(struct kref *); | ||
174 | |||
175 | static void ide_floppy_put(struct ide_floppy_obj *floppy) | 180 | static void ide_floppy_put(struct ide_floppy_obj *floppy) |
176 | { | 181 | { |
177 | mutex_lock(&idefloppy_ref_mutex); | 182 | mutex_lock(&idefloppy_ref_mutex); |
183 | ide_device_put(floppy->drive); | ||
178 | kref_put(&floppy->kref, idefloppy_cleanup_obj); | 184 | kref_put(&floppy->kref, idefloppy_cleanup_obj); |
179 | mutex_unlock(&idefloppy_ref_mutex); | 185 | mutex_unlock(&idefloppy_ref_mutex); |
180 | } | 186 | } |
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 890c15b1b3ae..9ab5892eaea1 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c | |||
@@ -1595,6 +1595,8 @@ struct ide_host *ide_host_alloc_all(const struct ide_port_info *d, | |||
1595 | 1595 | ||
1596 | ide_init_port_data(hwif, idx); | 1596 | ide_init_port_data(hwif, idx); |
1597 | 1597 | ||
1598 | hwif->host = host; | ||
1599 | |||
1598 | host->ports[i] = hwif; | 1600 | host->ports[i] = hwif; |
1599 | host->n_ports++; | 1601 | host->n_ports++; |
1600 | } | 1602 | } |
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 6962ca4891a1..789f3428f072 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c | |||
@@ -322,23 +322,29 @@ static struct class *idetape_sysfs_class; | |||
322 | #define ide_tape_g(disk) \ | 322 | #define ide_tape_g(disk) \ |
323 | container_of((disk)->private_data, struct ide_tape_obj, driver) | 323 | container_of((disk)->private_data, struct ide_tape_obj, driver) |
324 | 324 | ||
325 | static void ide_tape_release(struct kref *); | ||
326 | |||
325 | static struct ide_tape_obj *ide_tape_get(struct gendisk *disk) | 327 | static struct ide_tape_obj *ide_tape_get(struct gendisk *disk) |
326 | { | 328 | { |
327 | struct ide_tape_obj *tape = NULL; | 329 | struct ide_tape_obj *tape = NULL; |
328 | 330 | ||
329 | mutex_lock(&idetape_ref_mutex); | 331 | mutex_lock(&idetape_ref_mutex); |
330 | tape = ide_tape_g(disk); | 332 | tape = ide_tape_g(disk); |
331 | if (tape) | 333 | if (tape) { |
332 | kref_get(&tape->kref); | 334 | kref_get(&tape->kref); |
335 | if (ide_device_get(tape->drive)) { | ||
336 | kref_put(&tape->kref, ide_tape_release); | ||
337 | tape = NULL; | ||
338 | } | ||
339 | } | ||
333 | mutex_unlock(&idetape_ref_mutex); | 340 | mutex_unlock(&idetape_ref_mutex); |
334 | return tape; | 341 | return tape; |
335 | } | 342 | } |
336 | 343 | ||
337 | static void ide_tape_release(struct kref *); | ||
338 | |||
339 | static void ide_tape_put(struct ide_tape_obj *tape) | 344 | static void ide_tape_put(struct ide_tape_obj *tape) |
340 | { | 345 | { |
341 | mutex_lock(&idetape_ref_mutex); | 346 | mutex_lock(&idetape_ref_mutex); |
347 | ide_device_put(tape->drive); | ||
342 | kref_put(&tape->kref, ide_tape_release); | 348 | kref_put(&tape->kref, ide_tape_release); |
343 | mutex_unlock(&idetape_ref_mutex); | 349 | mutex_unlock(&idetape_ref_mutex); |
344 | } | 350 | } |
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 60f0ca66aa93..772451600e4d 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c | |||
@@ -618,6 +618,53 @@ set_val: | |||
618 | 618 | ||
619 | EXPORT_SYMBOL(generic_ide_ioctl); | 619 | EXPORT_SYMBOL(generic_ide_ioctl); |
620 | 620 | ||
621 | /** | ||
622 | * ide_device_get - get an additional reference to a ide_drive_t | ||
623 | * @drive: device to get a reference to | ||
624 | * | ||
625 | * Gets a reference to the ide_drive_t and increments the use count of the | ||
626 | * underlying LLDD module. | ||
627 | */ | ||
628 | int ide_device_get(ide_drive_t *drive) | ||
629 | { | ||
630 | struct device *host_dev; | ||
631 | struct module *module; | ||
632 | |||
633 | if (!get_device(&drive->gendev)) | ||
634 | return -ENXIO; | ||
635 | |||
636 | host_dev = drive->hwif->host->dev[0]; | ||
637 | module = host_dev ? host_dev->driver->owner : NULL; | ||
638 | |||
639 | if (module && !try_module_get(module)) { | ||
640 | put_device(&drive->gendev); | ||
641 | return -ENXIO; | ||
642 | } | ||
643 | |||
644 | return 0; | ||
645 | } | ||
646 | EXPORT_SYMBOL_GPL(ide_device_get); | ||
647 | |||
648 | /** | ||
649 | * ide_device_put - release a reference to a ide_drive_t | ||
650 | * @drive: device to release a reference on | ||
651 | * | ||
652 | * Release a reference to the ide_drive_t and decrements the use count of | ||
653 | * the underlying LLDD module. | ||
654 | */ | ||
655 | void ide_device_put(ide_drive_t *drive) | ||
656 | { | ||
657 | #ifdef CONFIG_MODULE_UNLOAD | ||
658 | struct device *host_dev = drive->hwif->host->dev[0]; | ||
659 | struct module *module = host_dev ? host_dev->driver->owner : NULL; | ||
660 | |||
661 | if (module) | ||
662 | module_put(module); | ||
663 | #endif | ||
664 | put_device(&drive->gendev); | ||
665 | } | ||
666 | EXPORT_SYMBOL_GPL(ide_device_put); | ||
667 | |||
621 | static int ide_bus_match(struct device *dev, struct device_driver *drv) | 668 | static int ide_bus_match(struct device *dev, struct device_driver *drv) |
622 | { | 669 | { |
623 | return 1; | 670 | return 1; |
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 538552495d48..318ef382448f 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c | |||
@@ -101,8 +101,13 @@ static struct ide_scsi_obj *ide_scsi_get(struct gendisk *disk) | |||
101 | 101 | ||
102 | mutex_lock(&idescsi_ref_mutex); | 102 | mutex_lock(&idescsi_ref_mutex); |
103 | scsi = ide_scsi_g(disk); | 103 | scsi = ide_scsi_g(disk); |
104 | if (scsi) | 104 | if (scsi) { |
105 | scsi_host_get(scsi->host); | 105 | scsi_host_get(scsi->host); |
106 | if (ide_device_get(scsi->drive)) { | ||
107 | scsi_host_put(scsi->host); | ||
108 | scsi = NULL; | ||
109 | } | ||
110 | } | ||
106 | mutex_unlock(&idescsi_ref_mutex); | 111 | mutex_unlock(&idescsi_ref_mutex); |
107 | return scsi; | 112 | return scsi; |
108 | } | 113 | } |
@@ -110,6 +115,7 @@ static struct ide_scsi_obj *ide_scsi_get(struct gendisk *disk) | |||
110 | static void ide_scsi_put(struct ide_scsi_obj *scsi) | 115 | static void ide_scsi_put(struct ide_scsi_obj *scsi) |
111 | { | 116 | { |
112 | mutex_lock(&idescsi_ref_mutex); | 117 | mutex_lock(&idescsi_ref_mutex); |
118 | ide_device_put(scsi->drive); | ||
113 | scsi_host_put(scsi->host); | 119 | scsi_host_put(scsi->host); |
114 | mutex_unlock(&idescsi_ref_mutex); | 120 | mutex_unlock(&idescsi_ref_mutex); |
115 | } | 121 | } |
diff --git a/include/linux/ide.h b/include/linux/ide.h index 776c574c9640..3eccac0a2a36 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h | |||
@@ -532,12 +532,16 @@ struct ide_dma_ops { | |||
532 | void (*dma_timeout)(struct ide_drive_s *); | 532 | void (*dma_timeout)(struct ide_drive_s *); |
533 | }; | 533 | }; |
534 | 534 | ||
535 | struct ide_host; | ||
536 | |||
535 | typedef struct hwif_s { | 537 | typedef struct hwif_s { |
536 | struct hwif_s *next; /* for linked-list in ide_hwgroup_t */ | 538 | struct hwif_s *next; /* for linked-list in ide_hwgroup_t */ |
537 | struct hwif_s *mate; /* other hwif from same PCI chip */ | 539 | struct hwif_s *mate; /* other hwif from same PCI chip */ |
538 | struct hwgroup_s *hwgroup; /* actually (ide_hwgroup_t *) */ | 540 | struct hwgroup_s *hwgroup; /* actually (ide_hwgroup_t *) */ |
539 | struct proc_dir_entry *proc; /* /proc/ide/ directory entry */ | 541 | struct proc_dir_entry *proc; /* /proc/ide/ directory entry */ |
540 | 542 | ||
543 | struct ide_host *host; | ||
544 | |||
541 | char name[6]; /* name of interface, eg. "ide0" */ | 545 | char name[6]; /* name of interface, eg. "ide0" */ |
542 | 546 | ||
543 | struct ide_io_ports io_ports; | 547 | struct ide_io_ports io_ports; |
@@ -876,6 +880,9 @@ struct ide_driver_s { | |||
876 | 880 | ||
877 | #define to_ide_driver(drv) container_of(drv, ide_driver_t, gen_driver) | 881 | #define to_ide_driver(drv) container_of(drv, ide_driver_t, gen_driver) |
878 | 882 | ||
883 | int ide_device_get(ide_drive_t *); | ||
884 | void ide_device_put(ide_drive_t *); | ||
885 | |||
879 | int generic_ide_ioctl(ide_drive_t *, struct file *, struct block_device *, unsigned, unsigned long); | 886 | int generic_ide_ioctl(ide_drive_t *, struct file *, struct block_device *, unsigned, unsigned long); |
880 | 887 | ||
881 | extern int ide_vlb_clk; | 888 | extern int ide_vlb_clk; |