more qc_complete work
PATCH 1/1 more qc_complete work
Here's the latest work, updating ata_qc_complete() API to supply better error handling information, and eliminating the sometimes-emulated drv_stat argument.
drivers/scsi/ahci.c +6 -2
@@ -593,6 +593,10 @@ static void ahci_eng_timeout(struct ata_printk (KERN_ERR "ata%u: BUG: timeout without command\n" , ap->id); }else { +/* +* should never occur +*/ +/* hack alert! We cannot use the supplied completion * function from inside the ->eh_strategy_handler() thread. * libata is the only user of ->eh_strategy_handler() in
@@ -600,7 +604,7 @@ static void ahci_eng_timeout(struct ata_* not being called from the SCSI EH. */ 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);
@@ -629,7 +633,7 @@ static inline int ahci_host_intr(structif (status &PORT_IRQ_FATAL ) {ahci_intr_error (ap, status);if (qc) -ata_qc_complete (qc,ATA_ERR ); +ata_qc_complete (qc,AC_ERR_OTHER ); }return 1 ;
drivers/scsi/libata-core.c +15 -16
@@ -2669,7 +2669,7 @@ static int ata_sg_setup(struct ata_queue* 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;unsigned long flags;
@@ -2677,7 +2677,7 @@ void ata_poll_qc_complete(struct ata_quespin_lock_irqsave (&ap->host_set->lock, flags); ap->flags &= ~ATA_FLAG_NOINTR ;ata_irq_on (ap); -ata_qc_complete (qc, drv_stat); +ata_qc_complete (qc, err_mask);spin_unlock_irqrestore (&ap->host_set->lock, flags); }
@@ -2774,7 +2774,7 @@ static int ata_pio_complete (struct ata_ 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 */
@@ -3142,18 +3142,15 @@ static void ata_pio_block(struct ata_porstatic void ata_pio_error (struct ata_port *ap) {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);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 ; -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)
@@ -3276,7 +3273,7 @@ static void ata_qc_timeout(struct ata_qu ap->id, qc->tf.command, drv_stat, host_stat);/* complete taskfile transaction */ -ata_qc_complete (qc, drv_stat); +ata_qc_complete (qc,ac_err_mask (drv_stat));break ; }
@@ -3381,7 +3378,7 @@ struct ata_queued_cmd *ata_qc_new_init(sreturn 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 ; }
@@ -3440,7 +3437,7 @@ void ata_qc_free(struct ata_queued_cmd ** 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;
@@ -3457,7 +3454,7 @@ void ata_qc_complete(struct ata_queued_c qc->flags &= ~ATA_QCFLAG_ACTIVE ;/* 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), * return immediately
@@ -3895,7 +3892,7 @@ inline unsigned int ata_host_intr (struc ap->ops->irq_clear (ap);/* complete taskfile transaction */ -ata_qc_complete (qc, status); +ata_qc_complete (qc,ac_err_mask (status));break ;default :
@@ -3990,7 +3987,7 @@ static void atapi_packet_task(void *_dat/* sleep-wait for BSY to clear */ DPRINTK ("busy wait\n" );if (ata_busy_sleep (ap,ATA_TMOUT_CDB_QUICK ,ATA_TMOUT_CDB )) - goto err_out; + goto err_out_status;/* make sure DRQ is set */ status =ata_chk_status (ap);
@@ -4027,8 +4024,10 @@ static void atapi_packet_task(void *_datreturn ; +err_out_status: + status =ata_chk_status (ap); err_out: -ata_poll_qc_complete (qc,ATA_ERR ); +ata_poll_qc_complete (qc,__ac_err_mask (status)); }
drivers/scsi/libata-scsi.c +28 -18
100 lines not on this page · raw message
drivers/scsi/libata.h +1 -1
@@ -39,7 +39,7 @@ struct ata_scsi_args {/* libata-core.c */ 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,struct ata_device *dev);extern void ata_rwcmd_protocol (struct ata_queued_cmd *qc);
drivers/scsi/pdc_adma.c +8 -5
@@ -451,7 +451,7 @@ static inline unsigned int adma_intr_pktstruct adma_port_priv *pp;struct ata_queued_cmd *qc;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 )continue ;
@@ -464,11 +464,14 @@ static inline unsigned int adma_intr_pktcontinue ; qc =ata_qc_from_tag (ap, ap->active_tag);if (qc && (!(qc->tf.ctl &ATA_NIEN ))) { +unsigned int err_mask =0 ; +if ((status & (aPERR | aPSD | aUIRQ))) - drv_stat =ATA_ERR ; + err_mask =AC_ERR_OTHER ;else if (pp->pkt[0 ] != cDONE) - drv_stat =ATA_ERR ; -ata_qc_complete (qc, drv_stat); + err_mask =AC_ERR_OTHER ; + +ata_qc_complete (qc, err_mask); } }return handled;
@@ -498,7 +501,7 @@ static inline unsigned int adma_intr_mmi/* complete taskfile transaction */ pp->state = adma_state_idle; -ata_qc_complete (qc, status); +ata_qc_complete (qc,ac_err_mask (status)); handled =1 ; } }
drivers/scsi/sata_mv.c +6 -5
@@ -1065,6 +1065,7 @@ static void mv_host_intr(struct ata_hoststruct ata_queued_cmd *qc;u32 hc_irq_cause;int shift, port, port0, hard_port, handled; +unsigned int err_mask;u8 ata_status =0 ;if (hc ==0 ) {
@@ -1100,15 +1101,15 @@ static void mv_host_intr(struct ata_host handled++; } + err_mask =ac_err_mask (ata_status); + shift = port <<1 ;/* (port * 2) */ if (port >=MV_PORTS_PER_HC ) { shift++;/* skip bit 8 in the HC Main IRQ reg */ }if ((PORT0_ERR << shift) & relevant) {mv_err_intr (ap); -/* OR in ATA_ERR to ensure libata knows we took one */ - ata_status =readb ((void __iomem *) - ap->ioaddr.status_addr) |ATA_ERR ; + err_mask |=AC_ERR_OTHER ; handled++; }
@@ -1118,7 +1119,7 @@ static void mv_host_intr(struct ata_hostVPRINTK ("port %u IRQ found for qc, " "ata_status 0x%x\n" , port,ata_status);/* 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_po*/ spin_lock_irqsave (&ap->host_set->lock, flags); 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); } }
drivers/scsi/sata_promise.c +7 -9
@@ -399,7 +399,8 @@ static void pdc_eng_timeout(struct ata_pcase ATA_PROT_DMA :case ATA_PROT_NODATA :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 ;default :
@@ -408,7 +409,7 @@ static void pdc_eng_timeout(struct ata_pprintk (KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n" , ap->id, qc->tf.command, drv_stat); -ata_qc_complete (qc, drv_stat); +ata_qc_complete (qc,ac_err_mask (drv_stat));break ; }
@@ -420,24 +421,21 @@ out:static inline unsigned int pdc_host_intr (struct ata_port *ap,struct ata_queued_cmd *qc) { -u8 status; -unsigned int handled =0 , have_err =0 ; +unsigned int handled =0 , err_mask =0 ;u32 tmp;void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr +PDC_GLOBAL_CTL ; tmp =readl (mmio);if (tmp &PDC_ERR_MASK ) { - have_err =1 ; + err_mask =AC_ERR_DEV ;pdc_reset_port (ap); }switch (qc->tf.protocol) {case ATA_PROT_DMA :case ATA_PROT_NODATA : - status =ata_wait_idle (ap); -if (have_err) - status |=ATA_ERR ; -ata_qc_complete (qc, status); + err_mask |=ac_err_mask (ata_wait_idle (ap)); +ata_qc_complete (qc, err_mask); handled =1 ;break ;
drivers/scsi/sata_qstor.c +4 -3
@@ -400,11 +400,12 @@ static inline unsigned int qs_intr_pkt(s qc =ata_qc_from_tag (ap, ap->active_tag);if (qc && (!(qc->tf.ctl &ATA_NIEN ))) {switch (sHST) { -case 0 :/* sucessful CPB */ +case 0 :/* successful CPB */ case 3 :/* device error */ pp->state = qs_state_idle;qs_enter_reg_mode (qc->ap); -ata_qc_complete (qc, sDST); +ata_qc_complete (qc, +ac_err_mask (sDST));break ;default :break ;
@@ -441,7 +442,7 @@ static inline unsigned int qs_intr_mmio(/* complete taskfile transaction */ pp->state = qs_state_idle; -ata_qc_complete (qc, status); +ata_qc_complete (qc,ac_err_mask (status)); handled =1 ; } }
drivers/scsi/sata_sil24.c +7 -5
@@ -498,7 +498,7 @@ static void sil24_eng_timeout(struct ata qc =ata_qc_from_tag (ap, ap->active_tag);if (!qc) { -printk (KERN_ERR "ata%u: BUG: tiemout without command\n" , +printk (KERN_ERR "ata%u: BUG: timeout without command\n" , ap->id);return ; }
@@ -512,7 +512,7 @@ static void sil24_eng_timeout(struct ata*/ printk (KERN_ERR "ata%u: command timeout\n" , ap->id); qc->scsidone = scsi_finish_command; -ata_qc_complete (qc,ATA_ERR ); +ata_qc_complete (qc,AC_ERR_OTHER );sil24_reset_controller (ap); }
@@ -523,6 +523,7 @@ static void sil24_error_intr(struct ata_struct sil24_port_priv *pp = ap->private_data;void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;u32 irq_stat, cmd_err, sstatus, serror; +unsigned int err_mask; irq_stat =readl (port +PORT_IRQ_STAT );writel (irq_stat, port +PORT_IRQ_STAT );/* clear irq */
@@ -550,17 +551,18 @@ static void sil24_error_intr(struct ata_* Device is reporting error, tf registers are valid. */ sil24_update_tf (ap); + err_mask =ac_err_mask (pp->tf.command); }else {/* * Other errors. libata currently doesn't have any * mechanism to report these errors. Just turn on * ATA_ERR. */ - pp->tf.command =ATA_ERR ; + err_mask =AC_ERR_OTHER ; }if (qc) -ata_qc_complete (qc, pp->tf.command); +ata_qc_complete (qc, err_mask);sil24_reset_controller (ap); }
@@ -585,7 +587,7 @@ static inline void sil24_host_intr(strucsil24_update_tf (ap);if (qc) -ata_qc_complete (qc, pp->tf.command); +ata_qc_complete (qc,ac_err_mask (pp->tf.command)); }else sil24_error_intr (ap, slot_stat); }
drivers/scsi/sata_sx4.c +5 -5
@@ -718,7 +718,7 @@ static inline unsigned int pdc20621_hostVPRINTK ("ata%u: read hdma, 0x%x 0x%x\n" , ap->id,readl (mmio +0x104 ),readl (mmio +PDC_HDMA_CTLSTAT ));/* 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); }
@@ -756,7 +756,7 @@ static inline unsigned int pdc20621_hostVPRINTK ("ata%u: write ata, 0x%x 0x%x\n" , ap->id,readl (mmio +0x104 ),readl (mmio +PDC_HDMA_CTLSTAT ));/* 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); } handled =1 ;
@@ -766,7 +766,7 @@ static inline unsigned int pdc20621_host status =ata_busy_wait (ap,ATA_BUSY |ATA_DRQ ,1000 );DPRINTK ("BUS_NODATA (drv_stat 0x%X)\n" , status); -ata_qc_complete (qc, status); +ata_qc_complete (qc,ac_err_mask (status)); handled =1 ; }else {
@@ -881,7 +881,7 @@ static void pdc_eng_timeout(struct ata_pcase ATA_PROT_DMA :case ATA_PROT_NODATA :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 ;default :
@@ -890,7 +890,7 @@ static void pdc_eng_timeout(struct ata_pprintk (KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n" , ap->id, qc->tf.command, drv_stat); -ata_qc_complete (qc, drv_stat); +ata_qc_complete (qc,ac_err_mask (drv_stat));break ; }
include/linux/libata.h +26 -2
@@ -172,6 +172,13 @@ enum hsm_task_states { 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 */ struct scsi_device ;struct ata_port_operations ;
@@ -179,7 +186,7 @@ struct ata_port;struct ata_queued_cmd ;/* 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 {unsigned long cmd_addr;
@@ -453,7 +460,7 @@ extern void ata_bmdma_start (struct ata_extern void ata_bmdma_stop (struct ata_queued_cmd *qc);extern u8 ata_bmdma_status (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_scsi_simulate (u16 *id,struct scsi_cmnd *cmd,void (*done)(struct scsi_cmnd *));
@@ -716,4 +723,21 @@ static inline int ata_try_flush_cache(co 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__ */