Example #1
0
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;
}
Example #2
0
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);
	}
}