ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
ATA_FLAG_NCQ | ATA_FLAG_ACPI_SATA |
ATA_FLAG_AN | ATA_FLAG_PMP,
- SIL24_COMMON_LFLAGS = ATA_LFLAG_SKIP_D2H_BSY,
SIL24_FLAG_PCIX_IRQ_WOC = (1 << 24), /* IRQ loss errata on PCI-X */
IRQ_STAT_4PORTS = 0xf,
"device error via D2H FIS" },
[PORT_CERR_SDB] = { AC_ERR_DEV, 0,
"device error via SDB FIS" },
- [PORT_CERR_DATA] = { AC_ERR_ATA_BUS, ATA_EH_SOFTRESET,
+ [PORT_CERR_DATA] = { AC_ERR_ATA_BUS, ATA_EH_RESET,
"error in data FIS" },
- [PORT_CERR_SEND] = { AC_ERR_ATA_BUS, ATA_EH_SOFTRESET,
+ [PORT_CERR_SEND] = { AC_ERR_ATA_BUS, ATA_EH_RESET,
"failed to transmit command FIS" },
- [PORT_CERR_INCONSISTENT] = { AC_ERR_HSM, ATA_EH_SOFTRESET,
+ [PORT_CERR_INCONSISTENT] = { AC_ERR_HSM, ATA_EH_RESET,
"protocol mismatch" },
- [PORT_CERR_DIRECTION] = { AC_ERR_HSM, ATA_EH_SOFTRESET,
+ [PORT_CERR_DIRECTION] = { AC_ERR_HSM, ATA_EH_RESET,
"data directon mismatch" },
- [PORT_CERR_UNDERRUN] = { AC_ERR_HSM, ATA_EH_SOFTRESET,
+ [PORT_CERR_UNDERRUN] = { AC_ERR_HSM, ATA_EH_RESET,
"ran out of SGEs while writing" },
- [PORT_CERR_OVERRUN] = { AC_ERR_HSM, ATA_EH_SOFTRESET,
+ [PORT_CERR_OVERRUN] = { AC_ERR_HSM, ATA_EH_RESET,
"ran out of SGEs while reading" },
- [PORT_CERR_PKT_PROT] = { AC_ERR_HSM, ATA_EH_SOFTRESET,
+ [PORT_CERR_PKT_PROT] = { AC_ERR_HSM, ATA_EH_RESET,
"invalid data directon for ATAPI CDB" },
- [PORT_CERR_SGT_BOUNDARY] = { AC_ERR_SYSTEM, ATA_EH_SOFTRESET,
+ [PORT_CERR_SGT_BOUNDARY] = { AC_ERR_SYSTEM, ATA_EH_RESET,
"SGT not on qword boundary" },
- [PORT_CERR_SGT_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+ [PORT_CERR_SGT_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_RESET,
"PCI target abort while fetching SGT" },
- [PORT_CERR_SGT_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+ [PORT_CERR_SGT_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_RESET,
"PCI master abort while fetching SGT" },
- [PORT_CERR_SGT_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+ [PORT_CERR_SGT_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_RESET,
"PCI parity error while fetching SGT" },
- [PORT_CERR_CMD_BOUNDARY] = { AC_ERR_SYSTEM, ATA_EH_SOFTRESET,
+ [PORT_CERR_CMD_BOUNDARY] = { AC_ERR_SYSTEM, ATA_EH_RESET,
"PRB not on qword boundary" },
- [PORT_CERR_CMD_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+ [PORT_CERR_CMD_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_RESET,
"PCI target abort while fetching PRB" },
- [PORT_CERR_CMD_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+ [PORT_CERR_CMD_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_RESET,
"PCI master abort while fetching PRB" },
- [PORT_CERR_CMD_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+ [PORT_CERR_CMD_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_RESET,
"PCI parity error while fetching PRB" },
- [PORT_CERR_XFR_UNDEF] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+ [PORT_CERR_XFR_UNDEF] = { AC_ERR_HOST_BUS, ATA_EH_RESET,
"undefined error while transferring data" },
- [PORT_CERR_XFR_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+ [PORT_CERR_XFR_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_RESET,
"PCI target abort while transferring data" },
- [PORT_CERR_XFR_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+ [PORT_CERR_XFR_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_RESET,
"PCI master abort while transferring data" },
- [PORT_CERR_XFR_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+ [PORT_CERR_XFR_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_RESET,
"PCI parity error while transferring data" },
- [PORT_CERR_SENDSERVICE] = { AC_ERR_HSM, ATA_EH_SOFTRESET,
+ [PORT_CERR_SENDSERVICE] = { AC_ERR_HSM, ATA_EH_RESET,
"FIS received while sending service FIS" },
};
static u8 sil24_check_status(struct ata_port *ap);
static int sil24_scr_read(struct ata_port *ap, unsigned sc_reg, u32 *val);
static int sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val);
-static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
static int sil24_qc_defer(struct ata_queued_cmd *qc);
static void sil24_qc_prep(struct ata_queued_cmd *qc);
static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc);
-static void sil24_irq_clear(struct ata_port *ap);
+static bool sil24_qc_fill_rtf(struct ata_queued_cmd *qc);
static void sil24_pmp_attach(struct ata_port *ap);
static void sil24_pmp_detach(struct ata_port *ap);
static void sil24_freeze(struct ata_port *ap);
static void sil24_thaw(struct ata_port *ap);
+static int sil24_softreset(struct ata_link *link, unsigned int *class,
+ unsigned long deadline);
+static int sil24_hardreset(struct ata_link *link, unsigned int *class,
+ unsigned long deadline);
+static int sil24_pmp_softreset(struct ata_link *link, unsigned int *class,
+ unsigned long deadline);
+static int sil24_pmp_hardreset(struct ata_link *link, unsigned int *class,
+ unsigned long deadline);
static void sil24_error_handler(struct ata_port *ap);
static void sil24_post_internal_cmd(struct ata_queued_cmd *qc);
static int sil24_port_start(struct ata_port *ap);
};
static struct scsi_host_template sil24_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 = SIL24_MAX_CMDS,
- .this_id = ATA_SHT_THIS_ID,
.sg_tablesize = SIL24_MAX_SGE,
- .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,
};
-static const struct ata_port_operations sil24_ops = {
- .dev_config = sil24_dev_config,
-
- .check_status = sil24_check_status,
- .check_altstatus = sil24_check_status,
- .dev_select = ata_noop_dev_select,
-
- .tf_read = sil24_tf_read,
+static struct ata_port_operations sil24_ops = {
+ .inherits = &sata_pmp_port_ops,
+ .sff_check_status = sil24_check_status,
+ .sff_check_altstatus = sil24_check_status,
.qc_defer = sil24_qc_defer,
.qc_prep = sil24_qc_prep,
.qc_issue = sil24_qc_issue,
+ .qc_fill_rtf = sil24_qc_fill_rtf,
- .irq_clear = sil24_irq_clear,
+ .freeze = sil24_freeze,
+ .thaw = sil24_thaw,
+ .softreset = sil24_softreset,
+ .hardreset = sil24_hardreset,
+ .pmp_softreset = sil24_pmp_softreset,
+ .pmp_hardreset = sil24_pmp_hardreset,
+ .error_handler = sil24_error_handler,
+ .post_internal_cmd = sil24_post_internal_cmd,
+ .dev_config = sil24_dev_config,
.scr_read = sil24_scr_read,
.scr_write = sil24_scr_write,
-
.pmp_attach = sil24_pmp_attach,
.pmp_detach = sil24_pmp_detach,
- .freeze = sil24_freeze,
- .thaw = sil24_thaw,
- .error_handler = sil24_error_handler,
- .post_internal_cmd = sil24_post_internal_cmd,
-
.port_start = sil24_port_start,
-
#ifdef CONFIG_PM
.port_resume = sil24_port_resume,
#endif
{
.flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(4) |
SIL24_FLAG_PCIX_IRQ_WOC,
- .link_flags = SIL24_COMMON_LFLAGS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = ATA_UDMA5, /* udma0-5 */
/* sil_3132 */
{
.flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(2),
- .link_flags = SIL24_COMMON_LFLAGS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = ATA_UDMA5, /* udma0-5 */
/* sil_3131/sil_3531 */
{
.flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(1),
- .link_flags = SIL24_COMMON_LFLAGS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = ATA_UDMA5, /* udma0-5 */
return -EINVAL;
}
-static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
-{
- struct sil24_port_priv *pp = ap->private_data;
- *tf = pp->tf;
-}
-
static void sil24_config_port(struct ata_port *ap)
{
void __iomem *port = ap->ioaddr.cmd_addr;
if ((tmp & (PORT_CS_INIT | PORT_CS_RDY)) != PORT_CS_RDY) {
pp->do_port_rst = 1;
- ap->link.eh_context.i.action |= ATA_EH_HARDRESET;
+ ap->link.eh_context.i.action |= ATA_EH_RESET;
return -EIO;
}
{
struct scatterlist *sg;
struct sil24_sge *last_sge = NULL;
+ unsigned int si;
- ata_for_each_sg(sg, qc) {
+ for_each_sg(qc->sg, sg, qc->n_elem, si) {
sge->addr = cpu_to_le64(sg_dma_address(sg));
sge->cnt = cpu_to_le32(sg_dma_len(sg));
sge->flags = 0;
sge++;
}
- if (likely(last_sge))
- last_sge->flags = cpu_to_le32(SGE_TRM);
+ last_sge->flags = cpu_to_le32(SGE_TRM);
}
static int sil24_qc_defer(struct ata_queued_cmd *qc)
* set.
*
*/
- int is_excl = (prot == ATA_PROT_ATAPI ||
- prot == ATA_PROT_ATAPI_NODATA ||
- prot == ATA_PROT_ATAPI_DMA ||
+ int is_excl = (ata_is_atapi(prot) ||
(qc->flags & ATA_QCFLAG_RESULT_TF));
if (unlikely(ap->excl_link)) {
cb = &pp->cmd_block[sil24_tag(qc->tag)];
- switch (qc->tf.protocol) {
- case ATA_PROT_PIO:
- case ATA_PROT_DMA:
- case ATA_PROT_NCQ:
- case ATA_PROT_NODATA:
+ if (!ata_is_atapi(qc->tf.protocol)) {
prb = &cb->ata.prb;
sge = cb->ata.sge;
- break;
-
- case ATA_PROT_ATAPI:
- case ATA_PROT_ATAPI_DMA:
- case ATA_PROT_ATAPI_NODATA:
+ } else {
prb = &cb->atapi.prb;
sge = cb->atapi.sge;
memset(cb->atapi.cdb, 0, 32);
memcpy(cb->atapi.cdb, qc->cdb, qc->dev->cdb_len);
- if (qc->tf.protocol != ATA_PROT_ATAPI_NODATA) {
+ if (ata_is_data(qc->tf.protocol)) {
if (qc->tf.flags & ATA_TFLAG_WRITE)
ctrl = PRB_CTRL_PACKET_WRITE;
else
ctrl = PRB_CTRL_PACKET_READ;
}
- break;
-
- default:
- prb = NULL; /* shut up, gcc */
- sge = NULL;
- BUG();
}
prb->ctrl = cpu_to_le16(ctrl);
return 0;
}
-static void sil24_irq_clear(struct ata_port *ap)
+static bool sil24_qc_fill_rtf(struct ata_queued_cmd *qc)
{
- /* unused */
+ sil24_read_tf(qc->ap, qc->tag, &qc->result_tf);
+ return true;
}
static void sil24_pmp_attach(struct ata_port *ap)
return rc;
}
- return sata_pmp_std_hardreset(link, class, deadline);
+ return sata_std_hardreset(link, class, deadline);
}
static void sil24_freeze(struct ata_port *ap)
if (irq_stat & PORT_IRQ_UNK_FIS) {
ehi->err_mask |= AC_ERR_HSM;
- ehi->action |= ATA_EH_SOFTRESET;
+ ehi->action |= ATA_EH_RESET;
ata_ehi_push_desc(ehi, "unknown FIS");
freeze = 1;
}
*/
if (ap->nr_active_links >= 3) {
ehi->err_mask |= AC_ERR_OTHER;
- ehi->action |= ATA_EH_HARDRESET;
+ ehi->action |= ATA_EH_RESET;
ata_ehi_push_desc(ehi, "PMP DMA CS errata");
pp->do_port_rst = 1;
freeze = 1;
irq_stat);
} else {
err_mask |= AC_ERR_HSM;
- action |= ATA_EH_HARDRESET;
+ action |= ATA_EH_RESET;
freeze = 1;
}
} else
if (ci && ci->desc) {
err_mask |= ci->err_mask;
action |= ci->action;
- if (action & ATA_EH_RESET_MASK)
+ if (action & ATA_EH_RESET)
freeze = 1;
ata_ehi_push_desc(ehi, "%s", ci->desc);
} else {
err_mask |= AC_ERR_OTHER;
- action |= ATA_EH_SOFTRESET;
+ action |= ATA_EH_RESET;
freeze = 1;
ata_ehi_push_desc(ehi, "unknown command error %d",
cerr);
}
}
-static void sil24_finish_qc(struct ata_queued_cmd *qc)
-{
- struct ata_port *ap = qc->ap;
- struct sil24_port_priv *pp = ap->private_data;
-
- if (qc->flags & ATA_QCFLAG_RESULT_TF)
- sil24_read_tf(ap, qc->tag, &pp->tf);
-}
-
static inline void sil24_host_intr(struct ata_port *ap)
{
void __iomem *port = ap->ioaddr.cmd_addr;
}
qc_active = slot_stat & ~HOST_SSTAT_ATTN;
- rc = ata_qc_complete_multiple(ap, qc_active, sil24_finish_qc);
+ rc = ata_qc_complete_multiple(ap, qc_active);
if (rc > 0)
return;
if (rc < 0) {
struct ata_eh_info *ehi = &ap->link.eh_info;
ehi->err_mask |= AC_ERR_HSM;
- ehi->action |= ATA_EH_SOFTRESET;
+ ehi->action |= ATA_EH_RESET;
ata_port_freeze(ap);
return;
}
if (sil24_init_port(ap))
ata_eh_freeze_port(ap);
- /* perform recovery */
- sata_pmp_do_eh(ap, ata_std_prereset, sil24_softreset, sil24_hardreset,
- ata_std_postreset, sata_pmp_std_prereset,
- sil24_pmp_softreset, sil24_pmp_hardreset,
- sata_pmp_std_postreset);
+ sata_pmp_error_handler(ap);
pp->do_port_rst = 0;
}
union sil24_cmd_block *cb;
size_t cb_size = sizeof(*cb) * SIL24_MAX_CMDS;
dma_addr_t cb_dma;
- int rc;
pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
if (!pp)
return -ENOMEM;
memset(cb, 0, cb_size);
- rc = ata_pad_alloc(ap, dev);
- if (rc)
- return rc;
-
pp->cmd_block = cb;
pp->cmd_block_dma = cb_dma;