rum(4): add command queue for running sleepable tasks in non-sleepable contexts
Tested: * Tested on WUSB54GC, STA mode. * rum0: MAC/BBP RT2573 (rev 0x2573a), RF RT2528 Submitted by: <s3erios@gmail.com> Differential Revision: https://reviews.freebsd.org/D3629
This commit is contained in:
parent
e7b7db3d59
commit
f28c2f5e54
@ -158,6 +158,9 @@ static struct ieee80211vap *rum_vap_create(struct ieee80211com *,
|
||||
int, const uint8_t [IEEE80211_ADDR_LEN],
|
||||
const uint8_t [IEEE80211_ADDR_LEN]);
|
||||
static void rum_vap_delete(struct ieee80211vap *);
|
||||
static void rum_cmdq_cb(void *, int);
|
||||
static int rum_cmd_sleepable(struct rum_softc *, const void *,
|
||||
size_t, uint8_t, uint8_t, CMD_FUNC_PROTO);
|
||||
static void rum_tx_free(struct rum_tx_data *, int);
|
||||
static void rum_setup_tx_list(struct rum_softc *);
|
||||
static void rum_unsetup_tx_list(struct rum_softc *);
|
||||
@ -438,8 +441,8 @@ rum_attach(device_t self)
|
||||
sc->sc_udev = uaa->device;
|
||||
sc->sc_dev = self;
|
||||
|
||||
mtx_init(&sc->sc_mtx, device_get_nameunit(self),
|
||||
MTX_NETWORK_LOCK, MTX_DEF);
|
||||
RUM_LOCK_INIT(sc);
|
||||
RUM_CMDQ_LOCK_INIT(sc);
|
||||
mbufq_init(&sc->sc_snd, ifqmaxlen);
|
||||
|
||||
iface_index = RT2573_IFACE_INDEX;
|
||||
@ -516,6 +519,8 @@ rum_attach(device_t self)
|
||||
&sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap),
|
||||
RT2573_RX_RADIOTAP_PRESENT);
|
||||
|
||||
TASK_INIT(&sc->cmdq_task, 0, rum_cmdq_cb, sc);
|
||||
|
||||
if (bootverbose)
|
||||
ieee80211_announce(ic);
|
||||
|
||||
@ -545,10 +550,15 @@ rum_detach(device_t self)
|
||||
rum_unsetup_tx_list(sc);
|
||||
RUM_UNLOCK(sc);
|
||||
|
||||
if (ic->ic_softc == sc)
|
||||
if (ic->ic_softc == sc) {
|
||||
ieee80211_draintask(ic, &sc->cmdq_task);
|
||||
ieee80211_ifdetach(ic);
|
||||
}
|
||||
|
||||
mbufq_drain(&sc->sc_snd);
|
||||
mtx_destroy(&sc->sc_mtx);
|
||||
RUM_CMDQ_LOCK_DESTROY(sc);
|
||||
RUM_LOCK_DESTROY(sc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -624,6 +634,57 @@ rum_vap_delete(struct ieee80211vap *vap)
|
||||
free(rvp, M_80211_VAP);
|
||||
}
|
||||
|
||||
static void
|
||||
rum_cmdq_cb(void *arg, int pending)
|
||||
{
|
||||
struct rum_softc *sc = arg;
|
||||
struct rum_cmdq *rc;
|
||||
|
||||
RUM_CMDQ_LOCK(sc);
|
||||
while (sc->cmdq[sc->cmdq_first].func != NULL) {
|
||||
rc = &sc->cmdq[sc->cmdq_first];
|
||||
RUM_CMDQ_UNLOCK(sc);
|
||||
|
||||
RUM_LOCK(sc);
|
||||
rc->func(sc, &rc->data, rc->rn_id, rc->rvp_id);
|
||||
RUM_UNLOCK(sc);
|
||||
|
||||
RUM_CMDQ_LOCK(sc);
|
||||
memset(rc, 0, sizeof (*rc));
|
||||
sc->cmdq_first = (sc->cmdq_first + 1) % RUM_CMDQ_SIZE;
|
||||
}
|
||||
RUM_CMDQ_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static int
|
||||
rum_cmd_sleepable(struct rum_softc *sc, const void *ptr, size_t len,
|
||||
uint8_t rn_id, uint8_t rvp_id, CMD_FUNC_PROTO)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
|
||||
KASSERT(len <= sizeof(union sec_param), ("buffer overflow"));
|
||||
|
||||
RUM_CMDQ_LOCK(sc);
|
||||
if (sc->cmdq[sc->cmdq_last].func != NULL) {
|
||||
device_printf(sc->sc_dev, "%s: cmdq overflow\n", __func__);
|
||||
RUM_CMDQ_UNLOCK(sc);
|
||||
|
||||
return EAGAIN;
|
||||
}
|
||||
|
||||
if (ptr != NULL)
|
||||
memcpy(&sc->cmdq[sc->cmdq_last].data, ptr, len);
|
||||
sc->cmdq[sc->cmdq_last].rn_id = rn_id;
|
||||
sc->cmdq[sc->cmdq_last].rvp_id = rvp_id;
|
||||
sc->cmdq[sc->cmdq_last].func = func;
|
||||
sc->cmdq_last = (sc->cmdq_last + 1) % RUM_CMDQ_SIZE;
|
||||
RUM_CMDQ_UNLOCK(sc);
|
||||
|
||||
ieee80211_runtask(ic, &sc->cmdq_task);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
rum_tx_free(struct rum_tx_data *data, int txerr)
|
||||
{
|
||||
|
@ -67,6 +67,25 @@ struct rum_tx_data {
|
||||
};
|
||||
typedef STAILQ_HEAD(, rum_tx_data) rum_txdhead;
|
||||
|
||||
union sec_param {
|
||||
struct ieee80211_key key;
|
||||
uint8_t macaddr[IEEE80211_ADDR_LEN];
|
||||
struct ieee80211vap *vap;
|
||||
};
|
||||
#define CMD_FUNC_PROTO void (*func)(struct rum_softc *, \
|
||||
union sec_param *, uint8_t, \
|
||||
uint8_t)
|
||||
|
||||
struct rum_cmdq {
|
||||
union sec_param data;
|
||||
|
||||
uint8_t rn_id;
|
||||
uint8_t rvp_id;
|
||||
|
||||
CMD_FUNC_PROTO;
|
||||
};
|
||||
#define RUM_CMDQ_SIZE 16
|
||||
|
||||
struct rum_vap {
|
||||
struct ieee80211vap vap;
|
||||
struct ieee80211_beacon_offsets bo;
|
||||
@ -103,6 +122,12 @@ struct rum_softc {
|
||||
|
||||
struct mtx sc_mtx;
|
||||
|
||||
struct rum_cmdq cmdq[RUM_CMDQ_SIZE];
|
||||
struct mtx cmdq_mtx;
|
||||
struct task cmdq_task;
|
||||
uint8_t cmdq_first;
|
||||
uint8_t cmdq_last;
|
||||
|
||||
uint32_t sta[6];
|
||||
uint32_t rf_regs[4];
|
||||
uint8_t txpow[44];
|
||||
@ -128,6 +153,16 @@ struct rum_softc {
|
||||
struct rum_tx_radiotap_header sc_txtap;
|
||||
};
|
||||
|
||||
#define RUM_LOCK(sc) mtx_lock(&(sc)->sc_mtx)
|
||||
#define RUM_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx)
|
||||
#define RUM_LOCK_ASSERT(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED)
|
||||
#define RUM_LOCK_INIT(sc) \
|
||||
mtx_init(&(sc)->sc_mtx, device_get_nameunit((sc)->sc_dev), \
|
||||
MTX_NETWORK_LOCK, MTX_DEF);
|
||||
#define RUM_LOCK(sc) mtx_lock(&(sc)->sc_mtx)
|
||||
#define RUM_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx)
|
||||
#define RUM_LOCK_ASSERT(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED)
|
||||
#define RUM_LOCK_DESTROY(sc) mtx_destroy(&(sc)->sc_mtx)
|
||||
|
||||
#define RUM_CMDQ_LOCK_INIT(sc) \
|
||||
mtx_init(&(sc)->cmdq_mtx, "cmdq lock", NULL, MTX_DEF)
|
||||
#define RUM_CMDQ_LOCK(sc) mtx_lock(&(sc)->cmdq_mtx)
|
||||
#define RUM_CMDQ_UNLOCK(sc) mtx_unlock(&(sc)->cmdq_mtx)
|
||||
#define RUM_CMDQ_LOCK_DESTROY(sc) mtx_destroy(&(sc)->cmdq_mtx)
|
||||
|
Loading…
x
Reference in New Issue
Block a user