aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-scsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ata/libata-scsi.c')
-rw-r--r--drivers/ata/libata-scsi.c69
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;
224error: 255error:
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
1420static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) 1452static 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
1581err_did: 1615err_did:
1582 ata_qc_free(qc); 1616 ata_qc_free(qc);
1583err_mem:
1584 cmd->result = (DID_ERROR << 16); 1617 cmd->result = (DID_ERROR << 16);
1585 done(cmd); 1618 done(cmd);
1619err_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
3319int ata_sas_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), 3354int 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}
3332EXPORT_SYMBOL_GPL(ata_sas_queuecmd); 3369EXPORT_SYMBOL_GPL(ata_sas_queuecmd);