X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fata%2Fsata_nv.c;h=858f70610edaa8370a6b79b2367147cf3d69dba9;hb=5eb81e808de6f49af1dd74db68876a79da1314a5;hp=240a8920d0bda4384090bcea86a7ffdfc763c459;hpb=a52cefc80fc92981592c688d1c8067442afe4cec;p=linux-2.6-omap-h63xx.git diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index 240a8920d0b..858f70610ed 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -163,7 +163,7 @@ enum { NV_ADMA_STAT_STOPPED = (1 << 10), NV_ADMA_STAT_DONE = (1 << 12), NV_ADMA_STAT_ERR = NV_ADMA_STAT_CPBERR | - NV_ADMA_STAT_TIMEOUT, + NV_ADMA_STAT_TIMEOUT, /* port flags */ NV_ADMA_PORT_REGISTER_MODE = (1 << 0), @@ -228,7 +228,7 @@ struct nv_adma_cpb { u8 reserved1; /* 1 */ u8 ctl_flags; /* 2 */ /* len is length of taskfile in 64 bit words */ - u8 len; /* 3 */ + u8 len; /* 3 */ u8 tag; /* 4 */ u8 next_cpb_idx; /* 5 */ __le16 reserved2; /* 6-7 */ @@ -244,9 +244,10 @@ struct nv_adma_port_priv { dma_addr_t cpb_dma; struct nv_adma_prd *aprd; dma_addr_t aprd_dma; - void __iomem * ctl_block; - void __iomem * gen_block; - void __iomem * notifier_clear_block; + void __iomem *ctl_block; + void __iomem *gen_block; + void __iomem *notifier_clear_block; + u64 adma_dma_mask; u8 flags; int last_issue_ncq; }; @@ -291,9 +292,9 @@ struct nv_swncq_port_priv { }; -#define NV_ADMA_CHECK_INTR(GCTL, PORT) ((GCTL) & ( 1 << (19 + (12 * (PORT))))) +#define NV_ADMA_CHECK_INTR(GCTL, PORT) ((GCTL) & (1 << (19 + (12 * (PORT))))) -static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); +static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); #ifdef CONFIG_PM static int nv_pci_device_resume(struct pci_dev *pdev); #endif @@ -301,14 +302,15 @@ 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_port *ap, unsigned int sc_reg, u32 *val); +static int nv_scr_write(struct ata_port *ap, 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 void nv_ck804_freeze(struct ata_port *ap); static void nv_ck804_thaw(struct ata_port *ap); -static void nv_error_handler(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); @@ -365,9 +367,9 @@ static const struct pci_device_id nv_pci_tbl[] = { { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2), SWNCQ }, { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA), SWNCQ }, { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2), SWNCQ }, - { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA), SWNCQ }, - { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2), SWNCQ }, - { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3), SWNCQ }, + { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA), GENERIC }, + { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2), GENERIC }, + { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3), GENERIC }, { } /* terminate list */ }; @@ -384,157 +386,60 @@ static struct pci_driver nv_pci_driver = { }; static struct scsi_host_template nv_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .slave_destroy = ata_scsi_slave_destroy, - .bios_param = ata_std_bios_param, + ATA_BMDMA_SHT(DRV_NAME), }; static struct scsi_host_template nv_adma_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .change_queue_depth = ata_scsi_change_queue_depth, + ATA_NCQ_SHT(DRV_NAME), .can_queue = NV_ADMA_MAX_CPBS, - .this_id = ATA_SHT_THIS_ID, .sg_tablesize = NV_ADMA_SGTBL_TOTAL_LEN, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, .dma_boundary = NV_ADMA_DMA_BOUNDARY, .slave_configure = nv_adma_slave_config, - .slave_destroy = ata_scsi_slave_destroy, - .bios_param = ata_std_bios_param, }; static struct scsi_host_template nv_swncq_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .change_queue_depth = ata_scsi_change_queue_depth, + ATA_NCQ_SHT(DRV_NAME), .can_queue = ATA_MAX_QUEUE, - .this_id = ATA_SHT_THIS_ID, .sg_tablesize = LIBATA_MAX_PRD, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = nv_swncq_slave_config, - .slave_destroy = ata_scsi_slave_destroy, - .bios_param = ata_std_bios_param, }; -static const struct ata_port_operations nv_generic_ops = { - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .exec_command = ata_exec_command, - .check_status = ata_check_status, - .dev_select = ata_std_dev_select, - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = nv_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - .data_xfer = ata_data_xfer, - .irq_clear = ata_bmdma_irq_clear, - .irq_on = ata_irq_on, +static struct ata_port_operations nv_generic_ops = { + .inherits = &ata_bmdma_port_ops, + .hardreset = nv_hardreset, .scr_read = nv_scr_read, .scr_write = nv_scr_write, - .port_start = ata_port_start, }; -static const struct ata_port_operations nv_nf2_ops = { - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .exec_command = ata_exec_command, - .check_status = ata_check_status, - .dev_select = ata_std_dev_select, - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, +static struct ata_port_operations nv_nf2_ops = { + .inherits = &nv_generic_ops, .freeze = nv_nf2_freeze, .thaw = nv_nf2_thaw, - .error_handler = nv_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - .data_xfer = ata_data_xfer, - .irq_clear = ata_bmdma_irq_clear, - .irq_on = ata_irq_on, - .scr_read = nv_scr_read, - .scr_write = nv_scr_write, - .port_start = ata_port_start, }; -static const struct ata_port_operations nv_ck804_ops = { - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .exec_command = ata_exec_command, - .check_status = ata_check_status, - .dev_select = ata_std_dev_select, - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, +static struct ata_port_operations nv_ck804_ops = { + .inherits = &nv_generic_ops, .freeze = nv_ck804_freeze, .thaw = nv_ck804_thaw, - .error_handler = nv_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - .data_xfer = ata_data_xfer, - .irq_clear = ata_bmdma_irq_clear, - .irq_on = ata_irq_on, - .scr_read = nv_scr_read, - .scr_write = nv_scr_write, - .port_start = ata_port_start, .host_stop = nv_ck804_host_stop, }; -static const struct ata_port_operations nv_adma_ops = { - .tf_load = ata_tf_load, - .tf_read = nv_adma_tf_read, +static struct ata_port_operations nv_adma_ops = { + .inherits = &nv_generic_ops, + .check_atapi_dma = nv_adma_check_atapi_dma, - .exec_command = ata_exec_command, - .check_status = ata_check_status, - .dev_select = ata_std_dev_select, - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, + .sff_tf_read = nv_adma_tf_read, .qc_defer = ata_std_qc_defer, .qc_prep = nv_adma_qc_prep, .qc_issue = nv_adma_qc_issue, + .sff_irq_clear = nv_adma_irq_clear, + .freeze = nv_adma_freeze, .thaw = nv_adma_thaw, .error_handler = nv_adma_error_handler, .post_internal_cmd = nv_adma_post_internal_cmd, - .data_xfer = ata_data_xfer, - .irq_clear = nv_adma_irq_clear, - .irq_on = ata_irq_on, - .scr_read = nv_scr_read, - .scr_write = nv_scr_write, + .port_start = nv_adma_port_start, .port_stop = nv_adma_port_stop, #ifdef CONFIG_PM @@ -544,28 +449,17 @@ static const struct ata_port_operations nv_adma_ops = { .host_stop = nv_adma_host_stop, }; -static const struct ata_port_operations nv_swncq_ops = { - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .exec_command = ata_exec_command, - .check_status = ata_check_status, - .dev_select = ata_std_dev_select, - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, +static struct ata_port_operations nv_swncq_ops = { + .inherits = &nv_generic_ops, + .qc_defer = ata_std_qc_defer, .qc_prep = nv_swncq_qc_prep, .qc_issue = nv_swncq_qc_issue, + .freeze = nv_mcp55_freeze, .thaw = nv_mcp55_thaw, .error_handler = nv_swncq_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - .data_xfer = ata_data_xfer, - .irq_clear = ata_bmdma_irq_clear, - .irq_on = ata_irq_on, - .scr_read = nv_scr_read, - .scr_write = nv_scr_write, + #ifdef CONFIG_PM .port_suspend = nv_swncq_port_suspend, .port_resume = nv_swncq_port_resume, @@ -573,63 +467,61 @@ static const struct ata_port_operations nv_swncq_ops = { .port_start = nv_swncq_port_start, }; +struct nv_pi_priv { + irq_handler_t irq_handler; + struct scsi_host_template *sht; +}; + +#define NV_PI_PRIV(_irq_handler, _sht) \ + &(struct nv_pi_priv){ .irq_handler = _irq_handler, .sht = _sht } + static const struct ata_port_info nv_port_info[] = { /* generic */ { - .sht = &nv_sht, .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, - .link_flags = ATA_LFLAG_HRST_TO_RESUME, .pio_mask = NV_PIO_MASK, .mwdma_mask = NV_MWDMA_MASK, .udma_mask = NV_UDMA_MASK, .port_ops = &nv_generic_ops, - .irq_handler = nv_generic_interrupt, + .private_data = NV_PI_PRIV(nv_generic_interrupt, &nv_sht), }, /* nforce2/3 */ { - .sht = &nv_sht, .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, - .link_flags = ATA_LFLAG_HRST_TO_RESUME, .pio_mask = NV_PIO_MASK, .mwdma_mask = NV_MWDMA_MASK, .udma_mask = NV_UDMA_MASK, .port_ops = &nv_nf2_ops, - .irq_handler = nv_nf2_interrupt, + .private_data = NV_PI_PRIV(nv_nf2_interrupt, &nv_sht), }, /* ck804 */ { - .sht = &nv_sht, .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, - .link_flags = ATA_LFLAG_HRST_TO_RESUME, .pio_mask = NV_PIO_MASK, .mwdma_mask = NV_MWDMA_MASK, .udma_mask = NV_UDMA_MASK, .port_ops = &nv_ck804_ops, - .irq_handler = nv_ck804_interrupt, + .private_data = NV_PI_PRIV(nv_ck804_interrupt, &nv_sht), }, /* ADMA */ { - .sht = &nv_adma_sht, .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | ATA_FLAG_NCQ, - .link_flags = ATA_LFLAG_HRST_TO_RESUME, .pio_mask = NV_PIO_MASK, .mwdma_mask = NV_MWDMA_MASK, .udma_mask = NV_UDMA_MASK, .port_ops = &nv_adma_ops, - .irq_handler = nv_adma_interrupt, + .private_data = NV_PI_PRIV(nv_adma_interrupt, &nv_adma_sht), }, /* SWNCQ */ { - .sht = &nv_swncq_sht, .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_NCQ, - .link_flags = ATA_LFLAG_HRST_TO_RESUME, .pio_mask = NV_PIO_MASK, .mwdma_mask = NV_MWDMA_MASK, .udma_mask = NV_UDMA_MASK, .port_ops = &nv_swncq_ops, - .irq_handler = nv_swncq_interrupt, + .private_data = NV_PI_PRIV(nv_swncq_interrupt, &nv_swncq_sht), }, }; @@ -639,8 +531,8 @@ MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, nv_pci_tbl); MODULE_VERSION(DRV_VERSION); -static int adma_enabled = 1; -static int swncq_enabled; +static int adma_enabled; +static int swncq_enabled = 1; static void nv_adma_register_mode(struct ata_port *ap) { @@ -653,12 +545,12 @@ static void nv_adma_register_mode(struct ata_port *ap) return; status = readw(mmio + NV_ADMA_STAT); - while(!(status & NV_ADMA_STAT_IDLE) && count < 20) { + while (!(status & NV_ADMA_STAT_IDLE) && count < 20) { ndelay(50); status = readw(mmio + NV_ADMA_STAT); count++; } - if(count == 20) + if (count == 20) ata_port_printk(ap, KERN_WARNING, "timeout waiting for ADMA IDLE, stat=0x%hx\n", status); @@ -668,12 +560,12 @@ static void nv_adma_register_mode(struct ata_port *ap) count = 0; status = readw(mmio + NV_ADMA_STAT); - while(!(status & NV_ADMA_STAT_LEGACY) && count < 20) { + while (!(status & NV_ADMA_STAT_LEGACY) && count < 20) { ndelay(50); status = readw(mmio + NV_ADMA_STAT); count++; } - if(count == 20) + if (count == 20) ata_port_printk(ap, KERN_WARNING, "timeout waiting for ADMA LEGACY, stat=0x%hx\n", status); @@ -697,13 +589,13 @@ static void nv_adma_mode(struct ata_port *ap) writew(tmp | NV_ADMA_CTL_GO, mmio + NV_ADMA_CTL); status = readw(mmio + NV_ADMA_STAT); - while(((status & NV_ADMA_STAT_LEGACY) || + while (((status & NV_ADMA_STAT_LEGACY) || !(status & NV_ADMA_STAT_IDLE)) && count < 20) { ndelay(50); status = readw(mmio + NV_ADMA_STAT); count++; } - if(count == 20) + if (count == 20) ata_port_printk(ap, KERN_WARNING, "timeout waiting for ADMA LEGACY clear and IDLE, stat=0x%hx\n", status); @@ -715,9 +607,10 @@ static int nv_adma_slave_config(struct scsi_device *sdev) { struct ata_port *ap = ata_shost_to_port(sdev->host); struct nv_adma_port_priv *pp = ap->private_data; + struct nv_adma_port_priv *port0, *port1; + struct scsi_device *sdev0, *sdev1; struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u64 bounce_limit; - unsigned long segment_boundary; + unsigned long segment_boundary, flags; unsigned short sg_tablesize; int rc; int adma_enable; @@ -729,6 +622,8 @@ static int nv_adma_slave_config(struct scsi_device *sdev) /* Not a proper libata device, ignore */ return rc; + spin_lock_irqsave(ap->lock, flags); + if (ap->link.device[sdev->id].class == ATA_DEV_ATAPI) { /* * NVIDIA reports that ADMA mode does not support ATAPI commands. @@ -737,7 +632,6 @@ static int nv_adma_slave_config(struct scsi_device *sdev) * Restrict DMA parameters as required by the legacy interface * when an ATAPI device is connected. */ - bounce_limit = ATA_DMA_MASK; segment_boundary = ATA_DMA_BOUNDARY; /* Subtract 1 since an extra entry may be needed for padding, see libata-scsi.c */ @@ -747,9 +641,7 @@ static int nv_adma_slave_config(struct scsi_device *sdev) on the port. */ adma_enable = 0; nv_adma_register_mode(ap); - } - else { - bounce_limit = *ap->dev->dma_mask; + } else { segment_boundary = NV_ADMA_DMA_BOUNDARY; sg_tablesize = NV_ADMA_SGTBL_TOTAL_LEN; adma_enable = 1; @@ -757,31 +649,67 @@ static int nv_adma_slave_config(struct scsi_device *sdev) pci_read_config_dword(pdev, NV_MCP_SATA_CFG_20, ¤t_reg); - if(ap->port_no == 1) + if (ap->port_no == 1) config_mask = NV_MCP_SATA_CFG_20_PORT1_EN | NV_MCP_SATA_CFG_20_PORT1_PWB_EN; else config_mask = NV_MCP_SATA_CFG_20_PORT0_EN | NV_MCP_SATA_CFG_20_PORT0_PWB_EN; - if(adma_enable) { + if (adma_enable) { new_reg = current_reg | config_mask; pp->flags &= ~NV_ADMA_ATAPI_SETUP_COMPLETE; - } - else { + } else { new_reg = current_reg & ~config_mask; pp->flags |= NV_ADMA_ATAPI_SETUP_COMPLETE; } - if(current_reg != new_reg) + if (current_reg != new_reg) pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, new_reg); - blk_queue_bounce_limit(sdev->request_queue, bounce_limit); + port0 = ap->host->ports[0]->private_data; + port1 = ap->host->ports[1]->private_data; + sdev0 = ap->host->ports[0]->link.device[0].sdev; + sdev1 = ap->host->ports[1]->link.device[0].sdev; + if ((port0->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) || + (port1->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)) { + /** We have to set the DMA mask to 32-bit if either port is in + ATAPI mode, since they are on the same PCI device which is + used for DMA mapping. If we set the mask we also need to set + the bounce limit on both ports to ensure that the block + layer doesn't feed addresses that cause DMA mapping to + choke. If either SCSI device is not allocated yet, it's OK + since that port will discover its correct setting when it + does get allocated. + Note: Setting 32-bit mask should not fail. */ + if (sdev0) + blk_queue_bounce_limit(sdev0->request_queue, + ATA_DMA_MASK); + if (sdev1) + blk_queue_bounce_limit(sdev1->request_queue, + ATA_DMA_MASK); + + pci_set_dma_mask(pdev, ATA_DMA_MASK); + } else { + /** This shouldn't fail as it was set to this value before */ + pci_set_dma_mask(pdev, pp->adma_dma_mask); + if (sdev0) + blk_queue_bounce_limit(sdev0->request_queue, + pp->adma_dma_mask); + if (sdev1) + blk_queue_bounce_limit(sdev1->request_queue, + pp->adma_dma_mask); + } + blk_queue_segment_boundary(sdev->request_queue, segment_boundary); blk_queue_max_hw_segments(sdev->request_queue, sg_tablesize); ata_port_printk(ap, KERN_INFO, - "bounce limit 0x%llX, segment boundary 0x%lX, hw segs %hu\n", - (unsigned long long)bounce_limit, segment_boundary, sg_tablesize); + "DMA mask 0x%llX, segment boundary 0x%lX, hw segs %hu\n", + (unsigned long long)*ap->host->dev->dma_mask, + segment_boundary, sg_tablesize); + + spin_unlock_irqrestore(ap->lock, flags); + return rc; } @@ -793,21 +721,23 @@ static int nv_adma_check_atapi_dma(struct ata_queued_cmd *qc) static void nv_adma_tf_read(struct ata_port *ap, struct ata_taskfile *tf) { - /* Since commands where a result TF is requested are not - executed in ADMA mode, the only time this function will be called - in ADMA mode will be if a command fails. In this case we - don't care about going into register mode with ADMA commands - pending, as the commands will all shortly be aborted anyway. */ + /* Other than when internal or pass-through commands are executed, + the only time this function will be called in ADMA mode will be + if a command fails. In the failure case we don't care about going + into register mode with ADMA commands pending, as the commands will + all shortly be aborted anyway. We assume that NCQ commands are not + issued via passthrough, which is the only way that switching into + ADMA mode could abort outstanding commands. */ nv_adma_register_mode(ap); - ata_tf_read(ap, tf); + ata_sff_tf_read(ap, tf); } static unsigned int nv_adma_tf_to_cpb(struct ata_taskfile *tf, __le16 *cpb) { unsigned int idx = 0; - if(tf->flags & ATA_TFLAG_ISADDR) { + if (tf->flags & ATA_TFLAG_ISADDR) { if (tf->flags & ATA_TFLAG_LBA48) { cpb[idx++] = cpu_to_le16((ATA_REG_ERR << 8) | tf->hob_feature | WNB); cpb[idx++] = cpu_to_le16((ATA_REG_NSECT << 8) | tf->hob_nsect); @@ -824,12 +754,12 @@ static unsigned int nv_adma_tf_to_cpb(struct ata_taskfile *tf, __le16 *cpb) cpb[idx++] = cpu_to_le16((ATA_REG_LBAH << 8) | tf->lbah); } - if(tf->flags & ATA_TFLAG_DEVICE) + if (tf->flags & ATA_TFLAG_DEVICE) cpb[idx++] = cpu_to_le16((ATA_REG_DEVICE << 8) | tf->device); cpb[idx++] = cpu_to_le16((ATA_REG_CMD << 8) | tf->command | CMDEND); - while(idx < 12) + while (idx < 12) cpb[idx++] = cpu_to_le16(IGN); return idx; @@ -850,7 +780,7 @@ static int nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err) int freeze = 0; ata_ehi_clear_desc(ehi); - __ata_ehi_push_desc(ehi, "CPB resp_flags 0x%x: ", flags ); + __ata_ehi_push_desc(ehi, "CPB resp_flags 0x%x: ", flags); if (flags & NV_CPB_RESP_ATA_ERR) { ata_ehi_push_desc(ehi, "ATA error"); ehi->err_mask |= AC_ERR_DEV; @@ -879,17 +809,18 @@ static int nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err) struct ata_queued_cmd *qc = ata_qc_from_tag(ap, cpb_num); VPRINTK("CPB flags done, flags=0x%x\n", flags); if (likely(qc)) { - DPRINTK("Completing qc from tag %d\n",cpb_num); + DPRINTK("Completing qc from tag %d\n", cpb_num); ata_qc_complete(qc); } else { struct ata_eh_info *ehi = &ap->link.eh_info; /* Notifier bits set without a command may indicate the drive is misbehaving. Raise host state machine violation on this condition. */ - ata_port_printk(ap, KERN_ERR, "notifier for tag %d with no command?\n", - cpb_num); + ata_port_printk(ap, KERN_ERR, + "notifier for tag %d with no cmd?\n", + cpb_num); ehi->err_mask |= AC_ERR_HSM; - ehi->action |= ATA_EH_SOFTRESET; + ehi->action |= ATA_EH_RESET; ata_port_freeze(ap); return 1; } @@ -913,12 +844,12 @@ static int nv_host_intr(struct ata_port *ap, u8 irq_stat) /* DEV interrupt w/ no active qc? */ if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) { - ata_check_status(ap); + ata_sff_check_status(ap); return 1; } /* handle interrupt */ - return ata_host_intr(ap, qc); + return ata_sff_host_intr(ap, qc); } static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance) @@ -952,7 +883,7 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance) if (pp->flags & NV_ADMA_PORT_REGISTER_MODE) { u8 irq_stat = readb(host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804) >> (NV_INT_PORT_SHIFT * i); - if(ata_tag_valid(ap->link.active_tag)) + if (ata_tag_valid(ap->link.active_tag)) /** NV_INT_DEV indication seems unreliable at times at least in ADMA mode. Force it on always when a command is active, to prevent losing interrupts. */ @@ -966,7 +897,7 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance) gen_ctl = readl(pp->gen_block + NV_ADMA_GEN_CTL); - if( !NV_ADMA_CHECK_INTR(gen_ctl, ap->port_no) && !notifier && + if (!NV_ADMA_CHECK_INTR(gen_ctl, ap->port_no) && !notifier && !notifier_error) /* Nothing to do */ continue; @@ -990,7 +921,7 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance) struct ata_eh_info *ehi = &ap->link.eh_info; ata_ehi_clear_desc(ehi); - __ata_ehi_push_desc(ehi, "ADMA status 0x%08x: ", status ); + __ata_ehi_push_desc(ehi, "ADMA status 0x%08x: ", status); if (status & NV_ADMA_STAT_TIMEOUT) { ehi->err_mask |= AC_ERR_SYSTEM; ata_ehi_push_desc(ehi, "timeout"); @@ -1010,27 +941,33 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance) } if (status & (NV_ADMA_STAT_DONE | - NV_ADMA_STAT_CPBERR)) { - u32 check_commands; + NV_ADMA_STAT_CPBERR | + NV_ADMA_STAT_CMD_COMPLETE)) { + u32 check_commands = notifier_clears[i]; int pos, error = 0; - if(ata_tag_valid(ap->link.active_tag)) - check_commands = 1 << ap->link.active_tag; - else - check_commands = ap->link.sactive; + if (status & NV_ADMA_STAT_CPBERR) { + /* Check all active commands */ + if (ata_tag_valid(ap->link.active_tag)) + check_commands = 1 << + ap->link.active_tag; + else + check_commands = ap-> + link.sactive; + } /** Check CPBs for completed commands */ while ((pos = ffs(check_commands)) && !error) { pos--; error = nv_adma_check_cpb(ap, pos, - notifier_error & (1 << pos) ); - check_commands &= ~(1 << pos ); + notifier_error & (1 << pos)); + check_commands &= ~(1 << pos); } } } } - if(notifier_clears[0] || notifier_clears[1]) { + if (notifier_clears[0] || notifier_clears[1]) { /* Note: Both notifier clear registers must be written if either is set, even if one is zero, according to NVIDIA. */ struct nv_adma_port_priv *pp = host->ports[0]->private_data; @@ -1056,14 +993,14 @@ static void nv_adma_freeze(struct ata_port *ap) return; /* clear any outstanding CK804 notifications */ - writeb( NV_INT_ALL << (ap->port_no * NV_INT_PORT_SHIFT), + writeb(NV_INT_ALL << (ap->port_no * NV_INT_PORT_SHIFT), ap->host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804); /* Disable interrupt */ tmp = readw(mmio + NV_ADMA_CTL); - writew( tmp & ~(NV_ADMA_CTL_AIEN | NV_ADMA_CTL_HOTPLUG_IEN), + writew(tmp & ~(NV_ADMA_CTL_AIEN | NV_ADMA_CTL_HOTPLUG_IEN), mmio + NV_ADMA_CTL); - readw( mmio + NV_ADMA_CTL ); /* flush posted write */ + readw(mmio + NV_ADMA_CTL); /* flush posted write */ } static void nv_adma_thaw(struct ata_port *ap) @@ -1079,9 +1016,9 @@ static void nv_adma_thaw(struct ata_port *ap) /* Enable interrupt */ tmp = readw(mmio + NV_ADMA_CTL); - writew( tmp | (NV_ADMA_CTL_AIEN | NV_ADMA_CTL_HOTPLUG_IEN), + writew(tmp | (NV_ADMA_CTL_AIEN | NV_ADMA_CTL_HOTPLUG_IEN), mmio + NV_ADMA_CTL); - readw( mmio + NV_ADMA_CTL ); /* flush posted write */ + readw(mmio + NV_ADMA_CTL); /* flush posted write */ } static void nv_adma_irq_clear(struct ata_port *ap) @@ -1091,12 +1028,12 @@ static void nv_adma_irq_clear(struct ata_port *ap) u32 notifier_clears[2]; if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) { - ata_bmdma_irq_clear(ap); + ata_sff_irq_clear(ap); return; } /* clear any outstanding CK804 notifications */ - writeb( NV_INT_ALL << (ap->port_no * NV_INT_PORT_SHIFT), + writeb(NV_INT_ALL << (ap->port_no * NV_INT_PORT_SHIFT), ap->host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804); /* clear ADMA status */ @@ -1121,8 +1058,8 @@ static void nv_adma_post_internal_cmd(struct ata_queued_cmd *qc) { struct nv_adma_port_priv *pp = qc->ap->private_data; - if(pp->flags & NV_ADMA_PORT_REGISTER_MODE) - ata_bmdma_post_internal_cmd(qc); + if (pp->flags & NV_ADMA_PORT_REGISTER_MODE) + ata_sff_post_internal_cmd(qc); } static int nv_adma_port_start(struct ata_port *ap) @@ -1133,10 +1070,20 @@ static int nv_adma_port_start(struct ata_port *ap) void *mem; dma_addr_t mem_dma; void __iomem *mmio; + struct pci_dev *pdev = to_pci_dev(dev); u16 tmp; VPRINTK("ENTER\n"); + /* Ensure DMA mask is set to 32-bit before allocating legacy PRD and + pad buffers */ + rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (rc) + return rc; + rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + if (rc) + return rc; + rc = ata_port_start(ap); if (rc) return rc; @@ -1152,6 +1099,15 @@ static int nv_adma_port_start(struct ata_port *ap) pp->notifier_clear_block = pp->gen_block + NV_ADMA_NOTIFIER_CLEAR + (4 * ap->port_no); + /* Now that the legacy PRD and padding buffer are allocated we can + safely raise the DMA mask to allocate the CPB/APRD table. + These are allowed to fail since we store the value that ends up + being used to set as the bounce limit in slave_config later if + needed. */ + pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); + pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); + pp->adma_dma_mask = *dev->dma_mask; + mem = dmam_alloc_coherent(dev, NV_ADMA_PORT_PRIV_DMA_SZ, &mem_dma, GFP_KERNEL); if (!mem) @@ -1167,7 +1123,7 @@ static int nv_adma_port_start(struct ata_port *ap) pp->cpb_dma = mem_dma; writel(mem_dma & 0xFFFFFFFF, mmio + NV_ADMA_CPB_BASE_LOW); - writel((mem_dma >> 16 ) >> 16, mmio + NV_ADMA_CPB_BASE_HIGH); + writel((mem_dma >> 16) >> 16, mmio + NV_ADMA_CPB_BASE_HIGH); mem += NV_ADMA_MAX_CPBS * NV_ADMA_CPB_SZ; mem_dma += NV_ADMA_MAX_CPBS * NV_ADMA_CPB_SZ; @@ -1191,15 +1147,15 @@ static int nv_adma_port_start(struct ata_port *ap) /* clear GO for register mode, enable interrupt */ tmp = readw(mmio + NV_ADMA_CTL); - writew( (tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN | - NV_ADMA_CTL_HOTPLUG_IEN, mmio + NV_ADMA_CTL); + writew((tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN | + NV_ADMA_CTL_HOTPLUG_IEN, mmio + NV_ADMA_CTL); tmp = readw(mmio + NV_ADMA_CTL); writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); - readw( mmio + NV_ADMA_CTL ); /* flush posted write */ + readw(mmio + NV_ADMA_CTL); /* flush posted write */ udelay(1); writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); - readw( mmio + NV_ADMA_CTL ); /* flush posted write */ + readw(mmio + NV_ADMA_CTL); /* flush posted write */ return 0; } @@ -1239,7 +1195,7 @@ static int nv_adma_port_resume(struct ata_port *ap) /* set CPB block location */ writel(pp->cpb_dma & 0xFFFFFFFF, mmio + NV_ADMA_CPB_BASE_LOW); - writel((pp->cpb_dma >> 16 ) >> 16, mmio + NV_ADMA_CPB_BASE_HIGH); + writel((pp->cpb_dma >> 16) >> 16, mmio + NV_ADMA_CPB_BASE_HIGH); /* clear any outstanding interrupt conditions */ writew(0xffff, mmio + NV_ADMA_STAT); @@ -1252,15 +1208,15 @@ static int nv_adma_port_resume(struct ata_port *ap) /* clear GO for register mode, enable interrupt */ tmp = readw(mmio + NV_ADMA_CTL); - writew( (tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN | - NV_ADMA_CTL_HOTPLUG_IEN, mmio + NV_ADMA_CTL); + writew((tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN | + NV_ADMA_CTL_HOTPLUG_IEN, mmio + NV_ADMA_CTL); tmp = readw(mmio + NV_ADMA_CTL); writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); - readw( mmio + NV_ADMA_CTL ); /* flush posted write */ + readw(mmio + NV_ADMA_CTL); /* flush posted write */ udelay(1); writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); - readw( mmio + NV_ADMA_CTL ); /* flush posted write */ + readw(mmio + NV_ADMA_CTL); /* flush posted write */ return 0; } @@ -1335,20 +1291,18 @@ static void nv_adma_fill_aprd(struct ata_queued_cmd *qc, static void nv_adma_fill_sg(struct ata_queued_cmd *qc, struct nv_adma_cpb *cpb) { struct nv_adma_port_priv *pp = qc->ap->private_data; - unsigned int idx; struct nv_adma_prd *aprd; struct scatterlist *sg; + unsigned int si; VPRINTK("ENTER\n"); - idx = 0; - - ata_for_each_sg(sg, qc) { - aprd = (idx < 5) ? &cpb->aprd[idx] : &pp->aprd[NV_ADMA_SGTBL_LEN * qc->tag + (idx-5)]; - nv_adma_fill_aprd(qc, sg, idx, aprd); - idx++; + for_each_sg(qc->sg, sg, qc->n_elem, si) { + aprd = (si < 5) ? &cpb->aprd[si] : + &pp->aprd[NV_ADMA_SGTBL_LEN * qc->tag + (si-5)]; + nv_adma_fill_aprd(qc, sg, si, aprd); } - if (idx > 5) + if (si > 5) cpb->next_aprd = cpu_to_le64(((u64)(pp->aprd_dma + NV_ADMA_SGTBL_SZ * qc->tag))); else cpb->next_aprd = cpu_to_le64(0); @@ -1359,14 +1313,12 @@ static int nv_adma_use_reg_mode(struct ata_queued_cmd *qc) struct nv_adma_port_priv *pp = qc->ap->private_data; /* ADMA engine can only be used for non-ATAPI DMA commands, - or interrupt-driven no-data commands, where a result taskfile - is not required. */ - if((pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) || - (qc->tf.flags & ATA_TFLAG_POLLING) || - (qc->flags & ATA_QCFLAG_RESULT_TF)) + or interrupt-driven no-data commands. */ + if ((pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) || + (qc->tf.flags & ATA_TFLAG_POLLING)) return 1; - if((qc->flags & ATA_QCFLAG_DMAMAP) || + if ((qc->flags & ATA_QCFLAG_DMAMAP) || (qc->tf.protocol == ATA_PROT_NODATA)) return 0; @@ -1381,8 +1333,10 @@ static void nv_adma_qc_prep(struct ata_queued_cmd *qc) NV_CPB_CTL_IEN; if (nv_adma_use_reg_mode(qc)) { + BUG_ON(!(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) && + (qc->flags & ATA_QCFLAG_DMAMAP)); nv_adma_register_mode(qc->ap); - ata_qc_prep(qc); + ata_sff_qc_prep(qc); return; } @@ -1403,14 +1357,14 @@ static void nv_adma_qc_prep(struct ata_queued_cmd *qc) nv_adma_tf_to_cpb(&qc->tf, cpb->tf); - if(qc->flags & ATA_QCFLAG_DMAMAP) { + if (qc->flags & ATA_QCFLAG_DMAMAP) { nv_adma_fill_sg(qc, cpb); ctl_flags |= NV_CPB_CTL_APRD_VALID; } else memset(&cpb->aprd[0], 0, sizeof(struct nv_adma_prd) * 5); - /* Be paranoid and don't let the device see NV_CPB_CTL_CPB_VALID until we are - finished filling in all of the contents */ + /* Be paranoid and don't let the device see NV_CPB_CTL_CPB_VALID + until we are finished filling in all of the contents */ wmb(); cpb->ctl_flags = ctl_flags; wmb(); @@ -1425,11 +1379,23 @@ static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc) VPRINTK("ENTER\n"); + /* We can't handle result taskfile with NCQ commands, since + retrieving the taskfile switches us out of ADMA mode and would abort + existing commands. */ + if (unlikely(qc->tf.protocol == ATA_PROT_NCQ && + (qc->flags & ATA_QCFLAG_RESULT_TF))) { + ata_dev_printk(qc->dev, KERN_ERR, + "NCQ w/ RESULT_TF not allowed\n"); + return AC_ERR_SYSTEM; + } + if (nv_adma_use_reg_mode(qc)) { /* use ATA register mode */ VPRINTK("using ATA register mode: 0x%lx\n", qc->flags); + BUG_ON(!(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) && + (qc->flags & ATA_QCFLAG_DMAMAP)); nv_adma_register_mode(qc->ap); - return ata_qc_issue_prot(qc); + return ata_sff_qc_issue(qc); } else nv_adma_mode(qc->ap); @@ -1437,16 +1403,16 @@ static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc) and (number of cpbs to append -1) in top 8 bits */ wmb(); - if(curr_ncq != pp->last_issue_ncq) { - /* Seems to need some delay before switching between NCQ and non-NCQ - commands, else we get command timeouts and such. */ + if (curr_ncq != pp->last_issue_ncq) { + /* Seems to need some delay before switching between NCQ and + non-NCQ commands, else we get command timeouts and such. */ udelay(20); pp->last_issue_ncq = curr_ncq; } writew(qc->tag, mmio + NV_ADMA_APPEND); - DPRINTK("Issued tag %u\n",qc->tag); + DPRINTK("Issued tag %u\n", qc->tag); return 0; } @@ -1470,11 +1436,11 @@ static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance) qc = ata_qc_from_tag(ap, ap->link.active_tag); if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) - handled += ata_host_intr(ap, qc); + handled += ata_sff_host_intr(ap, qc); else // No request pending? Clear interrupt status // anyway, in case there's one pending. - ap->ops->check_status(ap); + ap->ops->sff_check_status(ap); } } @@ -1605,7 +1571,7 @@ static void nv_mcp55_freeze(struct ata_port *ap) mask = readl(mmio_base + NV_INT_ENABLE_MCP55); mask &= ~(NV_INT_ALL_MCP55 << shift); writel(mask, mmio_base + NV_INT_ENABLE_MCP55); - ata_bmdma_freeze(ap); + ata_sff_freeze(ap); } static void nv_mcp55_thaw(struct ata_port *ap) @@ -1619,36 +1585,33 @@ static void nv_mcp55_thaw(struct ata_port *ap) mask = readl(mmio_base + NV_INT_ENABLE_MCP55); mask |= (NV_INT_MASK_MCP55 << shift); writel(mask, mmio_base + NV_INT_ENABLE_MCP55); - ata_bmdma_thaw(ap); + ata_sff_thaw(ap); } static int nv_hardreset(struct ata_link *link, unsigned int *class, unsigned long deadline) { - unsigned int dummy; + int rc; /* SATA hardreset fails to retrieve proper device signature on - * some controllers. Don't classify on hardreset. For more - * info, see http://bugme.osdl.org/show_bug.cgi?id=3352 + * some controllers. Request follow up SRST. For more info, + * see http://bugzilla.kernel.org/show_bug.cgi?id=3352 */ - return sata_std_hardreset(link, &dummy, deadline); -} - -static void nv_error_handler(struct ata_port *ap) -{ - ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, - nv_hardreset, ata_std_postreset); + 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; - if(!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) { + if (!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) { void __iomem *mmio = pp->ctl_block; int i; u16 tmp; - if(ata_tag_valid(ap->link.active_tag) || ap->link.sactive) { + if (ata_tag_valid(ap->link.active_tag) || ap->link.sactive) { u32 notifier = readl(mmio + NV_ADMA_NOTIFIER); u32 notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR); u32 gen_ctl = readl(pp->gen_block + NV_ADMA_GEN_CTL); @@ -1656,16 +1619,17 @@ static void nv_adma_error_handler(struct ata_port *ap) u8 cpb_count = readb(mmio + NV_ADMA_CPB_COUNT); u8 next_cpb_idx = readb(mmio + NV_ADMA_NEXT_CPB_IDX); - ata_port_printk(ap, KERN_ERR, "EH in ADMA mode, notifier 0x%X " + ata_port_printk(ap, KERN_ERR, + "EH in ADMA mode, notifier 0x%X " "notifier_error 0x%X gen_ctl 0x%X status 0x%X " "next cpb count 0x%X next cpb idx 0x%x\n", notifier, notifier_error, gen_ctl, status, cpb_count, next_cpb_idx); - for( i=0;icpb[i]; - if( (ata_tag_valid(ap->link.active_tag) && i == ap->link.active_tag) || - ap->link.sactive & (1 << i) ) + if ((ata_tag_valid(ap->link.active_tag) && i == ap->link.active_tag) || + ap->link.sactive & (1 << i)) ata_port_printk(ap, KERN_ERR, "CPB %d: ctl_flags 0x%x, resp_flags 0x%x\n", i, cpb->ctl_flags, cpb->resp_flags); @@ -1675,8 +1639,9 @@ static void nv_adma_error_handler(struct ata_port *ap) /* Push us back into port register mode for error handling. */ nv_adma_register_mode(ap); - /* Mark all of the CPBs as invalid to prevent them from being executed */ - for( i=0;icpb[i].ctl_flags &= ~NV_CPB_CTL_CPB_VALID; /* clear CPB fetch count */ @@ -1685,14 +1650,13 @@ static void nv_adma_error_handler(struct ata_port *ap) /* Reset channel */ tmp = readw(mmio + NV_ADMA_CTL); writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); - readw( mmio + NV_ADMA_CTL ); /* flush posted write */ + readw(mmio + NV_ADMA_CTL); /* flush posted write */ udelay(1); writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); - readw( mmio + NV_ADMA_CTL ); /* flush posted write */ + readw(mmio + NV_ADMA_CTL); /* flush posted write */ } - ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, - nv_hardreset, ata_std_postreset); + ata_sff_error_handler(ap); } static void nv_swncq_qc_to_dq(struct ata_port *ap, struct ata_queued_cmd *qc) @@ -1778,7 +1742,7 @@ static void nv_swncq_ncq_stop(struct ata_port *ap) pp->dhfis_bits, pp->dmafis_bits, pp->sdbfis_bits); ata_port_printk(ap, KERN_ERR, "ATA_REG 0x%X ERR_REG 0x%X\n", - ap->ops->check_status(ap), + ap->ops->sff_check_status(ap), ioread8(ap->ioaddr.error_addr)); sactive = readl(pp->sactive_block); @@ -1804,7 +1768,7 @@ static void nv_swncq_ncq_stop(struct ata_port *ap) } nv_swncq_pp_reinit(ap); - ap->ops->irq_clear(ap); + ap->ops->sff_irq_clear(ap); __ata_bmdma_stop(ap); nv_swncq_irq_clear(ap, 0xffff); } @@ -1815,11 +1779,10 @@ static void nv_swncq_error_handler(struct ata_port *ap) if (ap->link.sactive) { nv_swncq_ncq_stop(ap); - ehc->i.action |= ATA_EH_HARDRESET; + ehc->i.action |= ATA_EH_RESET; } - ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, - nv_hardreset, ata_std_postreset); + ata_sff_error_handler(ap); } #ifdef CONFIG_PM @@ -1965,7 +1928,7 @@ static int nv_swncq_port_start(struct ata_port *ap) static void nv_swncq_qc_prep(struct ata_queued_cmd *qc) { if (qc->tf.protocol != ATA_PROT_NCQ) { - ata_qc_prep(qc); + ata_sff_qc_prep(qc); return; } @@ -1979,17 +1942,14 @@ static void nv_swncq_fill_sg(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; struct scatterlist *sg; - unsigned int idx; struct nv_swncq_port_priv *pp = ap->private_data; struct ata_prd *prd; - - WARN_ON(qc->__sg == NULL); - WARN_ON(qc->n_elem == 0 && qc->pad_len == 0); + unsigned int si, idx; prd = pp->prd + ATA_MAX_PRD * qc->tag; idx = 0; - ata_for_each_sg(sg, qc) { + for_each_sg(qc->sg, sg, qc->n_elem, si) { u32 addr, offset; u32 sg_len, len; @@ -2011,8 +1971,7 @@ static void nv_swncq_fill_sg(struct ata_queued_cmd *qc) } } - if (idx) - prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT); + prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT); } static unsigned int nv_swncq_issue_atacmd(struct ata_port *ap, @@ -2031,8 +1990,8 @@ static unsigned int nv_swncq_issue_atacmd(struct ata_port *ap, pp->dmafis_bits &= ~(1 << qc->tag); pp->qc_active |= (0x1 << qc->tag); - ap->ops->tf_load(ap, &qc->tf); /* load tf registers */ - ap->ops->exec_command(ap, &qc->tf); + ap->ops->sff_tf_load(ap, &qc->tf); /* load tf registers */ + ap->ops->sff_exec_command(ap, &qc->tf); DPRINTK("Issued tag %u\n", qc->tag); @@ -2045,7 +2004,7 @@ static unsigned int nv_swncq_qc_issue(struct ata_queued_cmd *qc) struct nv_swncq_port_priv *pp = ap->private_data; if (qc->tf.protocol != ATA_PROT_NCQ) - return ata_qc_issue_prot(qc); + return ata_sff_qc_issue(qc); DPRINTK("Enter\n"); @@ -2100,11 +2059,11 @@ static int nv_swncq_sdbfis(struct ata_port *ap) ata_ehi_clear_desc(ehi); ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat); ehi->err_mask |= AC_ERR_HOST_BUS; - ehi->action |= ATA_EH_SOFTRESET; + ehi->action |= ATA_EH_RESET; return -EINVAL; } - ap->ops->irq_clear(ap); + ap->ops->sff_irq_clear(ap); __ata_bmdma_stop(ap); sactive = readl(pp->sactive_block); @@ -2115,7 +2074,7 @@ static int nv_swncq_sdbfis(struct ata_port *ap) ata_ehi_push_desc(ehi, "illegal SWNCQ:qc_active transition" "(%08x->%08x)", pp->qc_active, sactive); ehi->err_mask |= AC_ERR_HSM; - ehi->action |= ATA_EH_HARDRESET; + ehi->action |= ATA_EH_RESET; return -EINVAL; } for (i = 0; i < ATA_MAX_QUEUE; i++) { @@ -2226,7 +2185,7 @@ static void nv_swncq_host_interrupt(struct ata_port *ap, u16 fis) u8 ata_stat; int rc = 0; - ata_stat = ap->ops->check_status(ap); + ata_stat = ap->ops->sff_check_status(ap); nv_swncq_irq_clear(ap, fis); if (!fis) return; @@ -2251,7 +2210,7 @@ static void nv_swncq_host_interrupt(struct ata_port *ap, u16 fis) ata_ehi_push_desc(ehi, "Ata error. fis:0x%X", fis); ehi->err_mask |= AC_ERR_DEV; ehi->serror |= serror; - ehi->action |= ATA_EH_SOFTRESET; + ehi->action |= ATA_EH_RESET; ata_port_freeze(ap); return; } @@ -2283,13 +2242,13 @@ static void nv_swncq_host_interrupt(struct ata_port *ap, u16 fis) if (pp->ncq_flags & (ncq_saw_sdb | ncq_saw_backout)) { ata_ehi_push_desc(ehi, "illegal fis transaction"); ehi->err_mask |= AC_ERR_HSM; - ehi->action |= ATA_EH_HARDRESET; + ehi->action |= ATA_EH_RESET; goto irq_error; } if (!(fis & NV_SWNCQ_IRQ_DMASETUP) && !(pp->ncq_flags & ncq_saw_dmas)) { - ata_stat = ap->ops->check_status(ap); + ata_stat = ap->ops->sff_check_status(ap); if (ata_stat & ATA_BUSY) goto irq_exit; @@ -2352,10 +2311,11 @@ static irqreturn_t nv_swncq_interrupt(int irq, void *dev_instance) return IRQ_RETVAL(handled); } -static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) +static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - static int printed_version = 0; + static int printed_version; const struct ata_port_info *ppi[] = { NULL, NULL }; + struct nv_pi_priv *ipriv; struct ata_host *host; struct nv_host_priv *hpriv; int rc; @@ -2366,7 +2326,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) // Make sure this is a SATA controller by counting the number of bars // (NVIDIA SATA controllers will always have six bars). Otherwise, // it's an IDE controller and we ignore it. - for (bar=0; bar<6; bar++) + for (bar = 0; bar < 6; bar++) if (pci_resource_start(pdev, bar) == 0) return -ENODEV; @@ -2383,8 +2343,17 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) type = ADMA; } + if (type == SWNCQ) { + if (swncq_enabled) + dev_printk(KERN_NOTICE, &pdev->dev, + "Using SWNCQ mode\n"); + else + type = GENERIC; + } + ppi[0] = &nv_port_info[type]; - rc = ata_pci_prepare_sff_host(pdev, ppi, &host); + ipriv = ppi[0]->private_data; + rc = ata_pci_sff_prepare_host(pdev, ppi, &host); if (rc) return rc; @@ -2394,12 +2363,6 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) hpriv->type = type; host->private_data = hpriv; - /* set 64bit dma masks, may fail */ - if (type == ADMA) { - if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) - pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); - } - /* request and iomap NV_MMIO_BAR */ rc = pcim_iomap_regions(pdev, 1 << NV_MMIO_BAR, DRV_NAME); if (rc) @@ -2424,14 +2387,12 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) rc = nv_adma_host_init(host); if (rc) return rc; - } else if (type == SWNCQ && swncq_enabled) { - dev_printk(KERN_NOTICE, &pdev->dev, "Using SWNCQ mode\n"); + } else if (type == SWNCQ) nv_swncq_host_init(host); - } pci_set_master(pdev); - return ata_host_activate(host, pdev->irq, ppi[0]->irq_handler, - IRQF_SHARED, ppi[0]->sht); + return ata_host_activate(host, pdev->irq, ipriv->irq_handler, + IRQF_SHARED, ipriv->sht); } #ifdef CONFIG_PM @@ -2442,37 +2403,37 @@ static int nv_pci_device_resume(struct pci_dev *pdev) int rc; rc = ata_pci_device_do_resume(pdev); - if(rc) + if (rc) return rc; if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { - if(hpriv->type >= CK804) { + if (hpriv->type >= CK804) { u8 regval; pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, ®val); regval |= NV_MCP_SATA_CFG_20_SATA_SPACE_EN; pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval); } - if(hpriv->type == ADMA) { + if (hpriv->type == ADMA) { u32 tmp32; struct nv_adma_port_priv *pp; /* enable/disable ADMA on the ports appropriately */ pci_read_config_dword(pdev, NV_MCP_SATA_CFG_20, &tmp32); pp = host->ports[0]->private_data; - if(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) + if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) tmp32 &= ~(NV_MCP_SATA_CFG_20_PORT0_EN | - NV_MCP_SATA_CFG_20_PORT0_PWB_EN); + NV_MCP_SATA_CFG_20_PORT0_PWB_EN); else tmp32 |= (NV_MCP_SATA_CFG_20_PORT0_EN | - NV_MCP_SATA_CFG_20_PORT0_PWB_EN); + NV_MCP_SATA_CFG_20_PORT0_PWB_EN); pp = host->ports[1]->private_data; - if(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) + if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) tmp32 &= ~(NV_MCP_SATA_CFG_20_PORT1_EN | - NV_MCP_SATA_CFG_20_PORT1_PWB_EN); + NV_MCP_SATA_CFG_20_PORT1_PWB_EN); else tmp32 |= (NV_MCP_SATA_CFG_20_PORT1_EN | - NV_MCP_SATA_CFG_20_PORT1_PWB_EN); + NV_MCP_SATA_CFG_20_PORT1_PWB_EN); pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, tmp32); } @@ -2527,5 +2488,5 @@ module_exit(nv_exit); module_param_named(adma, adma_enabled, bool, 0444); MODULE_PARM_DESC(adma, "Enable use of ADMA (Default: true)"); module_param_named(swncq, swncq_enabled, bool, 0444); -MODULE_PARM_DESC(swncq, "Enable use of SWNCQ (Default: false)"); +MODULE_PARM_DESC(swncq, "Enable use of SWNCQ (Default: true)");