diff options
| author | Alok Kumar <alokkuma@codeaurora.org> | 2018-06-03 02:25:41 +0530 |
|---|---|---|
| committer | nshrivas <nshrivas@codeaurora.org> | 2018-06-06 07:35:50 -0700 |
| commit | aa08e3143dc3ecd0fb26e65104da188ea361cbc9 (patch) | |
| tree | 7cda38689e5eb7f733d111b00e6753dc0b255bce | |
| parent | 43981a16968ac615bbd6677f75f08e5f216eab03 (diff) | |
qcacld-3.0: Add Tx compl callback to check if OTA is needed for TX desc
During hard_start_xmit, a flag in TX desc is marked as true or false
based on, if OTA is needed during TX completion. Based on this flag,
a callback gets called on TX completion before freeing this descriptor.
Change-Id: I4e11b2c35b4747c7af35a387b404e3ccb1e8e8e4
CRs-Fixed: 2253557
| -rw-r--r-- | core/dp/ol/inc/ol_txrx_osif_api.h | 6 | ||||
| -rw-r--r-- | core/dp/txrx/ol_rx_fwd.c | 4 | ||||
| -rw-r--r-- | core/dp/txrx/ol_tx.c | 47 | ||||
| -rw-r--r-- | core/dp/txrx/ol_tx.h | 9 | ||||
| -rw-r--r-- | core/dp/txrx/ol_tx_desc.c | 1 | ||||
| -rw-r--r-- | core/dp/txrx/ol_tx_send.c | 38 | ||||
| -rw-r--r-- | core/dp/txrx/ol_txrx.c | 1 | ||||
| -rw-r--r-- | core/dp/txrx/ol_txrx_types.h | 4 | ||||
| -rw-r--r-- | core/hdd/inc/wlan_hdd_softap_tx_rx.h | 16 | ||||
| -rw-r--r-- | core/hdd/src/wlan_hdd_softap_tx_rx.c | 89 | ||||
| -rw-r--r-- | core/hdd/src/wlan_hdd_tx_rx.c | 2 |
11 files changed, 180 insertions, 37 deletions
diff --git a/core/dp/ol/inc/ol_txrx_osif_api.h b/core/dp/ol/inc/ol_txrx_osif_api.h index fff4da3d1bda..eea3d384d437 100644 --- a/core/dp/ol/inc/ol_txrx_osif_api.h +++ b/core/dp/ol/inc/ol_txrx_osif_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2014-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012, 2014-2018 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -69,7 +69,9 @@ qdf_nbuf_t ol_txrx_osif_tso_segment(ol_txrx_vdev_handle txrx_vdev, int max_seg_payload_bytes, qdf_nbuf_t jumbo_tcp_frame); -qdf_nbuf_t ol_tx_data(ol_txrx_vdev_handle data_vdev, qdf_nbuf_t skb); +qdf_nbuf_t ol_tx_data(ol_txrx_vdev_handle data_vdev, + qdf_nbuf_t skb, + bool notify_tx_comp); void ol_rx_data_process(struct ol_txrx_peer_t *peer, qdf_nbuf_t rx_buf_list); diff --git a/core/dp/txrx/ol_rx_fwd.c b/core/dp/txrx/ol_rx_fwd.c index f33db7424a81..ebc15b7206d9 100644 --- a/core/dp/txrx/ol_rx_fwd.c +++ b/core/dp/txrx/ol_rx_fwd.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2011, 2014-2018 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -124,7 +124,7 @@ static inline void ol_rx_fwd_to_tx(struct ol_txrx_vdev_t *vdev, qdf_nbuf_t msdu) qdf_mem_set(msdu->cb, sizeof(msdu->cb), 0); /* update any cb field expected by OL_TX_SEND */ - msdu = OL_TX_SEND(vdev, msdu); + msdu = OL_TX_SEND(vdev, msdu, 0); if (msdu) { /* diff --git a/core/dp/txrx/ol_tx.c b/core/dp/txrx/ol_tx.c index e08ebab8e82b..201498853abf 100644 --- a/core/dp/txrx/ol_tx.c +++ b/core/dp/txrx/ol_tx.c @@ -239,10 +239,12 @@ static inline uint8_t ol_tx_prepare_tso(ol_txrx_vdev_handle vdev, * ol_tx_data() - send data frame * @vdev: virtual device handle * @skb: skb + * @notify_tx_comp: whether OTA to be notified * * Return: skb/NULL for success */ -qdf_nbuf_t ol_tx_data(ol_txrx_vdev_handle vdev, qdf_nbuf_t skb) +qdf_nbuf_t ol_tx_data(ol_txrx_vdev_handle vdev, qdf_nbuf_t skb, + bool notify_tx_comp) { struct ol_txrx_pdev_t *pdev; qdf_nbuf_t ret; @@ -268,7 +270,7 @@ qdf_nbuf_t ol_tx_data(ol_txrx_vdev_handle vdev, qdf_nbuf_t skb) /* Terminate the (single-element) list of tx frames */ qdf_nbuf_set_next(skb, NULL); - ret = OL_TX_SEND(vdev, skb); + ret = OL_TX_SEND(vdev, skb, notify_tx_comp); if (ret) { ol_txrx_dbg("%s: Failed to tx", __func__); return ret; @@ -312,7 +314,7 @@ qdf_nbuf_t ol_tx_send_ipa_data_frame(void *vdev, */ qdf_net_buf_debug_acquire_skb(skb, __FILE__, __LINE__); - ret = OL_TX_SEND((struct ol_txrx_vdev_t *)vdev, skb); + ret = OL_TX_SEND((struct ol_txrx_vdev_t *)vdev, skb, 0); if (ret) { ol_txrx_dbg("%s: Failed to tx", __func__); return ret; @@ -375,7 +377,8 @@ static uint32_t ol_tx_tso_get_stats_idx(struct ol_txrx_pdev_t *pdev) #endif #if defined(FEATURE_TSO) -qdf_nbuf_t ol_tx_ll(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list) +qdf_nbuf_t ol_tx_ll(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list, + bool notify_tx_comp) { qdf_nbuf_t msdu = msdu_list; struct ol_txrx_msdu_info_t msdu_info; @@ -473,7 +476,8 @@ qdf_nbuf_t ol_tx_ll(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list) } #else /* TSO */ -qdf_nbuf_t ol_tx_ll(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list) +qdf_nbuf_t ol_tx_ll(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list, + bool notify_tx_comp) { qdf_nbuf_t msdu = msdu_list; struct ol_txrx_msdu_info_t msdu_info; @@ -709,7 +713,8 @@ ol_tx_prepare_ll_fast(struct ol_txrx_pdev_t *pdev, * Return: on success return NULL, pointer to nbuf when it fails to send. */ qdf_nbuf_t -ol_tx_ll_fast(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list) +ol_tx_ll_fast(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list, + bool notify_tx_comp) { qdf_nbuf_t msdu = msdu_list; struct ol_txrx_pdev_t *pdev = vdev->pdev; @@ -823,6 +828,10 @@ ol_tx_ll_fast(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list) htt_tx_desc_display(tx_desc->htt_tx_desc); + if (!msdu_info.tso_info.is_tso) + tx_desc->notify_tx_comp = + notify_tx_comp; + /* mark the relevant tso_seg free-able */ if (msdu_info.tso_info.curr_seg) { msdu_info.tso_info.curr_seg-> @@ -890,7 +899,8 @@ ol_tx_ll_fast(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list) } #else qdf_nbuf_t -ol_tx_ll_fast(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list) +ol_tx_ll_fast(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list, + bool notify_tx_comp) { qdf_nbuf_t msdu = msdu_list; struct ol_txrx_pdev_t *pdev = vdev->pdev; @@ -955,6 +965,8 @@ ol_tx_ll_fast(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list) pkt_download_len += sizeof(struct htt_tx_msdu_desc_ext_t); + tx_desc->notify_tx_comp = notify_tx_comp; + htt_tx_desc_display(tx_desc->htt_tx_desc); /* * The netbuf may get linked into a different list @@ -991,23 +1003,25 @@ ol_tx_ll_fast(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list) * */ qdf_nbuf_t -ol_tx_ll_wrapper(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list) +ol_tx_ll_wrapper(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list, + bool notify_tx_comp) { struct hif_opaque_softc *hif_device = (struct hif_opaque_softc *)cds_get_context(QDF_MODULE_ID_HIF); if (qdf_likely(hif_device && hif_is_fastpath_mode_enabled(hif_device))) - msdu_list = ol_tx_ll_fast(vdev, msdu_list); + msdu_list = ol_tx_ll_fast(vdev, msdu_list, notify_tx_comp); else - msdu_list = ol_tx_ll(vdev, msdu_list); + msdu_list = ol_tx_ll(vdev, msdu_list, notify_tx_comp); return msdu_list; } #else qdf_nbuf_t -ol_tx_ll_wrapper(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list) +ol_tx_ll_wrapper(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list, + bool notify_tx_comp) { - return ol_tx_ll(vdev, msdu_list); + return ol_tx_ll(vdev, msdu_list, notify_tx_comp); } #endif /* WLAN_FEATURE_FASTPATH */ @@ -1057,7 +1071,7 @@ static void ol_tx_vdev_ll_pause_queue_send_base(struct ol_txrx_vdev_t *vdev) qdf_nbuf_set_next(tx_msdu, NULL); QDF_NBUF_UPDATE_TX_PKT_COUNT(tx_msdu, QDF_NBUF_TX_PKT_TXRX_DEQUEUE); - tx_msdu = ol_tx_ll_wrapper(vdev, tx_msdu); + tx_msdu = ol_tx_ll_wrapper(vdev, tx_msdu, 0); /* * It is unexpected that ol_tx_ll would reject the frame * since we checked that there's room for it, though @@ -1153,7 +1167,8 @@ qdf_nbuf_t ol_tx_ll_queue(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list) (((struct ethernet_hdr_t *) qdf_nbuf_data(msdu_list))->ethertype[1]); if (ETHERTYPE_IS_EAPOL_WAPI(eth_type)) { - msdu_list = ol_tx_ll_wrapper(vdev, msdu_list); + msdu_list = + ol_tx_ll_wrapper(vdev, msdu_list, 0); return msdu_list; } } @@ -1187,7 +1202,7 @@ qdf_nbuf_t ol_tx_ll_queue(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list) * not paused, no throttle and no backlog - * send the new frames */ - msdu_list = ol_tx_ll_wrapper(vdev, msdu_list); + msdu_list = ol_tx_ll_wrapper(vdev, msdu_list, 0); } } return msdu_list; @@ -1251,7 +1266,7 @@ void ol_tx_pdev_ll_pause_queue_send_all(struct ol_txrx_pdev_t *pdev) vdev->ll_pause.txq.tail = NULL; qdf_nbuf_set_next(tx_msdu, NULL); - tx_msdu = ol_tx_ll_wrapper(vdev, tx_msdu); + tx_msdu = ol_tx_ll_wrapper(vdev, tx_msdu, 0); /* * It is unexpected that ol_tx_ll would reject * the frame, since we checked that there's diff --git a/core/dp/txrx/ol_tx.h b/core/dp/txrx/ol_tx.h index 7eb71ea38eb2..35d56bb6dcb5 100644 --- a/core/dp/txrx/ol_tx.h +++ b/core/dp/txrx/ol_tx.h @@ -30,10 +30,13 @@ #include <ol_txrx_types.h> /* ol_tx_desc_t, ol_txrx_msdu_info_t */ -qdf_nbuf_t ol_tx_ll(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list); -qdf_nbuf_t ol_tx_ll_wrapper(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list); +qdf_nbuf_t ol_tx_ll(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list, + bool notify_tx_comp); +qdf_nbuf_t ol_tx_ll_wrapper(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list, + bool notify_tx_comp); #ifdef WLAN_FEATURE_FASTPATH -qdf_nbuf_t ol_tx_ll_fast(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list); +qdf_nbuf_t ol_tx_ll_fast(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list, + bool notify_tx_comp); #endif qdf_nbuf_t ol_tx_ll_queue(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list); diff --git a/core/dp/txrx/ol_tx_desc.c b/core/dp/txrx/ol_tx_desc.c index e8e150536ff0..0232296e745d 100644 --- a/core/dp/txrx/ol_tx_desc.c +++ b/core/dp/txrx/ol_tx_desc.c @@ -415,6 +415,7 @@ static void ol_tx_desc_free_common(struct ol_txrx_pdev_t *pdev, /* clear the ref cnt */ qdf_atomic_init(&tx_desc->ref_cnt); tx_desc->vdev_id = OL_TXRX_INVALID_VDEV_ID; + tx_desc->notify_tx_comp = 0; } #ifndef QCA_LL_TX_FLOW_CONTROL_V2 diff --git a/core/dp/txrx/ol_tx_send.c b/core/dp/txrx/ol_tx_send.c index 9fcf10c9d9f0..71fcda87da90 100644 --- a/core/dp/txrx/ol_tx_send.c +++ b/core/dp/txrx/ol_tx_send.c @@ -575,6 +575,41 @@ void ol_tx_flow_pool_unlock(struct ol_tx_desc_t *tx_desc) #endif /** + * ol_tx_notify_completion() - Notify tx completion for this desc + * @tx_desc: tx desc + * @netbuf: buffer + * + * Return: none + */ +static void ol_tx_notify_completion(struct ol_tx_desc_t *tx_desc, + qdf_nbuf_t netbuf) +{ + void *osif_dev; + ol_txrx_completion_fp tx_compl_cbk = NULL; + + qdf_assert(tx_desc); + + ol_tx_flow_pool_lock(tx_desc); + /* + * In cases when vdev has gone down and tx completion + * are received, leads to NULL vdev access. + * So, check for NULL before dereferencing it. + */ + if (!tx_desc->vdev || + !tx_desc->vdev->osif_dev || + !tx_desc->vdev->tx_comp || + !tx_desc->notify_tx_comp) { + ol_tx_flow_pool_unlock(tx_desc); + return; + } + osif_dev = tx_desc->vdev->osif_dev; + tx_compl_cbk = tx_desc->vdev->tx_comp; + ol_tx_flow_pool_unlock(tx_desc); + + tx_compl_cbk(netbuf, osif_dev); +} + +/** * ol_tx_update_connectivity_stats() - update connectivity stats * @tx_desc: tx desc * @netbuf: buffer @@ -772,6 +807,9 @@ ol_tx_completion_handler(ol_txrx_pdev_handle pdev, ol_tx_update_arp_stats(tx_desc, netbuf, status); } + /* check tx completion notification */ + ol_tx_notify_completion(tx_desc, netbuf); + /* track connectivity stats */ ol_tx_update_connectivity_stats(tx_desc, netbuf, status); diff --git a/core/dp/txrx/ol_txrx.c b/core/dp/txrx/ol_txrx.c index 419fa98f16b7..049f548598c8 100644 --- a/core/dp/txrx/ol_txrx.c +++ b/core/dp/txrx/ol_txrx.c @@ -2469,6 +2469,7 @@ void ol_txrx_vdev_register(ol_txrx_vdev_handle vdev, vdev->osif_dev = osif_vdev; vdev->rx = txrx_ops->rx.rx; vdev->stats_rx = txrx_ops->rx.stats_rx; + vdev->tx_comp = txrx_ops->tx.tx_comp; txrx_ops->tx.tx = ol_tx_data; } diff --git a/core/dp/txrx/ol_txrx_types.h b/core/dp/txrx/ol_txrx_types.h index 2d595b20b343..ea28aa3ba3da 100644 --- a/core/dp/txrx/ol_txrx_types.h +++ b/core/dp/txrx/ol_txrx_types.h @@ -203,6 +203,7 @@ struct ol_tx_desc_t { #endif void *tso_desc; void *tso_num_desc; + bool notify_tx_comp; }; typedef TAILQ_HEAD(some_struct_name, ol_tx_desc_t) ol_tx_desc_list; @@ -1058,6 +1059,9 @@ struct ol_txrx_vdev_t { ol_txrx_rx_fp rx; /* receive function used by this vdev */ ol_txrx_stats_rx_fp stats_rx; /* receive function used by this vdev */ + /* completion function used by this vdev*/ + ol_txrx_completion_fp tx_comp; + struct { /* * If the vdev object couldn't be deleted immediately because diff --git a/core/hdd/inc/wlan_hdd_softap_tx_rx.h b/core/hdd/inc/wlan_hdd_softap_tx_rx.h index 66a8e323d11e..7ea467131d3d 100644 --- a/core/hdd/inc/wlan_hdd_softap_tx_rx.h +++ b/core/hdd/inc/wlan_hdd_softap_tx_rx.h @@ -38,7 +38,7 @@ QDF_STATUS hdd_softap_init_tx_rx_sta(hdd_adapter_t *pAdapter, struct qdf_mac_addr *pmacAddrSTA); QDF_STATUS hdd_softap_deinit_tx_rx_sta(hdd_adapter_t *pAdapter, uint8_t STAId); - +void hdd_softap_notify_tx_compl_cbk(struct sk_buff *skb, void *context); QDF_STATUS hdd_softap_rx_packet_cbk(void *context, qdf_nbuf_t rxBufChain); #ifdef IPA_OFFLOAD QDF_STATUS hdd_softap_rx_mul_packet_cbk(void *cds_context, @@ -92,15 +92,25 @@ QDF_STATUS hdd_post_dhcp_ind(hdd_adapter_t *adapter, uint8_t sta_id, uint16_t type); /** + * hdd_softap_notify_dhcp_ind() - Notify SAP for DHCP indication for tx desc + * @context: pointer to HDD context + * @netbuf: pointer to OS packet (sk_buff) + * + * Return: None + */ +void hdd_softap_notify_dhcp_ind(void *context, + struct sk_buff *netbuf); + +/** * hdd_dhcp_indication() - Send DHCP START/STOP indication to FW * @adapter: pointer to hdd adapter * @sta_id: peer station ID * @skb: pointer to OS packet (sk_buff) * @dir: direction * - * Return: None + * Return: true if tx comp is to be notified for skb */ -void hdd_dhcp_indication(hdd_adapter_t *adapter, +bool hdd_dhcp_indication(hdd_adapter_t *adapter, uint8_t sta_id, struct sk_buff *skb, enum qdf_proto_dir dir); diff --git a/core/hdd/src/wlan_hdd_softap_tx_rx.c b/core/hdd/src/wlan_hdd_softap_tx_rx.c index 69cfb7d565b5..0eef1a708cad 100644 --- a/core/hdd/src/wlan_hdd_softap_tx_rx.c +++ b/core/hdd/src/wlan_hdd_softap_tx_rx.c @@ -285,6 +285,47 @@ QDF_STATUS hdd_post_dhcp_ind(hdd_adapter_t *adapter, return status; } +void hdd_softap_notify_dhcp_ind(void *context, struct sk_buff *netbuf) +{ + hdd_ap_ctx_t *hdd_ap_ctx; + struct qdf_mac_addr *dest_mac_addr; + uint8_t sta_id; + + hdd_adapter_t *adapter = context; + + if (!adapter) { + hdd_err("NULL adapter"); + return; + } + + hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter); + if (!hdd_ap_ctx) { + hdd_err("HDD sap context is NULL"); + return; + } + + dest_mac_addr = (struct qdf_mac_addr *)netbuf->data; + + if (QDF_NBUF_CB_GET_IS_BCAST(netbuf) || + QDF_NBUF_CB_GET_IS_MCAST(netbuf)) { + /* The BC/MC station ID is assigned during BSS + * starting phase. SAP will return the station ID + * used for BC/MC traffic. + */ + sta_id = hdd_ap_ctx->uBCStaId; + } else { + if (QDF_STATUS_SUCCESS != + hdd_softap_get_sta_id(adapter, + dest_mac_addr, &sta_id)) { + QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, + QDF_TRACE_LEVEL_INFO_HIGH, + "%s: Failed to find right station", __func__); + return; + } + } + hdd_post_dhcp_ind(adapter, sta_id, WMA_DHCP_STOP_IND); +} + /** * hdd_dhcp_indication() - Send DHCP START/STOP indication to FW * @adapter: pointer to hdd adapter @@ -292,19 +333,22 @@ QDF_STATUS hdd_post_dhcp_ind(hdd_adapter_t *adapter, * @skb: pointer to OS packet (sk_buff) * @dir: direction * - * Return: None + * Return: true if tx completion to be notified for skb */ -void hdd_dhcp_indication(hdd_adapter_t *adapter, - uint8_t sta_id, - struct sk_buff *skb, - enum qdf_proto_dir dir) +bool hdd_dhcp_indication(hdd_adapter_t *adapter, + uint8_t sta_id, + struct sk_buff *skb, + enum qdf_proto_dir dir) { enum qdf_proto_subtype subtype = QDF_PROTO_INVALID; hdd_station_info_t *hdd_sta_info; + bool notify_tx_comp = false; + hdd_debug("adapter=%p, sta_id=%d, dir=%d", adapter, sta_id, dir); - if ((adapter->device_mode == QDF_SAP_MODE) && + if (((adapter->device_mode == QDF_SAP_MODE) || + (adapter->device_mode == QDF_P2P_GO_MODE)) && ((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_DHCP == QDF_NBUF_CB_GET_PACKET_TYPE(skb)) || (dir == QDF_RX && qdf_nbuf_is_ipv4_dhcp_pkt(skb) == true))) { @@ -346,8 +390,7 @@ void hdd_dhcp_indication(hdd_adapter_t *adapter, hdd_sta_info->dhcp_phase = DHCP_PHASE_ACK; if ((hdd_sta_info->dhcp_nego_status == DHCP_NEGO_IN_PROGRESS)) - hdd_post_dhcp_ind(adapter, sta_id, - WMA_DHCP_STOP_IND); + notify_tx_comp = true; hdd_sta_info->dhcp_nego_status = DHCP_NEGO_STOP; break; default: @@ -358,6 +401,7 @@ void hdd_dhcp_indication(hdd_adapter_t *adapter, hdd_sta_info->dhcp_phase, hdd_sta_info->dhcp_nego_status); } + return notify_tx_comp; } /** @@ -382,6 +426,7 @@ static netdev_tx_t __hdd_softap_hard_start_xmit(struct sk_buff *skb, struct qdf_mac_addr *pDestMacAddress; uint8_t STAId; uint32_t num_seg; + bool notify_tx_comp = false; ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled; pAdapter->hdd_stats.hddTxRxStats.cont_txtimeout_cnt = 0; @@ -523,7 +568,8 @@ static netdev_tx_t __hdd_softap_hard_start_xmit(struct sk_buff *skb, pAdapter->aStaInfo[STAId].last_tx_rx_ts = qdf_system_ticks(); if (STAId != pHddApCtx->uBCStaId) - hdd_dhcp_indication(pAdapter, STAId, skb, QDF_TX); + notify_tx_comp = hdd_dhcp_indication(pAdapter, + STAId, skb, QDF_TX); hdd_event_eapol_log(skb, QDF_TX); QDF_NBUF_CB_TX_PACKET_TRACK(skb) = QDF_NBUF_TX_PKT_DATA_TRACK; @@ -544,7 +590,7 @@ static netdev_tx_t __hdd_softap_hard_start_xmit(struct sk_buff *skb, } if (pAdapter->tx_fn(ol_txrx_get_vdev_by_sta_id(STAId), - (qdf_nbuf_t) skb) != NULL) { + (qdf_nbuf_t)skb, notify_tx_comp) != NULL) { QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO_HIGH, "%s: Failed to send packet to txrx for staid:%d", __func__, STAId); @@ -768,6 +814,28 @@ QDF_STATUS hdd_softap_deinit_tx_rx_sta(hdd_adapter_t *pAdapter, uint8_t STAId) } /** + * hdd_softap_notify_tx_compl_cbk() - callback to notify tx completion + * @skb: pointer to skb data + * @adapter: pointer to vdev apdapter + * + * Return: None + */ +void hdd_softap_notify_tx_compl_cbk(struct sk_buff *skb, + void *context) +{ + int errno; + hdd_adapter_t *adapter = NULL; + + adapter = (hdd_adapter_t *)context; + errno = hdd_validate_adapter(adapter); + if (errno) + return; + + if (QDF_NBUF_CB_PACKET_TYPE_DHCP == QDF_NBUF_CB_GET_PACKET_TYPE(skb)) + hdd_softap_notify_dhcp_ind(context, skb); +} + +/** * hdd_softap_rx_packet_cbk() - Receive packet handler * @context: pointer to HDD context * @rxBuf: pointer to rx qdf_nbuf @@ -987,6 +1055,7 @@ QDF_STATUS hdd_softap_register_sta(hdd_adapter_t *pAdapter, /* Register the vdev transmit and receive functions */ qdf_mem_zero(&txrx_ops, sizeof(txrx_ops)); txrx_ops.rx.rx = hdd_softap_rx_packet_cbk; + txrx_ops.tx.tx_comp = hdd_softap_notify_tx_compl_cbk; ol_txrx_vdev_register( ol_txrx_get_vdev_from_vdev_id(pAdapter->sessionId), pAdapter, &txrx_ops); diff --git a/core/hdd/src/wlan_hdd_tx_rx.c b/core/hdd/src/wlan_hdd_tx_rx.c index b07a7aaec412..89c5ac95997e 100644 --- a/core/hdd/src/wlan_hdd_tx_rx.c +++ b/core/hdd/src/wlan_hdd_tx_rx.c @@ -1071,7 +1071,7 @@ static netdev_tx_t __hdd_hard_start_xmit(struct sk_buff *skb, } if (pAdapter->tx_fn(ol_txrx_get_vdev_by_sta_id(STAId), - (qdf_nbuf_t) skb) != NULL) { + (qdf_nbuf_t)skb, 0) != NULL) { QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_INFO_HIGH, "%s: Failed to send packet to txrx for staid: %d", __func__, STAId); |
