From 735ab6bfc03878e6b41feb1f14da750a951854ad Mon Sep 17 00:00:00 2001 From: Zhaoyang Liu Date: Fri, 18 Sep 2015 06:32:18 -0700 Subject: [PATCH] mwifiex: complete usb tx data with multi endpoints This patch do the work to TX data with specific USB endpoint. At the same time, update data_sent flag according to multi port status. And is_port_ready API is added for BSS interface to check if current used usb data endpoint is available or not. Signed-off-by: Zhaoyang Liu Signed-off-by: Cathy Luo Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/mwifiex/11n_aggr.c | 2 +- drivers/net/wireless/mwifiex/main.h | 1 + drivers/net/wireless/mwifiex/sta_event.c | 4 +- drivers/net/wireless/mwifiex/sta_tx.c | 6 ++- drivers/net/wireless/mwifiex/txrx.c | 4 +- drivers/net/wireless/mwifiex/uap_event.c | 4 +- drivers/net/wireless/mwifiex/usb.c | 47 +++++++++++++++++++++--- drivers/net/wireless/mwifiex/wmm.c | 38 +++++++++++++++++-- 8 files changed, 90 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c index 46221c2d0f90..2c5ffa13f7b5 100644 --- a/drivers/net/wireless/mwifiex/11n_aggr.c +++ b/drivers/net/wireless/mwifiex/11n_aggr.c @@ -259,7 +259,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, } if (adapter->iface_type == MWIFIEX_USB) { - ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_USB_EP_DATA, + ret = adapter->if_ops.host_to_card(adapter, priv->usb_port, skb_aggr, NULL); } else { if (skb_src) diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 88130028cd89..3959f1c97f4e 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -817,6 +817,7 @@ struct mwifiex_if_ops { void (*submit_rem_rx_urbs)(struct mwifiex_adapter *adapter); void (*deaggr_pkt)(struct mwifiex_adapter *, struct sk_buff *); void (*multi_port_resync)(struct mwifiex_adapter *); + bool (*is_port_ready)(struct mwifiex_private *); }; struct mwifiex_adapter { diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c index c333b2492451..ff3ee9dfbbd5 100644 --- a/drivers/net/wireless/mwifiex/sta_event.c +++ b/drivers/net/wireless/mwifiex/sta_event.c @@ -616,7 +616,9 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) adapter->tx_lock_flag = false; if (adapter->pps_uapsd_mode && adapter->gen_null_pkt) { if (mwifiex_check_last_packet_indication(priv)) { - if (adapter->data_sent) { + if (adapter->data_sent || + (adapter->if_ops.is_port_ready && + !adapter->if_ops.is_port_ready(priv))) { adapter->ps_state = PS_STATE_AWAKE; adapter->pm_wakeup_card_req = false; adapter->pm_wakeup_fw_try = false; diff --git a/drivers/net/wireless/mwifiex/sta_tx.c b/drivers/net/wireless/mwifiex/sta_tx.c index 877ad06336a9..f6683ea6bd5d 100644 --- a/drivers/net/wireless/mwifiex/sta_tx.c +++ b/drivers/net/wireless/mwifiex/sta_tx.c @@ -153,6 +153,10 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags) if (adapter->data_sent) return -1; + if (adapter->if_ops.is_port_ready && + !adapter->if_ops.is_port_ready(priv)) + return -1; + skb = dev_alloc_skb(data_len); if (!skb) return -1; @@ -174,7 +178,7 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags) local_tx_pd->bss_type = priv->bss_type; if (adapter->iface_type == MWIFIEX_USB) { - ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_USB_EP_DATA, + ret = adapter->if_ops.host_to_card(adapter, priv->usb_port, skb, NULL); } else { skb_push(skb, INTF_HEADER_LEN); diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c index 90f4915aea58..bf6182b646a5 100644 --- a/drivers/net/wireless/mwifiex/txrx.c +++ b/drivers/net/wireless/mwifiex/txrx.c @@ -116,7 +116,7 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, local_tx_pd = (struct txpd *)(head_ptr + hroom); if (adapter->iface_type == MWIFIEX_USB) { ret = adapter->if_ops.host_to_card(adapter, - MWIFIEX_USB_EP_DATA, + priv->usb_port, skb, NULL); } else { ret = adapter->if_ops.host_to_card(adapter, @@ -189,7 +189,7 @@ static int mwifiex_host_to_card(struct mwifiex_adapter *adapter, if (adapter->iface_type == MWIFIEX_USB) { ret = adapter->if_ops.host_to_card(adapter, - MWIFIEX_USB_EP_DATA, + priv->usb_port, skb, NULL); } else { ret = adapter->if_ops.host_to_card(adapter, diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c index 46c972a650a4..078834cf1251 100644 --- a/drivers/net/wireless/mwifiex/uap_event.c +++ b/drivers/net/wireless/mwifiex/uap_event.c @@ -269,7 +269,9 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv) adapter->tx_lock_flag = false; if (adapter->pps_uapsd_mode && adapter->gen_null_pkt) { if (mwifiex_check_last_packet_indication(priv)) { - if (adapter->data_sent) { + if (adapter->data_sent || + (adapter->if_ops.is_port_ready && + !adapter->if_ops.is_port_ready(priv))) { adapter->ps_state = PS_STATE_AWAKE; adapter->pm_wakeup_card_req = false; adapter->pm_wakeup_fw_try = false; diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c index 78ad857f20ea..9f5356ef0531 100644 --- a/drivers/net/wireless/mwifiex/usb.c +++ b/drivers/net/wireless/mwifiex/usb.c @@ -282,6 +282,7 @@ static void mwifiex_usb_tx_complete(struct urb *urb) port = &card->port[i]; if (context->ep == port->tx_data_ep) { atomic_dec(&port->tx_data_urb_pending); + port->block_status = false; break; } } @@ -823,6 +824,31 @@ static void mwifiex_usb_port_resync(struct mwifiex_adapter *adapter) } } +static bool mwifiex_usb_is_port_ready(struct mwifiex_private *priv) +{ + struct usb_card_rec *card = priv->adapter->card; + int idx; + + for (idx = 0; idx < MWIFIEX_TX_DATA_PORT; idx++) { + if (priv->usb_port == card->port[idx].tx_data_ep) + return !card->port[idx].block_status; + } + + return false; +} + +static inline u8 mwifiex_usb_data_sent(struct mwifiex_adapter *adapter) +{ + struct usb_card_rec *card = adapter->card; + int i; + + for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) + if (!card->port[i].block_status) + return false; + + return true; +} + /* This function write a command/data packet to card. */ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep, struct sk_buff *skb, @@ -833,7 +859,7 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep, struct usb_tx_data_port *port = NULL; u8 *data = (u8 *)skb->data; struct urb *tx_urb; - int idx; + int idx, ret; if (adapter->is_suspended) { mwifiex_dbg(adapter, ERROR, @@ -856,8 +882,9 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep, port = &card->port[idx]; if (atomic_read(&port->tx_data_urb_pending) >= MWIFIEX_TX_DATA_URB) { - adapter->data_sent = true; - return -EBUSY; + port->block_status = true; + ret = -EBUSY; + goto done; } if (port->tx_data_ix >= MWIFIEX_TX_DATA_URB) port->tx_data_ix = 0; @@ -895,7 +922,7 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep, atomic_dec(&card->tx_cmd_urb_pending); } else { atomic_dec(&port->tx_data_urb_pending); - adapter->data_sent = false; + port->block_status = false; if (port->tx_data_ix) port->tx_data_ix--; else @@ -907,12 +934,19 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep, if (ep != card->tx_cmd_ep && atomic_read(&port->tx_data_urb_pending) == MWIFIEX_TX_DATA_URB) { - adapter->data_sent = true; - return -ENOSR; + port->block_status = true; + ret = -ENOSR; + goto done; } } return -EINPROGRESS; + +done: + if (ep != card->tx_cmd_ep) + adapter->data_sent = mwifiex_usb_data_sent(adapter); + + return ret; } /* This function register usb device and initialize parameter. */ @@ -1189,6 +1223,7 @@ static struct mwifiex_if_ops usb_ops = { .host_to_card = mwifiex_usb_host_to_card, .submit_rem_rx_urbs = mwifiex_usb_submit_rem_rx_urbs, .multi_port_resync = mwifiex_usb_port_resync, + .is_port_ready = mwifiex_usb_is_port_ready, }; /* This function initializes the USB driver module. diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 4f303f388647..7bbdfe4872e4 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c @@ -452,7 +452,21 @@ mwifiex_wmm_init(struct mwifiex_adapter *adapter) int mwifiex_bypass_txlist_empty(struct mwifiex_adapter *adapter) { - return atomic_read(&adapter->bypass_tx_pending) ? false : true; + struct mwifiex_private *priv; + int i; + + for (i = 0; i < adapter->priv_num; i++) { + priv = adapter->priv[i]; + if (!priv) + continue; + if (adapter->if_ops.is_port_ready && + !adapter->if_ops.is_port_ready(priv)) + continue; + if (!skb_queue_empty(&priv->bypass_txq)) + return false; + } + + return true; } /* @@ -466,9 +480,14 @@ mwifiex_wmm_lists_empty(struct mwifiex_adapter *adapter) for (i = 0; i < adapter->priv_num; ++i) { priv = adapter->priv[i]; - if (priv && !priv->port_open) + if (!priv) + continue; + if (!priv->port_open) + continue; + if (adapter->if_ops.is_port_ready && + !adapter->if_ops.is_port_ready(priv)) continue; - if (priv && atomic_read(&priv->wmm.tx_pkts_queued)) + if (atomic_read(&priv->wmm.tx_pkts_queued)) return false; } @@ -1091,6 +1110,10 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, (atomic_read(&priv_tmp->wmm.tx_pkts_queued) == 0)) continue; + if (adapter->if_ops.is_port_ready && + !adapter->if_ops.is_port_ready(priv_tmp)) + continue; + /* iterate over the WMM queues of the BSS */ hqp = &priv_tmp->wmm.highest_queued_prio; for (i = atomic_read(hqp); i >= LOW_PRIO_TID; --i) { @@ -1326,7 +1349,7 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv, spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags); if (adapter->iface_type == MWIFIEX_USB) { - ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_USB_EP_DATA, + ret = adapter->if_ops.host_to_card(adapter, priv->usb_port, skb, NULL); } else { tx_param.next_pkt_len = @@ -1467,6 +1490,13 @@ void mwifiex_process_bypass_tx(struct mwifiex_adapter *adapter) for (i = 0; i < adapter->priv_num; ++i) { priv = adapter->priv[i]; + if (!priv) + continue; + + if (adapter->if_ops.is_port_ready && + !adapter->if_ops.is_port_ready(priv)) + continue; + if (skb_queue_empty(&priv->bypass_txq)) continue; -- 2.20.1