forked from Minki/linux
Merge branch 'upstream'
This commit is contained in:
commit
d2927cbe40
@ -600,7 +600,7 @@ static void ahci_eng_timeout(struct ata_port *ap)
|
|||||||
* not being called from the SCSI EH.
|
* not being called from the SCSI EH.
|
||||||
*/
|
*/
|
||||||
qc->scsidone = scsi_finish_command;
|
qc->scsidone = scsi_finish_command;
|
||||||
ata_qc_complete(qc, ATA_ERR);
|
ata_qc_complete(qc, AC_ERR_OTHER);
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock_irqrestore(&host_set->lock, flags);
|
spin_unlock_irqrestore(&host_set->lock, flags);
|
||||||
@ -629,7 +629,7 @@ static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
|
|||||||
if (status & PORT_IRQ_FATAL) {
|
if (status & PORT_IRQ_FATAL) {
|
||||||
ahci_intr_error(ap, status);
|
ahci_intr_error(ap, status);
|
||||||
if (qc)
|
if (qc)
|
||||||
ata_qc_complete(qc, ATA_ERR);
|
ata_qc_complete(qc, AC_ERR_OTHER);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -2663,7 +2663,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc)
|
|||||||
* None. (grabs host lock)
|
* None. (grabs host lock)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void ata_poll_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
|
void ata_poll_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask)
|
||||||
{
|
{
|
||||||
struct ata_port *ap = qc->ap;
|
struct ata_port *ap = qc->ap;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
@ -2671,7 +2671,7 @@ void ata_poll_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
|
|||||||
spin_lock_irqsave(&ap->host_set->lock, flags);
|
spin_lock_irqsave(&ap->host_set->lock, flags);
|
||||||
ap->flags &= ~ATA_FLAG_NOINTR;
|
ap->flags &= ~ATA_FLAG_NOINTR;
|
||||||
ata_irq_on(ap);
|
ata_irq_on(ap);
|
||||||
ata_qc_complete(qc, drv_stat);
|
ata_qc_complete(qc, err_mask);
|
||||||
spin_unlock_irqrestore(&ap->host_set->lock, flags);
|
spin_unlock_irqrestore(&ap->host_set->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2768,7 +2768,7 @@ static int ata_pio_complete (struct ata_port *ap)
|
|||||||
|
|
||||||
ap->hsm_task_state = HSM_ST_IDLE;
|
ap->hsm_task_state = HSM_ST_IDLE;
|
||||||
|
|
||||||
ata_poll_qc_complete(qc, drv_stat);
|
ata_poll_qc_complete(qc, 0);
|
||||||
|
|
||||||
/* another command may start at this point */
|
/* another command may start at this point */
|
||||||
|
|
||||||
@ -3136,18 +3136,15 @@ static void ata_pio_block(struct ata_port *ap)
|
|||||||
static void ata_pio_error(struct ata_port *ap)
|
static void ata_pio_error(struct ata_port *ap)
|
||||||
{
|
{
|
||||||
struct ata_queued_cmd *qc;
|
struct ata_queued_cmd *qc;
|
||||||
u8 drv_stat;
|
|
||||||
|
printk(KERN_WARNING "ata%u: PIO error\n", ap->id);
|
||||||
|
|
||||||
qc = ata_qc_from_tag(ap, ap->active_tag);
|
qc = ata_qc_from_tag(ap, ap->active_tag);
|
||||||
assert(qc != NULL);
|
assert(qc != NULL);
|
||||||
|
|
||||||
drv_stat = ata_chk_status(ap);
|
|
||||||
printk(KERN_WARNING "ata%u: PIO error, drv_stat 0x%x\n",
|
|
||||||
ap->id, drv_stat);
|
|
||||||
|
|
||||||
ap->hsm_task_state = HSM_ST_IDLE;
|
ap->hsm_task_state = HSM_ST_IDLE;
|
||||||
|
|
||||||
ata_poll_qc_complete(qc, drv_stat | ATA_ERR);
|
ata_poll_qc_complete(qc, AC_ERR_ATA_BUS);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ata_pio_task(void *_data)
|
static void ata_pio_task(void *_data)
|
||||||
@ -3270,7 +3267,7 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc)
|
|||||||
ap->id, qc->tf.command, drv_stat, host_stat);
|
ap->id, qc->tf.command, drv_stat, host_stat);
|
||||||
|
|
||||||
/* complete taskfile transaction */
|
/* complete taskfile transaction */
|
||||||
ata_qc_complete(qc, drv_stat);
|
ata_qc_complete(qc, ac_err_mask(drv_stat));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3375,7 +3372,7 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
|
|||||||
return qc;
|
return qc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ata_qc_complete_noop(struct ata_queued_cmd *qc, u8 drv_stat)
|
int ata_qc_complete_noop(struct ata_queued_cmd *qc, unsigned int err_mask)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -3434,7 +3431,7 @@ void ata_qc_free(struct ata_queued_cmd *qc)
|
|||||||
* spin_lock_irqsave(host_set lock)
|
* spin_lock_irqsave(host_set lock)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
|
void ata_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
@ -3451,7 +3448,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
|
|||||||
qc->flags &= ~ATA_QCFLAG_ACTIVE;
|
qc->flags &= ~ATA_QCFLAG_ACTIVE;
|
||||||
|
|
||||||
/* call completion callback */
|
/* call completion callback */
|
||||||
rc = qc->complete_fn(qc, drv_stat);
|
rc = qc->complete_fn(qc, err_mask);
|
||||||
|
|
||||||
/* if callback indicates not to complete command (non-zero),
|
/* if callback indicates not to complete command (non-zero),
|
||||||
* return immediately
|
* return immediately
|
||||||
@ -3889,7 +3886,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
|
|||||||
ap->ops->irq_clear(ap);
|
ap->ops->irq_clear(ap);
|
||||||
|
|
||||||
/* complete taskfile transaction */
|
/* complete taskfile transaction */
|
||||||
ata_qc_complete(qc, status);
|
ata_qc_complete(qc, ac_err_mask(status));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -3984,7 +3981,7 @@ static void atapi_packet_task(void *_data)
|
|||||||
/* sleep-wait for BSY to clear */
|
/* sleep-wait for BSY to clear */
|
||||||
DPRINTK("busy wait\n");
|
DPRINTK("busy wait\n");
|
||||||
if (ata_busy_sleep(ap, ATA_TMOUT_CDB_QUICK, ATA_TMOUT_CDB))
|
if (ata_busy_sleep(ap, ATA_TMOUT_CDB_QUICK, ATA_TMOUT_CDB))
|
||||||
goto err_out;
|
goto err_out_status;
|
||||||
|
|
||||||
/* make sure DRQ is set */
|
/* make sure DRQ is set */
|
||||||
status = ata_chk_status(ap);
|
status = ata_chk_status(ap);
|
||||||
@ -4021,8 +4018,10 @@ static void atapi_packet_task(void *_data)
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
err_out_status:
|
||||||
|
status = ata_chk_status(ap);
|
||||||
err_out:
|
err_out:
|
||||||
ata_poll_qc_complete(qc, ATA_ERR);
|
ata_poll_qc_complete(qc, __ac_err_mask(status));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -560,7 +560,7 @@ void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc)
|
|||||||
* Use ata_to_sense_error() to map status register bits
|
* Use ata_to_sense_error() to map status register bits
|
||||||
* onto sense key, asc & ascq.
|
* onto sense key, asc & ascq.
|
||||||
*/
|
*/
|
||||||
if (unlikely(tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ))) {
|
if (tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) {
|
||||||
ata_to_sense_error(qc->ap->id, tf->command, tf->feature,
|
ata_to_sense_error(qc->ap->id, tf->command, tf->feature,
|
||||||
&sb[1], &sb[2], &sb[3]);
|
&sb[1], &sb[2], &sb[3]);
|
||||||
sb[1] &= 0x0f;
|
sb[1] &= 0x0f;
|
||||||
@ -635,7 +635,7 @@ void ata_gen_fixed_sense(struct ata_queued_cmd *qc)
|
|||||||
* Use ata_to_sense_error() to map status register bits
|
* Use ata_to_sense_error() to map status register bits
|
||||||
* onto sense key, asc & ascq.
|
* onto sense key, asc & ascq.
|
||||||
*/
|
*/
|
||||||
if (unlikely(tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ))) {
|
if (tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) {
|
||||||
ata_to_sense_error(qc->ap->id, tf->command, tf->feature,
|
ata_to_sense_error(qc->ap->id, tf->command, tf->feature,
|
||||||
&sb[2], &sb[12], &sb[13]);
|
&sb[2], &sb[12], &sb[13]);
|
||||||
sb[2] &= 0x0f;
|
sb[2] &= 0x0f;
|
||||||
@ -644,7 +644,11 @@ void ata_gen_fixed_sense(struct ata_queued_cmd *qc)
|
|||||||
sb[0] = 0x70;
|
sb[0] = 0x70;
|
||||||
sb[7] = 0x0a;
|
sb[7] = 0x0a;
|
||||||
|
|
||||||
if (tf->flags & ATA_TFLAG_LBA && !(tf->flags & ATA_TFLAG_LBA48)) {
|
if (tf->flags & ATA_TFLAG_LBA48) {
|
||||||
|
/* TODO: find solution for LBA48 descriptors */
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (tf->flags & ATA_TFLAG_LBA) {
|
||||||
/* A small (28b) LBA will fit in the 32b info field */
|
/* A small (28b) LBA will fit in the 32b info field */
|
||||||
sb[0] |= 0x80; /* set valid bit */
|
sb[0] |= 0x80; /* set valid bit */
|
||||||
sb[3] = tf->device & 0x0f;
|
sb[3] = tf->device & 0x0f;
|
||||||
@ -652,6 +656,10 @@ void ata_gen_fixed_sense(struct ata_queued_cmd *qc)
|
|||||||
sb[5] = tf->lbam;
|
sb[5] = tf->lbam;
|
||||||
sb[6] = tf->lbal;
|
sb[6] = tf->lbal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
/* TODO: C/H/S */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1193,10 +1201,12 @@ nothing_to_do:
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ata_scsi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
|
static int ata_scsi_qc_complete(struct ata_queued_cmd *qc,
|
||||||
|
unsigned int err_mask)
|
||||||
{
|
{
|
||||||
struct scsi_cmnd *cmd = qc->scsicmd;
|
struct scsi_cmnd *cmd = qc->scsicmd;
|
||||||
int need_sense = drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ);
|
u8 *cdb = cmd->cmnd;
|
||||||
|
int need_sense = (err_mask != 0);
|
||||||
|
|
||||||
/* For ATA pass thru (SAT) commands, generate a sense block if
|
/* For ATA pass thru (SAT) commands, generate a sense block if
|
||||||
* user mandated it or if there's an error. Note that if we
|
* user mandated it or if there's an error. Note that if we
|
||||||
@ -1205,8 +1215,8 @@ static int ata_scsi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
|
|||||||
* whether the command completed successfully or not. If there
|
* whether the command completed successfully or not. If there
|
||||||
* was no error, SK, ASC and ASCQ will all be zero.
|
* was no error, SK, ASC and ASCQ will all be zero.
|
||||||
*/
|
*/
|
||||||
if (((cmd->cmnd[0] == ATA_16) || (cmd->cmnd[0] == ATA_12)) &&
|
if (((cdb[0] == ATA_16) || (cdb[0] == ATA_12)) &&
|
||||||
((cmd->cmnd[2] & 0x20) || need_sense)) {
|
((cdb[2] & 0x20) || need_sense)) {
|
||||||
ata_gen_ata_desc_sense(qc);
|
ata_gen_ata_desc_sense(qc);
|
||||||
} else {
|
} else {
|
||||||
if (!need_sense) {
|
if (!need_sense) {
|
||||||
@ -1989,21 +1999,13 @@ void atapi_request_sense(struct ata_port *ap, struct ata_device *dev,
|
|||||||
DPRINTK("EXIT\n");
|
DPRINTK("EXIT\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int atapi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
|
static int atapi_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask)
|
||||||
{
|
{
|
||||||
struct scsi_cmnd *cmd = qc->scsicmd;
|
struct scsi_cmnd *cmd = qc->scsicmd;
|
||||||
|
|
||||||
VPRINTK("ENTER, drv_stat == 0x%x\n", drv_stat);
|
VPRINTK("ENTER, err_mask 0x%X\n", err_mask);
|
||||||
|
|
||||||
if (unlikely(drv_stat & (ATA_BUSY | ATA_DRQ)))
|
if (unlikely(err_mask & AC_ERR_DEV)) {
|
||||||
/* FIXME: not quite right; we don't want the
|
|
||||||
* translation of taskfile registers into
|
|
||||||
* a sense descriptors, since that's only
|
|
||||||
* correct for ATA, not ATAPI
|
|
||||||
*/
|
|
||||||
ata_gen_ata_desc_sense(qc);
|
|
||||||
|
|
||||||
else if (unlikely(drv_stat & ATA_ERR)) {
|
|
||||||
DPRINTK("request check condition\n");
|
DPRINTK("request check condition\n");
|
||||||
|
|
||||||
/* FIXME: command completion with check condition
|
/* FIXME: command completion with check condition
|
||||||
@ -2020,6 +2022,14 @@ static int atapi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (unlikely(err_mask))
|
||||||
|
/* FIXME: not quite right; we don't want the
|
||||||
|
* translation of taskfile registers into
|
||||||
|
* a sense descriptors, since that's only
|
||||||
|
* correct for ATA, not ATAPI
|
||||||
|
*/
|
||||||
|
ata_gen_ata_desc_sense(qc);
|
||||||
|
|
||||||
else {
|
else {
|
||||||
u8 *scsicmd = cmd->cmnd;
|
u8 *scsicmd = cmd->cmnd;
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ struct ata_scsi_args {
|
|||||||
|
|
||||||
/* libata-core.c */
|
/* libata-core.c */
|
||||||
extern int atapi_enabled;
|
extern int atapi_enabled;
|
||||||
extern int ata_qc_complete_noop(struct ata_queued_cmd *qc, u8 drv_stat);
|
extern int ata_qc_complete_noop(struct ata_queued_cmd *qc, unsigned int err_mask);
|
||||||
extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
|
extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
|
||||||
struct ata_device *dev);
|
struct ata_device *dev);
|
||||||
extern void ata_rwcmd_protocol(struct ata_queued_cmd *qc);
|
extern void ata_rwcmd_protocol(struct ata_queued_cmd *qc);
|
||||||
|
@ -451,7 +451,7 @@ static inline unsigned int adma_intr_pkt(struct ata_host_set *host_set)
|
|||||||
struct adma_port_priv *pp;
|
struct adma_port_priv *pp;
|
||||||
struct ata_queued_cmd *qc;
|
struct ata_queued_cmd *qc;
|
||||||
void __iomem *chan = ADMA_REGS(mmio_base, port_no);
|
void __iomem *chan = ADMA_REGS(mmio_base, port_no);
|
||||||
u8 drv_stat = 0, status = readb(chan + ADMA_STATUS);
|
u8 status = readb(chan + ADMA_STATUS);
|
||||||
|
|
||||||
if (status == 0)
|
if (status == 0)
|
||||||
continue;
|
continue;
|
||||||
@ -464,11 +464,14 @@ static inline unsigned int adma_intr_pkt(struct ata_host_set *host_set)
|
|||||||
continue;
|
continue;
|
||||||
qc = ata_qc_from_tag(ap, ap->active_tag);
|
qc = ata_qc_from_tag(ap, ap->active_tag);
|
||||||
if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
|
if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
|
||||||
|
unsigned int err_mask = 0;
|
||||||
|
|
||||||
if ((status & (aPERR | aPSD | aUIRQ)))
|
if ((status & (aPERR | aPSD | aUIRQ)))
|
||||||
drv_stat = ATA_ERR;
|
err_mask = AC_ERR_OTHER;
|
||||||
else if (pp->pkt[0] != cDONE)
|
else if (pp->pkt[0] != cDONE)
|
||||||
drv_stat = ATA_ERR;
|
err_mask = AC_ERR_OTHER;
|
||||||
ata_qc_complete(qc, drv_stat);
|
|
||||||
|
ata_qc_complete(qc, err_mask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return handled;
|
return handled;
|
||||||
@ -498,7 +501,7 @@ static inline unsigned int adma_intr_mmio(struct ata_host_set *host_set)
|
|||||||
|
|
||||||
/* complete taskfile transaction */
|
/* complete taskfile transaction */
|
||||||
pp->state = adma_state_idle;
|
pp->state = adma_state_idle;
|
||||||
ata_qc_complete(qc, status);
|
ata_qc_complete(qc, ac_err_mask(status));
|
||||||
handled = 1;
|
handled = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1065,6 +1065,7 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
|
|||||||
struct ata_queued_cmd *qc;
|
struct ata_queued_cmd *qc;
|
||||||
u32 hc_irq_cause;
|
u32 hc_irq_cause;
|
||||||
int shift, port, port0, hard_port, handled;
|
int shift, port, port0, hard_port, handled;
|
||||||
|
unsigned int err_mask;
|
||||||
u8 ata_status = 0;
|
u8 ata_status = 0;
|
||||||
|
|
||||||
if (hc == 0) {
|
if (hc == 0) {
|
||||||
@ -1100,15 +1101,15 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
|
|||||||
handled++;
|
handled++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err_mask = ac_err_mask(ata_status);
|
||||||
|
|
||||||
shift = port << 1; /* (port * 2) */
|
shift = port << 1; /* (port * 2) */
|
||||||
if (port >= MV_PORTS_PER_HC) {
|
if (port >= MV_PORTS_PER_HC) {
|
||||||
shift++; /* skip bit 8 in the HC Main IRQ reg */
|
shift++; /* skip bit 8 in the HC Main IRQ reg */
|
||||||
}
|
}
|
||||||
if ((PORT0_ERR << shift) & relevant) {
|
if ((PORT0_ERR << shift) & relevant) {
|
||||||
mv_err_intr(ap);
|
mv_err_intr(ap);
|
||||||
/* OR in ATA_ERR to ensure libata knows we took one */
|
err_mask |= AC_ERR_OTHER;
|
||||||
ata_status = readb((void __iomem *)
|
|
||||||
ap->ioaddr.status_addr) | ATA_ERR;
|
|
||||||
handled++;
|
handled++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1118,7 +1119,7 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
|
|||||||
VPRINTK("port %u IRQ found for qc, "
|
VPRINTK("port %u IRQ found for qc, "
|
||||||
"ata_status 0x%x\n", port,ata_status);
|
"ata_status 0x%x\n", port,ata_status);
|
||||||
/* mark qc status appropriately */
|
/* mark qc status appropriately */
|
||||||
ata_qc_complete(qc, ata_status);
|
ata_qc_complete(qc, err_mask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1294,7 +1295,7 @@ static void mv_eng_timeout(struct ata_port *ap)
|
|||||||
*/
|
*/
|
||||||
spin_lock_irqsave(&ap->host_set->lock, flags);
|
spin_lock_irqsave(&ap->host_set->lock, flags);
|
||||||
qc->scsidone = scsi_finish_command;
|
qc->scsidone = scsi_finish_command;
|
||||||
ata_qc_complete(qc, ATA_ERR);
|
ata_qc_complete(qc, AC_ERR_OTHER);
|
||||||
spin_unlock_irqrestore(&ap->host_set->lock, flags);
|
spin_unlock_irqrestore(&ap->host_set->lock, flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -399,7 +399,8 @@ static void pdc_eng_timeout(struct ata_port *ap)
|
|||||||
case ATA_PROT_DMA:
|
case ATA_PROT_DMA:
|
||||||
case ATA_PROT_NODATA:
|
case ATA_PROT_NODATA:
|
||||||
printk(KERN_ERR "ata%u: command timeout\n", ap->id);
|
printk(KERN_ERR "ata%u: command timeout\n", ap->id);
|
||||||
ata_qc_complete(qc, ata_wait_idle(ap) | ATA_ERR);
|
drv_stat = ata_wait_idle(ap);
|
||||||
|
ata_qc_complete(qc, __ac_err_mask(drv_stat));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -408,7 +409,7 @@ static void pdc_eng_timeout(struct ata_port *ap)
|
|||||||
printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n",
|
printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n",
|
||||||
ap->id, qc->tf.command, drv_stat);
|
ap->id, qc->tf.command, drv_stat);
|
||||||
|
|
||||||
ata_qc_complete(qc, drv_stat);
|
ata_qc_complete(qc, ac_err_mask(drv_stat));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -420,24 +421,21 @@ out:
|
|||||||
static inline unsigned int pdc_host_intr( struct ata_port *ap,
|
static inline unsigned int pdc_host_intr( struct ata_port *ap,
|
||||||
struct ata_queued_cmd *qc)
|
struct ata_queued_cmd *qc)
|
||||||
{
|
{
|
||||||
u8 status;
|
unsigned int handled = 0, err_mask = 0;
|
||||||
unsigned int handled = 0, have_err = 0;
|
|
||||||
u32 tmp;
|
u32 tmp;
|
||||||
void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr + PDC_GLOBAL_CTL;
|
void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr + PDC_GLOBAL_CTL;
|
||||||
|
|
||||||
tmp = readl(mmio);
|
tmp = readl(mmio);
|
||||||
if (tmp & PDC_ERR_MASK) {
|
if (tmp & PDC_ERR_MASK) {
|
||||||
have_err = 1;
|
err_mask = AC_ERR_DEV;
|
||||||
pdc_reset_port(ap);
|
pdc_reset_port(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (qc->tf.protocol) {
|
switch (qc->tf.protocol) {
|
||||||
case ATA_PROT_DMA:
|
case ATA_PROT_DMA:
|
||||||
case ATA_PROT_NODATA:
|
case ATA_PROT_NODATA:
|
||||||
status = ata_wait_idle(ap);
|
err_mask |= ac_err_mask(ata_wait_idle(ap));
|
||||||
if (have_err)
|
ata_qc_complete(qc, err_mask);
|
||||||
status |= ATA_ERR;
|
|
||||||
ata_qc_complete(qc, status);
|
|
||||||
handled = 1;
|
handled = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -400,11 +400,12 @@ static inline unsigned int qs_intr_pkt(struct ata_host_set *host_set)
|
|||||||
qc = ata_qc_from_tag(ap, ap->active_tag);
|
qc = ata_qc_from_tag(ap, ap->active_tag);
|
||||||
if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
|
if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
|
||||||
switch (sHST) {
|
switch (sHST) {
|
||||||
case 0: /* sucessful CPB */
|
case 0: /* successful CPB */
|
||||||
case 3: /* device error */
|
case 3: /* device error */
|
||||||
pp->state = qs_state_idle;
|
pp->state = qs_state_idle;
|
||||||
qs_enter_reg_mode(qc->ap);
|
qs_enter_reg_mode(qc->ap);
|
||||||
ata_qc_complete(qc, sDST);
|
ata_qc_complete(qc,
|
||||||
|
ac_err_mask(sDST));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -441,7 +442,7 @@ static inline unsigned int qs_intr_mmio(struct ata_host_set *host_set)
|
|||||||
|
|
||||||
/* complete taskfile transaction */
|
/* complete taskfile transaction */
|
||||||
pp->state = qs_state_idle;
|
pp->state = qs_state_idle;
|
||||||
ata_qc_complete(qc, status);
|
ata_qc_complete(qc, ac_err_mask(status));
|
||||||
handled = 1;
|
handled = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -498,7 +498,7 @@ static void sil24_eng_timeout(struct ata_port *ap)
|
|||||||
|
|
||||||
qc = ata_qc_from_tag(ap, ap->active_tag);
|
qc = ata_qc_from_tag(ap, ap->active_tag);
|
||||||
if (!qc) {
|
if (!qc) {
|
||||||
printk(KERN_ERR "ata%u: BUG: tiemout without command\n",
|
printk(KERN_ERR "ata%u: BUG: timeout without command\n",
|
||||||
ap->id);
|
ap->id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -512,7 +512,7 @@ static void sil24_eng_timeout(struct ata_port *ap)
|
|||||||
*/
|
*/
|
||||||
printk(KERN_ERR "ata%u: command timeout\n", ap->id);
|
printk(KERN_ERR "ata%u: command timeout\n", ap->id);
|
||||||
qc->scsidone = scsi_finish_command;
|
qc->scsidone = scsi_finish_command;
|
||||||
ata_qc_complete(qc, ATA_ERR);
|
ata_qc_complete(qc, AC_ERR_OTHER);
|
||||||
|
|
||||||
sil24_reset_controller(ap);
|
sil24_reset_controller(ap);
|
||||||
}
|
}
|
||||||
@ -523,6 +523,7 @@ static void sil24_error_intr(struct ata_port *ap, u32 slot_stat)
|
|||||||
struct sil24_port_priv *pp = ap->private_data;
|
struct sil24_port_priv *pp = ap->private_data;
|
||||||
void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
|
void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
|
||||||
u32 irq_stat, cmd_err, sstatus, serror;
|
u32 irq_stat, cmd_err, sstatus, serror;
|
||||||
|
unsigned int err_mask;
|
||||||
|
|
||||||
irq_stat = readl(port + PORT_IRQ_STAT);
|
irq_stat = readl(port + PORT_IRQ_STAT);
|
||||||
writel(irq_stat, port + PORT_IRQ_STAT); /* clear irq */
|
writel(irq_stat, port + PORT_IRQ_STAT); /* clear irq */
|
||||||
@ -550,17 +551,18 @@ static void sil24_error_intr(struct ata_port *ap, u32 slot_stat)
|
|||||||
* Device is reporting error, tf registers are valid.
|
* Device is reporting error, tf registers are valid.
|
||||||
*/
|
*/
|
||||||
sil24_update_tf(ap);
|
sil24_update_tf(ap);
|
||||||
|
err_mask = ac_err_mask(pp->tf.command);
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* Other errors. libata currently doesn't have any
|
* Other errors. libata currently doesn't have any
|
||||||
* mechanism to report these errors. Just turn on
|
* mechanism to report these errors. Just turn on
|
||||||
* ATA_ERR.
|
* ATA_ERR.
|
||||||
*/
|
*/
|
||||||
pp->tf.command = ATA_ERR;
|
err_mask = AC_ERR_OTHER;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qc)
|
if (qc)
|
||||||
ata_qc_complete(qc, pp->tf.command);
|
ata_qc_complete(qc, err_mask);
|
||||||
|
|
||||||
sil24_reset_controller(ap);
|
sil24_reset_controller(ap);
|
||||||
}
|
}
|
||||||
@ -585,7 +587,7 @@ static inline void sil24_host_intr(struct ata_port *ap)
|
|||||||
sil24_update_tf(ap);
|
sil24_update_tf(ap);
|
||||||
|
|
||||||
if (qc)
|
if (qc)
|
||||||
ata_qc_complete(qc, pp->tf.command);
|
ata_qc_complete(qc, ac_err_mask(pp->tf.command));
|
||||||
} else
|
} else
|
||||||
sil24_error_intr(ap, slot_stat);
|
sil24_error_intr(ap, slot_stat);
|
||||||
}
|
}
|
||||||
|
@ -718,7 +718,7 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
|
|||||||
VPRINTK("ata%u: read hdma, 0x%x 0x%x\n", ap->id,
|
VPRINTK("ata%u: read hdma, 0x%x 0x%x\n", ap->id,
|
||||||
readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
|
readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
|
||||||
/* get drive status; clear intr; complete txn */
|
/* get drive status; clear intr; complete txn */
|
||||||
ata_qc_complete(qc, ata_wait_idle(ap));
|
ata_qc_complete(qc, ac_err_mask(ata_wait_idle(ap)));
|
||||||
pdc20621_pop_hdma(qc);
|
pdc20621_pop_hdma(qc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -756,7 +756,7 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
|
|||||||
VPRINTK("ata%u: write ata, 0x%x 0x%x\n", ap->id,
|
VPRINTK("ata%u: write ata, 0x%x 0x%x\n", ap->id,
|
||||||
readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
|
readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
|
||||||
/* get drive status; clear intr; complete txn */
|
/* get drive status; clear intr; complete txn */
|
||||||
ata_qc_complete(qc, ata_wait_idle(ap));
|
ata_qc_complete(qc, ac_err_mask(ata_wait_idle(ap)));
|
||||||
pdc20621_pop_hdma(qc);
|
pdc20621_pop_hdma(qc);
|
||||||
}
|
}
|
||||||
handled = 1;
|
handled = 1;
|
||||||
@ -766,7 +766,7 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
|
|||||||
|
|
||||||
status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
|
status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
|
||||||
DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status);
|
DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status);
|
||||||
ata_qc_complete(qc, status);
|
ata_qc_complete(qc, ac_err_mask(status));
|
||||||
handled = 1;
|
handled = 1;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -881,7 +881,7 @@ static void pdc_eng_timeout(struct ata_port *ap)
|
|||||||
case ATA_PROT_DMA:
|
case ATA_PROT_DMA:
|
||||||
case ATA_PROT_NODATA:
|
case ATA_PROT_NODATA:
|
||||||
printk(KERN_ERR "ata%u: command timeout\n", ap->id);
|
printk(KERN_ERR "ata%u: command timeout\n", ap->id);
|
||||||
ata_qc_complete(qc, ata_wait_idle(ap) | ATA_ERR);
|
ata_qc_complete(qc, __ac_err_mask(ata_wait_idle(ap)));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -890,7 +890,7 @@ static void pdc_eng_timeout(struct ata_port *ap)
|
|||||||
printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n",
|
printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n",
|
||||||
ap->id, qc->tf.command, drv_stat);
|
ap->id, qc->tf.command, drv_stat);
|
||||||
|
|
||||||
ata_qc_complete(qc, drv_stat);
|
ata_qc_complete(qc, ac_err_mask(drv_stat));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,6 +172,13 @@ enum hsm_task_states {
|
|||||||
HSM_ST_ERR,
|
HSM_ST_ERR,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum ata_completion_errors {
|
||||||
|
AC_ERR_OTHER = (1 << 0),
|
||||||
|
AC_ERR_DEV = (1 << 1),
|
||||||
|
AC_ERR_ATA_BUS = (1 << 2),
|
||||||
|
AC_ERR_HOST_BUS = (1 << 3),
|
||||||
|
};
|
||||||
|
|
||||||
/* forward declarations */
|
/* forward declarations */
|
||||||
struct scsi_device;
|
struct scsi_device;
|
||||||
struct ata_port_operations;
|
struct ata_port_operations;
|
||||||
@ -179,7 +186,7 @@ struct ata_port;
|
|||||||
struct ata_queued_cmd;
|
struct ata_queued_cmd;
|
||||||
|
|
||||||
/* typedefs */
|
/* typedefs */
|
||||||
typedef int (*ata_qc_cb_t) (struct ata_queued_cmd *qc, u8 drv_stat);
|
typedef int (*ata_qc_cb_t) (struct ata_queued_cmd *qc, unsigned int err_mask);
|
||||||
|
|
||||||
struct ata_ioports {
|
struct ata_ioports {
|
||||||
unsigned long cmd_addr;
|
unsigned long cmd_addr;
|
||||||
@ -453,7 +460,7 @@ extern void ata_bmdma_start (struct ata_queued_cmd *qc);
|
|||||||
extern void ata_bmdma_stop(struct ata_queued_cmd *qc);
|
extern void ata_bmdma_stop(struct ata_queued_cmd *qc);
|
||||||
extern u8 ata_bmdma_status(struct ata_port *ap);
|
extern u8 ata_bmdma_status(struct ata_port *ap);
|
||||||
extern void ata_bmdma_irq_clear(struct ata_port *ap);
|
extern void ata_bmdma_irq_clear(struct ata_port *ap);
|
||||||
extern void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat);
|
extern void ata_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask);
|
||||||
extern void ata_eng_timeout(struct ata_port *ap);
|
extern void ata_eng_timeout(struct ata_port *ap);
|
||||||
extern void ata_scsi_simulate(u16 *id, struct scsi_cmnd *cmd,
|
extern void ata_scsi_simulate(u16 *id, struct scsi_cmnd *cmd,
|
||||||
void (*done)(struct scsi_cmnd *));
|
void (*done)(struct scsi_cmnd *));
|
||||||
@ -716,4 +723,21 @@ static inline int ata_try_flush_cache(const struct ata_device *dev)
|
|||||||
ata_id_has_flush_ext(dev->id);
|
ata_id_has_flush_ext(dev->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline unsigned int ac_err_mask(u8 status)
|
||||||
|
{
|
||||||
|
if (status & ATA_BUSY)
|
||||||
|
return AC_ERR_ATA_BUS;
|
||||||
|
if (status & (ATA_ERR | ATA_DF))
|
||||||
|
return AC_ERR_DEV;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned int __ac_err_mask(u8 status)
|
||||||
|
{
|
||||||
|
unsigned int mask = ac_err_mask(status);
|
||||||
|
if (mask == 0)
|
||||||
|
return AC_ERR_OTHER;
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* __LINUX_LIBATA_H__ */
|
#endif /* __LINUX_LIBATA_H__ */
|
||||||
|
Loading…
Reference in New Issue
Block a user