Avoid a race condition that could allow a removable controller (such as

a compact flash card) to lock the atabus thread if it gets detached during
the probe process.
This commit is contained in:
briggs 2003-10-22 23:59:00 +00:00
parent aa20eb60ec
commit 7dc8540d52

View File

@ -1,4 +1,4 @@
/* $NetBSD: wdc.c,v 1.143 2003/10/15 20:29:26 bouyer Exp $ */ /* $NetBSD: wdc.c,v 1.144 2003/10/22 23:59:00 briggs Exp $ */
/* /*
* Copyright (c) 1998, 2001, 2003 Manuel Bouyer. All rights reserved. * Copyright (c) 1998, 2001, 2003 Manuel Bouyer. All rights reserved.
@ -70,7 +70,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: wdc.c,v 1.143 2003/10/15 20:29:26 bouyer Exp $"); __KERNEL_RCSID(0, "$NetBSD: wdc.c,v 1.144 2003/10/22 23:59:00 briggs Exp $");
#ifndef WDCDEBUG #ifndef WDCDEBUG
#define WDCDEBUG #define WDCDEBUG
@ -268,8 +268,7 @@ atabus_thread(arg)
chp->ch_flags |= WDCF_TH_RUN; chp->ch_flags |= WDCF_TH_RUN;
splx(s); splx(s);
atabusconfig(atabus_sc); atabusconfig(atabus_sc);
for(;;) while (!(chp->ch_flags & WDCF_SHUTDOWN)) {
{
s = splbio(); s = splbio();
chp->ch_flags &= ~WDCF_TH_RUN; chp->ch_flags &= ~WDCF_TH_RUN;
tsleep(&chp->thread, PRIBIO, "atath", 0); tsleep(&chp->thread, PRIBIO, "atath", 0);
@ -313,7 +312,7 @@ atabusconfig(atabus_sc)
struct atabus_softc *atabus_sc; struct atabus_softc *atabus_sc;
{ {
struct channel_softc *chp = atabus_sc->sc_chan; struct channel_softc *chp = atabus_sc->sc_chan;
int ctrl_flags, i, error; int ctrl_flags, i, error, need_delref = 0;
struct ataparams params; struct ataparams params;
struct atabus_initq *atabus_initq = NULL; struct atabus_initq *atabus_initq = NULL;
u_int8_t st0, st1; u_int8_t st0, st1;
@ -321,9 +320,9 @@ atabusconfig(atabus_sc)
if ((error = wdc_addref(chp)) != 0) { if ((error = wdc_addref(chp)) != 0) {
aprint_error("%s: unable to enable controller\n", aprint_error("%s: unable to enable controller\n",
chp->wdc->sc_dev.dv_xname); chp->wdc->sc_dev.dv_xname);
config_pending_decr(); goto out;
return;
} }
need_delref = 1;
if (__wdcprobe(chp, 0) == 0) if (__wdcprobe(chp, 0) == 0)
/* If no drives, abort attach here. */ /* If no drives, abort attach here. */
@ -383,11 +382,20 @@ atabusconfig(atabus_sc)
if ((chp->ch_drive[i].drive_flags & DRIVE) == 0) if ((chp->ch_drive[i].drive_flags & DRIVE) == 0)
continue; continue;
/* Shortcut in case we've been shutdown */
if (chp->ch_flags & WDCF_SHUTDOWN)
goto out;
/* issue an identify, to try to detect ghosts */ /* issue an identify, to try to detect ghosts */
error = ata_get_params(&chp->ch_drive[i], error = ata_get_params(&chp->ch_drive[i],
AT_WAIT | AT_POLL, &params); AT_WAIT | AT_POLL, &params);
if (error != CMD_OK) { if (error != CMD_OK) {
tsleep(&atabus_sc, PRIBIO, "atacnf", mstohz(1000)); tsleep(&atabus_sc, PRIBIO, "atacnf", mstohz(1000));
/* Shortcut in case we've been shutdown */
if (chp->ch_flags & WDCF_SHUTDOWN)
goto out;
error = ata_get_params(&chp->ch_drive[i], error = ata_get_params(&chp->ch_drive[i],
AT_WAIT | AT_POLL, &params); AT_WAIT | AT_POLL, &params);
} }
@ -549,7 +557,8 @@ out:
wakeup(&atabus_initq_head); wakeup(&atabus_initq_head);
config_pending_decr(); config_pending_decr();
wdc_delref(chp); if (need_delref)
wdc_delref(chp);
} }