diff options
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/Kconfig | 4 | ||||
-rw-r--r-- | drivers/scsi/libata-bmdma.c | 37 | ||||
-rw-r--r-- | drivers/scsi/libata-core.c | 27 | ||||
-rw-r--r-- | drivers/scsi/libata-scsi.c | 140 | ||||
-rw-r--r-- | drivers/scsi/pdc_adma.c | 2 | ||||
-rw-r--r-- | drivers/scsi/sata_mv.c | 5 | ||||
-rw-r--r-- | drivers/scsi/sata_svw.c | 56 | ||||
-rw-r--r-- | drivers/scsi/sata_vsc.c | 124 |
8 files changed, 245 insertions, 150 deletions
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 5c94a5d..4035920 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -595,10 +595,10 @@ config SCSI_SATA_VIA If unsure, say N. config SCSI_SATA_VITESSE - tristate "VITESSE VSC-7174 SATA support" + tristate "VITESSE VSC-7174 / INTEL 31244 SATA support" depends on SCSI_SATA && PCI help - This option enables support for Vitesse VSC7174 Serial ATA. + This option enables support for Vitesse VSC7174 and Intel 31244 Serial ATA. If unsure, say N. diff --git a/drivers/scsi/libata-bmdma.c b/drivers/scsi/libata-bmdma.c index a93336ad..999725c 100644 --- a/drivers/scsi/libata-bmdma.c +++ b/drivers/scsi/libata-bmdma.c @@ -648,6 +648,7 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, goto err_out_regions; } + /* FIXME: If we get no DMA mask we should fall back to PIO */ rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); if (rc) goto err_out_regions; @@ -699,5 +700,41 @@ err_out: return rc; } +/** + * ata_pci_clear_simplex - attempt to kick device out of simplex + * @pdev: PCI device + * + * Some PCI ATA devices report simplex mode but in fact can be told to + * enter non simplex mode. This implements the neccessary logic to + * perform the task on such devices. Calling it on other devices will + * have -undefined- behaviour. + */ + +int ata_pci_clear_simplex(struct pci_dev *pdev) +{ + unsigned long bmdma = pci_resource_start(pdev, 4); + u8 simplex; + + if (bmdma == 0) + return -ENOENT; + + simplex = inb(bmdma + 0x02); + outb(simplex & 0x60, bmdma + 0x02); + simplex = inb(bmdma + 0x02); + if (simplex & 0x80) + return -EOPNOTSUPP; + return 0; +} + +unsigned long ata_pci_default_filter(const struct ata_port *ap, struct ata_device *adev, unsigned long xfer_mask) +{ + /* Filter out DMA modes if the device has been configured by + the BIOS as PIO only */ + + if (ap->ioaddr.bmdma_addr == 0) + xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); + return xfer_mask; +} + #endif /* CONFIG_PCI */ diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 64dce00..5d00bb7 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -962,6 +962,8 @@ ata_exec_internal(struct ata_port *ap, struct ata_device *dev, spin_unlock_irqrestore(&ap->host_set->lock, flags); if (!wait_for_completion_timeout(&wait, ATA_TMOUT_INTERNAL)) { + ata_port_flush_task(ap); + spin_lock_irqsave(&ap->host_set->lock, flags); /* We're racing with irq here. If we lose, the @@ -1737,7 +1739,7 @@ static int ata_host_set_pio(struct ata_port *ap) continue; if (!dev->pio_mode) { - printk(KERN_WARNING "ata%u: no PIO support\n", ap->id); + printk(KERN_WARNING "ata%u: no PIO support for device %d.\n", ap->id, i); return -1; } @@ -2863,6 +2865,8 @@ void ata_qc_prep(struct ata_queued_cmd *qc) ata_fill_sg(qc); } +void ata_noop_qc_prep(struct ata_queued_cmd *qc) { } + /** * ata_sg_init_one - Associate command with memory buffer * @qc: Command to be associated @@ -3907,7 +3911,6 @@ static inline int ata_should_dma_map(struct ata_queued_cmd *qc) case ATA_PROT_ATAPI: case ATA_PROT_PIO: - case ATA_PROT_PIO_MULT: if (ap->flags & ATA_FLAG_PIO_DMA) return 1; @@ -4199,14 +4202,17 @@ void ata_bmdma_setup(struct ata_queued_cmd *qc) void ata_bmdma_irq_clear(struct ata_port *ap) { - if (ap->flags & ATA_FLAG_MMIO) { - void __iomem *mmio = ((void __iomem *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS; - writeb(readb(mmio), mmio); - } else { - unsigned long addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS; - outb(inb(addr), addr); - } + if (!ap->ioaddr.bmdma_addr) + return; + if (ap->flags & ATA_FLAG_MMIO) { + void __iomem *mmio = + ((void __iomem *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS; + writeb(readb(mmio), mmio); + } else { + unsigned long addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS; + outb(inb(addr), addr); + } } @@ -4337,9 +4343,9 @@ idle_irq: #ifdef ATA_IRQ_TRAP if ((ap->stats.idle_irq % 1000) == 0) { - handled = 1; ata_irq_ack(ap, 0); /* debug trap */ printk(KERN_WARNING "ata%d: irq trap\n", ap->id); + return 1; } #endif return 0; /* irq not handled */ @@ -5064,6 +5070,7 @@ EXPORT_SYMBOL_GPL(ata_port_stop); EXPORT_SYMBOL_GPL(ata_host_stop); EXPORT_SYMBOL_GPL(ata_interrupt); EXPORT_SYMBOL_GPL(ata_qc_prep); +EXPORT_SYMBOL_GPL(ata_noop_qc_prep); EXPORT_SYMBOL_GPL(ata_bmdma_setup); EXPORT_SYMBOL_GPL(ata_bmdma_start); EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear); diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index bd9f217..a1259b2 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -521,13 +521,11 @@ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc, printk(KERN_WARNING "ata%u: no sense translation for status: 0x%02x\n", id, drv_stat); - /* For our last chance pick, use medium read error because - * it's much more common than an ATA drive telling you a write - * has failed. - */ - *sk = MEDIUM_ERROR; - *asc = 0x11; /* "unrecovered read error" */ - *ascq = 0x04; /* "auto-reallocation failed" */ + /* We need a sensible error return here, which is tricky, and one + that won't cause people to do things like return a disk wrongly */ + *sk = ABORTED_COMMAND; + *asc = 0x00; + *ascq = 0x00; translate_done: printk(KERN_ERR "ata%u: translated ATA stat/err 0x%02x/%02x to " @@ -672,6 +670,41 @@ void ata_gen_fixed_sense(struct ata_queued_cmd *qc) } } +static void ata_scsi_sdev_config(struct scsi_device *sdev) +{ + sdev->use_10_for_rw = 1; + sdev->use_10_for_ms = 1; +} + +static void ata_scsi_dev_config(struct scsi_device *sdev, + struct ata_device *dev) +{ + unsigned int max_sectors; + + /* TODO: 2048 is an arbitrary number, not the + * hardware maximum. This should be increased to + * 65534 when Jens Axboe's patch for dynamically + * determining max_sectors is merged. + */ + max_sectors = ATA_MAX_SECTORS; + if (dev->flags & ATA_DFLAG_LBA48) + max_sectors = 2048; + if (dev->max_sectors) + max_sectors = dev->max_sectors; + + blk_queue_max_sectors(sdev->request_queue, max_sectors); + + /* + * SATA DMA transfers must be multiples of 4 byte, so + * we need to pad ATAPI transfers using an extra sg. + * Decrement max hw segments accordingly. + */ + if (dev->class == ATA_DEV_ATAPI) { + request_queue_t *q = sdev->request_queue; + blk_queue_max_hw_segments(q, q->max_hw_segments - 1); + } +} + /** * ata_scsi_slave_config - Set SCSI device attributes * @sdev: SCSI device to examine @@ -686,41 +719,18 @@ void ata_gen_fixed_sense(struct ata_queued_cmd *qc) int ata_scsi_slave_config(struct scsi_device *sdev) { - sdev->use_10_for_rw = 1; - sdev->use_10_for_ms = 1; + ata_scsi_sdev_config(sdev); blk_queue_max_phys_segments(sdev->request_queue, LIBATA_MAX_PRD); if (sdev->id < ATA_MAX_DEVICES) { struct ata_port *ap; struct ata_device *dev; - unsigned int max_sectors; ap = (struct ata_port *) &sdev->host->hostdata[0]; dev = &ap->device[sdev->id]; - /* TODO: 2048 is an arbitrary number, not the - * hardware maximum. This should be increased to - * 65534 when Jens Axboe's patch for dynamically - * determining max_sectors is merged. - */ - max_sectors = ATA_MAX_SECTORS; - if (dev->flags & ATA_DFLAG_LBA48) - max_sectors = 2048; - if (dev->max_sectors) - max_sectors = dev->max_sectors; - - blk_queue_max_sectors(sdev->request_queue, max_sectors); - - /* - * SATA DMA transfers must be multiples of 4 byte, so - * we need to pad ATAPI transfers using an extra sg. - * Decrement max hw segments accordingly. - */ - if (dev->class == ATA_DEV_ATAPI) { - request_queue_t *q = sdev->request_queue; - blk_queue_max_hw_segments(q, q->max_hw_segments - 1); - } + ata_scsi_dev_config(sdev, dev); } return 0; /* scsi layer doesn't check return value, sigh */ @@ -1552,7 +1562,7 @@ void ata_scsi_rbuf_fill(struct ata_scsi_args *args, * @buflen: Response buffer length. * * Returns standard device identification data associated - * with non-EVPD INQUIRY command output. + * with non-VPD INQUIRY command output. * * LOCKING: * spin_lock_irqsave(host_set lock) @@ -1603,12 +1613,12 @@ unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, } /** - * ata_scsiop_inq_00 - Simulate INQUIRY EVPD page 0, list of pages + * ata_scsiop_inq_00 - Simulate INQUIRY VPD page 0, list of pages * @args: device IDENTIFY data / SCSI command of interest. * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. * @buflen: Response buffer length. * - * Returns list of inquiry EVPD pages available. + * Returns list of inquiry VPD pages available. * * LOCKING: * spin_lock_irqsave(host_set lock) @@ -1622,7 +1632,7 @@ unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf, 0x80, /* page 0x80, unit serial no page */ 0x83 /* page 0x83, device ident page */ }; - rbuf[3] = sizeof(pages); /* number of supported EVPD pages */ + rbuf[3] = sizeof(pages); /* number of supported VPD pages */ if (buflen > 6) memcpy(rbuf + 4, pages, sizeof(pages)); @@ -1631,7 +1641,7 @@ unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf, } /** - * ata_scsiop_inq_80 - Simulate INQUIRY EVPD page 80, device serial number + * ata_scsiop_inq_80 - Simulate INQUIRY VPD page 80, device serial number * @args: device IDENTIFY data / SCSI command of interest. * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. * @buflen: Response buffer length. @@ -1660,16 +1670,16 @@ unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf, return 0; } -static const char * const inq_83_str = "Linux ATA-SCSI simulator"; - /** - * ata_scsiop_inq_83 - Simulate INQUIRY EVPD page 83, device identity + * ata_scsiop_inq_83 - Simulate INQUIRY VPD page 83, device identity * @args: device IDENTIFY data / SCSI command of interest. * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. * @buflen: Response buffer length. * - * Returns device identification. Currently hardcoded to - * return "Linux ATA-SCSI simulator". + * Yields two logical unit device identification designators: + * - vendor specific ASCII containing the ATA serial number + * - SAT defined "t10 vendor id based" containing ASCII vendor + * name ("ATA "), model and serial numbers. * * LOCKING: * spin_lock_irqsave(host_set lock) @@ -1678,16 +1688,39 @@ static const char * const inq_83_str = "Linux ATA-SCSI simulator"; unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf, unsigned int buflen) { - rbuf[1] = 0x83; /* this page code */ - rbuf[3] = 4 + strlen(inq_83_str); /* page len */ + int num; + const int sat_model_serial_desc_len = 68; + const int ata_model_byte_len = 40; - /* our one and only identification descriptor (vendor-specific) */ - if (buflen > (strlen(inq_83_str) + 4 + 4 - 1)) { - rbuf[4 + 0] = 2; /* code set: ASCII */ - rbuf[4 + 3] = strlen(inq_83_str); - memcpy(rbuf + 4 + 4, inq_83_str, strlen(inq_83_str)); + rbuf[1] = 0x83; /* this page code */ + num = 4; + + if (buflen > (ATA_SERNO_LEN + num + 3)) { + /* piv=0, assoc=lu, code_set=ACSII, designator=vendor */ + rbuf[num + 0] = 2; + rbuf[num + 3] = ATA_SERNO_LEN; + num += 4; + ata_id_string(args->id, (unsigned char *) rbuf + num, + ATA_ID_SERNO_OFS, ATA_SERNO_LEN); + num += ATA_SERNO_LEN; } - + if (buflen > (sat_model_serial_desc_len + num + 3)) { + /* SAT defined lu model and serial numbers descriptor */ + /* piv=0, assoc=lu, code_set=ACSII, designator=t10 vendor id */ + rbuf[num + 0] = 2; + rbuf[num + 1] = 1; + rbuf[num + 3] = sat_model_serial_desc_len; + num += 4; + memcpy(rbuf + num, "ATA ", 8); + num += 8; + ata_id_string(args->id, (unsigned char *) rbuf + num, + ATA_ID_PROD_OFS, ata_model_byte_len); + num += ata_model_byte_len; + ata_id_string(args->id, (unsigned char *) rbuf + num, + ATA_ID_SERNO_OFS, ATA_SERNO_LEN); + num += ATA_SERNO_LEN; + } + rbuf[3] = num - 4; /* page len (assume less than 256 bytes) */ return 0; } @@ -2366,9 +2399,6 @@ ata_scsi_map_proto(u8 byte1) case 4: /* PIO Data-in */ case 5: /* PIO Data-out */ - if (byte1 & 0xe0) { - return ATA_PROT_PIO_MULT; - } return ATA_PROT_PIO; case 10: /* Device Reset */ @@ -2407,6 +2437,10 @@ ata_scsi_pass_thru(struct ata_queued_cmd *qc, const u8 *scsicmd) if ((tf->protocol = ata_scsi_map_proto(scsicmd[1])) == ATA_PROT_UNKNOWN) goto invalid_fld; + if (scsicmd[1] & 0xe0) + /* PIO multi not supported yet */ + goto invalid_fld; + /* * 12 and 16 byte CDBs use different offsets to * provide the various register values. diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c index b3dc5f8..3c85c4b 100644 --- a/drivers/scsi/pdc_adma.c +++ b/drivers/scsi/pdc_adma.c @@ -321,7 +321,7 @@ static int adma_fill_sg(struct ata_queued_cmd *qc) = (pFLAGS & pEND) ? 0 : cpu_to_le32(pp->pkt_dma + i + 4); i += 4; - VPRINTK("PRD[%u] = (0x%lX, 0x%X)\n", nelem, + VPRINTK("PRD[%u] = (0x%lX, 0x%X)\n", i/4, (unsigned long)addr, len); } return i; diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index 874c5be..275ed9b 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -1262,6 +1262,7 @@ static u8 mv_get_crpb_status(struct ata_port *ap) void __iomem *port_mmio = mv_ap_base(ap); struct mv_port_priv *pp = ap->private_data; u32 out_ptr; + u8 ata_status; out_ptr = readl(port_mmio + EDMA_RSP_Q_OUT_PTR_OFS); @@ -1269,6 +1270,8 @@ static u8 mv_get_crpb_status(struct ata_port *ap) WARN_ON(((out_ptr >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) != pp->rsp_consumer); + ata_status = pp->crpb[pp->rsp_consumer].flags >> CRPB_FLAG_STATUS_SHIFT; + /* increment our consumer index... */ pp->rsp_consumer = mv_inc_q_index(&pp->rsp_consumer); @@ -1283,7 +1286,7 @@ static u8 mv_get_crpb_status(struct ata_port *ap) writelfl(out_ptr, port_mmio + EDMA_RSP_Q_OUT_PTR_OFS); /* Return ATA status register for completed CRPB */ - return (pp->crpb[pp->rsp_consumer].flags >> CRPB_FLAG_STATUS_SHIFT); + return ata_status; } /** diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c index 051e47d..724f0ed 100644 --- a/drivers/scsi/sata_svw.c +++ b/drivers/scsi/sata_svw.c @@ -56,33 +56,35 @@ #define DRV_NAME "sata_svw" #define DRV_VERSION "1.07" -/* Taskfile registers offsets */ -#define K2_SATA_TF_CMD_OFFSET 0x00 -#define K2_SATA_TF_DATA_OFFSET 0x00 -#define K2_SATA_TF_ERROR_OFFSET 0x04 -#define K2_SATA_TF_NSECT_OFFSET 0x08 -#define K2_SATA_TF_LBAL_OFFSET 0x0c -#define K2_SATA_TF_LBAM_OFFSET 0x10 -#define K2_SATA_TF_LBAH_OFFSET 0x14 -#define K2_SATA_TF_DEVICE_OFFSET 0x18 -#define K2_SATA_TF_CMDSTAT_OFFSET 0x1c -#define K2_SATA_TF_CTL_OFFSET 0x20 - -/* DMA base */ -#define K2_SATA_DMA_CMD_OFFSET 0x30 - -/* SCRs base */ -#define K2_SATA_SCR_STATUS_OFFSET 0x40 -#define K2_SATA_SCR_ERROR_OFFSET 0x44 -#define K2_SATA_SCR_CONTROL_OFFSET 0x48 - -/* Others */ -#define K2_SATA_SICR1_OFFSET 0x80 -#define K2_SATA_SICR2_OFFSET 0x84 -#define K2_SATA_SIM_OFFSET 0x88 - -/* Port stride */ -#define K2_SATA_PORT_OFFSET 0x100 +enum { + /* Taskfile registers offsets */ + K2_SATA_TF_CMD_OFFSET = 0x00, + K2_SATA_TF_DATA_OFFSET = 0x00, + K2_SATA_TF_ERROR_OFFSET = 0x04, + K2_SATA_TF_NSECT_OFFSET = 0x08, + K2_SATA_TF_LBAL_OFFSET = 0x0c, + K2_SATA_TF_LBAM_OFFSET = 0x10, + K2_SATA_TF_LBAH_OFFSET = 0x14, + K2_SATA_TF_DEVICE_OFFSET = 0x18, + K2_SATA_TF_CMDSTAT_OFFSET = 0x1c, + K2_SATA_TF_CTL_OFFSET = 0x20, + + /* DMA base */ + K2_SATA_DMA_CMD_OFFSET = 0x30, + + /* SCRs base */ + K2_SATA_SCR_STATUS_OFFSET = 0x40, + K2_SATA_SCR_ERROR_OFFSET = 0x44, + K2_SATA_SCR_CONTROL_OFFSET = 0x48, + + /* Others */ + K2_SATA_SICR1_OFFSET = 0x80, + K2_SATA_SICR2_OFFSET = 0x84, + K2_SATA_SIM_OFFSET = 0x88, + + /* Port stride */ + K2_SATA_PORT_OFFSET = 0x100, +}; static u8 k2_stat_check_status(struct ata_port *ap); diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c index ee75b9b..9701a80 100644 --- a/drivers/scsi/sata_vsc.c +++ b/drivers/scsi/sata_vsc.c @@ -47,52 +47,58 @@ #include <linux/libata.h> #define DRV_NAME "sata_vsc" -#define DRV_VERSION "1.1" - -/* Interrupt register offsets (from chip base address) */ -#define VSC_SATA_INT_STAT_OFFSET 0x00 -#define VSC_SATA_INT_MASK_OFFSET 0x04 - -/* Taskfile registers offsets */ -#define VSC_SATA_TF_CMD_OFFSET 0x00 -#define VSC_SATA_TF_DATA_OFFSET 0x00 -#define VSC_SATA_TF_ERROR_OFFSET 0x04 -#define VSC_SATA_TF_FEATURE_OFFSET 0x06 -#define VSC_SATA_TF_NSECT_OFFSET 0x08 -#define VSC_SATA_TF_LBAL_OFFSET 0x0c -#define VSC_SATA_TF_LBAM_OFFSET 0x10 -#define VSC_SATA_TF_LBAH_OFFSET 0x14 -#define VSC_SATA_TF_DEVICE_OFFSET 0x18 -#define VSC_SATA_TF_STATUS_OFFSET 0x1c -#define VSC_SATA_TF_COMMAND_OFFSET 0x1d -#define VSC_SATA_TF_ALTSTATUS_OFFSET 0x28 -#define VSC_SATA_TF_CTL_OFFSET 0x29 - -/* DMA base */ -#define VSC_SATA_UP_DESCRIPTOR_OFFSET 0x64 -#define VSC_SATA_UP_DATA_BUFFER_OFFSET 0x6C -#define VSC_SATA_DMA_CMD_OFFSET 0x70 - -/* SCRs base */ -#define VSC_SATA_SCR_STATUS_OFFSET 0x100 -#define VSC_SATA_SCR_ERROR_OFFSET 0x104 -#define VSC_SATA_SCR_CONTROL_OFFSET 0x108 - -/* Port stride */ -#define VSC_SATA_PORT_OFFSET 0x200 - -/* Error interrupt status bit offsets */ -#define VSC_SATA_INT_ERROR_E_OFFSET 2 -#define VSC_SATA_INT_ERROR_P_OFFSET 4 -#define VSC_SATA_INT_ERROR_T_OFFSET 5 -#define VSC_SATA_INT_ERROR_M_OFFSET 1 +#define DRV_VERSION "1.2" + +enum { + /* Interrupt register offsets (from chip base address) */ + VSC_SATA_INT_STAT_OFFSET = 0x00, + VSC_SATA_INT_MASK_OFFSET = 0x04, + + /* Taskfile registers offsets */ + VSC_SATA_TF_CMD_OFFSET = 0x00, + VSC_SATA_TF_DATA_OFFSET = 0x00, + VSC_SATA_TF_ERROR_OFFSET = 0x04, + VSC_SATA_TF_FEATURE_OFFSET = 0x06, + VSC_SATA_TF_NSECT_OFFSET = 0x08, + VSC_SATA_TF_LBAL_OFFSET = 0x0c, + VSC_SATA_TF_LBAM_OFFSET = 0x10, + VSC_SATA_TF_LBAH_OFFSET = 0x14, + VSC_SATA_TF_DEVICE_OFFSET = 0x18, + VSC_SATA_TF_STATUS_OFFSET = 0x1c, + VSC_SATA_TF_COMMAND_OFFSET = 0x1d, + VSC_SATA_TF_ALTSTATUS_OFFSET = 0x28, + VSC_SATA_TF_CTL_OFFSET = 0x29, + + /* DMA base */ + VSC_SATA_UP_DESCRIPTOR_OFFSET = 0x64, + VSC_SATA_UP_DATA_BUFFER_OFFSET = 0x6C, + VSC_SATA_DMA_CMD_OFFSET = 0x70, + + /* SCRs base */ + VSC_SATA_SCR_STATUS_OFFSET = 0x100, + VSC_SATA_SCR_ERROR_OFFSET = 0x104, + VSC_SATA_SCR_CONTROL_OFFSET = 0x108, + + /* Port stride */ + VSC_SATA_PORT_OFFSET = 0x200, + + /* Error interrupt status bit offsets */ + VSC_SATA_INT_ERROR_CRC = 0x40, + VSC_SATA_INT_ERROR_T = 0x20, + VSC_SATA_INT_ERROR_P = 0x10, + VSC_SATA_INT_ERROR_R = 0x8, + VSC_SATA_INT_ERROR_E = 0x4, + VSC_SATA_INT_ERROR_M = 0x2, + VSC_SATA_INT_PHY_CHANGE = 0x1, + VSC_SATA_INT_ERROR = (VSC_SATA_INT_ERROR_CRC | VSC_SATA_INT_ERROR_T | \ + VSC_SATA_INT_ERROR_P | VSC_SATA_INT_ERROR_R | \ + VSC_SATA_INT_ERROR_E | VSC_SATA_INT_ERROR_M | \ + VSC_SATA_INT_PHY_CHANGE), +}; + + #define is_vsc_sata_int_err(port_idx, int_status) \ - (int_status & ((1 << (VSC_SATA_INT_ERROR_E_OFFSET + (8 * port_idx))) | \ - (1 << (VSC_SATA_INT_ERROR_P_OFFSET + (8 * port_idx))) | \ - (1 << (VSC_SATA_INT_ERROR_T_OFFSET + (8 * port_idx))) | \ - (1 << (VSC_SATA_INT_ERROR_M_OFFSET + (8 * port_idx))) \ - )\ - ) + (int_status & (VSC_SATA_INT_ERROR << (8 * port_idx))) static u32 vsc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg) @@ -215,14 +221,6 @@ static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance, ap = host_set->ports[i]; - if (is_vsc_sata_int_err(i, int_status)) { - u32 err_status; - printk(KERN_DEBUG "%s: ignoring interrupt(s)\n", __FUNCTION__); - err_status = ap ? vsc_sata_scr_read(ap, SCR_ERROR) : 0; - vsc_sata_scr_write(ap, SCR_ERROR, err_status); - handled++; - } - if (ap && !(ap->flags & (ATA_FLAG_PORT_DISABLED|ATA_FLAG_NOINTR))) { struct ata_queued_cmd *qc; @@ -230,12 +228,26 @@ static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance, qc = ata_qc_from_tag(ap, ap->active_tag); if (qc && (!(qc->tf.ctl & ATA_NIEN))) { handled += ata_host_intr(ap, qc); - } else { - printk(KERN_DEBUG "%s: ignoring interrupt(s)\n", __FUNCTION__); + } else if (is_vsc_sata_int_err(i, int_status)) { + /* + * On some chips (i.e. Intel 31244), an error + * interrupt will sneak in at initialization + * time (phy state changes). Clearing the SCR + * error register is not required, but it prevents + * the phy state change interrupts from recurring + * later. + */ + u32 err_status; + err_status = vsc_sata_scr_read(ap, SCR_ERROR); + printk(KERN_DEBUG "%s: clearing interrupt, " + "status %x; sata err status %x\n", + __FUNCTION__, + int_status, err_status); + vsc_sata_scr_write(ap, SCR_ERROR, err_status); + /* Clear interrupt status */ ata_chk_status(ap); handled++; } - } } } |