aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-scsi.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-10-10 10:46:45 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-10-10 10:46:45 -0400
commit82219fceeb654789a9dd7cd3c6cce12dbf659342 (patch)
treed00570c185471efd2c53ceae5d6e509db0603cf8 /drivers/ata/libata-scsi.c
parent3fa8749e584b55f1180411ab1b51117190bac1e5 (diff)
parent0395e61babd59c749fb5efe112affbfaa7d50eb7 (diff)
Merge branch 'upstream-2.6.28' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev
* 'upstream-2.6.28' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev: ata_piix: IDE Mode SATA patch for Intel Ibex Peak DeviceIDs libata-eh: clear UNIT ATTENTION after reset ata_piix: add Hercules EC-900 mini-notebook to ich_laptop short cable list libata: reorder ata_device to remove 8 bytes of padding on 64 bits [libata] pata_bf54x: Add proper PM operation pata_sil680: convert CONFIG_PPC_MERGE to CONFIG_PPC libata: Implement disk shock protection support [libata] Introduce ata_id_has_unload() PATA: RPC now selects HAVE_PATA_PLATFORM for pata platform driver ata_piix: drop merged SCR access and use slave_link instead libata: implement slave_link libata: misc updates to prepare for slave link libata: reimplement link iterator libata: make SCR access ops per-link
Diffstat (limited to 'drivers/ata/libata-scsi.c')
-rw-r--r--drivers/ata/libata-scsi.c108
1 files changed, 108 insertions, 0 deletions
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index b9d3ba423cb2..fccd5e496c62 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);
184EXPORT_SYMBOL_GPL(dev_attr_link_power_management_policy); 184EXPORT_SYMBOL_GPL(dev_attr_link_power_management_policy);
185 185
186static 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
218unlock:
219 spin_unlock_irq(ap->lock);
220
221 return rc ? rc : snprintf(buf, 20, "%u\n", msecs);
222}
223
224static 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 }
276unlock:
277 spin_unlock_irqrestore(ap->lock, flags);
278
279 return rc ? rc : len;
280}
281DEVICE_ATTR(unload_heads, S_IRUGO | S_IWUSR,
282 ata_scsi_park_show, ata_scsi_park_store);
283EXPORT_SYMBOL_GPL(dev_attr_unload_heads);
284
186static void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq) 285static 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);
270EXPORT_SYMBOL_GPL(dev_attr_sw_activity); 369EXPORT_SYMBOL_GPL(dev_attr_sw_activity);
271 370
371struct device_attribute *ata_common_sdev_attrs[] = {
372 &dev_attr_unload_heads,
373 NULL
374};
375EXPORT_SYMBOL_GPL(ata_common_sdev_attrs);
376
272static void ata_scsi_invalid_field(struct scsi_cmnd *cmd, 377static void ata_scsi_invalid_field(struct scsi_cmnd *cmd,
273 void (*done)(struct scsi_cmnd *)) 378 void (*done)(struct scsi_cmnd *))
274{ 379{
@@ -954,6 +1059,9 @@ static int atapi_drain_needed(struct request *rq)
954static int ata_scsi_dev_config(struct scsi_device *sdev, 1059static int ata_scsi_dev_config(struct scsi_device *sdev,
955 struct ata_device *dev) 1060 struct ata_device *dev)
956{ 1061{
1062 if (!ata_id_has_unload(dev->id))
1063 dev->flags |= ATA_DFLAG_NO_UNLOAD;
1064
957 /* configure max sectors */ 1065 /* configure max sectors */
958 blk_queue_max_sectors(sdev->request_queue, dev->max_sectors); 1066 blk_queue_max_sectors(sdev->request_queue, dev->max_sectors);
959 1067