mirror of
https://github.com/torvalds/linux.git
synced 2024-11-15 16:41:58 +00:00
[PATCH] libata: implement ata_drive_probe_reset()
Most low level drivers share supported reset/classify actions and sequence. This patch implements ata_drive_probe_reset() which helps constructing ->probe_reset from three component operations - softreset, hardreset and postreset. This minimizes duplicate code and yet allows flexibility if needed. The three component operations can also be shared by EH later. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
This commit is contained in:
parent
c19ba8af4f
commit
a62c0fc526
@ -2233,6 +2233,94 @@ err_out:
|
|||||||
DPRINTK("EXIT\n");
|
DPRINTK("EXIT\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int do_probe_reset(struct ata_port *ap, ata_reset_fn_t reset,
|
||||||
|
ata_postreset_fn_t postreset,
|
||||||
|
unsigned int *classes)
|
||||||
|
{
|
||||||
|
int i, rc;
|
||||||
|
|
||||||
|
for (i = 0; i < ATA_MAX_DEVICES; i++)
|
||||||
|
classes[i] = ATA_DEV_UNKNOWN;
|
||||||
|
|
||||||
|
rc = reset(ap, 0, classes);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/* If any class isn't ATA_DEV_UNKNOWN, consider classification
|
||||||
|
* is complete and convert all ATA_DEV_UNKNOWN to
|
||||||
|
* ATA_DEV_NONE.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < ATA_MAX_DEVICES; i++)
|
||||||
|
if (classes[i] != ATA_DEV_UNKNOWN)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (i < ATA_MAX_DEVICES)
|
||||||
|
for (i = 0; i < ATA_MAX_DEVICES; i++)
|
||||||
|
if (classes[i] == ATA_DEV_UNKNOWN)
|
||||||
|
classes[i] = ATA_DEV_NONE;
|
||||||
|
|
||||||
|
if (postreset)
|
||||||
|
postreset(ap, classes);
|
||||||
|
|
||||||
|
return classes[0] != ATA_DEV_UNKNOWN ? 0 : -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ata_drive_probe_reset - Perform probe reset with given methods
|
||||||
|
* @ap: port to reset
|
||||||
|
* @softreset: softreset method (can be NULL)
|
||||||
|
* @hardreset: hardreset method (can be NULL)
|
||||||
|
* @postreset: postreset method (can be NULL)
|
||||||
|
* @classes: resulting classes of attached devices
|
||||||
|
*
|
||||||
|
* Reset the specified port and classify attached devices using
|
||||||
|
* given methods. This function prefers softreset but tries all
|
||||||
|
* possible reset sequences to reset and classify devices. This
|
||||||
|
* function is intended to be used for constructing ->probe_reset
|
||||||
|
* callback by low level drivers.
|
||||||
|
*
|
||||||
|
* Reset methods should follow the following rules.
|
||||||
|
*
|
||||||
|
* - Return 0 on sucess, -errno on failure.
|
||||||
|
* - If classification is supported, fill classes[] with
|
||||||
|
* recognized class codes.
|
||||||
|
* - If classification is not supported, leave classes[] alone.
|
||||||
|
* - If verbose is non-zero, print error message on failure;
|
||||||
|
* otherwise, shut up.
|
||||||
|
*
|
||||||
|
* LOCKING:
|
||||||
|
* Kernel thread context (may sleep)
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* 0 on success, -EINVAL if no reset method is avaliable, -ENODEV
|
||||||
|
* if classification fails, and any error code from reset
|
||||||
|
* methods.
|
||||||
|
*/
|
||||||
|
int ata_drive_probe_reset(struct ata_port *ap,
|
||||||
|
ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
|
||||||
|
ata_postreset_fn_t postreset, unsigned int *classes)
|
||||||
|
{
|
||||||
|
int rc = -EINVAL;
|
||||||
|
|
||||||
|
if (softreset) {
|
||||||
|
rc = do_probe_reset(ap, softreset, postreset, classes);
|
||||||
|
if (rc == 0)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hardreset)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
rc = do_probe_reset(ap, hardreset, postreset, classes);
|
||||||
|
if (rc == 0 || rc != -ENODEV)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
if (softreset)
|
||||||
|
rc = do_probe_reset(ap, softreset, postreset, classes);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
static void ata_pr_blacklisted(const struct ata_port *ap,
|
static void ata_pr_blacklisted(const struct ata_port *ap,
|
||||||
const struct ata_device *dev)
|
const struct ata_device *dev)
|
||||||
{
|
{
|
||||||
@ -5180,6 +5268,7 @@ EXPORT_SYMBOL_GPL(ata_port_probe);
|
|||||||
EXPORT_SYMBOL_GPL(sata_phy_reset);
|
EXPORT_SYMBOL_GPL(sata_phy_reset);
|
||||||
EXPORT_SYMBOL_GPL(__sata_phy_reset);
|
EXPORT_SYMBOL_GPL(__sata_phy_reset);
|
||||||
EXPORT_SYMBOL_GPL(ata_bus_reset);
|
EXPORT_SYMBOL_GPL(ata_bus_reset);
|
||||||
|
EXPORT_SYMBOL_GPL(ata_drive_probe_reset);
|
||||||
EXPORT_SYMBOL_GPL(ata_port_disable);
|
EXPORT_SYMBOL_GPL(ata_port_disable);
|
||||||
EXPORT_SYMBOL_GPL(ata_ratelimit);
|
EXPORT_SYMBOL_GPL(ata_ratelimit);
|
||||||
EXPORT_SYMBOL_GPL(ata_busy_sleep);
|
EXPORT_SYMBOL_GPL(ata_busy_sleep);
|
||||||
|
@ -241,6 +241,8 @@ struct ata_queued_cmd;
|
|||||||
|
|
||||||
/* typedefs */
|
/* typedefs */
|
||||||
typedef void (*ata_qc_cb_t) (struct ata_queued_cmd *qc);
|
typedef void (*ata_qc_cb_t) (struct ata_queued_cmd *qc);
|
||||||
|
typedef int (*ata_reset_fn_t)(struct ata_port *, int, unsigned int *);
|
||||||
|
typedef void (*ata_postreset_fn_t)(struct ata_port *ap, unsigned int *);
|
||||||
|
|
||||||
struct ata_ioports {
|
struct ata_ioports {
|
||||||
unsigned long cmd_addr;
|
unsigned long cmd_addr;
|
||||||
@ -478,6 +480,9 @@ extern void ata_port_probe(struct ata_port *);
|
|||||||
extern void __sata_phy_reset(struct ata_port *ap);
|
extern void __sata_phy_reset(struct ata_port *ap);
|
||||||
extern void sata_phy_reset(struct ata_port *ap);
|
extern void sata_phy_reset(struct ata_port *ap);
|
||||||
extern void ata_bus_reset(struct ata_port *ap);
|
extern void ata_bus_reset(struct ata_port *ap);
|
||||||
|
extern int ata_drive_probe_reset(struct ata_port *ap,
|
||||||
|
ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
|
||||||
|
ata_postreset_fn_t postreset, unsigned int *classes);
|
||||||
extern void ata_port_disable(struct ata_port *);
|
extern void ata_port_disable(struct ata_port *);
|
||||||
extern void ata_std_ports(struct ata_ioports *ioaddr);
|
extern void ata_std_ports(struct ata_ioports *ioaddr);
|
||||||
#ifdef CONFIG_PCI
|
#ifdef CONFIG_PCI
|
||||||
|
Loading…
Reference in New Issue
Block a user