xref: /openbmc/linux/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
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) {
321*1f5020acSVladimir 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 
449381709deSShahed Shaikh 	first_desc->tcp_hdr_offset = skb_inner_transport_header(skb) -
450381709deSShahed Shaikh 				     skb->data;
451381709deSShahed Shaikh 	first_desc->ip_hdr_offset = skb_inner_network_offset(skb);
452381709deSShahed Shaikh 
453381709deSShahed Shaikh 	qlcnic_set_tx_flags_opcode(first_desc, flags, opcode);
454381709deSShahed Shaikh 
455381709deSShahed Shaikh 	return 0;
456381709deSShahed Shaikh }
457381709deSShahed 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)458d17dd0d9SSony Chacko static int qlcnic_tx_pkt(struct qlcnic_adapter *adapter,
459012ec812SHimanshu Madhani 			 struct cmd_desc_type0 *first_desc, struct sk_buff *skb,
460012ec812SHimanshu Madhani 			 struct qlcnic_host_tx_ring *tx_ring)
461c70001a9SSony Chacko {
462b25ddb00SMichał Mirosław 	u8 l4proto, opcode = 0, hdr_len = 0, tag_vlan = 0;
463c70001a9SSony Chacko 	u16 flags = 0, vlan_tci = 0;
464d17dd0d9SSony Chacko 	int copied, offset, copy_len, size;
465c70001a9SSony Chacko 	struct cmd_desc_type0 *hwdesc;
466c70001a9SSony Chacko 	struct vlan_ethhdr *vh;
467c70001a9SSony Chacko 	u16 protocol = ntohs(skb->protocol);
468c70001a9SSony Chacko 	u32 producer = tx_ring->producer;
469c70001a9SSony Chacko 
470c70001a9SSony Chacko 	if (protocol == ETH_P_8021Q) {
471*1f5020acSVladimir Oltean 		vh = skb_vlan_eth_hdr(skb);
472381709deSShahed Shaikh 		flags = QLCNIC_FLAGS_VLAN_TAGGED;
473c70001a9SSony Chacko 		vlan_tci = ntohs(vh->h_vlan_TCI);
474c70001a9SSony Chacko 		protocol = ntohs(vh->h_vlan_encapsulated_proto);
475b25ddb00SMichał Mirosław 		tag_vlan = 1;
476df8a39deSJiri Pirko 	} else if (skb_vlan_tag_present(skb)) {
477381709deSShahed Shaikh 		flags = QLCNIC_FLAGS_VLAN_OOB;
478df8a39deSJiri Pirko 		vlan_tci = skb_vlan_tag_get(skb);
479b25ddb00SMichał Mirosław 		tag_vlan = 1;
480c70001a9SSony Chacko 	}
48191b7282bSRajesh Borundia 	if (unlikely(adapter->tx_pvid)) {
482b25ddb00SMichał Mirosław 		if (tag_vlan && !(adapter->flags & QLCNIC_TAGGING_ENABLED))
483c70001a9SSony Chacko 			return -EIO;
484b25ddb00SMichał Mirosław 		if (tag_vlan && (adapter->flags & QLCNIC_TAGGING_ENABLED))
485c70001a9SSony Chacko 			goto set_flags;
486c70001a9SSony Chacko 
487381709deSShahed Shaikh 		flags = QLCNIC_FLAGS_VLAN_OOB;
48891b7282bSRajesh Borundia 		vlan_tci = adapter->tx_pvid;
489c70001a9SSony Chacko 	}
490c70001a9SSony Chacko set_flags:
491c70001a9SSony Chacko 	qlcnic_set_tx_vlan_tci(first_desc, vlan_tci);
492c70001a9SSony Chacko 	qlcnic_set_tx_flags_opcode(first_desc, flags, opcode);
493c70001a9SSony Chacko 
494c70001a9SSony Chacko 	if (*(skb->data) & BIT_0) {
495c70001a9SSony Chacko 		flags |= BIT_0;
496c70001a9SSony Chacko 		memcpy(&first_desc->eth_addr, skb->data, ETH_ALEN);
497c70001a9SSony Chacko 	}
498381709deSShahed Shaikh 	opcode = QLCNIC_TX_ETHER_PKT;
4993eead213SSritej Velaga 	if (skb_is_gso(skb)) {
500504148feSEric Dumazet 		hdr_len = skb_tcp_all_headers(skb);
501c70001a9SSony Chacko 		first_desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
502381709deSShahed Shaikh 		first_desc->hdr_length = hdr_len;
503381709deSShahed Shaikh 		opcode = (protocol == ETH_P_IPV6) ? QLCNIC_TX_TCP_LSO6 :
504381709deSShahed Shaikh 						    QLCNIC_TX_TCP_LSO;
505c70001a9SSony Chacko 
506c70001a9SSony Chacko 		/* For LSO, we need to copy the MAC/IP/TCP headers into
507c70001a9SSony Chacko 		* the descriptor ring */
508c70001a9SSony Chacko 		copied = 0;
509c70001a9SSony Chacko 		offset = 2;
510c70001a9SSony Chacko 
511381709deSShahed Shaikh 		if (flags & QLCNIC_FLAGS_VLAN_OOB) {
512381709deSShahed Shaikh 			first_desc->hdr_length += VLAN_HLEN;
513c70001a9SSony Chacko 			first_desc->tcp_hdr_offset = VLAN_HLEN;
514c70001a9SSony Chacko 			first_desc->ip_hdr_offset = VLAN_HLEN;
515d17dd0d9SSony Chacko 
516c70001a9SSony Chacko 			/* Only in case of TSO on vlan device */
517381709deSShahed Shaikh 			flags |= QLCNIC_FLAGS_VLAN_TAGGED;
518c70001a9SSony Chacko 
519c70001a9SSony Chacko 			/* Create a TSO vlan header template for firmware */
520c70001a9SSony Chacko 			hwdesc = &tx_ring->desc_head[producer];
521c70001a9SSony Chacko 			tx_ring->cmd_buf_arr[producer].skb = NULL;
522c70001a9SSony Chacko 
523c70001a9SSony Chacko 			copy_len = min((int)sizeof(struct cmd_desc_type0) -
524c70001a9SSony Chacko 				       offset, hdr_len + VLAN_HLEN);
525c70001a9SSony Chacko 
526c70001a9SSony Chacko 			vh = (struct vlan_ethhdr *)((char *) hwdesc + 2);
527c70001a9SSony Chacko 			skb_copy_from_linear_data(skb, vh, 12);
528c70001a9SSony Chacko 			vh->h_vlan_proto = htons(ETH_P_8021Q);
529c70001a9SSony Chacko 			vh->h_vlan_TCI = htons(vlan_tci);
530c70001a9SSony Chacko 
531c70001a9SSony Chacko 			skb_copy_from_linear_data_offset(skb, 12,
532d17dd0d9SSony Chacko 							 (char *)vh + 16,
533d17dd0d9SSony Chacko 							 copy_len - 16);
534c70001a9SSony Chacko 			copied = copy_len - VLAN_HLEN;
535c70001a9SSony Chacko 			offset = 0;
536c70001a9SSony Chacko 			producer = get_next_index(producer, tx_ring->num_desc);
537c70001a9SSony Chacko 		}
538c70001a9SSony Chacko 
539c70001a9SSony Chacko 		while (copied < hdr_len) {
540d17dd0d9SSony Chacko 			size = (int)sizeof(struct cmd_desc_type0) - offset;
541d17dd0d9SSony Chacko 			copy_len = min(size, (hdr_len - copied));
542c70001a9SSony Chacko 			hwdesc = &tx_ring->desc_head[producer];
543c70001a9SSony Chacko 			tx_ring->cmd_buf_arr[producer].skb = NULL;
544c70001a9SSony Chacko 			skb_copy_from_linear_data_offset(skb, copied,
545d17dd0d9SSony Chacko 							 (char *)hwdesc +
546d17dd0d9SSony Chacko 							 offset, copy_len);
547c70001a9SSony Chacko 			copied += copy_len;
548c70001a9SSony Chacko 			offset = 0;
549c70001a9SSony Chacko 			producer = get_next_index(producer, tx_ring->num_desc);
550c70001a9SSony Chacko 		}
551c70001a9SSony Chacko 
552c70001a9SSony Chacko 		tx_ring->producer = producer;
553c70001a9SSony Chacko 		smp_mb();
554c70001a9SSony Chacko 		adapter->stats.lso_frames++;
555c70001a9SSony Chacko 
556c70001a9SSony Chacko 	} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
557c70001a9SSony Chacko 		if (protocol == ETH_P_IP) {
558c70001a9SSony Chacko 			l4proto = ip_hdr(skb)->protocol;
559c70001a9SSony Chacko 
560c70001a9SSony Chacko 			if (l4proto == IPPROTO_TCP)
561381709deSShahed Shaikh 				opcode = QLCNIC_TX_TCP_PKT;
562c70001a9SSony Chacko 			else if (l4proto == IPPROTO_UDP)
563381709deSShahed Shaikh 				opcode = QLCNIC_TX_UDP_PKT;
564c70001a9SSony Chacko 		} else if (protocol == ETH_P_IPV6) {
565c70001a9SSony Chacko 			l4proto = ipv6_hdr(skb)->nexthdr;
566c70001a9SSony Chacko 
567c70001a9SSony Chacko 			if (l4proto == IPPROTO_TCP)
568381709deSShahed Shaikh 				opcode = QLCNIC_TX_TCPV6_PKT;
569c70001a9SSony Chacko 			else if (l4proto == IPPROTO_UDP)
570381709deSShahed Shaikh 				opcode = QLCNIC_TX_UDPV6_PKT;
571c70001a9SSony Chacko 		}
572c70001a9SSony Chacko 	}
573c70001a9SSony Chacko 	first_desc->tcp_hdr_offset += skb_transport_offset(skb);
574c70001a9SSony Chacko 	first_desc->ip_hdr_offset += skb_network_offset(skb);
575c70001a9SSony Chacko 	qlcnic_set_tx_flags_opcode(first_desc, flags, opcode);
576c70001a9SSony Chacko 
577c70001a9SSony Chacko 	return 0;
578c70001a9SSony Chacko }
579c70001a9SSony Chacko 
qlcnic_map_tx_skb(struct pci_dev * pdev,struct sk_buff * skb,struct qlcnic_cmd_buffer * pbuf)580d17dd0d9SSony Chacko static int qlcnic_map_tx_skb(struct pci_dev *pdev, struct sk_buff *skb,
581d17dd0d9SSony Chacko 			     struct qlcnic_cmd_buffer *pbuf)
582c70001a9SSony Chacko {
583c70001a9SSony Chacko 	struct qlcnic_skb_frag *nf;
584d7840976SMatthew Wilcox (Oracle) 	skb_frag_t *frag;
585c70001a9SSony Chacko 	int i, nr_frags;
586c70001a9SSony Chacko 	dma_addr_t map;
587c70001a9SSony Chacko 
588c70001a9SSony Chacko 	nr_frags = skb_shinfo(skb)->nr_frags;
589c70001a9SSony Chacko 	nf = &pbuf->frag_array[0];
590c70001a9SSony Chacko 
591a14e3904SChristophe JAILLET 	map = dma_map_single(&pdev->dev, skb->data, skb_headlen(skb),
592a14e3904SChristophe JAILLET 			     DMA_TO_DEVICE);
593a14e3904SChristophe JAILLET 	if (dma_mapping_error(&pdev->dev, map))
594c70001a9SSony Chacko 		goto out_err;
595c70001a9SSony Chacko 
596c70001a9SSony Chacko 	nf->dma = map;
597c70001a9SSony Chacko 	nf->length = skb_headlen(skb);
598c70001a9SSony Chacko 
599c70001a9SSony Chacko 	for (i = 0; i < nr_frags; i++) {
600c70001a9SSony Chacko 		frag = &skb_shinfo(skb)->frags[i];
601c70001a9SSony Chacko 		nf = &pbuf->frag_array[i+1];
602c70001a9SSony Chacko 		map = skb_frag_dma_map(&pdev->dev, frag, 0, skb_frag_size(frag),
603c70001a9SSony Chacko 				       DMA_TO_DEVICE);
604c70001a9SSony Chacko 		if (dma_mapping_error(&pdev->dev, map))
605c70001a9SSony Chacko 			goto unwind;
606c70001a9SSony Chacko 
607c70001a9SSony Chacko 		nf->dma = map;
608c70001a9SSony Chacko 		nf->length = skb_frag_size(frag);
609c70001a9SSony Chacko 	}
610c70001a9SSony Chacko 
611c70001a9SSony Chacko 	return 0;
612c70001a9SSony Chacko 
613c70001a9SSony Chacko unwind:
614c70001a9SSony Chacko 	while (--i >= 0) {
615c70001a9SSony Chacko 		nf = &pbuf->frag_array[i+1];
616a14e3904SChristophe JAILLET 		dma_unmap_page(&pdev->dev, nf->dma, nf->length, DMA_TO_DEVICE);
617c70001a9SSony Chacko 	}
618c70001a9SSony Chacko 
619c70001a9SSony Chacko 	nf = &pbuf->frag_array[0];
620a14e3904SChristophe JAILLET 	dma_unmap_single(&pdev->dev, nf->dma, skb_headlen(skb), DMA_TO_DEVICE);
621c70001a9SSony Chacko 
622c70001a9SSony Chacko out_err:
623c70001a9SSony Chacko 	return -ENOMEM;
624c70001a9SSony Chacko }
625c70001a9SSony Chacko 
qlcnic_unmap_buffers(struct pci_dev * pdev,struct sk_buff * skb,struct qlcnic_cmd_buffer * pbuf)626d17dd0d9SSony Chacko static void qlcnic_unmap_buffers(struct pci_dev *pdev, struct sk_buff *skb,
627c70001a9SSony Chacko 				 struct qlcnic_cmd_buffer *pbuf)
628c70001a9SSony Chacko {
629c70001a9SSony Chacko 	struct qlcnic_skb_frag *nf = &pbuf->frag_array[0];
630d17dd0d9SSony Chacko 	int i, nr_frags = skb_shinfo(skb)->nr_frags;
631c70001a9SSony Chacko 
632c70001a9SSony Chacko 	for (i = 0; i < nr_frags; i++) {
633c70001a9SSony Chacko 		nf = &pbuf->frag_array[i+1];
634a14e3904SChristophe JAILLET 		dma_unmap_page(&pdev->dev, nf->dma, nf->length, DMA_TO_DEVICE);
635c70001a9SSony Chacko 	}
636c70001a9SSony Chacko 
637c70001a9SSony Chacko 	nf = &pbuf->frag_array[0];
638a14e3904SChristophe JAILLET 	dma_unmap_single(&pdev->dev, nf->dma, skb_headlen(skb), DMA_TO_DEVICE);
639c70001a9SSony Chacko 	pbuf->skb = NULL;
640c70001a9SSony Chacko }
641c70001a9SSony Chacko 
qlcnic_clear_cmddesc(u64 * desc)642d17dd0d9SSony Chacko static inline void qlcnic_clear_cmddesc(u64 *desc)
643c70001a9SSony Chacko {
644c70001a9SSony Chacko 	desc[0] = 0ULL;
645c70001a9SSony Chacko 	desc[2] = 0ULL;
646c70001a9SSony Chacko 	desc[7] = 0ULL;
647c70001a9SSony Chacko }
648c70001a9SSony Chacko 
qlcnic_xmit_frame(struct sk_buff * skb,struct net_device * netdev)649d17dd0d9SSony Chacko netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
650c70001a9SSony Chacko {
651c70001a9SSony Chacko 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
652012ec812SHimanshu Madhani 	struct qlcnic_host_tx_ring *tx_ring;
653c70001a9SSony Chacko 	struct qlcnic_cmd_buffer *pbuf;
654c70001a9SSony Chacko 	struct qlcnic_skb_frag *buffrag;
655c70001a9SSony Chacko 	struct cmd_desc_type0 *hwdesc, *first_desc;
656c70001a9SSony Chacko 	struct pci_dev *pdev;
657c70001a9SSony Chacko 	struct ethhdr *phdr;
658d17dd0d9SSony Chacko 	int i, k, frag_count, delta = 0;
659d17dd0d9SSony Chacko 	u32 producer, num_txd;
660381709deSShahed Shaikh 	u16 protocol;
661381709deSShahed Shaikh 	bool l4_is_udp = false;
662c70001a9SSony Chacko 
663c70001a9SSony Chacko 	if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
664012ec812SHimanshu Madhani 		netif_tx_stop_all_queues(netdev);
665c70001a9SSony Chacko 		return NETDEV_TX_BUSY;
666c70001a9SSony Chacko 	}
667c70001a9SSony Chacko 
668c70001a9SSony Chacko 	if (adapter->flags & QLCNIC_MACSPOOF) {
669c70001a9SSony Chacko 		phdr = (struct ethhdr *)skb->data;
670c70001a9SSony Chacko 		if (!ether_addr_equal(phdr->h_source, adapter->mac_addr))
671c70001a9SSony Chacko 			goto drop_packet;
672c70001a9SSony Chacko 	}
673c70001a9SSony Chacko 
674012ec812SHimanshu Madhani 	tx_ring = &adapter->tx_ring[skb_get_queue_mapping(skb)];
675012ec812SHimanshu Madhani 	num_txd = tx_ring->num_desc;
676012ec812SHimanshu Madhani 
677c70001a9SSony Chacko 	frag_count = skb_shinfo(skb)->nr_frags + 1;
678012ec812SHimanshu Madhani 
679c70001a9SSony Chacko 	/* 14 frags supported for normal packet and
680c70001a9SSony Chacko 	 * 32 frags supported for TSO packet
681c70001a9SSony Chacko 	 */
682c70001a9SSony Chacko 	if (!skb_is_gso(skb) && frag_count > QLCNIC_MAX_FRAGS_PER_TX) {
683c70001a9SSony Chacko 		for (i = 0; i < (frag_count - QLCNIC_MAX_FRAGS_PER_TX); i++)
684c70001a9SSony Chacko 			delta += skb_frag_size(&skb_shinfo(skb)->frags[i]);
685c70001a9SSony Chacko 
686c70001a9SSony Chacko 		if (!__pskb_pull_tail(skb, delta))
687c70001a9SSony Chacko 			goto drop_packet;
688c70001a9SSony Chacko 
689c70001a9SSony Chacko 		frag_count = 1 + skb_shinfo(skb)->nr_frags;
690c70001a9SSony Chacko 	}
691c70001a9SSony Chacko 
692c70001a9SSony Chacko 	if (unlikely(qlcnic_tx_avail(tx_ring) <= TX_STOP_THRESH)) {
693012ec812SHimanshu Madhani 		netif_tx_stop_queue(tx_ring->txq);
694d17dd0d9SSony Chacko 		if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) {
695012ec812SHimanshu Madhani 			netif_tx_start_queue(tx_ring->txq);
696d17dd0d9SSony Chacko 		} else {
697f27c75b3SHimanshu Madhani 			tx_ring->tx_stats.xmit_off++;
698c70001a9SSony Chacko 			return NETDEV_TX_BUSY;
699c70001a9SSony Chacko 		}
700c70001a9SSony Chacko 	}
701c70001a9SSony Chacko 
702c70001a9SSony Chacko 	producer = tx_ring->producer;
703c70001a9SSony Chacko 	pbuf = &tx_ring->cmd_buf_arr[producer];
704c70001a9SSony Chacko 	pdev = adapter->pdev;
705d17dd0d9SSony Chacko 	first_desc = &tx_ring->desc_head[producer];
706d17dd0d9SSony Chacko 	hwdesc = &tx_ring->desc_head[producer];
707c70001a9SSony Chacko 	qlcnic_clear_cmddesc((u64 *)hwdesc);
708c70001a9SSony Chacko 
709c70001a9SSony Chacko 	if (qlcnic_map_tx_skb(pdev, skb, pbuf)) {
710c70001a9SSony Chacko 		adapter->stats.tx_dma_map_error++;
711c70001a9SSony Chacko 		goto drop_packet;
712c70001a9SSony Chacko 	}
713c70001a9SSony Chacko 
714c70001a9SSony Chacko 	pbuf->skb = skb;
715c70001a9SSony Chacko 	pbuf->frag_count = frag_count;
716c70001a9SSony Chacko 
717c70001a9SSony Chacko 	qlcnic_set_tx_frags_len(first_desc, frag_count, skb->len);
718c70001a9SSony Chacko 	qlcnic_set_tx_port(first_desc, adapter->portnum);
719c70001a9SSony Chacko 
720c70001a9SSony Chacko 	for (i = 0; i < frag_count; i++) {
721c70001a9SSony Chacko 		k = i % 4;
722c70001a9SSony Chacko 
723c70001a9SSony Chacko 		if ((k == 0) && (i > 0)) {
724c70001a9SSony Chacko 			/* move to next desc.*/
725c70001a9SSony Chacko 			producer = get_next_index(producer, num_txd);
726c70001a9SSony Chacko 			hwdesc = &tx_ring->desc_head[producer];
727c70001a9SSony Chacko 			qlcnic_clear_cmddesc((u64 *)hwdesc);
728c70001a9SSony Chacko 			tx_ring->cmd_buf_arr[producer].skb = NULL;
729c70001a9SSony Chacko 		}
730c70001a9SSony Chacko 
731c70001a9SSony Chacko 		buffrag = &pbuf->frag_array[i];
732c70001a9SSony Chacko 		hwdesc->buffer_length[k] = cpu_to_le16(buffrag->length);
733c70001a9SSony Chacko 		switch (k) {
734c70001a9SSony Chacko 		case 0:
735c70001a9SSony Chacko 			hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma);
736c70001a9SSony Chacko 			break;
737c70001a9SSony Chacko 		case 1:
738c70001a9SSony Chacko 			hwdesc->addr_buffer2 = cpu_to_le64(buffrag->dma);
739c70001a9SSony Chacko 			break;
740c70001a9SSony Chacko 		case 2:
741c70001a9SSony Chacko 			hwdesc->addr_buffer3 = cpu_to_le64(buffrag->dma);
742c70001a9SSony Chacko 			break;
743c70001a9SSony Chacko 		case 3:
744c70001a9SSony Chacko 			hwdesc->addr_buffer4 = cpu_to_le64(buffrag->dma);
745c70001a9SSony Chacko 			break;
746c70001a9SSony Chacko 		}
747c70001a9SSony Chacko 	}
748c70001a9SSony Chacko 
749c70001a9SSony Chacko 	tx_ring->producer = get_next_index(producer, num_txd);
750c70001a9SSony Chacko 	smp_mb();
751c70001a9SSony Chacko 
752381709deSShahed Shaikh 	protocol = ntohs(skb->protocol);
753381709deSShahed Shaikh 	if (protocol == ETH_P_IP)
754381709deSShahed Shaikh 		l4_is_udp = ip_hdr(skb)->protocol == IPPROTO_UDP;
755381709deSShahed Shaikh 	else if (protocol == ETH_P_IPV6)
756381709deSShahed Shaikh 		l4_is_udp = ipv6_hdr(skb)->nexthdr == IPPROTO_UDP;
757381709deSShahed Shaikh 
758381709deSShahed Shaikh 	/* Check if it is a VXLAN packet */
759381709deSShahed Shaikh 	if (!skb->encapsulation || !l4_is_udp ||
760381709deSShahed Shaikh 	    !qlcnic_encap_tx_offload(adapter)) {
761381709deSShahed Shaikh 		if (unlikely(qlcnic_tx_pkt(adapter, first_desc, skb,
762381709deSShahed Shaikh 					   tx_ring)))
763c70001a9SSony Chacko 			goto unwind_buff;
764381709deSShahed Shaikh 	} else {
765381709deSShahed Shaikh 		if (unlikely(qlcnic_tx_encap_pkt(adapter, first_desc,
766381709deSShahed Shaikh 						 skb, tx_ring)))
767381709deSShahed Shaikh 			goto unwind_buff;
768381709deSShahed Shaikh 	}
769c70001a9SSony Chacko 
770fe1adc6bSJitendra Kalsaria 	if (adapter->drv_mac_learn)
771c333fa0cSShahed Shaikh 		qlcnic_send_filter(adapter, first_desc, skb, tx_ring);
772c70001a9SSony Chacko 
773f27c75b3SHimanshu Madhani 	tx_ring->tx_stats.tx_bytes += skb->len;
774f27c75b3SHimanshu Madhani 	tx_ring->tx_stats.xmit_called++;
775c70001a9SSony Chacko 
7769216a97aSSony Chacko 	/* Ensure writes are complete before HW fetches Tx descriptors */
7779216a97aSSony Chacko 	wmb();
778c70001a9SSony Chacko 	qlcnic_update_cmd_producer(tx_ring);
779c70001a9SSony Chacko 
780c70001a9SSony Chacko 	return NETDEV_TX_OK;
781c70001a9SSony Chacko 
782c70001a9SSony Chacko unwind_buff:
783c70001a9SSony Chacko 	qlcnic_unmap_buffers(pdev, skb, pbuf);
784c70001a9SSony Chacko drop_packet:
785c70001a9SSony Chacko 	adapter->stats.txdropped++;
786c70001a9SSony Chacko 	dev_kfree_skb_any(skb);
787c70001a9SSony Chacko 	return NETDEV_TX_OK;
788c70001a9SSony Chacko }
789c70001a9SSony Chacko 
qlcnic_advert_link_change(struct qlcnic_adapter * adapter,int linkup)7907f966452SSony Chacko void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup)
791c70001a9SSony Chacko {
792c70001a9SSony Chacko 	struct net_device *netdev = adapter->netdev;
793c70001a9SSony Chacko 
794c70001a9SSony Chacko 	if (adapter->ahw->linkup && !linkup) {
795c70001a9SSony Chacko 		netdev_info(netdev, "NIC Link is down\n");
796c70001a9SSony Chacko 		adapter->ahw->linkup = 0;
797c70001a9SSony Chacko 		netif_carrier_off(netdev);
798c70001a9SSony Chacko 	} else if (!adapter->ahw->linkup && linkup) {
799092dfcf3SShahed Shaikh 		adapter->ahw->linkup = 1;
800092dfcf3SShahed Shaikh 
801092dfcf3SShahed Shaikh 		/* Do not advertise Link up to the stack if device
802092dfcf3SShahed Shaikh 		 * is in loopback mode
803092dfcf3SShahed Shaikh 		 */
804092dfcf3SShahed Shaikh 		if (qlcnic_83xx_check(adapter) && adapter->ahw->lb_mode) {
805092dfcf3SShahed Shaikh 			netdev_info(netdev, "NIC Link is up for loopback test\n");
806d9c602f0SManish Chopra 			return;
807092dfcf3SShahed Shaikh 		}
808d9c602f0SManish Chopra 
809c70001a9SSony Chacko 		netdev_info(netdev, "NIC Link is up\n");
810c70001a9SSony Chacko 		netif_carrier_on(netdev);
811c70001a9SSony Chacko 	}
812c70001a9SSony Chacko }
813c70001a9SSony Chacko 
qlcnic_alloc_rx_skb(struct qlcnic_adapter * adapter,struct qlcnic_host_rds_ring * rds_ring,struct qlcnic_rx_buffer * buffer)814d17dd0d9SSony Chacko static int qlcnic_alloc_rx_skb(struct qlcnic_adapter *adapter,
815c70001a9SSony Chacko 			       struct qlcnic_host_rds_ring *rds_ring,
816c70001a9SSony Chacko 			       struct qlcnic_rx_buffer *buffer)
817c70001a9SSony Chacko {
818c70001a9SSony Chacko 	struct sk_buff *skb;
819c70001a9SSony Chacko 	dma_addr_t dma;
820c70001a9SSony Chacko 	struct pci_dev *pdev = adapter->pdev;
821c70001a9SSony Chacko 
822c70001a9SSony Chacko 	skb = netdev_alloc_skb(adapter->netdev, rds_ring->skb_size);
823c70001a9SSony Chacko 	if (!skb) {
824c70001a9SSony Chacko 		adapter->stats.skb_alloc_failure++;
825c70001a9SSony Chacko 		return -ENOMEM;
826c70001a9SSony Chacko 	}
827c70001a9SSony Chacko 
828c70001a9SSony Chacko 	skb_reserve(skb, NET_IP_ALIGN);
829a14e3904SChristophe JAILLET 	dma = dma_map_single(&pdev->dev, skb->data, rds_ring->dma_size,
830a14e3904SChristophe JAILLET 			     DMA_FROM_DEVICE);
831c70001a9SSony Chacko 
832a14e3904SChristophe JAILLET 	if (dma_mapping_error(&pdev->dev, dma)) {
833c70001a9SSony Chacko 		adapter->stats.rx_dma_map_error++;
834c70001a9SSony Chacko 		dev_kfree_skb_any(skb);
835c70001a9SSony Chacko 		return -ENOMEM;
836c70001a9SSony Chacko 	}
837c70001a9SSony Chacko 
838c70001a9SSony Chacko 	buffer->skb = skb;
839c70001a9SSony Chacko 	buffer->dma = dma;
840c70001a9SSony Chacko 
841c70001a9SSony Chacko 	return 0;
842c70001a9SSony Chacko }
843c70001a9SSony Chacko 
qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter * adapter,struct qlcnic_host_rds_ring * rds_ring,u8 ring_id)844c70001a9SSony Chacko static void qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter,
8454be41e92SSony Chacko 					struct qlcnic_host_rds_ring *rds_ring,
8464be41e92SSony Chacko 					u8 ring_id)
847c70001a9SSony Chacko {
848c70001a9SSony Chacko 	struct rcv_desc *pdesc;
849c70001a9SSony Chacko 	struct qlcnic_rx_buffer *buffer;
850c70001a9SSony Chacko 	int  count = 0;
8514be41e92SSony Chacko 	uint32_t producer, handle;
852c70001a9SSony Chacko 	struct list_head *head;
853c70001a9SSony Chacko 
854c70001a9SSony Chacko 	if (!spin_trylock(&rds_ring->lock))
855c70001a9SSony Chacko 		return;
856c70001a9SSony Chacko 
857c70001a9SSony Chacko 	producer = rds_ring->producer;
858c70001a9SSony Chacko 	head = &rds_ring->free_list;
859d17dd0d9SSony Chacko 	while (!list_empty(head)) {
860c70001a9SSony Chacko 		buffer = list_entry(head->next, struct qlcnic_rx_buffer, list);
861c70001a9SSony Chacko 
862c70001a9SSony Chacko 		if (!buffer->skb) {
863c70001a9SSony Chacko 			if (qlcnic_alloc_rx_skb(adapter, rds_ring, buffer))
864c70001a9SSony Chacko 				break;
865c70001a9SSony Chacko 		}
866c70001a9SSony Chacko 		count++;
867c70001a9SSony Chacko 		list_del(&buffer->list);
868c70001a9SSony Chacko 
869c70001a9SSony Chacko 		/* make a rcv descriptor  */
870c70001a9SSony Chacko 		pdesc = &rds_ring->desc_head[producer];
8714be41e92SSony Chacko 		handle = qlcnic_get_ref_handle(adapter,
8724be41e92SSony Chacko 					       buffer->ref_handle, ring_id);
8734be41e92SSony Chacko 		pdesc->reference_handle = cpu_to_le16(handle);
874c70001a9SSony Chacko 		pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
875c70001a9SSony Chacko 		pdesc->addr_buffer = cpu_to_le64(buffer->dma);
876c70001a9SSony Chacko 		producer = get_next_index(producer, rds_ring->num_desc);
877c70001a9SSony Chacko 	}
878c70001a9SSony Chacko 	if (count) {
879c70001a9SSony Chacko 		rds_ring->producer = producer;
880c70001a9SSony Chacko 		writel((producer - 1) & (rds_ring->num_desc - 1),
881c70001a9SSony Chacko 		       rds_ring->crb_rcv_producer);
882c70001a9SSony Chacko 	}
883c70001a9SSony Chacko 	spin_unlock(&rds_ring->lock);
884c70001a9SSony Chacko }
885c70001a9SSony Chacko 
qlcnic_process_cmd_ring(struct qlcnic_adapter * adapter,struct qlcnic_host_tx_ring * tx_ring,int budget)8864be41e92SSony Chacko static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter,
8874be41e92SSony Chacko 				   struct qlcnic_host_tx_ring *tx_ring,
8884be41e92SSony Chacko 				   int budget)
889c70001a9SSony Chacko {
890c70001a9SSony Chacko 	u32 sw_consumer, hw_consumer;
891d17dd0d9SSony Chacko 	int i, done, count = 0;
892c70001a9SSony Chacko 	struct qlcnic_cmd_buffer *buffer;
893c70001a9SSony Chacko 	struct pci_dev *pdev = adapter->pdev;
894c70001a9SSony Chacko 	struct net_device *netdev = adapter->netdev;
895c70001a9SSony Chacko 	struct qlcnic_skb_frag *frag;
896c70001a9SSony Chacko 
897a02bdd42SShahed Shaikh 	if (!spin_trylock(&tx_ring->tx_clean_lock))
89834e8c406SHimanshu Madhani 		return 1;
89934e8c406SHimanshu Madhani 
900c70001a9SSony Chacko 	sw_consumer = tx_ring->sw_consumer;
901c70001a9SSony Chacko 	hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
902c70001a9SSony Chacko 
903c70001a9SSony Chacko 	while (sw_consumer != hw_consumer) {
904c70001a9SSony Chacko 		buffer = &tx_ring->cmd_buf_arr[sw_consumer];
905c70001a9SSony Chacko 		if (buffer->skb) {
906c70001a9SSony Chacko 			frag = &buffer->frag_array[0];
907a14e3904SChristophe JAILLET 			dma_unmap_single(&pdev->dev, frag->dma, frag->length,
908a14e3904SChristophe JAILLET 					 DMA_TO_DEVICE);
909c70001a9SSony Chacko 			frag->dma = 0ULL;
910c70001a9SSony Chacko 			for (i = 1; i < buffer->frag_count; i++) {
911c70001a9SSony Chacko 				frag++;
912a14e3904SChristophe JAILLET 				dma_unmap_page(&pdev->dev, frag->dma,
913a14e3904SChristophe JAILLET 					       frag->length, DMA_TO_DEVICE);
914c70001a9SSony Chacko 				frag->dma = 0ULL;
915c70001a9SSony Chacko 			}
916f27c75b3SHimanshu Madhani 			tx_ring->tx_stats.xmit_finished++;
917c70001a9SSony Chacko 			dev_kfree_skb_any(buffer->skb);
918c70001a9SSony Chacko 			buffer->skb = NULL;
919c70001a9SSony Chacko 		}
920c70001a9SSony Chacko 
921c70001a9SSony Chacko 		sw_consumer = get_next_index(sw_consumer, tx_ring->num_desc);
9224be41e92SSony Chacko 		if (++count >= budget)
923c70001a9SSony Chacko 			break;
924c70001a9SSony Chacko 	}
925c70001a9SSony Chacko 
926c70001a9SSony Chacko 	tx_ring->sw_consumer = sw_consumer;
927a02bdd42SShahed Shaikh 
928a02bdd42SShahed Shaikh 	if (count && netif_running(netdev)) {
929c70001a9SSony Chacko 		smp_mb();
930012ec812SHimanshu Madhani 		if (netif_tx_queue_stopped(tx_ring->txq) &&
931012ec812SHimanshu Madhani 		    netif_carrier_ok(netdev)) {
932c70001a9SSony Chacko 			if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) {
933012ec812SHimanshu Madhani 				netif_tx_wake_queue(tx_ring->txq);
934f27c75b3SHimanshu Madhani 				tx_ring->tx_stats.xmit_on++;
935c70001a9SSony Chacko 			}
936c70001a9SSony Chacko 		}
937c70001a9SSony Chacko 		adapter->tx_timeo_cnt = 0;
938c70001a9SSony Chacko 	}
939c70001a9SSony Chacko 	/*
940c70001a9SSony Chacko 	 * If everything is freed up to consumer then check if the ring is full
941c70001a9SSony Chacko 	 * If the ring is full then check if more needs to be freed and
942c70001a9SSony Chacko 	 * schedule the call back again.
943c70001a9SSony Chacko 	 *
944c70001a9SSony Chacko 	 * This happens when there are 2 CPUs. One could be freeing and the
945c70001a9SSony Chacko 	 * other filling it. If the ring is full when we get out of here and
946c70001a9SSony Chacko 	 * the card has already interrupted the host then the host can miss the
947c70001a9SSony Chacko 	 * interrupt.
948c70001a9SSony Chacko 	 *
949c70001a9SSony Chacko 	 * There is still a possible race condition and the host could miss an
950c70001a9SSony Chacko 	 * interrupt. The card has to take care of this.
951c70001a9SSony Chacko 	 */
952c70001a9SSony Chacko 	hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
953c70001a9SSony Chacko 	done = (sw_consumer == hw_consumer);
954a02bdd42SShahed Shaikh 
955a02bdd42SShahed Shaikh 	spin_unlock(&tx_ring->tx_clean_lock);
956c70001a9SSony Chacko 
957c70001a9SSony Chacko 	return done;
958c70001a9SSony Chacko }
959c70001a9SSony Chacko 
qlcnic_poll(struct napi_struct * napi,int budget)960c70001a9SSony Chacko static int qlcnic_poll(struct napi_struct *napi, int budget)
961c70001a9SSony Chacko {
9624be41e92SSony Chacko 	int tx_complete, work_done;
963d17dd0d9SSony Chacko 	struct qlcnic_host_sds_ring *sds_ring;
964d17dd0d9SSony Chacko 	struct qlcnic_adapter *adapter;
965012ec812SHimanshu Madhani 	struct qlcnic_host_tx_ring *tx_ring;
966c70001a9SSony Chacko 
967d17dd0d9SSony Chacko 	sds_ring = container_of(napi, struct qlcnic_host_sds_ring, napi);
968d17dd0d9SSony Chacko 	adapter = sds_ring->adapter;
969012ec812SHimanshu Madhani 	tx_ring = sds_ring->tx_ring;
970012ec812SHimanshu Madhani 
971012ec812SHimanshu Madhani 	tx_complete = qlcnic_process_cmd_ring(adapter, tx_ring,
9724be41e92SSony Chacko 					      budget);
973c70001a9SSony Chacko 	work_done = qlcnic_process_rcv_ring(sds_ring, budget);
974f31ec95fSShahed Shaikh 
975f31ec95fSShahed Shaikh 	/* Check if we need a repoll */
976f31ec95fSShahed Shaikh 	if (!tx_complete)
977f31ec95fSShahed Shaikh 		work_done = budget;
978f31ec95fSShahed Shaikh 
979f31ec95fSShahed Shaikh 	if (work_done < budget) {
9806ad20165SEric Dumazet 		napi_complete_done(&sds_ring->napi, work_done);
981012ec812SHimanshu Madhani 		if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
9822cc5752eSManish chopra 			qlcnic_enable_sds_intr(adapter, sds_ring);
983012ec812SHimanshu Madhani 			qlcnic_enable_tx_intr(adapter, tx_ring);
984012ec812SHimanshu Madhani 		}
985012ec812SHimanshu Madhani 	}
986012ec812SHimanshu Madhani 
987012ec812SHimanshu Madhani 	return work_done;
988012ec812SHimanshu Madhani }
989012ec812SHimanshu Madhani 
qlcnic_tx_poll(struct napi_struct * napi,int budget)990012ec812SHimanshu Madhani static int qlcnic_tx_poll(struct napi_struct *napi, int budget)
991012ec812SHimanshu Madhani {
992012ec812SHimanshu Madhani 	struct qlcnic_host_tx_ring *tx_ring;
993012ec812SHimanshu Madhani 	struct qlcnic_adapter *adapter;
994012ec812SHimanshu Madhani 	int work_done;
995012ec812SHimanshu Madhani 
996012ec812SHimanshu Madhani 	tx_ring = container_of(napi, struct qlcnic_host_tx_ring, napi);
997012ec812SHimanshu Madhani 	adapter = tx_ring->adapter;
998012ec812SHimanshu Madhani 
999012ec812SHimanshu Madhani 	work_done = qlcnic_process_cmd_ring(adapter, tx_ring, budget);
1000012ec812SHimanshu Madhani 	if (work_done) {
1001012ec812SHimanshu Madhani 		napi_complete(&tx_ring->napi);
1002012ec812SHimanshu Madhani 		if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
1003012ec812SHimanshu Madhani 			qlcnic_enable_tx_intr(adapter, tx_ring);
1004f31ec95fSShahed Shaikh 	} else {
1005f31ec95fSShahed Shaikh 		/* As qlcnic_process_cmd_ring() returned 0, we need a repoll*/
1006f31ec95fSShahed Shaikh 		work_done = budget;
1007c70001a9SSony Chacko 	}
1008c70001a9SSony Chacko 
1009c70001a9SSony Chacko 	return work_done;
1010c70001a9SSony Chacko }
1011c70001a9SSony Chacko 
qlcnic_rx_poll(struct napi_struct * napi,int budget)1012c70001a9SSony Chacko static int qlcnic_rx_poll(struct napi_struct *napi, int budget)
1013c70001a9SSony Chacko {
1014d17dd0d9SSony Chacko 	struct qlcnic_host_sds_ring *sds_ring;
1015d17dd0d9SSony Chacko 	struct qlcnic_adapter *adapter;
1016c70001a9SSony Chacko 	int work_done;
1017c70001a9SSony Chacko 
1018d17dd0d9SSony Chacko 	sds_ring = container_of(napi, struct qlcnic_host_sds_ring, napi);
1019d17dd0d9SSony Chacko 	adapter = sds_ring->adapter;
1020d17dd0d9SSony Chacko 
1021c70001a9SSony Chacko 	work_done = qlcnic_process_rcv_ring(sds_ring, budget);
1022c70001a9SSony Chacko 
1023c70001a9SSony Chacko 	if (work_done < budget) {
10246ad20165SEric Dumazet 		napi_complete_done(&sds_ring->napi, work_done);
1025c70001a9SSony Chacko 		if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
10262cc5752eSManish chopra 			qlcnic_enable_sds_intr(adapter, sds_ring);
1027c70001a9SSony Chacko 	}
1028c70001a9SSony Chacko 
1029c70001a9SSony Chacko 	return work_done;
1030c70001a9SSony Chacko }
1031c70001a9SSony Chacko 
qlcnic_handle_linkevent(struct qlcnic_adapter * adapter,struct qlcnic_fw_msg * msg)1032d17dd0d9SSony Chacko static void qlcnic_handle_linkevent(struct qlcnic_adapter *adapter,
1033c70001a9SSony Chacko 				    struct qlcnic_fw_msg *msg)
1034c70001a9SSony Chacko {
1035c70001a9SSony Chacko 	u32 cable_OUI;
1036d17dd0d9SSony Chacko 	u16 cable_len, link_speed;
1037d17dd0d9SSony Chacko 	u8  link_status, module, duplex, autoneg, lb_status = 0;
1038c70001a9SSony Chacko 	struct net_device *netdev = adapter->netdev;
1039c70001a9SSony Chacko 
104079788450SSony Chacko 	adapter->ahw->has_link_events = 1;
1041c70001a9SSony Chacko 
1042c70001a9SSony Chacko 	cable_OUI = msg->body[1] & 0xffffffff;
1043c70001a9SSony Chacko 	cable_len = (msg->body[1] >> 32) & 0xffff;
1044c70001a9SSony Chacko 	link_speed = (msg->body[1] >> 48) & 0xffff;
1045c70001a9SSony Chacko 
1046c70001a9SSony Chacko 	link_status = msg->body[2] & 0xff;
1047c70001a9SSony Chacko 	duplex = (msg->body[2] >> 16) & 0xff;
1048c70001a9SSony Chacko 	autoneg = (msg->body[2] >> 24) & 0xff;
1049c70001a9SSony Chacko 	lb_status = (msg->body[2] >> 32) & 0x3;
1050c70001a9SSony Chacko 
1051c70001a9SSony Chacko 	module = (msg->body[2] >> 8) & 0xff;
1052c70001a9SSony Chacko 	if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE)
1053d17dd0d9SSony Chacko 		dev_info(&netdev->dev,
1054d17dd0d9SSony Chacko 			 "unsupported cable: OUI 0x%x, length %d\n",
1055d17dd0d9SSony Chacko 			 cable_OUI, cable_len);
1056c70001a9SSony Chacko 	else if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN)
1057c70001a9SSony Chacko 		dev_info(&netdev->dev, "unsupported cable length %d\n",
1058c70001a9SSony Chacko 			 cable_len);
1059c70001a9SSony Chacko 
1060c70001a9SSony Chacko 	if (!link_status && (lb_status == QLCNIC_ILB_MODE ||
1061c70001a9SSony Chacko 	    lb_status == QLCNIC_ELB_MODE))
1062c70001a9SSony Chacko 		adapter->ahw->loopback_state |= QLCNIC_LINKEVENT;
1063c70001a9SSony Chacko 
1064c70001a9SSony Chacko 	qlcnic_advert_link_change(adapter, link_status);
1065c70001a9SSony Chacko 
1066c70001a9SSony Chacko 	if (duplex == LINKEVENT_FULL_DUPLEX)
106779788450SSony Chacko 		adapter->ahw->link_duplex = DUPLEX_FULL;
1068c70001a9SSony Chacko 	else
106979788450SSony Chacko 		adapter->ahw->link_duplex = DUPLEX_HALF;
1070c70001a9SSony Chacko 
107179788450SSony Chacko 	adapter->ahw->module_type = module;
107279788450SSony Chacko 	adapter->ahw->link_autoneg = autoneg;
1073c70001a9SSony Chacko 
1074c70001a9SSony Chacko 	if (link_status) {
107579788450SSony Chacko 		adapter->ahw->link_speed = link_speed;
1076c70001a9SSony Chacko 	} else {
107779788450SSony Chacko 		adapter->ahw->link_speed = SPEED_UNKNOWN;
107879788450SSony Chacko 		adapter->ahw->link_duplex = DUPLEX_UNKNOWN;
1079c70001a9SSony Chacko 	}
1080c70001a9SSony Chacko }
1081c70001a9SSony Chacko 
qlcnic_handle_fw_message(int desc_cnt,int index,struct qlcnic_host_sds_ring * sds_ring)1082d17dd0d9SSony Chacko static void qlcnic_handle_fw_message(int desc_cnt, int index,
1083c70001a9SSony Chacko 				     struct qlcnic_host_sds_ring *sds_ring)
1084c70001a9SSony Chacko {
1085c70001a9SSony Chacko 	struct qlcnic_fw_msg msg;
1086c70001a9SSony Chacko 	struct status_desc *desc;
1087c70001a9SSony Chacko 	struct qlcnic_adapter *adapter;
1088c70001a9SSony Chacko 	struct device *dev;
1089c70001a9SSony Chacko 	int i = 0, opcode, ret;
1090c70001a9SSony Chacko 
1091c70001a9SSony Chacko 	while (desc_cnt > 0 && i < 8) {
1092c70001a9SSony Chacko 		desc = &sds_ring->desc_head[index];
1093c70001a9SSony Chacko 		msg.words[i++] = le64_to_cpu(desc->status_desc_data[0]);
1094c70001a9SSony Chacko 		msg.words[i++] = le64_to_cpu(desc->status_desc_data[1]);
1095c70001a9SSony Chacko 
1096c70001a9SSony Chacko 		index = get_next_index(index, sds_ring->num_desc);
1097c70001a9SSony Chacko 		desc_cnt--;
1098c70001a9SSony Chacko 	}
1099c70001a9SSony Chacko 
1100c70001a9SSony Chacko 	adapter = sds_ring->adapter;
1101c70001a9SSony Chacko 	dev = &adapter->pdev->dev;
1102c70001a9SSony Chacko 	opcode = qlcnic_get_nic_msg_opcode(msg.body[0]);
1103c70001a9SSony Chacko 
1104c70001a9SSony Chacko 	switch (opcode) {
1105c70001a9SSony Chacko 	case QLCNIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE:
1106c70001a9SSony Chacko 		qlcnic_handle_linkevent(adapter, &msg);
1107c70001a9SSony Chacko 		break;
1108c70001a9SSony Chacko 	case QLCNIC_C2H_OPCODE_CONFIG_LOOPBACK:
1109c70001a9SSony Chacko 		ret = (u32)(msg.body[1]);
1110c70001a9SSony Chacko 		switch (ret) {
1111c70001a9SSony Chacko 		case 0:
1112c70001a9SSony Chacko 			adapter->ahw->loopback_state |= QLCNIC_LB_RESPONSE;
1113c70001a9SSony Chacko 			break;
1114c70001a9SSony Chacko 		case 1:
1115c70001a9SSony Chacko 			dev_info(dev, "loopback already in progress\n");
1116b9c11984SJitendra Kalsaria 			adapter->ahw->diag_cnt = -EINPROGRESS;
1117c70001a9SSony Chacko 			break;
1118c70001a9SSony Chacko 		case 2:
1119c70001a9SSony Chacko 			dev_info(dev, "loopback cable is not connected\n");
1120b9c11984SJitendra Kalsaria 			adapter->ahw->diag_cnt = -ENODEV;
1121c70001a9SSony Chacko 			break;
1122c70001a9SSony Chacko 		default:
1123d17dd0d9SSony Chacko 			dev_info(dev,
1124d17dd0d9SSony Chacko 				 "loopback configure request failed, err %x\n",
1125d17dd0d9SSony Chacko 				 ret);
1126b9c11984SJitendra Kalsaria 			adapter->ahw->diag_cnt = -EIO;
1127c70001a9SSony Chacko 			break;
1128c70001a9SSony Chacko 		}
1129c70001a9SSony Chacko 		break;
11302d8ebcabSSucheta Chakraborty 	case QLCNIC_C2H_OPCODE_GET_DCB_AEN:
11311de899d3SSucheta Chakraborty 		qlcnic_dcb_aen_handler(adapter->dcb, (void *)&msg);
11322d8ebcabSSucheta Chakraborty 		break;
1133c70001a9SSony Chacko 	default:
1134c70001a9SSony Chacko 		break;
1135c70001a9SSony Chacko 	}
1136c70001a9SSony Chacko }
1137c70001a9SSony Chacko 
qlcnic_process_rxbuf(struct qlcnic_adapter * adapter,struct qlcnic_host_rds_ring * ring,u16 index,u16 cksum)113821041400Sstephen hemminger static struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *adapter,
11394be41e92SSony Chacko 					    struct qlcnic_host_rds_ring *ring,
11404be41e92SSony Chacko 					    u16 index, u16 cksum)
1141c70001a9SSony Chacko {
1142c70001a9SSony Chacko 	struct qlcnic_rx_buffer *buffer;
1143c70001a9SSony Chacko 	struct sk_buff *skb;
1144c70001a9SSony Chacko 
11454be41e92SSony Chacko 	buffer = &ring->rx_buf_arr[index];
1146c70001a9SSony Chacko 	if (unlikely(buffer->skb == NULL)) {
1147c70001a9SSony Chacko 		WARN_ON(1);
1148c70001a9SSony Chacko 		return NULL;
1149c70001a9SSony Chacko 	}
1150c70001a9SSony Chacko 
1151a14e3904SChristophe JAILLET 	dma_unmap_single(&adapter->pdev->dev, buffer->dma, ring->dma_size,
1152a14e3904SChristophe JAILLET 			 DMA_FROM_DEVICE);
1153c70001a9SSony Chacko 
1154c70001a9SSony Chacko 	skb = buffer->skb;
1155c70001a9SSony Chacko 	if (likely((adapter->netdev->features & NETIF_F_RXCSUM) &&
1156c70001a9SSony Chacko 		   (cksum == STATUS_CKSUM_OK || cksum == STATUS_CKSUM_LOOP))) {
1157c70001a9SSony Chacko 		adapter->stats.csummed++;
1158c70001a9SSony Chacko 		skb->ip_summed = CHECKSUM_UNNECESSARY;
1159c70001a9SSony Chacko 	} else {
1160c70001a9SSony Chacko 		skb_checksum_none_assert(skb);
1161c70001a9SSony Chacko 	}
1162c70001a9SSony Chacko 
11634be41e92SSony Chacko 
1164c70001a9SSony Chacko 	buffer->skb = NULL;
1165c70001a9SSony Chacko 
1166c70001a9SSony Chacko 	return skb;
1167c70001a9SSony Chacko }
1168c70001a9SSony Chacko 
qlcnic_check_rx_tagging(struct qlcnic_adapter * adapter,struct sk_buff * skb,u16 * vlan_tag)1169d17dd0d9SSony Chacko static inline int qlcnic_check_rx_tagging(struct qlcnic_adapter *adapter,
1170d17dd0d9SSony Chacko 					  struct sk_buff *skb, u16 *vlan_tag)
1171c70001a9SSony Chacko {
1172c70001a9SSony Chacko 	struct ethhdr *eth_hdr;
1173c70001a9SSony Chacko 
1174c70001a9SSony Chacko 	if (!__vlan_get_tag(skb, vlan_tag)) {
1175c70001a9SSony Chacko 		eth_hdr = (struct ethhdr *)skb->data;
1176c70001a9SSony Chacko 		memmove(skb->data + VLAN_HLEN, eth_hdr, ETH_ALEN * 2);
1177c70001a9SSony Chacko 		skb_pull(skb, VLAN_HLEN);
1178c70001a9SSony Chacko 	}
117991b7282bSRajesh Borundia 	if (!adapter->rx_pvid)
1180c70001a9SSony Chacko 		return 0;
1181c70001a9SSony Chacko 
118291b7282bSRajesh Borundia 	if (*vlan_tag == adapter->rx_pvid) {
1183c70001a9SSony Chacko 		/* Outer vlan tag. Packet should follow non-vlan path */
1184c70001a9SSony Chacko 		*vlan_tag = 0xffff;
1185c70001a9SSony Chacko 		return 0;
1186c70001a9SSony Chacko 	}
1187c70001a9SSony Chacko 	if (adapter->flags & QLCNIC_TAGGING_ENABLED)
1188c70001a9SSony Chacko 		return 0;
1189c70001a9SSony Chacko 
1190c70001a9SSony Chacko 	return -EINVAL;
1191c70001a9SSony Chacko }
1192c70001a9SSony Chacko 
1193c70001a9SSony 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)1194c70001a9SSony Chacko qlcnic_process_rcv(struct qlcnic_adapter *adapter,
1195d17dd0d9SSony Chacko 		   struct qlcnic_host_sds_ring *sds_ring, int ring,
1196d17dd0d9SSony Chacko 		   u64 sts_data0)
1197c70001a9SSony Chacko {
1198c70001a9SSony Chacko 	struct net_device *netdev = adapter->netdev;
1199c70001a9SSony Chacko 	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
1200c70001a9SSony Chacko 	struct qlcnic_rx_buffer *buffer;
1201c70001a9SSony Chacko 	struct sk_buff *skb;
1202c70001a9SSony Chacko 	struct qlcnic_host_rds_ring *rds_ring;
120353643a75SShahed Shaikh 	int index, length, cksum, pkt_offset, is_lb_pkt;
120453643a75SShahed Shaikh 	u16 vid = 0xffff, t_vid;
1205c70001a9SSony Chacko 
1206c70001a9SSony Chacko 	if (unlikely(ring >= adapter->max_rds_rings))
1207c70001a9SSony Chacko 		return NULL;
1208c70001a9SSony Chacko 
1209c70001a9SSony Chacko 	rds_ring = &recv_ctx->rds_rings[ring];
1210c70001a9SSony Chacko 
1211c70001a9SSony Chacko 	index = qlcnic_get_sts_refhandle(sts_data0);
1212c70001a9SSony Chacko 	if (unlikely(index >= rds_ring->num_desc))
1213c70001a9SSony Chacko 		return NULL;
1214c70001a9SSony Chacko 
1215c70001a9SSony Chacko 	buffer = &rds_ring->rx_buf_arr[index];
1216c70001a9SSony Chacko 	length = qlcnic_get_sts_totallength(sts_data0);
1217c70001a9SSony Chacko 	cksum  = qlcnic_get_sts_status(sts_data0);
1218c70001a9SSony Chacko 	pkt_offset = qlcnic_get_sts_pkt_offset(sts_data0);
1219c70001a9SSony Chacko 
1220c70001a9SSony Chacko 	skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum);
1221c70001a9SSony Chacko 	if (!skb)
1222c70001a9SSony Chacko 		return buffer;
1223c70001a9SSony Chacko 
1224ddfbac07SShahed Shaikh 	if (adapter->rx_mac_learn) {
122553643a75SShahed Shaikh 		t_vid = 0;
122653643a75SShahed Shaikh 		is_lb_pkt = qlcnic_82xx_is_lb_pkt(sts_data0);
1227f80bc8feSRajesh Borundia 		qlcnic_add_lb_filter(adapter, skb, is_lb_pkt, t_vid);
122853643a75SShahed Shaikh 	}
122953643a75SShahed Shaikh 
1230c70001a9SSony Chacko 	if (length > rds_ring->skb_size)
1231c70001a9SSony Chacko 		skb_put(skb, rds_ring->skb_size);
1232c70001a9SSony Chacko 	else
1233c70001a9SSony Chacko 		skb_put(skb, length);
1234c70001a9SSony Chacko 
1235c70001a9SSony Chacko 	if (pkt_offset)
1236c70001a9SSony Chacko 		skb_pull(skb, pkt_offset);
1237c70001a9SSony Chacko 
1238c70001a9SSony Chacko 	if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) {
1239c70001a9SSony Chacko 		adapter->stats.rxdropped++;
1240c70001a9SSony Chacko 		dev_kfree_skb(skb);
1241c70001a9SSony Chacko 		return buffer;
1242c70001a9SSony Chacko 	}
1243c70001a9SSony Chacko 
1244c70001a9SSony Chacko 	skb->protocol = eth_type_trans(skb, netdev);
1245c70001a9SSony Chacko 
1246c70001a9SSony Chacko 	if (vid != 0xffff)
124786a9bad3SPatrick McHardy 		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid);
1248c70001a9SSony Chacko 
1249c70001a9SSony Chacko 	napi_gro_receive(&sds_ring->napi, skb);
1250c70001a9SSony Chacko 
1251c70001a9SSony Chacko 	adapter->stats.rx_pkts++;
1252c70001a9SSony Chacko 	adapter->stats.rxbytes += length;
1253c70001a9SSony Chacko 
1254c70001a9SSony Chacko 	return buffer;
1255c70001a9SSony Chacko }
1256c70001a9SSony Chacko 
1257c70001a9SSony Chacko #define QLC_TCP_HDR_SIZE            20
1258c70001a9SSony Chacko #define QLC_TCP_TS_OPTION_SIZE      12
1259c70001a9SSony Chacko #define QLC_TCP_TS_HDR_SIZE         (QLC_TCP_HDR_SIZE + QLC_TCP_TS_OPTION_SIZE)
1260c70001a9SSony Chacko 
1261c70001a9SSony Chacko static struct qlcnic_rx_buffer *
qlcnic_process_lro(struct qlcnic_adapter * adapter,int ring,u64 sts_data0,u64 sts_data1)1262c70001a9SSony Chacko qlcnic_process_lro(struct qlcnic_adapter *adapter,
1263c70001a9SSony Chacko 		   int ring, u64 sts_data0, u64 sts_data1)
1264c70001a9SSony Chacko {
1265c70001a9SSony Chacko 	struct net_device *netdev = adapter->netdev;
1266c70001a9SSony Chacko 	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
1267c70001a9SSony Chacko 	struct qlcnic_rx_buffer *buffer;
1268c70001a9SSony Chacko 	struct sk_buff *skb;
1269c70001a9SSony Chacko 	struct qlcnic_host_rds_ring *rds_ring;
1270c70001a9SSony Chacko 	struct iphdr *iph;
1271776e7bdeSShahed Shaikh 	struct ipv6hdr *ipv6h;
1272c70001a9SSony Chacko 	struct tcphdr *th;
1273c70001a9SSony Chacko 	bool push, timestamp;
127453643a75SShahed Shaikh 	int index, l2_hdr_offset, l4_hdr_offset, is_lb_pkt;
127553643a75SShahed Shaikh 	u16 lro_length, length, data_offset, t_vid, vid = 0xffff;
1276c70001a9SSony Chacko 	u32 seq_number;
1277c70001a9SSony Chacko 
1278462bed48SManish Chopra 	if (unlikely(ring >= adapter->max_rds_rings))
1279c70001a9SSony Chacko 		return NULL;
1280c70001a9SSony Chacko 
1281c70001a9SSony Chacko 	rds_ring = &recv_ctx->rds_rings[ring];
1282c70001a9SSony Chacko 
1283c70001a9SSony Chacko 	index = qlcnic_get_lro_sts_refhandle(sts_data0);
1284462bed48SManish Chopra 	if (unlikely(index >= rds_ring->num_desc))
1285c70001a9SSony Chacko 		return NULL;
1286c70001a9SSony Chacko 
1287c70001a9SSony Chacko 	buffer = &rds_ring->rx_buf_arr[index];
1288c70001a9SSony Chacko 
1289c70001a9SSony Chacko 	timestamp = qlcnic_get_lro_sts_timestamp(sts_data0);
1290c70001a9SSony Chacko 	lro_length = qlcnic_get_lro_sts_length(sts_data0);
1291c70001a9SSony Chacko 	l2_hdr_offset = qlcnic_get_lro_sts_l2_hdr_offset(sts_data0);
1292c70001a9SSony Chacko 	l4_hdr_offset = qlcnic_get_lro_sts_l4_hdr_offset(sts_data0);
1293c70001a9SSony Chacko 	push = qlcnic_get_lro_sts_push_flag(sts_data0);
1294c70001a9SSony Chacko 	seq_number = qlcnic_get_lro_sts_seq_number(sts_data1);
1295c70001a9SSony Chacko 
1296c70001a9SSony Chacko 	skb = qlcnic_process_rxbuf(adapter, rds_ring, index, STATUS_CKSUM_OK);
1297c70001a9SSony Chacko 	if (!skb)
1298c70001a9SSony Chacko 		return buffer;
1299c70001a9SSony Chacko 
1300ddfbac07SShahed Shaikh 	if (adapter->rx_mac_learn) {
130153643a75SShahed Shaikh 		t_vid = 0;
130253643a75SShahed Shaikh 		is_lb_pkt = qlcnic_82xx_is_lb_pkt(sts_data0);
1303f80bc8feSRajesh Borundia 		qlcnic_add_lb_filter(adapter, skb, is_lb_pkt, t_vid);
130453643a75SShahed Shaikh 	}
130553643a75SShahed Shaikh 
1306c70001a9SSony Chacko 	if (timestamp)
1307c70001a9SSony Chacko 		data_offset = l4_hdr_offset + QLC_TCP_TS_HDR_SIZE;
1308c70001a9SSony Chacko 	else
1309c70001a9SSony Chacko 		data_offset = l4_hdr_offset + QLC_TCP_HDR_SIZE;
1310c70001a9SSony Chacko 
1311c70001a9SSony Chacko 	skb_put(skb, lro_length + data_offset);
1312c70001a9SSony Chacko 	skb_pull(skb, l2_hdr_offset);
1313c70001a9SSony Chacko 
1314c70001a9SSony Chacko 	if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) {
1315c70001a9SSony Chacko 		adapter->stats.rxdropped++;
1316c70001a9SSony Chacko 		dev_kfree_skb(skb);
1317c70001a9SSony Chacko 		return buffer;
1318c70001a9SSony Chacko 	}
1319c70001a9SSony Chacko 
1320c70001a9SSony Chacko 	skb->protocol = eth_type_trans(skb, netdev);
1321776e7bdeSShahed Shaikh 
1322069048f1SShahed Shaikh 	if (ntohs(skb->protocol) == ETH_P_IPV6) {
1323776e7bdeSShahed Shaikh 		ipv6h = (struct ipv6hdr *)skb->data;
1324776e7bdeSShahed Shaikh 		th = (struct tcphdr *)(skb->data + sizeof(struct ipv6hdr));
1325776e7bdeSShahed Shaikh 		length = (th->doff << 2) + lro_length;
1326776e7bdeSShahed Shaikh 		ipv6h->payload_len = htons(length);
1327776e7bdeSShahed Shaikh 	} else {
1328c70001a9SSony Chacko 		iph = (struct iphdr *)skb->data;
1329c70001a9SSony Chacko 		th = (struct tcphdr *)(skb->data + (iph->ihl << 2));
1330c70001a9SSony Chacko 		length = (iph->ihl << 2) + (th->doff << 2) + lro_length;
13311bcac3b0SLi RongQing 		csum_replace2(&iph->check, iph->tot_len, htons(length));
1332c70001a9SSony Chacko 		iph->tot_len = htons(length);
1333776e7bdeSShahed Shaikh 	}
1334776e7bdeSShahed Shaikh 
1335c70001a9SSony Chacko 	th->psh = push;
1336c70001a9SSony Chacko 	th->seq = htonl(seq_number);
1337c70001a9SSony Chacko 	length = skb->len;
1338c70001a9SSony Chacko 
1339bd69ba79SMichael S. Tsirkin 	if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP) {
1340c70001a9SSony Chacko 		skb_shinfo(skb)->gso_size = qlcnic_get_lro_sts_mss(sts_data1);
1341bd69ba79SMichael S. Tsirkin 		if (skb->protocol == htons(ETH_P_IPV6))
1342bd69ba79SMichael S. Tsirkin 			skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
1343bd69ba79SMichael S. Tsirkin 		else
1344bd69ba79SMichael S. Tsirkin 			skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
1345bd69ba79SMichael S. Tsirkin 	}
1346c70001a9SSony Chacko 
1347c70001a9SSony Chacko 	if (vid != 0xffff)
134886a9bad3SPatrick McHardy 		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid);
1349c70001a9SSony Chacko 	netif_receive_skb(skb);
1350c70001a9SSony Chacko 
1351c70001a9SSony Chacko 	adapter->stats.lro_pkts++;
1352c70001a9SSony Chacko 	adapter->stats.lrobytes += length;
1353c70001a9SSony Chacko 
1354c70001a9SSony Chacko 	return buffer;
1355c70001a9SSony Chacko }
1356c70001a9SSony Chacko 
qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring * sds_ring,int max)135721041400Sstephen hemminger static int qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max)
1358c70001a9SSony Chacko {
1359d17dd0d9SSony Chacko 	struct qlcnic_host_rds_ring *rds_ring;
1360c70001a9SSony Chacko 	struct qlcnic_adapter *adapter = sds_ring->adapter;
1361c70001a9SSony Chacko 	struct list_head *cur;
1362c70001a9SSony Chacko 	struct status_desc *desc;
1363c70001a9SSony Chacko 	struct qlcnic_rx_buffer *rxbuf;
13644be41e92SSony Chacko 	int opcode, desc_cnt, count = 0;
1365c70001a9SSony Chacko 	u64 sts_data0, sts_data1;
13664be41e92SSony Chacko 	u8 ring;
1367c70001a9SSony Chacko 	u32 consumer = sds_ring->consumer;
1368c70001a9SSony Chacko 
1369c70001a9SSony Chacko 	while (count < max) {
1370c70001a9SSony Chacko 		desc = &sds_ring->desc_head[consumer];
1371c70001a9SSony Chacko 		sts_data0 = le64_to_cpu(desc->status_desc_data[0]);
1372c70001a9SSony Chacko 
1373c70001a9SSony Chacko 		if (!(sts_data0 & STATUS_OWNER_HOST))
1374c70001a9SSony Chacko 			break;
1375c70001a9SSony Chacko 
1376c70001a9SSony Chacko 		desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0);
1377c70001a9SSony Chacko 		opcode = qlcnic_get_sts_opcode(sts_data0);
1378c70001a9SSony Chacko 		switch (opcode) {
1379c70001a9SSony Chacko 		case QLCNIC_RXPKT_DESC:
1380c70001a9SSony Chacko 		case QLCNIC_OLD_RXPKT_DESC:
1381c70001a9SSony Chacko 		case QLCNIC_SYN_OFFLOAD:
1382c70001a9SSony Chacko 			ring = qlcnic_get_sts_type(sts_data0);
1383d17dd0d9SSony Chacko 			rxbuf = qlcnic_process_rcv(adapter, sds_ring, ring,
1384d17dd0d9SSony Chacko 						   sts_data0);
1385c70001a9SSony Chacko 			break;
1386c70001a9SSony Chacko 		case QLCNIC_LRO_DESC:
1387c70001a9SSony Chacko 			ring = qlcnic_get_lro_sts_type(sts_data0);
1388c70001a9SSony Chacko 			sts_data1 = le64_to_cpu(desc->status_desc_data[1]);
1389c70001a9SSony Chacko 			rxbuf = qlcnic_process_lro(adapter, ring, sts_data0,
1390c70001a9SSony Chacko 						   sts_data1);
1391c70001a9SSony Chacko 			break;
1392c70001a9SSony Chacko 		case QLCNIC_RESPONSE_DESC:
1393c70001a9SSony Chacko 			qlcnic_handle_fw_message(desc_cnt, consumer, sds_ring);
1394d66aea44SGustavo A. R. Silva 			goto skip;
1395c70001a9SSony Chacko 		default:
1396c70001a9SSony Chacko 			goto skip;
1397c70001a9SSony Chacko 		}
1398c70001a9SSony Chacko 		WARN_ON(desc_cnt > 1);
1399c70001a9SSony Chacko 
1400c70001a9SSony Chacko 		if (likely(rxbuf))
1401c70001a9SSony Chacko 			list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]);
1402c70001a9SSony Chacko 		else
1403c70001a9SSony Chacko 			adapter->stats.null_rxbuf++;
1404c70001a9SSony Chacko skip:
1405c70001a9SSony Chacko 		for (; desc_cnt > 0; desc_cnt--) {
1406c70001a9SSony Chacko 			desc = &sds_ring->desc_head[consumer];
14074be41e92SSony Chacko 			desc->status_desc_data[0] = QLCNIC_DESC_OWNER_FW;
1408c70001a9SSony Chacko 			consumer = get_next_index(consumer, sds_ring->num_desc);
1409c70001a9SSony Chacko 		}
1410c70001a9SSony Chacko 		count++;
1411c70001a9SSony Chacko 	}
1412c70001a9SSony Chacko 
1413c70001a9SSony Chacko 	for (ring = 0; ring < adapter->max_rds_rings; ring++) {
1414d17dd0d9SSony Chacko 		rds_ring = &adapter->recv_ctx->rds_rings[ring];
1415c70001a9SSony Chacko 		if (!list_empty(&sds_ring->free_list[ring])) {
1416c70001a9SSony Chacko 			list_for_each(cur, &sds_ring->free_list[ring]) {
1417d17dd0d9SSony Chacko 				rxbuf = list_entry(cur, struct qlcnic_rx_buffer,
1418d17dd0d9SSony Chacko 						   list);
1419c70001a9SSony Chacko 				qlcnic_alloc_rx_skb(adapter, rds_ring, rxbuf);
1420c70001a9SSony Chacko 			}
1421c70001a9SSony Chacko 			spin_lock(&rds_ring->lock);
1422c70001a9SSony Chacko 			list_splice_tail_init(&sds_ring->free_list[ring],
1423c70001a9SSony Chacko 					      &rds_ring->free_list);
1424c70001a9SSony Chacko 			spin_unlock(&rds_ring->lock);
1425c70001a9SSony Chacko 		}
1426c70001a9SSony Chacko 
14274be41e92SSony Chacko 		qlcnic_post_rx_buffers_nodb(adapter, rds_ring, ring);
1428c70001a9SSony Chacko 	}
1429c70001a9SSony Chacko 
1430c70001a9SSony Chacko 	if (count) {
1431c70001a9SSony Chacko 		sds_ring->consumer = consumer;
1432c70001a9SSony Chacko 		writel(consumer, sds_ring->crb_sts_consumer);
1433c70001a9SSony Chacko 	}
1434c70001a9SSony Chacko 
1435c70001a9SSony Chacko 	return count;
1436c70001a9SSony Chacko }
1437c70001a9SSony Chacko 
qlcnic_post_rx_buffers(struct qlcnic_adapter * adapter,struct qlcnic_host_rds_ring * rds_ring,u8 ring_id)1438d17dd0d9SSony Chacko void qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter,
14394be41e92SSony Chacko 			    struct qlcnic_host_rds_ring *rds_ring, u8 ring_id)
1440c70001a9SSony Chacko {
1441c70001a9SSony Chacko 	struct rcv_desc *pdesc;
1442c70001a9SSony Chacko 	struct qlcnic_rx_buffer *buffer;
1443c70001a9SSony Chacko 	int count = 0;
14444be41e92SSony Chacko 	u32 producer, handle;
1445c70001a9SSony Chacko 	struct list_head *head;
1446c70001a9SSony Chacko 
1447c70001a9SSony Chacko 	producer = rds_ring->producer;
1448c70001a9SSony Chacko 	head = &rds_ring->free_list;
1449d17dd0d9SSony Chacko 
1450c70001a9SSony Chacko 	while (!list_empty(head)) {
1451c70001a9SSony Chacko 
1452c70001a9SSony Chacko 		buffer = list_entry(head->next, struct qlcnic_rx_buffer, list);
1453c70001a9SSony Chacko 
1454c70001a9SSony Chacko 		if (!buffer->skb) {
1455c70001a9SSony Chacko 			if (qlcnic_alloc_rx_skb(adapter, rds_ring, buffer))
1456c70001a9SSony Chacko 				break;
1457c70001a9SSony Chacko 		}
1458c70001a9SSony Chacko 
1459c70001a9SSony Chacko 		count++;
1460c70001a9SSony Chacko 		list_del(&buffer->list);
1461c70001a9SSony Chacko 
1462c70001a9SSony Chacko 		/* make a rcv descriptor  */
1463c70001a9SSony Chacko 		pdesc = &rds_ring->desc_head[producer];
1464c70001a9SSony Chacko 		pdesc->addr_buffer = cpu_to_le64(buffer->dma);
14654be41e92SSony Chacko 		handle = qlcnic_get_ref_handle(adapter, buffer->ref_handle,
14664be41e92SSony Chacko 					       ring_id);
14674be41e92SSony Chacko 		pdesc->reference_handle = cpu_to_le16(handle);
1468c70001a9SSony Chacko 		pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
1469c70001a9SSony Chacko 		producer = get_next_index(producer, rds_ring->num_desc);
1470c70001a9SSony Chacko 	}
1471c70001a9SSony Chacko 
1472c70001a9SSony Chacko 	if (count) {
1473c70001a9SSony Chacko 		rds_ring->producer = producer;
1474c70001a9SSony Chacko 		writel((producer-1) & (rds_ring->num_desc-1),
1475c70001a9SSony Chacko 		       rds_ring->crb_rcv_producer);
1476c70001a9SSony Chacko 	}
1477c70001a9SSony Chacko }
1478c70001a9SSony Chacko 
dump_skb(struct sk_buff * skb,struct qlcnic_adapter * adapter)1479c70001a9SSony Chacko static void dump_skb(struct sk_buff *skb, struct qlcnic_adapter *adapter)
1480c70001a9SSony Chacko {
14813620af0eSJoe Perches 	if (adapter->ahw->msg_enable & NETIF_MSG_DRV) {
14823620af0eSJoe Perches 		char prefix[30];
1483c70001a9SSony Chacko 
14843620af0eSJoe Perches 		scnprintf(prefix, sizeof(prefix), "%s: %s: ",
14853620af0eSJoe Perches 			  dev_name(&adapter->pdev->dev), __func__);
14863620af0eSJoe Perches 
14873620af0eSJoe Perches 		print_hex_dump_debug(prefix, DUMP_PREFIX_NONE, 16, 1,
14883620af0eSJoe Perches 				     skb->data, skb->len, true);
1489c70001a9SSony Chacko 	}
1490c70001a9SSony Chacko }
1491c70001a9SSony Chacko 
qlcnic_process_rcv_diag(struct qlcnic_adapter * adapter,int ring,u64 sts_data0)1492c70001a9SSony Chacko static void qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter, int ring,
1493c70001a9SSony Chacko 				    u64 sts_data0)
1494c70001a9SSony Chacko {
1495c70001a9SSony Chacko 	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
1496c70001a9SSony Chacko 	struct sk_buff *skb;
1497c70001a9SSony Chacko 	struct qlcnic_host_rds_ring *rds_ring;
1498c70001a9SSony Chacko 	int index, length, cksum, pkt_offset;
1499c70001a9SSony Chacko 
1500c70001a9SSony Chacko 	if (unlikely(ring >= adapter->max_rds_rings))
1501c70001a9SSony Chacko 		return;
1502c70001a9SSony Chacko 
1503c70001a9SSony Chacko 	rds_ring = &recv_ctx->rds_rings[ring];
1504c70001a9SSony Chacko 
1505c70001a9SSony Chacko 	index = qlcnic_get_sts_refhandle(sts_data0);
1506c70001a9SSony Chacko 	length = qlcnic_get_sts_totallength(sts_data0);
1507c70001a9SSony Chacko 	if (unlikely(index >= rds_ring->num_desc))
1508c70001a9SSony Chacko 		return;
1509c70001a9SSony Chacko 
1510c70001a9SSony Chacko 	cksum  = qlcnic_get_sts_status(sts_data0);
1511c70001a9SSony Chacko 	pkt_offset = qlcnic_get_sts_pkt_offset(sts_data0);
1512c70001a9SSony Chacko 
1513c70001a9SSony Chacko 	skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum);
1514c70001a9SSony Chacko 	if (!skb)
1515c70001a9SSony Chacko 		return;
1516c70001a9SSony Chacko 
1517c70001a9SSony Chacko 	if (length > rds_ring->skb_size)
1518c70001a9SSony Chacko 		skb_put(skb, rds_ring->skb_size);
1519c70001a9SSony Chacko 	else
1520c70001a9SSony Chacko 		skb_put(skb, length);
1521c70001a9SSony Chacko 
1522c70001a9SSony Chacko 	if (pkt_offset)
1523c70001a9SSony Chacko 		skb_pull(skb, pkt_offset);
1524c70001a9SSony Chacko 
1525c70001a9SSony Chacko 	if (!qlcnic_check_loopback_buff(skb->data, adapter->mac_addr))
152679788450SSony Chacko 		adapter->ahw->diag_cnt++;
1527c70001a9SSony Chacko 	else
1528c70001a9SSony Chacko 		dump_skb(skb, adapter);
1529c70001a9SSony Chacko 
1530c70001a9SSony Chacko 	dev_kfree_skb_any(skb);
1531c70001a9SSony Chacko 	adapter->stats.rx_pkts++;
1532c70001a9SSony Chacko 	adapter->stats.rxbytes += length;
1533c70001a9SSony Chacko 
1534c70001a9SSony Chacko 	return;
1535c70001a9SSony Chacko }
1536c70001a9SSony Chacko 
qlcnic_82xx_process_rcv_ring_diag(struct qlcnic_host_sds_ring * sds_ring)15377e2cf4feSSony Chacko void qlcnic_82xx_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring)
1538c70001a9SSony Chacko {
1539c70001a9SSony Chacko 	struct qlcnic_adapter *adapter = sds_ring->adapter;
1540c70001a9SSony Chacko 	struct status_desc *desc;
1541c70001a9SSony Chacko 	u64 sts_data0;
1542c70001a9SSony Chacko 	int ring, opcode, desc_cnt;
1543c70001a9SSony Chacko 
1544c70001a9SSony Chacko 	u32 consumer = sds_ring->consumer;
1545c70001a9SSony Chacko 
1546c70001a9SSony Chacko 	desc = &sds_ring->desc_head[consumer];
1547c70001a9SSony Chacko 	sts_data0 = le64_to_cpu(desc->status_desc_data[0]);
1548c70001a9SSony Chacko 
1549c70001a9SSony Chacko 	if (!(sts_data0 & STATUS_OWNER_HOST))
1550c70001a9SSony Chacko 		return;
1551c70001a9SSony Chacko 
1552c70001a9SSony Chacko 	desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0);
1553c70001a9SSony Chacko 	opcode = qlcnic_get_sts_opcode(sts_data0);
1554c70001a9SSony Chacko 	switch (opcode) {
1555c70001a9SSony Chacko 	case QLCNIC_RESPONSE_DESC:
1556c70001a9SSony Chacko 		qlcnic_handle_fw_message(desc_cnt, consumer, sds_ring);
1557c70001a9SSony Chacko 		break;
1558c70001a9SSony Chacko 	default:
1559c70001a9SSony Chacko 		ring = qlcnic_get_sts_type(sts_data0);
1560c70001a9SSony Chacko 		qlcnic_process_rcv_diag(adapter, ring, sts_data0);
1561c70001a9SSony Chacko 		break;
1562c70001a9SSony Chacko 	}
1563c70001a9SSony Chacko 
1564c70001a9SSony Chacko 	for (; desc_cnt > 0; desc_cnt--) {
1565c70001a9SSony Chacko 		desc = &sds_ring->desc_head[consumer];
1566c70001a9SSony Chacko 		desc->status_desc_data[0] = cpu_to_le64(STATUS_OWNER_PHANTOM);
1567c70001a9SSony Chacko 		consumer = get_next_index(consumer, sds_ring->num_desc);
1568c70001a9SSony Chacko 	}
1569c70001a9SSony Chacko 
1570c70001a9SSony Chacko 	sds_ring->consumer = consumer;
1571c70001a9SSony Chacko 	writel(consumer, sds_ring->crb_sts_consumer);
1572c70001a9SSony Chacko }
1573c70001a9SSony Chacko 
qlcnic_82xx_napi_add(struct qlcnic_adapter * adapter,struct net_device * netdev)15747e2cf4feSSony Chacko int qlcnic_82xx_napi_add(struct qlcnic_adapter *adapter,
15757e2cf4feSSony Chacko 			 struct net_device *netdev)
1576c70001a9SSony Chacko {
1577df95fc44SMichal Schmidt 	int ring;
1578c70001a9SSony Chacko 	struct qlcnic_host_sds_ring *sds_ring;
1579c70001a9SSony Chacko 	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
1580012ec812SHimanshu Madhani 	struct qlcnic_host_tx_ring *tx_ring;
1581c70001a9SSony Chacko 
158234e8c406SHimanshu Madhani 	if (qlcnic_alloc_sds_rings(recv_ctx, adapter->drv_sds_rings))
1583c70001a9SSony Chacko 		return -ENOMEM;
1584c70001a9SSony Chacko 
158534e8c406SHimanshu Madhani 	for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
1586c70001a9SSony Chacko 		sds_ring = &recv_ctx->sds_rings[ring];
1587012ec812SHimanshu Madhani 		if (qlcnic_check_multi_tx(adapter) &&
158880c0e4f3SHimanshu Madhani 		    !adapter->ahw->diag_test) {
1589b48b89f9SJakub Kicinski 			netif_napi_add(netdev, &sds_ring->napi,
1590b48b89f9SJakub Kicinski 				       qlcnic_rx_poll);
1591012ec812SHimanshu Madhani 		} else {
159234e8c406SHimanshu Madhani 			if (ring == (adapter->drv_sds_rings - 1))
1593012ec812SHimanshu Madhani 				netif_napi_add(netdev, &sds_ring->napi,
1594b48b89f9SJakub Kicinski 					       qlcnic_poll);
1595012ec812SHimanshu Madhani 			else
1596012ec812SHimanshu Madhani 				netif_napi_add(netdev, &sds_ring->napi,
1597b48b89f9SJakub Kicinski 					       qlcnic_rx_poll);
1598012ec812SHimanshu Madhani 		}
1599c70001a9SSony Chacko 	}
1600c70001a9SSony Chacko 
16014be41e92SSony Chacko 	if (qlcnic_alloc_tx_rings(adapter, netdev)) {
16024be41e92SSony Chacko 		qlcnic_free_sds_rings(recv_ctx);
16034be41e92SSony Chacko 		return -ENOMEM;
16044be41e92SSony Chacko 	}
16054be41e92SSony Chacko 
1606c2c5e3a0SHimanshu Madhani 	if (qlcnic_check_multi_tx(adapter) && !adapter->ahw->diag_test) {
160734e8c406SHimanshu Madhani 		for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
1608012ec812SHimanshu Madhani 			tx_ring = &adapter->tx_ring[ring];
160916d083e2SJakub Kicinski 			netif_napi_add_tx(netdev, &tx_ring->napi,
161016d083e2SJakub Kicinski 					  qlcnic_tx_poll);
1611012ec812SHimanshu Madhani 		}
1612012ec812SHimanshu Madhani 	}
1613012ec812SHimanshu Madhani 
1614c70001a9SSony Chacko 	return 0;
1615c70001a9SSony Chacko }
1616c70001a9SSony Chacko 
qlcnic_82xx_napi_del(struct qlcnic_adapter * adapter)16174be41e92SSony Chacko void qlcnic_82xx_napi_del(struct qlcnic_adapter *adapter)
1618c70001a9SSony Chacko {
1619c70001a9SSony Chacko 	int ring;
1620c70001a9SSony Chacko 	struct qlcnic_host_sds_ring *sds_ring;
1621c70001a9SSony Chacko 	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
1622012ec812SHimanshu Madhani 	struct qlcnic_host_tx_ring *tx_ring;
1623c70001a9SSony Chacko 
162434e8c406SHimanshu Madhani 	for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
1625c70001a9SSony Chacko 		sds_ring = &recv_ctx->sds_rings[ring];
1626c70001a9SSony Chacko 		netif_napi_del(&sds_ring->napi);
1627c70001a9SSony Chacko 	}
1628c70001a9SSony Chacko 
1629c70001a9SSony Chacko 	qlcnic_free_sds_rings(adapter->recv_ctx);
1630012ec812SHimanshu Madhani 
1631c2c5e3a0SHimanshu Madhani 	if (qlcnic_check_multi_tx(adapter) && !adapter->ahw->diag_test) {
163234e8c406SHimanshu Madhani 		for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
1633012ec812SHimanshu Madhani 			tx_ring = &adapter->tx_ring[ring];
1634012ec812SHimanshu Madhani 			netif_napi_del(&tx_ring->napi);
1635012ec812SHimanshu Madhani 		}
1636012ec812SHimanshu Madhani 	}
1637012ec812SHimanshu Madhani 
16384be41e92SSony Chacko 	qlcnic_free_tx_rings(adapter);
1639c70001a9SSony Chacko }
1640c70001a9SSony Chacko 
qlcnic_82xx_napi_enable(struct qlcnic_adapter * adapter)16417e2cf4feSSony Chacko void qlcnic_82xx_napi_enable(struct qlcnic_adapter *adapter)
1642c70001a9SSony Chacko {
1643c70001a9SSony Chacko 	int ring;
1644c70001a9SSony Chacko 	struct qlcnic_host_sds_ring *sds_ring;
1645012ec812SHimanshu Madhani 	struct qlcnic_host_tx_ring *tx_ring;
1646c70001a9SSony Chacko 	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
1647c70001a9SSony Chacko 
1648c70001a9SSony Chacko 	if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
1649c70001a9SSony Chacko 		return;
1650c70001a9SSony Chacko 
165134e8c406SHimanshu Madhani 	for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
1652c70001a9SSony Chacko 		sds_ring = &recv_ctx->sds_rings[ring];
1653c70001a9SSony Chacko 		napi_enable(&sds_ring->napi);
16542cc5752eSManish chopra 		qlcnic_enable_sds_intr(adapter, sds_ring);
1655c70001a9SSony Chacko 	}
1656012ec812SHimanshu Madhani 
1657012ec812SHimanshu Madhani 	if (qlcnic_check_multi_tx(adapter) &&
1658012ec812SHimanshu Madhani 	    (adapter->flags & QLCNIC_MSIX_ENABLED) &&
165980c0e4f3SHimanshu Madhani 	    !adapter->ahw->diag_test) {
166034e8c406SHimanshu Madhani 		for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
1661012ec812SHimanshu Madhani 			tx_ring = &adapter->tx_ring[ring];
1662012ec812SHimanshu Madhani 			napi_enable(&tx_ring->napi);
1663012ec812SHimanshu Madhani 			qlcnic_enable_tx_intr(adapter, tx_ring);
1664012ec812SHimanshu Madhani 		}
1665012ec812SHimanshu Madhani 	}
1666c70001a9SSony Chacko }
1667c70001a9SSony Chacko 
qlcnic_82xx_napi_disable(struct qlcnic_adapter * adapter)16687e2cf4feSSony Chacko void qlcnic_82xx_napi_disable(struct qlcnic_adapter *adapter)
1669c70001a9SSony Chacko {
1670c70001a9SSony Chacko 	int ring;
1671c70001a9SSony Chacko 	struct qlcnic_host_sds_ring *sds_ring;
1672012ec812SHimanshu Madhani 	struct qlcnic_host_tx_ring *tx_ring;
1673c70001a9SSony Chacko 	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
1674c70001a9SSony Chacko 
1675c70001a9SSony Chacko 	if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
1676c70001a9SSony Chacko 		return;
1677c70001a9SSony Chacko 
167834e8c406SHimanshu Madhani 	for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
1679c70001a9SSony Chacko 		sds_ring = &recv_ctx->sds_rings[ring];
16802cc5752eSManish chopra 		qlcnic_disable_sds_intr(adapter, sds_ring);
1681c70001a9SSony Chacko 		napi_synchronize(&sds_ring->napi);
1682c70001a9SSony Chacko 		napi_disable(&sds_ring->napi);
1683c70001a9SSony Chacko 	}
1684012ec812SHimanshu Madhani 
1685012ec812SHimanshu Madhani 	if ((adapter->flags & QLCNIC_MSIX_ENABLED) &&
1686c2c5e3a0SHimanshu Madhani 	    !adapter->ahw->diag_test &&
1687012ec812SHimanshu Madhani 	    qlcnic_check_multi_tx(adapter)) {
168834e8c406SHimanshu Madhani 		for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
1689012ec812SHimanshu Madhani 			tx_ring = &adapter->tx_ring[ring];
16902cc5752eSManish chopra 			qlcnic_disable_tx_intr(adapter, tx_ring);
1691012ec812SHimanshu Madhani 			napi_synchronize(&tx_ring->napi);
1692012ec812SHimanshu Madhani 			napi_disable(&tx_ring->napi);
1693012ec812SHimanshu Madhani 		}
1694012ec812SHimanshu Madhani 	}
1695c70001a9SSony Chacko }
16964be41e92SSony Chacko 
169753643a75SShahed Shaikh #define QLC_83XX_NORMAL_LB_PKT	(1ULL << 36)
169853643a75SShahed Shaikh #define QLC_83XX_LRO_LB_PKT	(1ULL << 46)
169953643a75SShahed Shaikh 
qlcnic_83xx_is_lb_pkt(u64 sts_data,int lro_pkt)170053643a75SShahed Shaikh static inline int qlcnic_83xx_is_lb_pkt(u64 sts_data, int lro_pkt)
170153643a75SShahed Shaikh {
170253643a75SShahed Shaikh 	if (lro_pkt)
170353643a75SShahed Shaikh 		return (sts_data & QLC_83XX_LRO_LB_PKT) ? 1 : 0;
170453643a75SShahed Shaikh 	else
170553643a75SShahed Shaikh 		return (sts_data & QLC_83XX_NORMAL_LB_PKT) ? 1 : 0;
170653643a75SShahed Shaikh }
170753643a75SShahed Shaikh 
17082b3d7b75SShahed Shaikh #define QLCNIC_ENCAP_LENGTH_MASK	0x7f
17092b3d7b75SShahed Shaikh 
qlcnic_encap_length(u64 sts_data)17102b3d7b75SShahed Shaikh static inline u8 qlcnic_encap_length(u64 sts_data)
17112b3d7b75SShahed Shaikh {
17122b3d7b75SShahed Shaikh 	return sts_data & QLCNIC_ENCAP_LENGTH_MASK;
17132b3d7b75SShahed Shaikh }
17142b3d7b75SShahed Shaikh 
17154be41e92SSony 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[])17164be41e92SSony Chacko qlcnic_83xx_process_rcv(struct qlcnic_adapter *adapter,
17174be41e92SSony Chacko 			struct qlcnic_host_sds_ring *sds_ring,
17184be41e92SSony Chacko 			u8 ring, u64 sts_data[])
17194be41e92SSony Chacko {
17204be41e92SSony Chacko 	struct net_device *netdev = adapter->netdev;
17214be41e92SSony Chacko 	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
17224be41e92SSony Chacko 	struct qlcnic_rx_buffer *buffer;
17234be41e92SSony Chacko 	struct sk_buff *skb;
17244be41e92SSony Chacko 	struct qlcnic_host_rds_ring *rds_ring;
172553643a75SShahed Shaikh 	int index, length, cksum, is_lb_pkt;
1726b3f7de83SSucheta Chakraborty 	u16 vid = 0xffff;
1727b3f7de83SSucheta Chakraborty 	int err;
17284be41e92SSony Chacko 
17294be41e92SSony Chacko 	if (unlikely(ring >= adapter->max_rds_rings))
17304be41e92SSony Chacko 		return NULL;
17314be41e92SSony Chacko 
17324be41e92SSony Chacko 	rds_ring = &recv_ctx->rds_rings[ring];
17334be41e92SSony Chacko 
17344be41e92SSony Chacko 	index = qlcnic_83xx_hndl(sts_data[0]);
17354be41e92SSony Chacko 	if (unlikely(index >= rds_ring->num_desc))
17364be41e92SSony Chacko 		return NULL;
17374be41e92SSony Chacko 
17384be41e92SSony Chacko 	buffer = &rds_ring->rx_buf_arr[index];
17394be41e92SSony Chacko 	length = qlcnic_83xx_pktln(sts_data[0]);
17404be41e92SSony Chacko 	cksum  = qlcnic_83xx_csum_status(sts_data[1]);
17414be41e92SSony Chacko 	skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum);
17424be41e92SSony Chacko 	if (!skb)
17434be41e92SSony Chacko 		return buffer;
17444be41e92SSony Chacko 
17454be41e92SSony Chacko 	if (length > rds_ring->skb_size)
17464be41e92SSony Chacko 		skb_put(skb, rds_ring->skb_size);
17474be41e92SSony Chacko 	else
17484be41e92SSony Chacko 		skb_put(skb, length);
17494be41e92SSony Chacko 
1750b3f7de83SSucheta Chakraborty 	err = qlcnic_check_rx_tagging(adapter, skb, &vid);
1751b3f7de83SSucheta Chakraborty 
1752b3f7de83SSucheta Chakraborty 	if (adapter->rx_mac_learn) {
1753b3f7de83SSucheta Chakraborty 		is_lb_pkt = qlcnic_83xx_is_lb_pkt(sts_data[1], 0);
1754b3f7de83SSucheta Chakraborty 		qlcnic_add_lb_filter(adapter, skb, is_lb_pkt, vid);
1755b3f7de83SSucheta Chakraborty 	}
1756b3f7de83SSucheta Chakraborty 
1757b3f7de83SSucheta Chakraborty 	if (unlikely(err)) {
17584be41e92SSony Chacko 		adapter->stats.rxdropped++;
17594be41e92SSony Chacko 		dev_kfree_skb(skb);
17604be41e92SSony Chacko 		return buffer;
17614be41e92SSony Chacko 	}
17624be41e92SSony Chacko 
17634be41e92SSony Chacko 	skb->protocol = eth_type_trans(skb, netdev);
17644be41e92SSony Chacko 
17652b3d7b75SShahed Shaikh 	if (qlcnic_encap_length(sts_data[1]) &&
17662b3d7b75SShahed Shaikh 	    skb->ip_summed == CHECKSUM_UNNECESSARY) {
176771d7a277STom Herbert 		skb->csum_level = 1;
17682b3d7b75SShahed Shaikh 		adapter->stats.encap_rx_csummed++;
17692b3d7b75SShahed Shaikh 	}
17702b3d7b75SShahed Shaikh 
17714be41e92SSony Chacko 	if (vid != 0xffff)
177286a9bad3SPatrick McHardy 		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid);
17734be41e92SSony Chacko 
17744be41e92SSony Chacko 	napi_gro_receive(&sds_ring->napi, skb);
17754be41e92SSony Chacko 
17764be41e92SSony Chacko 	adapter->stats.rx_pkts++;
17774be41e92SSony Chacko 	adapter->stats.rxbytes += length;
17784be41e92SSony Chacko 
17794be41e92SSony Chacko 	return buffer;
17804be41e92SSony Chacko }
17814be41e92SSony Chacko 
17824be41e92SSony Chacko static struct qlcnic_rx_buffer *
qlcnic_83xx_process_lro(struct qlcnic_adapter * adapter,u8 ring,u64 sts_data[])17834be41e92SSony Chacko qlcnic_83xx_process_lro(struct qlcnic_adapter *adapter,
17844be41e92SSony Chacko 			u8 ring, u64 sts_data[])
17854be41e92SSony Chacko {
17864be41e92SSony Chacko 	struct net_device *netdev = adapter->netdev;
17874be41e92SSony Chacko 	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
17884be41e92SSony Chacko 	struct qlcnic_rx_buffer *buffer;
17894be41e92SSony Chacko 	struct sk_buff *skb;
17904be41e92SSony Chacko 	struct qlcnic_host_rds_ring *rds_ring;
17914be41e92SSony Chacko 	struct iphdr *iph;
17924be41e92SSony Chacko 	struct ipv6hdr *ipv6h;
17934be41e92SSony Chacko 	struct tcphdr *th;
17944be41e92SSony Chacko 	bool push;
17954be41e92SSony Chacko 	int l2_hdr_offset, l4_hdr_offset;
179653643a75SShahed Shaikh 	int index, is_lb_pkt;
179799e85879SShahed Shaikh 	u16 lro_length, length, data_offset, gso_size;
1798b3f7de83SSucheta Chakraborty 	u16 vid = 0xffff;
1799b3f7de83SSucheta Chakraborty 	int err;
18004be41e92SSony Chacko 
1801462bed48SManish Chopra 	if (unlikely(ring >= adapter->max_rds_rings))
18024be41e92SSony Chacko 		return NULL;
18034be41e92SSony Chacko 
18044be41e92SSony Chacko 	rds_ring = &recv_ctx->rds_rings[ring];
18054be41e92SSony Chacko 
18064be41e92SSony Chacko 	index = qlcnic_83xx_hndl(sts_data[0]);
1807462bed48SManish Chopra 	if (unlikely(index >= rds_ring->num_desc))
18084be41e92SSony Chacko 		return NULL;
18094be41e92SSony Chacko 
18104be41e92SSony Chacko 	buffer = &rds_ring->rx_buf_arr[index];
18114be41e92SSony Chacko 
18124be41e92SSony Chacko 	lro_length = qlcnic_83xx_lro_pktln(sts_data[0]);
18134be41e92SSony Chacko 	l2_hdr_offset = qlcnic_83xx_l2_hdr_off(sts_data[1]);
18144be41e92SSony Chacko 	l4_hdr_offset = qlcnic_83xx_l4_hdr_off(sts_data[1]);
18154be41e92SSony Chacko 	push = qlcnic_83xx_is_psh_bit(sts_data[1]);
18164be41e92SSony Chacko 
18174be41e92SSony Chacko 	skb = qlcnic_process_rxbuf(adapter, rds_ring, index, STATUS_CKSUM_OK);
18184be41e92SSony Chacko 	if (!skb)
18194be41e92SSony Chacko 		return buffer;
182053643a75SShahed Shaikh 
18214be41e92SSony Chacko 	if (qlcnic_83xx_is_tstamp(sts_data[1]))
18224be41e92SSony Chacko 		data_offset = l4_hdr_offset + QLCNIC_TCP_TS_HDR_SIZE;
18234be41e92SSony Chacko 	else
18244be41e92SSony Chacko 		data_offset = l4_hdr_offset + QLCNIC_TCP_HDR_SIZE;
18254be41e92SSony Chacko 
18264be41e92SSony Chacko 	skb_put(skb, lro_length + data_offset);
18274be41e92SSony Chacko 	skb_pull(skb, l2_hdr_offset);
18284be41e92SSony Chacko 
1829b3f7de83SSucheta Chakraborty 	err = qlcnic_check_rx_tagging(adapter, skb, &vid);
1830b3f7de83SSucheta Chakraborty 
1831b3f7de83SSucheta Chakraborty 	if (adapter->rx_mac_learn) {
1832b3f7de83SSucheta Chakraborty 		is_lb_pkt = qlcnic_83xx_is_lb_pkt(sts_data[1], 1);
1833b3f7de83SSucheta Chakraborty 		qlcnic_add_lb_filter(adapter, skb, is_lb_pkt, vid);
1834b3f7de83SSucheta Chakraborty 	}
1835b3f7de83SSucheta Chakraborty 
1836b3f7de83SSucheta Chakraborty 	if (unlikely(err)) {
18374be41e92SSony Chacko 		adapter->stats.rxdropped++;
18384be41e92SSony Chacko 		dev_kfree_skb(skb);
18394be41e92SSony Chacko 		return buffer;
18404be41e92SSony Chacko 	}
18414be41e92SSony Chacko 
18424be41e92SSony Chacko 	skb->protocol = eth_type_trans(skb, netdev);
18434be41e92SSony Chacko 	if (ntohs(skb->protocol) == ETH_P_IPV6) {
18444be41e92SSony Chacko 		ipv6h = (struct ipv6hdr *)skb->data;
18454be41e92SSony Chacko 		th = (struct tcphdr *)(skb->data + sizeof(struct ipv6hdr));
18464be41e92SSony Chacko 
18474be41e92SSony Chacko 		length = (th->doff << 2) + lro_length;
18484be41e92SSony Chacko 		ipv6h->payload_len = htons(length);
18494be41e92SSony Chacko 	} else {
18504be41e92SSony Chacko 		iph = (struct iphdr *)skb->data;
18514be41e92SSony Chacko 		th = (struct tcphdr *)(skb->data + (iph->ihl << 2));
18524be41e92SSony Chacko 		length = (iph->ihl << 2) + (th->doff << 2) + lro_length;
18531bcac3b0SLi RongQing 		csum_replace2(&iph->check, iph->tot_len, htons(length));
18544be41e92SSony Chacko 		iph->tot_len = htons(length);
18554be41e92SSony Chacko 	}
18564be41e92SSony Chacko 
18574be41e92SSony Chacko 	th->psh = push;
18584be41e92SSony Chacko 	length = skb->len;
18594be41e92SSony Chacko 
186099e85879SShahed Shaikh 	if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP) {
186199e85879SShahed Shaikh 		gso_size = qlcnic_83xx_get_lro_sts_mss(sts_data[0]);
186299e85879SShahed Shaikh 		skb_shinfo(skb)->gso_size = gso_size;
186399e85879SShahed Shaikh 		if (skb->protocol == htons(ETH_P_IPV6))
186499e85879SShahed Shaikh 			skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
186599e85879SShahed Shaikh 		else
186699e85879SShahed Shaikh 			skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
186799e85879SShahed Shaikh 	}
186899e85879SShahed Shaikh 
18694be41e92SSony Chacko 	if (vid != 0xffff)
187086a9bad3SPatrick McHardy 		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid);
18714be41e92SSony Chacko 
18724be41e92SSony Chacko 	netif_receive_skb(skb);
18734be41e92SSony Chacko 
18744be41e92SSony Chacko 	adapter->stats.lro_pkts++;
18754be41e92SSony Chacko 	adapter->stats.lrobytes += length;
18764be41e92SSony Chacko 	return buffer;
18774be41e92SSony Chacko }
18784be41e92SSony Chacko 
qlcnic_83xx_process_rcv_ring(struct qlcnic_host_sds_ring * sds_ring,int max)18794be41e92SSony Chacko static int qlcnic_83xx_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring,
18804be41e92SSony Chacko 					int max)
18814be41e92SSony Chacko {
18824be41e92SSony Chacko 	struct qlcnic_host_rds_ring *rds_ring;
18834be41e92SSony Chacko 	struct qlcnic_adapter *adapter = sds_ring->adapter;
18844be41e92SSony Chacko 	struct list_head *cur;
18854be41e92SSony Chacko 	struct status_desc *desc;
18864be41e92SSony Chacko 	struct qlcnic_rx_buffer *rxbuf = NULL;
18874be41e92SSony Chacko 	u8 ring;
18884be41e92SSony Chacko 	u64 sts_data[2];
18894be41e92SSony Chacko 	int count = 0, opcode;
18904be41e92SSony Chacko 	u32 consumer = sds_ring->consumer;
18914be41e92SSony Chacko 
18924be41e92SSony Chacko 	while (count < max) {
18934be41e92SSony Chacko 		desc = &sds_ring->desc_head[consumer];
18944be41e92SSony Chacko 		sts_data[1] = le64_to_cpu(desc->status_desc_data[1]);
18954be41e92SSony Chacko 		opcode = qlcnic_83xx_opcode(sts_data[1]);
18964be41e92SSony Chacko 		if (!opcode)
18974be41e92SSony Chacko 			break;
18984be41e92SSony Chacko 		sts_data[0] = le64_to_cpu(desc->status_desc_data[0]);
18994be41e92SSony Chacko 		ring = QLCNIC_FETCH_RING_ID(sts_data[0]);
19004be41e92SSony Chacko 
19014be41e92SSony Chacko 		switch (opcode) {
19024be41e92SSony Chacko 		case QLC_83XX_REG_DESC:
19034be41e92SSony Chacko 			rxbuf = qlcnic_83xx_process_rcv(adapter, sds_ring,
19044be41e92SSony Chacko 							ring, sts_data);
19054be41e92SSony Chacko 			break;
19064be41e92SSony Chacko 		case QLC_83XX_LRO_DESC:
19074be41e92SSony Chacko 			rxbuf = qlcnic_83xx_process_lro(adapter, ring,
19084be41e92SSony Chacko 							sts_data);
19094be41e92SSony Chacko 			break;
19104be41e92SSony Chacko 		default:
19114be41e92SSony Chacko 			dev_info(&adapter->pdev->dev,
19120b1587b1SMasanari Iida 				 "Unknown opcode: 0x%x\n", opcode);
19134be41e92SSony Chacko 			goto skip;
19144be41e92SSony Chacko 		}
19154be41e92SSony Chacko 
19164be41e92SSony Chacko 		if (likely(rxbuf))
19174be41e92SSony Chacko 			list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]);
19184be41e92SSony Chacko 		else
19194be41e92SSony Chacko 			adapter->stats.null_rxbuf++;
19204be41e92SSony Chacko skip:
19214be41e92SSony Chacko 		desc = &sds_ring->desc_head[consumer];
19224be41e92SSony Chacko 		/* Reset the descriptor */
19234be41e92SSony Chacko 		desc->status_desc_data[1] = 0;
19244be41e92SSony Chacko 		consumer = get_next_index(consumer, sds_ring->num_desc);
19254be41e92SSony Chacko 		count++;
19264be41e92SSony Chacko 	}
19274be41e92SSony Chacko 	for (ring = 0; ring < adapter->max_rds_rings; ring++) {
19284be41e92SSony Chacko 		rds_ring = &adapter->recv_ctx->rds_rings[ring];
19294be41e92SSony Chacko 		if (!list_empty(&sds_ring->free_list[ring])) {
19304be41e92SSony Chacko 			list_for_each(cur, &sds_ring->free_list[ring]) {
19314be41e92SSony Chacko 				rxbuf = list_entry(cur, struct qlcnic_rx_buffer,
19324be41e92SSony Chacko 						   list);
19334be41e92SSony Chacko 				qlcnic_alloc_rx_skb(adapter, rds_ring, rxbuf);
19344be41e92SSony Chacko 			}
19354be41e92SSony Chacko 			spin_lock(&rds_ring->lock);
19364be41e92SSony Chacko 			list_splice_tail_init(&sds_ring->free_list[ring],
19374be41e92SSony Chacko 					      &rds_ring->free_list);
19384be41e92SSony Chacko 			spin_unlock(&rds_ring->lock);
19394be41e92SSony Chacko 		}
19404be41e92SSony Chacko 		qlcnic_post_rx_buffers_nodb(adapter, rds_ring, ring);
19414be41e92SSony Chacko 	}
19424be41e92SSony Chacko 	if (count) {
19434be41e92SSony Chacko 		sds_ring->consumer = consumer;
19444be41e92SSony Chacko 		writel(consumer, sds_ring->crb_sts_consumer);
19454be41e92SSony Chacko 	}
19464be41e92SSony Chacko 	return count;
19474be41e92SSony Chacko }
19484be41e92SSony Chacko 
qlcnic_83xx_msix_sriov_vf_poll(struct napi_struct * napi,int budget)1949da6c8063SRajesh Borundia static int qlcnic_83xx_msix_sriov_vf_poll(struct napi_struct *napi, int budget)
1950da6c8063SRajesh Borundia {
1951da6c8063SRajesh Borundia 	int tx_complete;
1952da6c8063SRajesh Borundia 	int work_done;
1953da6c8063SRajesh Borundia 	struct qlcnic_host_sds_ring *sds_ring;
1954da6c8063SRajesh Borundia 	struct qlcnic_adapter *adapter;
1955da6c8063SRajesh Borundia 	struct qlcnic_host_tx_ring *tx_ring;
1956da6c8063SRajesh Borundia 
1957da6c8063SRajesh Borundia 	sds_ring = container_of(napi, struct qlcnic_host_sds_ring, napi);
1958da6c8063SRajesh Borundia 	adapter = sds_ring->adapter;
1959da6c8063SRajesh Borundia 	/* tx ring count = 1 */
1960da6c8063SRajesh Borundia 	tx_ring = adapter->tx_ring;
1961da6c8063SRajesh Borundia 
1962da6c8063SRajesh Borundia 	tx_complete = qlcnic_process_cmd_ring(adapter, tx_ring, budget);
1963da6c8063SRajesh Borundia 	work_done = qlcnic_83xx_process_rcv_ring(sds_ring, budget);
1964f31ec95fSShahed Shaikh 
1965f31ec95fSShahed Shaikh 	/* Check if we need a repoll */
1966f31ec95fSShahed Shaikh 	if (!tx_complete)
1967f31ec95fSShahed Shaikh 		work_done = budget;
1968f31ec95fSShahed Shaikh 
1969f31ec95fSShahed Shaikh 	if (work_done < budget) {
19706ad20165SEric Dumazet 		napi_complete_done(&sds_ring->napi, work_done);
19712cc5752eSManish chopra 		qlcnic_enable_sds_intr(adapter, sds_ring);
1972da6c8063SRajesh Borundia 	}
1973da6c8063SRajesh Borundia 
1974da6c8063SRajesh Borundia 	return work_done;
1975da6c8063SRajesh Borundia }
1976da6c8063SRajesh Borundia 
qlcnic_83xx_poll(struct napi_struct * napi,int budget)19774be41e92SSony Chacko static int qlcnic_83xx_poll(struct napi_struct *napi, int budget)
19784be41e92SSony Chacko {
19794be41e92SSony Chacko 	int tx_complete;
19804be41e92SSony Chacko 	int work_done;
19814be41e92SSony Chacko 	struct qlcnic_host_sds_ring *sds_ring;
19824be41e92SSony Chacko 	struct qlcnic_adapter *adapter;
19834be41e92SSony Chacko 	struct qlcnic_host_tx_ring *tx_ring;
19844be41e92SSony Chacko 
19854be41e92SSony Chacko 	sds_ring = container_of(napi, struct qlcnic_host_sds_ring, napi);
19864be41e92SSony Chacko 	adapter = sds_ring->adapter;
19874be41e92SSony Chacko 	/* tx ring count = 1 */
19884be41e92SSony Chacko 	tx_ring = adapter->tx_ring;
19894be41e92SSony Chacko 
19904be41e92SSony Chacko 	tx_complete = qlcnic_process_cmd_ring(adapter, tx_ring, budget);
19914be41e92SSony Chacko 	work_done = qlcnic_83xx_process_rcv_ring(sds_ring, budget);
1992f31ec95fSShahed Shaikh 
1993f31ec95fSShahed Shaikh 	/* Check if we need a repoll */
1994f31ec95fSShahed Shaikh 	if (!tx_complete)
1995f31ec95fSShahed Shaikh 		work_done = budget;
1996f31ec95fSShahed Shaikh 
1997f31ec95fSShahed Shaikh 	if (work_done < budget) {
19986ad20165SEric Dumazet 		napi_complete_done(&sds_ring->napi, work_done);
19992cc5752eSManish chopra 		qlcnic_enable_sds_intr(adapter, sds_ring);
20004be41e92SSony Chacko 	}
20014be41e92SSony Chacko 
20024be41e92SSony Chacko 	return work_done;
20034be41e92SSony Chacko }
20044be41e92SSony Chacko 
qlcnic_83xx_msix_tx_poll(struct napi_struct * napi,int budget)20054be41e92SSony Chacko static int qlcnic_83xx_msix_tx_poll(struct napi_struct *napi, int budget)
20064be41e92SSony Chacko {
20074be41e92SSony Chacko 	int work_done;
20084be41e92SSony Chacko 	struct qlcnic_host_tx_ring *tx_ring;
20094be41e92SSony Chacko 	struct qlcnic_adapter *adapter;
20104be41e92SSony Chacko 
20114be41e92SSony Chacko 	tx_ring = container_of(napi, struct qlcnic_host_tx_ring, napi);
20124be41e92SSony Chacko 	adapter = tx_ring->adapter;
20134be41e92SSony Chacko 	work_done = qlcnic_process_cmd_ring(adapter, tx_ring, budget);
20144be41e92SSony Chacko 	if (work_done) {
20154be41e92SSony Chacko 		napi_complete(&tx_ring->napi);
20164be41e92SSony Chacko 		if (test_bit(__QLCNIC_DEV_UP , &adapter->state))
20172cc5752eSManish chopra 			qlcnic_enable_tx_intr(adapter, tx_ring);
2018f31ec95fSShahed Shaikh 	} else {
2019f31ec95fSShahed Shaikh 		/* need a repoll */
2020f31ec95fSShahed Shaikh 		work_done = budget;
20214be41e92SSony Chacko 	}
20224be41e92SSony Chacko 
20234be41e92SSony Chacko 	return work_done;
20244be41e92SSony Chacko }
20254be41e92SSony Chacko 
qlcnic_83xx_rx_poll(struct napi_struct * napi,int budget)20264be41e92SSony Chacko static int qlcnic_83xx_rx_poll(struct napi_struct *napi, int budget)
20274be41e92SSony Chacko {
20284be41e92SSony Chacko 	int work_done;
20294be41e92SSony Chacko 	struct qlcnic_host_sds_ring *sds_ring;
20304be41e92SSony Chacko 	struct qlcnic_adapter *adapter;
20314be41e92SSony Chacko 
20324be41e92SSony Chacko 	sds_ring = container_of(napi, struct qlcnic_host_sds_ring, napi);
20334be41e92SSony Chacko 	adapter = sds_ring->adapter;
20344be41e92SSony Chacko 	work_done = qlcnic_83xx_process_rcv_ring(sds_ring, budget);
20354be41e92SSony Chacko 	if (work_done < budget) {
20366ad20165SEric Dumazet 		napi_complete_done(&sds_ring->napi, work_done);
20374be41e92SSony Chacko 		if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
20382cc5752eSManish chopra 			qlcnic_enable_sds_intr(adapter, sds_ring);
20394be41e92SSony Chacko 	}
20404be41e92SSony Chacko 
20414be41e92SSony Chacko 	return work_done;
20424be41e92SSony Chacko }
20434be41e92SSony Chacko 
qlcnic_83xx_napi_enable(struct qlcnic_adapter * adapter)20444be41e92SSony Chacko void qlcnic_83xx_napi_enable(struct qlcnic_adapter *adapter)
20454be41e92SSony Chacko {
20464be41e92SSony Chacko 	int ring;
20474be41e92SSony Chacko 	struct qlcnic_host_sds_ring *sds_ring;
20484be41e92SSony Chacko 	struct qlcnic_host_tx_ring *tx_ring;
20494be41e92SSony Chacko 	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
20504be41e92SSony Chacko 
20514be41e92SSony Chacko 	if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
20524be41e92SSony Chacko 		return;
20534be41e92SSony Chacko 
205434e8c406SHimanshu Madhani 	for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
20554be41e92SSony Chacko 		sds_ring = &recv_ctx->sds_rings[ring];
20564be41e92SSony Chacko 		napi_enable(&sds_ring->napi);
2057ac166700SHimanshu Madhani 		if (adapter->flags & QLCNIC_MSIX_ENABLED)
20582cc5752eSManish chopra 			qlcnic_enable_sds_intr(adapter, sds_ring);
20594be41e92SSony Chacko 	}
20604be41e92SSony Chacko 
2061da6c8063SRajesh Borundia 	if ((adapter->flags & QLCNIC_MSIX_ENABLED) &&
2062da6c8063SRajesh Borundia 	    !(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
206334e8c406SHimanshu Madhani 		for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
20644be41e92SSony Chacko 			tx_ring = &adapter->tx_ring[ring];
20654be41e92SSony Chacko 			napi_enable(&tx_ring->napi);
20662cc5752eSManish chopra 			qlcnic_enable_tx_intr(adapter, tx_ring);
20674be41e92SSony Chacko 		}
20684be41e92SSony Chacko 	}
20694be41e92SSony Chacko }
20704be41e92SSony Chacko 
qlcnic_83xx_napi_disable(struct qlcnic_adapter * adapter)20714be41e92SSony Chacko void qlcnic_83xx_napi_disable(struct qlcnic_adapter *adapter)
20724be41e92SSony Chacko {
20734be41e92SSony Chacko 	int ring;
20744be41e92SSony Chacko 	struct qlcnic_host_sds_ring *sds_ring;
20754be41e92SSony Chacko 	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
20764be41e92SSony Chacko 	struct qlcnic_host_tx_ring *tx_ring;
20774be41e92SSony Chacko 
20784be41e92SSony Chacko 	if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
20794be41e92SSony Chacko 		return;
20804be41e92SSony Chacko 
208134e8c406SHimanshu Madhani 	for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
20824be41e92SSony Chacko 		sds_ring = &recv_ctx->sds_rings[ring];
2083ac166700SHimanshu Madhani 		if (adapter->flags & QLCNIC_MSIX_ENABLED)
20842cc5752eSManish chopra 			qlcnic_disable_sds_intr(adapter, sds_ring);
20854be41e92SSony Chacko 		napi_synchronize(&sds_ring->napi);
20864be41e92SSony Chacko 		napi_disable(&sds_ring->napi);
20874be41e92SSony Chacko 	}
20884be41e92SSony Chacko 
2089da6c8063SRajesh Borundia 	if ((adapter->flags & QLCNIC_MSIX_ENABLED) &&
2090da6c8063SRajesh Borundia 	    !(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
209134e8c406SHimanshu Madhani 		for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
20924be41e92SSony Chacko 			tx_ring = &adapter->tx_ring[ring];
20932cc5752eSManish chopra 			qlcnic_disable_tx_intr(adapter, tx_ring);
20944be41e92SSony Chacko 			napi_synchronize(&tx_ring->napi);
20954be41e92SSony Chacko 			napi_disable(&tx_ring->napi);
20964be41e92SSony Chacko 		}
20974be41e92SSony Chacko 	}
20984be41e92SSony Chacko }
20994be41e92SSony Chacko 
qlcnic_83xx_napi_add(struct qlcnic_adapter * adapter,struct net_device * netdev)21004be41e92SSony Chacko int qlcnic_83xx_napi_add(struct qlcnic_adapter *adapter,
21014be41e92SSony Chacko 			 struct net_device *netdev)
21024be41e92SSony Chacko {
2103df95fc44SMichal Schmidt 	int ring;
21044be41e92SSony Chacko 	struct qlcnic_host_sds_ring *sds_ring;
21054be41e92SSony Chacko 	struct qlcnic_host_tx_ring *tx_ring;
21064be41e92SSony Chacko 	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
21074be41e92SSony Chacko 
210834e8c406SHimanshu Madhani 	if (qlcnic_alloc_sds_rings(recv_ctx, adapter->drv_sds_rings))
21094be41e92SSony Chacko 		return -ENOMEM;
21104be41e92SSony Chacko 
211134e8c406SHimanshu Madhani 	for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
21124be41e92SSony Chacko 		sds_ring = &recv_ctx->sds_rings[ring];
2113da6c8063SRajesh Borundia 		if (adapter->flags & QLCNIC_MSIX_ENABLED) {
2114df95fc44SMichal Schmidt 			if (!(adapter->flags & QLCNIC_TX_INTR_SHARED))
21154be41e92SSony Chacko 				netif_napi_add(netdev, &sds_ring->napi,
2116b48b89f9SJakub Kicinski 					       qlcnic_83xx_rx_poll);
2117df95fc44SMichal Schmidt 			else
2118da6c8063SRajesh Borundia 				netif_napi_add(netdev, &sds_ring->napi,
2119b48b89f9SJakub Kicinski 					       qlcnic_83xx_msix_sriov_vf_poll);
2120da6c8063SRajesh Borundia 
2121da6c8063SRajesh Borundia 		} else {
21224be41e92SSony Chacko 			netif_napi_add(netdev, &sds_ring->napi,
2123b48b89f9SJakub Kicinski 				       qlcnic_83xx_poll);
21244be41e92SSony Chacko 		}
2125da6c8063SRajesh Borundia 	}
21264be41e92SSony Chacko 
21274be41e92SSony Chacko 	if (qlcnic_alloc_tx_rings(adapter, netdev)) {
21284be41e92SSony Chacko 		qlcnic_free_sds_rings(recv_ctx);
21294be41e92SSony Chacko 		return -ENOMEM;
21304be41e92SSony Chacko 	}
21314be41e92SSony Chacko 
2132da6c8063SRajesh Borundia 	if ((adapter->flags & QLCNIC_MSIX_ENABLED) &&
2133da6c8063SRajesh Borundia 	    !(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
213434e8c406SHimanshu Madhani 		for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
21354be41e92SSony Chacko 			tx_ring = &adapter->tx_ring[ring];
213616d083e2SJakub Kicinski 			netif_napi_add_tx(netdev, &tx_ring->napi,
213716d083e2SJakub Kicinski 					  qlcnic_83xx_msix_tx_poll);
21384be41e92SSony Chacko 		}
21394be41e92SSony Chacko 	}
21404be41e92SSony Chacko 
21414be41e92SSony Chacko 	return 0;
21424be41e92SSony Chacko }
21434be41e92SSony Chacko 
qlcnic_83xx_napi_del(struct qlcnic_adapter * adapter)21444be41e92SSony Chacko void qlcnic_83xx_napi_del(struct qlcnic_adapter *adapter)
21454be41e92SSony Chacko {
21464be41e92SSony Chacko 	int ring;
21474be41e92SSony Chacko 	struct qlcnic_host_sds_ring *sds_ring;
21484be41e92SSony Chacko 	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
21494be41e92SSony Chacko 	struct qlcnic_host_tx_ring *tx_ring;
21504be41e92SSony Chacko 
215134e8c406SHimanshu Madhani 	for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
21524be41e92SSony Chacko 		sds_ring = &recv_ctx->sds_rings[ring];
21534be41e92SSony Chacko 		netif_napi_del(&sds_ring->napi);
21544be41e92SSony Chacko 	}
21554be41e92SSony Chacko 
21564be41e92SSony Chacko 	qlcnic_free_sds_rings(adapter->recv_ctx);
21574be41e92SSony Chacko 
2158da6c8063SRajesh Borundia 	if ((adapter->flags & QLCNIC_MSIX_ENABLED) &&
2159da6c8063SRajesh Borundia 	    !(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
216034e8c406SHimanshu Madhani 		for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
21614be41e92SSony Chacko 			tx_ring = &adapter->tx_ring[ring];
21624be41e92SSony Chacko 			netif_napi_del(&tx_ring->napi);
21634be41e92SSony Chacko 		}
21644be41e92SSony Chacko 	}
21654be41e92SSony Chacko 
21664be41e92SSony Chacko 	qlcnic_free_tx_rings(adapter);
21674be41e92SSony Chacko }
21684be41e92SSony Chacko 
qlcnic_83xx_process_rcv_diag(struct qlcnic_adapter * adapter,int ring,u64 sts_data[])216921041400Sstephen hemminger static void qlcnic_83xx_process_rcv_diag(struct qlcnic_adapter *adapter,
21704be41e92SSony Chacko 					 int ring, u64 sts_data[])
21714be41e92SSony Chacko {
21724be41e92SSony Chacko 	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
21734be41e92SSony Chacko 	struct sk_buff *skb;
21744be41e92SSony Chacko 	struct qlcnic_host_rds_ring *rds_ring;
21754be41e92SSony Chacko 	int index, length;
21764be41e92SSony Chacko 
21774be41e92SSony Chacko 	if (unlikely(ring >= adapter->max_rds_rings))
21784be41e92SSony Chacko 		return;
21794be41e92SSony Chacko 
21804be41e92SSony Chacko 	rds_ring = &recv_ctx->rds_rings[ring];
21814be41e92SSony Chacko 	index = qlcnic_83xx_hndl(sts_data[0]);
21824be41e92SSony Chacko 	if (unlikely(index >= rds_ring->num_desc))
21834be41e92SSony Chacko 		return;
21844be41e92SSony Chacko 
21854be41e92SSony Chacko 	length = qlcnic_83xx_pktln(sts_data[0]);
21864be41e92SSony Chacko 
21874be41e92SSony Chacko 	skb = qlcnic_process_rxbuf(adapter, rds_ring, index, STATUS_CKSUM_OK);
21884be41e92SSony Chacko 	if (!skb)
21894be41e92SSony Chacko 		return;
21904be41e92SSony Chacko 
21914be41e92SSony Chacko 	if (length > rds_ring->skb_size)
21924be41e92SSony Chacko 		skb_put(skb, rds_ring->skb_size);
21934be41e92SSony Chacko 	else
21944be41e92SSony Chacko 		skb_put(skb, length);
21954be41e92SSony Chacko 
21964be41e92SSony Chacko 	if (!qlcnic_check_loopback_buff(skb->data, adapter->mac_addr))
21974be41e92SSony Chacko 		adapter->ahw->diag_cnt++;
21984be41e92SSony Chacko 	else
21994be41e92SSony Chacko 		dump_skb(skb, adapter);
22004be41e92SSony Chacko 
22014be41e92SSony Chacko 	dev_kfree_skb_any(skb);
22024be41e92SSony Chacko 	return;
22034be41e92SSony Chacko }
22044be41e92SSony Chacko 
qlcnic_83xx_process_rcv_ring_diag(struct qlcnic_host_sds_ring * sds_ring)22054be41e92SSony Chacko void qlcnic_83xx_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring)
22064be41e92SSony Chacko {
22074be41e92SSony Chacko 	struct qlcnic_adapter *adapter = sds_ring->adapter;
22084be41e92SSony Chacko 	struct status_desc *desc;
22094be41e92SSony Chacko 	u64 sts_data[2];
22104be41e92SSony Chacko 	int ring, opcode;
22114be41e92SSony Chacko 	u32 consumer = sds_ring->consumer;
22124be41e92SSony Chacko 
22134be41e92SSony Chacko 	desc = &sds_ring->desc_head[consumer];
22144be41e92SSony Chacko 	sts_data[0] = le64_to_cpu(desc->status_desc_data[0]);
22154be41e92SSony Chacko 	sts_data[1] = le64_to_cpu(desc->status_desc_data[1]);
22164be41e92SSony Chacko 	opcode = qlcnic_83xx_opcode(sts_data[1]);
22174be41e92SSony Chacko 	if (!opcode)
22184be41e92SSony Chacko 		return;
22194be41e92SSony Chacko 
22205b4d10f5SDan Carpenter 	ring = QLCNIC_FETCH_RING_ID(sts_data[0]);
22214be41e92SSony Chacko 	qlcnic_83xx_process_rcv_diag(adapter, ring, sts_data);
22224be41e92SSony Chacko 	desc = &sds_ring->desc_head[consumer];
22234be41e92SSony Chacko 	desc->status_desc_data[0] = cpu_to_le64(STATUS_OWNER_PHANTOM);
22244be41e92SSony Chacko 	consumer = get_next_index(consumer, sds_ring->num_desc);
22254be41e92SSony Chacko 	sds_ring->consumer = consumer;
22264be41e92SSony Chacko 	writel(consumer, sds_ring->crb_sts_consumer);
22274be41e92SSony Chacko }
2228