diff options
Diffstat (limited to 'drivers/ata')
-rw-r--r-- | drivers/ata/Kconfig | 10 | ||||
-rw-r--r-- | drivers/ata/Makefile | 1 | ||||
-rw-r--r-- | drivers/ata/ahci.c | 104 | ||||
-rw-r--r-- | drivers/ata/libata-acpi.c | 104 | ||||
-rw-r--r-- | drivers/ata/libata-core.c | 63 | ||||
-rw-r--r-- | drivers/ata/libata-eh.c | 10 | ||||
-rw-r--r-- | drivers/ata/libata-scsi.c | 17 | ||||
-rw-r--r-- | drivers/ata/libata-sff.c | 36 | ||||
-rw-r--r-- | drivers/ata/pata_ali.c | 2 | ||||
-rw-r--r-- | drivers/ata/pata_hpt366.c | 6 | ||||
-rw-r--r-- | drivers/ata/pata_hpt37x.c | 6 | ||||
-rw-r--r-- | drivers/ata/pata_it821x.c | 2 | ||||
-rw-r--r-- | drivers/ata/pata_pdc2027x.c | 2 | ||||
-rw-r--r-- | drivers/ata/pata_rb500_cf.c | 314 | ||||
-rw-r--r-- | drivers/ata/pata_serverworks.c | 2 | ||||
-rw-r--r-- | drivers/ata/sata_promise.c | 109 |
16 files changed, 656 insertions, 132 deletions
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index ba8f7f4dfa1..25aba69b59b 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -30,6 +30,7 @@ config ATA_NONSTANDARD config ATA_ACPI bool depends on ACPI && PCI + select ACPI_DOCK default y help This option adds support for ATA-related ACPI objects. @@ -538,6 +539,15 @@ config PATA_RADISYS If unsure, say N. +config PATA_RB500 + tristate "RouterBoard 500 PATA CompactFlash support" + depends on MIKROTIK_RB500 + help + This option enables support for the RouterBoard 500 + PATA CompactFlash controller. + + If unsure, say N. + config PATA_RZ1000 tristate "PC Tech RZ1000 PATA support" depends on PCI diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index 701651e37c8..0511e6f0bb5 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile @@ -55,6 +55,7 @@ obj-$(CONFIG_PATA_PDC2027X) += pata_pdc2027x.o obj-$(CONFIG_PATA_PDC_OLD) += pata_pdc202xx_old.o obj-$(CONFIG_PATA_QDI) += pata_qdi.o obj-$(CONFIG_PATA_RADISYS) += pata_radisys.o +obj-$(CONFIG_PATA_RB500) += pata_rb500_cf.o obj-$(CONFIG_PATA_RZ1000) += pata_rz1000.o obj-$(CONFIG_PATA_SC1200) += pata_sc1200.o obj-$(CONFIG_PATA_SERVERWORKS) += pata_serverworks.o diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 1db93b61907..b1eb4e24c86 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -49,6 +49,10 @@ #define DRV_NAME "ahci" #define DRV_VERSION "3.0" +static int ahci_skip_host_reset; +module_param_named(skip_host_reset, ahci_skip_host_reset, int, 0444); +MODULE_PARM_DESC(skip_host_reset, "skip global host reset (0=don't skip, 1=skip)"); + static int ahci_enable_alpm(struct ata_port *ap, enum link_pm policy); static void ahci_disable_alpm(struct ata_port *ap); @@ -186,6 +190,7 @@ enum { AHCI_HFLAG_NO_MSI = (1 << 5), /* no PCI MSI */ AHCI_HFLAG_NO_PMP = (1 << 6), /* no PMP */ AHCI_HFLAG_NO_HOTPLUG = (1 << 7), /* ignore PxSERR.DIAG.N */ + AHCI_HFLAG_SECT255 = (1 << 8), /* max 255 sectors */ /* ap->flags bits */ @@ -255,6 +260,7 @@ static void ahci_vt8251_error_handler(struct ata_port *ap); static void ahci_p5wdh_error_handler(struct ata_port *ap); static void ahci_post_internal_cmd(struct ata_queued_cmd *qc); static int ahci_port_resume(struct ata_port *ap); +static void ahci_dev_config(struct ata_device *dev); static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl); static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag, u32 opts); @@ -294,6 +300,8 @@ static const struct ata_port_operations ahci_ops = { .check_altstatus = ahci_check_status, .dev_select = ata_noop_dev_select, + .dev_config = ahci_dev_config, + .tf_read = ahci_tf_read, .qc_defer = sata_pmp_qc_defer_cmd_switch, @@ -425,7 +433,8 @@ static const struct ata_port_info ahci_port_info[] = { /* board_ahci_sb600 */ { AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL | - AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_PMP), + AHCI_HFLAG_32BIT_ONLY | + AHCI_HFLAG_SECT255 | AHCI_HFLAG_NO_PMP), .flags = AHCI_FLAG_COMMON, .link_flags = AHCI_LFLAG_COMMON, .pio_mask = 0x1f, /* pio0-4 */ @@ -563,6 +572,18 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci }, /* MCP79 */ { PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci }, /* MCP79 */ { PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci }, /* MCP79 */ + { PCI_VDEVICE(NVIDIA, 0x0bc8), board_ahci }, /* MCP7B */ + { PCI_VDEVICE(NVIDIA, 0x0bc9), board_ahci }, /* MCP7B */ + { PCI_VDEVICE(NVIDIA, 0x0bca), board_ahci }, /* MCP7B */ + { PCI_VDEVICE(NVIDIA, 0x0bcb), board_ahci }, /* MCP7B */ + { PCI_VDEVICE(NVIDIA, 0x0bcc), board_ahci }, /* MCP7B */ + { PCI_VDEVICE(NVIDIA, 0x0bcd), board_ahci }, /* MCP7B */ + { PCI_VDEVICE(NVIDIA, 0x0bce), board_ahci }, /* MCP7B */ + { PCI_VDEVICE(NVIDIA, 0x0bcf), board_ahci }, /* MCP7B */ + { PCI_VDEVICE(NVIDIA, 0x0bd0), board_ahci }, /* MCP7B */ + { PCI_VDEVICE(NVIDIA, 0x0bd1), board_ahci }, /* MCP7B */ + { PCI_VDEVICE(NVIDIA, 0x0bd2), board_ahci }, /* MCP7B */ + { PCI_VDEVICE(NVIDIA, 0x0bd3), board_ahci }, /* MCP7B */ /* SiS */ { PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */ @@ -571,6 +592,7 @@ static const struct pci_device_id ahci_pci_tbl[] = { /* Marvell */ { PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */ + { PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv }, /* 6121 */ /* Generic, PCI class code for AHCI */ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, @@ -645,6 +667,7 @@ static void ahci_save_initial_config(struct pci_dev *pdev, void __iomem *mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR]; u32 cap, port_map; int i; + int mv; /* make sure AHCI mode is enabled before accessing CAP */ ahci_enable_ahci(mmio); @@ -668,7 +691,7 @@ static void ahci_save_initial_config(struct pci_dev *pdev, cap &= ~HOST_CAP_NCQ; } - if ((cap && HOST_CAP_PMP) && (hpriv->flags & AHCI_HFLAG_NO_PMP)) { + if ((cap & HOST_CAP_PMP) && (hpriv->flags & AHCI_HFLAG_NO_PMP)) { dev_printk(KERN_INFO, &pdev->dev, "controller can't do PMP, turning off CAP_PMP\n"); cap &= ~HOST_CAP_PMP; @@ -680,12 +703,16 @@ static void ahci_save_initial_config(struct pci_dev *pdev, * presence register, as bit 4 (counting from 0) */ if (hpriv->flags & AHCI_HFLAG_MV_PATA) { + if (pdev->device == 0x6121) + mv = 0x3; + else + mv = 0xf; dev_printk(KERN_ERR, &pdev->dev, "MV_AHCI HACK: port_map %x -> %x\n", - hpriv->port_map, - hpriv->port_map & 0xf); + port_map, + port_map & mv); - port_map &= 0xf; + port_map &= mv; } /* cross check port_map and cap.n_ports */ @@ -1072,29 +1099,35 @@ static int ahci_reset_controller(struct ata_host *host) ahci_enable_ahci(mmio); /* global controller reset */ - tmp = readl(mmio + HOST_CTL); - if ((tmp & HOST_RESET) == 0) { - writel(tmp | HOST_RESET, mmio + HOST_CTL); - readl(mmio + HOST_CTL); /* flush */ - } + if (!ahci_skip_host_reset) { + tmp = readl(mmio + HOST_CTL); + if ((tmp & HOST_RESET) == 0) { + writel(tmp | HOST_RESET, mmio + HOST_CTL); + readl(mmio + HOST_CTL); /* flush */ + } - /* reset must complete within 1 second, or - * the hardware should be considered fried. - */ - ssleep(1); + /* reset must complete within 1 second, or + * the hardware should be considered fried. + */ + ssleep(1); - tmp = readl(mmio + HOST_CTL); - if (tmp & HOST_RESET) { - dev_printk(KERN_ERR, host->dev, - "controller reset failed (0x%x)\n", tmp); - return -EIO; - } + tmp = readl(mmio + HOST_CTL); + if (tmp & HOST_RESET) { + dev_printk(KERN_ERR, host->dev, + "controller reset failed (0x%x)\n", tmp); + return -EIO; + } - /* turn on AHCI mode */ - ahci_enable_ahci(mmio); + /* turn on AHCI mode */ + ahci_enable_ahci(mmio); - /* some registers might be cleared on reset. restore initial values */ - ahci_restore_initial_config(host); + /* Some registers might be cleared on reset. Restore + * initial values. + */ + ahci_restore_initial_config(host); + } else + dev_printk(KERN_INFO, host->dev, + "skipping global host reset\n"); if (pdev->vendor == PCI_VENDOR_ID_INTEL) { u16 tmp16; @@ -1146,9 +1179,14 @@ static void ahci_init_controller(struct ata_host *host) int i; void __iomem *port_mmio; u32 tmp; + int mv; if (hpriv->flags & AHCI_HFLAG_MV_PATA) { - port_mmio = __ahci_port_base(host, 4); + if (pdev->device == 0x6121) + mv = 2; + else + mv = 4; + port_mmio = __ahci_port_base(host, mv); writel(0, port_mmio + PORT_IRQ_MASK); @@ -1176,6 +1214,17 @@ static void ahci_init_controller(struct ata_host *host) VPRINTK("HOST_CTL 0x%x\n", tmp); } +static void ahci_dev_config(struct ata_device *dev) +{ + struct ahci_host_priv *hpriv = dev->link->ap->host->private_data; + + if (hpriv->flags & AHCI_HFLAG_SECT255) { + dev->max_sectors = 255; + ata_dev_printk(dev, KERN_INFO, + "SB600 AHCI: limiting to 255 sectors per cmd\n"); + } +} + static unsigned int ahci_dev_classify(struct ata_port *ap) { void __iomem *port_mmio = ahci_port_base(ap); @@ -2217,7 +2266,10 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (rc) return rc; - rc = pcim_iomap_regions(pdev, 1 << AHCI_PCI_BAR, DRV_NAME); + /* AHCI controllers often implement SFF compatible interface. + * Grab all PCI BARs just in case. + */ + rc = pcim_iomap_regions_request_all(pdev, 1 << AHCI_PCI_BAR, DRV_NAME); if (rc == -EBUSY) pcim_pin_device(pdev); if (rc) diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index 9e8ec19260a..bf98a566ada 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c @@ -118,45 +118,77 @@ static void ata_acpi_associate_ide_port(struct ata_port *ap) ap->pflags |= ATA_PFLAG_INIT_GTM_VALID; } -static void ata_acpi_handle_hotplug(struct ata_port *ap, struct kobject *kobj, +static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev, u32 event) { char event_string[12]; char *envp[] = { event_string, NULL }; - struct ata_eh_info *ehi = &ap->link.eh_info; - - if (event == 0 || event == 1) { - unsigned long flags; - spin_lock_irqsave(ap->lock, flags); - ata_ehi_clear_desc(ehi); - ata_ehi_push_desc(ehi, "ACPI event"); - ata_ehi_hotplugged(ehi); - ata_port_freeze(ap); - spin_unlock_irqrestore(ap->lock, flags); + struct ata_eh_info *ehi; + struct kobject *kobj = NULL; + int wait = 0; + unsigned long flags; + + if (!ap) + ap = dev->link->ap; + ehi = &ap->link.eh_info; + + spin_lock_irqsave(ap->lock, flags); + + switch (event) { + case ACPI_NOTIFY_BUS_CHECK: + case ACPI_NOTIFY_DEVICE_CHECK: + ata_ehi_push_desc(ehi, "ACPI event"); + ata_ehi_hotplugged(ehi); + ata_port_freeze(ap); + break; + + case ACPI_NOTIFY_EJECT_REQUEST: + ata_ehi_push_desc(ehi, "ACPI event"); + if (dev) + dev->flags |= ATA_DFLAG_DETACH; + else { + struct ata_link *tlink; + struct ata_device *tdev; + + ata_port_for_each_link(tlink, ap) + ata_link_for_each_dev(tdev, tlink) + tdev->flags |= ATA_DFLAG_DETACH; + } + + ata_port_schedule_eh(ap); + wait = 1; + break; } + if (dev) { + if (dev->sdev) + kobj = &dev->sdev->sdev_gendev.kobj; + } else + kobj = &ap->dev->kobj; + if (kobj) { sprintf(event_string, "BAY_EVENT=%d", event); kobject_uevent_env(kobj, KOBJ_CHANGE, envp); } + + spin_unlock_irqrestore(ap->lock, flags); + + if (wait) + ata_port_wait_eh(ap); } static void ata_acpi_dev_notify(acpi_handle handle, u32 event, void *data) { struct ata_device *dev = data; - struct kobject *kobj = NULL; - if (dev->sdev) - kobj = &dev->sdev->sdev_gendev.kobj; - - ata_acpi_handle_hotplug(dev->link->ap, kobj, event); + ata_acpi_handle_hotplug(NULL, dev, event); } static void ata_acpi_ap_notify(acpi_handle handle, u32 event, void *data) { struct ata_port *ap = data; - ata_acpi_handle_hotplug(ap, &ap->dev->kobj, event); + ata_acpi_handle_hotplug(ap, NULL, event); } /** @@ -191,20 +223,30 @@ void ata_acpi_associate(struct ata_host *host) else ata_acpi_associate_ide_port(ap); - if (ap->acpi_handle) - acpi_install_notify_handler (ap->acpi_handle, - ACPI_SYSTEM_NOTIFY, - ata_acpi_ap_notify, - ap); + if (ap->acpi_handle) { + acpi_install_notify_handler(ap->acpi_handle, + ACPI_SYSTEM_NOTIFY, + ata_acpi_ap_notify, ap); +#if defined(CONFIG_ACPI_DOCK) || defined(CONFIG_ACPI_DOCK_MODULE) + /* we might be on a docking station */ + register_hotplug_dock_device(ap->acpi_handle, + ata_acpi_ap_notify, ap); +#endif + } for (j = 0; j < ata_link_max_devices(&ap->link); j++) { struct ata_device *dev = &ap->link.device[j]; - if (dev->acpi_handle) - acpi_install_notify_handler (dev->acpi_handle, - ACPI_SYSTEM_NOTIFY, - ata_acpi_dev_notify, - dev); + if (dev->acpi_handle) { + acpi_install_notify_handler(dev->acpi_handle, + ACPI_SYSTEM_NOTIFY, + ata_acpi_dev_notify, dev); +#if defined(CONFIG_ACPI_DOCK) || defined(CONFIG_ACPI_DOCK_MODULE) + /* we might be on a docking station */ + register_hotplug_dock_device(dev->acpi_handle, + ata_acpi_dev_notify, dev); +#endif + } } } } @@ -382,7 +424,7 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf) if (ata_msg_probe(ap)) ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER: port#: %d\n", - __FUNCTION__, ap->port_no); + __func__, ap->port_no); /* _GTF has no input parameters */ status = acpi_evaluate_object(dev->acpi_handle, "_GTF", NULL, &output); @@ -402,7 +444,7 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf) if (ata_msg_probe(ap)) ata_dev_printk(dev, KERN_DEBUG, "%s: Run _GTF: " "length or ptr is NULL (0x%llx, 0x%p)\n", - __FUNCTION__, + __func__, (unsigned long long)output.length, output.pointer); rc = -EINVAL; @@ -432,7 +474,7 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf) if (ata_msg_probe(ap)) ata_dev_printk(dev, KERN_DEBUG, "%s: returning gtf=%p, gtf_count=%d\n", - __FUNCTION__, *gtf, rc); + __func__, *gtf, rc); } return rc; @@ -725,7 +767,7 @@ static int ata_acpi_push_id(struct ata_device *dev) if (ata_msg_probe(ap)) ata_dev_printk(dev, KERN_DEBUG, "%s: ix = %d, port#: %d\n", - __FUNCTION__, dev->devno, ap->port_no); + __func__, dev->devno, ap->port_no); /* Give the drive Identify data to the drive via the _SDD method */ /* _SDD: set up input parameters */ diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 4fbcce758b0..c4248b37ff6 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -106,7 +106,8 @@ static struct ata_force_ent *ata_force_tbl; static int ata_force_tbl_size; static char ata_force_param_buf[PAGE_SIZE] __initdata; -module_param_string(force, ata_force_param_buf, sizeof(ata_force_param_buf), 0444); +/* param_buf is thrown away after initialization, disallow read */ +module_param_string(force, ata_force_param_buf, sizeof(ata_force_param_buf), 0); MODULE_PARM_DESC(force, "Force ATA configurations including cable type, link speed and transfer mode (see Documentation/kernel-parameters.txt for details)"); int atapi_enabled = 1; @@ -1415,12 +1416,12 @@ static int ata_hpa_resize(struct ata_device *dev) /* read native max address */ rc = ata_read_native_max_address(dev, &native_sectors); if (rc) { - /* If HPA isn't going to be unlocked, skip HPA - * resizing from the next try. + /* If device aborted the command or HPA isn't going to + * be unlocked, skip HPA resizing. */ - if (!ata_ignore_hpa) { + if (rc == -EACCES || !ata_ignore_hpa) { ata_dev_printk(dev, KERN_WARNING, "HPA support seems " - "broken, will skip HPA handling\n"); + "broken, skipping HPA handling\n"); dev->horkage |= ATA_HORKAGE_BROKEN_HPA; /* we can continue if device aborted the command */ @@ -1719,7 +1720,7 @@ void ata_port_flush_task(struct ata_port *ap) cancel_rearming_delayed_work(&ap->port_task); if (ata_msg_ctl(ap)) - ata_port_printk(ap, KERN_DEBUG, "%s: EXIT\n", __FUNCTION__); + ata_port_printk(ap, KERN_DEBUG, "%s: EXIT\n", __func__); } static void ata_qc_complete_internal(struct ata_queued_cmd *qc) @@ -2056,7 +2057,7 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, int rc; if (ata_msg_ctl(ap)) - ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __FUNCTION__); + ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __func__); ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */ retry: @@ -2091,24 +2092,34 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, id, sizeof(id[0]) * ATA_ID_WORDS, 0); if (err_mask) { if (err_mask & AC_ERR_NODEV_HINT) { - DPRINTK("ata%u.%d: NODEV after polling detection\n", - ap->print_id, dev->devno); + ata_dev_printk(dev, KERN_DEBUG, + "NODEV after polling detection\n"); return -ENOENT; } - /* Device or controller might have reported the wrong - * device class. Give a shot at the other IDENTIFY if - * the current one is aborted by the device. - */ - if (may_fallback && - (err_mask == AC_ERR_DEV) && (tf.feature & ATA_ABORTED)) { - may_fallback = 0; + if ((err_mask == AC_ERR_DEV) && (tf.feature & ATA_ABORTED)) { + /* Device or controller might have reported + * the wrong device class. Give a shot at the + * other IDENTIFY if the current one is + * aborted by the device. + */ + if (may_fallback) { + may_fallback = 0; - if (class == ATA_DEV_ATA) - class = ATA_DEV_ATAPI; - else - class = ATA_DEV_ATA; - goto retry; + if (class == ATA_DEV_ATA) + class = ATA_DEV_ATAPI; + else + class = ATA_DEV_ATA; + goto retry; + } + + /* Control reaches here iff the device aborted + * both flavors of IDENTIFYs which happens + * sometimes with phantom devices. + */ + ata_dev_printk(dev, KERN_DEBUG, + "both IDENTIFYs aborted, assuming NODEV\n"); + return -ENOENT; } rc = -EIO; @@ -2253,12 +2264,12 @@ int ata_dev_configure(struct ata_device *dev) if (!ata_dev_enabled(dev) && ata_msg_info(ap)) { ata_dev_printk(dev, KERN_INFO, "%s: ENTER/EXIT -- nodev\n", - __FUNCTION__); + __func__); return 0; } if (ata_msg_probe(ap)) - ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __FUNCTION__); + ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __func__); /* set horkage */ dev->horkage |= ata_dev_blacklisted(dev); @@ -2279,7 +2290,7 @@ int ata_dev_configure(struct ata_device *dev) ata_dev_printk(dev, KERN_DEBUG, "%s: cfg 49:%04x 82:%04x 83:%04x 84:%04x " "85:%04x 86:%04x 87:%04x 88:%04x\n", - __FUNCTION__, + __func__, id[49], id[82], id[83], id[84], id[85], id[86], id[87], id[88]); @@ -2511,13 +2522,13 @@ int ata_dev_configure(struct ata_device *dev) if (ata_msg_probe(ap)) ata_dev_printk(dev, KERN_DEBUG, "%s: EXIT, drv_stat = 0x%x\n", - __FUNCTION__, ata_chk_status(ap)); + __func__, ata_chk_status(ap)); return 0; err_out_nosup: if (ata_msg_probe(ap)) ata_dev_printk(dev, KERN_DEBUG, - "%s: EXIT, err\n", __FUNCTION__); + "%s: EXIT, err\n", __func__); return rc; } diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 698ce2cea52..681252fd814 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2150,6 +2150,15 @@ int ata_eh_reset(struct ata_link *link, int classify, ap->ops->set_piomode(ap, dev); } + if (!softreset && !hardreset) { + if (verbose) + ata_link_printk(link, KERN_INFO, "no reset method " + "available, skipping reset\n"); + if (!(lflags & ATA_LFLAG_ASSUME_CLASS)) + lflags |= ATA_LFLAG_ASSUME_ATA; + goto done; + } + /* Determine which reset to use and record in ehc->i.action. * prereset() may examine and modify it. */ @@ -2254,6 +2263,7 @@ int ata_eh_reset(struct ata_link *link, int classify, lflags |= ATA_LFLAG_ASSUME_ATA; } + done: ata_link_for_each_dev(dev, link) { /* After the reset, the device state is PIO 0 and the * controller state is undefined. Reset also wakes up diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 7b1f1ee8131..15795394b0a 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -527,6 +527,14 @@ static struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev, return qc; } +static void ata_qc_set_pc_nbytes(struct ata_queued_cmd *qc) +{ + struct scsi_cmnd *scmd = qc->scsicmd; + + qc->extrabytes = scmd->request->extra_len; + qc->nbytes = scsi_bufflen(scmd) + qc->extrabytes; +} + /** * ata_dump_status - user friendly display of error info * @id: id of the port in question @@ -862,9 +870,10 @@ static int ata_scsi_dev_config(struct scsi_device *sdev, struct request_queue *q = sdev->request_queue; void *buf; - /* set the min alignment */ + /* set the min alignment and padding */ blk_queue_update_dma_alignment(sdev->request_queue, ATA_DMA_PAD_SZ - 1); + blk_queue_dma_pad(sdev->request_queue, ATA_DMA_PAD_SZ - 1); /* configure draining */ buf = kmalloc(ATAPI_MAX_DRAIN, q->bounce_gfp | GFP_KERNEL); @@ -2538,7 +2547,7 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc) } qc->tf.command = ATA_CMD_PACKET; - qc->nbytes = scsi_bufflen(scmd); + ata_qc_set_pc_nbytes(qc); /* check whether ATAPI DMA is safe */ if (!using_pio && ata_check_atapi_dma(qc)) @@ -2549,7 +2558,7 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc) * want to set it properly, and for DMA where it is * effectively meaningless. */ - nbytes = min(scmd->request->raw_data_len, (unsigned int)63 * 1024); + nbytes = min(ata_qc_raw_nbytes(qc), (unsigned int)63 * 1024); /* Most ATAPI devices which honor transfer chunk size don't * behave according to the spec when odd chunk size which @@ -2875,7 +2884,7 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) * TODO: find out if we need to do more here to * cover scatter/gather case. */ - qc->nbytes = scsi_bufflen(scmd); + ata_qc_set_pc_nbytes(qc); /* request result TF and be quiet about device error */ qc->flags |= ATA_QCFLAG_RESULT_TF | ATA_QCFLAG_QUIET; diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 60cd4b17976..20dc572fb45 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -56,7 +56,8 @@ u8 ata_irq_on(struct ata_port *ap) ap->ctl &= ~ATA_NIEN; ap->last_ctl = ap->ctl; - iowrite8(ap->ctl, ioaddr->ctl_addr); + if (ioaddr->ctl_addr) + iowrite8(ap->ctl, ioaddr->ctl_addr); tmp = ata_wait_idle(ap); ap->ops->irq_clear(ap); @@ -81,12 +82,14 @@ void ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf) unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR; if (tf->ctl != ap->last_ctl) { - iowrite8(tf->ctl, ioaddr->ctl_addr); + if (ioaddr->ctl_addr) + iowrite8(tf->ctl, ioaddr->ctl_addr); ap->last_ctl = tf->ctl; ata_wait_idle(ap); } if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) { + WARN_ON(!ioaddr->ctl_addr); iowrite8(tf->hob_feature, ioaddr->feature_addr); iowrite8(tf->hob_nsect, ioaddr->nsect_addr); iowrite8(tf->hob_lbal, ioaddr->lbal_addr); @@ -167,14 +170,17 @@ void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf) tf->device = ioread8(ioaddr->device_addr); if (tf->flags & ATA_TFLAG_LBA48) { - iowrite8(tf->ctl | ATA_HOB, ioaddr->ctl_addr); - tf->hob_feature = ioread8(ioaddr->error_addr); - tf->hob_nsect = ioread8(ioaddr->nsect_addr); - tf->hob_lbal = ioread8(ioaddr->lbal_addr); - tf->hob_lbam = ioread8(ioaddr->lbam_addr); - tf->hob_lbah = ioread8(ioaddr->lbah_addr); - iowrite8(tf->ctl, ioaddr->ctl_addr); - ap->last_ctl = tf->ctl; + if (likely(ioaddr->ctl_addr)) { + iowrite8(tf->ctl | ATA_HOB, ioaddr->ctl_addr); + tf->hob_feature = ioread8(ioaddr->error_addr); + tf->hob_nsect = ioread8(ioaddr->nsect_addr); + tf->hob_lbal = ioread8(ioaddr->lbal_addr); + tf->hob_lbam = ioread8(ioaddr->lbam_addr); + tf->hob_lbah = ioread8(ioaddr->lbah_addr); + iowrite8(tf->ctl, ioaddr->ctl_addr); + ap->last_ctl = tf->ctl; + } else + WARN_ON(1); } } @@ -352,7 +358,8 @@ void ata_bmdma_freeze(struct ata_port *ap) ap->ctl |= ATA_NIEN; ap->last_ctl = ap->ctl; - iowrite8(ap->ctl, ioaddr->ctl_addr); + if (ioaddr->ctl_addr) + iowrite8(ap->ctl, ioaddr->ctl_addr); /* Under certain circumstances, some controllers raise IRQ on * ATA_NIEN manipulation. Also, many controllers fail to mask @@ -459,13 +466,14 @@ void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset, */ void ata_bmdma_error_handler(struct ata_port *ap) { - ata_reset_fn_t hardreset; + ata_reset_fn_t softreset = NULL, hardreset = NULL; - hardreset = NULL; + if (ap->ioaddr.ctl_addr) + softreset = ata_std_softreset; if (sata_scr_valid(&ap->link)) hardreset = sata_std_hardreset; - ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, hardreset, + ata_bmdma_drive_eh(ap, ata_std_prereset, softreset, hardreset, ata_std_postreset); } diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c index 7e68edf3c0f..8786455c901 100644 --- a/drivers/ata/pata_ali.c +++ b/drivers/ata/pata_ali.c @@ -295,7 +295,7 @@ static void ali_lock_sectors(struct ata_device *adev) static int ali_check_atapi_dma(struct ata_queued_cmd *qc) { /* If its not a media command, its not worth it */ - if (qc->nbytes < 2048) + if (atapi_cmd_type(qc->cdb[0]) == ATAPI_MISC) return -EOPNOTSUPP; return 0; } diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c index 0713872cf65..a742efa0da2 100644 --- a/drivers/ata/pata_hpt366.c +++ b/drivers/ata/pata_hpt366.c @@ -27,7 +27,7 @@ #include <linux/libata.h> #define DRV_NAME "pata_hpt366" -#define DRV_VERSION "0.6.1" +#define DRV_VERSION "0.6.2" struct hpt_clock { u8 xfer_speed; @@ -180,9 +180,9 @@ static unsigned long hpt366_filter(struct ata_device *adev, unsigned long mask) if (hpt_dma_blacklisted(adev, "UDMA", bad_ata33)) mask &= ~ATA_MASK_UDMA; if (hpt_dma_blacklisted(adev, "UDMA3", bad_ata66_3)) - mask &= ~(0x07 << ATA_SHIFT_UDMA); + mask &= ~(0xF8 << ATA_SHIFT_UDMA); if (hpt_dma_blacklisted(adev, "UDMA4", bad_ata66_4)) - mask &= ~(0x0F << ATA_SHIFT_UDMA); + mask &= ~(0xF0 << ATA_SHIFT_UDMA); } return ata_pci_default_filter(adev, mask); } diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c index 68eb34929ce..9a10878b2ad 100644 --- a/drivers/ata/pata_hpt37x.c +++ b/drivers/ata/pata_hpt37x.c @@ -24,7 +24,7 @@ #include <linux/libata.h> #define DRV_NAME "pata_hpt37x" -#define DRV_VERSION "0.6.9" +#define DRV_VERSION "0.6.11" struct hpt_clock { u8 xfer_speed; @@ -281,7 +281,7 @@ static unsigned long hpt370_filter(struct ata_device *adev, unsigned long mask) if (hpt_dma_blacklisted(adev, "UDMA", bad_ata33)) mask &= ~ATA_MASK_UDMA; if (hpt_dma_blacklisted(adev, "UDMA100", bad_ata100_5)) - mask &= ~(0x1F << ATA_SHIFT_UDMA); + mask &= ~(0xE0 << ATA_SHIFT_UDMA); } return ata_pci_default_filter(adev, mask); } @@ -297,7 +297,7 @@ static unsigned long hpt370a_filter(struct ata_device *adev, unsigned long mask) { if (adev->class == ATA_DEV_ATA) { if (hpt_dma_blacklisted(adev, "UDMA100", bad_ata100_5)) - mask &= ~ (0x1F << ATA_SHIFT_UDMA); + mask &= ~(0xE0 << ATA_SHIFT_UDMA); } return ata_pci_default_filter(adev, mask); } diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c index 109ddd42c26..257951d03db 100644 --- a/drivers/ata/pata_it821x.c +++ b/drivers/ata/pata_it821x.c @@ -564,7 +564,7 @@ static int it821x_check_atapi_dma(struct ata_queued_cmd *qc) struct it821x_dev *itdev = ap->private_data; /* Only use dma for transfers to/from the media. */ - if (qc->nbytes < 2048) + if (ata_qc_raw_nbytes(qc) < 2048) return -EOPNOTSUPP; /* No ATAPI DMA in smart mode */ diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c index 028af5dbeed..511c89b9bae 100644 --- a/drivers/ata/pata_pdc2027x.c +++ b/drivers/ata/pata_pdc2027x.c @@ -39,7 +39,7 @@ #undef PDC_DEBUG #ifdef PDC_DEBUG -#define PDPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args) +#define PDPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __func__, ## args) #else #define PDPRINTK(fmt, args...) #endif diff --git a/drivers/ata/pata_rb500_cf.c b/drivers/ata/pata_rb500_cf.c new file mode 100644 index 00000000000..4ce9b03fe6c --- /dev/null +++ b/drivers/ata/pata_rb500_cf.c @@ -0,0 +1,314 @@ +/* + * A low-level PATA driver to handle a Compact Flash connected on the + * Mikrotik's RouterBoard 532 board. + * + * Copyright (C) 2007 Gabor Juhos <juhosg at openwrt.org> + * Copyright (C) 2008 Florian Fainelli <florian@openwrt.org> + * + * This file was based on: drivers/ata/pata_ixp4xx_cf.c + * Copyright (C) 2006-07 Tower Technologies + * Author: Alessandro Zummo <a.zummo@towertech.it> + * + * Also was based on the driver for Linux 2.4.xx published by Mikrotik for + * their RouterBoard 1xx and 5xx series devices. The original Mikrotik code + * seems not to have a license. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/platform_device.h> + +#include <linux/io.h> +#include <linux/interrupt.h> +#include <linux/irq.h> + +#include <linux/libata.h> +#include <scsi/scsi_host.h> + +#include <asm/gpio.h> + +#define DRV_NAME "pata-rb500-cf" +#define DRV_VERSION "0.1.0" +#define DRV_DESC "PATA driver for RouterBOARD 532 Compact Flash" + +#define RB500_CF_MAXPORTS 1 +#define RB500_CF_IO_DELAY 400 + +#define RB500_CF_REG_CMD 0x0800 +#define RB500_CF_REG_CTRL 0x080E +#define RB500_CF_REG_DATA 0x0C00 + +struct rb500_cf_info { + void __iomem *iobase; + unsigned int gpio_line; + int frozen; + unsigned int irq; +}; + +/* ------------------------------------------------------------------------ */ + +static inline void rb500_pata_finish_io(struct ata_port *ap) +{ + struct ata_host *ah = ap->host; + struct rb500_cf_info *info = ah->private_data; + + ata_altstatus(ap); + ndelay(RB500_CF_IO_DELAY); + + set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH); +} + +static void rb500_pata_exec_command(struct ata_port *ap, + const struct ata_taskfile *tf) +{ + writeb(tf->command, ap->ioaddr.command_addr); + rb500_pata_finish_io(ap); +} + +static void rb500_pata_data_xfer(struct ata_device *adev, unsigned char *buf, + unsigned int buflen, int write_data) +{ + struct ata_port *ap = adev->link->ap; + void __iomem *ioaddr = ap->ioaddr.data_addr; + + if (write_data) { + for (; buflen > 0; buflen--, buf++) + writeb(*buf, ioaddr); + } else { + for (; buflen > 0; buflen--, buf++) + *buf = readb(ioaddr); + } + + rb500_pata_finish_io(adev->link->ap); +} + +static void rb500_pata_freeze(struct ata_port *ap) +{ + struct rb500_cf_info *info = ap->host->private_data; + + info->frozen = 1; +} + +static void rb500_pata_thaw(struct ata_port *ap) +{ + struct rb500_cf_info *info = ap->host->private_data; + + info->frozen = 0; +} + +static irqreturn_t rb500_pata_irq_handler(int irq, void *dev_instance) +{ + struct ata_host *ah = dev_instance; + struct rb500_cf_info *info = ah->private_data; + + if (gpio_get_value(info->gpio_line)) { + set_irq_type(info->irq, IRQ_TYPE_LEVEL_LOW); + if (!info->frozen) + ata_interrupt(info->irq, dev_instance); + } else { + set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH); + } + + return IRQ_HANDLED; +} + +static void rb500_pata_irq_clear(struct ata_port *ap) +{ +} + +static int rb500_pata_port_start(struct ata_port *ap) +{ + return 0; +} + +static struct ata_port_operations rb500_pata_port_ops = { + .tf_load = ata_tf_load, + .tf_read = ata_tf_read, + + .exec_command = rb500_pata_exec_command, + .check_status = ata_check_status, + .dev_select = ata_std_dev_select, + + .data_xfer = rb500_pata_data_xfer, + + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, + + .freeze = rb500_pata_freeze, + .thaw = rb500_pata_thaw, + .error_handler = ata_bmdma_error_handler, + + .irq_handler = rb500_pata_irq_handler, + .irq_clear = rb500_pata_irq_clear, + .irq_on = ata_irq_on, + + .port_start = rb500_pata_port_start, +}; + +/* ------------------------------------------------------------------------ */ + +static struct scsi_host_template rb500_pata_sht = { + .module = THIS_MODULE, + .name = DRV_NAME, + .ioctl = ata_scsi_ioctl, + .queuecommand = ata_scsi_queuecmd, + .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, + .bios_param = ata_std_bios_param, + .proc_name = DRV_NAME, + + .can_queue = ATA_DEF_QUEUE, + .this_id = ATA_SHT_THIS_ID, + .sg_tablesize = LIBATA_MAX_PRD, + .dma_boundary = ATA_DMA_BOUNDARY, + .cmd_per_lun = ATA_SHT_CMD_PER_LUN, + .emulated = ATA_SHT_EMULATED, + .use_clustering = ATA_SHT_USE_CLUSTERING, +}; + +/* ------------------------------------------------------------------------ */ + +static void rb500_pata_setup_ports(struct ata_host *ah) +{ + struct rb500_cf_info *info = ah->private_data; + struct ata_port *ap; + + ap = ah->ports[0]; + + ap->ops = &rb500_pata_port_ops; + ap->pio_mask = 0x1f; /* PIO4 */ + ap->flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO; + + ap->ioaddr.cmd_addr = info->iobase + RB500_CF_REG_CMD; + ap->ioaddr.ctl_addr = info->iobase + RB500_CF_REG_CTRL; + ap->ioaddr.altstatus_addr = info->iobase + RB500_CF_REG_CTRL; + + ata_std_ports(&ap->ioaddr); + + ap->ioaddr.data_addr = info->iobase + RB500_CF_REG_DATA; +} + +static __devinit int rb500_pata_driver_probe(struct platform_device *pdev) +{ + unsigned int irq; + int gpio; + struct resource *res; + struct ata_host *ah; + struct rb500_cf_info *info; + int ret; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "no IOMEM resource found\n"); + return -EINVAL; + } + + irq = platform_get_irq(pdev, 0); + if (irq <= 0) { + dev_err(&pdev->dev, "no IRQ resource found\n"); + return -ENOENT; + } + + gpio = irq_to_gpio(irq); + if (gpio < 0) { + dev_err(&pdev->dev, "no GPIO found for irq%d\n", irq); + return -ENOENT; + } + + ret = gpio_request(gpio, DRV_NAME); + if (ret) { + dev_err(&pdev->dev, "GPIO request failed\n"); + return ret; + } + + /* allocate host */ + ah = ata_host_alloc(&pdev->dev, RB500_CF_MAXPORTS); + if (!ah) + return -ENOMEM; + + platform_set_drvdata(pdev, ah); + + info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + ah->private_data = info; + info->gpio_line = gpio; + info->irq = irq; + + info->iobase = devm_ioremap_nocache(&pdev->dev, res->start, + res->end - res->start + 1); + if (!info->iobase) + return -ENOMEM; + + ret = gpio_direction_input(gpio); + if (ret) { + dev_err(&pdev->dev, "unable to set GPIO direction, err=%d\n", + ret); + goto err_free_gpio; + } + + rb500_pata_setup_ports(ah); + + ret = ata_host_activate(ah, irq, rb500_pata_irq_handler, + IRQF_TRIGGER_LOW, &rb500_pata_sht); + if (ret) + goto err_free_gpio; + + return 0; + +err_free_gpio: + gpio_free(gpio); + + return ret; +} + +static __devexit int rb500_pata_driver_remove(struct platform_device *pdev) +{ + struct ata_host *ah = platform_get_drvdata(pdev); + struct rb500_cf_info *info = ah->private_data; + + ata_host_detach(ah); + gpio_free(info->gpio_line); + + return 0; +} + +static struct platform_driver rb500_pata_platform_driver = { + .probe = rb500_pata_driver_probe, + .remove = __devexit_p(rb500_pata_driver_remove), + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + }, +}; + +/* ------------------------------------------------------------------------ */ + +#define DRV_INFO DRV_DESC " version " DRV_VERSION + +static int __init rb500_pata_module_init(void) +{ + printk(KERN_INFO DRV_INFO "\n"); + + return platform_driver_register(&rb500_pata_platform_driver); +} + +static void __exit rb500_pata_module_exit(void) +{ + platform_driver_unregister(&rb500_pata_platform_driver); +} + +MODULE_AUTHOR("Gabor Juhos <juhosg at openwrt.org>"); +MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>"); +MODULE_DESCRIPTION(DRV_DESC); +MODULE_VERSION(DRV_VERSION); +MODULE_LICENSE("GPL"); + +module_init(rb500_pata_module_init); +module_exit(rb500_pata_module_exit); diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c index 9c523fbf529..a589c0fa0db 100644 --- a/drivers/ata/pata_serverworks.c +++ b/drivers/ata/pata_serverworks.c @@ -226,7 +226,7 @@ static unsigned long serverworks_csb_filter(struct ata_device *adev, unsigned lo for (i = 0; (p = csb_bad_ata100[i]) != NULL; i++) { if (!strcmp(p, model_num)) - mask &= ~(0x1F << ATA_SHIFT_UDMA); + mask &= ~(0xE0 << ATA_SHIFT_UDMA); } return ata_pci_default_filter(adev, mask); } diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c index f251a5f569d..11c1afea2db 100644 --- a/drivers/ata/sata_promise.c +++ b/drivers/ata/sata_promise.c @@ -46,7 +46,7 @@ #include "sata_promise.h" #define DRV_NAME "sata_promise" -#define DRV_VERSION "2.11" +#define DRV_VERSION "2.12" enum { PDC_MAX_PORTS = 4, @@ -145,7 +145,9 @@ static int pdc_old_sata_check_atapi_dma(struct ata_queued_cmd *qc); static void pdc_irq_clear(struct ata_port *ap); static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc); static void pdc_freeze(struct ata_port *ap); +static void pdc_sata_freeze(struct ata_port *ap); static void pdc_thaw(struct ata_port *ap); +static void pdc_sata_thaw(struct ata_port *ap); static void pdc_pata_error_handler(struct ata_port *ap); static void pdc_sata_error_handler(struct ata_port *ap); static void pdc_post_internal_cmd(struct ata_queued_cmd *qc); @@ -180,8 +182,8 @@ static const struct ata_port_operations pdc_sata_ops = { .qc_prep = pdc_qc_prep, .qc_issue = pdc_qc_issue_prot, - .freeze = pdc_freeze, - .thaw = pdc_thaw, + .freeze = pdc_sata_freeze, + .thaw = pdc_sata_thaw, .error_handler = pdc_sata_error_handler, .post_internal_cmd = pdc_post_internal_cmd, .cable_detect = pdc_sata_cable_detect, @@ -205,8 +207,8 @@ static const struct ata_port_operations pdc_old_sata_ops = { .qc_prep = pdc_qc_prep, .qc_issue = pdc_qc_issue_prot, - .freeze = pdc_freeze, - .thaw = pdc_thaw, + .freeze = pdc_sata_freeze, + .thaw = pdc_sata_thaw, .error_handler = pdc_sata_error_handler, .post_internal_cmd = pdc_post_internal_cmd, .cable_detect = pdc_sata_cable_detect, @@ -631,6 +633,41 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc) } } +static int pdc_is_sataii_tx4(unsigned long flags) +{ + const unsigned long mask = PDC_FLAG_GEN_II | PDC_FLAG_4_PORTS; + return (flags & mask) == mask; +} + +static unsigned int pdc_port_no_to_ata_no(unsigned int port_no, + int is_sataii_tx4) +{ + static const unsigned char sataii_tx4_port_remap[4] = { 3, 1, 0, 2}; + return is_sataii_tx4 ? sataii_tx4_port_remap[port_no] : port_no; +} + +static unsigned int pdc_sata_nr_ports(const struct ata_port *ap) +{ + return (ap->flags & PDC_FLAG_4_PORTS) ? 4 : 2; +} + +static unsigned int pdc_sata_ata_port_to_ata_no(const struct ata_port *ap) +{ + const struct ata_host *host = ap->host; + unsigned int nr_ports = pdc_sata_nr_ports(ap); + unsigned int i; + + for(i = 0; i < nr_ports && host->ports[i] != ap; ++i) + ; + BUG_ON(i >= nr_ports); + return pdc_port_no_to_ata_no(i, pdc_is_sataii_tx4(ap->flags)); +} + +static unsigned int pdc_sata_hotplug_offset(const struct ata_port *ap) +{ + return (ap->flags & PDC_FLAG_GEN_II) ? PDC2_SATA_PLUG_CSR : PDC_SATA_PLUG_CSR; +} + static void pdc_freeze(struct ata_port *ap) { void __iomem *mmio = ap->ioaddr.cmd_addr; @@ -643,6 +680,29 @@ static void pdc_freeze(struct ata_port *ap) readl(mmio + PDC_CTLSTAT); /* flush */ } +static void pdc_sata_freeze(struct ata_port *ap) +{ + struct ata_host *host = ap->host; + void __iomem *host_mmio = host->iomap[PDC_MMIO_BAR]; + unsigned int hotplug_offset = pdc_sata_hotplug_offset(ap); + unsigned int ata_no = pdc_sata_ata_port_to_ata_no(ap); + u32 hotplug_status; + + /* Disable hotplug events on this port. + * + * Locking: + * 1) hotplug register accesses must be serialised via host->lock + * 2) ap->lock == &ap->host->lock + * 3) ->freeze() and ->thaw() are called with ap->lock held + */ + hotplug_status = readl(host_mmio + hotplug_offset); + hotplug_status |= 0x11 << (ata_no + 16); + writel(hotplug_status, host_mmio + hotplug_offset); + readl(host_mmio + hotplug_offset); /* flush */ + + pdc_freeze(ap); +} + static void pdc_thaw(struct ata_port *ap) { void __iomem *mmio = ap->ioaddr.cmd_addr; @@ -658,6 +718,26 @@ static void pdc_thaw(struct ata_port *ap) readl(mmio + PDC_CTLSTAT); /* flush */ } +static void pdc_sata_thaw(struct ata_port *ap) +{ + struct ata_host *host = ap->host; + void __iomem *host_mmio = host->iomap[PDC_MMIO_BAR]; + unsigned int hotplug_offset = pdc_sata_hotplug_offset(ap); + unsigned int ata_no = pdc_sata_ata_port_to_ata_no(ap); + u32 hotplug_status; + + pdc_thaw(ap); + + /* Enable hotplug events on this port. + * Locking: see pdc_sata_freeze(). + */ + hotplug_status = readl(host_mmio + hotplug_offset); + hotplug_status |= 0x11 << ata_no; + hotplug_status &= ~(0x11 << (ata_no + 16)); + writel(hotplug_status, host_mmio + hotplug_offset); + readl(host_mmio + hotplug_offset); /* flush */ +} + static void pdc_common_error_handler(struct ata_port *ap, ata_reset_fn_t hardreset) { if (!(ap->pflags & ATA_PFLAG_FROZEN)) @@ -765,19 +845,6 @@ static void pdc_irq_clear(struct ata_port *ap) readl(mmio + PDC_INT_SEQMASK); } -static int pdc_is_sataii_tx4(unsigned long flags) -{ - const unsigned long mask = PDC_FLAG_GEN_II | PDC_FLAG_4_PORTS; - return (flags & mask) == mask; -} - -static unsigned int pdc_port_no_to_ata_no(unsigned int port_no, - int is_sataii_tx4) -{ - static const unsigned char sataii_tx4_port_remap[4] = { 3, 1, 0, 2}; - return is_sataii_tx4 ? sataii_tx4_port_remap[port_no] : port_no; -} - static irqreturn_t pdc_interrupt(int irq, void *dev_instance) { struct ata_host *host = dev_instance; @@ -799,6 +866,8 @@ static irqreturn_t pdc_interrupt(int irq, void *dev_instance) mmio_base = host->iomap[PDC_MMIO_BAR]; + spin_lock(&host->lock); + /* read and clear hotplug flags for all ports */ if (host->ports[0]->flags & PDC_FLAG_GEN_II) hotplug_offset = PDC2_SATA_PLUG_CSR; @@ -814,11 +883,9 @@ static irqreturn_t pdc_interrupt(int irq, void *dev_instance) if (mask == 0xffffffff && hotplug_status == 0) { VPRINTK("QUICK EXIT 2\n"); - return IRQ_NONE; + goto done_irq; } - spin_lock(&host->lock); - mask &= 0xffff; /* only 16 tags possible */ if (mask == 0 && hotplug_status == 0) { VPRINTK("QUICK EXIT 3\n"); |