diff options
| -rw-r--r-- | drivers/scsi/libata-core.c | 99 | ||||
| -rw-r--r-- | include/linux/libata.h | 2 |
2 files changed, 101 insertions, 0 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index a0060cf31e0d..de80abeab065 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c | |||
| @@ -1046,6 +1046,105 @@ static unsigned int ata_pio_modes(const struct ata_device *adev) | |||
| 1046 | return modes; | 1046 | return modes; |
| 1047 | } | 1047 | } |
| 1048 | 1048 | ||
| 1049 | struct ata_exec_internal_arg { | ||
| 1050 | unsigned int err_mask; | ||
| 1051 | struct ata_taskfile *tf; | ||
| 1052 | struct completion *waiting; | ||
| 1053 | }; | ||
| 1054 | |||
| 1055 | int ata_qc_complete_internal(struct ata_queued_cmd *qc) | ||
| 1056 | { | ||
| 1057 | struct ata_exec_internal_arg *arg = qc->private_data; | ||
| 1058 | struct completion *waiting = arg->waiting; | ||
| 1059 | |||
| 1060 | if (!(qc->err_mask & ~AC_ERR_DEV)) | ||
| 1061 | qc->ap->ops->tf_read(qc->ap, arg->tf); | ||
| 1062 | arg->err_mask = qc->err_mask; | ||
| 1063 | arg->waiting = NULL; | ||
| 1064 | complete(waiting); | ||
| 1065 | |||
| 1066 | return 0; | ||
| 1067 | } | ||
| 1068 | |||
| 1069 | /** | ||
| 1070 | * ata_exec_internal - execute libata internal command | ||
| 1071 | * @ap: Port to which the command is sent | ||
| 1072 | * @dev: Device to which the command is sent | ||
| 1073 | * @tf: Taskfile registers for the command and the result | ||
| 1074 | * @dma_dir: Data tranfer direction of the command | ||
| 1075 | * @buf: Data buffer of the command | ||
| 1076 | * @buflen: Length of data buffer | ||
| 1077 | * | ||
| 1078 | * Executes libata internal command with timeout. @tf contains | ||
| 1079 | * command on entry and result on return. Timeout and error | ||
| 1080 | * conditions are reported via return value. No recovery action | ||
| 1081 | * is taken after a command times out. It's caller's duty to | ||
| 1082 | * clean up after timeout. | ||
| 1083 | * | ||
| 1084 | * LOCKING: | ||
| 1085 | * None. Should be called with kernel context, might sleep. | ||
| 1086 | */ | ||
| 1087 | |||
| 1088 | static unsigned | ||
| 1089 | ata_exec_internal(struct ata_port *ap, struct ata_device *dev, | ||
| 1090 | struct ata_taskfile *tf, | ||
| 1091 | int dma_dir, void *buf, unsigned int buflen) | ||
| 1092 | { | ||
| 1093 | u8 command = tf->command; | ||
| 1094 | struct ata_queued_cmd *qc; | ||
| 1095 | DECLARE_COMPLETION(wait); | ||
| 1096 | unsigned long flags; | ||
| 1097 | struct ata_exec_internal_arg arg; | ||
| 1098 | |||
| 1099 | spin_lock_irqsave(&ap->host_set->lock, flags); | ||
| 1100 | |||
| 1101 | qc = ata_qc_new_init(ap, dev); | ||
| 1102 | BUG_ON(qc == NULL); | ||
| 1103 | |||
| 1104 | qc->tf = *tf; | ||
| 1105 | qc->dma_dir = dma_dir; | ||
| 1106 | if (dma_dir != DMA_NONE) { | ||
| 1107 | ata_sg_init_one(qc, buf, buflen); | ||
| 1108 | qc->nsect = buflen / ATA_SECT_SIZE; | ||
| 1109 | } | ||
| 1110 | |||
| 1111 | arg.waiting = &wait; | ||
| 1112 | arg.tf = tf; | ||
| 1113 | qc->private_data = &arg; | ||
| 1114 | qc->complete_fn = ata_qc_complete_internal; | ||
| 1115 | |||
| 1116 | if (ata_qc_issue(qc)) | ||
| 1117 | goto issue_fail; | ||
| 1118 | |||
| 1119 | spin_unlock_irqrestore(&ap->host_set->lock, flags); | ||
| 1120 | |||
| 1121 | if (!wait_for_completion_timeout(&wait, ATA_TMOUT_INTERNAL)) { | ||
| 1122 | spin_lock_irqsave(&ap->host_set->lock, flags); | ||
| 1123 | |||
| 1124 | /* We're racing with irq here. If we lose, the | ||
| 1125 | * following test prevents us from completing the qc | ||
| 1126 | * again. If completion irq occurs after here but | ||
| 1127 | * before the caller cleans up, it will result in a | ||
| 1128 | * spurious interrupt. We can live with that. | ||
| 1129 | */ | ||
| 1130 | if (arg.waiting) { | ||
| 1131 | qc->err_mask = AC_ERR_OTHER; | ||
| 1132 | ata_qc_complete(qc); | ||
| 1133 | printk(KERN_WARNING "ata%u: qc timeout (cmd 0x%x)\n", | ||
| 1134 | ap->id, command); | ||
| 1135 | } | ||
| 1136 | |||
| 1137 | spin_unlock_irqrestore(&ap->host_set->lock, flags); | ||
| 1138 | } | ||
| 1139 | |||
| 1140 | return arg.err_mask; | ||
| 1141 | |||
| 1142 | issue_fail: | ||
| 1143 | ata_qc_free(qc); | ||
| 1144 | spin_unlock_irqrestore(&ap->host_set->lock, flags); | ||
| 1145 | return AC_ERR_OTHER; | ||
| 1146 | } | ||
| 1147 | |||
| 1049 | static int ata_qc_wait_err(struct ata_queued_cmd *qc, | 1148 | static int ata_qc_wait_err(struct ata_queued_cmd *qc, |
| 1050 | struct completion *wait) | 1149 | struct completion *wait) |
| 1051 | { | 1150 | { |
diff --git a/include/linux/libata.h b/include/linux/libata.h index e18ce039cdfd..833e57afd54c 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h | |||
| @@ -135,6 +135,8 @@ enum { | |||
| 135 | ATA_TMOUT_BOOT_QUICK = 7 * HZ, /* hueristic */ | 135 | ATA_TMOUT_BOOT_QUICK = 7 * HZ, /* hueristic */ |
| 136 | ATA_TMOUT_CDB = 30 * HZ, | 136 | ATA_TMOUT_CDB = 30 * HZ, |
| 137 | ATA_TMOUT_CDB_QUICK = 5 * HZ, | 137 | ATA_TMOUT_CDB_QUICK = 5 * HZ, |
| 138 | ATA_TMOUT_INTERNAL = 30 * HZ, | ||
| 139 | ATA_TMOUT_INTERNAL_QUICK = 5 * HZ, | ||
| 138 | 140 | ||
| 139 | /* ATA bus states */ | 141 | /* ATA bus states */ |
| 140 | BUS_UNKNOWN = 0, | 142 | BUS_UNKNOWN = 0, |
