From b1d249e845efb07975183c62b4f75576c4a8d467 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 2 Jan 2009 16:12:47 +0100 Subject: ide: remove chipset type fixup from ide_host_register() * Set chipset type explicitly in tx4938ide and tx4939ide host drivers (all other host drivers were updated already). * Remove no longer used chipset type fixup from ide_host_register(). Acked-by: Atsushi Nemoto Cc: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-probe.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/ide/ide-probe.c') diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index a64ec259f3d1..291dacee52ef 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -1655,9 +1655,6 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d, if (hwif == NULL) continue; - if (hwif->chipset == ide_unknown) - hwif->chipset = ide_generic; - if (hwif->present) hwif_register_devices(hwif); } -- cgit v1.2.3-59-g8ed1b From 96d40941236722777c259775640b8880b7dc6f33 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 2 Jan 2009 16:12:47 +0100 Subject: ide: small ide_register_port() cleanup Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-probe.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers/ide/ide-probe.c') diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 291dacee52ef..7576a902a6a0 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -641,14 +641,9 @@ static int ide_register_port(ide_hwif_t *hwif) /* register with global device tree */ dev_set_name(&hwif->gendev, hwif->name); hwif->gendev.driver_data = hwif; - if (hwif->gendev.parent == NULL) { - if (hwif->dev) - hwif->gendev.parent = hwif->dev; - else - /* Would like to do = &device_legacy */ - hwif->gendev.parent = NULL; - } + hwif->gendev.parent = hwif->dev; hwif->gendev.release = hwif_release_dev; + ret = device_register(&hwif->gendev); if (ret < 0) { printk(KERN_WARNING "IDE: %s: device_register error: %d\n", -- cgit v1.2.3-59-g8ed1b From 24630dc68a499baec367d24285bc6b92207cc100 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 2 Jan 2009 16:12:47 +0100 Subject: ide: factor out device type classifying from do_identify() Factor out device type classifying from do_identify() to ide_classify_ata_dev() and ide_classify_atapi_dev(). There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-probe.c | 154 +++++++++++++++++++++++++----------------------- 1 file changed, 81 insertions(+), 73 deletions(-) (limited to 'drivers/ide/ide-probe.c') diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 7576a902a6a0..91f5faee7404 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -101,6 +101,82 @@ static void ide_disk_init_mult_count(ide_drive_t *drive) } } +static void ide_classify_ata_dev(ide_drive_t *drive) +{ + u16 *id = drive->id; + char *m = (char *)&id[ATA_ID_PROD]; + int is_cfa = ata_id_is_cfa(id); + + /* CF devices are *not* removable in Linux definition of the term */ + if (is_cfa == 0 && (id[ATA_ID_CONFIG] & (1 << 7))) + drive->dev_flags |= IDE_DFLAG_REMOVABLE; + + drive->media = ide_disk; + + if (!ata_id_has_unload(drive->id)) + drive->dev_flags |= IDE_DFLAG_NO_UNLOAD; + + printk(KERN_INFO "%s: %s, %s DISK drive\n", drive->name, m, + is_cfa ? "CFA" : "ATA"); +} + +static void ide_classify_atapi_dev(ide_drive_t *drive) +{ + u16 *id = drive->id; + char *m = (char *)&id[ATA_ID_PROD]; + u8 type = (id[ATA_ID_CONFIG] >> 8) & 0x1f; + + printk(KERN_INFO "%s: %s, ATAPI ", drive->name, m); + switch (type) { + case ide_floppy: + if (!strstr(m, "CD-ROM")) { + if (!strstr(m, "oppy") && + !strstr(m, "poyp") && + !strstr(m, "ZIP")) + printk(KERN_CONT "cdrom or floppy?, assuming "); + if (drive->media != ide_cdrom) { + printk(KERN_CONT "FLOPPY"); + drive->dev_flags |= IDE_DFLAG_REMOVABLE; + break; + } + } + /* Early cdrom models used zero */ + type = ide_cdrom; + case ide_cdrom: + drive->dev_flags |= IDE_DFLAG_REMOVABLE; +#ifdef CONFIG_PPC + /* kludge for Apple PowerBook internal zip */ + if (!strstr(m, "CD-ROM") && strstr(m, "ZIP")) { + printk(KERN_CONT "FLOPPY"); + type = ide_floppy; + break; + } +#endif + printk(KERN_CONT "CD/DVD-ROM"); + break; + case ide_tape: + printk(KERN_CONT "TAPE"); + break; + case ide_optical: + printk(KERN_CONT "OPTICAL"); + drive->dev_flags |= IDE_DFLAG_REMOVABLE; + break; + default: + printk(KERN_CONT "UNKNOWN (type %d)", type); + break; + } + + printk(KERN_CONT " drive\n"); + drive->media = type; + /* an ATAPI device ignores DRDY */ + drive->ready_stat = 0; + if (ata_id_cdb_intr(id)) + drive->atapi_flags |= IDE_AFLAG_DRQ_INTERRUPT; + drive->dev_flags |= IDE_DFLAG_DOORLOCKING; + /* we don't do head unloading on ATAPI devices */ + drive->dev_flags |= IDE_DFLAG_NO_UNLOAD; +} + /** * do_identify - identify a drive * @drive: drive to identify @@ -117,7 +193,7 @@ static void do_identify(ide_drive_t *drive, u8 cmd) u16 *id = drive->id; char *m = (char *)&id[ATA_ID_PROD]; unsigned long flags; - int bswap = 1, is_cfa; + int bswap = 1; /* local CPU only; some systems need this */ local_irq_save(flags); @@ -154,91 +230,23 @@ static void do_identify(ide_drive_t *drive, u8 cmd) if (strstr(m, "E X A B Y T E N E S T")) goto err_misc; - printk(KERN_INFO "%s: %s, ", drive->name, m); - drive->dev_flags |= IDE_DFLAG_PRESENT; drive->dev_flags &= ~IDE_DFLAG_DEAD; /* * Check for an ATAPI device */ - if (cmd == ATA_CMD_ID_ATAPI) { - u8 type = (id[ATA_ID_CONFIG] >> 8) & 0x1f; - - printk(KERN_CONT "ATAPI "); - switch (type) { - case ide_floppy: - if (!strstr(m, "CD-ROM")) { - if (!strstr(m, "oppy") && - !strstr(m, "poyp") && - !strstr(m, "ZIP")) - printk(KERN_CONT "cdrom or floppy?, assuming "); - if (drive->media != ide_cdrom) { - printk(KERN_CONT "FLOPPY"); - drive->dev_flags |= IDE_DFLAG_REMOVABLE; - break; - } - } - /* Early cdrom models used zero */ - type = ide_cdrom; - case ide_cdrom: - drive->dev_flags |= IDE_DFLAG_REMOVABLE; -#ifdef CONFIG_PPC - /* kludge for Apple PowerBook internal zip */ - if (!strstr(m, "CD-ROM") && strstr(m, "ZIP")) { - printk(KERN_CONT "FLOPPY"); - type = ide_floppy; - break; - } -#endif - printk(KERN_CONT "CD/DVD-ROM"); - break; - case ide_tape: - printk(KERN_CONT "TAPE"); - break; - case ide_optical: - printk(KERN_CONT "OPTICAL"); - drive->dev_flags |= IDE_DFLAG_REMOVABLE; - break; - default: - printk(KERN_CONT "UNKNOWN (type %d)", type); - break; - } - printk(KERN_CONT " drive\n"); - drive->media = type; - /* an ATAPI device ignores DRDY */ - drive->ready_stat = 0; - if (ata_id_cdb_intr(id)) - drive->atapi_flags |= IDE_AFLAG_DRQ_INTERRUPT; - drive->dev_flags |= IDE_DFLAG_DOORLOCKING; - /* we don't do head unloading on ATAPI devices */ - drive->dev_flags |= IDE_DFLAG_NO_UNLOAD; - return; - } - + if (cmd == ATA_CMD_ID_ATAPI) + ide_classify_atapi_dev(drive); + else /* * Not an ATAPI device: looks like a "regular" hard disk */ - - is_cfa = ata_id_is_cfa(id); - - /* CF devices are *not* removable in Linux definition of the term */ - if (is_cfa == 0 && (id[ATA_ID_CONFIG] & (1 << 7))) - drive->dev_flags |= IDE_DFLAG_REMOVABLE; - - drive->media = ide_disk; - - if (!ata_id_has_unload(drive->id)) - drive->dev_flags |= IDE_DFLAG_NO_UNLOAD; - - printk(KERN_CONT "%s DISK drive\n", is_cfa ? "CFA" : "ATA"); - + ide_classify_ata_dev(drive); return; - err_misc: kfree(id); drive->dev_flags &= ~IDE_DFLAG_PRESENT; - return; } /** -- cgit v1.2.3-59-g8ed1b From ebdab07dad3d3a008e519b0a028e1e1ad5ecaef0 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 2 Jan 2009 16:12:48 +0100 Subject: ide: move sysfs support to ide-sysfs.c While at it: - media_string() -> ide_media_string() There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/Makefile | 2 +- drivers/ide/ide-probe.c | 52 -------------------- drivers/ide/ide-sysfs.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++++ drivers/ide/ide.c | 72 +--------------------------- include/linux/ide.h | 4 ++ 5 files changed, 132 insertions(+), 123 deletions(-) create mode 100644 drivers/ide/ide-sysfs.c (limited to 'drivers/ide/ide-probe.c') diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index 177e3f8523ed..410728992e6a 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile @@ -5,7 +5,7 @@ EXTRA_CFLAGS += -Idrivers/ide ide-core-y += ide.o ide-ioctls.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \ - ide-taskfile.o ide-pm.o ide-park.o ide-pio-blacklist.o + ide-taskfile.o ide-pm.o ide-park.o ide-pio-blacklist.o ide-sysfs.o # core IDE code ide-core-$(CONFIG_IDE_TIMINGS) += ide-timings.o diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 91f5faee7404..f9efd069edc2 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -1420,58 +1420,6 @@ static void ide_port_cable_detect(ide_hwif_t *hwif) } } -static ssize_t store_delete_devices(struct device *portdev, - struct device_attribute *attr, - const char *buf, size_t n) -{ - ide_hwif_t *hwif = dev_get_drvdata(portdev); - - if (strncmp(buf, "1", n)) - return -EINVAL; - - ide_port_unregister_devices(hwif); - - return n; -}; - -static DEVICE_ATTR(delete_devices, S_IWUSR, NULL, store_delete_devices); - -static ssize_t store_scan(struct device *portdev, - struct device_attribute *attr, - const char *buf, size_t n) -{ - ide_hwif_t *hwif = dev_get_drvdata(portdev); - - if (strncmp(buf, "1", n)) - return -EINVAL; - - ide_port_unregister_devices(hwif); - ide_port_scan(hwif); - - return n; -}; - -static DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan); - -static struct device_attribute *ide_port_attrs[] = { - &dev_attr_delete_devices, - &dev_attr_scan, - NULL -}; - -static int ide_sysfs_register_port(ide_hwif_t *hwif) -{ - int i, uninitialized_var(rc); - - for (i = 0; ide_port_attrs[i]; i++) { - rc = device_create_file(hwif->portdev, ide_port_attrs[i]); - if (rc) - break; - } - - return rc; -} - static unsigned int ide_indexes; /** diff --git a/drivers/ide/ide-sysfs.c b/drivers/ide/ide-sysfs.c new file mode 100644 index 000000000000..883ffacaf45a --- /dev/null +++ b/drivers/ide/ide-sysfs.c @@ -0,0 +1,125 @@ +#include +#include + +char *ide_media_string(ide_drive_t *drive) +{ + switch (drive->media) { + case ide_disk: + return "disk"; + case ide_cdrom: + return "cdrom"; + case ide_tape: + return "tape"; + case ide_floppy: + return "floppy"; + case ide_optical: + return "optical"; + default: + return "UNKNOWN"; + } +} + +static ssize_t media_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + ide_drive_t *drive = to_ide_device(dev); + return sprintf(buf, "%s\n", ide_media_string(drive)); +} + +static ssize_t drivename_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + ide_drive_t *drive = to_ide_device(dev); + return sprintf(buf, "%s\n", drive->name); +} + +static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + ide_drive_t *drive = to_ide_device(dev); + return sprintf(buf, "ide:m-%s\n", ide_media_string(drive)); +} + +static ssize_t model_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + ide_drive_t *drive = to_ide_device(dev); + return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_PROD]); +} + +static ssize_t firmware_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + ide_drive_t *drive = to_ide_device(dev); + return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_FW_REV]); +} + +static ssize_t serial_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + ide_drive_t *drive = to_ide_device(dev); + return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_SERNO]); +} + +struct device_attribute ide_dev_attrs[] = { + __ATTR_RO(media), + __ATTR_RO(drivename), + __ATTR_RO(modalias), + __ATTR_RO(model), + __ATTR_RO(firmware), + __ATTR(serial, 0400, serial_show, NULL), + __ATTR(unload_heads, 0644, ide_park_show, ide_park_store), + __ATTR_NULL +}; + +static ssize_t store_delete_devices(struct device *portdev, + struct device_attribute *attr, + const char *buf, size_t n) +{ + ide_hwif_t *hwif = dev_get_drvdata(portdev); + + if (strncmp(buf, "1", n)) + return -EINVAL; + + ide_port_unregister_devices(hwif); + + return n; +}; + +static DEVICE_ATTR(delete_devices, S_IWUSR, NULL, store_delete_devices); + +static ssize_t store_scan(struct device *portdev, + struct device_attribute *attr, + const char *buf, size_t n) +{ + ide_hwif_t *hwif = dev_get_drvdata(portdev); + + if (strncmp(buf, "1", n)) + return -EINVAL; + + ide_port_unregister_devices(hwif); + ide_port_scan(hwif); + + return n; +}; + +static DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan); + +static struct device_attribute *ide_port_attrs[] = { + &dev_attr_delete_devices, + &dev_attr_scan, + NULL +}; + +int ide_sysfs_register_port(ide_hwif_t *hwif) +{ + int i, uninitialized_var(rc); + + for (i = 0; ide_port_attrs[i]; i++) { + rc = device_create_file(hwif->portdev, ide_port_attrs[i]); + if (rc) + break; + } + + return rc; +} diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index f0f09f702e9c..46a2d4ca812b 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -440,81 +440,13 @@ static int ide_bus_match(struct device *dev, struct device_driver *drv) return 1; } -static char *media_string(ide_drive_t *drive) -{ - switch (drive->media) { - case ide_disk: - return "disk"; - case ide_cdrom: - return "cdrom"; - case ide_tape: - return "tape"; - case ide_floppy: - return "floppy"; - case ide_optical: - return "optical"; - default: - return "UNKNOWN"; - } -} - -static ssize_t media_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - ide_drive_t *drive = to_ide_device(dev); - return sprintf(buf, "%s\n", media_string(drive)); -} - -static ssize_t drivename_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - ide_drive_t *drive = to_ide_device(dev); - return sprintf(buf, "%s\n", drive->name); -} - -static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - ide_drive_t *drive = to_ide_device(dev); - return sprintf(buf, "ide:m-%s\n", media_string(drive)); -} - -static ssize_t model_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - ide_drive_t *drive = to_ide_device(dev); - return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_PROD]); -} - -static ssize_t firmware_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - ide_drive_t *drive = to_ide_device(dev); - return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_FW_REV]); -} - -static ssize_t serial_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - ide_drive_t *drive = to_ide_device(dev); - return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_SERNO]); -} - -static struct device_attribute ide_dev_attrs[] = { - __ATTR_RO(media), - __ATTR_RO(drivename), - __ATTR_RO(modalias), - __ATTR_RO(model), - __ATTR_RO(firmware), - __ATTR(serial, 0400, serial_show, NULL), - __ATTR(unload_heads, 0644, ide_park_show, ide_park_store), - __ATTR_NULL -}; - static int ide_uevent(struct device *dev, struct kobj_uevent_env *env) { ide_drive_t *drive = to_ide_device(dev); - add_uevent_var(env, "MEDIA=%s", media_string(drive)); + add_uevent_var(env, "MEDIA=%s", ide_media_string(drive)); add_uevent_var(env, "DRIVENAME=%s", drive->name); - add_uevent_var(env, "MODALIAS=ide:m-%s", media_string(drive)); + add_uevent_var(env, "MODALIAS=ide:m-%s", ide_media_string(drive)); return 0; } diff --git a/include/linux/ide.h b/include/linux/ide.h index e99c56de7f56..62fccaea3110 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1533,6 +1533,7 @@ void ide_unregister_region(struct gendisk *); void ide_undecoded_slave(ide_drive_t *); void ide_port_apply_params(ide_hwif_t *); +int ide_sysfs_register_port(ide_hwif_t *); struct ide_host *ide_host_alloc(const struct ide_port_info *, hw_regs_t **); void ide_host_free(struct ide_host *); @@ -1627,6 +1628,9 @@ extern struct mutex ide_cfg_mtx; #define local_irq_set(flags) do { local_save_flags((flags)); local_irq_enable_in_hardirq(); } while (0) +char *ide_media_string(ide_drive_t *); + +extern struct device_attribute ide_dev_attrs[]; extern struct bus_type ide_bus_type; extern struct class *ide_port_class; -- cgit v1.2.3-59-g8ed1b From 201bffa46466b4afdf7d29db8eca3fa5decb39c8 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 2 Jan 2009 16:12:50 +0100 Subject: ide: use per-device request queue locks (v2) * Move hack for flush requests from choose_drive() to do_ide_request(). * Add ide_plug_device() helper and convert core IDE code from using per-hwgroup lock as a request lock to use the ->queue_lock instead. * Remove no longer needed: - choose_drive() function - WAKEUP() macro - 'sleeping' flag from ide_hwif_t - 'service_{start,time}' fields from ide_drive_t This patch results in much simpler and more maintainable code (besides being a scalability improvement). v2: * Fixes/improvements based on review from Elias: - take as many requests off the queue as possible - remove now redundant BUG_ON() Cc: Elias Oltmanns Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-io.c | 214 +++++++++++++++--------------------------------- drivers/ide/ide-park.c | 13 +-- drivers/ide/ide-probe.c | 3 +- include/linux/ide.h | 4 - 4 files changed, 77 insertions(+), 157 deletions(-) (limited to 'drivers/ide/ide-probe.c') diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index ab480042757a..bb3248abf47d 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -667,85 +667,10 @@ void ide_stall_queue (ide_drive_t *drive, unsigned long timeout) drive->sleep = timeout + jiffies; drive->dev_flags |= IDE_DFLAG_SLEEPING; } - EXPORT_SYMBOL(ide_stall_queue); -#define WAKEUP(drive) ((drive)->service_start + 2 * (drive)->service_time) - -/** - * choose_drive - select a drive to service - * @hwgroup: hardware group to select on - * - * choose_drive() selects the next drive which will be serviced. - * This is necessary because the IDE layer can't issue commands - * to both drives on the same cable, unlike SCSI. - */ - -static inline ide_drive_t *choose_drive (ide_hwgroup_t *hwgroup) -{ - ide_drive_t *drive, *best; - -repeat: - best = NULL; - drive = hwgroup->drive; - - /* - * drive is doing pre-flush, ordered write, post-flush sequence. even - * though that is 3 requests, it must be seen as a single transaction. - * we must not preempt this drive until that is complete - */ - if (blk_queue_flushing(drive->queue)) { - /* - * small race where queue could get replugged during - * the 3-request flush cycle, just yank the plug since - * we want it to finish asap - */ - blk_remove_plug(drive->queue); - return drive; - } - - do { - u8 dev_s = !!(drive->dev_flags & IDE_DFLAG_SLEEPING); - u8 best_s = (best && !!(best->dev_flags & IDE_DFLAG_SLEEPING)); - - if ((dev_s == 0 || time_after_eq(jiffies, drive->sleep)) && - !elv_queue_empty(drive->queue)) { - if (best == NULL || - (dev_s && (best_s == 0 || time_before(drive->sleep, best->sleep))) || - (best_s == 0 && time_before(WAKEUP(drive), WAKEUP(best)))) { - if (!blk_queue_plugged(drive->queue)) - best = drive; - } - } - } while ((drive = drive->next) != hwgroup->drive); - - if (best && (best->dev_flags & IDE_DFLAG_NICE1) && - (best->dev_flags & IDE_DFLAG_SLEEPING) == 0 && - best != hwgroup->drive && best->service_time > WAIT_MIN_SLEEP) { - long t = (signed long)(WAKEUP(best) - jiffies); - if (t >= WAIT_MIN_SLEEP) { - /* - * We *may* have some time to spare, but first let's see if - * someone can potentially benefit from our nice mood today.. - */ - drive = best->next; - do { - if ((drive->dev_flags & IDE_DFLAG_SLEEPING) == 0 - && time_before(jiffies - best->service_time, WAKEUP(drive)) - && time_before(WAKEUP(drive), jiffies + t)) - { - ide_stall_queue(best, min_t(long, t, 10 * WAIT_MIN_SLEEP)); - goto repeat; - } - } while ((drive = drive->next) != best); - } - } - return best; -} - /* * Issue a new request to a drive from hwgroup - * Caller must have already done spin_lock_irqsave(&hwgroup->lock, ..); * * A hwgroup is a serialized group of IDE interfaces. Usually there is * exactly one hwif (interface) per hwgroup, but buggy controllers (eg. CMD640) @@ -757,8 +682,7 @@ repeat: * possibly along with many other devices. This is especially common in * PCI-based systems with off-board IDE controller cards. * - * The IDE driver uses a per-hwgroup spinlock to protect - * access to the request queues, and to protect the hwgroup->busy flag. + * The IDE driver uses a per-hwgroup lock to protect the hwgroup->busy flag. * * The first thread into the driver for a particular hwgroup sets the * hwgroup->busy flag to indicate that this hwgroup is now active, @@ -780,61 +704,38 @@ repeat: */ void do_ide_request(struct request_queue *q) { - ide_drive_t *orig_drive = q->queuedata; - ide_hwgroup_t *hwgroup = orig_drive->hwif->hwgroup; - ide_drive_t *drive; - ide_hwif_t *hwif; + ide_drive_t *drive = q->queuedata; + ide_hwif_t *hwif = drive->hwif; + ide_hwgroup_t *hwgroup = hwif->hwgroup; struct request *rq; ide_startstop_t startstop; - /* caller must own hwgroup->lock */ - BUG_ON(!irqs_disabled()); - - while (!ide_lock_hwgroup(hwgroup)) { - drive = choose_drive(hwgroup); - if (drive == NULL) { - int sleeping = 0; - unsigned long sleep = 0; /* shut up, gcc */ - hwgroup->rq = NULL; - drive = hwgroup->drive; - do { - if ((drive->dev_flags & IDE_DFLAG_SLEEPING) && - (sleeping == 0 || - time_before(drive->sleep, sleep))) { - sleeping = 1; - sleep = drive->sleep; - } - } while ((drive = drive->next) != hwgroup->drive); - if (sleeping) { + /* + * drive is doing pre-flush, ordered write, post-flush sequence. even + * though that is 3 requests, it must be seen as a single transaction. + * we must not preempt this drive until that is complete + */ + if (blk_queue_flushing(q)) /* - * Take a short snooze, and then wake up this hwgroup again. - * This gives other hwgroups on the same a chance to - * play fairly with us, just in case there are big differences - * in relative throughputs.. don't want to hog the cpu too much. + * small race where queue could get replugged during + * the 3-request flush cycle, just yank the plug since + * we want it to finish asap */ - if (time_before(sleep, jiffies + WAIT_MIN_SLEEP)) - sleep = jiffies + WAIT_MIN_SLEEP; -#if 1 - if (timer_pending(&hwgroup->timer)) - printk(KERN_CRIT "ide_set_handler: timer already active\n"); -#endif - /* so that ide_timer_expiry knows what to do */ - hwgroup->sleeping = 1; - hwgroup->req_gen_timer = hwgroup->req_gen; - mod_timer(&hwgroup->timer, sleep); - /* we purposely leave hwgroup locked - * while sleeping */ - } else - ide_unlock_hwgroup(hwgroup); + blk_remove_plug(q); - /* no more work for this hwgroup (for now) */ - goto plug_device; - } + spin_unlock_irq(q->queue_lock); + spin_lock_irq(&hwgroup->lock); - if (drive != orig_drive) - goto plug_device; + if (!ide_lock_hwgroup(hwgroup)) { +repeat: + hwgroup->rq = NULL; - hwif = drive->hwif; + if (drive->dev_flags & IDE_DFLAG_SLEEPING) { + if (time_before(drive->sleep, jiffies)) { + ide_unlock_hwgroup(hwgroup); + goto plug_device; + } + } if (hwif != hwgroup->hwif) { /* @@ -847,16 +748,20 @@ void do_ide_request(struct request_queue *q) hwgroup->hwif = hwif; hwgroup->drive = drive; drive->dev_flags &= ~(IDE_DFLAG_SLEEPING | IDE_DFLAG_PARKED); - drive->service_start = jiffies; + spin_unlock_irq(&hwgroup->lock); + spin_lock_irq(q->queue_lock); /* * we know that the queue isn't empty, but this can happen * if the q->prep_rq_fn() decides to kill a request */ rq = elv_next_request(drive->queue); + spin_unlock_irq(q->queue_lock); + spin_lock_irq(&hwgroup->lock); + if (!rq) { ide_unlock_hwgroup(hwgroup); - break; + goto out; } /* @@ -886,17 +791,21 @@ void do_ide_request(struct request_queue *q) startstop = start_request(drive, rq); spin_lock_irq(&hwgroup->lock); - if (startstop == ide_stopped) { - ide_unlock_hwgroup(hwgroup); - if (!elv_queue_empty(orig_drive->queue)) - blk_plug_device(orig_drive->queue); - } - } + if (startstop == ide_stopped) + goto repeat; + } else + goto plug_device; +out: + spin_unlock_irq(&hwgroup->lock); + spin_lock_irq(q->queue_lock); return; plug_device: - if (!elv_queue_empty(orig_drive->queue)) - blk_plug_device(orig_drive->queue); + spin_unlock_irq(&hwgroup->lock); + spin_lock_irq(q->queue_lock); + + if (!elv_queue_empty(q)) + blk_plug_device(q); } /* @@ -957,6 +866,17 @@ out: return ret; } +static void ide_plug_device(ide_drive_t *drive) +{ + struct request_queue *q = drive->queue; + unsigned long flags; + + spin_lock_irqsave(q->queue_lock, flags); + if (!elv_queue_empty(q)) + blk_plug_device(q); + spin_unlock_irqrestore(q->queue_lock, flags); +} + /** * ide_timer_expiry - handle lack of an IDE interrupt * @data: timer callback magic (hwgroup) @@ -974,10 +894,12 @@ out: void ide_timer_expiry (unsigned long data) { ide_hwgroup_t *hwgroup = (ide_hwgroup_t *) data; + ide_drive_t *uninitialized_var(drive); ide_handler_t *handler; ide_expiry_t *expiry; unsigned long flags; unsigned long wait = -1; + int plug_device = 0; spin_lock_irqsave(&hwgroup->lock, flags); @@ -989,12 +911,8 @@ void ide_timer_expiry (unsigned long data) * or we were "sleeping" to give other devices a chance. * Either way, we don't really want to complain about anything. */ - if (hwgroup->sleeping) { - hwgroup->sleeping = 0; - ide_unlock_hwgroup(hwgroup); - } } else { - ide_drive_t *drive = hwgroup->drive; + drive = hwgroup->drive; if (!drive) { printk(KERN_ERR "ide_timer_expiry: hwgroup->drive was NULL\n"); hwgroup->handler = NULL; @@ -1042,17 +960,18 @@ void ide_timer_expiry (unsigned long data) ide_error(drive, "irq timeout", hwif->tp_ops->read_status(hwif)); } - drive->service_time = jiffies - drive->service_start; spin_lock_irq(&hwgroup->lock); enable_irq(hwif->irq); if (startstop == ide_stopped) { ide_unlock_hwgroup(hwgroup); - if (!elv_queue_empty(drive->queue)) - blk_plug_device(drive->queue); + plug_device = 1; } } } spin_unlock_irqrestore(&hwgroup->lock, flags); + + if (plug_device) + ide_plug_device(drive); } /** @@ -1146,10 +1065,11 @@ irqreturn_t ide_intr (int irq, void *dev_id) unsigned long flags; ide_hwgroup_t *hwgroup = (ide_hwgroup_t *)dev_id; ide_hwif_t *hwif = hwgroup->hwif; - ide_drive_t *drive; + ide_drive_t *uninitialized_var(drive); ide_handler_t *handler; ide_startstop_t startstop; irqreturn_t irq_ret = IRQ_NONE; + int plug_device = 0; spin_lock_irqsave(&hwgroup->lock, flags); @@ -1236,12 +1156,10 @@ irqreturn_t ide_intr (int irq, void *dev_id) * same irq as is currently being serviced here, and Linux * won't allow another of the same (on any CPU) until we return. */ - drive->service_time = jiffies - drive->service_start; if (startstop == ide_stopped) { if (hwgroup->handler == NULL) { /* paranoia */ ide_unlock_hwgroup(hwgroup); - if (!elv_queue_empty(drive->queue)) - blk_plug_device(drive->queue); + plug_device = 1; } else printk(KERN_ERR "%s: %s: huh? expected NULL handler " "on exit\n", __func__, drive->name); @@ -1250,6 +1168,10 @@ out_handled: irq_ret = IRQ_HANDLED; out: spin_unlock_irqrestore(&hwgroup->lock, flags); + + if (plug_device) + ide_plug_device(drive); + return irq_ret; } diff --git a/drivers/ide/ide-park.c b/drivers/ide/ide-park.c index 44c6787f8aeb..678454ac2483 100644 --- a/drivers/ide/ide-park.c +++ b/drivers/ide/ide-park.c @@ -16,16 +16,19 @@ static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout) spin_lock_irq(&hwgroup->lock); if (drive->dev_flags & IDE_DFLAG_PARKED) { int reset_timer = time_before(timeout, drive->sleep); + int start_queue = 0; drive->sleep = timeout; wake_up_all(&ide_park_wq); - if (reset_timer && hwgroup->sleeping && - del_timer(&hwgroup->timer)) { - hwgroup->sleeping = 0; - ide_unlock_hwgroup(hwgroup); + if (reset_timer && del_timer(&hwgroup->timer)) + start_queue = 1; + spin_unlock_irq(&hwgroup->lock); + + if (start_queue) { + spin_lock_irq(q->queue_lock); blk_start_queueing(q); + spin_unlock_irq(q->queue_lock); } - spin_unlock_irq(&hwgroup->lock); return; } spin_unlock_irq(&hwgroup->lock); diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index f9efd069edc2..966b74c15773 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -881,8 +881,7 @@ static int ide_init_queue(ide_drive_t *drive) * do not. */ - q = blk_init_queue_node(do_ide_request, &hwif->hwgroup->lock, - hwif_to_node(hwif)); + q = blk_init_queue_node(do_ide_request, NULL, hwif_to_node(hwif)); if (!q) return 1; diff --git a/include/linux/ide.h b/include/linux/ide.h index f408d6123f14..5f86ad40ee7e 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -603,8 +603,6 @@ struct ide_drive_s { unsigned long dev_flags; unsigned long sleep; /* sleep until this time */ - unsigned long service_start; /* time we started last request */ - unsigned long service_time; /* service time of last request */ unsigned long timeout; /* max time to wait for irq */ special_t special; /* special action flags */ @@ -872,8 +870,6 @@ typedef struct hwgroup_s { /* BOOL: protects all fields below */ volatile int busy; - /* BOOL: wake us up on timer expiry */ - unsigned int sleeping : 1; /* BOOL: polling active & poll_timeout field valid */ unsigned int polling : 1; -- cgit v1.2.3-59-g8ed1b From 5317464dccd0c03026d60f1e9968de4f9cd23f69 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Fri, 2 Jan 2009 16:12:54 +0100 Subject: ide: remove the last ide-scsi remnants Signed-off-by: Borislav Petkov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-atapi.c | 3 +-- drivers/ide/ide-io.c | 3 --- drivers/ide/ide-ioctls.c | 3 +-- drivers/ide/ide-probe.c | 2 -- include/linux/ide.h | 28 +++++++++++++--------------- 5 files changed, 15 insertions(+), 24 deletions(-) (limited to 'drivers/ide/ide-probe.c') diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index 7a04509bf962..d412bd2bd7fd 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c @@ -17,8 +17,7 @@ static inline int dev_is_idecd(ide_drive_t *drive) { - return (drive->media == ide_cdrom || drive->media == ide_optical) && - !(drive->dev_flags & IDE_DFLAG_SCSI); + return drive->media == ide_cdrom || drive->media == ide_optical; } /* diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index bb3248abf47d..1c36a8e83d36 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -426,9 +426,6 @@ void ide_map_sg(ide_drive_t *drive, struct request *rq) ide_hwif_t *hwif = drive->hwif; struct scatterlist *sg = hwif->sg_table; - if (hwif->sg_mapped) /* needed by ide-scsi */ - return; - if (rq->cmd_type != REQ_TYPE_ATA_TASKFILE) { hwif->sg_nents = blk_rq_map_sg(drive->queue, rq, sg); } else { diff --git a/drivers/ide/ide-ioctls.c b/drivers/ide/ide-ioctls.c index 28232c64c346..1be263eb9c07 100644 --- a/drivers/ide/ide-ioctls.c +++ b/drivers/ide/ide-ioctls.c @@ -95,8 +95,7 @@ static int ide_set_nice_ioctl(ide_drive_t *drive, unsigned long arg) return -EPERM; if (((arg >> IDE_NICE_DSC_OVERLAP) & 1) && - (drive->media != ide_tape || - (drive->dev_flags & IDE_DFLAG_SCSI))) + (drive->media != ide_tape)) return -EPERM; if ((arg >> IDE_NICE_DSC_OVERLAP) & 1) diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 966b74c15773..c5adb7b9c5b5 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -1141,8 +1141,6 @@ static struct kobject *ata_probe(dev_t dev, int *part, void *data) if (drive->media == ide_disk) request_module("ide-disk"); - if (drive->dev_flags & IDE_DFLAG_SCSI) - request_module("ide-scsi"); if (drive->media == ide_cdrom || drive->media == ide_optical) request_module("ide-cd"); if (drive->media == ide_tape) diff --git a/include/linux/ide.h b/include/linux/ide.h index 257524ee1af2..ad57a4492941 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -559,28 +559,26 @@ enum { IDE_DFLAG_NODMA = (1 << 16), /* powermanagment told us not to do anything, so sleep nicely */ IDE_DFLAG_BLOCKED = (1 << 17), - /* ide-scsi emulation */ - IDE_DFLAG_SCSI = (1 << 18), /* sleeping & sleep field valid */ - IDE_DFLAG_SLEEPING = (1 << 19), - IDE_DFLAG_POST_RESET = (1 << 20), - IDE_DFLAG_UDMA33_WARNED = (1 << 21), - IDE_DFLAG_LBA48 = (1 << 22), + IDE_DFLAG_SLEEPING = (1 << 18), + IDE_DFLAG_POST_RESET = (1 << 19), + IDE_DFLAG_UDMA33_WARNED = (1 << 20), + IDE_DFLAG_LBA48 = (1 << 21), /* status of write cache */ - IDE_DFLAG_WCACHE = (1 << 23), + IDE_DFLAG_WCACHE = (1 << 22), /* used for ignoring ATA_DF */ - IDE_DFLAG_NOWERR = (1 << 24), + IDE_DFLAG_NOWERR = (1 << 23), /* retrying in PIO */ - IDE_DFLAG_DMA_PIO_RETRY = (1 << 25), - IDE_DFLAG_LBA = (1 << 26), + IDE_DFLAG_DMA_PIO_RETRY = (1 << 24), + IDE_DFLAG_LBA = (1 << 25), /* don't unload heads */ - IDE_DFLAG_NO_UNLOAD = (1 << 27), + IDE_DFLAG_NO_UNLOAD = (1 << 26), /* heads unloaded, please don't reset port */ - IDE_DFLAG_PARKED = (1 << 28), - IDE_DFLAG_MEDIA_CHANGED = (1 << 29), + IDE_DFLAG_PARKED = (1 << 27), + IDE_DFLAG_MEDIA_CHANGED = (1 << 28), /* write protect */ - IDE_DFLAG_WP = (1 << 30), - IDE_DFLAG_FORMAT_IN_PROGRESS = (1 << 31), + IDE_DFLAG_WP = (1 << 29), + IDE_DFLAG_FORMAT_IN_PROGRESS = (1 << 30), }; struct ide_drive_s { -- cgit v1.2.3-59-g8ed1b