diff options
| -rw-r--r-- | drivers/scsi/libata-core.c | 87 |
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 | ||
| 3808 | static 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 | |||
| 3819 | static 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, | |||
| 3819 | fsm_start: | 3844 | fsm_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 | ||
| 3911 | static void ata_pio_task(void *_data) | 3986 | static 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 | ||
| 4429 | idle_irq: | 4504 | idle_irq: |
