diff options
Diffstat (limited to 'drivers/ata/libata-scsi.c')
-rw-r--r-- | drivers/ata/libata-scsi.c | 69 |
1 files changed, 53 insertions, 16 deletions
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index b0d0cc41f3e8..47ea111d5ace 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c | |||
@@ -164,10 +164,10 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg) | |||
164 | { | 164 | { |
165 | int rc = 0; | 165 | int rc = 0; |
166 | u8 scsi_cmd[MAX_COMMAND_SIZE]; | 166 | u8 scsi_cmd[MAX_COMMAND_SIZE]; |
167 | u8 args[4], *argbuf = NULL; | 167 | u8 args[4], *argbuf = NULL, *sensebuf = NULL; |
168 | int argsize = 0; | 168 | int argsize = 0; |
169 | struct scsi_sense_hdr sshdr; | ||
170 | enum dma_data_direction data_dir; | 169 | enum dma_data_direction data_dir; |
170 | int cmd_result; | ||
171 | 171 | ||
172 | if (arg == NULL) | 172 | if (arg == NULL) |
173 | return -EINVAL; | 173 | return -EINVAL; |
@@ -175,6 +175,10 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg) | |||
175 | if (copy_from_user(args, arg, sizeof(args))) | 175 | if (copy_from_user(args, arg, sizeof(args))) |
176 | return -EFAULT; | 176 | return -EFAULT; |
177 | 177 | ||
178 | sensebuf = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_NOIO); | ||
179 | if (!sensebuf) | ||
180 | return -ENOMEM; | ||
181 | |||
178 | memset(scsi_cmd, 0, sizeof(scsi_cmd)); | 182 | memset(scsi_cmd, 0, sizeof(scsi_cmd)); |
179 | 183 | ||
180 | if (args[3]) { | 184 | if (args[3]) { |
@@ -191,7 +195,7 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg) | |||
191 | data_dir = DMA_FROM_DEVICE; | 195 | data_dir = DMA_FROM_DEVICE; |
192 | } else { | 196 | } else { |
193 | scsi_cmd[1] = (3 << 1); /* Non-data */ | 197 | scsi_cmd[1] = (3 << 1); /* Non-data */ |
194 | /* scsi_cmd[2] is already 0 -- no off.line, cc, or data xfer */ | 198 | scsi_cmd[2] = 0x20; /* cc but no off.line or data xfer */ |
195 | data_dir = DMA_NONE; | 199 | data_dir = DMA_NONE; |
196 | } | 200 | } |
197 | 201 | ||
@@ -210,18 +214,46 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg) | |||
210 | 214 | ||
211 | /* Good values for timeout and retries? Values below | 215 | /* Good values for timeout and retries? Values below |
212 | from scsi_ioctl_send_command() for default case... */ | 216 | from scsi_ioctl_send_command() for default case... */ |
213 | if (scsi_execute_req(scsidev, scsi_cmd, data_dir, argbuf, argsize, | 217 | cmd_result = scsi_execute(scsidev, scsi_cmd, data_dir, argbuf, argsize, |
214 | &sshdr, (10*HZ), 5)) { | 218 | sensebuf, (10*HZ), 5, 0); |
219 | |||
220 | if (driver_byte(cmd_result) == DRIVER_SENSE) {/* sense data available */ | ||
221 | u8 *desc = sensebuf + 8; | ||
222 | cmd_result &= ~(0xFF<<24); /* DRIVER_SENSE is not an error */ | ||
223 | |||
224 | /* If we set cc then ATA pass-through will cause a | ||
225 | * check condition even if no error. Filter that. */ | ||
226 | if (cmd_result & SAM_STAT_CHECK_CONDITION) { | ||
227 | struct scsi_sense_hdr sshdr; | ||
228 | scsi_normalize_sense(sensebuf, SCSI_SENSE_BUFFERSIZE, | ||
229 | &sshdr); | ||
230 | if (sshdr.sense_key==0 && | ||
231 | sshdr.asc==0 && sshdr.ascq==0) | ||
232 | cmd_result &= ~SAM_STAT_CHECK_CONDITION; | ||
233 | } | ||
234 | |||
235 | /* Send userspace a few ATA registers (same as drivers/ide) */ | ||
236 | if (sensebuf[0] == 0x72 && /* format is "descriptor" */ | ||
237 | desc[0] == 0x09 ) { /* code is "ATA Descriptor" */ | ||
238 | args[0] = desc[13]; /* status */ | ||
239 | args[1] = desc[3]; /* error */ | ||
240 | args[2] = desc[5]; /* sector count (0:7) */ | ||
241 | if (copy_to_user(arg, args, sizeof(args))) | ||
242 | rc = -EFAULT; | ||
243 | } | ||
244 | } | ||
245 | |||
246 | |||
247 | if (cmd_result) { | ||
215 | rc = -EIO; | 248 | rc = -EIO; |
216 | goto error; | 249 | goto error; |
217 | } | 250 | } |
218 | 251 | ||
219 | /* Need code to retrieve data from check condition? */ | ||
220 | |||
221 | if ((argbuf) | 252 | if ((argbuf) |
222 | && copy_to_user(arg + sizeof(args), argbuf, argsize)) | 253 | && copy_to_user(arg + sizeof(args), argbuf, argsize)) |
223 | rc = -EFAULT; | 254 | rc = -EFAULT; |
224 | error: | 255 | error: |
256 | kfree(sensebuf); | ||
225 | kfree(argbuf); | 257 | kfree(argbuf); |
226 | return rc; | 258 | return rc; |
227 | } | 259 | } |
@@ -1419,6 +1451,7 @@ nothing_to_do: | |||
1419 | 1451 | ||
1420 | static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) | 1452 | static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) |
1421 | { | 1453 | { |
1454 | struct ata_port *ap = qc->ap; | ||
1422 | struct scsi_cmnd *cmd = qc->scsicmd; | 1455 | struct scsi_cmnd *cmd = qc->scsicmd; |
1423 | u8 *cdb = cmd->cmnd; | 1456 | u8 *cdb = cmd->cmnd; |
1424 | int need_sense = (qc->err_mask != 0); | 1457 | int need_sense = (qc->err_mask != 0); |
@@ -1427,11 +1460,12 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) | |||
1427 | * schedule EH_REVALIDATE operation to update the IDENTIFY DEVICE | 1460 | * schedule EH_REVALIDATE operation to update the IDENTIFY DEVICE |
1428 | * cache | 1461 | * cache |
1429 | */ | 1462 | */ |
1430 | if (!need_sense && (qc->tf.command == ATA_CMD_SET_FEATURES) && | 1463 | if (ap->ops->error_handler && |
1464 | !need_sense && (qc->tf.command == ATA_CMD_SET_FEATURES) && | ||
1431 | ((qc->tf.feature == SETFEATURES_WC_ON) || | 1465 | ((qc->tf.feature == SETFEATURES_WC_ON) || |
1432 | (qc->tf.feature == SETFEATURES_WC_OFF))) { | 1466 | (qc->tf.feature == SETFEATURES_WC_OFF))) { |
1433 | qc->ap->eh_info.action |= ATA_EH_REVALIDATE; | 1467 | ap->eh_info.action |= ATA_EH_REVALIDATE; |
1434 | ata_port_schedule_eh(qc->ap); | 1468 | ata_port_schedule_eh(ap); |
1435 | } | 1469 | } |
1436 | 1470 | ||
1437 | /* For ATA pass thru (SAT) commands, generate a sense block if | 1471 | /* For ATA pass thru (SAT) commands, generate a sense block if |
@@ -1458,8 +1492,8 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) | |||
1458 | } | 1492 | } |
1459 | } | 1493 | } |
1460 | 1494 | ||
1461 | if (need_sense && !qc->ap->ops->error_handler) | 1495 | if (need_sense && !ap->ops->error_handler) |
1462 | ata_dump_status(qc->ap->id, &qc->result_tf); | 1496 | ata_dump_status(ap->id, &qc->result_tf); |
1463 | 1497 | ||
1464 | qc->scsidone(cmd); | 1498 | qc->scsidone(cmd); |
1465 | 1499 | ||
@@ -1580,9 +1614,9 @@ early_finish: | |||
1580 | 1614 | ||
1581 | err_did: | 1615 | err_did: |
1582 | ata_qc_free(qc); | 1616 | ata_qc_free(qc); |
1583 | err_mem: | ||
1584 | cmd->result = (DID_ERROR << 16); | 1617 | cmd->result = (DID_ERROR << 16); |
1585 | done(cmd); | 1618 | done(cmd); |
1619 | err_mem: | ||
1586 | DPRINTK("EXIT - internal\n"); | 1620 | DPRINTK("EXIT - internal\n"); |
1587 | return 0; | 1621 | return 0; |
1588 | 1622 | ||
@@ -3313,20 +3347,23 @@ EXPORT_SYMBOL_GPL(ata_sas_slave_configure); | |||
3313 | * @ap: ATA port to which the command is being sent | 3347 | * @ap: ATA port to which the command is being sent |
3314 | * | 3348 | * |
3315 | * RETURNS: | 3349 | * RETURNS: |
3316 | * Zero. | 3350 | * Return value from __ata_scsi_queuecmd() if @cmd can be queued, |
3351 | * 0 otherwise. | ||
3317 | */ | 3352 | */ |
3318 | 3353 | ||
3319 | int ata_sas_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), | 3354 | int ata_sas_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), |
3320 | struct ata_port *ap) | 3355 | struct ata_port *ap) |
3321 | { | 3356 | { |
3357 | int rc = 0; | ||
3358 | |||
3322 | ata_scsi_dump_cdb(ap, cmd); | 3359 | ata_scsi_dump_cdb(ap, cmd); |
3323 | 3360 | ||
3324 | if (likely(ata_scsi_dev_enabled(ap->device))) | 3361 | if (likely(ata_scsi_dev_enabled(ap->device))) |
3325 | __ata_scsi_queuecmd(cmd, done, ap->device); | 3362 | rc = __ata_scsi_queuecmd(cmd, done, ap->device); |
3326 | else { | 3363 | else { |
3327 | cmd->result = (DID_BAD_TARGET << 16); | 3364 | cmd->result = (DID_BAD_TARGET << 16); |
3328 | done(cmd); | 3365 | done(cmd); |
3329 | } | 3366 | } |
3330 | return 0; | 3367 | return rc; |
3331 | } | 3368 | } |
3332 | EXPORT_SYMBOL_GPL(ata_sas_queuecmd); | 3369 | EXPORT_SYMBOL_GPL(ata_sas_queuecmd); |