diff options
| -rw-r--r-- | drivers/scsi/libata-core.c | 56 | ||||
| -rw-r--r-- | include/linux/libata.h | 3 | 
2 files changed, 55 insertions, 4 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 249e67fab81f..9a785cf0c5b1 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c  | |||
| @@ -1074,19 +1074,66 @@ static unsigned int ata_pio_modes(const struct ata_device *adev) | |||
| 1074 | static inline void | 1074 | static inline void | 
| 1075 | ata_queue_packet_task(struct ata_port *ap) | 1075 | ata_queue_packet_task(struct ata_port *ap) | 
| 1076 | { | 1076 | { | 
| 1077 | queue_work(ata_wq, &ap->packet_task); | 1077 | if (!(ap->flags & ATA_FLAG_FLUSH_PIO_TASK)) | 
| 1078 | queue_work(ata_wq, &ap->packet_task); | ||
| 1078 | } | 1079 | } | 
| 1079 | 1080 | ||
| 1080 | static inline void | 1081 | static inline void | 
| 1081 | ata_queue_pio_task(struct ata_port *ap) | 1082 | ata_queue_pio_task(struct ata_port *ap) | 
| 1082 | { | 1083 | { | 
| 1083 | queue_work(ata_wq, &ap->pio_task); | 1084 | if (!(ap->flags & ATA_FLAG_FLUSH_PIO_TASK)) | 
| 1085 | queue_work(ata_wq, &ap->pio_task); | ||
| 1084 | } | 1086 | } | 
| 1085 | 1087 | ||
| 1086 | static inline void | 1088 | static inline void | 
| 1087 | ata_queue_delayed_pio_task(struct ata_port *ap, unsigned long delay) | 1089 | ata_queue_delayed_pio_task(struct ata_port *ap, unsigned long delay) | 
| 1088 | { | 1090 | { | 
| 1089 | queue_delayed_work(ata_wq, &ap->pio_task, delay); | 1091 | if (!(ap->flags & ATA_FLAG_FLUSH_PIO_TASK)) | 
| 1092 | queue_delayed_work(ata_wq, &ap->pio_task, delay); | ||
| 1093 | } | ||
| 1094 | |||
| 1095 | /** | ||
| 1096 | * ata_flush_pio_tasks - Flush pio_task and packet_task | ||
| 1097 | * @ap: the target ata_port | ||
| 1098 | * | ||
| 1099 | * After this function completes, pio_task and packet_task are | ||
| 1100 | * guranteed not to be running or scheduled. | ||
| 1101 | * | ||
| 1102 | * LOCKING: | ||
| 1103 | * Kernel thread context (may sleep) | ||
| 1104 | */ | ||
| 1105 | |||
| 1106 | static void ata_flush_pio_tasks(struct ata_port *ap) | ||
| 1107 | { | ||
| 1108 | int tmp = 0; | ||
| 1109 | unsigned long flags; | ||
| 1110 | |||
| 1111 | DPRINTK("ENTER\n"); | ||
| 1112 | |||
| 1113 | spin_lock_irqsave(&ap->host_set->lock, flags); | ||
| 1114 | ap->flags |= ATA_FLAG_FLUSH_PIO_TASK; | ||
| 1115 | spin_unlock_irqrestore(&ap->host_set->lock, flags); | ||
| 1116 | |||
| 1117 | DPRINTK("flush #1\n"); | ||
| 1118 | flush_workqueue(ata_wq); | ||
| 1119 | |||
| 1120 | /* | ||
| 1121 | * At this point, if a task is running, it's guaranteed to see | ||
| 1122 | * the FLUSH flag; thus, it will never queue pio tasks again. | ||
| 1123 | * Cancel and flush. | ||
| 1124 | */ | ||
| 1125 | tmp |= cancel_delayed_work(&ap->pio_task); | ||
| 1126 | tmp |= cancel_delayed_work(&ap->packet_task); | ||
| 1127 | if (!tmp) { | ||
| 1128 | DPRINTK("flush #2\n"); | ||
| 1129 | flush_workqueue(ata_wq); | ||
| 1130 | } | ||
| 1131 | |||
| 1132 | spin_lock_irqsave(&ap->host_set->lock, flags); | ||
| 1133 | ap->flags &= ~ATA_FLAG_FLUSH_PIO_TASK; | ||
| 1134 | spin_unlock_irqrestore(&ap->host_set->lock, flags); | ||
| 1135 | |||
| 1136 | DPRINTK("EXIT\n"); | ||
| 1090 | } | 1137 | } | 
| 1091 | 1138 | ||
| 1092 | void ata_qc_complete_internal(struct ata_queued_cmd *qc) | 1139 | void ata_qc_complete_internal(struct ata_queued_cmd *qc) | 
| @@ -3767,6 +3814,9 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc) | |||
| 3767 | 3814 | ||
| 3768 | DPRINTK("ENTER\n"); | 3815 | DPRINTK("ENTER\n"); | 
| 3769 | 3816 | ||
| 3817 | ata_flush_pio_tasks(ap); | ||
| 3818 | ap->hsm_task_state = HSM_ST_IDLE; | ||
| 3819 | |||
| 3770 | spin_lock_irqsave(&host_set->lock, flags); | 3820 | spin_lock_irqsave(&host_set->lock, flags); | 
| 3771 | 3821 | ||
| 3772 | switch (qc->tf.protocol) { | 3822 | switch (qc->tf.protocol) { | 
diff --git a/include/linux/libata.h b/include/linux/libata.h index 55176df403a5..f4cd1eb734a0 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h  | |||
| @@ -162,7 +162,8 @@ enum { | |||
| 162 | ATA_FLAG_PIO_LBA48 = (1 << 13), /* Host DMA engine is LBA28 only */ | 162 | ATA_FLAG_PIO_LBA48 = (1 << 13), /* Host DMA engine is LBA28 only */ | 
| 163 | ATA_FLAG_IRQ_MASK = (1 << 14), /* Mask IRQ in PIO xfers */ | 163 | ATA_FLAG_IRQ_MASK = (1 << 14), /* Mask IRQ in PIO xfers */ | 
| 164 | 164 | ||
| 165 | ATA_FLAG_IN_EH = (1 << 15), /* EH in progress */ | 165 | ATA_FLAG_FLUSH_PIO_TASK = (1 << 15), /* Flush PIO task */ | 
| 166 | ATA_FLAG_IN_EH = (1 << 16), /* EH in progress */ | ||
| 166 | 167 | ||
| 167 | ATA_QCFLAG_ACTIVE = (1 << 1), /* cmd not yet ack'd to scsi lyer */ | 168 | ATA_QCFLAG_ACTIVE = (1 << 1), /* cmd not yet ack'd to scsi lyer */ | 
| 168 | ATA_QCFLAG_SG = (1 << 3), /* have s/g table? */ | 169 | ATA_QCFLAG_SG = (1 << 3), /* have s/g table? */ | 
