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 /drivers/scsi/libata-core.c | |
| 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>
Diffstat (limited to 'drivers/scsi/libata-core.c')
| -rw-r--r-- | drivers/scsi/libata-core.c | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index f29d43cb699..b9c5cbf0b78 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); |
