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