static void mwifiex_usb_tx_complete(struct urb *urb) { struct urb_context *context = (struct urb_context *)(urb->context); struct mwifiex_adapter *adapter = context->adapter; struct usb_card_rec *card = adapter->card; struct usb_tx_data_port *port; int i; mwifiex_dbg(adapter, INFO, "%s: status: %d\n", __func__, urb->status); if (context->ep == card->tx_cmd_ep) { mwifiex_dbg(adapter, CMD, "%s: CMD\n", __func__); atomic_dec(&card->tx_cmd_urb_pending); adapter->cmd_sent = false; } else { mwifiex_dbg(adapter, DATA, "%s: DATA\n", __func__); mwifiex_write_data_complete(adapter, context->skb, 0, urb->status ? -1 : 0); for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) { port = &card->port[i]; if (context->ep == port->tx_data_ep) { atomic_dec(&port->tx_data_urb_pending); port->block_status = false; break; } } adapter->data_sent = false; } if (card->mc_resync_flag) mwifiex_multi_chan_resync(adapter); mwifiex_queue_main_work(adapter); return; }
void mwifiex_process_multi_chan_event(struct mwifiex_private *priv, struct sk_buff *event_skb) { struct mwifiex_ie_types_multi_chan_info *chan_info; 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); if (le16_to_cpu(chan_info->header.type) != TLV_TYPE_MULTI_CHAN_INFO || tlv_buf_left < sizeof(struct mwifiex_ie_types_multi_chan_info)) { mwifiex_dbg(adapter, ERROR, "unknown TLV in chan_info event\n"); return; } 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"); tlv_buf_left -= sizeof(struct mwifiex_ie_types_multi_chan_info); tlv = (struct mwifiex_ie_types_header *)chan_info->tlv_buffer; while (tlv_buf_left >= (int)sizeof(struct mwifiex_ie_types_header)) { tlv_type = le16_to_cpu(tlv->type); 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)); } if (adapter->iface_type == MWIFIEX_USB) { adapter->tx_lock_flag = true; adapter->usb_mc_setup = true; mwifiex_multi_chan_resync(adapter); } }