diff options
author | Nicolas Pitre <nico@cam.org> | 2007-06-30 10:21:52 -0400 |
---|---|---|
committer | Pierre Ossman <drzeus@drzeus.cx> | 2007-09-23 14:55:13 -0400 |
commit | 2342f3323c9a76367a1d7f9a35525ee3cb3911df (patch) | |
tree | 1fdb42702137dfbe0be0c2e1c6777a0c0ddb1bcf /drivers/mmc | |
parent | 55fe77a0a24e05c9aaf1a13550dde5efad8b49f2 (diff) |
sdio: allow for mmc_claim_host to be aborted
It is sometimes necessary to give up on trying to claim the host lock,
especially if that happens in a thread that has to be stopped.
While at it, fix the description for mmc_claim_host() which was wrong.
Signed-off-by: Nicolas Pitre <npitre@mvista.com>
Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/core/core.c | 22 |
1 files changed, 16 insertions, 6 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index b8f27e5ade97..d1e4b0849e39 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
@@ -273,15 +273,20 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card) | |||
273 | EXPORT_SYMBOL(mmc_set_data_timeout); | 273 | EXPORT_SYMBOL(mmc_set_data_timeout); |
274 | 274 | ||
275 | /** | 275 | /** |
276 | * mmc_claim_host - exclusively claim a host | 276 | * __mmc_claim_host - exclusively claim a host |
277 | * @host: mmc host to claim | 277 | * @host: mmc host to claim |
278 | * @abort: whether or not the operation should be aborted | ||
278 | * | 279 | * |
279 | * Claim a host for a set of operations. | 280 | * Claim a host for a set of operations. If @abort is non null and |
281 | * dereference a non-zero value then this will return prematurely with | ||
282 | * that non-zero value without acquiring the lock. Returns zero | ||
283 | * with the lock held otherwise. | ||
280 | */ | 284 | */ |
281 | void mmc_claim_host(struct mmc_host *host) | 285 | int __mmc_claim_host(struct mmc_host *host, atomic_t *abort) |
282 | { | 286 | { |
283 | DECLARE_WAITQUEUE(wait, current); | 287 | DECLARE_WAITQUEUE(wait, current); |
284 | unsigned long flags; | 288 | unsigned long flags; |
289 | int stop; | ||
285 | 290 | ||
286 | might_sleep(); | 291 | might_sleep(); |
287 | 292 | ||
@@ -289,19 +294,24 @@ void mmc_claim_host(struct mmc_host *host) | |||
289 | spin_lock_irqsave(&host->lock, flags); | 294 | spin_lock_irqsave(&host->lock, flags); |
290 | while (1) { | 295 | while (1) { |
291 | set_current_state(TASK_UNINTERRUPTIBLE); | 296 | set_current_state(TASK_UNINTERRUPTIBLE); |
292 | if (!host->claimed) | 297 | stop = abort ? atomic_read(abort) : 0; |
298 | if (stop || !host->claimed) | ||
293 | break; | 299 | break; |
294 | spin_unlock_irqrestore(&host->lock, flags); | 300 | spin_unlock_irqrestore(&host->lock, flags); |
295 | schedule(); | 301 | schedule(); |
296 | spin_lock_irqsave(&host->lock, flags); | 302 | spin_lock_irqsave(&host->lock, flags); |
297 | } | 303 | } |
298 | set_current_state(TASK_RUNNING); | 304 | set_current_state(TASK_RUNNING); |
299 | host->claimed = 1; | 305 | if (!stop) |
306 | host->claimed = 1; | ||
307 | else | ||
308 | wake_up(&host->wq); | ||
300 | spin_unlock_irqrestore(&host->lock, flags); | 309 | spin_unlock_irqrestore(&host->lock, flags); |
301 | remove_wait_queue(&host->wq, &wait); | 310 | remove_wait_queue(&host->wq, &wait); |
311 | return stop; | ||
302 | } | 312 | } |
303 | 313 | ||
304 | EXPORT_SYMBOL(mmc_claim_host); | 314 | EXPORT_SYMBOL(__mmc_claim_host); |
305 | 315 | ||
306 | /** | 316 | /** |
307 | * mmc_release_host - release a host | 317 | * mmc_release_host - release a host |