diff options
author | Tejun Heo <htejun@gmail.com> | 2006-05-15 07:57:46 -0400 |
---|---|---|
committer | Tejun Heo <htejun@gmail.com> | 2006-05-15 07:57:46 -0400 |
commit | 34bf21704c848fe00c516d1c8f163db08b70b137 (patch) | |
tree | 8482de3ddf6ff1b02ff9ddfd027d2478c7ecd7ac | |
parent | 838df6284c54447efae956fb9c243d8ba4ab0f47 (diff) |
[PATCH] libata: implement new SCR handling and port on/offline functions
Implement ata_scr_{valid|read|write|write_flush}() and
ata_port_{online|offline}(). These functions replace
scr_{read|write}() and sata_dev_present().
Major difference between between the new SCR functions and the old
ones is that the new ones have a way to signal error to the caller.
This makes handling SCR-available and SCR-unavailable cases in the
same path easier. Also, it eases later PM implementation where SCR
access can fail due to various reasons.
ata_port_{online|offline}() functions return 1 only when they are
affirmitive of the condition. e.g. if SCR is unaccessible or
presence cannot be determined for other reasons, these functions
return 0. So, ata_port_online() != !ata_port_offline(). This
distinction is useful in many exception handling cases.
Signed-off-by: Tejun Heo <htejun@gmail.com>
-rw-r--r-- | drivers/scsi/libata-core.c | 143 | ||||
-rw-r--r-- | include/linux/libata.h | 6 |
2 files changed, 149 insertions, 0 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index f29d43cb6991..b9c5cbf0b786 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c | |||
@@ -4365,6 +4365,143 @@ irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs) | |||
4365 | return IRQ_RETVAL(handled); | 4365 | return IRQ_RETVAL(handled); |
4366 | } | 4366 | } |
4367 | 4367 | ||
4368 | /** | ||
4369 | * sata_scr_valid - test whether SCRs are accessible | ||
4370 | * @ap: ATA port to test SCR accessibility for | ||
4371 | * | ||
4372 | * Test whether SCRs are accessible for @ap. | ||
4373 | * | ||
4374 | * LOCKING: | ||
4375 | * None. | ||
4376 | * | ||
4377 | * RETURNS: | ||
4378 | * 1 if SCRs are accessible, 0 otherwise. | ||
4379 | */ | ||
4380 | int sata_scr_valid(struct ata_port *ap) | ||
4381 | { | ||
4382 | return ap->cbl == ATA_CBL_SATA && ap->ops->scr_read; | ||
4383 | } | ||
4384 | |||
4385 | /** | ||
4386 | * sata_scr_read - read SCR register of the specified port | ||
4387 | * @ap: ATA port to read SCR for | ||
4388 | * @reg: SCR to read | ||
4389 | * @val: Place to store read value | ||
4390 | * | ||
4391 | * Read SCR register @reg of @ap into *@val. This function is | ||
4392 | * guaranteed to succeed if the cable type of the port is SATA | ||
4393 | * and the port implements ->scr_read. | ||
4394 | * | ||
4395 | * LOCKING: | ||
4396 | * None. | ||
4397 | * | ||
4398 | * RETURNS: | ||
4399 | * 0 on success, negative errno on failure. | ||
4400 | */ | ||
4401 | int sata_scr_read(struct ata_port *ap, int reg, u32 *val) | ||
4402 | { | ||
4403 | if (sata_scr_valid(ap)) { | ||
4404 | *val = ap->ops->scr_read(ap, reg); | ||
4405 | return 0; | ||
4406 | } | ||
4407 | return -EOPNOTSUPP; | ||
4408 | } | ||
4409 | |||
4410 | /** | ||
4411 | * sata_scr_write - write SCR register of the specified port | ||
4412 | * @ap: ATA port to write SCR for | ||
4413 | * @reg: SCR to write | ||
4414 | * @val: value to write | ||
4415 | * | ||
4416 | * Write @val to SCR register @reg of @ap. This function is | ||
4417 | * guaranteed to succeed if the cable type of the port is SATA | ||
4418 | * and the port implements ->scr_read. | ||
4419 | * | ||
4420 | * LOCKING: | ||
4421 | * None. | ||
4422 | * | ||
4423 | * RETURNS: | ||
4424 | * 0 on success, negative errno on failure. | ||
4425 | */ | ||
4426 | int sata_scr_write(struct ata_port *ap, int reg, u32 val) | ||
4427 | { | ||
4428 | if (sata_scr_valid(ap)) { | ||
4429 | ap->ops->scr_write(ap, reg, val); | ||
4430 | return 0; | ||
4431 | } | ||
4432 | return -EOPNOTSUPP; | ||
4433 | } | ||
4434 | |||
4435 | /** | ||
4436 | * sata_scr_write_flush - write SCR register of the specified port and flush | ||
4437 | * @ap: ATA port to write SCR for | ||
4438 | * @reg: SCR to write | ||
4439 | * @val: value to write | ||
4440 | * | ||
4441 | * This function is identical to sata_scr_write() except that this | ||
4442 | * function performs flush after writing to the register. | ||
4443 | * | ||
4444 | * LOCKING: | ||
4445 | * None. | ||
4446 | * | ||
4447 | * RETURNS: | ||
4448 | * 0 on success, negative errno on failure. | ||
4449 | */ | ||
4450 | int sata_scr_write_flush(struct ata_port *ap, int reg, u32 val) | ||
4451 | { | ||
4452 | if (sata_scr_valid(ap)) { | ||
4453 | ap->ops->scr_write(ap, reg, val); | ||
4454 | ap->ops->scr_read(ap, reg); | ||
4455 | return 0; | ||
4456 | } | ||
4457 | return -EOPNOTSUPP; | ||
4458 | } | ||
4459 | |||
4460 | /** | ||
4461 | * ata_port_online - test whether the given port is online | ||
4462 | * @ap: ATA port to test | ||
4463 | * | ||
4464 | * Test whether @ap is online. Note that this function returns 0 | ||
4465 | * if online status of @ap cannot be obtained, so | ||
4466 | * ata_port_online(ap) != !ata_port_offline(ap). | ||
4467 | * | ||
4468 | * LOCKING: | ||
4469 | * None. | ||
4470 | * | ||
4471 | * RETURNS: | ||
4472 | * 1 if the port online status is available and online. | ||
4473 | */ | ||
4474 | int ata_port_online(struct ata_port *ap) | ||
4475 | { | ||
4476 | u32 sstatus; | ||
4477 | |||
4478 | if (!sata_scr_read(ap, SCR_STATUS, &sstatus) && (sstatus & 0xf) == 0x3) | ||
4479 | return 1; | ||
4480 | return 0; | ||
4481 | } | ||
4482 | |||
4483 | /** | ||
4484 | * ata_port_offline - test whether the given port is offline | ||
4485 | * @ap: ATA port to test | ||
4486 | * | ||
4487 | * Test whether @ap is offline. Note that this function returns | ||
4488 | * 0 if offline status of @ap cannot be obtained, so | ||
4489 | * ata_port_online(ap) != !ata_port_offline(ap). | ||
4490 | * | ||
4491 | * LOCKING: | ||
4492 | * None. | ||
4493 | * | ||
4494 | * RETURNS: | ||
4495 | * 1 if the port offline status is available and offline. | ||
4496 | */ | ||
4497 | int ata_port_offline(struct ata_port *ap) | ||
4498 | { | ||
4499 | u32 sstatus; | ||
4500 | |||
4501 | if (!sata_scr_read(ap, SCR_STATUS, &sstatus) && (sstatus & 0xf) != 0x3) | ||
4502 | return 1; | ||
4503 | return 0; | ||
4504 | } | ||
4368 | 4505 | ||
4369 | /* | 4506 | /* |
4370 | * Execute a 'simple' command, that only consists of the opcode 'cmd' itself, | 4507 | * Execute a 'simple' command, that only consists of the opcode 'cmd' itself, |
@@ -5133,6 +5270,12 @@ EXPORT_SYMBOL_GPL(ata_scsi_queuecmd); | |||
5133 | EXPORT_SYMBOL_GPL(ata_scsi_slave_config); | 5270 | EXPORT_SYMBOL_GPL(ata_scsi_slave_config); |
5134 | EXPORT_SYMBOL_GPL(ata_scsi_release); | 5271 | EXPORT_SYMBOL_GPL(ata_scsi_release); |
5135 | EXPORT_SYMBOL_GPL(ata_host_intr); | 5272 | EXPORT_SYMBOL_GPL(ata_host_intr); |
5273 | EXPORT_SYMBOL_GPL(sata_scr_valid); | ||
5274 | EXPORT_SYMBOL_GPL(sata_scr_read); | ||
5275 | EXPORT_SYMBOL_GPL(sata_scr_write); | ||
5276 | EXPORT_SYMBOL_GPL(sata_scr_write_flush); | ||
5277 | EXPORT_SYMBOL_GPL(ata_port_online); | ||
5278 | EXPORT_SYMBOL_GPL(ata_port_offline); | ||
5136 | EXPORT_SYMBOL_GPL(ata_id_string); | 5279 | EXPORT_SYMBOL_GPL(ata_id_string); |
5137 | EXPORT_SYMBOL_GPL(ata_id_c_string); | 5280 | EXPORT_SYMBOL_GPL(ata_id_c_string); |
5138 | EXPORT_SYMBOL_GPL(ata_scsi_simulate); | 5281 | EXPORT_SYMBOL_GPL(ata_scsi_simulate); |
diff --git a/include/linux/libata.h b/include/linux/libata.h index a4b8a419caad..47b97157995d 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h | |||
@@ -536,6 +536,12 @@ extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg); | |||
536 | extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)); | 536 | extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)); |
537 | extern int ata_scsi_release(struct Scsi_Host *host); | 537 | extern int ata_scsi_release(struct Scsi_Host *host); |
538 | extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); | 538 | extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); |
539 | extern int sata_scr_valid(struct ata_port *ap); | ||
540 | extern int sata_scr_read(struct ata_port *ap, int reg, u32 *val); | ||
541 | extern int sata_scr_write(struct ata_port *ap, int reg, u32 val); | ||
542 | extern int sata_scr_write_flush(struct ata_port *ap, int reg, u32 val); | ||
543 | extern int ata_port_online(struct ata_port *ap); | ||
544 | extern int ata_port_offline(struct ata_port *ap); | ||
539 | extern int ata_scsi_device_resume(struct scsi_device *); | 545 | extern int ata_scsi_device_resume(struct scsi_device *); |
540 | extern int ata_scsi_device_suspend(struct scsi_device *, pm_message_t state); | 546 | extern int ata_scsi_device_suspend(struct scsi_device *, pm_message_t state); |
541 | extern int ata_device_resume(struct ata_port *, struct ata_device *); | 547 | extern int ata_device_resume(struct ata_port *, struct ata_device *); |