aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libata-core.c
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2006-05-15 07:57:46 -0400
committerTejun Heo <htejun@gmail.com>2006-05-15 07:57:46 -0400
commit34bf21704c848fe00c516d1c8f163db08b70b137 (patch)
tree8482de3ddf6ff1b02ff9ddfd027d2478c7ecd7ac /drivers/scsi/libata-core.c
parent838df6284c54447efae956fb9c243d8ba4ab0f47 (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.c143
1 files changed, 143 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 */
4380int 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 */
4401int 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 */
4426int 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 */
4450int 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 */
4474int 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 */
4497int 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);
5133EXPORT_SYMBOL_GPL(ata_scsi_slave_config); 5270EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
5134EXPORT_SYMBOL_GPL(ata_scsi_release); 5271EXPORT_SYMBOL_GPL(ata_scsi_release);
5135EXPORT_SYMBOL_GPL(ata_host_intr); 5272EXPORT_SYMBOL_GPL(ata_host_intr);
5273EXPORT_SYMBOL_GPL(sata_scr_valid);
5274EXPORT_SYMBOL_GPL(sata_scr_read);
5275EXPORT_SYMBOL_GPL(sata_scr_write);
5276EXPORT_SYMBOL_GPL(sata_scr_write_flush);
5277EXPORT_SYMBOL_GPL(ata_port_online);
5278EXPORT_SYMBOL_GPL(ata_port_offline);
5136EXPORT_SYMBOL_GPL(ata_id_string); 5279EXPORT_SYMBOL_GPL(ata_id_string);
5137EXPORT_SYMBOL_GPL(ata_id_c_string); 5280EXPORT_SYMBOL_GPL(ata_id_c_string);
5138EXPORT_SYMBOL_GPL(ata_scsi_simulate); 5281EXPORT_SYMBOL_GPL(ata_scsi_simulate);