mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-19 02:04:19 +08:00
[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>
This commit is contained in:
parent
838df6284c
commit
34bf21704c
@ -4365,6 +4365,143 @@ irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
|
||||
return IRQ_RETVAL(handled);
|
||||
}
|
||||
|
||||
/**
|
||||
* sata_scr_valid - test whether SCRs are accessible
|
||||
* @ap: ATA port to test SCR accessibility for
|
||||
*
|
||||
* Test whether SCRs are accessible for @ap.
|
||||
*
|
||||
* LOCKING:
|
||||
* None.
|
||||
*
|
||||
* RETURNS:
|
||||
* 1 if SCRs are accessible, 0 otherwise.
|
||||
*/
|
||||
int sata_scr_valid(struct ata_port *ap)
|
||||
{
|
||||
return ap->cbl == ATA_CBL_SATA && ap->ops->scr_read;
|
||||
}
|
||||
|
||||
/**
|
||||
* sata_scr_read - read SCR register of the specified port
|
||||
* @ap: ATA port to read SCR for
|
||||
* @reg: SCR to read
|
||||
* @val: Place to store read value
|
||||
*
|
||||
* Read SCR register @reg of @ap into *@val. This function is
|
||||
* guaranteed to succeed if the cable type of the port is SATA
|
||||
* and the port implements ->scr_read.
|
||||
*
|
||||
* LOCKING:
|
||||
* None.
|
||||
*
|
||||
* RETURNS:
|
||||
* 0 on success, negative errno on failure.
|
||||
*/
|
||||
int sata_scr_read(struct ata_port *ap, int reg, u32 *val)
|
||||
{
|
||||
if (sata_scr_valid(ap)) {
|
||||
*val = ap->ops->scr_read(ap, reg);
|
||||
return 0;
|
||||
}
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/**
|
||||
* sata_scr_write - write SCR register of the specified port
|
||||
* @ap: ATA port to write SCR for
|
||||
* @reg: SCR to write
|
||||
* @val: value to write
|
||||
*
|
||||
* Write @val to SCR register @reg of @ap. This function is
|
||||
* guaranteed to succeed if the cable type of the port is SATA
|
||||
* and the port implements ->scr_read.
|
||||
*
|
||||
* LOCKING:
|
||||
* None.
|
||||
*
|
||||
* RETURNS:
|
||||
* 0 on success, negative errno on failure.
|
||||
*/
|
||||
int sata_scr_write(struct ata_port *ap, int reg, u32 val)
|
||||
{
|
||||
if (sata_scr_valid(ap)) {
|
||||
ap->ops->scr_write(ap, reg, val);
|
||||
return 0;
|
||||
}
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/**
|
||||
* sata_scr_write_flush - write SCR register of the specified port and flush
|
||||
* @ap: ATA port to write SCR for
|
||||
* @reg: SCR to write
|
||||
* @val: value to write
|
||||
*
|
||||
* This function is identical to sata_scr_write() except that this
|
||||
* function performs flush after writing to the register.
|
||||
*
|
||||
* LOCKING:
|
||||
* None.
|
||||
*
|
||||
* RETURNS:
|
||||
* 0 on success, negative errno on failure.
|
||||
*/
|
||||
int sata_scr_write_flush(struct ata_port *ap, int reg, u32 val)
|
||||
{
|
||||
if (sata_scr_valid(ap)) {
|
||||
ap->ops->scr_write(ap, reg, val);
|
||||
ap->ops->scr_read(ap, reg);
|
||||
return 0;
|
||||
}
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_port_online - test whether the given port is online
|
||||
* @ap: ATA port to test
|
||||
*
|
||||
* Test whether @ap is online. Note that this function returns 0
|
||||
* if online status of @ap cannot be obtained, so
|
||||
* ata_port_online(ap) != !ata_port_offline(ap).
|
||||
*
|
||||
* LOCKING:
|
||||
* None.
|
||||
*
|
||||
* RETURNS:
|
||||
* 1 if the port online status is available and online.
|
||||
*/
|
||||
int ata_port_online(struct ata_port *ap)
|
||||
{
|
||||
u32 sstatus;
|
||||
|
||||
if (!sata_scr_read(ap, SCR_STATUS, &sstatus) && (sstatus & 0xf) == 0x3)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_port_offline - test whether the given port is offline
|
||||
* @ap: ATA port to test
|
||||
*
|
||||
* Test whether @ap is offline. Note that this function returns
|
||||
* 0 if offline status of @ap cannot be obtained, so
|
||||
* ata_port_online(ap) != !ata_port_offline(ap).
|
||||
*
|
||||
* LOCKING:
|
||||
* None.
|
||||
*
|
||||
* RETURNS:
|
||||
* 1 if the port offline status is available and offline.
|
||||
*/
|
||||
int ata_port_offline(struct ata_port *ap)
|
||||
{
|
||||
u32 sstatus;
|
||||
|
||||
if (!sata_scr_read(ap, SCR_STATUS, &sstatus) && (sstatus & 0xf) != 0x3)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute a 'simple' command, that only consists of the opcode 'cmd' itself,
|
||||
@ -5133,6 +5270,12 @@ EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
|
||||
EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
|
||||
EXPORT_SYMBOL_GPL(ata_scsi_release);
|
||||
EXPORT_SYMBOL_GPL(ata_host_intr);
|
||||
EXPORT_SYMBOL_GPL(sata_scr_valid);
|
||||
EXPORT_SYMBOL_GPL(sata_scr_read);
|
||||
EXPORT_SYMBOL_GPL(sata_scr_write);
|
||||
EXPORT_SYMBOL_GPL(sata_scr_write_flush);
|
||||
EXPORT_SYMBOL_GPL(ata_port_online);
|
||||
EXPORT_SYMBOL_GPL(ata_port_offline);
|
||||
EXPORT_SYMBOL_GPL(ata_id_string);
|
||||
EXPORT_SYMBOL_GPL(ata_id_c_string);
|
||||
EXPORT_SYMBOL_GPL(ata_scsi_simulate);
|
||||
|
@ -536,6 +536,12 @@ extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg);
|
||||
extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *));
|
||||
extern int ata_scsi_release(struct Scsi_Host *host);
|
||||
extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc);
|
||||
extern int sata_scr_valid(struct ata_port *ap);
|
||||
extern int sata_scr_read(struct ata_port *ap, int reg, u32 *val);
|
||||
extern int sata_scr_write(struct ata_port *ap, int reg, u32 val);
|
||||
extern int sata_scr_write_flush(struct ata_port *ap, int reg, u32 val);
|
||||
extern int ata_port_online(struct ata_port *ap);
|
||||
extern int ata_port_offline(struct ata_port *ap);
|
||||
extern int ata_scsi_device_resume(struct scsi_device *);
|
||||
extern int ata_scsi_device_suspend(struct scsi_device *, pm_message_t state);
|
||||
extern int ata_device_resume(struct ata_port *, struct ata_device *);
|
||||
|
Loading…
Reference in New Issue
Block a user