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