aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libata-core.c
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2006-01-24 03:05:22 -0500
committerJeff Garzik <jgarzik@pobox.com>2006-01-27 20:58:34 -0500
commita62c0fc526c344d8163f7a9e45e68cc63826ffd3 (patch)
treed803a14848eb785f63b5f9e2d0b3f19afa0bda9d /drivers/scsi/libata-core.c
parentc19ba8af4f104cca28d548cac55c128b28dd31fb (diff)
[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>
Diffstat (limited to 'drivers/scsi/libata-core.c')
-rw-r--r--drivers/scsi/libata-core.c89
1 files changed, 89 insertions, 0 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 147e1461062d..cf91fdc08ef6 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -2233,6 +2233,94 @@ err_out:
2233 DPRINTK("EXIT\n"); 2233 DPRINTK("EXIT\n");
2234} 2234}
2235 2235
2236static int do_probe_reset(struct ata_port *ap, ata_reset_fn_t reset,
2237 ata_postreset_fn_t postreset,
2238 unsigned int *classes)
2239{
2240 int i, rc;
2241
2242 for (i = 0; i < ATA_MAX_DEVICES; i++)
2243 classes[i] = ATA_DEV_UNKNOWN;
2244
2245 rc = reset(ap, 0, classes);
2246 if (rc)
2247 return rc;
2248
2249 /* If any class isn't ATA_DEV_UNKNOWN, consider classification
2250 * is complete and convert all ATA_DEV_UNKNOWN to
2251 * ATA_DEV_NONE.
2252 */
2253 for (i = 0; i < ATA_MAX_DEVICES; i++)
2254 if (classes[i] != ATA_DEV_UNKNOWN)
2255 break;
2256
2257 if (i < ATA_MAX_DEVICES)
2258 for (i = 0; i < ATA_MAX_DEVICES; i++)
2259 if (classes[i] == ATA_DEV_UNKNOWN)
2260 classes[i] = ATA_DEV_NONE;
2261
2262 if (postreset)
2263 postreset(ap, classes);
2264
2265 return classes[0] != ATA_DEV_UNKNOWN ? 0 : -ENODEV;
2266}
2267
2268/**
2269 * ata_drive_probe_reset - Perform probe reset with given methods
2270 * @ap: port to reset
2271 * @softreset: softreset method (can be NULL)
2272 * @hardreset: hardreset method (can be NULL)
2273 * @postreset: postreset method (can be NULL)
2274 * @classes: resulting classes of attached devices
2275 *
2276 * Reset the specified port and classify attached devices using
2277 * given methods. This function prefers softreset but tries all
2278 * possible reset sequences to reset and classify devices. This
2279 * function is intended to be used for constructing ->probe_reset
2280 * callback by low level drivers.
2281 *
2282 * Reset methods should follow the following rules.
2283 *
2284 * - Return 0 on sucess, -errno on failure.
2285 * - If classification is supported, fill classes[] with
2286 * recognized class codes.
2287 * - If classification is not supported, leave classes[] alone.
2288 * - If verbose is non-zero, print error message on failure;
2289 * otherwise, shut up.
2290 *
2291 * LOCKING:
2292 * Kernel thread context (may sleep)
2293 *
2294 * RETURNS:
2295 * 0 on success, -EINVAL if no reset method is avaliable, -ENODEV
2296 * if classification fails, and any error code from reset
2297 * methods.
2298 */
2299int ata_drive_probe_reset(struct ata_port *ap,
2300 ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
2301 ata_postreset_fn_t postreset, unsigned int *classes)
2302{
2303 int rc = -EINVAL;
2304
2305 if (softreset) {
2306 rc = do_probe_reset(ap, softreset, postreset, classes);
2307 if (rc == 0)
2308 return 0;
2309 }
2310
2311 if (!hardreset)
2312 return rc;
2313
2314 rc = do_probe_reset(ap, hardreset, postreset, classes);
2315 if (rc == 0 || rc != -ENODEV)
2316 return rc;
2317
2318 if (softreset)
2319 rc = do_probe_reset(ap, softreset, postreset, classes);
2320
2321 return rc;
2322}
2323
2236static void ata_pr_blacklisted(const struct ata_port *ap, 2324static void ata_pr_blacklisted(const struct ata_port *ap,
2237 const struct ata_device *dev) 2325 const struct ata_device *dev)
2238{ 2326{
@@ -5180,6 +5268,7 @@ EXPORT_SYMBOL_GPL(ata_port_probe);
5180EXPORT_SYMBOL_GPL(sata_phy_reset); 5268EXPORT_SYMBOL_GPL(sata_phy_reset);
5181EXPORT_SYMBOL_GPL(__sata_phy_reset); 5269EXPORT_SYMBOL_GPL(__sata_phy_reset);
5182EXPORT_SYMBOL_GPL(ata_bus_reset); 5270EXPORT_SYMBOL_GPL(ata_bus_reset);
5271EXPORT_SYMBOL_GPL(ata_drive_probe_reset);
5183EXPORT_SYMBOL_GPL(ata_port_disable); 5272EXPORT_SYMBOL_GPL(ata_port_disable);
5184EXPORT_SYMBOL_GPL(ata_ratelimit); 5273EXPORT_SYMBOL_GPL(ata_ratelimit);
5185EXPORT_SYMBOL_GPL(ata_busy_sleep); 5274EXPORT_SYMBOL_GPL(ata_busy_sleep);