aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/ide/ide-cd.c12
-rw-r--r--drivers/ide/ide-disk.c12
-rw-r--r--drivers/ide/ide-floppy.c12
-rw-r--r--drivers/ide/ide-probe.c2
-rw-r--r--drivers/ide/ide-tape.c12
-rw-r--r--drivers/ide/ide.c47
-rw-r--r--drivers/scsi/ide-scsi.c8
-rw-r--r--include/linux/ide.h7
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
60static void ide_cd_release(struct kref *);
61
60static struct cdrom_info *ide_cd_get(struct gendisk *disk) 62static 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
72static void ide_cd_release(struct kref *);
73
74static void ide_cd_put(struct cdrom_info *cd) 79static 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
59static void ide_disk_release(struct kref *);
60
59static struct ide_disk_obj *ide_disk_get(struct gendisk *disk) 61static 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
71static void ide_disk_release(struct kref *);
72
73static void ide_disk_put(struct ide_disk_obj *idkp) 78static 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
161static void idefloppy_cleanup_obj(struct kref *);
162
161static struct ide_floppy_obj *ide_floppy_get(struct gendisk *disk) 163static 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
173static void idefloppy_cleanup_obj(struct kref *);
174
175static void ide_floppy_put(struct ide_floppy_obj *floppy) 180static 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
325static void ide_tape_release(struct kref *);
326
325static struct ide_tape_obj *ide_tape_get(struct gendisk *disk) 327static 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
337static void ide_tape_release(struct kref *);
338
339static void ide_tape_put(struct ide_tape_obj *tape) 344static 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
619EXPORT_SYMBOL(generic_ide_ioctl); 619EXPORT_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 */
628int 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}
646EXPORT_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 */
655void 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}
666EXPORT_SYMBOL_GPL(ide_device_put);
667
621static int ide_bus_match(struct device *dev, struct device_driver *drv) 668static 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)
110static void ide_scsi_put(struct ide_scsi_obj *scsi) 115static 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
535struct ide_host;
536
535typedef struct hwif_s { 537typedef 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
883int ide_device_get(ide_drive_t *);
884void ide_device_put(ide_drive_t *);
885
879int generic_ide_ioctl(ide_drive_t *, struct file *, struct block_device *, unsigned, unsigned long); 886int generic_ide_ioctl(ide_drive_t *, struct file *, struct block_device *, unsigned, unsigned long);
880 887
881extern int ide_vlb_clk; 888extern int ide_vlb_clk;