summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlinux/moal_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlinux/moal_main.c')
-rw-r--r--drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlinux/moal_main.c149
1 files changed, 138 insertions, 11 deletions
diff --git a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlinux/moal_main.c b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlinux/moal_main.c
index a4d5f0b8b919..2bd60785c8cb 100644
--- a/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlinux/moal_main.c
+++ b/drivers/net/wireless/nxp/mxm_wifiex/wlan_src/mlinux/moal_main.c
@@ -635,6 +635,8 @@ static mlan_callbacks woal_callbacks = {
.moal_wait_hostcmd_complete = moal_wait_hostcmd_complete,
.moal_notify_hostcmd_complete = moal_notify_hostcmd_complete,
#endif
+ .moal_tp_accounting = moal_tp_accounting,
+ .moal_tp_accounting_rx_param = moal_tp_accounting_rx_param,
};
int woal_open(struct net_device *dev);
@@ -3731,6 +3733,7 @@ moal_private *woal_add_interface(moal_handle *handle, t_u8 bss_index,
INIT_LIST_HEAD(&priv->tx_stat_queue);
spin_lock_init(&priv->tx_stat_lock);
+
#ifdef STA_CFG80211
#ifdef STA_SUPPORT
spin_lock_init(&priv->connect_lock);
@@ -4329,7 +4332,11 @@ void woal_terminate_workqueue(moal_handle *handle)
destroy_workqueue(handle->evt_workqueue);
handle->evt_workqueue = NULL;
}
-
+ if (handle->tx_workqueue) {
+ flush_workqueue(handle->tx_workqueue);
+ destroy_workqueue(handle->tx_workqueue);
+ handle->tx_workqueue = NULL;
+ }
LEAVE();
}
@@ -5052,6 +5059,9 @@ void woal_flush_tx_stat_queue(moal_private *priv)
}
INIT_LIST_HEAD(&priv->tx_stat_queue);
spin_unlock_irqrestore(&priv->tx_stat_lock, flags);
+ spin_lock_bh(&(priv->tx_q.lock));
+ __skb_queue_purge(&priv->tx_q);
+ spin_unlock_bh(&(priv->tx_q.lock));
}
/**
@@ -5421,9 +5431,8 @@ done:
*
* @return 0 --success
*/
-netdev_tx_t woal_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+int woal_start_xmit(moal_private *priv, struct sk_buff *skb)
{
- moal_private *priv = (moal_private *)netdev_priv(dev);
mlan_buffer *pmbuf = NULL;
mlan_status status;
struct sk_buff *new_skb = NULL;
@@ -5433,14 +5442,7 @@ netdev_tx_t woal_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
int ret = 0;
ENTER();
- PRINTM(MDATA, "%lu : %s (bss=%d): Data <= kernel\n", jiffies, dev->name,
- priv->bss_index);
- if (priv->phandle->surprise_removed == MTRUE) {
- dev_kfree_skb_any(skb);
- priv->stats.tx_dropped++;
- goto done;
- }
priv->num_tx_timeout = 0;
if (!skb->len || (skb->len > ETH_FRAME_LEN)) {
PRINTM(MERROR, "Tx Error: Bad skb length %d : %d\n", skb->len,
@@ -5530,6 +5532,50 @@ done:
}
/**
+ * @brief This function handles packet transmission
+ *
+ * @param skb A pointer to sk_buff structure
+ * @param dev A pointer to net_device structure
+ *
+ * @return 0 --success
+ */
+netdev_tx_t woal_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ moal_private *priv = (moal_private *)netdev_priv(dev);
+ ENTER();
+ PRINTM(MDATA, "%lu : %s (bss=%d): Data <= kernel\n", jiffies, dev->name,
+ priv->bss_index);
+
+ /* Collect TP statistics */
+ if (priv->phandle->tp_acnt.on)
+ moal_tp_accounting(priv->phandle, skb, 1);
+ /* Drop Tx packets at drop point 1 */
+ if (priv->phandle->tp_acnt.drop_point == 1) {
+ dev_kfree_skb_any(skb);
+ LEAVE();
+ return 0;
+ }
+ if (priv->phandle->surprise_removed == MTRUE) {
+ dev_kfree_skb_any(skb);
+ priv->stats.tx_dropped++;
+ goto done;
+ }
+ if (moal_extflg_isset(priv->phandle, EXT_TX_WORK)) {
+ spin_lock_bh(&(priv->tx_q.lock));
+ __skb_queue_tail(&(priv->tx_q), skb);
+ spin_unlock_bh(&(priv->tx_q.lock));
+
+ queue_work(priv->phandle->tx_workqueue,
+ &priv->phandle->tx_work);
+ goto done;
+ }
+ woal_start_xmit(priv, skb);
+done:
+ LEAVE();
+ return 0;
+}
+
+/**
* @brief Convert ascii string to Hex integer
*
* @param d A pointer to integer buf
@@ -5793,6 +5839,7 @@ void woal_init_priv(moal_private *priv, t_u8 wait_option)
}
#endif
+ skb_queue_head_init(&priv->tx_q);
memset(&priv->tx_protocols, 0, sizeof(dot11_protocol));
memset(&priv->rx_protocols, 0, sizeof(dot11_protocol));
priv->media_connected = MFALSE;
@@ -6970,7 +7017,8 @@ save_ssudump:
return;
}
DBG_HEXDUMP(MEVT_D, "SSU addr", pmevent->event_buf, 8);
- moal_memcpy_ext(phandle, &tmpbuf, pmevent->event_buf, 8, 8);
+ moal_memcpy_ext(phandle, &tmpbuf, pmevent->event_buf, sizeof(t_ptr),
+ sizeof(t_ptr));
PRINTM(MEVENT, "woal_store_ssu_dump: tmpbuf %p\n", tmpbuf);
for (i = 0; i < pmevent->event_len / 4; i++) {
if ((i + 1) % 8 == 0)
@@ -8248,6 +8296,54 @@ t_void woal_rx_work_queue(struct work_struct *work)
}
/**
+ * @brief This function dequeue pkt from list
+ *
+ * @param list A pointer to struct sk_buff_head
+ *
+ * @return skb buffer
+ */
+
+struct sk_buff *woal_skb_dequeue_spinlock(struct sk_buff_head *list)
+{
+ struct sk_buff *result;
+
+ spin_lock_bh(&list->lock);
+ result = __skb_dequeue(list);
+ spin_unlock_bh(&list->lock);
+ return result;
+}
+
+/**
+ * @brief This workqueue function handles rx_work_process
+ *
+ * @param work A pointer to work_struct
+ *
+ * @return N/A
+ */
+t_void woal_tx_work_handler(struct work_struct *work)
+{
+ moal_handle *handle = container_of(work, moal_handle, tx_work);
+ moal_private *priv = NULL;
+ int i = 0;
+ struct sk_buff *skb = NULL;
+
+ ENTER();
+ if (handle->surprise_removed == MTRUE) {
+ LEAVE();
+ return;
+ }
+
+ for (i = 0; i < MIN(handle->priv_num, MLAN_MAX_BSS_NUM); i++) {
+ priv = handle->priv[i];
+ while ((skb = woal_skb_dequeue_spinlock(&priv->tx_q)) != NULL) {
+ woal_start_xmit(priv, skb);
+ }
+ }
+
+ LEAVE();
+}
+
+/**
* @brief This workqueue function handles main_process
*
* @param work A pointer to work_struct
@@ -8535,6 +8631,26 @@ moal_handle *woal_add_card(void *card, struct device *dev, moal_if_ops *if_ops,
napi_enable(&handle->napi_rx);
}
+ if (moal_extflg_isset(handle, EXT_TX_WORK)) {
+ /* Create workqueue for tx process */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
+ handle->tx_workqueue = create_workqueue("MOAL_TX_WORKQ");
+#else
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
+ handle->tx_workqueue = alloc_workqueue(
+ "MOAL_TX_WORK_QUEUE",
+ WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 1);
+#else
+ handle->tx_workqueue = create_workqueue("MOAL_TX_WORK_QUEUE");
+#endif
+#endif
+ if (!handle->tx_workqueue) {
+ woal_terminate_workqueue(handle);
+ goto err_kmalloc;
+ }
+ MLAN_INIT_WORK(&handle->tx_work, woal_tx_work_handler);
+ }
+
#ifdef REASSOCIATION
PRINTM(MINFO, "Starting re-association thread...\n");
handle->reassoc_thread.handle = handle;
@@ -8676,6 +8792,8 @@ mlan_status woal_remove_card(void *card)
flush_workqueue(handle->evt_workqueue);
if (handle->rx_workqueue)
flush_workqueue(handle->rx_workqueue);
+ if (handle->tx_workqueue)
+ flush_workqueue(handle->tx_workqueue);
if (moal_extflg_isset(handle, EXT_NAPI)) {
napi_disable(&handle->napi_rx);
@@ -8741,6 +8859,15 @@ mlan_status woal_remove_card(void *card)
#endif
#endif
#endif
+ if (handle->tp_acnt.on) {
+ handle->tp_acnt.on = 0;
+ handle->tp_acnt.drop_point = 0;
+ if (handle->is_tp_acnt_timer_set) {
+ woal_cancel_timer(&handle->tp_acnt.timer);
+ handle->is_tp_acnt_timer_set = MFALSE;
+ }
+ }
+
/* Remove interface */
for (i = 0; i < MIN(MLAN_MAX_BSS_NUM, handle->priv_num); i++)
woal_remove_interface(handle, i);