Locking changes.
+ Synchronize ath_calibrate() with ATH_LOCK()/ATH_UNLOCK(). Thanks to Steve Woodford for suggesting this fix. This patch stops ath(4) from generating messages "hardware error; resetting" while Steve's D-Link DWL-AG650 card is operating (kern/28385). The MiniPCI wireless adapter on one of my Soekris boards also operates more reliably following this patch. + Use ATH_LOCK_IMPL() and family to synchronize access to the transmit queue, also.
This commit is contained in:
parent
f069ffb8c5
commit
c1446c092d
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ath.c,v 1.52 2005/07/03 19:44:50 dyoung Exp $ */
|
||||
/* $NetBSD: ath.c,v 1.53 2005/07/03 19:58:16 dyoung Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
|
||||
|
@ -41,7 +41,7 @@
|
|||
__FBSDID("$FreeBSD: src/sys/dev/ath/if_ath.c,v 1.88 2005/04/12 17:56:43 sam Exp $");
|
||||
#endif
|
||||
#ifdef __NetBSD__
|
||||
__KERNEL_RCSID(0, "$NetBSD: ath.c,v 1.52 2005/07/03 19:44:50 dyoung Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ath.c,v 1.53 2005/07/03 19:58:16 dyoung Exp $");
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -4122,6 +4122,7 @@ ath_calibrate(void *arg)
|
|||
|
||||
sc->sc_stats.ast_per_cal++;
|
||||
|
||||
ATH_LOCK(sc);
|
||||
DPRINTF(sc, ATH_DEBUG_CALIBRATE, "%s: channel %u/%x\n",
|
||||
__func__, sc->sc_curchan.channel, sc->sc_curchan.channelFlags);
|
||||
|
||||
|
@ -4140,6 +4141,7 @@ ath_calibrate(void *arg)
|
|||
sc->sc_stats.ast_per_calfail++;
|
||||
}
|
||||
callout_reset(&sc->sc_cal_ch, ath_calinterval * hz, ath_calibrate, sc);
|
||||
ATH_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
@ -49,37 +49,29 @@ typedef struct ath_task {
|
|||
#define TASK_RUN_OR_ENQUEUE(__task) \
|
||||
((*(__task)->t_func)((__task)->t_context, 1))
|
||||
|
||||
typedef int ath_txq_lock_t;
|
||||
#define ATH_TXQ_LOCK_INIT(_sc, _tq)
|
||||
#define ATH_TXQ_LOCK_DESTROY(_tq)
|
||||
#define ATH_TXQ_LOCK(_tq) \
|
||||
do { (_tq)->axq_lock = splnet(); } while (0)
|
||||
#define ATH_TXQ_UNLOCK(_tq) \
|
||||
do { splx((_tq)->axq_lock); } while (0)
|
||||
#define ATH_TXQ_LOCK_ASSERT(_tq)
|
||||
|
||||
struct ath_lock {
|
||||
int count;
|
||||
int ipl;
|
||||
};
|
||||
|
||||
#define ATH_LOCK_INIT_IMPL(_sc, _member) \
|
||||
do { (_sc)->_member.count = 0; } while (0)
|
||||
#define ATH_LOCK_IMPL(_sc, _member) \
|
||||
#define ATH_LOCK_INIT_IMPL(_type, _member) \
|
||||
do { (_type)->_member.count = 0; } while (0)
|
||||
#define ATH_LOCK_IMPL(_type, _member) \
|
||||
do { \
|
||||
int __s = splnet(); \
|
||||
if ((_sc)->_member.count++ == 0) \
|
||||
(_sc)->_member.ipl = __s; \
|
||||
if ((_type)->_member.count++ == 0) \
|
||||
(_type)->_member.ipl = __s; \
|
||||
} while (0)
|
||||
#define ATH_UNLOCK_IMPL(_sc, _member) \
|
||||
#define ATH_UNLOCK_IMPL(_type, _member) \
|
||||
do { \
|
||||
if (--(_sc)->_member.count == 0) \
|
||||
splx((_sc)->_member.ipl); \
|
||||
if (--(_type)->_member.count == 0) \
|
||||
splx((_type)->_member.ipl); \
|
||||
else { \
|
||||
KASSERT((_sc)->_member.count >= 0, \
|
||||
KASSERT((_type)->_member.count >= 0, \
|
||||
("%s: no ATH_LOCK holders", __func__)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
typedef struct ath_lock ath_lock_t;
|
||||
#define ATH_LOCK_INIT(_sc) ATH_LOCK_INIT_IMPL(_sc, sc_mtx)
|
||||
#define ATH_LOCK_DESTROY(_sc)
|
||||
|
@ -87,6 +79,13 @@ typedef struct ath_lock ath_lock_t;
|
|||
#define ATH_UNLOCK(_sc) ATH_UNLOCK_IMPL(_sc, sc_mtx)
|
||||
#define ATH_LOCK_ASSERT(_sc)
|
||||
|
||||
typedef struct ath_lock ath_txq_lock_t;
|
||||
#define ATH_TXQ_LOCK_INIT(_sc, _tq) ATH_LOCK_INIT_IMPL(_tq, axq_lock)
|
||||
#define ATH_TXQ_LOCK_DESTROY(_tq)
|
||||
#define ATH_TXQ_LOCK(_tq) ATH_LOCK_IMPL(_tq, axq_lock)
|
||||
#define ATH_TXQ_UNLOCK(_tq) ATH_UNLOCK_IMPL(_tq, axq_lock)
|
||||
#define ATH_TXQ_LOCK_ASSERT(_tq)
|
||||
|
||||
typedef struct ath_lock ath_txbuf_lock_t;
|
||||
#define ATH_TXBUF_LOCK_INIT(_sc) ATH_LOCK_INIT_IMPL(_sc, sc_txbuflock)
|
||||
#define ATH_TXBUF_LOCK_DESTROY(_sc)
|
||||
|
|
Loading…
Reference in New Issue