diff --git a/core/hdd/src/wlan_hdd_rx_monitor.c b/core/hdd/src/wlan_hdd_rx_monitor.c index 2d438ca855..8fcbe6fae0 100644 --- a/core/hdd/src/wlan_hdd_rx_monitor.c +++ b/core/hdd/src/wlan_hdd_rx_monitor.c @@ -24,5 +24,97 @@ * under proprietary terms before Copyright ownership was assigned * to the Linux Foundation. */ - +#include "wlan_hdd_includes.h" +#include +#include +#include +#include +#include +#include #include "wlan_hdd_rx_monitor.h" + +/** + * hdd_rx_monitor_callback(): Callback function for receive monitor mode + * @vdev: Handle to vdev object + * @mpdu: pointer to mpdu to be delivered to os + * @rx_status: receive status + * + * Returns: None + */ +void hdd_rx_monitor_callback(ol_osif_vdev_handle context, + qdf_nbuf_t rxbuf, + void *rx_status) +{ + hdd_adapter_t *adapter; + int rxstat; + struct sk_buff *skb; + struct sk_buff *skb_next; + unsigned int cpu_index; + + qdf_assert(context); + qdf_assert(rxbuf); + + adapter = (hdd_adapter_t *)context; + if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) { + QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_ERROR, + "invalid adapter %p", adapter); + return; + } + + cpu_index = wlan_hdd_get_cpu(); + + /* walk the chain until all are processed */ + skb = (struct sk_buff *)rxbuf; + while (NULL != skb) { + skb_next = skb->next; + skb->dev = adapter->dev; + + ++adapter->hdd_stats.hddTxRxStats.rxPackets[cpu_index]; + ++adapter->stats.rx_packets; + adapter->stats.rx_bytes += skb->len; + + /* Remove SKB from internal tracking table before submitting + * it to stack + */ + qdf_net_buf_debug_release_skb(skb); + + /* + * If this is not a last packet on the chain + * Just put packet into backlog queue, not scheduling RX sirq + */ + if (skb->next) { + rxstat = netif_rx(skb); + } else { + /* + * This is the last packet on the chain + * Scheduling rx sirq + */ + rxstat = netif_rx_ni(skb); + } + + if (NET_RX_SUCCESS == rxstat) + ++adapter-> + hdd_stats.hddTxRxStats.rxDelivered[cpu_index]; + else + ++adapter->hdd_stats.hddTxRxStats.rxRefused[cpu_index]; + + skb = skb_next; + } + + adapter->dev->last_rx = jiffies; + + return; +} + +/** + * hdd_monitor_set_rx_monitor_cb(): Set rx monitor mode callback function + * @txrx: pointer to txrx ops + * @rx_monitor_cb: pointer to callback function + * + * Returns: None + */ +void hdd_monitor_set_rx_monitor_cb(struct ol_txrx_ops *txrx, + ol_txrx_rx_mon_fp rx_monitor_cb) +{ + txrx->rx.mon = rx_monitor_cb; +} diff --git a/core/hdd/src/wlan_hdd_rx_monitor.h b/core/hdd/src/wlan_hdd_rx_monitor.h index e657870146..161b8a14bb 100644 --- a/core/hdd/src/wlan_hdd_rx_monitor.h +++ b/core/hdd/src/wlan_hdd_rx_monitor.h @@ -28,5 +28,22 @@ #ifndef __WLAN_HDD_RX_MONITOR_H #define __WLAN_HDD_RX_MONITOR_H +struct ol_txrx_ops; + +#if defined(QCA_WIFI_QCA6290) +void hdd_monitor_set_rx_monitor_cb(struct ol_txrx_ops *txrx, + ol_txrx_rx_mon_fp rx_monitor_cb); + +void hdd_rx_monitor_callback(ol_osif_vdev_handle vdev, + qdf_nbuf_t mpdu, + void *rx_status); +#else +static void hdd_monitor_set_rx_monitor_cb(struct ol_txrx_ops *txrx, + ol_txrx_rx_mon_fp rx_monitor_cb){ } +static void hdd_rx_monitor_callback(ol_osif_vdev_handle vdev, + qdf_nbuf_t mpdu, + void *rx_status){ } +#endif /* CONFIG_LITHIUM */ + #endif /* __WLAN_HDD_RX_MONITOR_H */ diff --git a/core/hdd/src/wlan_hdd_tx_rx.c b/core/hdd/src/wlan_hdd_tx_rx.c index c48258d7fe..1438b5c3e4 100644 --- a/core/hdd/src/wlan_hdd_tx_rx.c +++ b/core/hdd/src/wlan_hdd_tx_rx.c @@ -60,6 +60,8 @@ #include "wlan_hdd_nan_datapath.h" #include "pld_common.h" #include +#include "wlan_hdd_rx_monitor.h" + #ifdef QCA_LL_TX_FLOW_CONTROL_V2 /* * Mapping Linux AC interpretation to SME AC. @@ -1427,6 +1429,7 @@ int hdd_set_mon_rx_cb(struct net_device *dev) qdf_mem_zero(&txrx_ops, sizeof(txrx_ops)); txrx_ops.rx.rx = hdd_mon_rx_packet_cbk; + hdd_monitor_set_rx_monitor_cb(&txrx_ops, hdd_rx_monitor_callback); cdp_vdev_register(soc, (struct cdp_vdev *)cdp_get_vdev_from_vdev_id(soc, (struct cdp_pdev *)pdev, adapter->sessionId),