aboutsummaryrefslogtreecommitdiff
path: root/drivers/ide/ide-probe.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ide/ide-probe.c')
-rw-r--r--drivers/ide/ide-probe.c189
1 files changed, 113 insertions, 76 deletions
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 7f264ed1141..a3d3b1733c4 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -97,7 +97,7 @@ static void ide_disk_init_mult_count(ide_drive_t *drive)
drive->mult_req = id[ATA_ID_MULTSECT] & 0xff;
if (drive->mult_req)
- drive->special.b.set_multmode = 1;
+ drive->special_flags |= IDE_SFLAG_SET_MULTMODE;
}
}
@@ -238,6 +238,7 @@ static void do_identify(ide_drive_t *drive, u8 cmd, u16 *id)
* @drive: drive to identify
* @cmd: command to use
* @id: buffer for IDENTIFY data
+ * @irq_ctx: flag set when called from the IRQ context
*
* Sends an ATA(PI) IDENTIFY request to a drive and waits for a response.
*
@@ -246,7 +247,7 @@ static void do_identify(ide_drive_t *drive, u8 cmd, u16 *id)
* 2 device aborted the command (refused to identify itself)
*/
-int ide_dev_read_id(ide_drive_t *drive, u8 cmd, u16 *id)
+int ide_dev_read_id(ide_drive_t *drive, u8 cmd, u16 *id, int irq_ctx)
{
ide_hwif_t *hwif = drive->hwif;
struct ide_io_ports *io_ports = &hwif->io_ports;
@@ -263,7 +264,10 @@ int ide_dev_read_id(ide_drive_t *drive, u8 cmd, u16 *id)
tp_ops->write_devctl(hwif, ATA_NIEN | ATA_DEVCTL_OBS);
/* take a deep breath */
- msleep(50);
+ if (irq_ctx)
+ mdelay(50);
+ else
+ msleep(50);
if (io_ports->ctl_addr &&
(hwif->host_flags & IDE_HFLAG_BROKEN_ALTSTATUS) == 0) {
@@ -295,12 +299,19 @@ int ide_dev_read_id(ide_drive_t *drive, u8 cmd, u16 *id)
timeout = ((cmd == ATA_CMD_ID_ATA) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2;
- if (ide_busy_sleep(hwif, timeout, use_altstatus))
- return 1;
-
/* wait for IRQ and ATA_DRQ */
- msleep(50);
- s = tp_ops->read_status(hwif);
+ if (irq_ctx) {
+ rc = __ide_wait_stat(drive, ATA_DRQ, BAD_R_STAT, timeout, &s);
+ if (rc)
+ return 1;
+ } else {
+ rc = ide_busy_sleep(drive, timeout, use_altstatus);
+ if (rc)
+ return 1;
+
+ msleep(50);
+ s = tp_ops->read_status(hwif);
+ }
if (OK_STAT(s, ATA_DRQ, BAD_R_STAT)) {
/* drive returned ID */
@@ -316,8 +327,9 @@ int ide_dev_read_id(ide_drive_t *drive, u8 cmd, u16 *id)
return rc;
}
-int ide_busy_sleep(ide_hwif_t *hwif, unsigned long timeout, int altstatus)
+int ide_busy_sleep(ide_drive_t *drive, unsigned long timeout, int altstatus)
{
+ ide_hwif_t *hwif = drive->hwif;
u8 stat;
timeout += jiffies;
@@ -330,6 +342,8 @@ int ide_busy_sleep(ide_hwif_t *hwif, unsigned long timeout, int altstatus)
return 0;
} while (time_before(jiffies, timeout));
+ printk(KERN_ERR "%s: timeout in %s\n", drive->name, __func__);
+
return 1; /* drive timed-out */
}
@@ -403,10 +417,10 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
if (OK_STAT(stat, ATA_DRDY, ATA_BUSY) ||
present || cmd == ATA_CMD_ID_ATAPI) {
- rc = ide_dev_read_id(drive, cmd, id);
+ rc = ide_dev_read_id(drive, cmd, id, 0);
if (rc)
/* failed: try again */
- rc = ide_dev_read_id(drive, cmd, id);
+ rc = ide_dev_read_id(drive, cmd, id, 0);
stat = tp_ops->read_status(hwif);
@@ -420,8 +434,8 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
tp_ops->dev_select(drive);
msleep(50);
tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET);
- (void)ide_busy_sleep(hwif, WAIT_WORSTCASE, 0);
- rc = ide_dev_read_id(drive, cmd, id);
+ (void)ide_busy_sleep(drive, WAIT_WORSTCASE, 0);
+ rc = ide_dev_read_id(drive, cmd, id, 0);
}
/* ensure drive IRQ is clear */
@@ -462,23 +476,8 @@ static u8 probe_for_drive(ide_drive_t *drive)
int rc;
u8 cmd;
- /*
- * In order to keep things simple we have an id
- * block for all drives at all times. If the device
- * is pre ATA or refuses ATA/ATAPI identify we
- * will add faked data to this.
- *
- * Also note that 0 everywhere means "can't do X"
- */
-
drive->dev_flags &= ~IDE_DFLAG_ID_READ;
- drive->id = kzalloc(SECTOR_SIZE, GFP_KERNEL);
- if (drive->id == NULL) {
- printk(KERN_ERR "ide: out of memory for id data.\n");
- return 0;
- }
-
m = (char *)&drive->id[ATA_ID_PROD];
strcpy(m, "UNKNOWN");
@@ -494,7 +493,7 @@ static u8 probe_for_drive(ide_drive_t *drive)
}
if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
- goto out_free;
+ return 0;
/* identification failed? */
if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) {
@@ -518,7 +517,7 @@ static u8 probe_for_drive(ide_drive_t *drive)
}
if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
- goto out_free;
+ return 0;
/* The drive wasn't being helpful. Add generic info only */
if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) {
@@ -532,9 +531,6 @@ static u8 probe_for_drive(ide_drive_t *drive)
}
return 1;
-out_free:
- kfree(drive->id);
- return 0;
}
static void hwif_release_dev(struct device *dev)
@@ -549,8 +545,8 @@ static int ide_register_port(ide_hwif_t *hwif)
int ret;
/* register with global device tree */
- dev_set_name(&hwif->gendev, hwif->name);
- hwif->gendev.driver_data = hwif;
+ dev_set_name(&hwif->gendev, "%s", hwif->name);
+ dev_set_drvdata(&hwif->gendev, hwif);
if (hwif->gendev.parent == NULL)
hwif->gendev.parent = hwif->dev;
hwif->gendev.release = hwif_release_dev;
@@ -563,7 +559,7 @@ static int ide_register_port(ide_hwif_t *hwif)
}
hwif->portdev = device_create(ide_port_class, &hwif->gendev,
- MKDEV(0, 0), hwif, hwif->name);
+ MKDEV(0, 0), hwif, "%s", hwif->name);
if (IS_ERR(hwif->portdev)) {
ret = PTR_ERR(hwif->portdev);
device_unregister(&hwif->gendev);
@@ -729,6 +725,8 @@ static void ide_port_tune_devices(ide_hwif_t *hwif)
int i;
ide_port_for_each_present_dev(i, drive, hwif) {
+ ide_check_nien_quirk_list(drive);
+
if (port_ops && port_ops->quirkproc)
port_ops->quirkproc(drive);
}
@@ -770,7 +768,7 @@ static int ide_init_queue(ide_drive_t *drive)
if (hwif->rqsize < max_sectors)
max_sectors = hwif->rqsize;
- blk_queue_max_sectors(q, max_sectors);
+ blk_queue_max_hw_sectors(q, max_sectors);
#ifdef CONFIG_PCI
/* When we have an IOMMU, we may have a problem where pci_map_sg()
@@ -786,8 +784,7 @@ static int ide_init_queue(ide_drive_t *drive)
max_sg_entries >>= 1;
#endif /* CONFIG_PCI */
- blk_queue_max_hw_segments(q, max_sg_entries);
- blk_queue_max_phys_segments(q, max_sg_entries);
+ blk_queue_max_segments(q, max_sg_entries);
/* assign drive queue */
drive->queue = q;
@@ -814,8 +811,6 @@ static int ide_port_setup_devices(ide_hwif_t *hwif)
if (ide_init_queue(drive)) {
printk(KERN_ERR "ide: failed to init %s\n",
drive->name);
- kfree(drive->id);
- drive->id = NULL;
drive->dev_flags &= ~IDE_DFLAG_PRESENT;
continue;
}
@@ -827,6 +822,24 @@ static int ide_port_setup_devices(ide_hwif_t *hwif)
return j;
}
+static void ide_host_enable_irqs(struct ide_host *host)
+{
+ ide_hwif_t *hwif;
+ int i;
+
+ ide_host_for_each_port(i, hwif, host) {
+ if (hwif == NULL)
+ continue;
+
+ /* clear any pending IRQs */
+ hwif->tp_ops->read_status(hwif);
+
+ /* unmask IRQs */
+ if (hwif->io_ports.ctl_addr)
+ hwif->tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS);
+ }
+}
+
/*
* This routine sets up the IRQ for an IDE interface.
*/
@@ -840,11 +853,9 @@ static int init_irq (ide_hwif_t *hwif)
if (irq_handler == NULL)
irq_handler = ide_intr;
- if (io_ports->ctl_addr)
- hwif->tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS);
-
- if (request_irq(hwif->irq, irq_handler, sa, hwif->name, hwif))
- goto out_up;
+ if (!host->get_lock)
+ if (request_irq(hwif->irq, irq_handler, sa, hwif->name, hwif))
+ goto out_up;
#if !defined(__mc68000__)
printk(KERN_INFO "%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name,
@@ -944,9 +955,6 @@ static void drive_release_dev (struct device *dev)
blk_cleanup_queue(drive->queue);
drive->queue = NULL;
- kfree(drive->id);
- drive->id = NULL;
-
drive->dev_flags &= ~IDE_DFLAG_PRESENT;
complete(&drive->gendev_rel_comp);
@@ -999,9 +1007,9 @@ static void hwif_register_devices(ide_hwif_t *hwif)
int ret;
dev_set_name(dev, "%u.%u", hwif->index, i);
+ dev_set_drvdata(dev, drive);
dev->parent = &hwif->gendev;
dev->bus = &ide_bus_type;
- dev->driver_data = drive;
dev->release = drive_release_dev;
ret = device_register(dev);
@@ -1029,6 +1037,8 @@ static void ide_port_init_devices(ide_hwif_t *hwif)
if (hwif->host_flags & IDE_HFLAG_NO_UNMASK_IRQS)
drive->dev_flags |= IDE_DFLAG_NO_UNMASK;
+ drive->pio_mode = XFER_PIO_0;
+
if (port_ops && port_ops->init_dev)
port_ops->init_dev(drive);
}
@@ -1039,8 +1049,7 @@ static void ide_init_port(ide_hwif_t *hwif, unsigned int port,
{
hwif->channel = port;
- if (d->chipset)
- hwif->chipset = d->chipset;
+ hwif->chipset = d->chipset ? d->chipset : ide_pci;
if (d->init_iops)
d->init_iops(hwif);
@@ -1121,16 +1130,19 @@ static void ide_port_init_devices_data(ide_hwif_t *hwif)
ide_port_for_each_dev(i, drive, hwif) {
u8 j = (hwif->index * MAX_DRIVES) + i;
+ u16 *saved_id = drive->id;
memset(drive, 0, sizeof(*drive));
+ memset(saved_id, 0, SECTOR_SIZE);
+ drive->id = saved_id;
drive->media = ide_disk;
drive->select = (i << 4) | ATA_DEVICE_OBS;
drive->hwif = hwif;
drive->ready_stat = ATA_DRDY;
drive->bad_wstat = BAD_W_STAT;
- drive->special.b.recalibrate = 1;
- drive->special.b.set_geometry = 1;
+ drive->special_flags = IDE_SFLAG_RECALIBRATE |
+ IDE_SFLAG_SET_GEOMETRY;
drive->name[0] = 'h';
drive->name[1] = 'd';
drive->name[2] = 'a' + j;
@@ -1165,14 +1177,12 @@ static void ide_init_port_data(ide_hwif_t *hwif, unsigned int index)
ide_port_init_devices_data(hwif);
}
-static void ide_init_port_hw(ide_hwif_t *hwif, hw_regs_t *hw)
+static void ide_init_port_hw(ide_hwif_t *hwif, struct ide_hw *hw)
{
memcpy(&hwif->io_ports, &hw->io_ports, sizeof(hwif->io_ports));
hwif->irq = hw->irq;
- hwif->chipset = hw->chipset;
hwif->dev = hw->dev;
hwif->gendev.parent = hw->parent ? hw->parent : hw->dev;
- hwif->ack_intr = hw->ack_intr;
hwif->config_data = hw->config;
}
@@ -1189,7 +1199,7 @@ static int ide_find_port_slot(const struct ide_port_info *d)
{
int idx = -ENOENT;
u8 bootable = (d && (d->host_flags & IDE_HFLAG_NON_BOOTABLE)) ? 0 : 1;
- u8 i = (d && (d->host_flags & IDE_HFLAG_QD_2ND_PORT)) ? 1 : 0;;
+ u8 i = (d && (d->host_flags & IDE_HFLAG_QD_2ND_PORT)) ? 1 : 0;
/*
* Claim an unassigned slot.
@@ -1230,8 +1240,10 @@ static void ide_port_free_devices(ide_hwif_t *hwif)
ide_drive_t *drive;
int i;
- ide_port_for_each_dev(i, drive, hwif)
+ ide_port_for_each_dev(i, drive, hwif) {
+ kfree(drive->id);
kfree(drive);
+ }
}
static int ide_port_alloc_devices(ide_hwif_t *hwif, int node)
@@ -1245,6 +1257,18 @@ static int ide_port_alloc_devices(ide_hwif_t *hwif, int node)
if (drive == NULL)
goto out_nomem;
+ /*
+ * In order to keep things simple we have an id
+ * block for all drives at all times. If the device
+ * is pre ATA or refuses ATA/ATAPI identify we
+ * will add faked data to this.
+ *
+ * Also note that 0 everywhere means "can't do X"
+ */
+ drive->id = kzalloc_node(SECTOR_SIZE, GFP_KERNEL, node);
+ if (drive->id == NULL)
+ goto out_nomem;
+
hwif->devices[i] = drive;
}
return 0;
@@ -1254,7 +1278,8 @@ out_nomem:
return -ENOMEM;
}
-struct ide_host *ide_host_alloc(const struct ide_port_info *d, hw_regs_t **hws)
+struct ide_host *ide_host_alloc(const struct ide_port_info *d,
+ struct ide_hw **hws, unsigned int n_ports)
{
struct ide_host *host;
struct device *dev = hws[0] ? hws[0]->dev : NULL;
@@ -1265,7 +1290,7 @@ struct ide_host *ide_host_alloc(const struct ide_port_info *d, hw_regs_t **hws)
if (host == NULL)
return NULL;
- for (i = 0; i < MAX_HOST_PORTS; i++) {
+ for (i = 0; i < n_ports; i++) {
ide_hwif_t *hwif;
int idx;
@@ -1285,6 +1310,7 @@ struct ide_host *ide_host_alloc(const struct ide_port_info *d, hw_regs_t **hws)
if (idx < 0) {
printk(KERN_ERR "%s: no free slot for interface\n",
d ? d->name : "ide");
+ ide_port_free_devices(hwif);
kfree(hwif);
continue;
}
@@ -1341,7 +1367,7 @@ static void ide_disable_port(ide_hwif_t *hwif)
}
int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
- hw_regs_t **hws)
+ struct ide_hw **hws)
{
ide_hwif_t *hwif, *mate = NULL;
int i, j = 0;
@@ -1364,6 +1390,9 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
ide_init_port(hwif, i & 1, d);
ide_port_cable_detect(hwif);
+
+ hwif->port_flags |= IDE_PFLAG_PROBING;
+
ide_port_init_devices(hwif);
}
@@ -1374,6 +1403,8 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
if (ide_probe_port(hwif) == 0)
hwif->present = 1;
+ hwif->port_flags &= ~IDE_PFLAG_PROBING;
+
if ((hwif->host_flags & IDE_HFLAG_4DRIVES) == 0 ||
hwif->mate == NULL || hwif->mate->present == 0) {
if (ide_register_port(hwif)) {
@@ -1386,6 +1417,8 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
ide_port_tune_devices(hwif);
}
+ ide_host_enable_irqs(host);
+
ide_host_for_each_port(i, hwif, host) {
if (hwif == NULL)
continue;
@@ -1416,32 +1449,26 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
if (hwif == NULL)
continue;
- if (hwif->present)
- hwif_register_devices(hwif);
- }
-
- ide_host_for_each_port(i, hwif, host) {
- if (hwif == NULL)
- continue;
-
ide_sysfs_register_port(hwif);
ide_proc_register_port(hwif);
- if (hwif->present)
+ if (hwif->present) {
ide_proc_port_register_devices(hwif);
+ hwif_register_devices(hwif);
+ }
}
return j ? 0 : -1;
}
EXPORT_SYMBOL_GPL(ide_host_register);
-int ide_host_add(const struct ide_port_info *d, hw_regs_t **hws,
- struct ide_host **hostp)
+int ide_host_add(const struct ide_port_info *d, struct ide_hw **hws,
+ unsigned int n_ports, struct ide_host **hostp)
{
struct ide_host *host;
int rc;
- host = ide_host_alloc(d, hws);
+ host = ide_host_alloc(d, hws, n_ports);
if (host == NULL)
return -ENOMEM;
@@ -1507,7 +1534,8 @@ static void ide_unregister(ide_hwif_t *hwif)
ide_proc_unregister_port(hwif);
- free_irq(hwif->irq, hwif);
+ if (!hwif->host->get_lock)
+ free_irq(hwif->irq, hwif);
device_unregister(hwif->portdev);
device_unregister(&hwif->gendev);
@@ -1555,11 +1583,20 @@ EXPORT_SYMBOL_GPL(ide_host_remove);
void ide_port_scan(ide_hwif_t *hwif)
{
+ int rc;
+
ide_port_apply_params(hwif);
ide_port_cable_detect(hwif);
+
+ hwif->port_flags |= IDE_PFLAG_PROBING;
+
ide_port_init_devices(hwif);
- if (ide_probe_port(hwif) < 0)
+ rc = ide_probe_port(hwif);
+
+ hwif->port_flags &= ~IDE_PFLAG_PROBING;
+
+ if (rc < 0)
return;
hwif->present = 1;