[Bug 198356] Possible infinite sleep in mmc_wait_for_req()
bugzilla-noreply at freebsd.org
bugzilla-noreply at freebsd.org
Fri Mar 6 14:45:14 UTC 2015
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=198356
Bug ID: 198356
Summary: Possible infinite sleep in mmc_wait_for_req()
Product: Base System
Version: 10.1-STABLE
Hardware: arm
OS: Any
Status: New
Severity: Affects Only Me
Priority: ---
Component: kern
Assignee: freebsd-bugs at FreeBSD.org
Reporter: soutade at gmail.com
This is the current code of sys/dev/mmc/mmc.c.
372 static void
373 mmc_wakeup(struct mmc_request *req)
374 {
375 struct mmc_softc *sc;
376
377 sc = (struct mmc_softc *)req->done_data;
378 MMC_LOCK(sc);
379 req->flags |= MMC_REQ_DONE;
380 MMC_UNLOCK(sc);
381 wakeup(req);
382 }
383
384 static int
385 mmc_wait_for_req(struct mmc_softc *sc, struct mmc_request *req)
386 {
387
388 req->done = mmc_wakeup;
389 req->done_data = sc;
390 if (mmc_debug > 1) {
391 device_printf(sc->dev, "REQUEST: CMD%d arg %#x flags
%#x",
392 req->cmd->opcode, req->cmd->arg, req->cmd->flags);
393 if (req->cmd->data) {
394 printf(" data %d\n", (int)req->cmd->data->len);
395 } else
396 printf("\n");
397 }
398 MMCBR_REQUEST(device_get_parent(sc->dev), sc->dev, req);
399 MMC_LOCK(sc);
400 while ((req->flags & MMC_REQ_DONE) == 0)
401 msleep(req, &sc->sc_mtx, 0, "mmcreq", 0);
402 MMC_UNLOCK(sc);
403 if (mmc_debug > 2 || (mmc_debug > 0 && req->cmd->error !=
MMC_ERR_NONE))
404 device_printf(sc->dev, "CMD%d RESULT: %d\n",
405 req->cmd->opcode, req->cmd->error);
406 return (0);
407 }
As I understand :
When the MMC stack sends a command, it goes into mmc_wait_for_req(), that
defines callback mmc_wakeup(). This callback should sets MMC_REQ_DONE flag and
wakeup sleeped thread when request is completed. Request is sent to driver at
line 398, then it locks the mutex, test flag and goes to sleep.
But, in my case, I got an interrupt after flag test (line 400) and before "req"
has been added to the sleepqueue. It results that mmc_wakeup() is called, it
sets flag and try to wakeup, but didn't find "req" in the sleepqueue. In theory
this behaviour is protected by MMC_LOCK, but the two calls (mmc task and
interrupt) has the same thread id, so anyone is being suspended.
To fix this, I suggest setting a timeout in msleep() instead of 0.
I marked it for version 10.1-STABLE, but 11.0-CURRENT has the same code.
--
You are receiving this mail because:
You are the assignee for the bug.
More information about the freebsd-bugs
mailing list