Commit 2b0f997d authored by Zhaoyang Liu's avatar Zhaoyang Liu Committed by Kalle Valo

mwifiex: add usb multi channel event process support

This patch add multi channel event process for USB multi tx data endpoints.
Driver receives firmware multi channel event only in case that new
connection is setup or interface is disconnect. Different BSS interface
need update used usb endpoint.
Signed-off-by: default avatarZhaoyang Liu <liuzy@marvell.com>
Signed-off-by: default avatarCathy Luo <cluo@marvell.com>
Signed-off-by: default avatarAmitkumar Karwar <akarwar@marvell.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent d9414443
...@@ -104,6 +104,7 @@ enum KEY_TYPE_ID { ...@@ -104,6 +104,7 @@ enum KEY_TYPE_ID {
enum mwifiex_usb_ep { enum mwifiex_usb_ep {
MWIFIEX_USB_EP_CMD_EVENT = 1, MWIFIEX_USB_EP_CMD_EVENT = 1,
MWIFIEX_USB_EP_DATA = 2, MWIFIEX_USB_EP_DATA = 2,
MWIFIEX_USB_EP_DATA_CH2 = 3,
}; };
enum MWIFIEX_802_11_PRIVACY_FILTER { enum MWIFIEX_802_11_PRIVACY_FILTER {
...@@ -173,6 +174,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { ...@@ -173,6 +174,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#define TLV_TYPE_COALESCE_RULE (PROPRIETARY_TLV_BASE_ID + 154) #define TLV_TYPE_COALESCE_RULE (PROPRIETARY_TLV_BASE_ID + 154)
#define TLV_TYPE_KEY_PARAM_V2 (PROPRIETARY_TLV_BASE_ID + 156) #define TLV_TYPE_KEY_PARAM_V2 (PROPRIETARY_TLV_BASE_ID + 156)
#define TLV_TYPE_MULTI_CHAN_INFO (PROPRIETARY_TLV_BASE_ID + 183) #define TLV_TYPE_MULTI_CHAN_INFO (PROPRIETARY_TLV_BASE_ID + 183)
#define TLV_TYPE_MC_GROUP_INFO (PROPRIETARY_TLV_BASE_ID + 184)
#define TLV_TYPE_TDLS_IDLE_TIMEOUT (PROPRIETARY_TLV_BASE_ID + 194) #define TLV_TYPE_TDLS_IDLE_TIMEOUT (PROPRIETARY_TLV_BASE_ID + 194)
#define TLV_TYPE_SCAN_CHANNEL_GAP (PROPRIETARY_TLV_BASE_ID + 197) #define TLV_TYPE_SCAN_CHANNEL_GAP (PROPRIETARY_TLV_BASE_ID + 197)
#define TLV_TYPE_API_REV (PROPRIETARY_TLV_BASE_ID + 199) #define TLV_TYPE_API_REV (PROPRIETARY_TLV_BASE_ID + 199)
...@@ -1984,6 +1986,22 @@ struct mwifiex_ie_types_multi_chan_info { ...@@ -1984,6 +1986,22 @@ struct mwifiex_ie_types_multi_chan_info {
u8 tlv_buffer[0]; u8 tlv_buffer[0];
} __packed; } __packed;
struct mwifiex_ie_types_mc_group_info {
struct mwifiex_ie_types_header header;
u8 chan_group_id;
u8 chan_buf_weight;
u8 band_config;
u8 chan_num;
u32 chan_time;
u32 reserved;
union {
u8 sdio_func_num;
u8 usb_ep_num;
} hid_num;
u8 intf_num;
u8 bss_type_numlist[0];
} __packed;
struct meas_rpt_map { struct meas_rpt_map {
u8 rssi:3; u8 rssi:3;
u8 unmeasured:1; u8 unmeasured:1;
......
...@@ -78,6 +78,7 @@ int mwifiex_init_priv(struct mwifiex_private *priv) ...@@ -78,6 +78,7 @@ int mwifiex_init_priv(struct mwifiex_private *priv)
priv->media_connected = false; priv->media_connected = false;
eth_broadcast_addr(priv->curr_addr); eth_broadcast_addr(priv->curr_addr);
priv->port_open = false; priv->port_open = false;
priv->usb_port = MWIFIEX_USB_EP_DATA;
priv->pkt_tx_ctrl = 0; priv->pkt_tx_ctrl = 0;
priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
priv->data_rate = 0; /* Initially indicate the rate as auto */ priv->data_rate = 0; /* Initially indicate the rate as auto */
......
...@@ -519,6 +519,7 @@ struct mwifiex_private { ...@@ -519,6 +519,7 @@ struct mwifiex_private {
u8 curr_addr[ETH_ALEN]; u8 curr_addr[ETH_ALEN];
u8 media_connected; u8 media_connected;
u8 port_open; u8 port_open;
u8 usb_port;
u32 num_tx_timeout; u32 num_tx_timeout;
/* track consecutive timeout */ /* track consecutive timeout */
u8 tx_timeout_cnt; u8 tx_timeout_cnt;
...@@ -989,6 +990,7 @@ struct mwifiex_adapter { ...@@ -989,6 +990,7 @@ struct mwifiex_adapter {
u8 coex_rx_win_size; u8 coex_rx_win_size;
bool drcs_enabled; bool drcs_enabled;
u8 active_scan_triggered; u8 active_scan_triggered;
bool usb_mc_status;
}; };
void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter); void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter);
......
...@@ -313,25 +313,74 @@ void mwifiex_process_multi_chan_event(struct mwifiex_private *priv, ...@@ -313,25 +313,74 @@ void mwifiex_process_multi_chan_event(struct mwifiex_private *priv,
struct sk_buff *event_skb) struct sk_buff *event_skb)
{ {
struct mwifiex_ie_types_multi_chan_info *chan_info; struct mwifiex_ie_types_multi_chan_info *chan_info;
u16 status; struct mwifiex_ie_types_mc_group_info *grp_info;
struct mwifiex_adapter *adapter = priv->adapter;
struct mwifiex_ie_types_header *tlv;
u16 tlv_buf_left, tlv_type, tlv_len;
int intf_num, bss_type, bss_num, i;
struct mwifiex_private *intf_priv;
tlv_buf_left = event_skb->len - sizeof(u32);
chan_info = (void *)event_skb->data + sizeof(u32); chan_info = (void *)event_skb->data + sizeof(u32);
if (le16_to_cpu(chan_info->header.type) != TLV_TYPE_MULTI_CHAN_INFO) { if (le16_to_cpu(chan_info->header.type) != TLV_TYPE_MULTI_CHAN_INFO ||
mwifiex_dbg(priv->adapter, ERROR, tlv_buf_left < sizeof(struct mwifiex_ie_types_multi_chan_info)) {
mwifiex_dbg(adapter, ERROR,
"unknown TLV in chan_info event\n"); "unknown TLV in chan_info event\n");
return; return;
} }
status = le16_to_cpu(chan_info->status); adapter->usb_mc_status = le16_to_cpu(chan_info->status);
mwifiex_dbg(adapter, EVENT, "multi chan operation %s\n",
adapter->usb_mc_status ? "started" : "over");
if (status) { tlv_buf_left -= sizeof(struct mwifiex_ie_types_multi_chan_info);
mwifiex_dbg(priv->adapter, EVENT, tlv = (struct mwifiex_ie_types_header *)chan_info->tlv_buffer;
"multi-channel operation started\n");
} else { while (tlv_buf_left >= (int)sizeof(struct mwifiex_ie_types_header)) {
mwifiex_dbg(priv->adapter, EVENT, tlv_type = le16_to_cpu(tlv->type);
"multi-channel operation over\n"); tlv_len = le16_to_cpu(tlv->len);
if ((sizeof(struct mwifiex_ie_types_header) + tlv_len) >
tlv_buf_left) {
mwifiex_dbg(adapter, ERROR, "wrong tlv: tlvLen=%d,\t"
"tlvBufLeft=%d\n", tlv_len, tlv_buf_left);
break;
} }
if (tlv_type != TLV_TYPE_MC_GROUP_INFO) {
mwifiex_dbg(adapter, ERROR, "wrong tlv type: 0x%x\n",
tlv_type);
break;
}
grp_info = (struct mwifiex_ie_types_mc_group_info *)tlv;
intf_num = grp_info->intf_num;
for (i = 0; i < intf_num; i++) {
bss_type = grp_info->bss_type_numlist[i] >> 4;
bss_num = grp_info->bss_type_numlist[i] & BSS_NUM_MASK;
intf_priv = mwifiex_get_priv_by_id(adapter, bss_num,
bss_type);
if (!intf_priv) {
mwifiex_dbg(adapter, ERROR,
"Invalid bss_type bss_num\t"
"in multi channel event\n");
continue;
}
if (adapter->iface_type == MWIFIEX_USB) {
u8 ep;
ep = grp_info->hid_num.usb_ep_num;
if (ep == MWIFIEX_USB_EP_DATA ||
ep == MWIFIEX_USB_EP_DATA_CH2)
intf_priv->usb_port = ep;
}
}
tlv_buf_left -= sizeof(struct mwifiex_ie_types_header) +
tlv_len;
tlv = (void *)((u8 *)tlv + tlv_len +
sizeof(struct mwifiex_ie_types_header));
}
} }
void mwifiex_process_tx_pause_event(struct mwifiex_private *priv, void mwifiex_process_tx_pause_event(struct mwifiex_private *priv,
......
...@@ -858,6 +858,8 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter) ...@@ -858,6 +858,8 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
break; break;
} }
adapter->usb_mc_status = false;
return 0; return 0;
} }
......
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