Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik...
[sfrench/cifs-2.6.git] / drivers / ide / ide.c
index defd4b4bd37488ab38198e8ab86f963c438e2809..3b334af0c7b98d1cb39ae07ec5e714998f385102 100644 (file)
@@ -450,7 +450,7 @@ void ide_hwif_release_regions(ide_hwif_t *hwif)
  *     @hwif: hwif to update
  *     @tmp_hwif: template
  *
- *     Restore hwif to a previous state by copying most settngs
+ *     Restore hwif to a previous state by copying most settings
  *     from the template.
  */
 
@@ -539,9 +539,10 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
        hwif->dma_vendor3               = tmp_hwif->dma_vendor3;
        hwif->dma_prdtable              = tmp_hwif->dma_prdtable;
 
-       hwif->dma_extra                 = tmp_hwif->dma_extra;
        hwif->config_data               = tmp_hwif->config_data;
        hwif->select_data               = tmp_hwif->select_data;
+       hwif->extra_base                = tmp_hwif->extra_base;
+       hwif->extra_ports               = tmp_hwif->extra_ports;
        hwif->autodma                   = tmp_hwif->autodma;
        hwif->udma_four                 = tmp_hwif->udma_four;
        hwif->no_dsc                    = tmp_hwif->no_dsc;
@@ -550,7 +551,7 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
 }
 
 /**
- *     ide_unregister          -       free an ide interface
+ *     ide_unregister          -       free an IDE interface
  *     @index: index of interface (will change soon to a pointer)
  *
  *     Perform the final unregister of an IDE interface. At the moment
@@ -563,8 +564,8 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
  *     deadlocking the IDE layer. The shutdown callback is called
  *     before we take the lock and free resources. It is up to the
  *     caller to be sure there is no pending I/O here, and that
- *     the interfce will not be reopened (present/vanishing locking
- *     isnt yet done btw). After we commit to the final kill we
+ *     the interface will not be reopened (present/vanishing locking
+ *     isn't yet done BTW). After we commit to the final kill we
  *     call the cleanup callback with the ide locks held.
  *
  *     Unregister restores the hwif structures to the default state.
@@ -674,6 +675,9 @@ void ide_unregister(unsigned int index)
                hwif->dma_status = 0;
                hwif->dma_vendor3 = 0;
                hwif->dma_prdtable = 0;
+
+               hwif->extra_base  = 0;
+               hwif->extra_ports = 0;
        }
 
        /* copy original settings */
@@ -969,8 +973,8 @@ ide_settings_t *ide_find_setting_by_name (ide_drive_t *drive, char *name)
  *     @drive: drive
  *
  *     Automatically remove all the driver specific settings for this
- *     drive. This function may sleep and must not be called from IRQ
- *     context. The caller must hold ide_setting_sem.
+ *     drive. This function may not be called from IRQ context. The
+ *     caller must hold ide_setting_sem.
  */
  
 static void auto_remove_settings (ide_drive_t *drive)
@@ -1207,7 +1211,7 @@ int system_bus_clock (void)
 
 EXPORT_SYMBOL(system_bus_clock);
 
-static int generic_ide_suspend(struct device *dev, pm_message_t state)
+static int generic_ide_suspend(struct device *dev, pm_message_t mesg)
 {
        ide_drive_t *drive = dev->driver_data;
        struct request rq;
@@ -1217,11 +1221,13 @@ static int generic_ide_suspend(struct device *dev, pm_message_t state)
        memset(&rq, 0, sizeof(rq));
        memset(&rqpm, 0, sizeof(rqpm));
        memset(&args, 0, sizeof(args));
-       rq.flags = REQ_PM_SUSPEND;
+       rq.cmd_type = REQ_TYPE_PM_SUSPEND;
        rq.special = &args;
-       rq.end_io_data = &rqpm;
+       rq.data = &rqpm;
        rqpm.pm_step = ide_pm_state_start_suspend;
-       rqpm.pm_state = state.event;
+       if (mesg.event == PM_EVENT_PRETHAW)
+               mesg.event = PM_EVENT_FREEZE;
+       rqpm.pm_state = mesg.event;
 
        return ide_do_drive_cmd(drive, &rq, ide_wait);
 }
@@ -1236,9 +1242,9 @@ static int generic_ide_resume(struct device *dev)
        memset(&rq, 0, sizeof(rq));
        memset(&rqpm, 0, sizeof(rqpm));
        memset(&args, 0, sizeof(args));
-       rq.flags = REQ_PM_RESUME;
+       rq.cmd_type = REQ_TYPE_PM_RESUME;
        rq.special = &args;
-       rq.end_io_data = &rqpm;
+       rq.data = &rqpm;
        rqpm.pm_step = ide_pm_state_start_resume;
        rqpm.pm_state = PM_EVENT_ON;
 
@@ -1358,6 +1364,11 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
 
                        spin_lock_irqsave(&ide_lock, flags);
 
+                       if (HWGROUP(drive)->resetting) {
+                               spin_unlock_irqrestore(&ide_lock, flags);
+                               return -EBUSY;
+                       }
+
                        ide_abort(drive, "drive reset");
 
                        BUG_ON(HWGROUP(drive)->handler);
@@ -1771,6 +1782,7 @@ done:
 }
 
 extern void pnpide_init(void);
+extern void pnpide_exit(void);
 extern void h8300_ide_init(void);
 
 /*
@@ -1863,11 +1875,22 @@ void ide_unregister_subdriver(ide_drive_t *drive, ide_driver_t *driver)
 {
        unsigned long flags;
        
-       down(&ide_setting_sem);
-       spin_lock_irqsave(&ide_lock, flags);
 #ifdef CONFIG_PROC_FS
        ide_remove_proc_entries(drive->proc, driver->proc);
 #endif
+       down(&ide_setting_sem);
+       spin_lock_irqsave(&ide_lock, flags);
+       /*
+        * ide_setting_sem protects the settings list
+        * ide_lock protects the use of settings
+        *
+        * so we need to hold both, ide_settings_sem because we want to
+        * modify the settings list, and ide_lock because we cannot take
+        * a setting out that is being used.
+        *
+        * OTOH both ide_{read,write}_setting are only ever used under
+        * ide_setting_sem.
+        */
        auto_remove_settings(drive);
        spin_unlock_irqrestore(&ide_lock, flags);
        up(&ide_setting_sem);
@@ -1991,10 +2014,16 @@ EXPORT_SYMBOL_GPL(ide_bus_type);
  */
 static int __init ide_init(void)
 {
+       int ret;
+
        printk(KERN_INFO "Uniform Multi-Platform E-IDE driver " REVISION "\n");
        system_bus_speed = ide_system_bus_speed();
 
-       bus_register(&ide_bus_type);
+       ret = bus_register(&ide_bus_type);
+       if (ret < 0) {
+               printk(KERN_WARNING "IDE: bus_register error: %d\n", ret);
+               return ret;
+       }
 
        init_ide_data();
 
@@ -2066,6 +2095,10 @@ void cleanup_module (void)
        for (index = 0; index < MAX_HWIFS; ++index)
                ide_unregister(index);
 
+#ifdef CONFIG_BLK_DEV_IDEPNP
+       pnpide_exit();
+#endif
+
 #ifdef CONFIG_PROC_FS
        proc_ide_destroy();
 #endif