xref: /linux/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c (revision 79790b6818e96c58fe2bffee1b418c16e64e7b80)
1004b26b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2577ae39dSJitendra Kalsaria /*
3577ae39dSJitendra Kalsaria  * QLogic qlcnic NIC Driver
4577ae39dSJitendra Kalsaria  * Copyright (c) 2009-2013 QLogic Corporation
5577ae39dSJitendra Kalsaria  */
6577ae39dSJitendra Kalsaria 
7c70001a9SSony Chacko #include <linux/netdevice.h>
8c70001a9SSony Chacko #include <linux/if_vlan.h>
9c70001a9SSony Chacko #include <net/ip.h>
10c70001a9SSony Chacko #include <linux/ipv6.h>
111bcac3b0SLi RongQing #include <net/checksum.h>
123620af0eSJoe Perches #include <linux/printk.h>
133b6cab7bSWang Qing #include <linux/jiffies.h>
14c70001a9SSony Chacko 
15c70001a9SSony Chacko #include "qlcnic.h"
16c70001a9SSony Chacko 
17381709deSShahed Shaikh #define QLCNIC_TX_ETHER_PKT		0x01
18381709deSShahed Shaikh #define QLCNIC_TX_TCP_PKT		0x02
19381709deSShahed Shaikh #define QLCNIC_TX_UDP_PKT		0x03
20381709deSShahed Shaikh #define QLCNIC_TX_IP_PKT		0x04
21381709deSShahed Shaikh #define QLCNIC_TX_TCP_LSO		0x05
22381709deSShahed Shaikh #define QLCNIC_TX_TCP_LSO6		0x06
23381709deSShahed Shaikh #define QLCNIC_TX_ENCAP_PKT		0x07
24381709deSShahed Shaikh #define QLCNIC_TX_ENCAP_LSO		0x08
25381709deSShahed Shaikh #define QLCNIC_TX_TCPV6_PKT		0x0b
26381709deSShahed Shaikh #define QLCNIC_TX_UDPV6_PKT		0x0c
27381709deSShahed Shaikh 
28381709deSShahed Shaikh #define QLCNIC_FLAGS_VLAN_TAGGED	0x10
29381709deSShahed Shaikh #define QLCNIC_FLAGS_VLAN_OOB		0x40
30c70001a9SSony Chacko 
31c70001a9SSony Chacko #define qlcnic_set_tx_vlan_tci(cmd_desc, v)	\
32c70001a9SSony Chacko 	(cmd_desc)->vlan_TCI = cpu_to_le16(v);
33c70001a9SSony Chacko #define qlcnic_set_cmd_desc_port(cmd_desc, var)	\
34c70001a9SSony Chacko 	((cmd_desc)->port_ctxid |= ((var) & 0x0F))
35c70001a9SSony Chacko #define qlcnic_set_cmd_desc_ctxid(cmd_desc, var)	\
36c70001a9SSony Chacko 	((cmd_desc)->port_ctxid |= ((var) << 4 & 0xF0))
37c70001a9SSony Chacko 
38c70001a9SSony Chacko #define qlcnic_set_tx_port(_desc, _port) \
39c70001a9SSony Chacko 	((_desc)->port_ctxid = ((_port) & 0xf) | (((_port) << 4) & 0xf0))
40c70001a9SSony Chacko 
41c70001a9SSony Chacko #define qlcnic_set_tx_flags_opcode(_desc, _flags, _opcode) \
42c70001a9SSony Chacko 	((_desc)->flags_opcode |= \
43c70001a9SSony Chacko 	cpu_to_le16(((_flags) & 0x7f) | (((_opcode) & 0x3f) << 7)))
44c70001a9SSony Chacko 
45c70001a9SSony Chacko #define qlcnic_set_tx_frags_len(_desc, _frags, _len) \
46c70001a9SSony Chacko 	((_desc)->nfrags__length = \
47c70001a9SSony Chacko 	cpu_to_le32(((_frags) & 0xff) | (((_len) & 0xffffff) << 8)))
48c70001a9SSony Chacko 
49c70001a9SSony Chacko /* owner bits of status_desc */
50c70001a9SSony Chacko #define STATUS_OWNER_HOST	(0x1ULL << 56)
51c70001a9SSony Chacko #define STATUS_OWNER_PHANTOM	(0x2ULL << 56)
52c70001a9SSony Chacko 
53c70001a9SSony Chacko /* Status descriptor:
54c70001a9SSony Chacko    0-3 port, 4-7 status, 8-11 type, 12-27 total_length
55c70001a9SSony Chacko    28-43 reference_handle, 44-47 protocol, 48-52 pkt_offset
56c70001a9SSony Chacko    53-55 desc_cnt, 56-57 owner, 58-63 opcode
57c70001a9SSony Chacko  */
58c70001a9SSony Chacko #define qlcnic_get_sts_port(sts_data)	\
59c70001a9SSony Chacko 	((sts_data) & 0x0F)
60c70001a9SSony Chacko #define qlcnic_get_sts_status(sts_data)	\
61c70001a9SSony Chacko 	(((sts_data) >> 4) & 0x0F)
62c70001a9SSony Chacko #define qlcnic_get_sts_type(sts_data)	\
63c70001a9SSony Chacko 	(((sts_data) >> 8) & 0x0F)
64c70001a9SSony Chacko #define qlcnic_get_sts_totallength(sts_data)	\
65c70001a9SSony Chacko 	(((sts_data) >> 12) & 0xFFFF)
66c70001a9SSony Chacko #define qlcnic_get_sts_refhandle(sts_data)	\
67c70001a9SSony Chacko 	(((sts_data) >> 28) & 0xFFFF)
68c70001a9SSony Chacko #define qlcnic_get_sts_prot(sts_data)	\
69c70001a9SSony Chacko 	(((sts_data) >> 44) & 0x0F)
70c70001a9SSony Chacko #define qlcnic_get_sts_pkt_offset(sts_data)	\
71c70001a9SSony Chacko 	(((sts_data) >> 48) & 0x1F)
72c70001a9SSony Chacko #define qlcnic_get_sts_desc_cnt(sts_data)	\
73c70001a9SSony Chacko 	(((sts_data) >> 53) & 0x7)
74c70001a9SSony Chacko #define qlcnic_get_sts_opcode(sts_data)	\
75c70001a9SSony Chacko 	(((sts_data) >> 58) & 0x03F)
76c70001a9SSony Chacko 
77c70001a9SSony Chacko #define qlcnic_get_lro_sts_refhandle(sts_data) 	\
785796bd04SSony Chacko 	((sts_data) & 0x07FFF)
79c70001a9SSony Chacko #define qlcnic_get_lro_sts_length(sts_data)	\
80c70001a9SSony Chacko 	(((sts_data) >> 16) & 0x0FFFF)
81c70001a9SSony Chacko #define qlcnic_get_lro_sts_l2_hdr_offset(sts_data)	\
82c70001a9SSony Chacko 	(((sts_data) >> 32) & 0x0FF)
83c70001a9SSony Chacko #define qlcnic_get_lro_sts_l4_hdr_offset(sts_data)	\
84c70001a9SSony Chacko 	(((sts_data) >> 40) & 0x0FF)
85c70001a9SSony Chacko #define qlcnic_get_lro_sts_timestamp(sts_data)	\
86c70001a9SSony Chacko 	(((sts_data) >> 48) & 0x1)
87c70001a9SSony Chacko #define qlcnic_get_lro_sts_type(sts_data)	\
88c70001a9SSony Chacko 	(((sts_data) >> 49) & 0x7)
89c70001a9SSony Chacko #define qlcnic_get_lro_sts_push_flag(sts_data)		\
90c70001a9SSony Chacko 	(((sts_data) >> 52) & 0x1)
91c70001a9SSony Chacko #define qlcnic_get_lro_sts_seq_number(sts_data)		\
92c70001a9SSony Chacko 	((sts_data) & 0x0FFFFFFFF)
93c70001a9SSony Chacko #define qlcnic_get_lro_sts_mss(sts_data1)		\
94c70001a9SSony Chacko 	((sts_data1 >> 32) & 0x0FFFF)
95c70001a9SSony Chacko 
9699e85879SShahed Shaikh #define qlcnic_83xx_get_lro_sts_mss(sts) ((sts) & 0xffff)
9799e85879SShahed Shaikh 
98c70001a9SSony Chacko /* opcode field in status_desc */
99c70001a9SSony Chacko #define QLCNIC_SYN_OFFLOAD	0x03
100c70001a9SSony Chacko #define QLCNIC_RXPKT_DESC  	0x04
101c70001a9SSony Chacko #define QLCNIC_OLD_RXPKT_DESC	0x3f
102c70001a9SSony Chacko #define QLCNIC_RESPONSE_DESC	0x05
103c70001a9SSony Chacko #define QLCNIC_LRO_DESC  	0x12
104c70001a9SSony Chacko 
1054be41e92SSony Chacko #define QLCNIC_TCP_HDR_SIZE		20
1064be41e92SSony Chacko #define QLCNIC_TCP_TS_OPTION_SIZE	12
1074be41e92SSony Chacko #define QLCNIC_FETCH_RING_ID(handle)	((handle) >> 63)
1084be41e92SSony Chacko #define QLCNIC_DESC_OWNER_FW		cpu_to_le64(STATUS_OWNER_PHANTOM)
1094be41e92SSony Chacko 
1104be41e92SSony Chacko #define QLCNIC_TCP_TS_HDR_SIZE (QLCNIC_TCP_HDR_SIZE + QLCNIC_TCP_TS_OPTION_SIZE)
1114be41e92SSony Chacko 
112c70001a9SSony Chacko /* for status field in status_desc */
113c70001a9SSony Chacko #define STATUS_CKSUM_LOOP	0
114c70001a9SSony Chacko #define STATUS_CKSUM_OK		2
115d17dd0d9SSony Chacko 
1164be41e92SSony Chacko #define qlcnic_83xx_pktln(sts)		((sts >> 32) & 0x3FFF)
1174be41e92SSony Chacko #define qlcnic_83xx_hndl(sts)		((sts >> 48) & 0x7FFF)
1184be41e92SSony Chacko #define qlcnic_83xx_csum_status(sts)	((sts >> 39) & 7)
1194be41e92SSony Chacko #define qlcnic_83xx_opcode(sts)	((sts >> 42) & 0xF)
1204be41e92SSony Chacko #define qlcnic_83xx_vlan_tag(sts)	(((sts) >> 48) & 0xFFFF)
1214be41e92SSony Chacko #define qlcnic_83xx_lro_pktln(sts)	(((sts) >> 32) & 0x3FFF)
1224be41e92SSony Chacko #define qlcnic_83xx_l2_hdr_off(sts)	(((sts) >> 16) & 0xFF)
1234be41e92SSony Chacko #define qlcnic_83xx_l4_hdr_off(sts)	(((sts) >> 24) & 0xFF)
1244be41e92SSony Chacko #define qlcnic_83xx_pkt_cnt(sts)	(((sts) >> 16) & 0x7)
1254be41e92SSony Chacko #define qlcnic_83xx_is_tstamp(sts)	(((sts) >> 40) & 1)
1264be41e92SSony Chacko #define qlcnic_83xx_is_psh_bit(sts)	(((sts) >> 41) & 1)
1274be41e92SSony Chacko #define qlcnic_83xx_is_ip_align(sts)	(((sts) >> 46) & 1)
1284be41e92SSony Chacko #define qlcnic_83xx_has_vlan_tag(sts)	(((sts) >> 47) & 1)
1294be41e92SSony Chacko 
13021041400Sstephen hemminger static int qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring,
13121041400Sstephen hemminger 				   int max);
13221041400Sstephen hemminger 
13321041400Sstephen hemminger static struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *,
13421041400Sstephen hemminger 					    struct qlcnic_host_rds_ring *,
13521041400Sstephen hemminger 					    u16, u16);
1364be41e92SSony Chacko 
qlcnic_mac_hash(u64 mac,u16 vlan)137b3f7de83SSucheta Chakraborty static inline u8 qlcnic_mac_hash(u64 mac, u16 vlan)
1384be41e92SSony Chacko {
139b3f7de83SSucheta Chakraborty 	return (u8)((mac & 0xff) ^ ((mac >> 40) & 0xff) ^ (vlan & 0xff));
1404be41e92SSony Chacko }
1414be41e92SSony Chacko 
qlcnic_get_ref_handle(struct qlcnic_adapter * adapter,u16 handle,u8 ring_id)1424be41e92SSony Chacko static inline u32 qlcnic_get_ref_handle(struct qlcnic_adapter *adapter,
1434be41e92SSony Chacko 					u16 handle, u8 ring_id)
1444be41e92SSony Chacko {
14515ca140fSManish Chopra 	if (qlcnic_83xx_check(adapter))
1464be41e92SSony Chacko 		return handle | (ring_id << 15);
1474be41e92SSony Chacko 	else
1484be41e92SSony Chacko 		return handle;
1494be41e92SSony Chacko }
1504be41e92SSony Chacko 
qlcnic_82xx_is_lb_pkt(u64 sts_data)15153643a75SShahed Shaikh static inline int qlcnic_82xx_is_lb_pkt(u64 sts_data)
15253643a75SShahed Shaikh {
15353643a75SShahed Shaikh 	return (qlcnic_get_sts_status(sts_data) == STATUS_CKSUM_LOOP) ? 1 : 0;
15453643a75SShahed Shaikh }
15553643a75SShahed Shaikh 
qlcnic_delete_rx_list_mac(struct qlcnic_adapter * adapter,struct qlcnic_filter * fil,void * addr,u16 vlan_id)156e0d138d9SShahed Shaikh static void qlcnic_delete_rx_list_mac(struct qlcnic_adapter *adapter,
157e0d138d9SShahed Shaikh 				      struct qlcnic_filter *fil,
158e0d138d9SShahed Shaikh 				      void *addr, u16 vlan_id)
159e0d138d9SShahed Shaikh {
160e0d138d9SShahed Shaikh 	int ret;
161e0d138d9SShahed Shaikh 	u8 op;
162e0d138d9SShahed Shaikh 
163e0d138d9SShahed Shaikh 	op = vlan_id ? QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_ADD;
164e0d138d9SShahed Shaikh 	ret = qlcnic_sre_macaddr_change(adapter, addr, vlan_id, op);
165e0d138d9SShahed Shaikh 	if (ret)
166e0d138d9SShahed Shaikh 		return;
167e0d138d9SShahed Shaikh 
168e0d138d9SShahed Shaikh 	op = vlan_id ? QLCNIC_MAC_VLAN_DEL : QLCNIC_MAC_DEL;
169e0d138d9SShahed Shaikh 	ret = qlcnic_sre_macaddr_change(adapter, addr, vlan_id, op);
170e0d138d9SShahed Shaikh 	if (!ret) {
171e0d138d9SShahed Shaikh 		hlist_del(&fil->fnode);
172e0d138d9SShahed Shaikh 		adapter->rx_fhash.fnum--;
173e0d138d9SShahed Shaikh 	}
174e0d138d9SShahed Shaikh }
175e0d138d9SShahed Shaikh 
qlcnic_find_mac_filter(struct hlist_head * head,void * addr,u16 vlan_id)176e0d138d9SShahed Shaikh static struct qlcnic_filter *qlcnic_find_mac_filter(struct hlist_head *head,
177e0d138d9SShahed Shaikh 						    void *addr, u16 vlan_id)
178e0d138d9SShahed Shaikh {
179e0d138d9SShahed Shaikh 	struct qlcnic_filter *tmp_fil = NULL;
180e0d138d9SShahed Shaikh 	struct hlist_node *n;
181e0d138d9SShahed Shaikh 
182e0d138d9SShahed Shaikh 	hlist_for_each_entry_safe(tmp_fil, n, head, fnode) {
1836878f79aSdingtianhong 		if (ether_addr_equal(tmp_fil->faddr, addr) &&
184e0d138d9SShahed Shaikh 		    tmp_fil->vlan_id == vlan_id)
185e0d138d9SShahed Shaikh 			return tmp_fil;
186e0d138d9SShahed Shaikh 	}
187e0d138d9SShahed Shaikh 
188e0d138d9SShahed Shaikh 	return NULL;
189e0d138d9SShahed Shaikh }
190e0d138d9SShahed Shaikh 
qlcnic_add_lb_filter(struct qlcnic_adapter * adapter,struct sk_buff * skb,int loopback_pkt,u16 vlan_id)19121041400Sstephen hemminger static void qlcnic_add_lb_filter(struct qlcnic_adapter *adapter,
19221041400Sstephen hemminger 				 struct sk_buff *skb, int loopback_pkt, u16 vlan_id)
19353643a75SShahed Shaikh {
19453643a75SShahed Shaikh 	struct ethhdr *phdr = (struct ethhdr *)(skb->data);
19553643a75SShahed Shaikh 	struct qlcnic_filter *fil, *tmp_fil;
19653643a75SShahed Shaikh 	struct hlist_head *head;
19753643a75SShahed Shaikh 	unsigned long time;
19853643a75SShahed Shaikh 	u64 src_addr = 0;
199e0d138d9SShahed Shaikh 	u8 hindex, op;
20053643a75SShahed Shaikh 	int ret;
20153643a75SShahed Shaikh 
202b3f7de83SSucheta Chakraborty 	if (!qlcnic_sriov_pf_check(adapter) || (vlan_id == 0xffff))
203b3f7de83SSucheta Chakraborty 		vlan_id = 0;
204b3f7de83SSucheta Chakraborty 
20553643a75SShahed Shaikh 	memcpy(&src_addr, phdr->h_source, ETH_ALEN);
206b3f7de83SSucheta Chakraborty 	hindex = qlcnic_mac_hash(src_addr, vlan_id) &
207e0d138d9SShahed Shaikh 		 (adapter->fhash.fbucket_size - 1);
20853643a75SShahed Shaikh 
20953643a75SShahed Shaikh 	if (loopback_pkt) {
21053643a75SShahed Shaikh 		if (adapter->rx_fhash.fnum >= adapter->rx_fhash.fmax)
21153643a75SShahed Shaikh 			return;
21253643a75SShahed Shaikh 
21353643a75SShahed Shaikh 		head = &(adapter->rx_fhash.fhead[hindex]);
21453643a75SShahed Shaikh 
215e0d138d9SShahed Shaikh 		tmp_fil = qlcnic_find_mac_filter(head, &src_addr, vlan_id);
216e0d138d9SShahed Shaikh 		if (tmp_fil) {
21753643a75SShahed Shaikh 			time = tmp_fil->ftime;
218e0d138d9SShahed Shaikh 			if (time_after(jiffies, QLCNIC_READD_AGE * HZ + time))
21953643a75SShahed Shaikh 				tmp_fil->ftime = jiffies;
22053643a75SShahed Shaikh 			return;
22153643a75SShahed Shaikh 		}
22253643a75SShahed Shaikh 
22353643a75SShahed Shaikh 		fil = kzalloc(sizeof(struct qlcnic_filter), GFP_ATOMIC);
22453643a75SShahed Shaikh 		if (!fil)
22553643a75SShahed Shaikh 			return;
22653643a75SShahed Shaikh 
22753643a75SShahed Shaikh 		fil->ftime = jiffies;
22853643a75SShahed Shaikh 		memcpy(fil->faddr, &src_addr, ETH_ALEN);
22953643a75SShahed Shaikh 		fil->vlan_id = vlan_id;
23053643a75SShahed Shaikh 		spin_lock(&adapter->rx_mac_learn_lock);
23153643a75SShahed Shaikh 		hlist_add_head(&(fil->fnode), head);
23253643a75SShahed Shaikh 		adapter->rx_fhash.fnum++;
23353643a75SShahed Shaikh 		spin_unlock(&adapter->rx_mac_learn_lock);
23453643a75SShahed Shaikh 	} else {
235e0d138d9SShahed Shaikh 		head = &adapter->fhash.fhead[hindex];
23653643a75SShahed Shaikh 
237e0d138d9SShahed Shaikh 		spin_lock(&adapter->mac_learn_lock);
23853643a75SShahed Shaikh 
239e0d138d9SShahed Shaikh 		tmp_fil = qlcnic_find_mac_filter(head, &src_addr, vlan_id);
240e0d138d9SShahed Shaikh 		if (tmp_fil) {
24153643a75SShahed Shaikh 			op = vlan_id ? QLCNIC_MAC_VLAN_DEL : QLCNIC_MAC_DEL;
24253643a75SShahed Shaikh 			ret = qlcnic_sre_macaddr_change(adapter,
24353643a75SShahed Shaikh 							(u8 *)&src_addr,
24453643a75SShahed Shaikh 							vlan_id, op);
24553643a75SShahed Shaikh 			if (!ret) {
246e0d138d9SShahed Shaikh 				hlist_del(&tmp_fil->fnode);
247e0d138d9SShahed Shaikh 				adapter->fhash.fnum--;
24853643a75SShahed Shaikh 			}
249e0d138d9SShahed Shaikh 
250e0d138d9SShahed Shaikh 			spin_unlock(&adapter->mac_learn_lock);
251e0d138d9SShahed Shaikh 
252e0d138d9SShahed Shaikh 			return;
25353643a75SShahed Shaikh 		}
254e0d138d9SShahed Shaikh 
255e0d138d9SShahed Shaikh 		spin_unlock(&adapter->mac_learn_lock);
256e0d138d9SShahed Shaikh 
257e0d138d9SShahed Shaikh 		head = &adapter->rx_fhash.fhead[hindex];
258e0d138d9SShahed Shaikh 
259e0d138d9SShahed Shaikh 		spin_lock(&adapter->rx_mac_learn_lock);
260e0d138d9SShahed Shaikh 
261e0d138d9SShahed Shaikh 		tmp_fil = qlcnic_find_mac_filter(head, &src_addr, vlan_id);
262e0d138d9SShahed Shaikh 		if (tmp_fil)
263e0d138d9SShahed Shaikh 			qlcnic_delete_rx_list_mac(adapter, tmp_fil, &src_addr,
264e0d138d9SShahed Shaikh 						  vlan_id);
265e0d138d9SShahed Shaikh 
26653643a75SShahed Shaikh 		spin_unlock(&adapter->rx_mac_learn_lock);
26753643a75SShahed Shaikh 	}
26853643a75SShahed Shaikh }
26953643a75SShahed Shaikh 
qlcnic_82xx_change_filter(struct qlcnic_adapter * adapter,u64 * uaddr,u16 vlan_id,struct qlcnic_host_tx_ring * tx_ring)2707e2cf4feSSony Chacko void qlcnic_82xx_change_filter(struct qlcnic_adapter *adapter, u64 *uaddr,
271c333fa0cSShahed Shaikh 			       u16 vlan_id, struct qlcnic_host_tx_ring *tx_ring)
272c70001a9SSony Chacko {
273c70001a9SSony Chacko 	struct cmd_desc_type0 *hwdesc;
274c70001a9SSony Chacko 	struct qlcnic_nic_req *req;
275c70001a9SSony Chacko 	struct qlcnic_mac_req *mac_req;
276c70001a9SSony Chacko 	struct qlcnic_vlan_req *vlan_req;
277c70001a9SSony Chacko 	u32 producer;
278c70001a9SSony Chacko 	u64 word;
279c70001a9SSony Chacko 
280c70001a9SSony Chacko 	producer = tx_ring->producer;
281c70001a9SSony Chacko 	hwdesc = &tx_ring->desc_head[tx_ring->producer];
282c70001a9SSony Chacko 
283c70001a9SSony Chacko 	req = (struct qlcnic_nic_req *)hwdesc;
284c70001a9SSony Chacko 	memset(req, 0, sizeof(struct qlcnic_nic_req));
285c70001a9SSony Chacko 	req->qhdr = cpu_to_le64(QLCNIC_REQUEST << 23);
286c70001a9SSony Chacko 
287c70001a9SSony Chacko 	word = QLCNIC_MAC_EVENT | ((u64)(adapter->portnum) << 16);
288c70001a9SSony Chacko 	req->req_hdr = cpu_to_le64(word);
289c70001a9SSony Chacko 
290c70001a9SSony Chacko 	mac_req = (struct qlcnic_mac_req *)&(req->words[0]);
291c70001a9SSony Chacko 	mac_req->op = vlan_id ? QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_ADD;
2924a99ab56SShahed Shaikh 	memcpy(mac_req->mac_addr, uaddr, ETH_ALEN);
293c70001a9SSony Chacko 
294c70001a9SSony Chacko 	vlan_req = (struct qlcnic_vlan_req *)&req->words[1];
295f80bc8feSRajesh Borundia 	vlan_req->vlan_id = cpu_to_le16(vlan_id);
296c70001a9SSony Chacko 
297c70001a9SSony Chacko 	tx_ring->producer = get_next_index(producer, tx_ring->num_desc);
298c70001a9SSony Chacko 	smp_mb();
299c70001a9SSony Chacko }
300c70001a9SSony Chacko 
qlcnic_send_filter(struct qlcnic_adapter * adapter,struct cmd_desc_type0 * first_desc,struct sk_buff * skb,struct qlcnic_host_tx_ring * tx_ring)301d17dd0d9SSony Chacko static void qlcnic_send_filter(struct qlcnic_adapter *adapter,
302c70001a9SSony Chacko 			       struct cmd_desc_type0 *first_desc,
303c333fa0cSShahed Shaikh 			       struct sk_buff *skb,
304c333fa0cSShahed Shaikh 			       struct qlcnic_host_tx_ring *tx_ring)
305c70001a9SSony Chacko {
306b3f7de83SSucheta Chakraborty 	struct vlan_ethhdr *vh = (struct vlan_ethhdr *)(skb->data);
3077e2cf4feSSony Chacko 	struct ethhdr *phdr = (struct ethhdr *)(skb->data);
308b3f7de83SSucheta Chakraborty 	u16 protocol = ntohs(skb->protocol);
309b3f7de83SSucheta Chakraborty 	struct qlcnic_filter *fil, *tmp_fil;
310b3f7de83SSucheta Chakraborty 	struct hlist_head *head;
311b3f7de83SSucheta Chakraborty 	struct hlist_node *n;
312c70001a9SSony Chacko 	u64 src_addr = 0;
313f80bc8feSRajesh Borundia 	u16 vlan_id = 0;
314b3f7de83SSucheta Chakraborty 	u8 hindex, hval;
315c70001a9SSony Chacko 
3164be41e92SSony Chacko 	if (ether_addr_equal(phdr->h_source, adapter->mac_addr))
317c70001a9SSony Chacko 		return;
318d747c333SRajesh Borundia 
319d747c333SRajesh Borundia 	if (adapter->flags & QLCNIC_VLAN_FILTERING) {
320b3f7de83SSucheta Chakraborty 		if (protocol == ETH_P_8021Q) {
3211f5020acSVladimir Oltean 			vh = skb_vlan_eth_hdr(skb);
322b3f7de83SSucheta Chakraborty 			vlan_id = ntohs(vh->h_vlan_TCI);
323df8a39deSJiri Pirko 		} else if (skb_vlan_tag_present(skb)) {
324df8a39deSJiri Pirko 			vlan_id = skb_vlan_tag_get(skb);
325b3f7de83SSucheta Chakraborty 		}
326b3f7de83SSucheta Chakraborty 	}
327c70001a9SSony Chacko 
328c70001a9SSony Chacko 	memcpy(&src_addr, phdr->h_source, ETH_ALEN);
329b3f7de83SSucheta Chakraborty 	hval = qlcnic_mac_hash(src_addr, vlan_id);
330b3f7de83SSucheta Chakraborty 	hindex = hval & (adapter->fhash.fbucket_size - 1);
331c70001a9SSony Chacko 	head = &(adapter->fhash.fhead[hindex]);
332c70001a9SSony Chacko 
333b67bfe0dSSasha Levin 	hlist_for_each_entry_safe(tmp_fil, n, head, fnode) {
334e2072cdfSdingtianhong 		if (ether_addr_equal(tmp_fil->faddr, (u8 *)&src_addr) &&
335c70001a9SSony Chacko 		    tmp_fil->vlan_id == vlan_id) {
3363b6cab7bSWang Qing 			if (time_is_before_jiffies(QLCNIC_READD_AGE * HZ + tmp_fil->ftime))
3377e2cf4feSSony Chacko 				qlcnic_change_filter(adapter, &src_addr,
338c333fa0cSShahed Shaikh 						     vlan_id, tx_ring);
339c70001a9SSony Chacko 			tmp_fil->ftime = jiffies;
340c70001a9SSony Chacko 			return;
341c70001a9SSony Chacko 		}
342c70001a9SSony Chacko 	}
343c70001a9SSony Chacko 
344ddfbac07SShahed Shaikh 	if (unlikely(adapter->fhash.fnum >= adapter->fhash.fmax)) {
345ddfbac07SShahed Shaikh 		adapter->stats.mac_filter_limit_overrun++;
346ddfbac07SShahed Shaikh 		return;
347ddfbac07SShahed Shaikh 	}
348ddfbac07SShahed Shaikh 
349c70001a9SSony Chacko 	fil = kzalloc(sizeof(struct qlcnic_filter), GFP_ATOMIC);
350c70001a9SSony Chacko 	if (!fil)
351c70001a9SSony Chacko 		return;
352c70001a9SSony Chacko 
353c333fa0cSShahed Shaikh 	qlcnic_change_filter(adapter, &src_addr, vlan_id, tx_ring);
354c70001a9SSony Chacko 	fil->ftime = jiffies;
355c70001a9SSony Chacko 	fil->vlan_id = vlan_id;
356c70001a9SSony Chacko 	memcpy(fil->faddr, &src_addr, ETH_ALEN);
357c70001a9SSony Chacko 	spin_lock(&adapter->mac_learn_lock);
358c70001a9SSony Chacko 	hlist_add_head(&(fil->fnode), head);
359c70001a9SSony Chacko 	adapter->fhash.fnum++;
360c70001a9SSony Chacko 	spin_unlock(&adapter->mac_learn_lock);
361c70001a9SSony Chacko }
362c70001a9SSony Chacko 
363381709deSShahed Shaikh #define QLCNIC_ENCAP_VXLAN_PKT		BIT_0
364381709deSShahed Shaikh #define QLCNIC_ENCAP_OUTER_L3_IP6	BIT_1
365381709deSShahed Shaikh #define QLCNIC_ENCAP_INNER_L3_IP6	BIT_2
366381709deSShahed Shaikh #define QLCNIC_ENCAP_INNER_L4_UDP	BIT_3
367381709deSShahed Shaikh #define QLCNIC_ENCAP_DO_L3_CSUM		BIT_4
368381709deSShahed Shaikh #define QLCNIC_ENCAP_DO_L4_CSUM		BIT_5
369381709deSShahed Shaikh 
qlcnic_tx_encap_pkt(struct qlcnic_adapter * adapter,struct cmd_desc_type0 * first_desc,struct sk_buff * skb,struct qlcnic_host_tx_ring * tx_ring)370381709deSShahed Shaikh static int qlcnic_tx_encap_pkt(struct qlcnic_adapter *adapter,
371381709deSShahed Shaikh 			       struct cmd_desc_type0 *first_desc,
372381709deSShahed Shaikh 			       struct sk_buff *skb,
373381709deSShahed Shaikh 			       struct qlcnic_host_tx_ring *tx_ring)
374381709deSShahed Shaikh {
375381709deSShahed Shaikh 	u8 opcode = 0, inner_hdr_len = 0, outer_hdr_len = 0, total_hdr_len = 0;
376381709deSShahed Shaikh 	int copied, copy_len, descr_size;
377381709deSShahed Shaikh 	u32 producer = tx_ring->producer;
378381709deSShahed Shaikh 	struct cmd_desc_type0 *hwdesc;
379381709deSShahed Shaikh 	u16 flags = 0, encap_descr = 0;
380381709deSShahed Shaikh 
381381709deSShahed Shaikh 	opcode = QLCNIC_TX_ETHER_PKT;
382381709deSShahed Shaikh 	encap_descr = QLCNIC_ENCAP_VXLAN_PKT;
383381709deSShahed Shaikh 
384381709deSShahed Shaikh 	if (skb_is_gso(skb)) {
385381709deSShahed Shaikh 		inner_hdr_len = skb_inner_transport_header(skb) +
386381709deSShahed Shaikh 				inner_tcp_hdrlen(skb) -
387381709deSShahed Shaikh 				skb_inner_mac_header(skb);
388381709deSShahed Shaikh 
389381709deSShahed Shaikh 		/* VXLAN header size = 8 */
390381709deSShahed Shaikh 		outer_hdr_len = skb_transport_offset(skb) + 8 +
391381709deSShahed Shaikh 				sizeof(struct udphdr);
392381709deSShahed Shaikh 		first_desc->outer_hdr_length = outer_hdr_len;
393381709deSShahed Shaikh 		total_hdr_len = inner_hdr_len + outer_hdr_len;
394381709deSShahed Shaikh 		encap_descr |= QLCNIC_ENCAP_DO_L3_CSUM |
395381709deSShahed Shaikh 			       QLCNIC_ENCAP_DO_L4_CSUM;
396381709deSShahed Shaikh 		first_desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
397381709deSShahed Shaikh 		first_desc->hdr_length = inner_hdr_len;
398381709deSShahed Shaikh 
399381709deSShahed Shaikh 		/* Copy inner and outer headers in Tx descriptor(s)
400381709deSShahed Shaikh 		 * If total_hdr_len > cmd_desc_type0, use multiple
401381709deSShahed Shaikh 		 * descriptors
402381709deSShahed Shaikh 		 */
403381709deSShahed Shaikh 		copied = 0;
404381709deSShahed Shaikh 		descr_size = (int)sizeof(struct cmd_desc_type0);
405381709deSShahed Shaikh 		while (copied < total_hdr_len) {
406381709deSShahed Shaikh 			copy_len = min(descr_size, (total_hdr_len - copied));
407381709deSShahed Shaikh 			hwdesc = &tx_ring->desc_head[producer];
408381709deSShahed Shaikh 			tx_ring->cmd_buf_arr[producer].skb = NULL;
409381709deSShahed Shaikh 			skb_copy_from_linear_data_offset(skb, copied,
410381709deSShahed Shaikh 							 (char *)hwdesc,
411381709deSShahed Shaikh 							 copy_len);
412381709deSShahed Shaikh 			copied += copy_len;
413381709deSShahed Shaikh 			producer = get_next_index(producer, tx_ring->num_desc);
414381709deSShahed Shaikh 		}
415381709deSShahed Shaikh 
416381709deSShahed Shaikh 		tx_ring->producer = producer;
417381709deSShahed Shaikh 
418381709deSShahed Shaikh 		/* Make sure updated tx_ring->producer is visible
419381709deSShahed Shaikh 		 * for qlcnic_tx_avail()
420381709deSShahed Shaikh 		 */
421381709deSShahed Shaikh 		smp_mb();
422381709deSShahed Shaikh 		adapter->stats.encap_lso_frames++;
423381709deSShahed Shaikh 
424381709deSShahed Shaikh 		opcode = QLCNIC_TX_ENCAP_LSO;
425381709deSShahed Shaikh 	} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
426381709deSShahed Shaikh 		if (inner_ip_hdr(skb)->version == 6) {
427381709deSShahed Shaikh 			if (inner_ipv6_hdr(skb)->nexthdr == IPPROTO_UDP)
428381709deSShahed Shaikh 				encap_descr |= QLCNIC_ENCAP_INNER_L4_UDP;
429381709deSShahed Shaikh 		} else {
430381709deSShahed Shaikh 			if (inner_ip_hdr(skb)->protocol == IPPROTO_UDP)
431381709deSShahed Shaikh 				encap_descr |= QLCNIC_ENCAP_INNER_L4_UDP;
432381709deSShahed Shaikh 		}
433381709deSShahed Shaikh 
434381709deSShahed Shaikh 		adapter->stats.encap_tx_csummed++;
435381709deSShahed Shaikh 		opcode = QLCNIC_TX_ENCAP_PKT;
436381709deSShahed Shaikh 	}
437381709deSShahed Shaikh 
438381709deSShahed Shaikh 	/* Prepare first 16 bits of byte offset 16 of Tx descriptor */
439381709deSShahed Shaikh 	if (ip_hdr(skb)->version == 6)
440381709deSShahed Shaikh 		encap_descr |= QLCNIC_ENCAP_OUTER_L3_IP6;
441381709deSShahed Shaikh 
442381709deSShahed Shaikh 	/* outer IP header's size in 32bit words size*/
443381709deSShahed Shaikh 	encap_descr |= (skb_network_header_len(skb) >> 2) << 6;
444381709deSShahed Shaikh 
445381709deSShahed Shaikh 	/* outer IP header offset */
446381709deSShahed Shaikh 	encap_descr |= skb_network_offset(skb) << 10;
447381709deSShahed Shaikh 	first_desc->encap_descr = cpu_to_le16(encap_descr);
448381709deSShahed Shaikh 
449*80bfab79SEric Dumazet 	first_desc->tcp_hdr_offset = skb_inner_transport_offset(skb);
450381709deSShahed Shaikh 	first_desc->ip_hdr_offset = skb_inner_network_offset(skb);
451381709deSShahed Shaikh 
452381709deSShahed Shaikh 	qlcnic_set_tx_flags_opcode(first_desc, flags, opcode);
453381709deSShahed Shaikh 
454381709deSShahed Shaikh 	return 0;
455381709deSShahed Shaikh }
456381709deSShahed Shaikh 
qlcnic_tx_pkt(struct qlcnic_adapter * adapter,struct cmd_desc_type0 * first_desc,struct sk_buff * skb,struct qlcnic_host_tx_ring * tx_ring)457d17dd0d9SSony Chacko static int qlcnic_tx_pkt(struct qlcnic_adapter *adapter,
458012ec812SHimanshu Madhani 			 struct cmd_desc_type0 *first_desc, struct sk_buff *skb,
459012ec812SHimanshu Madhani 			 struct qlcnic_host_tx_ring *tx_ring)
460c70001a9SSony Chacko {
461b25ddb00SMichał Mirosław 	u8 l4proto, opcode = 0, hdr_len = 0, tag_vlan = 0;
462c70001a9SSony Chacko 	u16 flags = 0, vlan_tci = 0;
463d17dd0d9SSony Chacko 	int copied, offset, copy_len, size;
464c70001a9SSony Chacko 	struct cmd_desc_type0 *hwdesc;
465c70001a9SSony Chacko 	struct vlan_ethhdr *vh;
466c70001a9SSony Chacko 	u16 protocol = ntohs(skb->protocol);
467c70001a9SSony Chacko 	u32 producer = tx_ring->producer;
468c70001a9SSony Chacko 
469c70001a9SSony Chacko 	if (protocol == ETH_P_8021Q) {
4701f5020acSVladimir Oltean 		vh = skb_vlan_eth_hdr(skb);
471381709deSShahed Shaikh 		flags = QLCNIC_FLAGS_VLAN_TAGGED;
472c70001a9SSony Chacko 		vlan_tci = ntohs(vh->h_vlan_TCI);
473c70001a9SSony Chacko 		protocol = ntohs(vh->h_vlan_encapsulated_proto);
474b25ddb00SMichał Mirosław 		tag_vlan = 1;
475df8a39deSJiri Pirko 	} else if (skb_vlan_tag_present(skb)) {
476381709deSShahed Shaikh 		flags = QLCNIC_FLAGS_VLAN_OOB;
477df8a39deSJiri Pirko 		vlan_tci = skb_vlan_tag_get(skb);
478b25ddb00SMichał Mirosław 		tag_vlan = 1;
479c70001a9SSony Chacko 	}
48091b7282bSRajesh Borundia 	if (unlikely(adapter->tx_pvid)) {
481b25ddb00SMichał Mirosław 		if (tag_vlan && !(adapter->flags & QLCNIC_TAGGING_ENABLED))
482c70001a9SSony Chacko 			return -EIO;
483b25ddb00SMichał Mirosław 		if (tag_vlan && (adapter->flags & QLCNIC_TAGGING_ENABLED))
484c70001a9SSony Chacko 			goto set_flags;
485c70001a9SSony Chacko 
486381709deSShahed Shaikh 		flags = QLCNIC_FLAGS_VLAN_OOB;
48791b7282bSRajesh Borundia 		vlan_tci = adapter->tx_pvid;
488c70001a9SSony Chacko 	}
489c70001a9SSony Chacko set_flags:
490c70001a9SSony Chacko 	qlcnic_set_tx_vlan_tci(first_desc, vlan_tci);
491c70001a9SSony Chacko 	qlcnic_set_tx_flags_opcode(first_desc, flags, opcode);
492c70001a9SSony Chacko 
493c70001a9SSony Chacko 	if (*(skb->data) & BIT_0) {
494c70001a9SSony Chacko 		flags |= BIT_0;
495c70001a9SSony Chacko 		memcpy(&first_desc->eth_addr, skb->data, ETH_ALEN);
496c70001a9SSony Chacko 	}
497381709deSShahed Shaikh 	opcode = QLCNIC_TX_ETHER_PKT;
4983eead213SSritej Velaga 	if (skb_is_gso(skb)) {
499504148feSEric Dumazet 		hdr_len = skb_tcp_all_headers(skb);
500c70001a9SSony Chacko 		first_desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
501381709deSShahed Shaikh 		first_desc->hdr_length = hdr_len;
502381709deSShahed Shaikh 		opcode = (protocol == ETH_P_IPV6) ? QLCNIC_TX_TCP_LSO6 :
503381709deSShahed Shaikh 						    QLCNIC_TX_TCP_LSO;
504c70001a9SSony Chacko 
505c70001a9SSony Chacko 		/* For LSO, we need to copy the MAC/IP/TCP headers into
506c70001a9SSony Chacko 		* the descriptor ring */
507c70001a9SSony Chacko 		copied = 0;
508c70001a9SSony Chacko 		offset = 2;
509c70001a9SSony Chacko 
510381709deSShahed Shaikh 		if (flags & QLCNIC_FLAGS_VLAN_OOB) {
511381709deSShahed Shaikh 			first_desc->hdr_length += VLAN_HLEN;
512c70001a9SSony Chacko 			first_desc->tcp_hdr_offset = VLAN_HLEN;
513c70001a9SSony Chacko 			first_desc->ip_hdr_offset = VLAN_HLEN;
514d17dd0d9SSony Chacko 
515c70001a9SSony Chacko 			/* Only in case of TSO on vlan device */
516381709deSShahed Shaikh 			flags |= QLCNIC_FLAGS_VLAN_TAGGED;
517c70001a9SSony Chacko 
518c70001a9SSony Chacko 			/* Create a TSO vlan header template for firmware */
519c70001a9SSony Chacko 			hwdesc = &tx_ring->desc_head[producer];
520c70001a9SSony Chacko 			tx_ring->cmd_buf_arr[producer].skb = NULL;
521c70001a9SSony Chacko 
522c70001a9SSony Chacko 			copy_len = min((int)sizeof(struct cmd_desc_type0) -
523c70001a9SSony Chacko 				       offset, hdr_len + VLAN_HLEN);
524c70001a9SSony Chacko 
525c70001a9SSony Chacko 			vh = (struct vlan_ethhdr *)((char *) hwdesc + 2);
526c70001a9SSony Chacko 			skb_copy_from_linear_data(skb, vh, 12);
527c70001a9SSony Chacko 			vh->h_vlan_proto = htons(ETH_P_8021Q);
528c70001a9SSony Chacko 			vh->h_vlan_TCI = htons(vlan_tci);
529c70001a9SSony Chacko 
530c70001a9SSony Chacko 			skb_copy_from_linear_data_offset(skb, 12,
531d17dd0d9SSony Chacko 							 (char *)vh + 16,
532d17dd0d9SSony Chacko 							 copy_len - 16);
533c70001a9SSony Chacko 			copied = copy_len - VLAN_HLEN;
534c70001a9SSony Chacko 			offset = 0;
535c70001a9SSony Chacko 			producer = get_next_index(producer, tx_ring->num_desc);
536c70001a9SSony Chacko 		}
537c70001a9SSony Chacko 
538c70001a9SSony Chacko 		while (copied < hdr_len) {
539d17dd0d9SSony Chacko 			size = (int)sizeof(struct cmd_desc_type0) - offset;
540d17dd0d9SSony Chacko 			copy_len = min(size, (hdr_len - copied));
541c70001a9SSony Chacko 			hwdesc = &tx_ring->desc_head[producer];
542c70001a9SSony Chacko 			tx_ring->cmd_buf_arr[producer].skb = NULL;
543c70001a9SSony Chacko 			skb_copy_from_linear_data_offset(skb, copied,
544d17dd0d9SSony Chacko 							 (char *)hwdesc +
545d17dd0d9SSony Chacko 							 offset, copy_len);
546c70001a9SSony Chacko 			copied += copy_len;
547c70001a9SSony Chacko 			offset = 0;
548c70001a9SSony Chacko 			producer = get_next_index(producer, tx_ring->num_desc);
549c70001a9SSony Chacko 		}
550c70001a9SSony Chacko 
551c70001a9SSony Chacko 		tx_ring->producer = producer;
552c70001a9SSony Chacko 		smp_mb();
553c70001a9SSony Chacko 		adapter->stats.lso_frames++;
554c70001a9SSony Chacko 
555c70001a9SSony Chacko 	} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
556c70001a9SSony Chacko 		if (protocol == ETH_P_IP) {
557c70001a9SSony Chacko 			l4proto = ip_hdr(skb)->protocol;
558c70001a9SSony Chacko 
559c70001a9SSony Chacko 			if (l4proto == IPPROTO_TCP)
560381709deSShahed Shaikh 				opcode = QLCNIC_TX_TCP_PKT;
561c70001a9SSony Chacko 			else if (l4proto == IPPROTO_UDP)
562381709deSShahed Shaikh 				opcode = QLCNIC_TX_UDP_PKT;
563c70001a9SSony Chacko 		} else if (protocol == ETH_P_IPV6) {
564c70001a9SSony Chacko 			l4proto = ipv6_hdr(skb)->nexthdr;
565c70001a9SSony Chacko 
566c70001a9SSony Chacko 			if (l4proto == IPPROTO_TCP)
567381709deSShahed Shaikh 				opcode = QLCNIC_TX_TCPV6_PKT;
568c70001a9SSony Chacko 			else if (l4proto == IPPROTO_UDP)
569381709deSShahed Shaikh 				opcode = QLCNIC_TX_UDPV6_PKT;
570c70001a9SSony Chacko 		}
571c70001a9SSony Chacko 	}
572c70001a9SSony Chacko 	first_desc->tcp_hdr_offset += skb_transport_offset(skb);
573c70001a9SSony Chacko 	first_desc->ip_hdr_offset += skb_network_offset(skb);
574c70001a9SSony Chacko 	qlcnic_set_tx_flags_opcode(first_desc, flags, opcode);
575c70001a9SSony Chacko 
576c70001a9SSony Chacko 	return 0;
577c70001a9SSony Chacko }
578c70001a9SSony Chacko 
qlcnic_map_tx_skb(struct pci_dev * pdev,struct sk_buff * skb,struct qlcnic_cmd_buffer * pbuf)579d17dd0d9SSony Chacko static int qlcnic_map_tx_skb(struct pci_dev *pdev, struct sk_buff *skb,
580d17dd0d9SSony Chacko 			     struct qlcnic_cmd_buffer *pbuf)
581c70001a9SSony Chacko {
582c70001a9SSony Chacko 	struct qlcnic_skb_frag *nf;
583d7840976SMatthew Wilcox (Oracle) 	skb_frag_t *frag;
584c70001a9SSony Chacko 	int i, nr_frags;
585c70001a9SSony Chacko 	dma_addr_t map;
586c70001a9SSony Chacko 
587c70001a9SSony Chacko 	nr_frags = skb_shinfo(skb)->nr_frags;
588c70001a9SSony Chacko 	nf = &pbuf->frag_array[0];
589c70001a9SSony Chacko 
590a14e3904SChristophe JAILLET 	map = dma_map_single(&pdev->dev, skb->data, skb_headlen(skb),
591a14e3904SChristophe JAILLET 			     DMA_TO_DEVICE);
592a14e3904SChristophe JAILLET 	if (dma_mapping_error(&pdev->dev, map))
593c70001a9SSony Chacko 		goto out_err;
594c70001a9SSony Chacko 
595c70001a9SSony Chacko 	nf->dma = map;
596c70001a9SSony Chacko 	nf->length = skb_headlen(skb);
597c70001a9SSony Chacko 
598c70001a9SSony Chacko 	for (i = 0; i < nr_frags; i++) {
599c70001a9SSony Chacko 		frag = &skb_shinfo(skb)->frags[i];
600c70001a9SSony Chacko 		nf = &pbuf->frag_array[i+1];
601c70001a9SSony Chacko 		map = skb_frag_dma_map(&pdev->dev, frag, 0, skb_frag_size(frag),
602c70001a9SSony Chacko 				       DMA_TO_DEVICE);
603c70001a9SSony Chacko 		if (dma_mapping_error(&pdev->dev, map))
604c70001a9SSony Chacko 			goto unwind;
605c70001a9SSony Chacko 
606c70001a9SSony Chacko 		nf->dma = map;
607c70001a9SSony Chacko 		nf->length = skb_frag_size(frag);
608c70001a9SSony Chacko 	}
609c70001a9SSony Chacko 
610c70001a9SSony Chacko 	return 0;
611c70001a9SSony Chacko 
612c70001a9SSony Chacko unwind:
613c70001a9SSony Chacko 	while (--i >= 0) {
614c70001a9SSony Chacko 		nf = &pbuf->frag_array[i+1];
615a14e3904SChristophe JAILLET 		dma_unmap_page(&pdev->dev, nf->dma, nf->length, DMA_TO_DEVICE);
616c70001a9SSony Chacko 	}
617c70001a9SSony Chacko 
618c70001a9SSony Chacko 	nf = &pbuf->frag_array[0];
619a14e3904SChristophe JAILLET 	dma_unmap_single(&pdev->dev, nf->dma, skb_headlen(skb), DMA_TO_DEVICE);
620c70001a9SSony Chacko 
621c70001a9SSony Chacko out_err:
622c70001a9SSony Chacko 	return -ENOMEM;
623c70001a9SSony Chacko }
624c70001a9SSony Chacko 
qlcnic_unmap_buffers(struct pci_dev * pdev,struct sk_buff * skb,struct qlcnic_cmd_buffer * pbuf)625d17dd0d9SSony Chacko static void qlcnic_unmap_buffers(struct pci_dev *pdev, struct sk_buff *skb,
626c70001a9SSony Chacko 				 struct qlcnic_cmd_buffer *pbuf)
627c70001a9SSony Chacko {
628c70001a9SSony Chacko 	struct qlcnic_skb_frag *nf = &pbuf->frag_array[0];
629d17dd0d9SSony Chacko 	int i, nr_frags = skb_shinfo(skb)->nr_frags;
630c70001a9SSony Chacko 
631c70001a9SSony Chacko 	for (i = 0; i < nr_frags; i++) {
632c70001a9SSony Chacko 		nf = &pbuf->frag_array[i+1];
633a14e3904SChristophe JAILLET 		dma_unmap_page(&pdev->dev, nf->dma, nf->length, DMA_TO_DEVICE);
634c70001a9SSony Chacko 	}
635c70001a9SSony Chacko 
636c70001a9SSony Chacko 	nf = &pbuf->frag_array[0];
637a14e3904SChristophe JAILLET 	dma_unmap_single(&pdev->dev, nf->dma, skb_headlen(skb), DMA_TO_DEVICE);
638c70001a9SSony Chacko 	pbuf->skb = NULL;
639c70001a9SSony Chacko }
640c70001a9SSony Chacko 
qlcnic_clear_cmddesc(u64 * desc)641d17dd0d9SSony Chacko static inline void qlcnic_clear_cmddesc(u64 *desc)
642c70001a9SSony Chacko {
643c70001a9SSony Chacko 	desc[0] = 0ULL;
644c70001a9SSony Chacko 	desc[2] = 0ULL;
645c70001a9SSony Chacko 	desc[7] = 0ULL;
646c70001a9SSony Chacko }
647c70001a9SSony Chacko 
qlcnic_xmit_frame(struct sk_buff * skb,struct net_device * netdev)648d17dd0d9SSony Chacko netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
649c70001a9SSony Chacko {
650c70001a9SSony Chacko 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
651012ec812SHimanshu Madhani 	struct qlcnic_host_tx_ring *tx_ring;
652c70001a9SSony Chacko 	struct qlcnic_cmd_buffer *pbuf;
653c70001a9SSony Chacko 	struct qlcnic_skb_frag *buffrag;
654c70001a9SSony Chacko 	struct cmd_desc_type0 *hwdesc, *first_desc;
655c70001a9SSony Chacko 	struct pci_dev *pdev;
656c70001a9SSony Chacko 	struct ethhdr *phdr;
657d17dd0d9SSony Chacko 	int i, k, frag_count, delta = 0;
658d17dd0d9SSony Chacko 	u32 producer, num_txd;
659381709deSShahed Shaikh 	u16 protocol;
660381709deSShahed Shaikh 	bool l4_is_udp = false;
661c70001a9SSony Chacko 
662c70001a9SSony Chacko 	if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
663012ec812SHimanshu Madhani 		netif_tx_stop_all_queues(netdev);
664c70001a9SSony Chacko 		return NETDEV_TX_BUSY;
665c70001a9SSony Chacko 	}
666c70001a9SSony Chacko 
667c70001a9SSony Chacko 	if (adapter->flags & QLCNIC_MACSPOOF) {
668c70001a9SSony Chacko 		phdr = (struct ethhdr *)skb->data;
669c70001a9SSony Chacko 		if (!ether_addr_equal(phdr->h_source, adapter->mac_addr))
670c70001a9SSony Chacko 			goto drop_packet;
671c70001a9SSony Chacko 	}
672c70001a9SSony Chacko 
673012ec812SHimanshu Madhani 	tx_ring = &adapter->tx_ring[skb_get_queue_mapping(skb)];
674012ec812SHimanshu Madhani 	num_txd = tx_ring->num_desc;
675012ec812SHimanshu Madhani 
676c70001a9SSony Chacko 	frag_count = skb_shinfo(skb)->nr_frags + 1;
677012ec812SHimanshu Madhani 
678c70001a9SSony Chacko 	/* 14 frags supported for normal packet and
679c70001a9SSony Chacko 	 * 32 frags supported for TSO packet
680c70001a9SSony Chacko 	 */
681c70001a9SSony Chacko 	if (!skb_is_gso(skb) && frag_count > QLCNIC_MAX_FRAGS_PER_TX) {
682c70001a9SSony Chacko 		for (i = 0; i < (frag_count - QLCNIC_MAX_FRAGS_PER_TX); i++)
683c70001a9SSony Chacko 			delta += skb_frag_size(&skb_shinfo(skb)->frags[i]);
684c70001a9SSony Chacko 
685c70001a9SSony Chacko 		if (!__pskb_pull_tail(skb, delta))
686c70001a9SSony Chacko 			goto drop_packet;
687c70001a9SSony Chacko 
688c70001a9SSony Chacko 		frag_count = 1 + skb_shinfo(skb)->nr_frags;
689c70001a9SSony Chacko 	}
690c70001a9SSony Chacko 
691c70001a9SSony Chacko 	if (unlikely(qlcnic_tx_avail(tx_ring) <= TX_STOP_THRESH)) {
692012ec812SHimanshu Madhani 		netif_tx_stop_queue(tx_ring->txq);
693d17dd0d9SSony Chacko 		if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) {
694012ec812SHimanshu Madhani 			netif_tx_start_queue(tx_ring->txq);
695d17dd0d9SSony Chacko 		} else {
696f27c75b3SHimanshu Madhani 			tx_ring->tx_stats.xmit_off++;
697c70001a9SSony Chacko 			return NETDEV_TX_BUSY;
698c70001a9SSony Chacko 		}
699c70001a9SSony Chacko 	}
700c70001a9SSony Chacko 
701c70001a9SSony Chacko 	producer = tx_ring->producer;
702c70001a9SSony Chacko 	pbuf = &tx_ring->cmd_buf_arr[producer];
703c70001a9SSony Chacko 	pdev = adapter->pdev;
704d17dd0d9SSony Chacko 	first_desc = &tx_ring->desc_head[producer];
705d17dd0d9SSony Chacko 	hwdesc = &tx_ring->desc_head[producer];
706c70001a9SSony Chacko 	qlcnic_clear_cmddesc((u64 *)hwdesc);
707c70001a9SSony Chacko 
708c70001a9SSony Chacko 	if (qlcnic_map_tx_skb(pdev, skb, pbuf)) {
709c70001a9SSony Chacko 		adapter->stats.tx_dma_map_error++;
710c70001a9SSony Chacko 		goto drop_packet;
711c70001a9SSony Chacko 	}
712c70001a9SSony Chacko 
713c70001a9SSony Chacko 	pbuf->skb = skb;
714c70001a9SSony Chacko 	pbuf->frag_count = frag_count;
715c70001a9SSony Chacko 
716c70001a9SSony Chacko 	qlcnic_set_tx_frags_len(first_desc, frag_count, skb->len);
717c70001a9SSony Chacko 	qlcnic_set_tx_port(first_desc, adapter->portnum);
718c70001a9SSony Chacko 
719c70001a9SSony Chacko 	for (i = 0; i < frag_count; i++) {
720c70001a9SSony Chacko 		k = i % 4;
721c70001a9SSony Chacko 
722c70001a9SSony Chacko 		if ((k == 0) && (i > 0)) {
723c70001a9SSony Chacko 			/* move to next desc.*/
724c70001a9SSony Chacko 			producer = get_next_index(producer, num_txd);
725c70001a9SSony Chacko 			hwdesc = &tx_ring->desc_head[producer];
726c70001a9SSony Chacko 			qlcnic_clear_cmddesc((u64 *)hwdesc);
727c70001a9SSony Chacko 			tx_ring->cmd_buf_arr[producer].skb = NULL;
728c70001a9SSony Chacko 		}
729c70001a9SSony Chacko 
730c70001a9SSony Chacko 		buffrag = &pbuf->frag_array[i];
731c70001a9SSony Chacko 		hwdesc->buffer_length[k] = cpu_to_le16(buffrag->length);
732c70001a9SSony Chacko 		switch (k) {
733c70001a9SSony Chacko 		case 0:
734c70001a9SSony Chacko 			hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma);
735c70001a9SSony Chacko 			break;
736c70001a9SSony Chacko 		case 1:
737c70001a9SSony Chacko 			hwdesc->addr_buffer2 = cpu_to_le64(buffrag->dma);
738c70001a9SSony Chacko 			break;
739c70001a9SSony Chacko 		case 2:
740c70001a9SSony Chacko 			hwdesc->addr_buffer3 = cpu_to_le64(buffrag->dma);
741c70001a9SSony Chacko 			break;
742c70001a9SSony Chacko 		case 3:
743c70001a9SSony Chacko 			hwdesc->addr_buffer4 = cpu_to_le64(buffrag->dma);
744c70001a9SSony Chacko 			break;
745c70001a9SSony Chacko 		}
746c70001a9SSony Chacko 	}
747c70001a9SSony Chacko 
748c70001a9SSony Chacko 	tx_ring->producer = get_next_index(producer, num_txd);
749c70001a9SSony Chacko 	smp_mb();
750c70001a9SSony Chacko 
751381709deSShahed Shaikh 	protocol = ntohs(skb->protocol);
752381709deSShahed Shaikh 	if (protocol == ETH_P_IP)
753381709deSShahed Shaikh 		l4_is_udp = ip_hdr(skb)->protocol == IPPROTO_UDP;
754381709deSShahed Shaikh 	else if (protocol == ETH_P_IPV6)
755381709deSShahed Shaikh 		l4_is_udp = ipv6_hdr(skb)->nexthdr == IPPROTO_UDP;
756381709deSShahed Shaikh 
757381709deSShahed Shaikh 	/* Check if it is a VXLAN packet */
758381709deSShahed Shaikh 	if (!skb->encapsulation || !l4_is_udp ||
759381709deSShahed Shaikh 	    !qlcnic_encap_tx_offload(adapter)) {
760381709deSShahed Shaikh 		if (unlikely(qlcnic_tx_pkt(adapter, first_desc, skb,
761381709deSShahed Shaikh 					   tx_ring)))
762c70001a9SSony Chacko 			goto unwind_buff;
763381709deSShahed Shaikh 	} else {
764381709deSShahed Shaikh 		if (unlikely(qlcnic_tx_encap_pkt(adapter, first_desc,
765381709deSShahed Shaikh 						 skb, tx_ring)))
766381709deSShahed Shaikh 			goto unwind_buff;
767381709deSShahed Shaikh 	}
768c70001a9SSony Chacko 
769fe1adc6bSJitendra Kalsaria 	if (adapter->drv_mac_learn)
770c333fa0cSShahed Shaikh 		qlcnic_send_filter(adapter, first_desc, skb, tx_ring);
771c70001a9SSony Chacko 
772f27c75b3SHimanshu Madhani 	tx_ring->tx_stats.tx_bytes += skb->len;
773f27c75b3SHimanshu Madhani 	tx_ring->tx_stats.xmit_called++;
774c70001a9SSony Chacko 
7759216a97aSSony Chacko 	/* Ensure writes are complete before HW fetches Tx descriptors */
7769216a97aSSony Chacko 	wmb();
777c70001a9SSony Chacko 	qlcnic_update_cmd_producer(tx_ring);
778c70001a9SSony Chacko 
779c70001a9SSony Chacko 	return NETDEV_TX_OK;
780c70001a9SSony Chacko 
781c70001a9SSony Chacko unwind_buff:
782c70001a9SSony Chacko 	qlcnic_unmap_buffers(pdev, skb, pbuf);
783c70001a9SSony Chacko drop_packet:
784c70001a9SSony Chacko 	adapter->stats.txdropped++;
785c70001a9SSony Chacko 	dev_kfree_skb_any(skb);
786c70001a9SSony Chacko 	return NETDEV_TX_OK;
787c70001a9SSony Chacko }
788c70001a9SSony Chacko 
qlcnic_advert_link_change(struct qlcnic_adapter * adapter,int linkup)7897f966452SSony Chacko void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup)
790c70001a9SSony Chacko {
791c70001a9SSony Chacko 	struct net_device *netdev = adapter->netdev;
792c70001a9SSony Chacko 
793c70001a9SSony Chacko 	if (adapter->ahw->linkup && !linkup) {
794c70001a9SSony Chacko 		netdev_info(netdev, "NIC Link is down\n");
795c70001a9SSony Chacko 		adapter->ahw->linkup = 0;
796c70001a9SSony Chacko 		netif_carrier_off(netdev);
797c70001a9SSony Chacko 	} else if (!adapter->ahw->linkup && linkup) {
798092dfcf3SShahed Shaikh 		adapter->ahw->linkup = 1;
799092dfcf3SShahed Shaikh 
800092dfcf3SShahed Shaikh 		/* Do not advertise Link up to the stack if device
801092dfcf3SShahed Shaikh 		 * is in loopback mode
802092dfcf3SShahed Shaikh 		 */
803092dfcf3SShahed Shaikh 		if (qlcnic_83xx_check(adapter) && adapter->ahw->lb_mode) {
804092dfcf3SShahed Shaikh 			netdev_info(netdev, "NIC Link is up for loopback test\n");
805d9c602f0SManish Chopra 			return;
806092dfcf3SShahed Shaikh 		}
807d9c602f0SManish Chopra 
808c70001a9SSony Chacko 		netdev_info(netdev, "NIC Link is up\n");
809c70001a9SSony Chacko 		netif_carrier_on(netdev);
810c70001a9SSony Chacko 	}
811c70001a9SSony Chacko }
812c70001a9SSony Chacko 
qlcnic_alloc_rx_skb(struct qlcnic_adapter * adapter,struct qlcnic_host_rds_ring * rds_ring,struct qlcnic_rx_buffer * buffer)813d17dd0d9SSony Chacko static int qlcnic_alloc_rx_skb(struct qlcnic_adapter *adapter,
814c70001a9SSony Chacko 			       struct qlcnic_host_rds_ring *rds_ring,
815c70001a9SSony Chacko 			       struct qlcnic_rx_buffer *buffer)
816c70001a9SSony Chacko {
817c70001a9SSony Chacko 	struct sk_buff *skb;
818c70001a9SSony Chacko 	dma_addr_t dma;
819c70001a9SSony Chacko 	struct pci_dev *pdev = adapter->pdev;
820c70001a9SSony Chacko 
821c70001a9SSony Chacko 	skb = netdev_alloc_skb(adapter->netdev, rds_ring->skb_size);
822c70001a9SSony Chacko 	if (!skb) {
823c70001a9SSony Chacko 		adapter->stats.skb_alloc_failure++;
824c70001a9SSony Chacko 		return -ENOMEM;
825c70001a9SSony Chacko 	}
826c70001a9SSony Chacko 
827c70001a9SSony Chacko 	skb_reserve(skb, NET_IP_ALIGN);
828a14e3904SChristophe JAILLET 	dma = dma_map_single(&pdev->dev, skb->data, rds_ring->dma_size,
829a14e3904SChristophe JAILLET 			     DMA_FROM_DEVICE);
830c70001a9SSony Chacko 
831a14e3904SChristophe JAILLET 	if (dma_mapping_error(&pdev->dev, dma)) {
832c70001a9SSony Chacko 		adapter->stats.rx_dma_map_error++;
833c70001a9SSony Chacko 		dev_kfree_skb_any(skb);
834c70001a9SSony Chacko 		return -ENOMEM;
835c70001a9SSony Chacko 	}
836c70001a9SSony Chacko 
837c70001a9SSony Chacko 	buffer->skb = skb;
838c70001a9SSony Chacko 	buffer->dma = dma;
839c70001a9SSony Chacko 
840c70001a9SSony Chacko 	return 0;
841c70001a9SSony Chacko }
842c70001a9SSony Chacko 
qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter * adapter,struct qlcnic_host_rds_ring * rds_ring,u8 ring_id)843c70001a9SSony Chacko static void qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter,
8444be41e92SSony Chacko 					struct qlcnic_host_rds_ring *rds_ring,
8454be41e92SSony Chacko 					u8 ring_id)
846c70001a9SSony Chacko {
847c70001a9SSony Chacko 	struct rcv_desc *pdesc;
848c70001a9SSony Chacko 	struct qlcnic_rx_buffer *buffer;
849c70001a9SSony Chacko 	int  count = 0;
8504be41e92SSony Chacko 	uint32_t producer, handle;
851c70001a9SSony Chacko 	struct list_head *head;
852c70001a9SSony Chacko 
853c70001a9SSony Chacko 	if (!spin_trylock(&rds_ring->lock))
854c70001a9SSony Chacko 		return;
855c70001a9SSony Chacko 
856c70001a9SSony Chacko 	producer = rds_ring->producer;
857c70001a9SSony Chacko 	head = &rds_ring->free_list;
858d17dd0d9SSony Chacko 	while (!list_empty(head)) {
859c70001a9SSony Chacko 		buffer = list_entry(head->next, struct qlcnic_rx_buffer, list);
860c70001a9SSony Chacko 
861c70001a9SSony Chacko 		if (!buffer->skb) {
862c70001a9SSony Chacko 			if (qlcnic_alloc_rx_skb(adapter, rds_ring, buffer))
863c70001a9SSony Chacko 				break;
864c70001a9SSony Chacko 		}
865c70001a9SSony Chacko 		count++;
866c70001a9SSony Chacko 		list_del(&buffer->list);
867c70001a9SSony Chacko 
868c70001a9SSony Chacko 		/* make a rcv descriptor  */
869c70001a9SSony Chacko 		pdesc = &rds_ring->desc_head[producer];
8704be41e92SSony Chacko 		handle = qlcnic_get_ref_handle(adapter,
8714be41e92SSony Chacko 					       buffer->ref_handle, ring_id);
8724be41e92SSony Chacko 		pdesc->reference_handle = cpu_to_le16(handle);
873c70001a9SSony Chacko 		pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
874c70001a9SSony Chacko 		pdesc->addr_buffer = cpu_to_le64(buffer->dma);
875c70001a9SSony Chacko 		producer = get_next_index(producer, rds_ring->num_desc);
876c70001a9SSony Chacko 	}
877c70001a9SSony Chacko 	if (count) {
878c70001a9SSony Chacko 		rds_ring->producer = producer;
879c70001a9SSony Chacko 		writel((producer - 1) & (rds_ring->num_desc - 1),
880c70001a9SSony Chacko 		       rds_ring->crb_rcv_producer);
881c70001a9SSony Chacko 	}
882c70001a9SSony Chacko 	spin_unlock(&rds_ring->lock);
883c70001a9SSony Chacko }
884c70001a9SSony Chacko 
qlcnic_process_cmd_ring(struct qlcnic_adapter * adapter,struct qlcnic_host_tx_ring * tx_ring,int budget)8854be41e92SSony Chacko static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter,
8864be41e92SSony Chacko 				   struct qlcnic_host_tx_ring *tx_ring,
8874be41e92SSony Chacko 				   int budget)
888c70001a9SSony Chacko {
889c70001a9SSony Chacko 	u32 sw_consumer, hw_consumer;
890d17dd0d9SSony Chacko 	int i, done, count = 0;
891c70001a9SSony Chacko 	struct qlcnic_cmd_buffer *buffer;
892c70001a9SSony Chacko 	struct pci_dev *pdev = adapter->pdev;
893c70001a9SSony Chacko 	struct net_device *netdev = adapter->netdev;
894c70001a9SSony Chacko 	struct qlcnic_skb_frag *frag;
895c70001a9SSony Chacko 
896a02bdd42SShahed Shaikh 	if (!spin_trylock(&tx_ring->tx_clean_lock))
89734e8c406SHimanshu Madhani 		return 1;
89834e8c406SHimanshu Madhani 
899c70001a9SSony Chacko 	sw_consumer = tx_ring->sw_consumer;
900c70001a9SSony Chacko 	hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
901c70001a9SSony Chacko 
902c70001a9SSony Chacko 	while (sw_consumer != hw_consumer) {
903c70001a9SSony Chacko 		buffer = &tx_ring->cmd_buf_arr[sw_consumer];
904c70001a9SSony Chacko 		if (buffer->skb) {
905c70001a9SSony Chacko 			frag = &buffer->frag_array[0];
906a14e3904SChristophe JAILLET 			dma_unmap_single(&pdev->dev, frag->dma, frag->length,
907a14e3904SChristophe JAILLET 					 DMA_TO_DEVICE);
908c70001a9SSony Chacko 			frag->dma = 0ULL;
909c70001a9SSony Chacko 			for (i = 1; i < buffer->frag_count; i++) {
910c70001a9SSony Chacko 				frag++;
911a14e3904SChristophe JAILLET 				dma_unmap_page(&pdev->dev, frag->dma,
912a14e3904SChristophe JAILLET 					       frag->length, DMA_TO_DEVICE);
913c70001a9SSony Chacko 				frag->dma = 0ULL;
914c70001a9SSony Chacko 			}
915f27c75b3SHimanshu Madhani 			tx_ring->tx_stats.xmit_finished++;
916c70001a9SSony Chacko 			dev_kfree_skb_any(buffer->skb);
917c70001a9SSony Chacko 			buffer->skb = NULL;
918c70001a9SSony Chacko 		}
919c70001a9SSony Chacko 
920c70001a9SSony Chacko 		sw_consumer = get_next_index(sw_consumer, tx_ring->num_desc);
9214be41e92SSony Chacko 		if (++count >= budget)
922c70001a9SSony Chacko 			break;
923c70001a9SSony Chacko 	}
924c70001a9SSony Chacko 
925c70001a9SSony Chacko 	tx_ring->sw_consumer = sw_consumer;
926a02bdd42SShahed Shaikh 
927a02bdd42SShahed Shaikh 	if (count && netif_running(netdev)) {
928c70001a9SSony Chacko 		smp_mb();
929012ec812SHimanshu Madhani 		if (netif_tx_queue_stopped(tx_ring->txq) &&
930012ec812SHimanshu Madhani 		    netif_carrier_ok(netdev)) {
931c70001a9SSony Chacko 			if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) {
932012ec812SHimanshu Madhani 				netif_tx_wake_queue(tx_ring->txq);
933f27c75b3SHimanshu Madhani 				tx_ring->tx_stats.xmit_on++;
934c70001a9SSony Chacko 			}
935c70001a9SSony Chacko 		}
936c70001a9SSony Chacko 		adapter->tx_timeo_cnt = 0;
937c70001a9SSony Chacko 	}
938c70001a9SSony Chacko 	/*
939c70001a9SSony Chacko 	 * If everything is freed up to consumer then check if the ring is full
940c70001a9SSony Chacko 	 * If the ring is full then check if more needs to be freed and
941c70001a9SSony Chacko 	 * schedule the call back again.
942c70001a9SSony Chacko 	 *
943c70001a9SSony Chacko 	 * This happens when there are 2 CPUs. One could be freeing and the
944c70001a9SSony Chacko 	 * other filling it. If the ring is full when we get out of here and
945c70001a9SSony Chacko 	 * the card has already interrupted the host then the host can miss the
946c70001a9SSony Chacko 	 * interrupt.
947c70001a9SSony Chacko 	 *
948c70001a9SSony Chacko 	 * There is still a possible race condition and the host could miss an
949c70001a9SSony Chacko 	 * interrupt. The card has to take care of this.
950c70001a9SSony Chacko 	 */
951c70001a9SSony Chacko 	hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
952c70001a9SSony Chacko 	done = (sw_consumer == hw_consumer);
953a02bdd42SShahed Shaikh 
954a02bdd42SShahed Shaikh 	spin_unlock(&tx_ring->tx_clean_lock);
955c70001a9SSony Chacko 
956c70001a9SSony Chacko 	return done;
957c70001a9SSony Chacko }
958c70001a9SSony Chacko 
qlcnic_poll(struct napi_struct * napi,int budget)959c70001a9SSony Chacko static int qlcnic_poll(struct napi_struct *napi, int budget)
960c70001a9SSony Chacko {
9614be41e92SSony Chacko 	int tx_complete, work_done;
962d17dd0d9SSony Chacko 	struct qlcnic_host_sds_ring *sds_ring;
963d17dd0d9SSony Chacko 	struct qlcnic_adapter *adapter;
964012ec812SHimanshu Madhani 	struct qlcnic_host_tx_ring *tx_ring;
965c70001a9SSony Chacko 
966d17dd0d9SSony Chacko 	sds_ring = container_of(napi, struct qlcnic_host_sds_ring, napi);
967d17dd0d9SSony Chacko 	adapter = sds_ring->adapter;
968012ec812SHimanshu Madhani 	tx_ring = sds_ring->tx_ring;
969012ec812SHimanshu Madhani 
970012ec812SHimanshu Madhani 	tx_complete = qlcnic_process_cmd_ring(adapter, tx_ring,
9714be41e92SSony Chacko 					      budget);
972c70001a9SSony Chacko 	work_done = qlcnic_process_rcv_ring(sds_ring, budget);
973f31ec95fSShahed Shaikh 
974f31ec95fSShahed Shaikh 	/* Check if we need a repoll */
975f31ec95fSShahed Shaikh 	if (!tx_complete)
976f31ec95fSShahed Shaikh 		work_done = budget;
977f31ec95fSShahed Shaikh 
978f31ec95fSShahed Shaikh 	if (work_done < budget) {
9796ad20165SEric Dumazet 		napi_complete_done(&sds_ring->napi, work_done);
980012ec812SHimanshu Madhani 		if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
9812cc5752eSManish chopra 			qlcnic_enable_sds_intr(adapter, sds_ring);
982012ec812SHimanshu Madhani 			qlcnic_enable_tx_intr(adapter, tx_ring);
983012ec812SHimanshu Madhani 		}
984012ec812SHimanshu Madhani 	}
985012ec812SHimanshu Madhani 
986012ec812SHimanshu Madhani 	return work_done;
987012ec812SHimanshu Madhani }
988012ec812SHimanshu Madhani 
qlcnic_tx_poll(struct napi_struct * napi,int budget)989012ec812SHimanshu Madhani static int qlcnic_tx_poll(struct napi_struct *napi, int budget)
990012ec812SHimanshu Madhani {
991012ec812SHimanshu Madhani 	struct qlcnic_host_tx_ring *tx_ring;
992012ec812SHimanshu Madhani 	struct qlcnic_adapter *adapter;
993012ec812SHimanshu Madhani 	int work_done;
994012ec812SHimanshu Madhani 
995012ec812SHimanshu Madhani 	tx_ring = container_of(napi, struct qlcnic_host_tx_ring, napi);
996012ec812SHimanshu Madhani 	adapter = tx_ring->adapter;
997012ec812SHimanshu Madhani 
998012ec812SHimanshu Madhani 	work_done = qlcnic_process_cmd_ring(adapter, tx_ring, budget);
999012ec812SHimanshu Madhani 	if (work_done) {
1000012ec812SHimanshu Madhani 		napi_complete(&tx_ring->napi);
1001012ec812SHimanshu Madhani 		if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
1002012ec812SHimanshu Madhani 			qlcnic_enable_tx_intr(adapter, tx_ring);
1003f31ec95fSShahed Shaikh 	} else {
1004f31ec95fSShahed Shaikh 		/* As qlcnic_process_cmd_ring() returned 0, we need a repoll*/
1005f31ec95fSShahed Shaikh 		work_done = budget;
1006c70001a9SSony Chacko 	}
1007c70001a9SSony Chacko 
1008c70001a9SSony Chacko 	return work_done;
1009c70001a9SSony Chacko }
1010c70001a9SSony Chacko 
qlcnic_rx_poll(struct napi_struct * napi,int budget)1011c70001a9SSony Chacko static int qlcnic_rx_poll(struct napi_struct *napi, int budget)
1012c70001a9SSony Chacko {
1013d17dd0d9SSony Chacko 	struct qlcnic_host_sds_ring *sds_ring;
1014d17dd0d9SSony Chacko 	struct qlcnic_adapter *adapter;
1015c70001a9SSony Chacko 	int work_done;
1016c70001a9SSony Chacko 
1017d17dd0d9SSony Chacko 	sds_ring = container_of(napi, struct qlcnic_host_sds_ring, napi);
1018d17dd0d9SSony Chacko 	adapter = sds_ring->adapter;
1019d17dd0d9SSony Chacko 
1020c70001a9SSony Chacko 	work_done = qlcnic_process_rcv_ring(sds_ring, budget);
1021c70001a9SSony Chacko 
1022c70001a9SSony Chacko 	if (work_done < budget) {
10236ad20165SEric Dumazet 		napi_complete_done(&sds_ring->napi, work_done);
1024c70001a9SSony Chacko 		if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
10252cc5752eSManish chopra 			qlcnic_enable_sds_intr(adapter, sds_ring);
1026c70001a9SSony Chacko 	}
1027c70001a9SSony Chacko 
1028c70001a9SSony Chacko 	return work_done;
1029c70001a9SSony Chacko }
1030c70001a9SSony Chacko 
qlcnic_handle_linkevent(struct qlcnic_adapter * adapter,struct qlcnic_fw_msg * msg)1031d17dd0d9SSony Chacko static void qlcnic_handle_linkevent(struct qlcnic_adapter *adapter,
1032c70001a9SSony Chacko 				    struct qlcnic_fw_msg *msg)
1033c70001a9SSony Chacko {
1034c70001a9SSony Chacko 	u32 cable_OUI;
1035d17dd0d9SSony Chacko 	u16 cable_len, link_speed;
1036d17dd0d9SSony Chacko 	u8  link_status, module, duplex, autoneg, lb_status = 0;
1037c70001a9SSony Chacko 	struct net_device *netdev = adapter->netdev;
1038c70001a9SSony Chacko 
103979788450SSony Chacko 	adapter->ahw->has_link_events = 1;
1040c70001a9SSony Chacko 
1041c70001a9SSony Chacko 	cable_OUI = msg->body[1] & 0xffffffff;
1042c70001a9SSony Chacko 	cable_len = (msg->body[1] >> 32) & 0xffff;
1043c70001a9SSony Chacko 	link_speed = (msg->body[1] >> 48) & 0xffff;
1044c70001a9SSony Chacko 
1045c70001a9SSony Chacko 	link_status = msg->body[2] & 0xff;
1046c70001a9SSony Chacko 	duplex = (msg->body[2] >> 16) & 0xff;
1047c70001a9SSony Chacko 	autoneg = (msg->body[2] >> 24) & 0xff;
1048c70001a9SSony Chacko 	lb_status = (msg->body[2] >> 32) & 0x3;
1049c70001a9SSony Chacko 
1050c70001a9SSony Chacko 	module = (msg->body[2] >> 8) & 0xff;
1051c70001a9SSony Chacko 	if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE)
1052d17dd0d9SSony Chacko 		dev_info(&netdev->dev,
1053d17dd0d9SSony Chacko 			 "unsupported cable: OUI 0x%x, length %d\n",
1054d17dd0d9SSony Chacko 			 cable_OUI, cable_len);
1055c70001a9SSony Chacko 	else if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN)
1056c70001a9SSony Chacko 		dev_info(&netdev->dev, "unsupported cable length %d\n",
1057c70001a9SSony Chacko 			 cable_len);
1058c70001a9SSony Chacko 
1059c70001a9SSony Chacko 	if (!link_status && (lb_status == QLCNIC_ILB_MODE ||
1060c70001a9SSony Chacko 	    lb_status == QLCNIC_ELB_MODE))
1061c70001a9SSony Chacko 		adapter->ahw->loopback_state |= QLCNIC_LINKEVENT;
1062c70001a9SSony Chacko 
1063c70001a9SSony Chacko 	qlcnic_advert_link_change(adapter, link_status);
1064c70001a9SSony Chacko 
1065c70001a9SSony Chacko 	if (duplex == LINKEVENT_FULL_DUPLEX)
106679788450SSony Chacko 		adapter->ahw->link_duplex = DUPLEX_FULL;
1067c70001a9SSony Chacko 	else
106879788450SSony Chacko 		adapter->ahw->link_duplex = DUPLEX_HALF;
1069c70001a9SSony Chacko 
107079788450SSony Chacko 	adapter->ahw->module_type = module;
107179788450SSony Chacko 	adapter->ahw->link_autoneg = autoneg;
1072c70001a9SSony Chacko 
1073c70001a9SSony Chacko 	if (link_status) {
107479788450SSony Chacko 		adapter->ahw->link_speed = link_speed;
1075c70001a9SSony Chacko 	} else {
107679788450SSony Chacko 		adapter->ahw->link_speed = SPEED_UNKNOWN;
107779788450SSony Chacko 		adapter->ahw->link_duplex = DUPLEX_UNKNOWN;
1078c70001a9SSony Chacko 	}
1079c70001a9SSony Chacko }
1080c70001a9SSony Chacko 
qlcnic_handle_fw_message(int desc_cnt,int index,struct qlcnic_host_sds_ring * sds_ring)1081d17dd0d9SSony Chacko static void qlcnic_handle_fw_message(int desc_cnt, int index,
1082c70001a9SSony Chacko 				     struct qlcnic_host_sds_ring *sds_ring)
1083c70001a9SSony Chacko {
1084c70001a9SSony Chacko 	struct qlcnic_fw_msg msg;
1085c70001a9SSony Chacko 	struct status_desc *desc;
1086c70001a9SSony Chacko 	struct qlcnic_adapter *adapter;
1087c70001a9SSony Chacko 	struct device *dev;
1088c70001a9SSony Chacko 	int i = 0, opcode, ret;
1089c70001a9SSony Chacko 
1090c70001a9SSony Chacko 	while (desc_cnt > 0 && i < 8) {
1091c70001a9SSony Chacko 		desc = &sds_ring->desc_head[index];
1092c70001a9SSony Chacko 		msg.words[i++] = le64_to_cpu(desc->status_desc_data[0]);
1093c70001a9SSony Chacko 		msg.words[i++] = le64_to_cpu(desc->status_desc_data[1]);
1094c70001a9SSony Chacko 
1095c70001a9SSony Chacko 		index = get_next_index(index, sds_ring->num_desc);
1096c70001a9SSony Chacko 		desc_cnt--;
1097c70001a9SSony Chacko 	}
1098c70001a9SSony Chacko 
1099c70001a9SSony Chacko 	adapter = sds_ring->adapter;
1100c70001a9SSony Chacko 	dev = &adapter->pdev->dev;
1101c70001a9SSony Chacko 	opcode = qlcnic_get_nic_msg_opcode(msg.body[0]);
1102c70001a9SSony Chacko 
1103c70001a9SSony Chacko 	switch (opcode) {
1104c70001a9SSony Chacko 	case QLCNIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE:
1105c70001a9SSony Chacko 		qlcnic_handle_linkevent(adapter, &msg);
1106c70001a9SSony Chacko 		break;
1107c70001a9SSony Chacko 	case QLCNIC_C2H_OPCODE_CONFIG_LOOPBACK:
1108c70001a9SSony Chacko 		ret = (u32)(msg.body[1]);
1109c70001a9SSony Chacko 		switch (ret) {
1110c70001a9SSony Chacko 		case 0:
1111c70001a9SSony Chacko 			adapter->ahw->loopback_state |= QLCNIC_LB_RESPONSE;
1112c70001a9SSony Chacko 			break;
1113c70001a9SSony Chacko 		case 1:
1114c70001a9SSony Chacko 			dev_info(dev, "loopback already in progress\n");
1115b9c11984SJitendra Kalsaria 			adapter->ahw->diag_cnt = -EINPROGRESS;
1116c70001a9SSony Chacko 			break;
1117c70001a9SSony Chacko 		case 2:
1118c70001a9SSony Chacko 			dev_info(dev, "loopback cable is not connected\n");
1119b9c11984SJitendra Kalsaria 			adapter->ahw->diag_cnt = -ENODEV;
1120c70001a9SSony Chacko 			break;
1121c70001a9SSony Chacko 		default:
1122d17dd0d9SSony Chacko 			dev_info(dev,
1123d17dd0d9SSony Chacko 				 "loopback configure request failed, err %x\n",
1124d17dd0d9SSony Chacko 				 ret);
1125b9c11984SJitendra Kalsaria 			adapter->ahw->diag_cnt = -EIO;
1126c70001a9SSony Chacko 			break;
1127c70001a9SSony Chacko 		}
1128c70001a9SSony Chacko 		break;
11292d8ebcabSSucheta Chakraborty 	case QLCNIC_C2H_OPCODE_GET_DCB_AEN:
11301de899d3SSucheta Chakraborty 		qlcnic_dcb_aen_handler(adapter->dcb, (void *)&msg);
11312d8ebcabSSucheta Chakraborty 		break;
1132c70001a9SSony Chacko 	default:
1133c70001a9SSony Chacko 		break;
1134c70001a9SSony Chacko 	}
1135c70001a9SSony Chacko }
1136c70001a9SSony Chacko 
qlcnic_process_rxbuf(struct qlcnic_adapter * adapter,struct qlcnic_host_rds_ring * ring,u16 index,u16 cksum)113721041400Sstephen hemminger static struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *adapter,
11384be41e92SSony Chacko 					    struct qlcnic_host_rds_ring *ring,
11394be41e92SSony Chacko 					    u16 index, u16 cksum)
1140c70001a9SSony Chacko {
1141c70001a9SSony Chacko 	struct qlcnic_rx_buffer *buffer;
1142c70001a9SSony Chacko 	struct sk_buff *skb;
1143c70001a9SSony Chacko 
11444be41e92SSony Chacko 	buffer = &ring->rx_buf_arr[index];
1145c70001a9SSony Chacko 	if (unlikely(buffer->skb == NULL)) {
1146c70001a9SSony Chacko 		WARN_ON(1);
1147c70001a9SSony Chacko 		return NULL;
1148c70001a9SSony Chacko 	}
1149c70001a9SSony Chacko 
1150a14e3904SChristophe JAILLET 	dma_unmap_single(&adapter->pdev->dev, buffer->dma, ring->dma_size,
1151a14e3904SChristophe JAILLET 			 DMA_FROM_DEVICE);
1152c70001a9SSony Chacko 
1153c70001a9SSony Chacko 	skb = buffer->skb;
1154c70001a9SSony Chacko 	if (likely((adapter->netdev->features & NETIF_F_RXCSUM) &&
1155c70001a9SSony Chacko 		   (cksum == STATUS_CKSUM_OK || cksum == STATUS_CKSUM_LOOP))) {
1156c70001a9SSony Chacko 		adapter->stats.csummed++;
1157c70001a9SSony Chacko 		skb->ip_summed = CHECKSUM_UNNECESSARY;
1158c70001a9SSony Chacko 	} else {
1159c70001a9SSony Chacko 		skb_checksum_none_assert(skb);
1160c70001a9SSony Chacko 	}
1161c70001a9SSony Chacko 
11624be41e92SSony Chacko 
1163c70001a9SSony Chacko 	buffer->skb = NULL;
1164c70001a9SSony Chacko 
1165c70001a9SSony Chacko 	return skb;
1166c70001a9SSony Chacko }
1167c70001a9SSony Chacko 
qlcnic_check_rx_tagging(struct qlcnic_adapter * adapter,struct sk_buff * skb,u16 * vlan_tag)1168d17dd0d9SSony Chacko static inline int qlcnic_check_rx_tagging(struct qlcnic_adapter *adapter,
1169d17dd0d9SSony Chacko 					  struct sk_buff *skb, u16 *vlan_tag)
1170c70001a9SSony Chacko {
1171c70001a9SSony Chacko 	struct ethhdr *eth_hdr;
1172c70001a9SSony Chacko 
1173c70001a9SSony Chacko 	if (!__vlan_get_tag(skb, vlan_tag)) {
1174c70001a9SSony Chacko 		eth_hdr = (struct ethhdr *)skb->data;
1175c70001a9SSony Chacko 		memmove(skb->data + VLAN_HLEN, eth_hdr, ETH_ALEN * 2);
1176c70001a9SSony Chacko 		skb_pull(skb, VLAN_HLEN);
1177c70001a9SSony Chacko 	}
117891b7282bSRajesh Borundia 	if (!adapter->rx_pvid)
1179c70001a9SSony Chacko 		return 0;
1180c70001a9SSony Chacko 
118191b7282bSRajesh Borundia 	if (*vlan_tag == adapter->rx_pvid) {
1182c70001a9SSony Chacko 		/* Outer vlan tag. Packet should follow non-vlan path */
1183c70001a9SSony Chacko 		*vlan_tag = 0xffff;
1184c70001a9SSony Chacko 		return 0;
1185c70001a9SSony Chacko 	}
1186c70001a9SSony Chacko 	if (adapter->flags & QLCNIC_TAGGING_ENABLED)
1187c70001a9SSony Chacko 		return 0;
1188c70001a9SSony Chacko 
1189c70001a9SSony Chacko 	return -EINVAL;
1190c70001a9SSony Chacko }
1191c70001a9SSony Chacko 
1192c70001a9SSony Chacko static struct qlcnic_rx_buffer *
qlcnic_process_rcv(struct qlcnic_adapter * adapter,struct qlcnic_host_sds_ring * sds_ring,int ring,u64 sts_data0)1193c70001a9SSony Chacko qlcnic_process_rcv(struct qlcnic_adapter *adapter,
1194d17dd0d9SSony Chacko 		   struct qlcnic_host_sds_ring *sds_ring, int ring,
1195d17dd0d9SSony Chacko 		   u64 sts_data0)
1196c70001a9SSony Chacko {
1197c70001a9SSony Chacko 	struct net_device *netdev = adapter->netdev;
1198c70001a9SSony Chacko 	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
1199c70001a9SSony Chacko 	struct qlcnic_rx_buffer *buffer;
1200c70001a9SSony Chacko 	struct sk_buff *skb;
1201c70001a9SSony Chacko 	struct qlcnic_host_rds_ring *rds_ring;
120253643a75SShahed Shaikh 	int index, length, cksum, pkt_offset, is_lb_pkt;
120353643a75SShahed Shaikh 	u16 vid = 0xffff, t_vid;
1204c70001a9SSony Chacko 
1205c70001a9SSony Chacko 	if (unlikely(ring >= adapter->max_rds_rings))
1206c70001a9SSony Chacko 		return NULL;
1207c70001a9SSony Chacko 
1208c70001a9SSony Chacko 	rds_ring = &recv_ctx->rds_rings[ring];
1209c70001a9SSony Chacko 
1210c70001a9SSony Chacko 	index = qlcnic_get_sts_refhandle(sts_data0);
1211c70001a9SSony Chacko 	if (unlikely(index >= rds_ring->num_desc))
1212c70001a9SSony Chacko 		return NULL;
1213c70001a9SSony Chacko 
1214c70001a9SSony Chacko 	buffer = &rds_ring->rx_buf_arr[index];
1215c70001a9SSony Chacko 	length = qlcnic_get_sts_totallength(sts_data0);
1216c70001a9SSony Chacko 	cksum  = qlcnic_get_sts_status(sts_data0);
1217c70001a9SSony Chacko 	pkt_offset = qlcnic_get_sts_pkt_offset(sts_data0);
1218c70001a9SSony Chacko 
1219c70001a9SSony Chacko 	skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum);
1220c70001a9SSony Chacko 	if (!skb)
1221c70001a9SSony Chacko 		return buffer;
1222c70001a9SSony Chacko 
1223ddfbac07SShahed Shaikh 	if (adapter->rx_mac_learn) {
122453643a75SShahed Shaikh 		t_vid = 0;
122553643a75SShahed Shaikh 		is_lb_pkt = qlcnic_82xx_is_lb_pkt(sts_data0);
1226f80bc8feSRajesh Borundia 		qlcnic_add_lb_filter(adapter, skb, is_lb_pkt, t_vid);
122753643a75SShahed Shaikh 	}
122853643a75SShahed Shaikh 
1229c70001a9SSony Chacko 	if (length > rds_ring->skb_size)
1230c70001a9SSony Chacko 		skb_put(skb, rds_ring->skb_size);
1231c70001a9SSony Chacko 	else
1232c70001a9SSony Chacko 		skb_put(skb, length);
1233c70001a9SSony Chacko 
1234c70001a9SSony Chacko 	if (pkt_offset)
1235c70001a9SSony Chacko 		skb_pull(skb, pkt_offset);
1236c70001a9SSony Chacko 
1237c70001a9SSony Chacko 	if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) {
1238c70001a9SSony Chacko 		adapter->stats.rxdropped++;
1239c70001a9SSony Chacko 		dev_kfree_skb(skb);
1240c70001a9SSony Chacko 		return buffer;
1241c70001a9SSony Chacko 	}
1242c70001a9SSony Chacko 
1243c70001a9SSony Chacko 	skb->protocol = eth_type_trans(skb, netdev);
1244c70001a9SSony Chacko 
1245c70001a9SSony Chacko 	if (vid != 0xffff)
124686a9bad3SPatrick McHardy 		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid);
1247c70001a9SSony Chacko 
1248c70001a9SSony Chacko 	napi_gro_receive(&sds_ring->napi, skb);
1249c70001a9SSony Chacko 
1250c70001a9SSony Chacko 	adapter->stats.rx_pkts++;
1251c70001a9SSony Chacko 	adapter->stats.rxbytes += length;
1252c70001a9SSony Chacko 
1253c70001a9SSony Chacko 	return buffer;
1254c70001a9SSony Chacko }
1255c70001a9SSony Chacko 
1256c70001a9SSony Chacko #define QLC_TCP_HDR_SIZE            20
1257c70001a9SSony Chacko #define QLC_TCP_TS_OPTION_SIZE      12
1258c70001a9SSony Chacko #define QLC_TCP_TS_HDR_SIZE         (QLC_TCP_HDR_SIZE + QLC_TCP_TS_OPTION_SIZE)
1259c70001a9SSony Chacko 
1260c70001a9SSony Chacko static struct qlcnic_rx_buffer *
qlcnic_process_lro(struct qlcnic_adapter * adapter,int ring,u64 sts_data0,u64 sts_data1)1261c70001a9SSony Chacko qlcnic_process_lro(struct qlcnic_adapter *adapter,
1262c70001a9SSony Chacko 		   int ring, u64 sts_data0, u64 sts_data1)
1263c70001a9SSony Chacko {
1264c70001a9SSony Chacko 	struct net_device *netdev = adapter->netdev;
1265c70001a9SSony Chacko 	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
1266c70001a9SSony Chacko 	struct qlcnic_rx_buffer *buffer;
1267c70001a9SSony Chacko 	struct sk_buff *skb;
1268c70001a9SSony Chacko 	struct qlcnic_host_rds_ring *rds_ring;
1269c70001a9SSony Chacko 	struct iphdr *iph;
1270776e7bdeSShahed Shaikh 	struct ipv6hdr *ipv6h;
1271c70001a9SSony Chacko 	struct tcphdr *th;
1272c70001a9SSony Chacko 	bool push, timestamp;
127353643a75SShahed Shaikh 	int index, l2_hdr_offset, l4_hdr_offset, is_lb_pkt;
127453643a75SShahed Shaikh 	u16 lro_length, length, data_offset, t_vid, vid = 0xffff;
1275c70001a9SSony Chacko 	u32 seq_number;
1276c70001a9SSony Chacko 
1277462bed48SManish Chopra 	if (unlikely(ring >= adapter->max_rds_rings))
1278c70001a9SSony Chacko 		return NULL;
1279c70001a9SSony Chacko 
1280c70001a9SSony Chacko 	rds_ring = &recv_ctx->rds_rings[ring];
1281c70001a9SSony Chacko 
1282c70001a9SSony Chacko 	index = qlcnic_get_lro_sts_refhandle(sts_data0);
1283462bed48SManish Chopra 	if (unlikely(index >= rds_ring->num_desc))
1284c70001a9SSony Chacko 		return NULL;
1285c70001a9SSony Chacko 
1286c70001a9SSony Chacko 	buffer = &rds_ring->rx_buf_arr[index];
1287c70001a9SSony Chacko 
1288c70001a9SSony Chacko 	timestamp = qlcnic_get_lro_sts_timestamp(sts_data0);
1289c70001a9SSony Chacko 	lro_length = qlcnic_get_lro_sts_length(sts_data0);
1290c70001a9SSony Chacko 	l2_hdr_offset = qlcnic_get_lro_sts_l2_hdr_offset(sts_data0);
1291c70001a9SSony Chacko 	l4_hdr_offset = qlcnic_get_lro_sts_l4_hdr_offset(sts_data0);
1292c70001a9SSony Chacko 	push = qlcnic_get_lro_sts_push_flag(sts_data0);
1293c70001a9SSony Chacko 	seq_number = qlcnic_get_lro_sts_seq_number(sts_data1);
1294c70001a9SSony Chacko 
1295c70001a9SSony Chacko 	skb = qlcnic_process_rxbuf(adapter, rds_ring, index, STATUS_CKSUM_OK);
1296c70001a9SSony Chacko 	if (!skb)
1297c70001a9SSony Chacko 		return buffer;
1298c70001a9SSony Chacko 
1299ddfbac07SShahed Shaikh 	if (adapter->rx_mac_learn) {
130053643a75SShahed Shaikh 		t_vid = 0;
130153643a75SShahed Shaikh 		is_lb_pkt = qlcnic_82xx_is_lb_pkt(sts_data0);
1302f80bc8feSRajesh Borundia 		qlcnic_add_lb_filter(adapter, skb, is_lb_pkt, t_vid);
130353643a75SShahed Shaikh 	}
130453643a75SShahed Shaikh 
1305c70001a9SSony Chacko 	if (timestamp)
1306c70001a9SSony Chacko 		data_offset = l4_hdr_offset + QLC_TCP_TS_HDR_SIZE;
1307c70001a9SSony Chacko 	else
1308c70001a9SSony Chacko 		data_offset = l4_hdr_offset + QLC_TCP_HDR_SIZE;
1309c70001a9SSony Chacko 
1310c70001a9SSony Chacko 	skb_put(skb, lro_length + data_offset);
1311c70001a9SSony Chacko 	skb_pull(skb, l2_hdr_offset);
1312c70001a9SSony Chacko 
1313c70001a9SSony Chacko 	if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) {
1314c70001a9SSony Chacko 		adapter->stats.rxdropped++;
1315c70001a9SSony Chacko 		dev_kfree_skb(skb);
1316c70001a9SSony Chacko 		return buffer;
1317c70001a9SSony Chacko 	}
1318c70001a9SSony Chacko 
1319c70001a9SSony Chacko 	skb->protocol = eth_type_trans(skb, netdev);
1320776e7bdeSShahed Shaikh 
1321069048f1SShahed Shaikh 	if (ntohs(skb->protocol) == ETH_P_IPV6) {
1322776e7bdeSShahed Shaikh 		ipv6h = (struct ipv6hdr *)skb->data;
1323776e7bdeSShahed Shaikh 		th = (struct tcphdr *)(skb->data + sizeof(struct ipv6hdr));
1324776e7bdeSShahed Shaikh 		length = (th->doff << 2) + lro_length;
1325776e7bdeSShahed Shaikh 		ipv6h->payload_len = htons(length);
1326776e7bdeSShahed Shaikh 	} else {
1327c70001a9SSony Chacko 		iph = (struct iphdr *)skb->data;
1328c70001a9SSony Chacko 		th = (struct tcphdr *)(skb->data + (iph->ihl << 2));
1329c70001a9SSony Chacko 		length = (iph->ihl << 2) + (th->doff << 2) + lro_length;
13301bcac3b0SLi RongQing 		csum_replace2(&iph->check, iph->tot_len, htons(length));
1331c70001a9SSony Chacko 		iph->tot_len = htons(length);
1332776e7bdeSShahed Shaikh 	}
1333776e7bdeSShahed Shaikh 
1334c70001a9SSony Chacko 	th->psh = push;
1335c70001a9SSony Chacko 	th->seq = htonl(seq_number);
1336c70001a9SSony Chacko 	length = skb->len;
1337c70001a9SSony Chacko 
1338bd69ba79SMichael S. Tsirkin 	if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP) {
1339c70001a9SSony Chacko 		skb_shinfo(skb)->gso_size = qlcnic_get_lro_sts_mss(sts_data1);
1340bd69ba79SMichael S. Tsirkin 		if (skb->protocol == htons(ETH_P_IPV6))
1341bd69ba79SMichael S. Tsirkin 			skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
1342bd69ba79SMichael S. Tsirkin 		else
1343bd69ba79SMichael S. Tsirkin 			skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
1344bd69ba79SMichael S. Tsirkin 	}
1345c70001a9SSony Chacko 
1346c70001a9SSony Chacko 	if (vid != 0xffff)
134786a9bad3SPatrick McHardy 		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid);
1348c70001a9SSony Chacko 	netif_receive_skb(skb);
1349c70001a9SSony Chacko 
1350c70001a9SSony Chacko 	adapter->stats.lro_pkts++;
1351c70001a9SSony Chacko 	adapter->stats.lrobytes += length;
1352c70001a9SSony Chacko 
1353c70001a9SSony Chacko 	return buffer;
1354c70001a9SSony Chacko }
1355c70001a9SSony Chacko 
qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring * sds_ring,int max)135621041400Sstephen hemminger static int qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max)
1357c70001a9SSony Chacko {
1358d17dd0d9SSony Chacko 	struct qlcnic_host_rds_ring *rds_ring;
1359c70001a9SSony Chacko 	struct qlcnic_adapter *adapter = sds_ring->adapter;
1360c70001a9SSony Chacko 	struct list_head *cur;
1361c70001a9SSony Chacko 	struct status_desc *desc;
1362c70001a9SSony Chacko 	struct qlcnic_rx_buffer *rxbuf;
13634be41e92SSony Chacko 	int opcode, desc_cnt, count = 0;
1364c70001a9SSony Chacko 	u64 sts_data0, sts_data1;
13654be41e92SSony Chacko 	u8 ring;
1366c70001a9SSony Chacko 	u32 consumer = sds_ring->consumer;
1367c70001a9SSony Chacko 
1368c70001a9SSony Chacko 	while (count < max) {
1369c70001a9SSony Chacko 		desc = &sds_ring->desc_head[consumer];
1370c70001a9SSony Chacko 		sts_data0 = le64_to_cpu(desc->status_desc_data[0]);
1371c70001a9SSony Chacko 
1372c70001a9SSony Chacko 		if (!(sts_data0 & STATUS_OWNER_HOST))
1373c70001a9SSony Chacko 			break;
1374c70001a9SSony Chacko 
1375c70001a9SSony Chacko 		desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0);
1376c70001a9SSony Chacko 		opcode = qlcnic_get_sts_opcode(sts_data0);
1377c70001a9SSony Chacko 		switch (opcode) {
1378c70001a9SSony Chacko 		case QLCNIC_RXPKT_DESC:
1379c70001a9SSony Chacko 		case QLCNIC_OLD_RXPKT_DESC:
1380c70001a9SSony Chacko 		case QLCNIC_SYN_OFFLOAD:
1381c70001a9SSony Chacko 			ring = qlcnic_get_sts_type(sts_data0);
1382d17dd0d9SSony Chacko 			rxbuf = qlcnic_process_rcv(adapter, sds_ring, ring,
1383d17dd0d9SSony Chacko 						   sts_data0);
1384c70001a9SSony Chacko 			break;
1385c70001a9SSony Chacko 		case QLCNIC_LRO_DESC:
1386c70001a9SSony Chacko 			ring = qlcnic_get_lro_sts_type(sts_data0);
1387c70001a9SSony Chacko 			sts_data1 = le64_to_cpu(desc->status_desc_data[1]);
1388c70001a9SSony Chacko 			rxbuf = qlcnic_process_lro(adapter, ring, sts_data0,
1389c70001a9SSony Chacko 						   sts_data1);
1390c70001a9SSony Chacko 			break;
1391c70001a9SSony Chacko 		case QLCNIC_RESPONSE_DESC:
1392c70001a9SSony Chacko 			qlcnic_handle_fw_message(desc_cnt, consumer, sds_ring);
1393d66aea44SGustavo A. R. Silva 			goto skip;
1394c70001a9SSony Chacko 		default:
1395c70001a9SSony Chacko 			goto skip;
1396c70001a9SSony Chacko 		}
1397c70001a9SSony Chacko 		WARN_ON(desc_cnt > 1);
1398c70001a9SSony Chacko 
1399c70001a9SSony Chacko 		if (likely(rxbuf))
1400c70001a9SSony Chacko 			list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]);
1401c70001a9SSony Chacko 		else
1402c70001a9SSony Chacko 			adapter->stats.null_rxbuf++;
1403c70001a9SSony Chacko skip:
1404c70001a9SSony Chacko 		for (; desc_cnt > 0; desc_cnt--) {
1405c70001a9SSony Chacko 			desc = &sds_ring->desc_head[consumer];
14064be41e92SSony Chacko 			desc->status_desc_data[0] = QLCNIC_DESC_OWNER_FW;
1407c70001a9SSony Chacko 			consumer = get_next_index(consumer, sds_ring->num_desc);
1408c70001a9SSony Chacko 		}
1409c70001a9SSony Chacko 		count++;
1410c70001a9SSony Chacko 	}
1411c70001a9SSony Chacko 
1412c70001a9SSony Chacko 	for (ring = 0; ring < adapter->max_rds_rings; ring++) {
1413d17dd0d9SSony Chacko 		rds_ring = &adapter->recv_ctx->rds_rings[ring];
1414c70001a9SSony Chacko 		if (!list_empty(&sds_ring->free_list[ring])) {
1415c70001a9SSony Chacko 			list_for_each(cur, &sds_ring->free_list[ring]) {
1416d17dd0d9SSony Chacko 				rxbuf = list_entry(cur, struct qlcnic_rx_buffer,
1417d17dd0d9SSony Chacko 						   list);
1418c70001a9SSony Chacko 				qlcnic_alloc_rx_skb(adapter, rds_ring, rxbuf);
1419c70001a9SSony Chacko 			}
1420c70001a9SSony Chacko 			spin_lock(&rds_ring->lock);
1421c70001a9SSony Chacko 			list_splice_tail_init(&sds_ring->free_list[ring],
1422c70001a9SSony Chacko 					      &rds_ring->free_list);
1423c70001a9SSony Chacko 			spin_unlock(&rds_ring->lock);
1424c70001a9SSony Chacko 		}
1425c70001a9SSony Chacko 
14264be41e92SSony Chacko 		qlcnic_post_rx_buffers_nodb(adapter, rds_ring, ring);
1427c70001a9SSony Chacko 	}
1428c70001a9SSony Chacko 
1429c70001a9SSony Chacko 	if (count) {
1430c70001a9SSony Chacko 		sds_ring->consumer = consumer;
1431c70001a9SSony Chacko 		writel(consumer, sds_ring->crb_sts_consumer);
1432c70001a9SSony Chacko 	}
1433c70001a9SSony Chacko 
1434c70001a9SSony Chacko 	return count;
1435c70001a9SSony Chacko }
1436c70001a9SSony Chacko 
qlcnic_post_rx_buffers(struct qlcnic_adapter * adapter,struct qlcnic_host_rds_ring * rds_ring,u8 ring_id)1437d17dd0d9SSony Chacko void qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter,
14384be41e92SSony Chacko 			    struct qlcnic_host_rds_ring *rds_ring, u8 ring_id)
1439c70001a9SSony Chacko {
1440c70001a9SSony Chacko 	struct rcv_desc *pdesc;
1441c70001a9SSony Chacko 	struct qlcnic_rx_buffer *buffer;
1442c70001a9SSony Chacko 	int count = 0;
14434be41e92SSony Chacko 	u32 producer, handle;
1444c70001a9SSony Chacko 	struct list_head *head;
1445c70001a9SSony Chacko 
1446c70001a9SSony Chacko 	producer = rds_ring->producer;
1447c70001a9SSony Chacko 	head = &rds_ring->free_list;
1448d17dd0d9SSony Chacko 
1449c70001a9SSony Chacko 	while (!list_empty(head)) {
1450c70001a9SSony Chacko 
1451c70001a9SSony Chacko 		buffer = list_entry(head->next, struct qlcnic_rx_buffer, list);
1452c70001a9SSony Chacko 
1453c70001a9SSony Chacko 		if (!buffer->skb) {
1454c70001a9SSony Chacko 			if (qlcnic_alloc_rx_skb(adapter, rds_ring, buffer))
1455c70001a9SSony Chacko 				break;
1456c70001a9SSony Chacko 		}
1457c70001a9SSony Chacko 
1458c70001a9SSony Chacko 		count++;
1459c70001a9SSony Chacko 		list_del(&buffer->list);
1460c70001a9SSony Chacko 
1461c70001a9SSony Chacko 		/* make a rcv descriptor  */
1462c70001a9SSony Chacko 		pdesc = &rds_ring->desc_head[producer];
1463c70001a9SSony Chacko 		pdesc->addr_buffer = cpu_to_le64(buffer->dma);
14644be41e92SSony Chacko 		handle = qlcnic_get_ref_handle(adapter, buffer->ref_handle,
14654be41e92SSony Chacko 					       ring_id);
14664be41e92SSony Chacko 		pdesc->reference_handle = cpu_to_le16(handle);
1467c70001a9SSony Chacko 		pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
1468c70001a9SSony Chacko 		producer = get_next_index(producer, rds_ring->num_desc);
1469c70001a9SSony Chacko 	}
1470c70001a9SSony Chacko 
1471c70001a9SSony Chacko 	if (count) {
1472c70001a9SSony Chacko 		rds_ring->producer = producer;
1473c70001a9SSony Chacko 		writel((producer-1) & (rds_ring->num_desc-1),
1474c70001a9SSony Chacko 		       rds_ring->crb_rcv_producer);
1475c70001a9SSony Chacko 	}
1476c70001a9SSony Chacko }
1477c70001a9SSony Chacko 
dump_skb(struct sk_buff * skb,struct qlcnic_adapter * adapter)1478c70001a9SSony Chacko static void dump_skb(struct sk_buff *skb, struct qlcnic_adapter *adapter)
1479c70001a9SSony Chacko {
14803620af0eSJoe Perches 	if (adapter->ahw->msg_enable & NETIF_MSG_DRV) {
14813620af0eSJoe Perches 		char prefix[30];
1482c70001a9SSony Chacko 
14833620af0eSJoe Perches 		scnprintf(prefix, sizeof(prefix), "%s: %s: ",
14843620af0eSJoe Perches 			  dev_name(&adapter->pdev->dev), __func__);
14853620af0eSJoe Perches 
14863620af0eSJoe Perches 		print_hex_dump_debug(prefix, DUMP_PREFIX_NONE, 16, 1,
14873620af0eSJoe Perches 				     skb->data, skb->len, true);
1488c70001a9SSony Chacko 	}
1489c70001a9SSony Chacko }
1490c70001a9SSony Chacko 
qlcnic_process_rcv_diag(struct qlcnic_adapter * adapter,int ring,u64 sts_data0)1491c70001a9SSony Chacko static void qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter, int ring,
1492c70001a9SSony Chacko 				    u64 sts_data0)
1493c70001a9SSony Chacko {
1494c70001a9SSony Chacko 	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
1495c70001a9SSony Chacko 	struct sk_buff *skb;
1496c70001a9SSony Chacko 	struct qlcnic_host_rds_ring *rds_ring;
1497c70001a9SSony Chacko 	int index, length, cksum, pkt_offset;
1498c70001a9SSony Chacko 
1499c70001a9SSony Chacko 	if (unlikely(ring >= adapter->max_rds_rings))
1500c70001a9SSony Chacko 		return;
1501c70001a9SSony Chacko 
1502c70001a9SSony Chacko 	rds_ring = &recv_ctx->rds_rings[ring];
1503c70001a9SSony Chacko 
1504c70001a9SSony Chacko 	index = qlcnic_get_sts_refhandle(sts_data0);
1505c70001a9SSony Chacko 	length = qlcnic_get_sts_totallength(sts_data0);
1506c70001a9SSony Chacko 	if (unlikely(index >= rds_ring->num_desc))
1507c70001a9SSony Chacko 		return;
1508c70001a9SSony Chacko 
1509c70001a9SSony Chacko 	cksum  = qlcnic_get_sts_status(sts_data0);
1510c70001a9SSony Chacko 	pkt_offset = qlcnic_get_sts_pkt_offset(sts_data0);
1511c70001a9SSony Chacko 
1512c70001a9SSony Chacko 	skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum);
1513c70001a9SSony Chacko 	if (!skb)
1514c70001a9SSony Chacko 		return;
1515c70001a9SSony Chacko 
1516c70001a9SSony Chacko 	if (length > rds_ring->skb_size)
1517c70001a9SSony Chacko 		skb_put(skb, rds_ring->skb_size);
1518c70001a9SSony Chacko 	else
1519c70001a9SSony Chacko 		skb_put(skb, length);
1520c70001a9SSony Chacko 
1521c70001a9SSony Chacko 	if (pkt_offset)
1522c70001a9SSony Chacko 		skb_pull(skb, pkt_offset);
1523c70001a9SSony Chacko 
1524c70001a9SSony Chacko 	if (!qlcnic_check_loopback_buff(skb->data, adapter->mac_addr))
152579788450SSony Chacko 		adapter->ahw->diag_cnt++;
1526c70001a9SSony Chacko 	else
1527c70001a9SSony Chacko 		dump_skb(skb, adapter);
1528c70001a9SSony Chacko 
1529c70001a9SSony Chacko 	dev_kfree_skb_any(skb);
1530c70001a9SSony Chacko 	adapter->stats.rx_pkts++;
1531c70001a9SSony Chacko 	adapter->stats.rxbytes += length;
1532c70001a9SSony Chacko 
1533c70001a9SSony Chacko 	return;
1534c70001a9SSony Chacko }
1535c70001a9SSony Chacko 
qlcnic_82xx_process_rcv_ring_diag(struct qlcnic_host_sds_ring * sds_ring)15367e2cf4feSSony Chacko void qlcnic_82xx_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring)
1537c70001a9SSony Chacko {
1538c70001a9SSony Chacko 	struct qlcnic_adapter *adapter = sds_ring->adapter;
1539c70001a9SSony Chacko 	struct status_desc *desc;
1540c70001a9SSony Chacko 	u64 sts_data0;
1541c70001a9SSony Chacko 	int ring, opcode, desc_cnt;
1542c70001a9SSony Chacko 
1543c70001a9SSony Chacko 	u32 consumer = sds_ring->consumer;
1544c70001a9SSony Chacko 
1545c70001a9SSony Chacko 	desc = &sds_ring->desc_head[consumer];
1546c70001a9SSony Chacko 	sts_data0 = le64_to_cpu(desc->status_desc_data[0]);
1547c70001a9SSony Chacko 
1548c70001a9SSony Chacko 	if (!(sts_data0 & STATUS_OWNER_HOST))
1549c70001a9SSony Chacko 		return;
1550c70001a9SSony Chacko 
1551c70001a9SSony Chacko 	desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0);
1552c70001a9SSony Chacko 	opcode = qlcnic_get_sts_opcode(sts_data0);
1553c70001a9SSony Chacko 	switch (opcode) {
1554c70001a9SSony Chacko 	case QLCNIC_RESPONSE_DESC:
1555c70001a9SSony Chacko 		qlcnic_handle_fw_message(desc_cnt, consumer, sds_ring);
1556c70001a9SSony Chacko 		break;
1557c70001a9SSony Chacko 	default:
1558c70001a9SSony Chacko 		ring = qlcnic_get_sts_type(sts_data0);
1559c70001a9SSony Chacko 		qlcnic_process_rcv_diag(adapter, ring, sts_data0);
1560c70001a9SSony Chacko 		break;
1561c70001a9SSony Chacko 	}
1562c70001a9SSony Chacko 
1563c70001a9SSony Chacko 	for (; desc_cnt > 0; desc_cnt--) {
1564c70001a9SSony Chacko 		desc = &sds_ring->desc_head[consumer];
1565c70001a9SSony Chacko 		desc->status_desc_data[0] = cpu_to_le64(STATUS_OWNER_PHANTOM);
1566c70001a9SSony Chacko 		consumer = get_next_index(consumer, sds_ring->num_desc);
1567c70001a9SSony Chacko 	}
1568c70001a9SSony Chacko 
1569c70001a9SSony Chacko 	sds_ring->consumer = consumer;
1570c70001a9SSony Chacko 	writel(consumer, sds_ring->crb_sts_consumer);
1571c70001a9SSony Chacko }
1572c70001a9SSony Chacko 
qlcnic_82xx_napi_add(struct qlcnic_adapter * adapter,struct net_device * netdev)15737e2cf4feSSony Chacko int qlcnic_82xx_napi_add(struct qlcnic_adapter *adapter,
15747e2cf4feSSony Chacko 			 struct net_device *netdev)
1575c70001a9SSony Chacko {
1576df95fc44SMichal Schmidt 	int ring;
1577c70001a9SSony Chacko 	struct qlcnic_host_sds_ring *sds_ring;
1578c70001a9SSony Chacko 	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
1579012ec812SHimanshu Madhani 	struct qlcnic_host_tx_ring *tx_ring;
1580c70001a9SSony Chacko 
158134e8c406SHimanshu Madhani 	if (qlcnic_alloc_sds_rings(recv_ctx, adapter->drv_sds_rings))
1582c70001a9SSony Chacko 		return -ENOMEM;
1583c70001a9SSony Chacko 
158434e8c406SHimanshu Madhani 	for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
1585c70001a9SSony Chacko 		sds_ring = &recv_ctx->sds_rings[ring];
1586012ec812SHimanshu Madhani 		if (qlcnic_check_multi_tx(adapter) &&
158780c0e4f3SHimanshu Madhani 		    !adapter->ahw->diag_test) {
1588b48b89f9SJakub Kicinski 			netif_napi_add(netdev, &sds_ring->napi,
1589b48b89f9SJakub Kicinski 				       qlcnic_rx_poll);
1590012ec812SHimanshu Madhani 		} else {
159134e8c406SHimanshu Madhani 			if (ring == (adapter->drv_sds_rings - 1))
1592012ec812SHimanshu Madhani 				netif_napi_add(netdev, &sds_ring->napi,
1593b48b89f9SJakub Kicinski 					       qlcnic_poll);
1594012ec812SHimanshu Madhani 			else
1595012ec812SHimanshu Madhani 				netif_napi_add(netdev, &sds_ring->napi,
1596b48b89f9SJakub Kicinski 					       qlcnic_rx_poll);
1597012ec812SHimanshu Madhani 		}
1598c70001a9SSony Chacko 	}
1599c70001a9SSony Chacko 
16004be41e92SSony Chacko 	if (qlcnic_alloc_tx_rings(adapter, netdev)) {
16014be41e92SSony Chacko 		qlcnic_free_sds_rings(recv_ctx);
16024be41e92SSony Chacko 		return -ENOMEM;
16034be41e92SSony Chacko 	}
16044be41e92SSony Chacko 
1605c2c5e3a0SHimanshu Madhani 	if (qlcnic_check_multi_tx(adapter) && !adapter->ahw->diag_test) {
160634e8c406SHimanshu Madhani 		for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
1607012ec812SHimanshu Madhani 			tx_ring = &adapter->tx_ring[ring];
160816d083e2SJakub Kicinski 			netif_napi_add_tx(netdev, &tx_ring->napi,
160916d083e2SJakub Kicinski 					  qlcnic_tx_poll);
1610012ec812SHimanshu Madhani 		}
1611012ec812SHimanshu Madhani 	}
1612012ec812SHimanshu Madhani 
1613c70001a9SSony Chacko 	return 0;
1614c70001a9SSony Chacko }
1615c70001a9SSony Chacko 
qlcnic_82xx_napi_del(struct qlcnic_adapter * adapter)16164be41e92SSony Chacko void qlcnic_82xx_napi_del(struct qlcnic_adapter *adapter)
1617c70001a9SSony Chacko {
1618c70001a9SSony Chacko 	int ring;
1619c70001a9SSony Chacko 	struct qlcnic_host_sds_ring *sds_ring;
1620c70001a9SSony Chacko 	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
1621012ec812SHimanshu Madhani 	struct qlcnic_host_tx_ring *tx_ring;
1622c70001a9SSony Chacko 
162334e8c406SHimanshu Madhani 	for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
1624c70001a9SSony Chacko 		sds_ring = &recv_ctx->sds_rings[ring];
1625c70001a9SSony Chacko 		netif_napi_del(&sds_ring->napi);
1626c70001a9SSony Chacko 	}
1627c70001a9SSony Chacko 
1628c70001a9SSony Chacko 	qlcnic_free_sds_rings(adapter->recv_ctx);
1629012ec812SHimanshu Madhani 
1630c2c5e3a0SHimanshu Madhani 	if (qlcnic_check_multi_tx(adapter) && !adapter->ahw->diag_test) {
163134e8c406SHimanshu Madhani 		for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
1632012ec812SHimanshu Madhani 			tx_ring = &adapter->tx_ring[ring];
1633012ec812SHimanshu Madhani 			netif_napi_del(&tx_ring->napi);
1634012ec812SHimanshu Madhani 		}
1635012ec812SHimanshu Madhani 	}
1636012ec812SHimanshu Madhani 
16374be41e92SSony Chacko 	qlcnic_free_tx_rings(adapter);
1638c70001a9SSony Chacko }
1639c70001a9SSony Chacko 
qlcnic_82xx_napi_enable(struct qlcnic_adapter * adapter)16407e2cf4feSSony Chacko void qlcnic_82xx_napi_enable(struct qlcnic_adapter *adapter)
1641c70001a9SSony Chacko {
1642c70001a9SSony Chacko 	int ring;
1643c70001a9SSony Chacko 	struct qlcnic_host_sds_ring *sds_ring;
1644012ec812SHimanshu Madhani 	struct qlcnic_host_tx_ring *tx_ring;
1645c70001a9SSony Chacko 	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
1646c70001a9SSony Chacko 
1647c70001a9SSony Chacko 	if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
1648c70001a9SSony Chacko 		return;
1649c70001a9SSony Chacko 
165034e8c406SHimanshu Madhani 	for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
1651c70001a9SSony Chacko 		sds_ring = &recv_ctx->sds_rings[ring];
1652c70001a9SSony Chacko 		napi_enable(&sds_ring->napi);
16532cc5752eSManish chopra 		qlcnic_enable_sds_intr(adapter, sds_ring);
1654c70001a9SSony Chacko 	}
1655012ec812SHimanshu Madhani 
1656012ec812SHimanshu Madhani 	if (qlcnic_check_multi_tx(adapter) &&
1657012ec812SHimanshu Madhani 	    (adapter->flags & QLCNIC_MSIX_ENABLED) &&
165880c0e4f3SHimanshu Madhani 	    !adapter->ahw->diag_test) {
165934e8c406SHimanshu Madhani 		for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
1660012ec812SHimanshu Madhani 			tx_ring = &adapter->tx_ring[ring];
1661012ec812SHimanshu Madhani 			napi_enable(&tx_ring->napi);
1662012ec812SHimanshu Madhani 			qlcnic_enable_tx_intr(adapter, tx_ring);
1663012ec812SHimanshu Madhani 		}
1664012ec812SHimanshu Madhani 	}
1665c70001a9SSony Chacko }
1666c70001a9SSony Chacko 
qlcnic_82xx_napi_disable(struct qlcnic_adapter * adapter)16677e2cf4feSSony Chacko void qlcnic_82xx_napi_disable(struct qlcnic_adapter *adapter)
1668c70001a9SSony Chacko {
1669c70001a9SSony Chacko 	int ring;
1670c70001a9SSony Chacko 	struct qlcnic_host_sds_ring *sds_ring;
1671012ec812SHimanshu Madhani 	struct qlcnic_host_tx_ring *tx_ring;
1672c70001a9SSony Chacko 	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
1673c70001a9SSony Chacko 
1674c70001a9SSony Chacko 	if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
1675c70001a9SSony Chacko 		return;
1676c70001a9SSony Chacko 
167734e8c406SHimanshu Madhani 	for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
1678c70001a9SSony Chacko 		sds_ring = &recv_ctx->sds_rings[ring];
16792cc5752eSManish chopra 		qlcnic_disable_sds_intr(adapter, sds_ring);
1680c70001a9SSony Chacko 		napi_synchronize(&sds_ring->napi);
1681c70001a9SSony Chacko 		napi_disable(&sds_ring->napi);
1682c70001a9SSony Chacko 	}
1683012ec812SHimanshu Madhani 
1684012ec812SHimanshu Madhani 	if ((adapter->flags & QLCNIC_MSIX_ENABLED) &&
1685c2c5e3a0SHimanshu Madhani 	    !adapter->ahw->diag_test &&
1686012ec812SHimanshu Madhani 	    qlcnic_check_multi_tx(adapter)) {
168734e8c406SHimanshu Madhani 		for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
1688012ec812SHimanshu Madhani 			tx_ring = &adapter->tx_ring[ring];
16892cc5752eSManish chopra 			qlcnic_disable_tx_intr(adapter, tx_ring);
1690012ec812SHimanshu Madhani 			napi_synchronize(&tx_ring->napi);
1691012ec812SHimanshu Madhani 			napi_disable(&tx_ring->napi);
1692012ec812SHimanshu Madhani 		}
1693012ec812SHimanshu Madhani 	}
1694c70001a9SSony Chacko }
16954be41e92SSony Chacko 
169653643a75SShahed Shaikh #define QLC_83XX_NORMAL_LB_PKT	(1ULL << 36)
169753643a75SShahed Shaikh #define QLC_83XX_LRO_LB_PKT	(1ULL << 46)
169853643a75SShahed Shaikh 
qlcnic_83xx_is_lb_pkt(u64 sts_data,int lro_pkt)169953643a75SShahed Shaikh static inline int qlcnic_83xx_is_lb_pkt(u64 sts_data, int lro_pkt)
170053643a75SShahed Shaikh {
170153643a75SShahed Shaikh 	if (lro_pkt)
170253643a75SShahed Shaikh 		return (sts_data & QLC_83XX_LRO_LB_PKT) ? 1 : 0;
170353643a75SShahed Shaikh 	else
170453643a75SShahed Shaikh 		return (sts_data & QLC_83XX_NORMAL_LB_PKT) ? 1 : 0;
170553643a75SShahed Shaikh }
170653643a75SShahed Shaikh 
17072b3d7b75SShahed Shaikh #define QLCNIC_ENCAP_LENGTH_MASK	0x7f
17082b3d7b75SShahed Shaikh 
qlcnic_encap_length(u64 sts_data)17092b3d7b75SShahed Shaikh static inline u8 qlcnic_encap_length(u64 sts_data)
17102b3d7b75SShahed Shaikh {
17112b3d7b75SShahed Shaikh 	return sts_data & QLCNIC_ENCAP_LENGTH_MASK;
17122b3d7b75SShahed Shaikh }
17132b3d7b75SShahed Shaikh 
17144be41e92SSony Chacko static struct qlcnic_rx_buffer *
qlcnic_83xx_process_rcv(struct qlcnic_adapter * adapter,struct qlcnic_host_sds_ring * sds_ring,u8 ring,u64 sts_data[])17154be41e92SSony Chacko qlcnic_83xx_process_rcv(struct qlcnic_adapter *adapter,
17164be41e92SSony Chacko 			struct qlcnic_host_sds_ring *sds_ring,
17174be41e92SSony Chacko 			u8 ring, u64 sts_data[])
17184be41e92SSony Chacko {
17194be41e92SSony Chacko 	struct net_device *netdev = adapter->netdev;
17204be41e92SSony Chacko 	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
17214be41e92SSony Chacko 	struct qlcnic_rx_buffer *buffer;
17224be41e92SSony Chacko 	struct sk_buff *skb;
17234be41e92SSony Chacko 	struct qlcnic_host_rds_ring *rds_ring;
172453643a75SShahed Shaikh 	int index, length, cksum, is_lb_pkt;
1725b3f7de83SSucheta Chakraborty 	u16 vid = 0xffff;
1726b3f7de83SSucheta Chakraborty 	int err;
17274be41e92SSony Chacko 
17284be41e92SSony Chacko 	if (unlikely(ring >= adapter->max_rds_rings))
17294be41e92SSony Chacko 		return NULL;
17304be41e92SSony Chacko 
17314be41e92SSony Chacko 	rds_ring = &recv_ctx->rds_rings[ring];
17324be41e92SSony Chacko 
17334be41e92SSony Chacko 	index = qlcnic_83xx_hndl(sts_data[0]);
17344be41e92SSony Chacko 	if (unlikely(index >= rds_ring->num_desc))
17354be41e92SSony Chacko 		return NULL;
17364be41e92SSony Chacko 
17374be41e92SSony Chacko 	buffer = &rds_ring->rx_buf_arr[index];
17384be41e92SSony Chacko 	length = qlcnic_83xx_pktln(sts_data[0]);
17394be41e92SSony Chacko 	cksum  = qlcnic_83xx_csum_status(sts_data[1]);
17404be41e92SSony Chacko 	skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum);
17414be41e92SSony Chacko 	if (!skb)
17424be41e92SSony Chacko 		return buffer;
17434be41e92SSony Chacko 
17444be41e92SSony Chacko 	if (length > rds_ring->skb_size)
17454be41e92SSony Chacko 		skb_put(skb, rds_ring->skb_size);
17464be41e92SSony Chacko 	else
17474be41e92SSony Chacko 		skb_put(skb, length);
17484be41e92SSony Chacko 
1749b3f7de83SSucheta Chakraborty 	err = qlcnic_check_rx_tagging(adapter, skb, &vid);
1750b3f7de83SSucheta Chakraborty 
1751b3f7de83SSucheta Chakraborty 	if (adapter->rx_mac_learn) {
1752b3f7de83SSucheta Chakraborty 		is_lb_pkt = qlcnic_83xx_is_lb_pkt(sts_data[1], 0);
1753b3f7de83SSucheta Chakraborty 		qlcnic_add_lb_filter(adapter, skb, is_lb_pkt, vid);
1754b3f7de83SSucheta Chakraborty 	}
1755b3f7de83SSucheta Chakraborty 
1756b3f7de83SSucheta Chakraborty 	if (unlikely(err)) {
17574be41e92SSony Chacko 		adapter->stats.rxdropped++;
17584be41e92SSony Chacko 		dev_kfree_skb(skb);
17594be41e92SSony Chacko 		return buffer;
17604be41e92SSony Chacko 	}
17614be41e92SSony Chacko 
17624be41e92SSony Chacko 	skb->protocol = eth_type_trans(skb, netdev);
17634be41e92SSony Chacko 
17642b3d7b75SShahed Shaikh 	if (qlcnic_encap_length(sts_data[1]) &&
17652b3d7b75SShahed Shaikh 	    skb->ip_summed == CHECKSUM_UNNECESSARY) {
176671d7a277STom Herbert 		skb->csum_level = 1;
17672b3d7b75SShahed Shaikh 		adapter->stats.encap_rx_csummed++;
17682b3d7b75SShahed Shaikh 	}
17692b3d7b75SShahed Shaikh 
17704be41e92SSony Chacko 	if (vid != 0xffff)
177186a9bad3SPatrick McHardy 		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid);
17724be41e92SSony Chacko 
17734be41e92SSony Chacko 	napi_gro_receive(&sds_ring->napi, skb);
17744be41e92SSony Chacko 
17754be41e92SSony Chacko 	adapter->stats.rx_pkts++;
17764be41e92SSony Chacko 	adapter->stats.rxbytes += length;
17774be41e92SSony Chacko 
17784be41e92SSony Chacko 	return buffer;
17794be41e92SSony Chacko }
17804be41e92SSony Chacko 
17814be41e92SSony Chacko static struct qlcnic_rx_buffer *
qlcnic_83xx_process_lro(struct qlcnic_adapter * adapter,u8 ring,u64 sts_data[])17824be41e92SSony Chacko qlcnic_83xx_process_lro(struct qlcnic_adapter *adapter,
17834be41e92SSony Chacko 			u8 ring, u64 sts_data[])
17844be41e92SSony Chacko {
17854be41e92SSony Chacko 	struct net_device *netdev = adapter->netdev;
17864be41e92SSony Chacko 	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
17874be41e92SSony Chacko 	struct qlcnic_rx_buffer *buffer;
17884be41e92SSony Chacko 	struct sk_buff *skb;
17894be41e92SSony Chacko 	struct qlcnic_host_rds_ring *rds_ring;
17904be41e92SSony Chacko 	struct iphdr *iph;
17914be41e92SSony Chacko 	struct ipv6hdr *ipv6h;
17924be41e92SSony Chacko 	struct tcphdr *th;
17934be41e92SSony Chacko 	bool push;
17944be41e92SSony Chacko 	int l2_hdr_offset, l4_hdr_offset;
179553643a75SShahed Shaikh 	int index, is_lb_pkt;
179699e85879SShahed Shaikh 	u16 lro_length, length, data_offset, gso_size;
1797b3f7de83SSucheta Chakraborty 	u16 vid = 0xffff;
1798b3f7de83SSucheta Chakraborty 	int err;
17994be41e92SSony Chacko 
1800462bed48SManish Chopra 	if (unlikely(ring >= adapter->max_rds_rings))
18014be41e92SSony Chacko 		return NULL;
18024be41e92SSony Chacko 
18034be41e92SSony Chacko 	rds_ring = &recv_ctx->rds_rings[ring];
18044be41e92SSony Chacko 
18054be41e92SSony Chacko 	index = qlcnic_83xx_hndl(sts_data[0]);
1806462bed48SManish Chopra 	if (unlikely(index >= rds_ring->num_desc))
18074be41e92SSony Chacko 		return NULL;
18084be41e92SSony Chacko 
18094be41e92SSony Chacko 	buffer = &rds_ring->rx_buf_arr[index];
18104be41e92SSony Chacko 
18114be41e92SSony Chacko 	lro_length = qlcnic_83xx_lro_pktln(sts_data[0]);
18124be41e92SSony Chacko 	l2_hdr_offset = qlcnic_83xx_l2_hdr_off(sts_data[1]);
18134be41e92SSony Chacko 	l4_hdr_offset = qlcnic_83xx_l4_hdr_off(sts_data[1]);
18144be41e92SSony Chacko 	push = qlcnic_83xx_is_psh_bit(sts_data[1]);
18154be41e92SSony Chacko 
18164be41e92SSony Chacko 	skb = qlcnic_process_rxbuf(adapter, rds_ring, index, STATUS_CKSUM_OK);
18174be41e92SSony Chacko 	if (!skb)
18184be41e92SSony Chacko 		return buffer;
181953643a75SShahed Shaikh 
18204be41e92SSony Chacko 	if (qlcnic_83xx_is_tstamp(sts_data[1]))
18214be41e92SSony Chacko 		data_offset = l4_hdr_offset + QLCNIC_TCP_TS_HDR_SIZE;
18224be41e92SSony Chacko 	else
18234be41e92SSony Chacko 		data_offset = l4_hdr_offset + QLCNIC_TCP_HDR_SIZE;
18244be41e92SSony Chacko 
18254be41e92SSony Chacko 	skb_put(skb, lro_length + data_offset);
18264be41e92SSony Chacko 	skb_pull(skb, l2_hdr_offset);
18274be41e92SSony Chacko 
1828b3f7de83SSucheta Chakraborty 	err = qlcnic_check_rx_tagging(adapter, skb, &vid);
1829b3f7de83SSucheta Chakraborty 
1830b3f7de83SSucheta Chakraborty 	if (adapter->rx_mac_learn) {
1831b3f7de83SSucheta Chakraborty 		is_lb_pkt = qlcnic_83xx_is_lb_pkt(sts_data[1], 1);
1832b3f7de83SSucheta Chakraborty 		qlcnic_add_lb_filter(adapter, skb, is_lb_pkt, vid);
1833b3f7de83SSucheta Chakraborty 	}
1834b3f7de83SSucheta Chakraborty 
1835b3f7de83SSucheta Chakraborty 	if (unlikely(err)) {
18364be41e92SSony Chacko 		adapter->stats.rxdropped++;
18374be41e92SSony Chacko 		dev_kfree_skb(skb);
18384be41e92SSony Chacko 		return buffer;
18394be41e92SSony Chacko 	}
18404be41e92SSony Chacko 
18414be41e92SSony Chacko 	skb->protocol = eth_type_trans(skb, netdev);
18424be41e92SSony Chacko 	if (ntohs(skb->protocol) == ETH_P_IPV6) {
18434be41e92SSony Chacko 		ipv6h = (struct ipv6hdr *)skb->data;
18444be41e92SSony Chacko 		th = (struct tcphdr *)(skb->data + sizeof(struct ipv6hdr));
18454be41e92SSony Chacko 
18464be41e92SSony Chacko 		length = (th->doff << 2) + lro_length;
18474be41e92SSony Chacko 		ipv6h->payload_len = htons(length);
18484be41e92SSony Chacko 	} else {
18494be41e92SSony Chacko 		iph = (struct iphdr *)skb->data;
18504be41e92SSony Chacko 		th = (struct tcphdr *)(skb->data + (iph->ihl << 2));
18514be41e92SSony Chacko 		length = (iph->ihl << 2) + (th->doff << 2) + lro_length;
18521bcac3b0SLi RongQing 		csum_replace2(&iph->check, iph->tot_len, htons(length));
18534be41e92SSony Chacko 		iph->tot_len = htons(length);
18544be41e92SSony Chacko 	}
18554be41e92SSony Chacko 
18564be41e92SSony Chacko 	th->psh = push;
18574be41e92SSony Chacko 	length = skb->len;
18584be41e92SSony Chacko 
185999e85879SShahed Shaikh 	if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP) {
186099e85879SShahed Shaikh 		gso_size = qlcnic_83xx_get_lro_sts_mss(sts_data[0]);
186199e85879SShahed Shaikh 		skb_shinfo(skb)->gso_size = gso_size;
186299e85879SShahed Shaikh 		if (skb->protocol == htons(ETH_P_IPV6))
186399e85879SShahed Shaikh 			skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
186499e85879SShahed Shaikh 		else
186599e85879SShahed Shaikh 			skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
186699e85879SShahed Shaikh 	}
186799e85879SShahed Shaikh 
18684be41e92SSony Chacko 	if (vid != 0xffff)
186986a9bad3SPatrick McHardy 		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid);
18704be41e92SSony Chacko 
18714be41e92SSony Chacko 	netif_receive_skb(skb);
18724be41e92SSony Chacko 
18734be41e92SSony Chacko 	adapter->stats.lro_pkts++;
18744be41e92SSony Chacko 	adapter->stats.lrobytes += length;
18754be41e92SSony Chacko 	return buffer;
18764be41e92SSony Chacko }
18774be41e92SSony Chacko 
qlcnic_83xx_process_rcv_ring(struct qlcnic_host_sds_ring * sds_ring,int max)18784be41e92SSony Chacko static int qlcnic_83xx_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring,
18794be41e92SSony Chacko 					int max)
18804be41e92SSony Chacko {
18814be41e92SSony Chacko 	struct qlcnic_host_rds_ring *rds_ring;
18824be41e92SSony Chacko 	struct qlcnic_adapter *adapter = sds_ring->adapter;
18834be41e92SSony Chacko 	struct list_head *cur;
18844be41e92SSony Chacko 	struct status_desc *desc;
18854be41e92SSony Chacko 	struct qlcnic_rx_buffer *rxbuf = NULL;
18864be41e92SSony Chacko 	u8 ring;
18874be41e92SSony Chacko 	u64 sts_data[2];
18884be41e92SSony Chacko 	int count = 0, opcode;
18894be41e92SSony Chacko 	u32 consumer = sds_ring->consumer;
18904be41e92SSony Chacko 
18914be41e92SSony Chacko 	while (count < max) {
18924be41e92SSony Chacko 		desc = &sds_ring->desc_head[consumer];
18934be41e92SSony Chacko 		sts_data[1] = le64_to_cpu(desc->status_desc_data[1]);
18944be41e92SSony Chacko 		opcode = qlcnic_83xx_opcode(sts_data[1]);
18954be41e92SSony Chacko 		if (!opcode)
18964be41e92SSony Chacko 			break;
18974be41e92SSony Chacko 		sts_data[0] = le64_to_cpu(desc->status_desc_data[0]);
18984be41e92SSony Chacko 		ring = QLCNIC_FETCH_RING_ID(sts_data[0]);
18994be41e92SSony Chacko 
19004be41e92SSony Chacko 		switch (opcode) {
19014be41e92SSony Chacko 		case QLC_83XX_REG_DESC:
19024be41e92SSony Chacko 			rxbuf = qlcnic_83xx_process_rcv(adapter, sds_ring,
19034be41e92SSony Chacko 							ring, sts_data);
19044be41e92SSony Chacko 			break;
19054be41e92SSony Chacko 		case QLC_83XX_LRO_DESC:
19064be41e92SSony Chacko 			rxbuf = qlcnic_83xx_process_lro(adapter, ring,
19074be41e92SSony Chacko 							sts_data);
19084be41e92SSony Chacko 			break;
19094be41e92SSony Chacko 		default:
19104be41e92SSony Chacko 			dev_info(&adapter->pdev->dev,
19110b1587b1SMasanari Iida 				 "Unknown opcode: 0x%x\n", opcode);
19124be41e92SSony Chacko 			goto skip;
19134be41e92SSony Chacko 		}
19144be41e92SSony Chacko 
19154be41e92SSony Chacko 		if (likely(rxbuf))
19164be41e92SSony Chacko 			list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]);
19174be41e92SSony Chacko 		else
19184be41e92SSony Chacko 			adapter->stats.null_rxbuf++;
19194be41e92SSony Chacko skip:
19204be41e92SSony Chacko 		desc = &sds_ring->desc_head[consumer];
19214be41e92SSony Chacko 		/* Reset the descriptor */
19224be41e92SSony Chacko 		desc->status_desc_data[1] = 0;
19234be41e92SSony Chacko 		consumer = get_next_index(consumer, sds_ring->num_desc);
19244be41e92SSony Chacko 		count++;
19254be41e92SSony Chacko 	}
19264be41e92SSony Chacko 	for (ring = 0; ring < adapter->max_rds_rings; ring++) {
19274be41e92SSony Chacko 		rds_ring = &adapter->recv_ctx->rds_rings[ring];
19284be41e92SSony Chacko 		if (!list_empty(&sds_ring->free_list[ring])) {
19294be41e92SSony Chacko 			list_for_each(cur, &sds_ring->free_list[ring]) {
19304be41e92SSony Chacko 				rxbuf = list_entry(cur, struct qlcnic_rx_buffer,
19314be41e92SSony Chacko 						   list);
19324be41e92SSony Chacko 				qlcnic_alloc_rx_skb(adapter, rds_ring, rxbuf);
19334be41e92SSony Chacko 			}
19344be41e92SSony Chacko 			spin_lock(&rds_ring->lock);
19354be41e92SSony Chacko 			list_splice_tail_init(&sds_ring->free_list[ring],
19364be41e92SSony Chacko 					      &rds_ring->free_list);
19374be41e92SSony Chacko 			spin_unlock(&rds_ring->lock);
19384be41e92SSony Chacko 		}
19394be41e92SSony Chacko 		qlcnic_post_rx_buffers_nodb(adapter, rds_ring, ring);
19404be41e92SSony Chacko 	}
19414be41e92SSony Chacko 	if (count) {
19424be41e92SSony Chacko 		sds_ring->consumer = consumer;
19434be41e92SSony Chacko 		writel(consumer, sds_ring->crb_sts_consumer);
19444be41e92SSony Chacko 	}
19454be41e92SSony Chacko 	return count;
19464be41e92SSony Chacko }
19474be41e92SSony Chacko 
qlcnic_83xx_msix_sriov_vf_poll(struct napi_struct * napi,int budget)1948da6c8063SRajesh Borundia static int qlcnic_83xx_msix_sriov_vf_poll(struct napi_struct *napi, int budget)
1949da6c8063SRajesh Borundia {
1950da6c8063SRajesh Borundia 	int tx_complete;
1951da6c8063SRajesh Borundia 	int work_done;
1952da6c8063SRajesh Borundia 	struct qlcnic_host_sds_ring *sds_ring;
1953da6c8063SRajesh Borundia 	struct qlcnic_adapter *adapter;
1954da6c8063SRajesh Borundia 	struct qlcnic_host_tx_ring *tx_ring;
1955da6c8063SRajesh Borundia 
1956da6c8063SRajesh Borundia 	sds_ring = container_of(napi, struct qlcnic_host_sds_ring, napi);
1957da6c8063SRajesh Borundia 	adapter = sds_ring->adapter;
1958da6c8063SRajesh Borundia 	/* tx ring count = 1 */
1959da6c8063SRajesh Borundia 	tx_ring = adapter->tx_ring;
1960da6c8063SRajesh Borundia 
1961da6c8063SRajesh Borundia 	tx_complete = qlcnic_process_cmd_ring(adapter, tx_ring, budget);
1962da6c8063SRajesh Borundia 	work_done = qlcnic_83xx_process_rcv_ring(sds_ring, budget);
1963f31ec95fSShahed Shaikh 
1964f31ec95fSShahed Shaikh 	/* Check if we need a repoll */
1965f31ec95fSShahed Shaikh 	if (!tx_complete)
1966f31ec95fSShahed Shaikh 		work_done = budget;
1967f31ec95fSShahed Shaikh 
1968f31ec95fSShahed Shaikh 	if (work_done < budget) {
19696ad20165SEric Dumazet 		napi_complete_done(&sds_ring->napi, work_done);
19702cc5752eSManish chopra 		qlcnic_enable_sds_intr(adapter, sds_ring);
1971da6c8063SRajesh Borundia 	}
1972da6c8063SRajesh Borundia 
1973da6c8063SRajesh Borundia 	return work_done;
1974da6c8063SRajesh Borundia }
1975da6c8063SRajesh Borundia 
qlcnic_83xx_poll(struct napi_struct * napi,int budget)19764be41e92SSony Chacko static int qlcnic_83xx_poll(struct napi_struct *napi, int budget)
19774be41e92SSony Chacko {
19784be41e92SSony Chacko 	int tx_complete;
19794be41e92SSony Chacko 	int work_done;
19804be41e92SSony Chacko 	struct qlcnic_host_sds_ring *sds_ring;
19814be41e92SSony Chacko 	struct qlcnic_adapter *adapter;
19824be41e92SSony Chacko 	struct qlcnic_host_tx_ring *tx_ring;
19834be41e92SSony Chacko 
19844be41e92SSony Chacko 	sds_ring = container_of(napi, struct qlcnic_host_sds_ring, napi);
19854be41e92SSony Chacko 	adapter = sds_ring->adapter;
19864be41e92SSony Chacko 	/* tx ring count = 1 */
19874be41e92SSony Chacko 	tx_ring = adapter->tx_ring;
19884be41e92SSony Chacko 
19894be41e92SSony Chacko 	tx_complete = qlcnic_process_cmd_ring(adapter, tx_ring, budget);
19904be41e92SSony Chacko 	work_done = qlcnic_83xx_process_rcv_ring(sds_ring, budget);
1991f31ec95fSShahed Shaikh 
1992f31ec95fSShahed Shaikh 	/* Check if we need a repoll */
1993f31ec95fSShahed Shaikh 	if (!tx_complete)
1994f31ec95fSShahed Shaikh 		work_done = budget;
1995f31ec95fSShahed Shaikh 
1996f31ec95fSShahed Shaikh 	if (work_done < budget) {
19976ad20165SEric Dumazet 		napi_complete_done(&sds_ring->napi, work_done);
19982cc5752eSManish chopra 		qlcnic_enable_sds_intr(adapter, sds_ring);
19994be41e92SSony Chacko 	}
20004be41e92SSony Chacko 
20014be41e92SSony Chacko 	return work_done;
20024be41e92SSony Chacko }
20034be41e92SSony Chacko 
qlcnic_83xx_msix_tx_poll(struct napi_struct * napi,int budget)20044be41e92SSony Chacko static int qlcnic_83xx_msix_tx_poll(struct napi_struct *napi, int budget)
20054be41e92SSony Chacko {
20064be41e92SSony Chacko 	int work_done;
20074be41e92SSony Chacko 	struct qlcnic_host_tx_ring *tx_ring;
20084be41e92SSony Chacko 	struct qlcnic_adapter *adapter;
20094be41e92SSony Chacko 
20104be41e92SSony Chacko 	tx_ring = container_of(napi, struct qlcnic_host_tx_ring, napi);
20114be41e92SSony Chacko 	adapter = tx_ring->adapter;
20124be41e92SSony Chacko 	work_done = qlcnic_process_cmd_ring(adapter, tx_ring, budget);
20134be41e92SSony Chacko 	if (work_done) {
20144be41e92SSony Chacko 		napi_complete(&tx_ring->napi);
20154be41e92SSony Chacko 		if (test_bit(__QLCNIC_DEV_UP , &adapter->state))
20162cc5752eSManish chopra 			qlcnic_enable_tx_intr(adapter, tx_ring);
2017f31ec95fSShahed Shaikh 	} else {
2018f31ec95fSShahed Shaikh 		/* need a repoll */
2019f31ec95fSShahed Shaikh 		work_done = budget;
20204be41e92SSony Chacko 	}
20214be41e92SSony Chacko 
20224be41e92SSony Chacko 	return work_done;
20234be41e92SSony Chacko }
20244be41e92SSony Chacko 
qlcnic_83xx_rx_poll(struct napi_struct * napi,int budget)20254be41e92SSony Chacko static int qlcnic_83xx_rx_poll(struct napi_struct *napi, int budget)
20264be41e92SSony Chacko {
20274be41e92SSony Chacko 	int work_done;
20284be41e92SSony Chacko 	struct qlcnic_host_sds_ring *sds_ring;
20294be41e92SSony Chacko 	struct qlcnic_adapter *adapter;
20304be41e92SSony Chacko 
20314be41e92SSony Chacko 	sds_ring = container_of(napi, struct qlcnic_host_sds_ring, napi);
20324be41e92SSony Chacko 	adapter = sds_ring->adapter;
20334be41e92SSony Chacko 	work_done = qlcnic_83xx_process_rcv_ring(sds_ring, budget);
20344be41e92SSony Chacko 	if (work_done < budget) {
20356ad20165SEric Dumazet 		napi_complete_done(&sds_ring->napi, work_done);
20364be41e92SSony Chacko 		if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
20372cc5752eSManish chopra 			qlcnic_enable_sds_intr(adapter, sds_ring);
20384be41e92SSony Chacko 	}
20394be41e92SSony Chacko 
20404be41e92SSony Chacko 	return work_done;
20414be41e92SSony Chacko }
20424be41e92SSony Chacko 
qlcnic_83xx_napi_enable(struct qlcnic_adapter * adapter)20434be41e92SSony Chacko void qlcnic_83xx_napi_enable(struct qlcnic_adapter *adapter)
20444be41e92SSony Chacko {
20454be41e92SSony Chacko 	int ring;
20464be41e92SSony Chacko 	struct qlcnic_host_sds_ring *sds_ring;
20474be41e92SSony Chacko 	struct qlcnic_host_tx_ring *tx_ring;
20484be41e92SSony Chacko 	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
20494be41e92SSony Chacko 
20504be41e92SSony Chacko 	if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
20514be41e92SSony Chacko 		return;
20524be41e92SSony Chacko 
205334e8c406SHimanshu Madhani 	for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
20544be41e92SSony Chacko 		sds_ring = &recv_ctx->sds_rings[ring];
20554be41e92SSony Chacko 		napi_enable(&sds_ring->napi);
2056ac166700SHimanshu Madhani 		if (adapter->flags & QLCNIC_MSIX_ENABLED)
20572cc5752eSManish chopra 			qlcnic_enable_sds_intr(adapter, sds_ring);
20584be41e92SSony Chacko 	}
20594be41e92SSony Chacko 
2060da6c8063SRajesh Borundia 	if ((adapter->flags & QLCNIC_MSIX_ENABLED) &&
2061da6c8063SRajesh Borundia 	    !(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
206234e8c406SHimanshu Madhani 		for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
20634be41e92SSony Chacko 			tx_ring = &adapter->tx_ring[ring];
20644be41e92SSony Chacko 			napi_enable(&tx_ring->napi);
20652cc5752eSManish chopra 			qlcnic_enable_tx_intr(adapter, tx_ring);
20664be41e92SSony Chacko 		}
20674be41e92SSony Chacko 	}
20684be41e92SSony Chacko }
20694be41e92SSony Chacko 
qlcnic_83xx_napi_disable(struct qlcnic_adapter * adapter)20704be41e92SSony Chacko void qlcnic_83xx_napi_disable(struct qlcnic_adapter *adapter)
20714be41e92SSony Chacko {
20724be41e92SSony Chacko 	int ring;
20734be41e92SSony Chacko 	struct qlcnic_host_sds_ring *sds_ring;
20744be41e92SSony Chacko 	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
20754be41e92SSony Chacko 	struct qlcnic_host_tx_ring *tx_ring;
20764be41e92SSony Chacko 
20774be41e92SSony Chacko 	if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
20784be41e92SSony Chacko 		return;
20794be41e92SSony Chacko 
208034e8c406SHimanshu Madhani 	for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
20814be41e92SSony Chacko 		sds_ring = &recv_ctx->sds_rings[ring];
2082ac166700SHimanshu Madhani 		if (adapter->flags & QLCNIC_MSIX_ENABLED)
20832cc5752eSManish chopra 			qlcnic_disable_sds_intr(adapter, sds_ring);
20844be41e92SSony Chacko 		napi_synchronize(&sds_ring->napi);
20854be41e92SSony Chacko 		napi_disable(&sds_ring->napi);
20864be41e92SSony Chacko 	}
20874be41e92SSony Chacko 
2088da6c8063SRajesh Borundia 	if ((adapter->flags & QLCNIC_MSIX_ENABLED) &&
2089da6c8063SRajesh Borundia 	    !(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
209034e8c406SHimanshu Madhani 		for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
20914be41e92SSony Chacko 			tx_ring = &adapter->tx_ring[ring];
20922cc5752eSManish chopra 			qlcnic_disable_tx_intr(adapter, tx_ring);
20934be41e92SSony Chacko 			napi_synchronize(&tx_ring->napi);
20944be41e92SSony Chacko 			napi_disable(&tx_ring->napi);
20954be41e92SSony Chacko 		}
20964be41e92SSony Chacko 	}
20974be41e92SSony Chacko }
20984be41e92SSony Chacko 
qlcnic_83xx_napi_add(struct qlcnic_adapter * adapter,struct net_device * netdev)20994be41e92SSony Chacko int qlcnic_83xx_napi_add(struct qlcnic_adapter *adapter,
21004be41e92SSony Chacko 			 struct net_device *netdev)
21014be41e92SSony Chacko {
2102df95fc44SMichal Schmidt 	int ring;
21034be41e92SSony Chacko 	struct qlcnic_host_sds_ring *sds_ring;
21044be41e92SSony Chacko 	struct qlcnic_host_tx_ring *tx_ring;
21054be41e92SSony Chacko 	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
21064be41e92SSony Chacko 
210734e8c406SHimanshu Madhani 	if (qlcnic_alloc_sds_rings(recv_ctx, adapter->drv_sds_rings))
21084be41e92SSony Chacko 		return -ENOMEM;
21094be41e92SSony Chacko 
211034e8c406SHimanshu Madhani 	for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
21114be41e92SSony Chacko 		sds_ring = &recv_ctx->sds_rings[ring];
2112da6c8063SRajesh Borundia 		if (adapter->flags & QLCNIC_MSIX_ENABLED) {
2113df95fc44SMichal Schmidt 			if (!(adapter->flags & QLCNIC_TX_INTR_SHARED))
21144be41e92SSony Chacko 				netif_napi_add(netdev, &sds_ring->napi,
2115b48b89f9SJakub Kicinski 					       qlcnic_83xx_rx_poll);
2116df95fc44SMichal Schmidt 			else
2117da6c8063SRajesh Borundia 				netif_napi_add(netdev, &sds_ring->napi,
2118b48b89f9SJakub Kicinski 					       qlcnic_83xx_msix_sriov_vf_poll);
2119da6c8063SRajesh Borundia 
2120da6c8063SRajesh Borundia 		} else {
21214be41e92SSony Chacko 			netif_napi_add(netdev, &sds_ring->napi,
2122b48b89f9SJakub Kicinski 				       qlcnic_83xx_poll);
21234be41e92SSony Chacko 		}
2124da6c8063SRajesh Borundia 	}
21254be41e92SSony Chacko 
21264be41e92SSony Chacko 	if (qlcnic_alloc_tx_rings(adapter, netdev)) {
21274be41e92SSony Chacko 		qlcnic_free_sds_rings(recv_ctx);
21284be41e92SSony Chacko 		return -ENOMEM;
21294be41e92SSony Chacko 	}
21304be41e92SSony Chacko 
2131da6c8063SRajesh Borundia 	if ((adapter->flags & QLCNIC_MSIX_ENABLED) &&
2132da6c8063SRajesh Borundia 	    !(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
213334e8c406SHimanshu Madhani 		for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
21344be41e92SSony Chacko 			tx_ring = &adapter->tx_ring[ring];
213516d083e2SJakub Kicinski 			netif_napi_add_tx(netdev, &tx_ring->napi,
213616d083e2SJakub Kicinski 					  qlcnic_83xx_msix_tx_poll);
21374be41e92SSony Chacko 		}
21384be41e92SSony Chacko 	}
21394be41e92SSony Chacko 
21404be41e92SSony Chacko 	return 0;
21414be41e92SSony Chacko }
21424be41e92SSony Chacko 
qlcnic_83xx_napi_del(struct qlcnic_adapter * adapter)21434be41e92SSony Chacko void qlcnic_83xx_napi_del(struct qlcnic_adapter *adapter)
21444be41e92SSony Chacko {
21454be41e92SSony Chacko 	int ring;
21464be41e92SSony Chacko 	struct qlcnic_host_sds_ring *sds_ring;
21474be41e92SSony Chacko 	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
21484be41e92SSony Chacko 	struct qlcnic_host_tx_ring *tx_ring;
21494be41e92SSony Chacko 
215034e8c406SHimanshu Madhani 	for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
21514be41e92SSony Chacko 		sds_ring = &recv_ctx->sds_rings[ring];
21524be41e92SSony Chacko 		netif_napi_del(&sds_ring->napi);
21534be41e92SSony Chacko 	}
21544be41e92SSony Chacko 
21554be41e92SSony Chacko 	qlcnic_free_sds_rings(adapter->recv_ctx);
21564be41e92SSony Chacko 
2157da6c8063SRajesh Borundia 	if ((adapter->flags & QLCNIC_MSIX_ENABLED) &&
2158da6c8063SRajesh Borundia 	    !(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
215934e8c406SHimanshu Madhani 		for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
21604be41e92SSony Chacko 			tx_ring = &adapter->tx_ring[ring];
21614be41e92SSony Chacko 			netif_napi_del(&tx_ring->napi);
21624be41e92SSony Chacko 		}
21634be41e92SSony Chacko 	}
21644be41e92SSony Chacko 
21654be41e92SSony Chacko 	qlcnic_free_tx_rings(adapter);
21664be41e92SSony Chacko }
21674be41e92SSony Chacko 
qlcnic_83xx_process_rcv_diag(struct qlcnic_adapter * adapter,int ring,u64 sts_data[])216821041400Sstephen hemminger static void qlcnic_83xx_process_rcv_diag(struct qlcnic_adapter *adapter,
21694be41e92SSony Chacko 					 int ring, u64 sts_data[])
21704be41e92SSony Chacko {
21714be41e92SSony Chacko 	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
21724be41e92SSony Chacko 	struct sk_buff *skb;
21734be41e92SSony Chacko 	struct qlcnic_host_rds_ring *rds_ring;
21744be41e92SSony Chacko 	int index, length;
21754be41e92SSony Chacko 
21764be41e92SSony Chacko 	if (unlikely(ring >= adapter->max_rds_rings))
21774be41e92SSony Chacko 		return;
21784be41e92SSony Chacko 
21794be41e92SSony Chacko 	rds_ring = &recv_ctx->rds_rings[ring];
21804be41e92SSony Chacko 	index = qlcnic_83xx_hndl(sts_data[0]);
21814be41e92SSony Chacko 	if (unlikely(index >= rds_ring->num_desc))
21824be41e92SSony Chacko 		return;
21834be41e92SSony Chacko 
21844be41e92SSony Chacko 	length = qlcnic_83xx_pktln(sts_data[0]);
21854be41e92SSony Chacko 
21864be41e92SSony Chacko 	skb = qlcnic_process_rxbuf(adapter, rds_ring, index, STATUS_CKSUM_OK);
21874be41e92SSony Chacko 	if (!skb)
21884be41e92SSony Chacko 		return;
21894be41e92SSony Chacko 
21904be41e92SSony Chacko 	if (length > rds_ring->skb_size)
21914be41e92SSony Chacko 		skb_put(skb, rds_ring->skb_size);
21924be41e92SSony Chacko 	else
21934be41e92SSony Chacko 		skb_put(skb, length);
21944be41e92SSony Chacko 
21954be41e92SSony Chacko 	if (!qlcnic_check_loopback_buff(skb->data, adapter->mac_addr))
21964be41e92SSony Chacko 		adapter->ahw->diag_cnt++;
21974be41e92SSony Chacko 	else
21984be41e92SSony Chacko 		dump_skb(skb, adapter);
21994be41e92SSony Chacko 
22004be41e92SSony Chacko 	dev_kfree_skb_any(skb);
22014be41e92SSony Chacko 	return;
22024be41e92SSony Chacko }
22034be41e92SSony Chacko 
qlcnic_83xx_process_rcv_ring_diag(struct qlcnic_host_sds_ring * sds_ring)22044be41e92SSony Chacko void qlcnic_83xx_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring)
22054be41e92SSony Chacko {
22064be41e92SSony Chacko 	struct qlcnic_adapter *adapter = sds_ring->adapter;
22074be41e92SSony Chacko 	struct status_desc *desc;
22084be41e92SSony Chacko 	u64 sts_data[2];
22094be41e92SSony Chacko 	int ring, opcode;
22104be41e92SSony Chacko 	u32 consumer = sds_ring->consumer;
22114be41e92SSony Chacko 
22124be41e92SSony Chacko 	desc = &sds_ring->desc_head[consumer];
22134be41e92SSony Chacko 	sts_data[0] = le64_to_cpu(desc->status_desc_data[0]);
22144be41e92SSony Chacko 	sts_data[1] = le64_to_cpu(desc->status_desc_data[1]);
22154be41e92SSony Chacko 	opcode = qlcnic_83xx_opcode(sts_data[1]);
22164be41e92SSony Chacko 	if (!opcode)
22174be41e92SSony Chacko 		return;
22184be41e92SSony Chacko 
22195b4d10f5SDan Carpenter 	ring = QLCNIC_FETCH_RING_ID(sts_data[0]);
22204be41e92SSony Chacko 	qlcnic_83xx_process_rcv_diag(adapter, ring, sts_data);
22214be41e92SSony Chacko 	desc = &sds_ring->desc_head[consumer];
22224be41e92SSony Chacko 	desc->status_desc_data[0] = cpu_to_le64(STATUS_OWNER_PHANTOM);
22234be41e92SSony Chacko 	consumer = get_next_index(consumer, sds_ring->num_desc);
22244be41e92SSony Chacko 	sds_ring->consumer = consumer;
22254be41e92SSony Chacko 	writel(consumer, sds_ring->crb_sts_consumer);
22264be41e92SSony Chacko }
2227