mirror of https://gitee.com/openkylin/linux.git
[libata] pdc_adma: convert to new exception handling (EH) framework
Signed-off-by: Jeff Garzik <jeff@garzik.org>
This commit is contained in:
parent
782e3b3b38
commit
640fdb5049
|
@ -92,6 +92,8 @@ enum {
|
||||||
|
|
||||||
/* CPB bits */
|
/* CPB bits */
|
||||||
cDONE = (1 << 0),
|
cDONE = (1 << 0),
|
||||||
|
cATERR = (1 << 3),
|
||||||
|
|
||||||
cVLD = (1 << 0),
|
cVLD = (1 << 0),
|
||||||
cDAT = (1 << 2),
|
cDAT = (1 << 2),
|
||||||
cIEN = (1 << 3),
|
cIEN = (1 << 3),
|
||||||
|
@ -131,14 +133,15 @@ static int adma_ata_init_one (struct pci_dev *pdev,
|
||||||
static int adma_port_start(struct ata_port *ap);
|
static int adma_port_start(struct ata_port *ap);
|
||||||
static void adma_host_stop(struct ata_host *host);
|
static void adma_host_stop(struct ata_host *host);
|
||||||
static void adma_port_stop(struct ata_port *ap);
|
static void adma_port_stop(struct ata_port *ap);
|
||||||
static void adma_phy_reset(struct ata_port *ap);
|
|
||||||
static void adma_qc_prep(struct ata_queued_cmd *qc);
|
static void adma_qc_prep(struct ata_queued_cmd *qc);
|
||||||
static unsigned int adma_qc_issue(struct ata_queued_cmd *qc);
|
static unsigned int adma_qc_issue(struct ata_queued_cmd *qc);
|
||||||
static int adma_check_atapi_dma(struct ata_queued_cmd *qc);
|
static int adma_check_atapi_dma(struct ata_queued_cmd *qc);
|
||||||
static void adma_bmdma_stop(struct ata_queued_cmd *qc);
|
static void adma_bmdma_stop(struct ata_queued_cmd *qc);
|
||||||
static u8 adma_bmdma_status(struct ata_port *ap);
|
static u8 adma_bmdma_status(struct ata_port *ap);
|
||||||
static void adma_irq_clear(struct ata_port *ap);
|
static void adma_irq_clear(struct ata_port *ap);
|
||||||
static void adma_eng_timeout(struct ata_port *ap);
|
static void adma_freeze(struct ata_port *ap);
|
||||||
|
static void adma_thaw(struct ata_port *ap);
|
||||||
|
static void adma_error_handler(struct ata_port *ap);
|
||||||
|
|
||||||
static struct scsi_host_template adma_ata_sht = {
|
static struct scsi_host_template adma_ata_sht = {
|
||||||
.module = THIS_MODULE,
|
.module = THIS_MODULE,
|
||||||
|
@ -165,12 +168,13 @@ static const struct ata_port_operations adma_ata_ops = {
|
||||||
.exec_command = ata_exec_command,
|
.exec_command = ata_exec_command,
|
||||||
.check_status = ata_check_status,
|
.check_status = ata_check_status,
|
||||||
.dev_select = ata_std_dev_select,
|
.dev_select = ata_std_dev_select,
|
||||||
.phy_reset = adma_phy_reset,
|
|
||||||
.check_atapi_dma = adma_check_atapi_dma,
|
.check_atapi_dma = adma_check_atapi_dma,
|
||||||
.data_xfer = ata_data_xfer,
|
.data_xfer = ata_data_xfer,
|
||||||
.qc_prep = adma_qc_prep,
|
.qc_prep = adma_qc_prep,
|
||||||
.qc_issue = adma_qc_issue,
|
.qc_issue = adma_qc_issue,
|
||||||
.eng_timeout = adma_eng_timeout,
|
.freeze = adma_freeze,
|
||||||
|
.thaw = adma_thaw,
|
||||||
|
.error_handler = adma_error_handler,
|
||||||
.irq_clear = adma_irq_clear,
|
.irq_clear = adma_irq_clear,
|
||||||
.irq_on = ata_irq_on,
|
.irq_on = ata_irq_on,
|
||||||
.irq_ack = ata_irq_ack,
|
.irq_ack = ata_irq_ack,
|
||||||
|
@ -184,7 +188,7 @@ static const struct ata_port_operations adma_ata_ops = {
|
||||||
static struct ata_port_info adma_port_info[] = {
|
static struct ata_port_info adma_port_info[] = {
|
||||||
/* board_1841_idx */
|
/* board_1841_idx */
|
||||||
{
|
{
|
||||||
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST |
|
.flags = ATA_FLAG_SLAVE_POSS |
|
||||||
ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO |
|
ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO |
|
||||||
ATA_FLAG_PIO_POLLING,
|
ATA_FLAG_PIO_POLLING,
|
||||||
.pio_mask = 0x10, /* pio4 */
|
.pio_mask = 0x10, /* pio4 */
|
||||||
|
@ -273,24 +277,41 @@ static inline void adma_enter_reg_mode(struct ata_port *ap)
|
||||||
readb(chan + ADMA_STATUS); /* flush */
|
readb(chan + ADMA_STATUS); /* flush */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void adma_phy_reset(struct ata_port *ap)
|
static void adma_freeze(struct ata_port *ap)
|
||||||
{
|
{
|
||||||
struct adma_port_priv *pp = ap->private_data;
|
void __iomem *chan = ADMA_PORT_REGS(ap);
|
||||||
|
|
||||||
pp->state = adma_state_idle;
|
/* mask/clear ATA interrupts */
|
||||||
adma_reinit_engine(ap);
|
writeb(ATA_NIEN, ap->ioaddr.ctl_addr);
|
||||||
ata_port_probe(ap);
|
ata_check_status(ap);
|
||||||
ata_bus_reset(ap);
|
|
||||||
|
/* reset ADMA to idle state */
|
||||||
|
writew(aPIOMD4 | aNIEN | aRSTADM, chan + ADMA_CONTROL);
|
||||||
|
udelay(2);
|
||||||
|
writew(aPIOMD4 | aNIEN, chan + ADMA_CONTROL);
|
||||||
|
udelay(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void adma_eng_timeout(struct ata_port *ap)
|
static void adma_thaw(struct ata_port *ap)
|
||||||
|
{
|
||||||
|
adma_reinit_engine(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int adma_prereset(struct ata_port *ap, unsigned long deadline)
|
||||||
{
|
{
|
||||||
struct adma_port_priv *pp = ap->private_data;
|
struct adma_port_priv *pp = ap->private_data;
|
||||||
|
|
||||||
if (pp->state != adma_state_idle) /* healthy paranoia */
|
if (pp->state != adma_state_idle) /* healthy paranoia */
|
||||||
pp->state = adma_state_mmio;
|
pp->state = adma_state_mmio;
|
||||||
adma_reinit_engine(ap);
|
adma_reinit_engine(ap);
|
||||||
ata_eng_timeout(ap);
|
|
||||||
|
return ata_std_prereset(ap, deadline);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void adma_error_handler(struct ata_port *ap)
|
||||||
|
{
|
||||||
|
ata_do_eh(ap, adma_prereset, ata_std_softreset, NULL,
|
||||||
|
ata_std_postreset);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int adma_fill_sg(struct ata_queued_cmd *qc)
|
static int adma_fill_sg(struct ata_queued_cmd *qc)
|
||||||
|
@ -466,12 +487,31 @@ static inline unsigned int adma_intr_pkt(struct ata_host *host)
|
||||||
continue;
|
continue;
|
||||||
qc = ata_qc_from_tag(ap, ap->active_tag);
|
qc = ata_qc_from_tag(ap, ap->active_tag);
|
||||||
if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
|
if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
|
||||||
if ((status & (aPERR | aPSD | aUIRQ)))
|
if (status & aPERR)
|
||||||
|
qc->err_mask |= AC_ERR_HOST_BUS;
|
||||||
|
else if ((status & (aPSD | aUIRQ)))
|
||||||
qc->err_mask |= AC_ERR_OTHER;
|
qc->err_mask |= AC_ERR_OTHER;
|
||||||
|
|
||||||
|
if (pp->pkt[0] & cATERR)
|
||||||
|
qc->err_mask |= AC_ERR_DEV;
|
||||||
else if (pp->pkt[0] != cDONE)
|
else if (pp->pkt[0] != cDONE)
|
||||||
qc->err_mask |= AC_ERR_OTHER;
|
qc->err_mask |= AC_ERR_OTHER;
|
||||||
|
|
||||||
ata_qc_complete(qc);
|
if (!qc->err_mask)
|
||||||
|
ata_qc_complete(qc);
|
||||||
|
else {
|
||||||
|
struct ata_eh_info *ehi = &ap->eh_info;
|
||||||
|
ata_ehi_clear_desc(ehi);
|
||||||
|
ata_ehi_push_desc(ehi,
|
||||||
|
"ADMA-status 0x%02X", status);
|
||||||
|
ata_ehi_push_desc(ehi,
|
||||||
|
"pkt[0] 0x%02X", pp->pkt[0]);
|
||||||
|
|
||||||
|
if (qc->err_mask == AC_ERR_DEV)
|
||||||
|
ata_port_abort(ap);
|
||||||
|
else
|
||||||
|
ata_port_freeze(ap);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return handled;
|
return handled;
|
||||||
|
@ -502,7 +542,19 @@ static inline unsigned int adma_intr_mmio(struct ata_host *host)
|
||||||
/* complete taskfile transaction */
|
/* complete taskfile transaction */
|
||||||
pp->state = adma_state_idle;
|
pp->state = adma_state_idle;
|
||||||
qc->err_mask |= ac_err_mask(status);
|
qc->err_mask |= ac_err_mask(status);
|
||||||
ata_qc_complete(qc);
|
if (!qc->err_mask)
|
||||||
|
ata_qc_complete(qc);
|
||||||
|
else {
|
||||||
|
struct ata_eh_info *ehi = &ap->eh_info;
|
||||||
|
ata_ehi_clear_desc(ehi);
|
||||||
|
ata_ehi_push_desc(ehi,
|
||||||
|
"status 0x%02X", status);
|
||||||
|
|
||||||
|
if (qc->err_mask == AC_ERR_DEV)
|
||||||
|
ata_port_abort(ap);
|
||||||
|
else
|
||||||
|
ata_port_freeze(ap);
|
||||||
|
}
|
||||||
handled = 1;
|
handled = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue