aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2007-05-14 14:28:16 -0400
committerJeff Garzik <jeff@garzik.org>2007-07-09 12:17:31 -0400
commit6746544c3b143ca7071d144f1882ccbe1f47b08d (patch)
tree49106311ab2a748feda2fa91f977f700938d3d5c
parent69b16a5f4c4f1dab70d4d555c487c318c6878b3e (diff)
libata: reimplement ACPI invocation
This patch reimplements ACPI invocation such that, instead of exporting ACPI details to the rest of libata, ACPI event handlers - ata_acpi_on_resume() and ata_acpi_on_devcfg() - are used. These two functions are responsible for determining whether specific ACPI method is used and when. On resume, _GTF is scheduled by setting ATA_DFLAG_ACPI_PENDING device flag. This is done this way to avoid performing the action on wrong device device (device swapping while suspended). On every ata_dev_configure(), ata_acpi_on_devcfg() is called, which performs _SDD and _GTF. _GTF is performed only after resuming and, if SATA, hardreset as the ACPI spec specifies. As _GTF may contain arbitrary commands, IDENTIFY page is re-read after _GTF taskfiles are executed. If one of ACPI methods fails, ata_acpi_on_devcfg() retries on the first failure. If it fails again on the second try, ACPI is disabled on the device. Note that successful configuration clears ACPI failed status. With all feature checks moved to the above two functions, do_drive_set_taskfiles() is trivial and thus collapsed into ata_acpi_exec_tfs(), which is now static and converted to return the number of executed taskfiles to be used by ata_acpi_on_resume(). As failures are handled properly, ata_acpi_push_id() now returns -errno on errors instead of unconditional zero. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r--drivers/ata/libata-acpi.c204
-rw-r--r--drivers/ata/libata-core.c16
-rw-r--r--drivers/ata/libata-eh.c3
-rw-r--r--drivers/ata/libata.h14
-rw-r--r--include/linux/libata.h2
5 files changed, 140 insertions, 99 deletions
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index ae2077e1e78f..e09df442a52f 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -273,91 +273,47 @@ static int taskfile_load_raw(struct ata_device *dev,
273} 273}
274 274
275/** 275/**
276 * ata_dev_set_taskfiles - write the drive taskfile settings from _GTF
277 * @dev: target ATA device
278 * @gtf: pointer to array of _GTF taskfiles to execute
279 * @gtf_count: number of taskfiles
280 *
281 * This applies to both PATA and SATA drives.
282 *
283 * Execute taskfiles in @gtf.
284 *
285 * LOCKING:
286 * EH context.
287 *
288 * RETURNS:
289 * 0 on success, -errno on failure.
290 */
291static int ata_dev_set_taskfiles(struct ata_device *dev,
292 struct ata_acpi_gtf *gtf, int gtf_count)
293{
294 struct ata_port *ap = dev->ap;
295 int ix;
296
297 if (ata_msg_probe(ap))
298 ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER: port#: %d\n",
299 __FUNCTION__, ap->port_no);
300
301 if (!(ap->flags & ATA_FLAG_ACPI_SATA))
302 return 0;
303
304 if (!ata_dev_enabled(dev) || (ap->flags & ATA_FLAG_DISABLED))
305 return -ENODEV;
306
307 /* send all TaskFile registers (0x1f1-0x1f7) *in*that*order* */
308 for (ix = 0; ix < gtf_count; ix++)
309 taskfile_load_raw(dev, gtf++);
310
311 return 0;
312}
313
314/**
315 * ata_acpi_exec_tfs - get then write drive taskfile settings 276 * ata_acpi_exec_tfs - get then write drive taskfile settings
316 * @ap: the ata_port for the drive 277 * @dev: target ATA device
317 * 278 *
318 * This applies to both PATA and SATA drives. 279 * Evaluate _GTF and excute returned taskfiles.
319 * 280 *
320 * LOCKING: 281 * LOCKING:
321 * EH context. 282 * EH context.
322 * 283 *
323 * RETURNS: 284 * RETURNS:
324 * 0 on success, -errno on failure. 285 * Number of executed taskfiles on success, 0 if _GTF doesn't exist or
286 * doesn't contain valid data. -errno on other errors.
325 */ 287 */
326int ata_acpi_exec_tfs(struct ata_port *ap) 288static int ata_acpi_exec_tfs(struct ata_device *dev)
327{ 289{
328 int ix, ret = 0; 290 struct ata_acpi_gtf *gtf = NULL;
329 291 void *ptr_to_free = NULL;
330 /* 292 int gtf_count, i, rc;
331 * TBD - implement PATA support. For now, 293
332 * we should not run GTF on PATA devices since some 294 /* get taskfiles */
333 * PATA require execution of GTM/STM before GTF. 295 rc = ata_dev_get_GTF(dev, &gtf, &ptr_to_free);
334 */ 296 if (rc < 0)
335 if (!(ap->flags & ATA_FLAG_ACPI_SATA)) 297 return rc;
336 return 0; 298 gtf_count = rc;
337 299
338 for (ix = 0; ix < ATA_MAX_DEVICES; ix++) { 300 /* execute them */
339 struct ata_device *dev = &ap->device[ix]; 301 for (i = 0, rc = 0; i < gtf_count; i++) {
340 struct ata_acpi_gtf *gtf = NULL; 302 int tmp;
341 int gtf_count; 303
342 void *ptr_to_free = NULL; 304 /* ACPI errors are eventually ignored. Run till the
343 305 * end even after errors.
344 if (!ata_dev_enabled(dev)) 306 */
345 continue; 307 tmp = taskfile_load_raw(dev, gtf++);
346 308 if (!rc)
347 ret = ata_dev_get_GTF(dev, &gtf, &ptr_to_free); 309 rc = tmp;
348 if (ret == 0)
349 continue;
350 if (ret < 0)
351 break;
352 gtf_count = ret;
353
354 ret = ata_dev_set_taskfiles(dev, gtf, gtf_count);
355 kfree(ptr_to_free);
356 if (ret < 0)
357 break;
358 } 310 }
359 311
360 return ret; 312 kfree(ptr_to_free);
313
314 if (rc == 0)
315 return gtf_count;
316 return rc;
361} 317}
362 318
363/** 319/**
@@ -376,7 +332,7 @@ int ata_acpi_exec_tfs(struct ata_port *ap)
376 * RETURNS: 332 * RETURNS:
377 * 0 on success, -errno on failure. 333 * 0 on success, -errno on failure.
378 */ 334 */
379int ata_acpi_push_id(struct ata_device *dev) 335static int ata_acpi_push_id(struct ata_device *dev)
380{ 336{
381 struct ata_port *ap = dev->ap; 337 struct ata_port *ap = dev->ap;
382 int err; 338 int err;
@@ -396,7 +352,7 @@ int ata_acpi_push_id(struct ata_device *dev)
396 if (ata_msg_probe(ap)) 352 if (ata_msg_probe(ap))
397 ata_dev_printk(dev, KERN_DEBUG, 353 ata_dev_printk(dev, KERN_DEBUG,
398 "%s: Not a SATA device\n", __FUNCTION__); 354 "%s: Not a SATA device\n", __FUNCTION__);
399 goto out; 355 return 0;
400 } 356 }
401 357
402 /* Give the drive Identify data to the drive via the _SDD method */ 358 /* Give the drive Identify data to the drive via the _SDD method */
@@ -418,9 +374,99 @@ int ata_acpi_push_id(struct ata_device *dev)
418 ata_dev_printk(dev, KERN_WARNING, 374 ata_dev_printk(dev, KERN_WARNING,
419 "ACPI _SDD failed (AE 0x%x)\n", status); 375 "ACPI _SDD failed (AE 0x%x)\n", status);
420 376
421 /* always return success */ 377 return err;
422out: 378}
423 return 0; 379
380/**
381 * ata_acpi_on_resume - ATA ACPI hook called on resume
382 * @ap: target ATA port
383 *
384 * This function is called when @ap is resumed - right after port
385 * itself is resumed but before any EH action is taken.
386 *
387 * LOCKING:
388 * EH context.
389 */
390void ata_acpi_on_resume(struct ata_port *ap)
391{
392 int i;
393
394 /* schedule _GTF */
395 for (i = 0; i < ATA_MAX_DEVICES; i++)
396 ap->device[i].flags |= ATA_DFLAG_ACPI_PENDING;
424} 397}
425 398
399/**
400 * ata_acpi_on_devcfg - ATA ACPI hook called on device donfiguration
401 * @dev: target ATA device
402 *
403 * This function is called when @dev is about to be configured.
404 * IDENTIFY data might have been modified after this hook is run.
405 *
406 * LOCKING:
407 * EH context.
408 *
409 * RETURNS:
410 * Positive number if IDENTIFY data needs to be refreshed, 0 if not,
411 * -errno on failure.
412 */
413int ata_acpi_on_devcfg(struct ata_device *dev)
414{
415 struct ata_port *ap = dev->ap;
416 struct ata_eh_context *ehc = &ap->eh_context;
417 int acpi_sata = ap->flags & ATA_FLAG_ACPI_SATA;
418 int rc;
419
420 /* XXX: _STM isn't implemented yet, skip if IDE for now */
421 if (!acpi_sata)
422 return 0;
426 423
424 if (!dev->acpi_handle)
425 return 0;
426
427 /* do we need to do _GTF? */
428 if (!(dev->flags & ATA_DFLAG_ACPI_PENDING) &&
429 !(acpi_sata && (ehc->i.flags & ATA_EHI_DID_HARDRESET)))
430 return 0;
431
432 /* do _SDD if SATA */
433 if (acpi_sata) {
434 rc = ata_acpi_push_id(dev);
435 if (rc)
436 goto acpi_err;
437 }
438
439 /* do _GTF */
440 rc = ata_acpi_exec_tfs(dev);
441 if (rc < 0)
442 goto acpi_err;
443
444 dev->flags &= ~ATA_DFLAG_ACPI_PENDING;
445
446 /* refresh IDENTIFY page if any _GTF command has been executed */
447 if (rc > 0) {
448 rc = ata_dev_reread_id(dev, 0);
449 if (rc < 0) {
450 ata_dev_printk(dev, KERN_ERR, "failed to IDENTIFY "
451 "after ACPI commands\n");
452 return rc;
453 }
454 }
455
456 return 0;
457
458 acpi_err:
459 /* let EH retry on the first failure, disable ACPI on the second */
460 if (dev->flags & ATA_DFLAG_ACPI_FAILED) {
461 ata_dev_printk(dev, KERN_WARNING, "ACPI on devcfg failed the "
462 "second time, disabling (errno=%d)\n", rc);
463
464 dev->acpi_handle = NULL;
465
466 /* if port is working, request IDENTIFY reload and continue */
467 if (!(ap->pflags & ATA_PFLAG_FROZEN))
468 rc = 1;
469 }
470 dev->flags |= ATA_DFLAG_ACPI_FAILED;
471 return rc;
472}
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 5a46cdebc588..90ed2b9a34de 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -1845,7 +1845,8 @@ static void ata_dev_config_ncq(struct ata_device *dev,
1845int ata_dev_configure(struct ata_device *dev) 1845int ata_dev_configure(struct ata_device *dev)
1846{ 1846{
1847 struct ata_port *ap = dev->ap; 1847 struct ata_port *ap = dev->ap;
1848 int print_info = ap->eh_context.i.flags & ATA_EHI_PRINTINFO; 1848 struct ata_eh_context *ehc = &ap->eh_context;
1849 int print_info = ehc->i.flags & ATA_EHI_PRINTINFO;
1849 const u16 *id = dev->id; 1850 const u16 *id = dev->id;
1850 unsigned int xfer_mask; 1851 unsigned int xfer_mask;
1851 char revbuf[7]; /* XYZ-99\0 */ 1852 char revbuf[7]; /* XYZ-99\0 */
@@ -1862,15 +1863,10 @@ int ata_dev_configure(struct ata_device *dev)
1862 if (ata_msg_probe(ap)) 1863 if (ata_msg_probe(ap))
1863 ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __FUNCTION__); 1864 ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __FUNCTION__);
1864 1865
1865 /* set _SDD */ 1866 /* let ACPI work its magic */
1866 rc = ata_acpi_push_id(dev); 1867 rc = ata_acpi_on_devcfg(dev);
1867 if (rc) { 1868 if (rc)
1868 ata_dev_printk(dev, KERN_WARNING, "failed to set _SDD(%d)\n", 1869 return rc;
1869 rc);
1870 }
1871
1872 /* retrieve and execute the ATA task file of _GTF */
1873 ata_acpi_exec_tfs(ap);
1874 1870
1875 /* print device capabilities */ 1871 /* print device capabilities */
1876 if (ata_msg_probe(ap)) 1872 if (ata_msg_probe(ap))
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index f7582c9c320e..fed217db82d2 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -2207,6 +2207,9 @@ static void ata_eh_handle_port_resume(struct ata_port *ap)
2207 if (ap->ops->port_resume) 2207 if (ap->ops->port_resume)
2208 rc = ap->ops->port_resume(ap); 2208 rc = ap->ops->port_resume(ap);
2209 2209
2210 /* tell ACPI that we're resuming */
2211 ata_acpi_on_resume(ap);
2212
2210 /* report result */ 2213 /* report result */
2211 spin_lock_irqsave(ap->lock, flags); 2214 spin_lock_irqsave(ap->lock, flags);
2212 ap->pflags &= ~(ATA_PFLAG_PM_PENDING | ATA_PFLAG_SUSPENDED); 2215 ap->pflags &= ~(ATA_PFLAG_PM_PENDING | ATA_PFLAG_SUSPENDED);
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 29037cd7c651..bee7cbc4c97c 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -99,18 +99,12 @@ extern struct ata_port *ata_port_alloc(struct ata_host *host);
99/* libata-acpi.c */ 99/* libata-acpi.c */
100#ifdef CONFIG_ATA_ACPI 100#ifdef CONFIG_ATA_ACPI
101extern void ata_acpi_associate(struct ata_host *host); 101extern void ata_acpi_associate(struct ata_host *host);
102extern int ata_acpi_exec_tfs(struct ata_port *ap); 102extern void ata_acpi_on_resume(struct ata_port *ap);
103extern int ata_acpi_push_id(struct ata_device *dev); 103extern int ata_acpi_on_devcfg(struct ata_device *adev);
104#else 104#else
105static inline void ata_acpi_associate(struct ata_host *host) { } 105static inline void ata_acpi_associate(struct ata_host *host) { }
106static inline int ata_acpi_exec_tfs(struct ata_port *ap) 106static inline void ata_acpi_on_resume(struct ata_port *ap) { }
107{ 107static inline int ata_acpi_on_devcfg(struct ata_device *adev) { return 0; }
108 return 0;
109}
110static inline int ata_acpi_push_id(struct ata_device *dev)
111{
112 return 0;
113}
114#endif 108#endif
115 109
116/* libata-scsi.c */ 110/* libata-scsi.c */
diff --git a/include/linux/libata.h b/include/linux/libata.h
index d758168ee45d..0c4f63b55ec6 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -136,6 +136,8 @@ enum {
136 ATA_DFLAG_CDB_INTR = (1 << 2), /* device asserts INTRQ when ready for CDB */ 136 ATA_DFLAG_CDB_INTR = (1 << 2), /* device asserts INTRQ when ready for CDB */
137 ATA_DFLAG_NCQ = (1 << 3), /* device supports NCQ */ 137 ATA_DFLAG_NCQ = (1 << 3), /* device supports NCQ */
138 ATA_DFLAG_FLUSH_EXT = (1 << 4), /* do FLUSH_EXT instead of FLUSH */ 138 ATA_DFLAG_FLUSH_EXT = (1 << 4), /* do FLUSH_EXT instead of FLUSH */
139 ATA_DFLAG_ACPI_PENDING = (1 << 5), /* ACPI resume action pending */
140 ATA_DFLAG_ACPI_FAILED = (1 << 6), /* ACPI on devcfg has failed */
139 ATA_DFLAG_CFG_MASK = (1 << 8) - 1, 141 ATA_DFLAG_CFG_MASK = (1 << 8) - 1,
140 142
141 ATA_DFLAG_PIO = (1 << 8), /* device limited to PIO mode */ 143 ATA_DFLAG_PIO = (1 << 8), /* device limited to PIO mode */