diff options
Diffstat (limited to 'drivers/ata/libata-scsi.c')
-rw-r--r-- | drivers/ata/libata-scsi.c | 162 |
1 files changed, 127 insertions, 35 deletions
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index f3b4b15a8dc4..4b95c4387e9e 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c | |||
@@ -183,6 +183,105 @@ DEVICE_ATTR(link_power_management_policy, S_IRUGO | S_IWUSR, | |||
183 | ata_scsi_lpm_show, ata_scsi_lpm_put); | 183 | ata_scsi_lpm_show, ata_scsi_lpm_put); |
184 | EXPORT_SYMBOL_GPL(dev_attr_link_power_management_policy); | 184 | EXPORT_SYMBOL_GPL(dev_attr_link_power_management_policy); |
185 | 185 | ||
186 | static ssize_t ata_scsi_park_show(struct device *device, | ||
187 | struct device_attribute *attr, char *buf) | ||
188 | { | ||
189 | struct scsi_device *sdev = to_scsi_device(device); | ||
190 | struct ata_port *ap; | ||
191 | struct ata_link *link; | ||
192 | struct ata_device *dev; | ||
193 | unsigned long flags; | ||
194 | unsigned int uninitialized_var(msecs); | ||
195 | int rc = 0; | ||
196 | |||
197 | ap = ata_shost_to_port(sdev->host); | ||
198 | |||
199 | spin_lock_irqsave(ap->lock, flags); | ||
200 | dev = ata_scsi_find_dev(ap, sdev); | ||
201 | if (!dev) { | ||
202 | rc = -ENODEV; | ||
203 | goto unlock; | ||
204 | } | ||
205 | if (dev->flags & ATA_DFLAG_NO_UNLOAD) { | ||
206 | rc = -EOPNOTSUPP; | ||
207 | goto unlock; | ||
208 | } | ||
209 | |||
210 | link = dev->link; | ||
211 | if (ap->pflags & ATA_PFLAG_EH_IN_PROGRESS && | ||
212 | link->eh_context.unloaded_mask & (1 << dev->devno) && | ||
213 | time_after(dev->unpark_deadline, jiffies)) | ||
214 | msecs = jiffies_to_msecs(dev->unpark_deadline - jiffies); | ||
215 | else | ||
216 | msecs = 0; | ||
217 | |||
218 | unlock: | ||
219 | spin_unlock_irq(ap->lock); | ||
220 | |||
221 | return rc ? rc : snprintf(buf, 20, "%u\n", msecs); | ||
222 | } | ||
223 | |||
224 | static ssize_t ata_scsi_park_store(struct device *device, | ||
225 | struct device_attribute *attr, | ||
226 | const char *buf, size_t len) | ||
227 | { | ||
228 | struct scsi_device *sdev = to_scsi_device(device); | ||
229 | struct ata_port *ap; | ||
230 | struct ata_device *dev; | ||
231 | long int input; | ||
232 | unsigned long flags; | ||
233 | int rc; | ||
234 | |||
235 | rc = strict_strtol(buf, 10, &input); | ||
236 | if (rc || input < -2) | ||
237 | return -EINVAL; | ||
238 | if (input > ATA_TMOUT_MAX_PARK) { | ||
239 | rc = -EOVERFLOW; | ||
240 | input = ATA_TMOUT_MAX_PARK; | ||
241 | } | ||
242 | |||
243 | ap = ata_shost_to_port(sdev->host); | ||
244 | |||
245 | spin_lock_irqsave(ap->lock, flags); | ||
246 | dev = ata_scsi_find_dev(ap, sdev); | ||
247 | if (unlikely(!dev)) { | ||
248 | rc = -ENODEV; | ||
249 | goto unlock; | ||
250 | } | ||
251 | if (dev->class != ATA_DEV_ATA) { | ||
252 | rc = -EOPNOTSUPP; | ||
253 | goto unlock; | ||
254 | } | ||
255 | |||
256 | if (input >= 0) { | ||
257 | if (dev->flags & ATA_DFLAG_NO_UNLOAD) { | ||
258 | rc = -EOPNOTSUPP; | ||
259 | goto unlock; | ||
260 | } | ||
261 | |||
262 | dev->unpark_deadline = ata_deadline(jiffies, input); | ||
263 | dev->link->eh_info.dev_action[dev->devno] |= ATA_EH_PARK; | ||
264 | ata_port_schedule_eh(ap); | ||
265 | complete(&ap->park_req_pending); | ||
266 | } else { | ||
267 | switch (input) { | ||
268 | case -1: | ||
269 | dev->flags &= ~ATA_DFLAG_NO_UNLOAD; | ||
270 | break; | ||
271 | case -2: | ||
272 | dev->flags |= ATA_DFLAG_NO_UNLOAD; | ||
273 | break; | ||
274 | } | ||
275 | } | ||
276 | unlock: | ||
277 | spin_unlock_irqrestore(ap->lock, flags); | ||
278 | |||
279 | return rc ? rc : len; | ||
280 | } | ||
281 | DEVICE_ATTR(unload_heads, S_IRUGO | S_IWUSR, | ||
282 | ata_scsi_park_show, ata_scsi_park_store); | ||
283 | EXPORT_SYMBOL_GPL(dev_attr_unload_heads); | ||
284 | |||
186 | static void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq) | 285 | static void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq) |
187 | { | 286 | { |
188 | cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; | 287 | cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; |
@@ -269,6 +368,12 @@ DEVICE_ATTR(sw_activity, S_IWUGO | S_IRUGO, ata_scsi_activity_show, | |||
269 | ata_scsi_activity_store); | 368 | ata_scsi_activity_store); |
270 | EXPORT_SYMBOL_GPL(dev_attr_sw_activity); | 369 | EXPORT_SYMBOL_GPL(dev_attr_sw_activity); |
271 | 370 | ||
371 | struct device_attribute *ata_common_sdev_attrs[] = { | ||
372 | &dev_attr_unload_heads, | ||
373 | NULL | ||
374 | }; | ||
375 | EXPORT_SYMBOL_GPL(ata_common_sdev_attrs); | ||
376 | |||
272 | static void ata_scsi_invalid_field(struct scsi_cmnd *cmd, | 377 | static void ata_scsi_invalid_field(struct scsi_cmnd *cmd, |
273 | void (*done)(struct scsi_cmnd *)) | 378 | void (*done)(struct scsi_cmnd *)) |
274 | { | 379 | { |
@@ -398,7 +503,7 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg) | |||
398 | scsi_cmd[0] = ATA_16; | 503 | scsi_cmd[0] = ATA_16; |
399 | 504 | ||
400 | scsi_cmd[4] = args[2]; | 505 | scsi_cmd[4] = args[2]; |
401 | if (args[0] == WIN_SMART) { /* hack -- ide driver does this too... */ | 506 | if (args[0] == ATA_CMD_SMART) { /* hack -- ide driver does this too */ |
402 | scsi_cmd[6] = args[3]; | 507 | scsi_cmd[6] = args[3]; |
403 | scsi_cmd[8] = args[1]; | 508 | scsi_cmd[8] = args[1]; |
404 | scsi_cmd[10] = 0x4f; | 509 | scsi_cmd[10] = 0x4f; |
@@ -603,7 +708,11 @@ static struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev, | |||
603 | { | 708 | { |
604 | struct ata_queued_cmd *qc; | 709 | struct ata_queued_cmd *qc; |
605 | 710 | ||
606 | qc = ata_qc_new_init(dev); | 711 | if (cmd->request->tag != -1) |
712 | qc = ata_qc_new_init(dev, cmd->request->tag); | ||
713 | else | ||
714 | qc = ata_qc_new_init(dev, 0); | ||
715 | |||
607 | if (qc) { | 716 | if (qc) { |
608 | qc->scsicmd = cmd; | 717 | qc->scsicmd = cmd; |
609 | qc->scsidone = done; | 718 | qc->scsidone = done; |
@@ -954,6 +1063,9 @@ static int atapi_drain_needed(struct request *rq) | |||
954 | static int ata_scsi_dev_config(struct scsi_device *sdev, | 1063 | static int ata_scsi_dev_config(struct scsi_device *sdev, |
955 | struct ata_device *dev) | 1064 | struct ata_device *dev) |
956 | { | 1065 | { |
1066 | if (!ata_id_has_unload(dev->id)) | ||
1067 | dev->flags |= ATA_DFLAG_NO_UNLOAD; | ||
1068 | |||
957 | /* configure max sectors */ | 1069 | /* configure max sectors */ |
958 | blk_queue_max_sectors(sdev->request_queue, dev->max_sectors); | 1070 | blk_queue_max_sectors(sdev->request_queue, dev->max_sectors); |
959 | 1071 | ||
@@ -977,6 +1089,10 @@ static int ata_scsi_dev_config(struct scsi_device *sdev, | |||
977 | 1089 | ||
978 | blk_queue_dma_drain(q, atapi_drain_needed, buf, ATAPI_MAX_DRAIN); | 1090 | blk_queue_dma_drain(q, atapi_drain_needed, buf, ATAPI_MAX_DRAIN); |
979 | } else { | 1091 | } else { |
1092 | if (ata_id_is_ssd(dev->id)) | ||
1093 | queue_flag_set_unlocked(QUEUE_FLAG_NONROT, | ||
1094 | sdev->request_queue); | ||
1095 | |||
980 | /* ATA devices must be sector aligned */ | 1096 | /* ATA devices must be sector aligned */ |
981 | blk_queue_update_dma_alignment(sdev->request_queue, | 1097 | blk_queue_update_dma_alignment(sdev->request_queue, |
982 | ATA_SECT_SIZE - 1); | 1098 | ATA_SECT_SIZE - 1); |
@@ -991,7 +1107,8 @@ static int ata_scsi_dev_config(struct scsi_device *sdev, | |||
991 | 1107 | ||
992 | depth = min(sdev->host->can_queue, ata_id_queue_depth(dev->id)); | 1108 | depth = min(sdev->host->can_queue, ata_id_queue_depth(dev->id)); |
993 | depth = min(ATA_MAX_QUEUE - 1, depth); | 1109 | depth = min(ATA_MAX_QUEUE - 1, depth); |
994 | scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, depth); | 1110 | scsi_set_tag_type(sdev, MSG_SIMPLE_TAG); |
1111 | scsi_activate_tcq(sdev, depth); | ||
995 | } | 1112 | } |
996 | 1113 | ||
997 | return 0; | 1114 | return 0; |
@@ -1831,6 +1948,11 @@ static unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf) | |||
1831 | hdr[1] |= (1 << 7); | 1948 | hdr[1] |= (1 << 7); |
1832 | 1949 | ||
1833 | memcpy(rbuf, hdr, sizeof(hdr)); | 1950 | memcpy(rbuf, hdr, sizeof(hdr)); |
1951 | |||
1952 | /* if ncq, set tags supported */ | ||
1953 | if (ata_id_has_ncq(args->id)) | ||
1954 | rbuf[7] |= (1 << 1); | ||
1955 | |||
1834 | memcpy(&rbuf[8], "ATA ", 8); | 1956 | memcpy(&rbuf[8], "ATA ", 8); |
1835 | ata_id_string(args->id, &rbuf[16], ATA_ID_PROD, 16); | 1957 | ata_id_string(args->id, &rbuf[16], ATA_ID_PROD, 16); |
1836 | ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV, 4); | 1958 | ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV, 4); |
@@ -2551,36 +2673,6 @@ static struct ata_device *__ata_scsi_find_dev(struct ata_port *ap, | |||
2551 | } | 2673 | } |
2552 | 2674 | ||
2553 | /** | 2675 | /** |
2554 | * ata_scsi_dev_enabled - determine if device is enabled | ||
2555 | * @dev: ATA device | ||
2556 | * | ||
2557 | * Determine if commands should be sent to the specified device. | ||
2558 | * | ||
2559 | * LOCKING: | ||
2560 | * spin_lock_irqsave(host lock) | ||
2561 | * | ||
2562 | * RETURNS: | ||
2563 | * 0 if commands are not allowed / 1 if commands are allowed | ||
2564 | */ | ||
2565 | |||
2566 | static int ata_scsi_dev_enabled(struct ata_device *dev) | ||
2567 | { | ||
2568 | if (unlikely(!ata_dev_enabled(dev))) | ||
2569 | return 0; | ||
2570 | |||
2571 | if (!atapi_enabled || (dev->link->ap->flags & ATA_FLAG_NO_ATAPI)) { | ||
2572 | if (unlikely(dev->class == ATA_DEV_ATAPI)) { | ||
2573 | ata_dev_printk(dev, KERN_WARNING, | ||
2574 | "WARNING: ATAPI is %s, device ignored.\n", | ||
2575 | atapi_enabled ? "not supported with this driver" : "disabled"); | ||
2576 | return 0; | ||
2577 | } | ||
2578 | } | ||
2579 | |||
2580 | return 1; | ||
2581 | } | ||
2582 | |||
2583 | /** | ||
2584 | * ata_scsi_find_dev - lookup ata_device from scsi_cmnd | 2676 | * ata_scsi_find_dev - lookup ata_device from scsi_cmnd |
2585 | * @ap: ATA port to which the device is attached | 2677 | * @ap: ATA port to which the device is attached |
2586 | * @scsidev: SCSI device from which we derive the ATA device | 2678 | * @scsidev: SCSI device from which we derive the ATA device |
@@ -2601,7 +2693,7 @@ ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev) | |||
2601 | { | 2693 | { |
2602 | struct ata_device *dev = __ata_scsi_find_dev(ap, scsidev); | 2694 | struct ata_device *dev = __ata_scsi_find_dev(ap, scsidev); |
2603 | 2695 | ||
2604 | if (unlikely(!dev || !ata_scsi_dev_enabled(dev))) | 2696 | if (unlikely(!dev || !ata_dev_enabled(dev))) |
2605 | return NULL; | 2697 | return NULL; |
2606 | 2698 | ||
2607 | return dev; | 2699 | return dev; |
@@ -3622,7 +3714,7 @@ int ata_sas_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), | |||
3622 | 3714 | ||
3623 | ata_scsi_dump_cdb(ap, cmd); | 3715 | ata_scsi_dump_cdb(ap, cmd); |
3624 | 3716 | ||
3625 | if (likely(ata_scsi_dev_enabled(ap->link.device))) | 3717 | if (likely(ata_dev_enabled(ap->link.device))) |
3626 | rc = __ata_scsi_queuecmd(cmd, done, ap->link.device); | 3718 | rc = __ata_scsi_queuecmd(cmd, done, ap->link.device); |
3627 | else { | 3719 | else { |
3628 | cmd->result = (DID_BAD_TARGET << 16); | 3720 | cmd->result = (DID_BAD_TARGET << 16); |