From 5b97fbd093ac2e0da0c7eec894fee065a04af55d Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 29 Oct 2008 22:35:08 -0700 Subject: ATA: remove excess kernel-doc notation Remove excess kernel-doc function parameter notation from drivers/ata/: Warning(drivers/ata/libata-core.c:1622): Excess function parameter or struct member 'fn' description in 'ata_pio_queue_task' Warning(drivers/ata/libata-core.c:4655): Excess function parameter or struct member 'err_mask' description in 'ata_qc_complete' Warning(drivers/ata/ata_piix.c:751): Excess function parameter or struct member 'udma' description in 'do_pata_set_dmamode' Signed-off-by: Randy Dunlap Signed-off-by: Jeff Garzik --- drivers/ata/ata_piix.c | 1 - drivers/ata/libata-core.c | 2 -- 2 files changed, 3 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 52dc2d8b8f22..8e37be19bbf5 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -738,7 +738,6 @@ static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev) * do_pata_set_dmamode - Initialize host controller PATA PIO timings * @ap: Port whose timings we are configuring * @adev: Drive in question - * @udma: udma mode, 0 - 6 * @isich: set if the chip is an ICH device * * Set UDMA mode for device, in host controller PCI config space. diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 2ff633c119e2..e398df12fd18 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -1602,7 +1602,6 @@ unsigned long ata_id_xfermask(const u16 *id) /** * ata_pio_queue_task - Queue port_task * @ap: The ata_port to queue port_task for - * @fn: workqueue function to be scheduled * @data: data for @fn to use * @delay: delay time in msecs for workqueue function * @@ -4648,7 +4647,6 @@ static void ata_verify_xfer(struct ata_queued_cmd *qc) /** * ata_qc_complete - Complete an active ATA command * @qc: Command to complete - * @err_mask: ATA Status register contents * * Indicate to the mid and upper layers that an ATA * command has completed, with either an ok or not-ok status. -- cgit v1.2.3 From ba14a9c291aa867896a90b3571fcc1c3759942ff Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Tue, 28 Oct 2008 16:52:20 -0700 Subject: libata: Avoid overflow in ata_tf_to_lba48() when tf->hba_lbal > 127 In ata_tf_to_lba48(), when evaluating (tf->hob_lbal & 0xff) << 24 the expression is promoted to signed int (since int can hold all values of u8). However, if hob_lbal is 128 or more, then it is treated as a negative signed value and sign-extended when promoted to u64 to | into sectors, which leads to the MSB 32 bits of section getting set incorrectly. For example, Phillip O'Donnell reported that a 1.5GB drive caused: ata3.00: HPA detected: current 2930277168, native 18446744072344861488 where 2930277168 == 0xAEA87B30 and 18446744072344861488 == 0xffffffffaea87b30 which shows the problem when hob_lbal is 0xae. Fix this by adding a cast to u64, just as is used by for hob_lbah and hob_lbam in the function. Reported-by: Phillip O'Donnell Signed-off-by: Roland Dreier Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/ata') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index e398df12fd18..8824c8da3f2f 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -1268,7 +1268,7 @@ u64 ata_tf_to_lba48(const struct ata_taskfile *tf) sectors |= ((u64)(tf->hob_lbah & 0xff)) << 40; sectors |= ((u64)(tf->hob_lbam & 0xff)) << 32; - sectors |= (tf->hob_lbal & 0xff) << 24; + sectors |= ((u64)(tf->hob_lbal & 0xff)) << 24; sectors |= (tf->lbah & 0xff) << 16; sectors |= (tf->lbam & 0xff) << 8; sectors |= (tf->lbal & 0xff); -- cgit v1.2.3 From b9d5b89b487517cbd4cb4702da829e07ef9e4432 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 22 Oct 2008 00:46:36 +0900 Subject: sata_via: fix support for 5287 5287 used to be treated as vt6420 but it didn't work. It's new family of controllers called vt8251 which hosts four SATA ports as M/S of the two ATA ports. This configuration is rather peculiar in that although the M/S devices are on the same port, each have its own SCR (or equivalent link status/control) registers which screws up the port-link-device hierarchy assumed by libata. Another controller which falls into this category is ata_piix w/ SIDPR access. libata now has facility to deal with this class of controllers named slave_link. A low level driver for such controllers can just call ata_slave_link_init() on the respective ports and libata will handle all the difficult parts like following up with single SRST after hardresetting both ports. This patch creates new controller class vt8251, implements slave_link aware init sequence and config space based SCR access for it and moves 5287 to the new class. This patch is based on Joseph Chan's larger patch which was created before slave_link was implemented in libata. http://thread.gmane.org/gmane.linux.kernel.commits.mm/40640 Signed-off-by: Tejun Heo Cc: Joseph Chan Signed-off-by: Jeff Garzik --- drivers/ata/sata_via.c | 155 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 143 insertions(+), 12 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index 5b72e734300a..62367fe4d5dc 100644 --- a/drivers/ata/sata_via.c +++ b/drivers/ata/sata_via.c @@ -44,11 +44,16 @@ #include #define DRV_NAME "sata_via" -#define DRV_VERSION "2.3" +#define DRV_VERSION "2.4" +/* + * vt8251 is different from other sata controllers of VIA. It has two + * channels, each channel has both Master and Slave slot. + */ enum board_ids_enum { vt6420, vt6421, + vt8251, }; enum { @@ -70,6 +75,8 @@ enum { static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); static int svia_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); static int svia_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val); +static int vt8251_scr_read(struct ata_link *link, unsigned int scr, u32 *val); +static int vt8251_scr_write(struct ata_link *link, unsigned int scr, u32 val); static void svia_tf_load(struct ata_port *ap, const struct ata_taskfile *tf); static void svia_noop_freeze(struct ata_port *ap); static int vt6420_prereset(struct ata_link *link, unsigned long deadline); @@ -79,12 +86,12 @@ static void vt6421_set_dma_mode(struct ata_port *ap, struct ata_device *adev); static const struct pci_device_id svia_pci_tbl[] = { { PCI_VDEVICE(VIA, 0x5337), vt6420 }, - { PCI_VDEVICE(VIA, 0x0591), vt6420 }, - { PCI_VDEVICE(VIA, 0x3149), vt6420 }, - { PCI_VDEVICE(VIA, 0x3249), vt6421 }, - { PCI_VDEVICE(VIA, 0x5287), vt6420 }, + { PCI_VDEVICE(VIA, 0x0591), vt6420 }, /* 2 sata chnls (Master) */ + { PCI_VDEVICE(VIA, 0x3149), vt6420 }, /* 2 sata chnls (Master) */ + { PCI_VDEVICE(VIA, 0x3249), vt6421 }, /* 2 sata chnls, 1 pata chnl */ { PCI_VDEVICE(VIA, 0x5372), vt6420 }, { PCI_VDEVICE(VIA, 0x7372), vt6420 }, + { PCI_VDEVICE(VIA, 0x5287), vt8251 }, /* 2 sata chnls (Master/Slave) */ { } /* terminate list */ }; @@ -128,6 +135,13 @@ static struct ata_port_operations vt6421_sata_ops = { .scr_write = svia_scr_write, }; +static struct ata_port_operations vt8251_ops = { + .inherits = &svia_base_ops, + .hardreset = sata_std_hardreset, + .scr_read = vt8251_scr_read, + .scr_write = vt8251_scr_write, +}; + static const struct ata_port_info vt6420_port_info = { .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, .pio_mask = 0x1f, @@ -152,6 +166,15 @@ static struct ata_port_info vt6421_pport_info = { .port_ops = &vt6421_pata_ops, }; +static struct ata_port_info vt8251_port_info = { + .flags = ATA_FLAG_SATA | ATA_FLAG_SLAVE_POSS | + ATA_FLAG_NO_LEGACY, + .pio_mask = 0x1f, + .mwdma_mask = 0x07, + .udma_mask = ATA_UDMA6, + .port_ops = &vt8251_ops, +}; + MODULE_AUTHOR("Jeff Garzik"); MODULE_DESCRIPTION("SCSI low-level driver for VIA SATA controllers"); MODULE_LICENSE("GPL"); @@ -174,6 +197,83 @@ static int svia_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val) return 0; } +static int vt8251_scr_read(struct ata_link *link, unsigned int scr, u32 *val) +{ + static const u8 ipm_tbl[] = { 1, 2, 6, 0 }; + struct pci_dev *pdev = to_pci_dev(link->ap->host->dev); + int slot = 2 * link->ap->port_no + link->pmp; + u32 v = 0; + u8 raw; + + switch (scr) { + case SCR_STATUS: + pci_read_config_byte(pdev, 0xA0 + slot, &raw); + + /* read the DET field, bit0 and 1 of the config byte */ + v |= raw & 0x03; + + /* read the SPD field, bit4 of the configure byte */ + if (raw & (1 << 4)) + v |= 0x02 << 4; + else + v |= 0x01 << 4; + + /* read the IPM field, bit2 and 3 of the config byte */ + v |= ipm_tbl[(raw >> 2) & 0x3]; + break; + + case SCR_ERROR: + /* devices other than 5287 uses 0xA8 as base */ + WARN_ON(pdev->device != 0x5287); + pci_read_config_dword(pdev, 0xB0 + slot * 4, &v); + break; + + case SCR_CONTROL: + pci_read_config_byte(pdev, 0xA4 + slot, &raw); + + /* read the DET field, bit0 and bit1 */ + v |= ((raw & 0x02) << 1) | (raw & 0x01); + + /* read the IPM field, bit2 and bit3 */ + v |= ((raw >> 2) & 0x03) << 8; + break; + + default: + return -EINVAL; + } + + *val = v; + return 0; +} + +static int vt8251_scr_write(struct ata_link *link, unsigned int scr, u32 val) +{ + struct pci_dev *pdev = to_pci_dev(link->ap->host->dev); + int slot = 2 * link->ap->port_no + link->pmp; + u32 v = 0; + + switch (scr) { + case SCR_ERROR: + /* devices other than 5287 uses 0xA8 as base */ + WARN_ON(pdev->device != 0x5287); + pci_write_config_dword(pdev, 0xB0 + slot * 4, val); + return 0; + + case SCR_CONTROL: + /* set the DET field */ + v |= ((val & 0x4) >> 1) | (val & 0x1); + + /* set the IPM field */ + v |= ((val >> 8) & 0x3) << 2; + + pci_write_config_byte(pdev, 0xA4 + slot, v); + return 0; + + default: + return -EINVAL; + } +} + /** * svia_tf_load - send taskfile registers to host controller * @ap: Port to which output is sent @@ -396,6 +496,30 @@ static int vt6421_prepare_host(struct pci_dev *pdev, struct ata_host **r_host) return 0; } +static int vt8251_prepare_host(struct pci_dev *pdev, struct ata_host **r_host) +{ + const struct ata_port_info *ppi[] = { &vt8251_port_info, NULL }; + struct ata_host *host; + int i, rc; + + rc = ata_pci_sff_prepare_host(pdev, ppi, &host); + if (rc) + return rc; + *r_host = host; + + rc = pcim_iomap_regions(pdev, 1 << 5, DRV_NAME); + if (rc) { + dev_printk(KERN_ERR, &pdev->dev, "failed to iomap PCI BAR 5\n"); + return rc; + } + + /* 8251 hosts four sata ports as M/S of the two channels */ + for (i = 0; i < host->n_ports; i++) + ata_slave_link_init(host->ports[i]); + + return 0; +} + static void svia_configure(struct pci_dev *pdev) { u8 tmp8; @@ -451,10 +575,10 @@ static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (rc) return rc; - if (board_id == vt6420) - bar_sizes = &svia_bar_sizes[0]; - else + if (board_id == vt6421) bar_sizes = &vt6421_bar_sizes[0]; + else + bar_sizes = &svia_bar_sizes[0]; for (i = 0; i < ARRAY_SIZE(svia_bar_sizes); i++) if ((pci_resource_start(pdev, i) == 0) || @@ -467,12 +591,19 @@ static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) return -ENODEV; } - if (board_id == vt6420) + switch (board_id) { + case vt6420: rc = vt6420_prepare_host(pdev, &host); - else + break; + case vt6421: rc = vt6421_prepare_host(pdev, &host); - if (rc) - return rc; + break; + case vt8251: + rc = vt8251_prepare_host(pdev, &host); + break; + default: + return -EINVAL; + } svia_configure(pdev); -- cgit v1.2.3 From 9ce8e3073d9cfd6f859c22a25441db41b85cbf6e Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 27 Aug 2008 15:23:18 +0200 Subject: libata: add whitelist for devices with known good pata-sata bridges libata currently imposes a UDMA5 max transfer rate and 200 sector max transfer size for SATA devices that sit behind a pata-sata bridge. Lots of devices have known good bridges that don't need this limit applied. The MTRON SSD disks are such devices. Transfer rates are increased by 20-30% with the restriction removed. So add a "blacklist" entry for the MTRON devices, with a flag indicating that the bridge is known good. Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/ata') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 8824c8da3f2f..82af7011f2dd 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2158,6 +2158,10 @@ retry: static inline u8 ata_dev_knobble(struct ata_device *dev) { struct ata_port *ap = dev->link->ap; + + if (ata_dev_blacklisted(dev) & ATA_HORKAGE_BRIDGE_OK) + return 0; + return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id))); } @@ -4062,6 +4066,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "TSSTcorp CDDVDW SH-S202N", "SB00", ATA_HORKAGE_IVB, }, { "TSSTcorp CDDVDW SH-S202N", "SB01", ATA_HORKAGE_IVB, }, + /* Devices that do not need bridging limits applied */ + { "MTRON MSP-SATA*", NULL, ATA_HORKAGE_BRIDGE_OK, }, + /* End Marker */ { } }; -- cgit v1.2.3 From cadef677e4a9b9c1d069675043767df486782986 Mon Sep 17 00:00:00 2001 From: Mikael Pettersson Date: Fri, 31 Oct 2008 08:03:55 +0100 Subject: sata_promise: add ATA engine reset to reset ops Promise ATA engines need to be reset when errors occur. That's currently done for errors detected by sata_promise itself, but it's not done for errors like timeouts detected outside of the low-level driver. The effect of this omission is that a timeout tends to result in a sequence of failed COMRESETs after which libata EH gives up and disables the port. At that point the port's ATA engine hangs and even reloading the driver will not resume it. To fix this, make sata_promise override ->hardreset on SATA ports with code which calls pdc_reset_port() on the port in question before calling libata's hardreset. PATA ports don't use ->hardreset, so for those we override ->softreset instead. Signed-off-by: Mikael Pettersson Signed-off-by: Jeff Garzik --- drivers/ata/sata_promise.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers/ata') diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c index 750d8cdc00cd..ba9a2570a742 100644 --- a/drivers/ata/sata_promise.c +++ b/drivers/ata/sata_promise.c @@ -153,6 +153,10 @@ 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 int pdc_pata_softreset(struct ata_link *link, unsigned int *class, + unsigned long deadline); +static int pdc_sata_hardreset(struct ata_link *link, unsigned int *class, + unsigned long deadline); static void pdc_error_handler(struct ata_port *ap); static void pdc_post_internal_cmd(struct ata_queued_cmd *qc); static int pdc_pata_cable_detect(struct ata_port *ap); @@ -186,6 +190,7 @@ static struct ata_port_operations pdc_sata_ops = { .scr_read = pdc_sata_scr_read, .scr_write = pdc_sata_scr_write, .port_start = pdc_sata_port_start, + .hardreset = pdc_sata_hardreset, }; /* First-generation chips need a more restrictive ->check_atapi_dma op */ @@ -200,6 +205,7 @@ static struct ata_port_operations pdc_pata_ops = { .freeze = pdc_freeze, .thaw = pdc_thaw, .port_start = pdc_common_port_start, + .softreset = pdc_pata_softreset, }; static const struct ata_port_info pdc_port_info[] = { @@ -693,6 +699,20 @@ static void pdc_sata_thaw(struct ata_port *ap) readl(host_mmio + hotplug_offset); /* flush */ } +static int pdc_pata_softreset(struct ata_link *link, unsigned int *class, + unsigned long deadline) +{ + pdc_reset_port(link->ap); + return ata_sff_softreset(link, class, deadline); +} + +static int pdc_sata_hardreset(struct ata_link *link, unsigned int *class, + unsigned long deadline) +{ + pdc_reset_port(link->ap); + return sata_sff_hardreset(link, class, deadline); +} + static void pdc_error_handler(struct ata_port *ap) { if (!(ap->pflags & ATA_PFLAG_FROZEN)) -- cgit v1.2.3 From 554d491de112a378b4d1a705bb93b58bcd444a70 Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Sun, 2 Nov 2008 22:18:52 +0100 Subject: sata_via: restore vt*_prepare_host error handling commit b9d5b89b487517cbd4cb4702da829e07ef9e4432 (sata_via: fix support for 5287) accidently (?) removed vt*_prepare_host error handling - restore it catched by gcc: drivers/ata/sata_via.c: In function 'svia_init_one': drivers/ata/sata_via.c:567: warning: 'host' may be used uninitialized in this function Signed-off-by: Marcin Slusarz Cc: Tejun Heo Cc: Joseph Chan Cc: Jeff Garzik Signed-off-by: Jeff Garzik --- drivers/ata/sata_via.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/ata') diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index 62367fe4d5dc..c18935f0bda2 100644 --- a/drivers/ata/sata_via.c +++ b/drivers/ata/sata_via.c @@ -602,8 +602,10 @@ static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) rc = vt8251_prepare_host(pdev, &host); break; default: - return -EINVAL; + rc = -EINVAL; } + if (rc) + return rc; svia_configure(pdev); -- cgit v1.2.3 From 3c324283e6cdb79210cf7975c3e40d3ba3e672b2 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 3 Nov 2008 12:37:49 +0900 Subject: sata_nv: fix generic, nf2/3 detection regression All three flavors of sata_nv's are different in how their hardreset behaves. * generic: Hardreset is not reliable. Link often doesn't come online after hardreset. * nf2/3: A little bit better - link comes online with longer debounce timing. However, nf2/3 can't reliable wait for the first D2H Register FIS, so it can't wait for device readiness or classify the device after hardreset. Follow-up SRST required. * ck804: Hardreset finally works. The core layer change to prefer hardreset and follow up changes exposed the above issues and caused various detection regressions for all three flavors. This patch, hopefully, fixes all the known issues and should make sata_nv error handling more reliable. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/sata_nv.c | 53 ++++++++++++++++++++++++--------------------------- 1 file changed, 25 insertions(+), 28 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index fae3841de0d8..6f1460614325 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -307,10 +307,10 @@ static int nv_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val); static void nv_nf2_freeze(struct ata_port *ap); static void nv_nf2_thaw(struct ata_port *ap); +static int nv_nf2_hardreset(struct ata_link *link, unsigned int *class, + unsigned long deadline); static void nv_ck804_freeze(struct ata_port *ap); static void nv_ck804_thaw(struct ata_port *ap); -static int nv_hardreset(struct ata_link *link, unsigned int *class, - unsigned long deadline); static int nv_adma_slave_config(struct scsi_device *sdev); static int nv_adma_check_atapi_dma(struct ata_queued_cmd *qc); static void nv_adma_qc_prep(struct ata_queued_cmd *qc); @@ -405,17 +405,8 @@ static struct scsi_host_template nv_swncq_sht = { .slave_configure = nv_swncq_slave_config, }; -/* OSDL bz3352 reports that some nv controllers can't determine device - * signature reliably and nv_hardreset is implemented to work around - * the problem. This was reported on nf3 and it's unclear whether any - * other controllers are affected. However, the workaround has been - * applied to all variants and there isn't much to gain by trying to - * find out exactly which ones are affected at this point especially - * because NV has moved over to ahci for newer controllers. - */ static struct ata_port_operations nv_common_ops = { .inherits = &ata_bmdma_port_ops, - .hardreset = nv_hardreset, .scr_read = nv_scr_read, .scr_write = nv_scr_write, }; @@ -429,12 +420,22 @@ static struct ata_port_operations nv_generic_ops = { .hardreset = ATA_OP_NULL, }; +/* OSDL bz3352 reports that nf2/3 controllers can't determine device + * signature reliably. Also, the following thread reports detection + * failure on cold boot with the standard debouncing timing. + * + * http://thread.gmane.org/gmane.linux.ide/34098 + * + * Debounce with hotplug timing and request follow-up SRST. + */ static struct ata_port_operations nv_nf2_ops = { .inherits = &nv_common_ops, .freeze = nv_nf2_freeze, .thaw = nv_nf2_thaw, + .hardreset = nv_nf2_hardreset, }; +/* CK804 finally gets hardreset right */ static struct ata_port_operations nv_ck804_ops = { .inherits = &nv_common_ops, .freeze = nv_ck804_freeze, @@ -443,7 +444,7 @@ static struct ata_port_operations nv_ck804_ops = { }; static struct ata_port_operations nv_adma_ops = { - .inherits = &nv_common_ops, + .inherits = &nv_ck804_ops, .check_atapi_dma = nv_adma_check_atapi_dma, .sff_tf_read = nv_adma_tf_read, @@ -467,7 +468,7 @@ static struct ata_port_operations nv_adma_ops = { }; static struct ata_port_operations nv_swncq_ops = { - .inherits = &nv_common_ops, + .inherits = &nv_generic_ops, .qc_defer = ata_std_qc_defer, .qc_prep = nv_swncq_qc_prep, @@ -1553,6 +1554,17 @@ static void nv_nf2_thaw(struct ata_port *ap) iowrite8(mask, scr_addr + NV_INT_ENABLE); } +static int nv_nf2_hardreset(struct ata_link *link, unsigned int *class, + unsigned long deadline) +{ + bool online; + int rc; + + rc = sata_link_hardreset(link, sata_deb_timing_hotplug, deadline, + &online, NULL); + return online ? -EAGAIN : rc; +} + static void nv_ck804_freeze(struct ata_port *ap) { void __iomem *mmio_base = ap->host->iomap[NV_MMIO_BAR]; @@ -1605,21 +1617,6 @@ static void nv_mcp55_thaw(struct ata_port *ap) ata_sff_thaw(ap); } -static int nv_hardreset(struct ata_link *link, unsigned int *class, - unsigned long deadline) -{ - int rc; - - /* SATA hardreset fails to retrieve proper device signature on - * some controllers. Request follow up SRST. For more info, - * see http://bugzilla.kernel.org/show_bug.cgi?id=3352 - */ - rc = sata_sff_hardreset(link, class, deadline); - if (rc) - return rc; - return -EAGAIN; -} - static void nv_adma_error_handler(struct ata_port *ap) { struct nv_adma_port_priv *pp = ap->private_data; -- cgit v1.2.3 From a464189de350b050aa8f334bd4cc53ed406e56dd Mon Sep 17 00:00:00 2001 From: Elias Oltmanns Date: Mon, 3 Nov 2008 19:01:08 +0900 Subject: libata: Fix a potential race condition in ata_scsi_park_show() Peter Moulder has pointed out that there is a slight chance that a negative value might be passed to jiffies_to_msecs() in ata_scsi_park_show(). This is fixed by saving the value of jiffies in a local variable, thus also reducing code since the volatile variable jiffies is accessed only once. Signed-off-by: Elias Oltmanns Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-scsi.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index bbb30d882f05..3fa75eac135d 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -190,7 +190,7 @@ static ssize_t ata_scsi_park_show(struct device *device, struct ata_port *ap; struct ata_link *link; struct ata_device *dev; - unsigned long flags; + unsigned long flags, now; unsigned int uninitialized_var(msecs); int rc = 0; @@ -208,10 +208,11 @@ static ssize_t ata_scsi_park_show(struct device *device, } link = dev->link; + now = jiffies; if (ap->pflags & ATA_PFLAG_EH_IN_PROGRESS && link->eh_context.unloaded_mask & (1 << dev->devno) && - time_after(dev->unpark_deadline, jiffies)) - msecs = jiffies_to_msecs(dev->unpark_deadline - jiffies); + time_after(dev->unpark_deadline, now)) + msecs = jiffies_to_msecs(dev->unpark_deadline - now); else msecs = 0; -- cgit v1.2.3 From 6a87e42e955ff27e07a77f65f8f077dc7c4171e1 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 3 Nov 2008 19:01:09 +0900 Subject: libata: implement ATA_HORKAGE_ATAPI_MOD16_DMA and apply it libata always uses PIO for ATAPI commands when the number of bytes to transfer isn't multiple of 16 but quantum DAT72 chokes on odd bytes PIO transfers. Implement a horkage to skip the mod16 check and apply it to the quantum device. This is reported by John Clark in the following thread. http://thread.gmane.org/gmane.linux.ide/34748 Signed-off-by: Tejun Heo Cc: John Clark Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/ata') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 82af7011f2dd..91b478f20557 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4024,6 +4024,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { /* Weird ATAPI devices */ { "TORiSAN DVD-ROM DRD-N216", NULL, ATA_HORKAGE_MAX_SEC_128 }, + { "QUANTUM DAT DAT72-000", NULL, ATA_HORKAGE_ATAPI_MOD16_DMA }, /* Devices we expect to fail diagnostics */ @@ -4444,7 +4445,8 @@ int atapi_check_dma(struct ata_queued_cmd *qc) /* Don't allow DMA if it isn't multiple of 16 bytes. Quite a * few ATAPI devices choke on such DMA requests. */ - if (unlikely(qc->nbytes & 15)) + if (!(qc->dev->horkage & ATA_HORKAGE_ATAPI_MOD16_DMA) && + unlikely(qc->nbytes & 15)) return 1; if (ap->ops->check_atapi_dma) -- cgit v1.2.3 From 299246f9a2a4c5c531863d72bad7ebd0de213de9 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 3 Nov 2008 19:27:07 +0900 Subject: libata: mask off DET when restoring SControl for detach libata restores SControl on detach; however, trying to restore non-zero DET can cause undeterministic behavior including PMP device going offline till power cycling. Mask off DET when restoring SControl. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/ata') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 91b478f20557..622350d9b2e3 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -5936,7 +5936,7 @@ static void ata_port_detach(struct ata_port *ap) * to us. Restore SControl and disable all existing devices. */ __ata_port_for_each_link(link, ap) { - sata_scr_write(link, SCR_CONTROL, link->saved_scontrol); + sata_scr_write(link, SCR_CONTROL, link->saved_scontrol & 0xff0); ata_link_for_each_dev(dev, link) ata_dev_disable(dev); } -- cgit v1.2.3 From 8a8bc22332ee6ea49137508467a76aa7f4367719 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 10 Nov 2008 14:48:21 +0900 Subject: libata: revert convert-to-block-tagging patches This patch reverts the following three commits which convert libata to use block layer tagging. 43a49cbdf31e812c0d8f553d433b09b421f5d52c e013e13bf605b9e6b702adffbe2853cfc60e7806 2fca5ccf97d2c28bcfce44f5b07d85e74e3cd18e Although using block layer tagging is the right direction, due to the tight coupling among tag number, data structure allocation and hardware command slot allocation, libata doesn't work correctly with the current conversion. The biggest problem is guaranteeing that tag 0 is always used for non-NCQ commands. Due to the way blk-tag is implemented and how SCSI starts and finishes requests, such guarantee can't be made. I'm not sure whether this would actually break any low level driver but it doesn't look like a good idea to break such assumption given the frailty of ATA controllers. So, for the time being, keep using the old dumb in-libata qc allocation. Signed-off-by: Tejun Heo Cc: Jens Axobe Cc: Jeff Garzik Signed-off-by: Linus Torvalds --- drivers/ata/libata-core.c | 66 ++++++++++++++++++++++++++++++++++++++++++----- drivers/ata/libata-scsi.c | 23 ++--------------- drivers/ata/libata.h | 19 ++------------ 3 files changed, 64 insertions(+), 44 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 622350d9b2e3..0cd3ad497136 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -1712,6 +1712,8 @@ unsigned ata_exec_internal_sg(struct ata_device *dev, else tag = 0; + if (test_and_set_bit(tag, &ap->qc_allocated)) + BUG(); qc = __ata_qc_from_tag(ap, tag); qc->tag = tag; @@ -4562,6 +4564,37 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words) #endif /* __BIG_ENDIAN */ } +/** + * ata_qc_new - Request an available ATA command, for queueing + * @ap: Port associated with device @dev + * @dev: Device from whom we request an available command structure + * + * LOCKING: + * None. + */ + +static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap) +{ + struct ata_queued_cmd *qc = NULL; + unsigned int i; + + /* no command while frozen */ + if (unlikely(ap->pflags & ATA_PFLAG_FROZEN)) + return NULL; + + /* the last tag is reserved for internal command. */ + for (i = 0; i < ATA_MAX_QUEUE - 1; i++) + if (!test_and_set_bit(i, &ap->qc_allocated)) { + qc = __ata_qc_from_tag(ap, i); + break; + } + + if (qc) + qc->tag = i; + + return qc; +} + /** * ata_qc_new_init - Request an available ATA command, and initialize it * @dev: Device from whom we request an available command structure @@ -4571,20 +4604,16 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words) * None. */ -struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev, int tag) +struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev) { struct ata_port *ap = dev->link->ap; struct ata_queued_cmd *qc; - if (unlikely(ap->pflags & ATA_PFLAG_FROZEN)) - return NULL; - - qc = __ata_qc_from_tag(ap, tag); + qc = ata_qc_new(ap); if (qc) { qc->scsicmd = NULL; qc->ap = ap; qc->dev = dev; - qc->tag = tag; ata_qc_reinit(qc); } @@ -4592,6 +4621,31 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev, int tag) return qc; } +/** + * ata_qc_free - free unused ata_queued_cmd + * @qc: Command to complete + * + * Designed to free unused ata_queued_cmd object + * in case something prevents using it. + * + * LOCKING: + * spin_lock_irqsave(host lock) + */ +void ata_qc_free(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + unsigned int tag; + + WARN_ON(qc == NULL); /* ata_qc_from_tag _might_ return NULL */ + + qc->flags = 0; + tag = qc->tag; + if (likely(ata_tag_valid(tag))) { + qc->tag = ATA_TAG_POISON; + clear_bit(tag, &ap->qc_allocated); + } +} + void __ata_qc_complete(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 3fa75eac135d..47c7afcb36f2 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -709,11 +709,7 @@ static struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev, { struct ata_queued_cmd *qc; - if (cmd->request->tag != -1) - qc = ata_qc_new_init(dev, cmd->request->tag); - else - qc = ata_qc_new_init(dev, 0); - + qc = ata_qc_new_init(dev); if (qc) { qc->scsicmd = cmd; qc->scsidone = done; @@ -1108,17 +1104,7 @@ static int ata_scsi_dev_config(struct scsi_device *sdev, depth = min(sdev->host->can_queue, ata_id_queue_depth(dev->id)); depth = min(ATA_MAX_QUEUE - 1, depth); - - /* - * If this device is behind a port multiplier, we have - * to share the tag map between all devices on that PMP. - * Set up the shared tag map here and we get automatic. - */ - if (dev->link->ap->pmp_link) - scsi_init_shared_tag_map(sdev->host, ATA_MAX_QUEUE - 1); - - scsi_set_tag_type(sdev, MSG_SIMPLE_TAG); - scsi_activate_tcq(sdev, depth); + scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, depth); } return 0; @@ -1958,11 +1944,6 @@ static unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf) hdr[1] |= (1 << 7); memcpy(rbuf, hdr, sizeof(hdr)); - - /* if ncq, set tags supported */ - if (ata_id_has_ncq(args->id)) - rbuf[7] |= (1 << 1); - memcpy(&rbuf[8], "ATA ", 8); ata_id_string(args->id, &rbuf[16], ATA_ID_PROD, 16); ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV, 4); diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index d3831d39bdaa..fe2839e58774 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -74,7 +74,7 @@ extern struct ata_link *ata_dev_phys_link(struct ata_device *dev); extern void ata_force_cbl(struct ata_port *ap); extern u64 ata_tf_to_lba(const struct ata_taskfile *tf); extern u64 ata_tf_to_lba48(const struct ata_taskfile *tf); -extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev, int tag); +extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev); extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev, u64 block, u32 n_block, unsigned int tf_flags, unsigned int tag); @@ -103,6 +103,7 @@ extern int ata_dev_configure(struct ata_device *dev); extern int sata_down_spd_limit(struct ata_link *link); extern int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel); extern void ata_sg_clean(struct ata_queued_cmd *qc); +extern void ata_qc_free(struct ata_queued_cmd *qc); extern void ata_qc_issue(struct ata_queued_cmd *qc); extern void __ata_qc_complete(struct ata_queued_cmd *qc); extern int atapi_check_dma(struct ata_queued_cmd *qc); @@ -118,22 +119,6 @@ extern struct ata_port *ata_port_alloc(struct ata_host *host); extern void ata_dev_enable_pm(struct ata_device *dev, enum link_pm policy); extern void ata_lpm_schedule(struct ata_port *ap, enum link_pm); -/** - * ata_qc_free - free unused ata_queued_cmd - * @qc: Command to complete - * - * Designed to free unused ata_queued_cmd object - * in case something prevents using it. - * - * LOCKING: - * spin_lock_irqsave(host lock) - */ -static inline void ata_qc_free(struct ata_queued_cmd *qc) -{ - qc->flags = 0; - qc->tag = ATA_TAG_POISON; -} - /* libata-acpi.c */ #ifdef CONFIG_ATA_ACPI extern void ata_acpi_associate_sata_port(struct ata_port *ap); -- cgit v1.2.3 From bd6b52a17b9af630c38bb4f89609be5654d71e1e Mon Sep 17 00:00:00 2001 From: Qinghuang Feng Date: Sat, 8 Nov 2008 16:32:02 +0800 Subject: [libata] pata_cs553*.c: cleanup kernel-doc No arguments named @deadline in cs5535_cable_detect() and cs5536_cable_detect(). Remove them. Signed-off-by: Qinghuang Feng Signed-off-by: Jeff Garzik --- drivers/ata/pata_cs5535.c | 1 - drivers/ata/pata_cs5536.c | 1 - 2 files changed, 2 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/pata_cs5535.c b/drivers/ata/pata_cs5535.c index 1b2d4a0f5f74..8b236af84c2e 100644 --- a/drivers/ata/pata_cs5535.c +++ b/drivers/ata/pata_cs5535.c @@ -72,7 +72,6 @@ /** * cs5535_cable_detect - detect cable type * @ap: Port to detect on - * @deadline: deadline jiffies for the operation * * Perform cable detection for ATA66 capable cable. Return a libata * cable type. diff --git a/drivers/ata/pata_cs5536.c b/drivers/ata/pata_cs5536.c index 73f8332cb679..afed92976198 100644 --- a/drivers/ata/pata_cs5536.c +++ b/drivers/ata/pata_cs5536.c @@ -110,7 +110,6 @@ static inline int cs5536_write(struct pci_dev *pdev, int reg, int val) /** * cs5536_cable_detect - detect cable type * @ap: Port to detect on - * @deadline: deadline jiffies for the operation * * Perform cable detection for ATA66 capable cable. Return a libata * cable type. -- cgit v1.2.3 From bc170e656881306d65eb1318c98032e1ab305ee8 Mon Sep 17 00:00:00 2001 From: Mark Salter Date: Thu, 6 Nov 2008 08:03:23 -0500 Subject: [libata] pata_sch: notice attached slave devices I posted this last month, but was prompted to do so again in bz#467457 Add capability flag to support slave devices with pata_sch driver. Signed-off-by: Mark Salter Signed-off-by: Jeff Garzik --- drivers/ata/pata_sch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/ata') diff --git a/drivers/ata/pata_sch.c b/drivers/ata/pata_sch.c index c8cc027789fe..6aeeeeb34124 100644 --- a/drivers/ata/pata_sch.c +++ b/drivers/ata/pata_sch.c @@ -83,7 +83,7 @@ static struct ata_port_operations sch_pata_ops = { }; static struct ata_port_info sch_port_info = { - .flags = 0, + .flags = ATA_FLAG_SLAVE_POSS, .pio_mask = ATA_PIO4, /* pio0-4 */ .mwdma_mask = ATA_MWDMA2, /* mwdma0-2 */ .udma_mask = ATA_UDMA5, /* udma0-5 */ -- cgit v1.2.3 From a12d6c9a09c644cb4a35be099eb5124d38e4feb8 Mon Sep 17 00:00:00 2001 From: Marc Pignat Date: Thu, 6 Nov 2008 11:44:34 +0100 Subject: [libata] pata_pcmcia: another memory card support Support for Apacer photo steno pro card. Signed-off-by: Marc Pignat Signed-off-by: Jeff Garzik --- drivers/ata/pata_pcmcia.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/ata') diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c index 271cb64d429e..64b2e2281ee7 100644 --- a/drivers/ata/pata_pcmcia.c +++ b/drivers/ata/pata_pcmcia.c @@ -416,6 +416,7 @@ static struct pcmcia_device_id pcmcia_devices[] = { PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209), PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e), PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6), + PCMCIA_DEVICE_PROD_ID2("Flash Card", 0x5a362506), PCMCIA_DEVICE_NULL, }; -- cgit v1.2.3 From 44901a96847b9967c057832b185e2f34ee6a14e5 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Tue, 4 Nov 2008 10:34:48 -0800 Subject: libata: Avoid overflow in ata_tf_read_block() when tf->hba_lbal > 127 Phillip O'Donnell pointed out that the same sign extension bug that was fixed in commit ba14a9c2 ("libata: Avoid overflow in ata_tf_to_lba48() when tf->hba_lbal > 127") also appears to exist in ata_tf_read_block(). Fix this by adding a cast to u64. Signed-off-by: Roland Dreier Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/ata') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 0cd3ad497136..4214bfb13bbd 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -612,7 +612,7 @@ u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev) if (tf->flags & ATA_TFLAG_LBA48) { block |= (u64)tf->hob_lbah << 40; block |= (u64)tf->hob_lbam << 32; - block |= tf->hob_lbal << 24; + block |= (u64)tf->hob_lbal << 24; } else block |= (tf->device & 0xf) << 24; -- cgit v1.2.3 From 19b723218bde79c60a394a3caee9eb156ac2d356 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 4 Nov 2008 17:08:40 +0900 Subject: libata: fix last_reset timestamp handling ehc->last_reset is used to ensure that resets are not issued too close to each other. It's initialized to jiffies minus one minute on EH entry. However, when new links are initialized after PMP is probed, new links have zero for this timestamp resulting in long wait depending on the current jiffies. This patch makes last_set considered iff ATA_EHI_DID_RESET is set, in which case last_reset is always initialized. As an added precaution, WARN_ON() is added so that warning is printed if last_reset is in future. This problem is spotted and debugged by Shane Huang. Signed-off-by: Tejun Heo Cc: Shane Huang Signed-off-by: Jeff Garzik --- drivers/ata/libata-eh.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 8077bdf5d30d..32da9a93ce44 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -610,9 +610,6 @@ void ata_scsi_error(struct Scsi_Host *host) if (ata_ncq_enabled(dev)) ehc->saved_ncq_enabled |= 1 << devno; } - - /* set last reset timestamp to some time in the past */ - ehc->last_reset = jiffies - 60 * HZ; } ap->pflags |= ATA_PFLAG_EH_IN_PROGRESS; @@ -2281,17 +2278,21 @@ int ata_eh_reset(struct ata_link *link, int classify, if (link->flags & ATA_LFLAG_NO_SRST) softreset = NULL; - now = jiffies; - deadline = ata_deadline(ehc->last_reset, ATA_EH_RESET_COOL_DOWN); - if (time_before(now, deadline)) - schedule_timeout_uninterruptible(deadline - now); + /* make sure each reset attemp is at least COOL_DOWN apart */ + if (ehc->i.flags & ATA_EHI_DID_RESET) { + now = jiffies; + WARN_ON(time_after(ehc->last_reset, now)); + deadline = ata_deadline(ehc->last_reset, + ATA_EH_RESET_COOL_DOWN); + if (time_before(now, deadline)) + schedule_timeout_uninterruptible(deadline - now); + } spin_lock_irqsave(ap->lock, flags); ap->pflags |= ATA_PFLAG_RESETTING; spin_unlock_irqrestore(ap->lock, flags); ata_eh_about_to_do(link, NULL, ATA_EH_RESET); - ehc->last_reset = jiffies; ata_link_for_each_dev(dev, link) { /* If we issue an SRST then an ATA drive (not ATAPI) @@ -2379,7 +2380,6 @@ int ata_eh_reset(struct ata_link *link, int classify, /* * Perform reset */ - ehc->last_reset = jiffies; if (ata_is_host_link(link)) ata_eh_freeze_port(ap); @@ -2391,6 +2391,7 @@ int ata_eh_reset(struct ata_link *link, int classify, reset == softreset ? "soft" : "hard"); /* mark that this EH session started with reset */ + ehc->last_reset = jiffies; if (reset == hardreset) ehc->i.flags |= ATA_EHI_DID_HARDRESET; else @@ -2535,7 +2536,7 @@ int ata_eh_reset(struct ata_link *link, int classify, ata_eh_done(link, NULL, ATA_EH_RESET); if (slave) ata_eh_done(slave, NULL, ATA_EH_RESET); - ehc->last_reset = jiffies; + ehc->last_reset = jiffies; /* update to completion time */ ehc->i.action |= ATA_EH_REVALIDATE; rc = 0; -- cgit v1.2.3 From 6a6b97d360702b98c02c7fca4c4e088dcf3a2985 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 13 Nov 2008 10:04:46 +0900 Subject: libata: improve phantom device detection Currently libata uses four methods to detect device presence. 1. PHY status if available. 2. TF register R/W test (only promotes presence, never demotes) 3. device signature after reset 4. IDENTIFY failure detection in SFF state machine Combination of the above works well in most cases but recently there have been a few reports where a phantom device causes unnecessary delay during probe. In both cases, PHY status wasn't available. In one case, it passed #2 and #3 and failed IDENTIFY with ATA_ERR which didn't qualify as #4. The other failed #2 but as it passed #3 and #4, it still caused failure. In both cases, phantom device reported diagnostic failure, so these cases can be safely worked around by considering any !ATA_DRQ IDENTIFY failure as NODEV_HINT if diagnostic failure is set. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-sff.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 4b4739486327..9033d164c4ec 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -1227,10 +1227,19 @@ fsm_start: /* ATA PIO protocol */ if (unlikely((status & ATA_DRQ) == 0)) { /* handle BSY=0, DRQ=0 as error */ - if (likely(status & (ATA_ERR | ATA_DF))) + if (likely(status & (ATA_ERR | ATA_DF))) { /* device stops HSM for abort/error */ qc->err_mask |= AC_ERR_DEV; - else { + + /* If diagnostic failed and this is + * IDENTIFY, it's likely a phantom + * device. Mark hint. + */ + if (qc->dev->horkage & + ATA_HORKAGE_DIAGNOSTIC) + qc->err_mask |= + AC_ERR_NODEV_HINT; + } else { /* HSM violation. Let EH handle this. * Phantom devices also trigger this * condition. Mark hint. -- cgit v1.2.3