Commit c6999d83 authored by Kalle Valo's avatar Kalle Valo Committed by John W. Linville

wl1271: implement WMM

Now that necessary commands for WMM are implemented, implement queue handling
for WMM. But WMM is not enabled yet, only one queue is used.

Based on a similar patch from wl1251.
Signed-off-by: default avatarKalle Valo <kalle.valo@nokia.com>
Reviewed-by: default avatarJuuso Oikarinen <juuso.oikarinen@nokia.com>
Signed-off-by: default avatarJuuso Oikarinen <juuso.oikarinen@nokia.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent f2054df5
...@@ -1712,6 +1712,36 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, ...@@ -1712,6 +1712,36 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
mutex_unlock(&wl->mutex); mutex_unlock(&wl->mutex);
} }
static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct wl1271 *wl = hw->priv;
int ret;
mutex_lock(&wl->mutex);
wl1271_debug(DEBUG_MAC80211, "mac80211 conf tx %d", queue);
ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue),
params->cw_min, params->cw_max,
params->aifs, params->txop);
if (ret < 0)
goto out;
ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue),
CONF_CHANNEL_TYPE_EDCF,
wl1271_tx_get_queue(queue),
CONF_PS_SCHEME_LEGACY_PSPOLL,
CONF_ACK_POLICY_LEGACY, 0, 0);
if (ret < 0)
goto out;
out:
mutex_unlock(&wl->mutex);
return ret;
}
/* can't be const, mac80211 writes to this */ /* can't be const, mac80211 writes to this */
static struct ieee80211_rate wl1271_rates[] = { static struct ieee80211_rate wl1271_rates[] = {
...@@ -1877,6 +1907,7 @@ static const struct ieee80211_ops wl1271_ops = { ...@@ -1877,6 +1907,7 @@ static const struct ieee80211_ops wl1271_ops = {
.hw_scan = wl1271_op_hw_scan, .hw_scan = wl1271_op_hw_scan,
.bss_info_changed = wl1271_op_bss_info_changed, .bss_info_changed = wl1271_op_bss_info_changed,
.set_rts_threshold = wl1271_op_set_rts_threshold, .set_rts_threshold = wl1271_op_set_rts_threshold,
.conf_tx = wl1271_op_conf_tx,
}; };
static int wl1271_register_hw(struct wl1271 *wl) static int wl1271_register_hw(struct wl1271 *wl)
......
...@@ -87,7 +87,7 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, ...@@ -87,7 +87,7 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
u32 extra, struct ieee80211_tx_info *control) u32 extra, struct ieee80211_tx_info *control)
{ {
struct wl1271_tx_hw_descr *desc; struct wl1271_tx_hw_descr *desc;
int pad; int pad, ac;
u16 tx_attr; u16 tx_attr;
desc = (struct wl1271_tx_hw_descr *) skb->data; desc = (struct wl1271_tx_hw_descr *) skb->data;
...@@ -107,9 +107,11 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, ...@@ -107,9 +107,11 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
/* configure the tx attributes */ /* configure the tx attributes */
tx_attr = wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER; tx_attr = wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER;
/* FIXME: do we know the packet priority? can we identify mgmt
packets, and use max prio for them at least? */ /* queue */
desc->tid = 0; ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
desc->tid = wl1271_tx_ac_to_tid(ac);
desc->aid = TX_HW_DEFAULT_AID; desc->aid = TX_HW_DEFAULT_AID;
desc->reserved = 0; desc->reserved = 0;
......
...@@ -123,6 +123,42 @@ struct wl1271_tx_hw_res_if { ...@@ -123,6 +123,42 @@ struct wl1271_tx_hw_res_if {
struct wl1271_tx_hw_res_descr tx_results_queue[TX_HW_RESULT_QUEUE_LEN]; struct wl1271_tx_hw_res_descr tx_results_queue[TX_HW_RESULT_QUEUE_LEN];
} __attribute__ ((packed)); } __attribute__ ((packed));
static inline int wl1271_tx_get_queue(int queue)
{
/* FIXME: use best effort until WMM is enabled */
return CONF_TX_AC_BE;
switch (queue) {
case 0:
return CONF_TX_AC_VO;
case 1:
return CONF_TX_AC_VI;
case 2:
return CONF_TX_AC_BE;
case 3:
return CONF_TX_AC_BK;
default:
return CONF_TX_AC_BE;
}
}
/* wl1271 tx descriptor needs the tid and we need to convert it from ac */
static inline int wl1271_tx_ac_to_tid(int ac)
{
switch (ac) {
case 0:
return 0;
case 1:
return 2;
case 2:
return 4;
case 3:
return 6;
default:
return 0;
}
}
void wl1271_tx_work(struct work_struct *work); void wl1271_tx_work(struct work_struct *work);
void wl1271_tx_complete(struct wl1271 *wl, u32 count); void wl1271_tx_complete(struct wl1271 *wl, u32 count);
void wl1271_tx_flush(struct wl1271 *wl); void wl1271_tx_flush(struct wl1271 *wl);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment