X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=drivers%2Fata%2Flibata-scsi.c;h=6cc817a10204a89ad2615ce3bd53f111cdf267da;hb=9f6632d6290785caf9e9f874c0a0cfaf2c178e59;hp=836947da5b14de4f7e75859d2e500cb2001b31a4;hpb=4604096768d3be37ee1a05aee424aceed3e1b56f;p=powerpc.git diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 836947da5b..6cc817a102 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -148,6 +148,45 @@ int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev, return 0; } +/** + * ata_get_identity - Handler for HDIO_GET_IDENTITY ioctl + * @sdev: SCSI device to get identify data for + * @arg: User buffer area for identify data + * + * LOCKING: + * Defined by the SCSI layer. We don't really care. + * + * RETURNS: + * Zero on success, negative errno on error. + */ +static int ata_get_identity(struct scsi_device *sdev, void __user *arg) +{ + struct ata_port *ap = ata_shost_to_port(sdev->host); + struct ata_device *dev = ata_scsi_find_dev(ap, sdev); + u16 __user *dst = arg; + char buf[40]; + + if (!dev) + return -ENOMSG; + + if (copy_to_user(dst, dev->id, ATA_ID_WORDS * sizeof(u16))) + return -EFAULT; + + ata_id_string(dev->id, buf, ATA_ID_PROD, ATA_ID_PROD_LEN); + if (copy_to_user(dst + ATA_ID_PROD, buf, ATA_ID_PROD_LEN)) + return -EFAULT; + + ata_id_string(dev->id, buf, ATA_ID_FW_REV, ATA_ID_FW_REV_LEN); + if (copy_to_user(dst + ATA_ID_FW_REV, buf, ATA_ID_FW_REV_LEN)) + return -EFAULT; + + ata_id_string(dev->id, buf, ATA_ID_SERNO, ATA_ID_SERNO_LEN); + if (copy_to_user(dst + ATA_ID_SERNO, buf, ATA_ID_SERNO_LEN)) + return -EFAULT; + + return 0; +} + /** * ata_cmd_ioctl - Handler for HDIO_DRIVE_CMD ioctl * @scsidev: Device to which we are issuing command @@ -159,7 +198,6 @@ int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev, * RETURNS: * Zero on success, negative errno on error. */ - int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg) { int rc = 0; @@ -273,8 +311,8 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg) { int rc = 0; u8 scsi_cmd[MAX_COMMAND_SIZE]; - u8 args[7]; - struct scsi_sense_hdr sshdr; + u8 args[7], *sensebuf = NULL; + int cmd_result; if (arg == NULL) return -EINVAL; @@ -282,24 +320,64 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg) if (copy_from_user(args, arg, sizeof(args))) return -EFAULT; + sensebuf = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_NOIO); + if (!sensebuf) + return -ENOMEM; + memset(scsi_cmd, 0, sizeof(scsi_cmd)); scsi_cmd[0] = ATA_16; scsi_cmd[1] = (3 << 1); /* Non-data */ - /* scsi_cmd[2] is already 0 -- no off.line, cc, or data xfer */ + scsi_cmd[2] = 0x20; /* cc but no off.line or data xfer */ scsi_cmd[4] = args[1]; scsi_cmd[6] = args[2]; scsi_cmd[8] = args[3]; scsi_cmd[10] = args[4]; scsi_cmd[12] = args[5]; + scsi_cmd[13] = args[6] & 0x0f; scsi_cmd[14] = args[0]; /* Good values for timeout and retries? Values below from scsi_ioctl_send_command() for default case... */ - if (scsi_execute_req(scsidev, scsi_cmd, DMA_NONE, NULL, 0, &sshdr, - (10*HZ), 5)) + cmd_result = scsi_execute(scsidev, scsi_cmd, DMA_NONE, NULL, 0, + sensebuf, (10*HZ), 5, 0); + + if (driver_byte(cmd_result) == DRIVER_SENSE) {/* sense data available */ + u8 *desc = sensebuf + 8; + cmd_result &= ~(0xFF<<24); /* DRIVER_SENSE is not an error */ + + /* If we set cc then ATA pass-through will cause a + * check condition even if no error. Filter that. */ + if (cmd_result & SAM_STAT_CHECK_CONDITION) { + struct scsi_sense_hdr sshdr; + scsi_normalize_sense(sensebuf, SCSI_SENSE_BUFFERSIZE, + &sshdr); + if (sshdr.sense_key==0 && + sshdr.asc==0 && sshdr.ascq==0) + cmd_result &= ~SAM_STAT_CHECK_CONDITION; + } + + /* Send userspace ATA registers */ + if (sensebuf[0] == 0x72 && /* format is "descriptor" */ + desc[0] == 0x09) {/* code is "ATA Descriptor" */ + args[0] = desc[13]; /* status */ + args[1] = desc[3]; /* error */ + args[2] = desc[5]; /* sector count (0:7) */ + args[3] = desc[7]; /* lbal */ + args[4] = desc[9]; /* lbam */ + args[5] = desc[11]; /* lbah */ + args[6] = desc[12]; /* select */ + if (copy_to_user(arg, args, sizeof(args))) + rc = -EFAULT; + } + } + + if (cmd_result) { rc = -EIO; + goto error; + } - /* Need code to retrieve data from check condition? */ + error: + kfree(sensebuf); return rc; } @@ -320,6 +398,9 @@ int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg) return -EINVAL; return 0; + case HDIO_GET_IDENTITY: + return ata_get_identity(scsidev, arg); + case HDIO_DRIVE_CMD: if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) return -EACCES; @@ -358,9 +439,9 @@ int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg) * RETURNS: * Command allocated, or %NULL if none available. */ -struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev, - struct scsi_cmnd *cmd, - void (*done)(struct scsi_cmnd *)) +static struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev, + struct scsi_cmnd *cmd, + void (*done)(struct scsi_cmnd *)) { struct ata_queued_cmd *qc; @@ -372,7 +453,7 @@ struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev, if (cmd->use_sg) { qc->__sg = (struct scatterlist *) cmd->request_buffer; qc->n_elem = cmd->use_sg; - } else { + } else if (cmd->request_bufflen) { qc->__sg = &qc->sgent; qc->n_elem = 1; } @@ -396,7 +477,7 @@ struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev, * LOCKING: * inherited from caller */ -void ata_dump_status(unsigned id, struct ata_taskfile *tf) +static void ata_dump_status(unsigned id, struct ata_taskfile *tf) { u8 stat = tf->command, err = tf->feature; @@ -429,6 +510,7 @@ void ata_dump_status(unsigned id, struct ata_taskfile *tf) } } +#ifdef CONFIG_PM /** * ata_scsi_device_suspend - suspend ATA device associated with sdev * @sdev: the SCSI device to suspend @@ -553,6 +635,7 @@ int ata_scsi_device_resume(struct scsi_device *sdev) sdev->sdev_gendev.power.power_state = PMSG_ON; return 0; } +#endif /* CONFIG_PM */ /** * ata_to_sense_error - convert ATA error to SCSI error @@ -571,8 +654,8 @@ int ata_scsi_device_resume(struct scsi_device *sdev) * LOCKING: * spin_lock_irqsave(host lock) */ -void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc, - u8 *ascq, int verbose) +static void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, + u8 *asc, u8 *ascq, int verbose) { int i; @@ -701,7 +784,7 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc) */ if (qc->err_mask || tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) { - ata_to_sense_error(qc->ap->id, tf->command, tf->feature, + ata_to_sense_error(qc->ap->print_id, tf->command, tf->feature, &sb[1], &sb[2], &sb[3], verbose); sb[1] &= 0x0f; } @@ -774,7 +857,7 @@ static void ata_gen_ata_sense(struct ata_queued_cmd *qc) */ if (qc->err_mask || tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) { - ata_to_sense_error(qc->ap->id, tf->command, tf->feature, + ata_to_sense_error(qc->ap->print_id, tf->command, tf->feature, &sb[1], &sb[2], &sb[3], verbose); sb[1] &= 0x0f; } @@ -906,29 +989,32 @@ int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth) struct ata_port *ap = ata_shost_to_port(sdev->host); struct ata_device *dev; unsigned long flags; - int max_depth; - if (queue_depth < 1) + if (queue_depth < 1 || queue_depth == sdev->queue_depth) return sdev->queue_depth; dev = ata_scsi_find_dev(ap, sdev); if (!dev || !ata_dev_enabled(dev)) return sdev->queue_depth; - max_depth = min(sdev->host->can_queue, ata_id_queue_depth(dev->id)); - max_depth = min(ATA_MAX_QUEUE - 1, max_depth); - if (queue_depth > max_depth) - queue_depth = max_depth; - - scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, queue_depth); - + /* NCQ enabled? */ spin_lock_irqsave(ap->lock, flags); - if (queue_depth > 1) - dev->flags &= ~ATA_DFLAG_NCQ_OFF; - else + dev->flags &= ~ATA_DFLAG_NCQ_OFF; + if (queue_depth == 1 || !ata_ncq_enabled(dev)) { dev->flags |= ATA_DFLAG_NCQ_OFF; + queue_depth = 1; + } spin_unlock_irqrestore(ap->lock, flags); + /* limit and apply queue depth */ + queue_depth = min(queue_depth, sdev->host->can_queue); + queue_depth = min(queue_depth, ata_id_queue_depth(dev->id)); + queue_depth = min(queue_depth, ATA_MAX_QUEUE - 1); + + if (sdev->queue_depth == queue_depth) + return -EINVAL; + + scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, queue_depth); return queue_depth; } @@ -983,11 +1069,10 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc) } tf->command = ATA_CMD_VERIFY; /* READ VERIFY */ - } else { - tf->nsect = 0; /* time period value (0 implies now) */ - tf->command = ATA_CMD_STANDBY; - /* Consider: ATA STANDBY IMMEDIATE command */ - } + } else + /* Issue ATA STANDBY IMMEDIATE command */ + tf->command = ATA_CMD_STANDBYNOW1; + /* * Standby and Idle condition timers could be implemented but that * would require libata to implement the Power condition mode page @@ -1321,7 +1406,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc) goto nothing_to_do; qc->flags |= ATA_QCFLAG_IO; - qc->nsect = n_block; + qc->nbytes = n_block * ATA_SECT_SIZE; rc = ata_build_rw_tf(&qc->tf, qc->dev, block, n_block, tf_flags, qc->tag); @@ -1390,7 +1475,7 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) } if (need_sense && !ap->ops->error_handler) - ata_dump_status(ap->id, &qc->result_tf); + ata_dump_status(ap->print_id, &qc->result_tf); qc->scsidone(cmd); @@ -1416,11 +1501,9 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) static int ata_scmd_need_defer(struct ata_device *dev, int is_io) { struct ata_port *ap = dev->ap; + int is_ncq = is_io && ata_ncq_enabled(dev); - if (!(dev->flags & ATA_DFLAG_NCQ)) - return 0; - - if (is_io) { + if (is_ncq) { if (!ata_tag_valid(ap->active_tag)) return 0; } else { @@ -1660,8 +1743,8 @@ unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, if (buflen > 35) { memcpy(&rbuf[8], "ATA ", 8); - ata_id_string(args->id, &rbuf[16], ATA_ID_PROD_OFS, 16); - ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV_OFS, 4); + ata_id_string(args->id, &rbuf[16], ATA_ID_PROD, 16); + ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV, 4); if (rbuf[32] == 0 || rbuf[32] == ' ') memcpy(&rbuf[32], "n/a ", 4); } @@ -1730,13 +1813,13 @@ unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf, 0, 0x80, /* this page code */ 0, - ATA_SERNO_LEN, /* page len */ + ATA_ID_SERNO_LEN, /* page len */ }; memcpy(rbuf, hdr, sizeof(hdr)); - if (buflen > (ATA_SERNO_LEN + 4 - 1)) + if (buflen > (ATA_ID_SERNO_LEN + 4 - 1)) ata_id_string(args->id, (unsigned char *) &rbuf[4], - ATA_ID_SERNO_OFS, ATA_SERNO_LEN); + ATA_ID_SERNO, ATA_ID_SERNO_LEN); return 0; } @@ -1761,19 +1844,18 @@ unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf, { int num; const int sat_model_serial_desc_len = 68; - const int ata_model_byte_len = 40; rbuf[1] = 0x83; /* this page code */ num = 4; - if (buflen > (ATA_SERNO_LEN + num + 3)) { + if (buflen > (ATA_ID_SERNO_LEN + num + 3)) { /* piv=0, assoc=lu, code_set=ACSII, designator=vendor */ rbuf[num + 0] = 2; - rbuf[num + 3] = ATA_SERNO_LEN; + rbuf[num + 3] = ATA_ID_SERNO_LEN; num += 4; ata_id_string(args->id, (unsigned char *) rbuf + num, - ATA_ID_SERNO_OFS, ATA_SERNO_LEN); - num += ATA_SERNO_LEN; + ATA_ID_SERNO, ATA_ID_SERNO_LEN); + num += ATA_ID_SERNO_LEN; } if (buflen > (sat_model_serial_desc_len + num + 3)) { /* SAT defined lu model and serial numbers descriptor */ @@ -1785,11 +1867,11 @@ unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf, memcpy(rbuf + num, "ATA ", 8); num += 8; ata_id_string(args->id, (unsigned char *) rbuf + num, - ATA_ID_PROD_OFS, ata_model_byte_len); - num += ata_model_byte_len; + ATA_ID_PROD, ATA_ID_PROD_LEN); + num += ATA_ID_PROD_LEN; ata_id_string(args->id, (unsigned char *) rbuf + num, - ATA_ID_SERNO_OFS, ATA_SERNO_LEN); - num += ATA_SERNO_LEN; + ATA_ID_SERNO, ATA_ID_SERNO_LEN); + num += ATA_ID_SERNO_LEN; } rbuf[3] = num - 4; /* page len (assume less than 256 bytes) */ return 0; @@ -1917,15 +1999,15 @@ static unsigned int ata_msense_rw_recovery(u8 **ptr_io, const u8 *last) */ static int ata_dev_supports_fua(u16 *id) { - unsigned char model[41], fw[9]; + unsigned char model[ATA_ID_PROD_LEN + 1], fw[ATA_ID_FW_REV_LEN + 1]; if (!libata_fua) return 0; if (!ata_id_has_fua(id)) return 0; - ata_id_c_string(id, model, ATA_ID_PROD_OFS, sizeof(model)); - ata_id_c_string(id, fw, ATA_ID_FW_REV_OFS, sizeof(fw)); + ata_id_c_string(id, model, ATA_ID_PROD, sizeof(model)); + ata_id_c_string(id, fw, ATA_ID_FW_REV, sizeof(fw)); if (strcmp(model, "Maxtor")) return 1; @@ -2623,7 +2705,7 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) * TODO: find out if we need to do more here to * cover scatter/gather case. */ - qc->nsect = scmd->request_bufflen / ATA_SECT_SIZE; + qc->nbytes = scmd->request_bufflen; /* request result TF */ qc->flags |= ATA_QCFLAG_RESULT_TF; @@ -2696,7 +2778,7 @@ static inline void ata_scsi_dump_cdb(struct ata_port *ap, u8 *scsicmd = cmd->cmnd; DPRINTK("CDB (%u:%d,%d,%d) %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - ap->id, + ap->print_id, scsidev->channel, scsidev->id, scsidev->lun, scsicmd[0], scsicmd[1], scsicmd[2], scsicmd[3], scsicmd[4], scsicmd[5], scsicmd[6], scsicmd[7], @@ -3021,7 +3103,8 @@ void ata_scsi_hotplug(struct work_struct *work) for (i = 0; i < ATA_MAX_DEVICES; i++) { struct ata_device *dev = &ap->device[i]; if (ata_dev_enabled(dev) && !dev->sdev) { - queue_delayed_work(ata_aux_wq, &ap->hotplug_task, HZ); + queue_delayed_work(ata_aux_wq, &ap->hotplug_task, + round_jiffies_relative(HZ)); break; } } @@ -3155,7 +3238,7 @@ struct ata_port *ata_sas_port_alloc(struct ata_host *host, ata_port_init(ap, host, ent, 0); ap->lock = shost->host_lock; - kfree(ent); + devm_kfree(host->dev, ent); return ap; } EXPORT_SYMBOL_GPL(ata_sas_port_alloc); @@ -3226,7 +3309,8 @@ EXPORT_SYMBOL_GPL(ata_sas_port_init); void ata_sas_port_destroy(struct ata_port *ap) { - ap->ops->port_stop(ap); + if (ap->ops->port_stop) + ap->ops->port_stop(ap); kfree(ap); } EXPORT_SYMBOL_GPL(ata_sas_port_destroy);