Commit b9010f10 authored by Ahmad Masri's avatar Ahmad Masri Committed by Kalle Valo

wil6210: add FT roam support for AP and station

This feature is needed for enterprise APs and clients to enable
fast roaming as defined in 802.11r between APs in the same ESS.

On AP side, this feature is supported only when disable_ap_sme
is enabled.
Signed-off-by: default avatarAhmad Masri <amasri@codeaurora.org>
Signed-off-by: default avatarMaya Erez <merez@codeaurora.org>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent 84f16fbb
This diff is collapsed.
......@@ -1669,6 +1669,7 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock)
char *status = "unknown";
u8 aid = 0;
u8 mid;
bool sta_connected = false;
switch (p->status) {
case wil_sta_unused:
......@@ -1683,8 +1684,20 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock)
break;
}
mid = (p->status != wil_sta_unused) ? p->mid : U8_MAX;
seq_printf(s, "[%d] %pM %s MID %d AID %d\n", i, p->addr, status,
mid, aid);
if (mid < wil->max_vifs) {
struct wil6210_vif *vif = wil->vifs[mid];
if (vif->wdev.iftype == NL80211_IFTYPE_STATION &&
p->status == wil_sta_connected)
sta_connected = true;
}
/* print roam counter only for connected stations */
if (sta_connected)
seq_printf(s, "[%d] %pM connected (roam counter %d) MID %d AID %d\n",
i, p->addr, p->stats.ft_roams, mid, aid);
else
seq_printf(s, "[%d] %pM %s MID %d AID %d\n", i,
p->addr, status, mid, aid);
if (p->status == wil_sta_connected) {
spin_lock_bh(&p->tid_rx_lock);
......
......@@ -361,6 +361,8 @@ static void _wil6210_disconnect(struct wil6210_vif *vif, const u8 *bssid,
vif->bss = NULL;
}
clear_bit(wil_vif_fwconnecting, vif->status);
clear_bit(wil_vif_ft_roam, vif->status);
break;
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_P2P_GO:
......
......@@ -1059,6 +1059,88 @@ static int wil_vring_init_tx(struct wil6210_vif *vif, int id, int size,
return rc;
}
static int wil_tx_vring_modify(struct wil6210_vif *vif, int ring_id, int cid,
int tid)
{
struct wil6210_priv *wil = vif_to_wil(vif);
int rc;
struct wmi_vring_cfg_cmd cmd = {
.action = cpu_to_le32(WMI_VRING_CMD_MODIFY),
.vring_cfg = {
.tx_sw_ring = {
.max_mpdu_size =
cpu_to_le16(wil_mtu2macbuf(mtu_max)),
.ring_size = 0,
},
.ringid = ring_id,
.cidxtid = mk_cidxtid(cid, tid),
.encap_trans_type = WMI_VRING_ENC_TYPE_802_3,
.mac_ctrl = 0,
.to_resolution = 0,
.agg_max_wsize = 0,
.schd_params = {
.priority = cpu_to_le16(0),
.timeslot_us = cpu_to_le16(0xfff),
},
},
};
struct {
struct wmi_cmd_hdr wmi;
struct wmi_vring_cfg_done_event cmd;
} __packed reply = {
.cmd = {.status = WMI_FW_STATUS_FAILURE},
};
struct wil_ring *vring = &wil->ring_tx[ring_id];
struct wil_ring_tx_data *txdata = &wil->ring_tx_data[ring_id];
wil_dbg_misc(wil, "vring_modify: ring %d cid %d tid %d\n", ring_id,
cid, tid);
lockdep_assert_held(&wil->mutex);
if (!vring->va) {
wil_err(wil, "Tx ring [%d] not allocated\n", ring_id);
return -EINVAL;
}
if (wil->ring2cid_tid[ring_id][0] != cid ||
wil->ring2cid_tid[ring_id][1] != tid) {
wil_err(wil, "ring info does not match cid=%u tid=%u\n",
wil->ring2cid_tid[ring_id][0],
wil->ring2cid_tid[ring_id][1]);
}
cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa);
rc = wmi_call(wil, WMI_VRING_CFG_CMDID, vif->mid, &cmd, sizeof(cmd),
WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply), 100);
if (rc)
goto fail;
if (reply.cmd.status != WMI_FW_STATUS_SUCCESS) {
wil_err(wil, "Tx modify failed, status 0x%02x\n",
reply.cmd.status);
rc = -EINVAL;
goto fail;
}
/* set BA aggregation window size to 0 to force a new BA with the
* new AP
*/
txdata->agg_wsize = 0;
if (txdata->dot1x_open && agg_wsize >= 0)
wil_addba_tx_request(wil, ring_id, agg_wsize);
return 0;
fail:
spin_lock_bh(&txdata->lock);
txdata->dot1x_open = false;
txdata->enabled = 0;
spin_unlock_bh(&txdata->lock);
wil->ring2cid_tid[ring_id][0] = WIL6210_MAX_CID;
wil->ring2cid_tid[ring_id][1] = 0;
return rc;
}
int wil_vring_init_bcast(struct wil6210_vif *vif, int id, int size)
{
struct wil6210_priv *wil = vif_to_wil(vif);
......@@ -2281,6 +2363,7 @@ void wil_init_txrx_ops_legacy_dma(struct wil6210_priv *wil)
wil->txrx_ops.ring_init_bcast = wil_vring_init_bcast;
wil->txrx_ops.tx_init = wil_tx_init;
wil->txrx_ops.tx_fini = wil_tx_fini;
wil->txrx_ops.tx_ring_modify = wil_tx_vring_modify;
/* RX ops */
wil->txrx_ops.rx_init = wil_rx_init;
wil->txrx_ops.wmi_addba_rx_resp = wmi_addba_rx_resp;
......
......@@ -747,6 +747,16 @@ static int wil_ring_init_tx_edma(struct wil6210_vif *vif, int ring_id,
return rc;
}
static int wil_tx_ring_modify_edma(struct wil6210_vif *vif, int ring_id,
int cid, int tid)
{
struct wil6210_priv *wil = vif_to_wil(vif);
wil_err(wil, "ring modify is not supported for EDMA\n");
return -EOPNOTSUPP;
}
/* This function is used only for RX SW reorder */
static int wil_check_bar(struct wil6210_priv *wil, void *msg, int cid,
struct sk_buff *skb, struct wil_net_stats *stats)
......@@ -1600,6 +1610,7 @@ void wil_init_txrx_ops_edma(struct wil6210_priv *wil)
wil->txrx_ops.tx_desc_map = wil_tx_desc_map_edma;
wil->txrx_ops.tx_desc_unmap = wil_tx_desc_unmap_edma;
wil->txrx_ops.tx_ring_tso = __wil_tx_ring_tso_edma;
wil->txrx_ops.tx_ring_modify = wil_tx_ring_modify_edma;
/* RX ops */
wil->txrx_ops.rx_init = wil_rx_init_edma;
wil->txrx_ops.wmi_addba_rx_resp = wmi_addba_rx_resp_edma;
......
......@@ -449,6 +449,15 @@ static inline void parse_cidxtid(u8 cidxtid, u8 *cid, u8 *tid)
*tid = (cidxtid >> 4) & 0xf;
}
/**
* wil_cid_valid - check cid is valid
* @cid: CID value
*/
static inline bool wil_cid_valid(u8 cid)
{
return (cid >= 0 && cid < WIL6210_MAX_CID);
}
struct wil6210_mbox_ring {
u32 base;
u16 entry_size; /* max. size of mbox entry, incl. all headers */
......@@ -577,6 +586,7 @@ struct wil_net_stats {
unsigned long rx_csum_err;
u16 last_mcs_rx;
u64 rx_per_mcs[WIL_MCS_MAX + 1];
u32 ft_roams; /* relevant in STA mode */
};
/**
......@@ -599,6 +609,8 @@ struct wil_txrx_ops {
struct wil_ctx *ctx);
int (*tx_ring_tso)(struct wil6210_priv *wil, struct wil6210_vif *vif,
struct wil_ring *ring, struct sk_buff *skb);
int (*tx_ring_modify)(struct wil6210_vif *vif, int ring_id,
int cid, int tid);
irqreturn_t (*irq_tx)(int irq, void *cookie);
/* RX ops */
int (*rx_init)(struct wil6210_priv *wil, u16 ring_size);
......@@ -821,6 +833,7 @@ extern u8 led_polarity;
enum wil6210_vif_status {
wil_vif_fwconnecting,
wil_vif_fwconnected,
wil_vif_ft_roam,
wil_vif_status_last /* keep last */
};
......@@ -1204,6 +1217,7 @@ int wmi_add_cipher_key(struct wil6210_vif *vif, u8 key_index,
int wmi_echo(struct wil6210_priv *wil);
int wmi_set_ie(struct wil6210_vif *vif, u8 type, u16 ie_len, const void *ie);
int wmi_rx_chain_add(struct wil6210_priv *wil, struct wil_ring *vring);
int wmi_update_ft_ies(struct wil6210_vif *vif, u16 ie_len, const void *ie);
int wmi_rxon(struct wil6210_priv *wil, bool on);
int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_m, u32 *t_r);
int wmi_disconnect_sta(struct wil6210_vif *vif, const u8 *mac,
......@@ -1319,6 +1333,9 @@ void wil6210_unmask_irq_tx_edma(struct wil6210_priv *wil);
void wil_rx_handle(struct wil6210_priv *wil, int *quota);
void wil6210_unmask_irq_rx(struct wil6210_priv *wil);
void wil6210_unmask_irq_rx_edma(struct wil6210_priv *wil);
void wil_set_crypto_rx(u8 key_index, enum wmi_key_usage key_usage,
struct wil_sta_info *cs,
struct key_params *params);
int wil_iftype_nl2wmi(enum nl80211_iftype type);
......
This diff is collapsed.
......@@ -2370,6 +2370,7 @@ struct wmi_ft_reassoc_status_event {
__le16 beacon_ie_len;
__le16 reassoc_req_ie_len;
__le16 reassoc_resp_ie_len;
u8 reserved[4];
u8 ie_info[0];
} __packed;
......
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