diff options
Diffstat (limited to 'drivers/ata/sata_nv.c')
-rw-r--r-- | drivers/ata/sata_nv.c | 43 |
1 files changed, 30 insertions, 13 deletions
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index 858f70610ed..fae3841de0d 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -302,8 +302,8 @@ static void nv_ck804_host_stop(struct ata_host *host); static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance); static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance); static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance); -static int nv_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val); -static int nv_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val); +static int nv_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); +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); @@ -405,28 +405,45 @@ static struct scsi_host_template nv_swncq_sht = { .slave_configure = nv_swncq_slave_config, }; -static struct ata_port_operations nv_generic_ops = { +/* 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, }; +/* OSDL bz11195 reports that link doesn't come online after hardreset + * on generic nv's and there have been several other similar reports + * on linux-ide. Disable hardreset for generic nv's. + */ +static struct ata_port_operations nv_generic_ops = { + .inherits = &nv_common_ops, + .hardreset = ATA_OP_NULL, +}; + static struct ata_port_operations nv_nf2_ops = { - .inherits = &nv_generic_ops, + .inherits = &nv_common_ops, .freeze = nv_nf2_freeze, .thaw = nv_nf2_thaw, }; static struct ata_port_operations nv_ck804_ops = { - .inherits = &nv_generic_ops, + .inherits = &nv_common_ops, .freeze = nv_ck804_freeze, .thaw = nv_ck804_thaw, .host_stop = nv_ck804_host_stop, }; static struct ata_port_operations nv_adma_ops = { - .inherits = &nv_generic_ops, + .inherits = &nv_common_ops, .check_atapi_dma = nv_adma_check_atapi_dma, .sff_tf_read = nv_adma_tf_read, @@ -450,7 +467,7 @@ static struct ata_port_operations nv_adma_ops = { }; static struct ata_port_operations nv_swncq_ops = { - .inherits = &nv_generic_ops, + .inherits = &nv_common_ops, .qc_defer = ata_std_qc_defer, .qc_prep = nv_swncq_qc_prep, @@ -1494,21 +1511,21 @@ static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance) return ret; } -static int nv_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val) +static int nv_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val) { if (sc_reg > SCR_CONTROL) return -EINVAL; - *val = ioread32(ap->ioaddr.scr_addr + (sc_reg * 4)); + *val = ioread32(link->ap->ioaddr.scr_addr + (sc_reg * 4)); return 0; } -static int nv_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val) +static int nv_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val) { if (sc_reg > SCR_CONTROL) return -EINVAL; - iowrite32(val, ap->ioaddr.scr_addr + (sc_reg * 4)); + iowrite32(val, link->ap->ioaddr.scr_addr + (sc_reg * 4)); return 0; } @@ -2201,9 +2218,9 @@ static void nv_swncq_host_interrupt(struct ata_port *ap, u16 fis) if (!pp->qc_active) return; - if (ap->ops->scr_read(ap, SCR_ERROR, &serror)) + if (ap->ops->scr_read(&ap->link, SCR_ERROR, &serror)) return; - ap->ops->scr_write(ap, SCR_ERROR, serror); + ap->ops->scr_write(&ap->link, SCR_ERROR, serror); if (ata_stat & ATA_ERR) { ata_ehi_clear_desc(ehi); |