aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-acpi.c
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 /drivers/ata/libata-acpi.c
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>
Diffstat (limited to 'drivers/ata/libata-acpi.c')
-rw-r--r--drivers/ata/libata-acpi.c204
1 files changed, 125 insertions, 79 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}