urtwn: add a command queue for sleepable tasks.
An implementation from rum(4) was used (it looks simpler for me). Will be used for h/w encryption support. Reviewed by: kevlo Approved by: adrian (mentor) Differential Revision: https://reviews.freebsd.org/D4447
This commit is contained in:
parent
be615269bb
commit
b3f5d50360
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=292174
@ -213,6 +213,9 @@ static uint16_t urtwn_read_2(struct urtwn_softc *, uint16_t);
|
||||
static uint32_t urtwn_read_4(struct urtwn_softc *, uint16_t);
|
||||
static int urtwn_fw_cmd(struct urtwn_softc *, uint8_t,
|
||||
const void *, int);
|
||||
static void urtwn_cmdq_cb(void *, int);
|
||||
static int urtwn_cmd_sleepable(struct urtwn_softc *, const void *,
|
||||
size_t, CMD_FUNC_PROTO);
|
||||
static void urtwn_r92c_rf_write(struct urtwn_softc *, int,
|
||||
uint8_t, uint32_t);
|
||||
static void urtwn_r88e_rf_write(struct urtwn_softc *, int,
|
||||
@ -427,6 +430,7 @@ urtwn_attach(device_t self)
|
||||
|
||||
mtx_init(&sc->sc_mtx, device_get_nameunit(self),
|
||||
MTX_NETWORK_LOCK, MTX_DEF);
|
||||
URTWN_CMDQ_LOCK_INIT(sc);
|
||||
URTWN_NT_LOCK_INIT(sc);
|
||||
callout_init(&sc->sc_watchdog_ch, 0);
|
||||
mbufq_init(&sc->sc_snd, ifqmaxlen);
|
||||
@ -525,6 +529,8 @@ urtwn_attach(device_t self)
|
||||
&sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap),
|
||||
URTWN_RX_RADIOTAP_PRESENT);
|
||||
|
||||
TASK_INIT(&sc->cmdq_task, 0, urtwn_cmdq_cb, sc);
|
||||
|
||||
if (bootverbose)
|
||||
ieee80211_announce(ic);
|
||||
|
||||
@ -574,8 +580,13 @@ urtwn_detach(device_t self)
|
||||
urtwn_free_rx_list(sc);
|
||||
URTWN_UNLOCK(sc);
|
||||
|
||||
ieee80211_ifdetach(ic);
|
||||
if (ic->ic_softc == sc) {
|
||||
ieee80211_draintask(ic, &sc->cmdq_task);
|
||||
ieee80211_ifdetach(ic);
|
||||
}
|
||||
|
||||
URTWN_NT_LOCK_DESTROY(sc);
|
||||
URTWN_CMDQ_LOCK_DESTROY(sc);
|
||||
mtx_destroy(&sc->sc_mtx);
|
||||
|
||||
return (0);
|
||||
@ -1259,6 +1270,64 @@ urtwn_fw_cmd(struct urtwn_softc *sc, uint8_t id, const void *buf, int len)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
urtwn_cmdq_cb(void *arg, int pending)
|
||||
{
|
||||
struct urtwn_softc *sc = arg;
|
||||
struct urtwn_cmdq *item;
|
||||
|
||||
/*
|
||||
* Device must be powered on (via urtwn_power_on())
|
||||
* before any command may be sent.
|
||||
*/
|
||||
URTWN_LOCK(sc);
|
||||
if (!(sc->sc_flags & URTWN_RUNNING)) {
|
||||
URTWN_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
|
||||
URTWN_CMDQ_LOCK(sc);
|
||||
while (sc->cmdq[sc->cmdq_first].func != NULL) {
|
||||
item = &sc->cmdq[sc->cmdq_first];
|
||||
sc->cmdq_first = (sc->cmdq_first + 1) % URTWN_CMDQ_SIZE;
|
||||
URTWN_CMDQ_UNLOCK(sc);
|
||||
|
||||
item->func(sc, &item->data);
|
||||
|
||||
URTWN_CMDQ_LOCK(sc);
|
||||
memset(item, 0, sizeof (*item));
|
||||
}
|
||||
URTWN_CMDQ_UNLOCK(sc);
|
||||
URTWN_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static int
|
||||
urtwn_cmd_sleepable(struct urtwn_softc *sc, const void *ptr, size_t len,
|
||||
CMD_FUNC_PROTO)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
|
||||
KASSERT(len <= sizeof(union sec_param), ("buffer overflow"));
|
||||
|
||||
URTWN_CMDQ_LOCK(sc);
|
||||
if (sc->cmdq[sc->cmdq_last].func != NULL) {
|
||||
device_printf(sc->sc_dev, "%s: cmdq overflow\n", __func__);
|
||||
URTWN_CMDQ_UNLOCK(sc);
|
||||
|
||||
return (EAGAIN);
|
||||
}
|
||||
|
||||
if (ptr != NULL)
|
||||
memcpy(&sc->cmdq[sc->cmdq_last].data, ptr, len);
|
||||
sc->cmdq[sc->cmdq_last].func = func;
|
||||
sc->cmdq_last = (sc->cmdq_last + 1) % URTWN_CMDQ_SIZE;
|
||||
URTWN_CMDQ_UNLOCK(sc);
|
||||
|
||||
ieee80211_runtask(ic, &sc->cmdq_task);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
urtwn_rf_write(struct urtwn_softc *sc, int chain, uint8_t addr, uint32_t val)
|
||||
{
|
||||
|
@ -71,16 +71,19 @@ struct urtwn_data {
|
||||
};
|
||||
typedef STAILQ_HEAD(, urtwn_data) urtwn_datahead;
|
||||
|
||||
struct urtwn_cmdq {
|
||||
void *arg0;
|
||||
void *arg1;
|
||||
void (*func)(void *);
|
||||
struct ieee80211_key *k;
|
||||
struct ieee80211_key key;
|
||||
uint8_t mac[IEEE80211_ADDR_LEN];
|
||||
uint8_t wcid;
|
||||
union sec_param {
|
||||
struct ieee80211_key key;
|
||||
};
|
||||
|
||||
#define CMD_FUNC_PROTO void (*func)(struct urtwn_softc *, \
|
||||
union sec_param *)
|
||||
|
||||
struct urtwn_cmdq {
|
||||
union sec_param data;
|
||||
CMD_FUNC_PROTO;
|
||||
};
|
||||
#define URTWN_CMDQ_SIZE 16
|
||||
|
||||
struct urtwn_fw_info {
|
||||
const uint8_t *data;
|
||||
size_t size;
|
||||
@ -203,17 +206,11 @@ struct urtwn_softc {
|
||||
struct callout sc_watchdog_ch;
|
||||
struct mtx sc_mtx;
|
||||
|
||||
/* need to be power of 2, otherwise URTWN_CMDQ_GET fails */
|
||||
#define URTWN_CMDQ_MAX 16
|
||||
#define URTWN_CMDQ_MASQ (URTWN_CMDQ_MAX - 1)
|
||||
struct urtwn_cmdq cmdq[URTWN_CMDQ_MAX];
|
||||
struct urtwn_cmdq cmdq[URTWN_CMDQ_SIZE];
|
||||
struct mtx cmdq_mtx;
|
||||
struct task cmdq_task;
|
||||
uint32_t cmdq_store;
|
||||
uint8_t cmdq_exec;
|
||||
uint8_t cmdq_run;
|
||||
uint8_t cmdq_key_set;
|
||||
#define URTWN_CMDQ_ABORT 0
|
||||
#define URTWN_CMDQ_GO 1
|
||||
uint8_t cmdq_first;
|
||||
uint8_t cmdq_last;
|
||||
|
||||
uint32_t rf_chnlbw[R92C_MAX_CHAINS];
|
||||
struct usb_xfer *sc_xfer[URTWN_N_TRANSFER];
|
||||
@ -226,6 +223,12 @@ struct urtwn_softc {
|
||||
#define URTWN_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx)
|
||||
#define URTWN_ASSERT_LOCKED(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED)
|
||||
|
||||
#define URTWN_CMDQ_LOCK_INIT(sc) \
|
||||
mtx_init(&(sc)->cmdq_mtx, "cmdq lock", NULL, MTX_DEF)
|
||||
#define URTWN_CMDQ_LOCK(sc) mtx_lock(&(sc)->cmdq_mtx)
|
||||
#define URTWN_CMDQ_UNLOCK(sc) mtx_unlock(&(sc)->cmdq_mtx)
|
||||
#define URTWN_CMDQ_LOCK_DESTROY(sc) mtx_destroy(&(sc)->cmdq_mtx)
|
||||
|
||||
#define URTWN_NT_LOCK_INIT(sc) \
|
||||
mtx_init(&(sc)->nt_mtx, "node table lock", NULL, MTX_DEF)
|
||||
#define URTWN_NT_LOCK(sc) mtx_lock(&(sc)->nt_mtx)
|
||||
|
Loading…
Reference in New Issue
Block a user