blob: 189f5456fe7357dd136b8f02d3240da1d04922d0 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Yun Parkf2e213b2018-01-09 14:38:45 -08002 * Copyright (c) 2015-2018 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all
7 * copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
17 */
18
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019/**
20 * DOC: wlan_hdd_lro.c
21 *
22 * WLAN HDD LRO interface implementation
23 */
24
25#include <wlan_hdd_includes.h>
Anurag Chouhan6d760662016-02-20 16:05:43 +053026#include <qdf_types.h>
Dhanashri Atre170855e2016-12-15 13:26:54 -080027#include <qdf_lro.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080028#include <wlan_hdd_lro.h>
29#include <wlan_hdd_napi.h>
30#include <wma_api.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080031
32#include <linux/inet_lro.h>
33#include <linux/list.h>
34#include <linux/random.h>
35#include <net/tcp.h>
36
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080037#define LRO_VALID_FIELDS \
38 (LRO_DESC | LRO_ELIGIBILITY_CHECKED | LRO_TCP_ACK_NUM | \
39 LRO_TCP_DATA_CSUM | LRO_TCP_SEQ_NUM | LRO_TCP_WIN)
40
psimha884025c2017-08-01 15:07:32 -070041#if defined(QCA_WIFI_QCA6290)
Dhanashri Atre1a6a4ce2017-05-03 19:40:33 -070042static qdf_lro_ctx_t wlan_hdd_get_lro_ctx(struct sk_buff *skb)
Dhanashri Atre170855e2016-12-15 13:26:54 -080043{
Dhanashri Atre1a6a4ce2017-05-03 19:40:33 -070044 return (qdf_lro_ctx_t)QDF_NBUF_CB_RX_LRO_CTX(skb);
Dhanashri Atre170855e2016-12-15 13:26:54 -080045}
Dhanashri Atre170855e2016-12-15 13:26:54 -080046#else
Dhanashri Atre1a6a4ce2017-05-03 19:40:33 -070047static qdf_lro_ctx_t wlan_hdd_get_lro_ctx(struct sk_buff *skb)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080048{
Dhanashri Atre1a6a4ce2017-05-03 19:40:33 -070049 struct hif_opaque_softc *hif_hdl =
50 (struct hif_opaque_softc *)cds_get_context(QDF_MODULE_ID_HIF);
51 if (hif_hdl == NULL) {
52 hdd_err("hif_hdl is NULL");
Yun Parkf2e213b2018-01-09 14:38:45 -080053 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080054 }
55
Dhanashri Atre1a6a4ce2017-05-03 19:40:33 -070056 return hif_get_lro_info(QDF_NBUF_CB_RX_CTX_ID(skb), hif_hdl);
Manjunathappa Prakash04f26442016-10-13 14:46:49 -070057}
Dhanashri Atre1a6a4ce2017-05-03 19:40:33 -070058#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080059
60/**
61 * hdd_lro_rx() - LRO receive function
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080062 * @adapter: HDD adapter
63 * @skb: network buffer
64 *
65 * Delivers LRO eligible frames to the LRO manager
66 *
Manjunathappa Prakash7b0ad462018-04-15 00:37:16 -070067 * Return: QDF_STATUS_SUCCESS - frame delivered to LRO manager
68 * QDF_STATUS_E_FAILURE - frame not delivered
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080069 */
Manjunathappa Prakash7b0ad462018-04-15 00:37:16 -070070QDF_STATUS hdd_lro_rx(struct hdd_adapter *adapter, struct sk_buff *skb)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080071{
Dhanashri Atre1a6a4ce2017-05-03 19:40:33 -070072 qdf_lro_ctx_t ctx;
Manjunathappa Prakash7b0ad462018-04-15 00:37:16 -070073 QDF_STATUS status = QDF_STATUS_E_FAILURE;
74 struct qdf_lro_info info;
75 struct net_lro_desc *lro_desc = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080076
Manjunathappa Prakash7b0ad462018-04-15 00:37:16 -070077 if ((adapter->dev->features & NETIF_F_LRO) != NETIF_F_LRO)
78 return QDF_STATUS_E_NOSUPPORT;
Manjunathappa Prakash7b6cb002017-10-09 00:40:24 -070079
Manjunathappa Prakash7b0ad462018-04-15 00:37:16 -070080 ctx = wlan_hdd_get_lro_ctx(skb);
81 if (!ctx) {
82 hdd_err("LRO mgr is NULL");
83 return status;
84 }
Manjunathappa Prakash04f26442016-10-13 14:46:49 -070085
Manjunathappa Prakash7b0ad462018-04-15 00:37:16 -070086 info.iph = skb->data;
87 info.tcph = skb->data + QDF_NBUF_CB_RX_TCP_OFFSET(skb);
88 ctx->lro_mgr->dev = adapter->dev;
89 if (qdf_lro_get_info(ctx, skb, &info, (void **)&lro_desc)) {
90 struct net_lro_info hdd_lro_info;
Manjunathappa Prakash04f26442016-10-13 14:46:49 -070091
Manjunathappa Prakash7b0ad462018-04-15 00:37:16 -070092 hdd_lro_info.valid_fields = LRO_VALID_FIELDS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080093
Manjunathappa Prakash7b0ad462018-04-15 00:37:16 -070094 hdd_lro_info.lro_desc = lro_desc;
95 hdd_lro_info.lro_eligible = 1;
96 hdd_lro_info.tcp_ack_num = QDF_NBUF_CB_RX_TCP_ACK_NUM(skb);
97 hdd_lro_info.tcp_data_csum =
98 csum_unfold(htons(QDF_NBUF_CB_RX_TCP_CHKSUM(skb)));
99 hdd_lro_info.tcp_seq_num = QDF_NBUF_CB_RX_TCP_SEQ_NUM(skb);
100 hdd_lro_info.tcp_win = QDF_NBUF_CB_RX_TCP_WIN(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800101
Manjunathappa Prakash7b0ad462018-04-15 00:37:16 -0700102 lro_receive_skb_ext(ctx->lro_mgr, skb, (void *)adapter,
103 &hdd_lro_info);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800104
Manjunathappa Prakash7b0ad462018-04-15 00:37:16 -0700105 if (!hdd_lro_info.lro_desc->active)
106 qdf_lro_desc_free(ctx, lro_desc);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800107
Manjunathappa Prakash7b0ad462018-04-15 00:37:16 -0700108 status = QDF_STATUS_SUCCESS;
109 } else {
110 qdf_lro_flush_pkt(ctx, &info);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800111 }
112 return status;
113}
Dhanashri Atree7d442a2016-07-14 18:20:29 -0700114
115/**
Dhanashri Atre1a6a4ce2017-05-03 19:40:33 -0700116 * hdd_lro_display_stats() - display LRO statistics
Dhanashri Atree7d442a2016-07-14 18:20:29 -0700117 * @hdd_ctx: hdd context
118 *
119 * Return: none
120 */
Jeff Johnson28c3e622017-08-28 11:54:45 -0700121void hdd_lro_display_stats(struct hdd_context *hdd_ctx)
Dhanashri Atree7d442a2016-07-14 18:20:29 -0700122{
Srinivas Girigowdaf91ec572017-03-06 17:20:19 -0800123 hdd_debug("LRO stats is broken, will fix it");
Dhanashri Atree7d442a2016-07-14 18:20:29 -0700124}
Manjunathappa Prakash7b6cb002017-10-09 00:40:24 -0700125
Poddar, Siddarth4b3f7312017-11-02 17:00:20 +0530126QDF_STATUS
127hdd_lro_set_reset(struct hdd_context *hdd_ctx, struct hdd_adapter *adapter,
128 uint8_t enable_flag)
129{
Manjunathappa Prakash7b0ad462018-04-15 00:37:16 -0700130 if ((hdd_ctx->ol_enable != CFG_LRO_ENABLED) ||
131 (adapter->device_mode != QDF_STA_MODE)) {
Poddar, Siddarth4b3f7312017-11-02 17:00:20 +0530132 hdd_debug("LRO is already Disabled");
133 return 0;
134 }
135
136 if (enable_flag) {
137 qdf_atomic_set(&hdd_ctx->vendor_disable_lro_flag, 0);
138 adapter->dev->features |= NETIF_F_LRO;
139 } else {
140 /* Disable LRO, Enable tcpdelack*/
141 qdf_atomic_set(&hdd_ctx->vendor_disable_lro_flag, 1);
142 adapter->dev->features &= ~NETIF_F_LRO;
143 hdd_debug("LRO Disabled");
144
145 if (hdd_ctx->en_tcp_delack_no_lro) {
146 struct wlan_rx_tp_data rx_tp_data;
147
148 hdd_debug("Enable TCP delack as LRO is disabled");
149 rx_tp_data.rx_tp_flags = TCP_DEL_ACK_IND;
Lin Bai556a1922017-11-10 20:32:04 +0800150 rx_tp_data.level = GET_CUR_RX_LVL(hdd_ctx);
Poddar, Siddarth4b3f7312017-11-02 17:00:20 +0530151 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
152 WLAN_SVC_WLAN_TP_IND,
153 &rx_tp_data,
154 sizeof(rx_tp_data));
155 hdd_ctx->en_tcp_delack_no_lro = 1;
156 }
157 }
158 return 0;
159}
160
Manjunathappa Prakash7b6cb002017-10-09 00:40:24 -0700161