aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libata-core.c
diff options
context:
space:
mode:
authorAlbert Lee <albertcc@tw.ibm.com>2006-03-25 04:48:02 -0500
committerJeff Garzik <jeff@garzik.org>2006-03-29 17:21:54 -0500
commitbb5cb290f095f17f88c912e3da35adf5b2d9500b (patch)
treecf8cbbfc3419988f869b4527c8be5d63361b3eb2 /drivers/scsi/libata-core.c
parent6912ccd5a4a095d71fd7215ef2abea877c8fed6f (diff)
[PATCH] libata-dev: Let ata_hsm_move() work with both irq-pio and polling pio
Let ata_hsm_move() work with both irq-pio and polling pio codepath. Changes: - add a new parameter "in_wq" for polling pio - add return value "poll_next" to tell polling pio task whether the HSM is finished - merge code from ata_pio_first_block() to the HSM_ST_FIRST state. - call ata_poll_qc_complete() if called from the workqueue Signed-off-by: Albert Lee <albertcc@tw.ibm.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/scsi/libata-core.c')
-rw-r--r--drivers/scsi/libata-core.c87
1 files changed, 81 insertions, 6 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 094c7907534a..33b39d3ce2d3 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -3805,11 +3805,36 @@ static void ata_pio_error(struct ata_port *ap)
3805 ata_poll_qc_complete(qc); 3805 ata_poll_qc_complete(qc);
3806} 3806}
3807 3807
3808static void ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc, 3808/**
3809 u8 status) 3809 * ata_hsm_move - move the HSM to the next state.
3810 * @ap: the target ata_port
3811 * @qc: qc on going
3812 * @status: current device status
3813 * @in_wq: 1 if called from workqueue, 0 otherwise
3814 *
3815 * RETURNS:
3816 * 1 when poll next status needed, 0 otherwise.
3817 */
3818
3819static int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
3820 u8 status, int in_wq)
3810{ 3821{
3822 unsigned long flags = 0;
3823 int poll_next;
3824
3811 WARN_ON((qc->flags & ATA_QCFLAG_ACTIVE) == 0); 3825 WARN_ON((qc->flags & ATA_QCFLAG_ACTIVE) == 0);
3812 3826
3827 /* Make sure ata_qc_issue_prot() does not throw things
3828 * like DMA polling into the workqueue. Notice that
3829 * in_wq is not equivalent to (qc->tf.flags & ATA_TFLAG_POLLING).
3830 */
3831 WARN_ON(in_wq != ((qc->tf.flags & ATA_TFLAG_POLLING) ||
3832 (ap->hsm_task_state == HSM_ST_FIRST &&
3833 ((qc->tf.protocol == ATA_PROT_PIO &&
3834 (qc->tf.flags & ATA_TFLAG_WRITE)) ||
3835 (is_atapi_taskfile(&qc->tf) &&
3836 !(qc->dev->flags & ATA_DFLAG_CDB_INTR))))));
3837
3813 /* check error */ 3838 /* check error */
3814 if (unlikely(status & (ATA_ERR | ATA_DF))) { 3839 if (unlikely(status & (ATA_ERR | ATA_DF))) {
3815 qc->err_mask |= AC_ERR_DEV; 3840 qc->err_mask |= AC_ERR_DEV;
@@ -3819,6 +3844,14 @@ static void ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
3819fsm_start: 3844fsm_start:
3820 switch (ap->hsm_task_state) { 3845 switch (ap->hsm_task_state) {
3821 case HSM_ST_FIRST: 3846 case HSM_ST_FIRST:
3847 /* Send first data block or PACKET CDB */
3848
3849 /* If polling, we will stay in the work queue after
3850 * sending the data. Otherwise, interrupt handler
3851 * takes over after sending the data.
3852 */
3853 poll_next = (qc->tf.flags & ATA_TFLAG_POLLING);
3854
3822 /* check device status */ 3855 /* check device status */
3823 if (unlikely((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ)) { 3856 if (unlikely((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ)) {
3824 /* Wrong status. Let EH handle this */ 3857 /* Wrong status. Let EH handle this */
@@ -3827,8 +3860,36 @@ fsm_start:
3827 goto fsm_start; 3860 goto fsm_start;
3828 } 3861 }
3829 3862
3830 atapi_send_cdb(ap, qc); 3863 /* Send the CDB (atapi) or the first data block (ata pio out).
3864 * During the state transition, interrupt handler shouldn't
3865 * be invoked before the data transfer is complete and
3866 * hsm_task_state is changed. Hence, the following locking.
3867 */
3868 if (in_wq)
3869 spin_lock_irqsave(&ap->host_set->lock, flags);
3870
3871 if (qc->tf.protocol == ATA_PROT_PIO) {
3872 /* PIO data out protocol.
3873 * send first data block.
3874 */
3831 3875
3876 /* ata_pio_sectors() might change the state
3877 * to HSM_ST_LAST. so, the state is changed here
3878 * before ata_pio_sectors().
3879 */
3880 ap->hsm_task_state = HSM_ST;
3881 ata_pio_sectors(qc);
3882 ata_altstatus(ap); /* flush */
3883 } else
3884 /* send CDB */
3885 atapi_send_cdb(ap, qc);
3886
3887 if (in_wq)
3888 spin_unlock_irqrestore(&ap->host_set->lock, flags);
3889
3890 /* if polling, ata_pio_task() handles the rest.
3891 * otherwise, interrupt handler takes over from here.
3892 */
3832 break; 3893 break;
3833 3894
3834 case HSM_ST: 3895 case HSM_ST:
@@ -3868,6 +3929,7 @@ fsm_start:
3868 } 3929 }
3869 3930
3870 ata_altstatus(ap); /* flush */ 3931 ata_altstatus(ap); /* flush */
3932 poll_next = 1;
3871 break; 3933 break;
3872 3934
3873 case HSM_ST_LAST: 3935 case HSM_ST_LAST:
@@ -3886,7 +3948,12 @@ fsm_start:
3886 ap->hsm_task_state = HSM_ST_IDLE; 3948 ap->hsm_task_state = HSM_ST_IDLE;
3887 3949
3888 /* complete taskfile transaction */ 3950 /* complete taskfile transaction */
3889 ata_qc_complete(qc); 3951 if (in_wq)
3952 ata_poll_qc_complete(qc);
3953 else
3954 ata_qc_complete(qc);
3955
3956 poll_next = 0;
3890 break; 3957 break;
3891 3958
3892 case HSM_ST_ERR: 3959 case HSM_ST_ERR:
@@ -3900,12 +3967,20 @@ fsm_start:
3900 WARN_ON(qc->err_mask == 0); 3967 WARN_ON(qc->err_mask == 0);
3901 3968
3902 ap->hsm_task_state = HSM_ST_IDLE; 3969 ap->hsm_task_state = HSM_ST_IDLE;
3903 ata_qc_complete(qc); 3970
3971 if (in_wq)
3972 ata_poll_qc_complete(qc);
3973 else
3974 ata_qc_complete(qc);
3975
3976 poll_next = 0;
3904 break; 3977 break;
3905 default: 3978 default:
3979 poll_next = 0;
3906 BUG(); 3980 BUG();
3907 } 3981 }
3908 3982
3983 return poll_next;
3909} 3984}
3910 3985
3911static void ata_pio_task(void *_data) 3986static void ata_pio_task(void *_data)
@@ -4423,7 +4498,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
4423 /* ack bmdma irq events */ 4498 /* ack bmdma irq events */
4424 ap->ops->irq_clear(ap); 4499 ap->ops->irq_clear(ap);
4425 4500
4426 ata_hsm_move(ap, qc, status); 4501 ata_hsm_move(ap, qc, status, 0);
4427 return 1; /* irq handled */ 4502 return 1; /* irq handled */
4428 4503
4429idle_irq: 4504idle_irq: