diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/libata-core.c | 99 |
1 files changed, 99 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 | { |