1f7917c00SJeff Kirsher /*
2f7917c00SJeff Kirsher  * This file is part of the Chelsio T4 Ethernet driver for Linux.
3f7917c00SJeff Kirsher  *
4ce100b8bSAnish Bhatt  * Copyright (c) 2003-2014 Chelsio Communications, Inc. All rights reserved.
5f7917c00SJeff Kirsher  *
6f7917c00SJeff Kirsher  * This software is available to you under a choice of one of two
7f7917c00SJeff Kirsher  * licenses.  You may choose to be licensed under the terms of the GNU
8f7917c00SJeff Kirsher  * General Public License (GPL) Version 2, available from the file
9f7917c00SJeff Kirsher  * COPYING in the main directory of this source tree, or the
10f7917c00SJeff Kirsher  * OpenIB.org BSD license below:
11f7917c00SJeff Kirsher  *
12f7917c00SJeff Kirsher  *     Redistribution and use in source and binary forms, with or
13f7917c00SJeff Kirsher  *     without modification, are permitted provided that the following
14f7917c00SJeff Kirsher  *     conditions are met:
15f7917c00SJeff Kirsher  *
16f7917c00SJeff Kirsher  *      - Redistributions of source code must retain the above
17f7917c00SJeff Kirsher  *        copyright notice, this list of conditions and the following
18f7917c00SJeff Kirsher  *        disclaimer.
19f7917c00SJeff Kirsher  *
20f7917c00SJeff Kirsher  *      - Redistributions in binary form must reproduce the above
21f7917c00SJeff Kirsher  *        copyright notice, this list of conditions and the following
22f7917c00SJeff Kirsher  *        disclaimer in the documentation and/or other materials
23f7917c00SJeff Kirsher  *        provided with the distribution.
24f7917c00SJeff Kirsher  *
25f7917c00SJeff Kirsher  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26f7917c00SJeff Kirsher  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27f7917c00SJeff Kirsher  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28f7917c00SJeff Kirsher  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29f7917c00SJeff Kirsher  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30f7917c00SJeff Kirsher  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31f7917c00SJeff Kirsher  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32f7917c00SJeff Kirsher  * SOFTWARE.
33f7917c00SJeff Kirsher  */
34f7917c00SJeff Kirsher 
35f7917c00SJeff Kirsher #include <linux/skbuff.h>
36f7917c00SJeff Kirsher #include <linux/netdevice.h>
37f7917c00SJeff Kirsher #include <linux/etherdevice.h>
38f7917c00SJeff Kirsher #include <linux/if_vlan.h>
39f7917c00SJeff Kirsher #include <linux/ip.h>
40f7917c00SJeff Kirsher #include <linux/dma-mapping.h>
41f7917c00SJeff Kirsher #include <linux/jiffies.h>
42f7917c00SJeff Kirsher #include <linux/prefetch.h>
43ee40fa06SPaul Gortmaker #include <linux/export.h>
44a6ec572bSAtul Gupta #include <net/xfrm.h>
45f7917c00SJeff Kirsher #include <net/ipv6.h>
46f7917c00SJeff Kirsher #include <net/tcp.h>
473a336cb1SHariprasad Shenai #include <net/busy_poll.h>
4884a200b3SVarun Prakash #ifdef CONFIG_CHELSIO_T4_FCOE
4984a200b3SVarun Prakash #include <scsi/fc/fc_fcoe.h>
5084a200b3SVarun Prakash #endif /* CONFIG_CHELSIO_T4_FCOE */
51f7917c00SJeff Kirsher #include "cxgb4.h"
52f7917c00SJeff Kirsher #include "t4_regs.h"
53f612b815SHariprasad Shenai #include "t4_values.h"
54f7917c00SJeff Kirsher #include "t4_msg.h"
55f7917c00SJeff Kirsher #include "t4fw_api.h"
56a4569504SAtul Gupta #include "cxgb4_ptp.h"
57a6ec572bSAtul Gupta #include "cxgb4_uld.h"
584846d533SRahul Lakkireddy #include "cxgb4_tc_mqprio.h"
590e395b3cSRahul Lakkireddy #include "sched.h"
60f7917c00SJeff Kirsher 
61f7917c00SJeff Kirsher /*
62f7917c00SJeff Kirsher  * Rx buffer size.  We use largish buffers if possible but settle for single
63f7917c00SJeff Kirsher  * pages under memory shortage.
64f7917c00SJeff Kirsher  */
65f7917c00SJeff Kirsher #if PAGE_SHIFT >= 16
66f7917c00SJeff Kirsher # define FL_PG_ORDER 0
67f7917c00SJeff Kirsher #else
68f7917c00SJeff Kirsher # define FL_PG_ORDER (16 - PAGE_SHIFT)
69f7917c00SJeff Kirsher #endif
70f7917c00SJeff Kirsher 
71f7917c00SJeff Kirsher /* RX_PULL_LEN should be <= RX_COPY_THRES */
72f7917c00SJeff Kirsher #define RX_COPY_THRES    256
73f7917c00SJeff Kirsher #define RX_PULL_LEN      128
74f7917c00SJeff Kirsher 
75f7917c00SJeff Kirsher /*
76f7917c00SJeff Kirsher  * Main body length for sk_buffs used for Rx Ethernet packets with fragments.
77f7917c00SJeff Kirsher  * Should be >= RX_PULL_LEN but possibly bigger to give pskb_may_pull some room.
78f7917c00SJeff Kirsher  */
79f7917c00SJeff Kirsher #define RX_PKT_SKB_LEN   512
80f7917c00SJeff Kirsher 
81f7917c00SJeff Kirsher /*
82f7917c00SJeff Kirsher  * Max number of Tx descriptors we clean up at a time.  Should be modest as
83f7917c00SJeff Kirsher  * freeing skbs isn't cheap and it happens while holding locks.  We just need
84f7917c00SJeff Kirsher  * to free packets faster than they arrive, we eventually catch up and keep
85d429005fSVishal Kulkarni  * the amortized cost reasonable.  Must be >= 2 * TXQ_STOP_THRES.  It should
86d429005fSVishal Kulkarni  * also match the CIDX Flush Threshold.
87f7917c00SJeff Kirsher  */
88d429005fSVishal Kulkarni #define MAX_TX_RECLAIM 32
89f7917c00SJeff Kirsher 
90f7917c00SJeff Kirsher /*
91f7917c00SJeff Kirsher  * Max number of Rx buffers we replenish at a time.  Again keep this modest,
92f7917c00SJeff Kirsher  * allocating buffers isn't cheap either.
93f7917c00SJeff Kirsher  */
94f7917c00SJeff Kirsher #define MAX_RX_REFILL 16U
95f7917c00SJeff Kirsher 
96f7917c00SJeff Kirsher /*
97f7917c00SJeff Kirsher  * Period of the Rx queue check timer.  This timer is infrequent as it has
98f7917c00SJeff Kirsher  * something to do only when the system experiences severe memory shortage.
99f7917c00SJeff Kirsher  */
100f7917c00SJeff Kirsher #define RX_QCHECK_PERIOD (HZ / 2)
101f7917c00SJeff Kirsher 
102f7917c00SJeff Kirsher /*
103f7917c00SJeff Kirsher  * Period of the Tx queue check timer.
104f7917c00SJeff Kirsher  */
105f7917c00SJeff Kirsher #define TX_QCHECK_PERIOD (HZ / 2)
106f7917c00SJeff Kirsher 
107f7917c00SJeff Kirsher /*
108f7917c00SJeff Kirsher  * Max number of Tx descriptors to be reclaimed by the Tx timer.
109f7917c00SJeff Kirsher  */
110f7917c00SJeff Kirsher #define MAX_TIMER_TX_RECLAIM 100
111f7917c00SJeff Kirsher 
112f7917c00SJeff Kirsher /*
113f7917c00SJeff Kirsher  * Timer index used when backing off due to memory shortage.
114f7917c00SJeff Kirsher  */
115f7917c00SJeff Kirsher #define NOMEM_TMR_IDX (SGE_NTIMERS - 1)
116f7917c00SJeff Kirsher 
117f7917c00SJeff Kirsher /*
118f7917c00SJeff Kirsher  * Suspension threshold for non-Ethernet Tx queues.  We require enough room
119f7917c00SJeff Kirsher  * for a full sized WR.
120f7917c00SJeff Kirsher  */
121f7917c00SJeff Kirsher #define TXQ_STOP_THRES (SGE_MAX_WR_LEN / sizeof(struct tx_desc))
122f7917c00SJeff Kirsher 
123f7917c00SJeff Kirsher /*
124f7917c00SJeff Kirsher  * Max Tx descriptor space we allow for an Ethernet packet to be inlined
125f7917c00SJeff Kirsher  * into a WR.
126f7917c00SJeff Kirsher  */
12721dcfad6SHariprasad Shenai #define MAX_IMM_TX_PKT_LEN 256
128f7917c00SJeff Kirsher 
129f7917c00SJeff Kirsher /*
130f7917c00SJeff Kirsher  * Max size of a WR sent through a control Tx queue.
131f7917c00SJeff Kirsher  */
132f7917c00SJeff Kirsher #define MAX_CTRL_WR_LEN SGE_MAX_WR_LEN
133f7917c00SJeff Kirsher 
134f7917c00SJeff Kirsher struct rx_sw_desc {                /* SW state per Rx descriptor */
135f7917c00SJeff Kirsher 	struct page *page;
136f7917c00SJeff Kirsher 	dma_addr_t dma_addr;
137f7917c00SJeff Kirsher };
138f7917c00SJeff Kirsher 
139f7917c00SJeff Kirsher /*
14052367a76SVipul Pandya  * Rx buffer sizes for "useskbs" Free List buffers (one ingress packet pe skb
14152367a76SVipul Pandya  * buffer).  We currently only support two sizes for 1500- and 9000-byte MTUs.
14252367a76SVipul Pandya  * We could easily support more but there doesn't seem to be much need for
14352367a76SVipul Pandya  * that ...
14452367a76SVipul Pandya  */
14552367a76SVipul Pandya #define FL_MTU_SMALL 1500
14652367a76SVipul Pandya #define FL_MTU_LARGE 9000
14752367a76SVipul Pandya 
14852367a76SVipul Pandya static inline unsigned int fl_mtu_bufsize(struct adapter *adapter,
14952367a76SVipul Pandya 					  unsigned int mtu)
15052367a76SVipul Pandya {
15152367a76SVipul Pandya 	struct sge *s = &adapter->sge;
15252367a76SVipul Pandya 
15352367a76SVipul Pandya 	return ALIGN(s->pktshift + ETH_HLEN + VLAN_HLEN + mtu, s->fl_align);
15452367a76SVipul Pandya }
15552367a76SVipul Pandya 
15652367a76SVipul Pandya #define FL_MTU_SMALL_BUFSIZE(adapter) fl_mtu_bufsize(adapter, FL_MTU_SMALL)
15752367a76SVipul Pandya #define FL_MTU_LARGE_BUFSIZE(adapter) fl_mtu_bufsize(adapter, FL_MTU_LARGE)
15852367a76SVipul Pandya 
15952367a76SVipul Pandya /*
16052367a76SVipul Pandya  * Bits 0..3 of rx_sw_desc.dma_addr have special meaning.  The hardware uses
16152367a76SVipul Pandya  * these to specify the buffer size as an index into the SGE Free List Buffer
16252367a76SVipul Pandya  * Size register array.  We also use bit 4, when the buffer has been unmapped
16352367a76SVipul Pandya  * for DMA, but this is of course never sent to the hardware and is only used
16452367a76SVipul Pandya  * to prevent double unmappings.  All of the above requires that the Free List
16552367a76SVipul Pandya  * Buffers which we allocate have the bottom 5 bits free (0) -- i.e. are
16652367a76SVipul Pandya  * 32-byte or or a power of 2 greater in alignment.  Since the SGE's minimal
16752367a76SVipul Pandya  * Free List Buffer alignment is 32 bytes, this works out for us ...
168f7917c00SJeff Kirsher  */
169f7917c00SJeff Kirsher enum {
17052367a76SVipul Pandya 	RX_BUF_FLAGS     = 0x1f,   /* bottom five bits are special */
17152367a76SVipul Pandya 	RX_BUF_SIZE      = 0x0f,   /* bottom three bits are for buf sizes */
17252367a76SVipul Pandya 	RX_UNMAPPED_BUF  = 0x10,   /* buffer is not mapped */
17352367a76SVipul Pandya 
17452367a76SVipul Pandya 	/*
17552367a76SVipul Pandya 	 * XXX We shouldn't depend on being able to use these indices.
17652367a76SVipul Pandya 	 * XXX Especially when some other Master PF has initialized the
17752367a76SVipul Pandya 	 * XXX adapter or we use the Firmware Configuration File.  We
17852367a76SVipul Pandya 	 * XXX should really search through the Host Buffer Size register
17952367a76SVipul Pandya 	 * XXX array for the appropriately sized buffer indices.
18052367a76SVipul Pandya 	 */
18152367a76SVipul Pandya 	RX_SMALL_PG_BUF  = 0x0,   /* small (PAGE_SIZE) page buffer */
18252367a76SVipul Pandya 	RX_LARGE_PG_BUF  = 0x1,   /* buffer large (FL_PG_ORDER) page buffer */
18352367a76SVipul Pandya 
18452367a76SVipul Pandya 	RX_SMALL_MTU_BUF = 0x2,   /* small MTU buffer */
18552367a76SVipul Pandya 	RX_LARGE_MTU_BUF = 0x3,   /* large MTU buffer */
186f7917c00SJeff Kirsher };
187f7917c00SJeff Kirsher 
188e553ec3fSHariprasad Shenai static int timer_pkt_quota[] = {1, 1, 2, 3, 4, 5};
189e553ec3fSHariprasad Shenai #define MIN_NAPI_WORK  1
190e553ec3fSHariprasad Shenai 
191f7917c00SJeff Kirsher static inline dma_addr_t get_buf_addr(const struct rx_sw_desc *d)
192f7917c00SJeff Kirsher {
19352367a76SVipul Pandya 	return d->dma_addr & ~(dma_addr_t)RX_BUF_FLAGS;
194f7917c00SJeff Kirsher }
195f7917c00SJeff Kirsher 
196f7917c00SJeff Kirsher static inline bool is_buf_mapped(const struct rx_sw_desc *d)
197f7917c00SJeff Kirsher {
198f7917c00SJeff Kirsher 	return !(d->dma_addr & RX_UNMAPPED_BUF);
199f7917c00SJeff Kirsher }
200f7917c00SJeff Kirsher 
201f7917c00SJeff Kirsher /**
202f7917c00SJeff Kirsher  *	txq_avail - return the number of available slots in a Tx queue
203f7917c00SJeff Kirsher  *	@q: the Tx queue
204f7917c00SJeff Kirsher  *
205f7917c00SJeff Kirsher  *	Returns the number of descriptors in a Tx queue available to write new
206f7917c00SJeff Kirsher  *	packets.
207f7917c00SJeff Kirsher  */
208f7917c00SJeff Kirsher static inline unsigned int txq_avail(const struct sge_txq *q)
209f7917c00SJeff Kirsher {
210f7917c00SJeff Kirsher 	return q->size - 1 - q->in_use;
211f7917c00SJeff Kirsher }
212f7917c00SJeff Kirsher 
213f7917c00SJeff Kirsher /**
214f7917c00SJeff Kirsher  *	fl_cap - return the capacity of a free-buffer list
215f7917c00SJeff Kirsher  *	@fl: the FL
216f7917c00SJeff Kirsher  *
217f7917c00SJeff Kirsher  *	Returns the capacity of a free-buffer list.  The capacity is less than
218f7917c00SJeff Kirsher  *	the size because one descriptor needs to be left unpopulated, otherwise
219f7917c00SJeff Kirsher  *	HW will think the FL is empty.
220f7917c00SJeff Kirsher  */
221f7917c00SJeff Kirsher static inline unsigned int fl_cap(const struct sge_fl *fl)
222f7917c00SJeff Kirsher {
223f7917c00SJeff Kirsher 	return fl->size - 8;   /* 1 descriptor = 8 buffers */
224f7917c00SJeff Kirsher }
225f7917c00SJeff Kirsher 
226c098b026SHariprasad Shenai /**
227c098b026SHariprasad Shenai  *	fl_starving - return whether a Free List is starving.
228c098b026SHariprasad Shenai  *	@adapter: pointer to the adapter
229c098b026SHariprasad Shenai  *	@fl: the Free List
230c098b026SHariprasad Shenai  *
231c098b026SHariprasad Shenai  *	Tests specified Free List to see whether the number of buffers
232c098b026SHariprasad Shenai  *	available to the hardware has falled below our "starvation"
233c098b026SHariprasad Shenai  *	threshold.
234c098b026SHariprasad Shenai  */
235c098b026SHariprasad Shenai static inline bool fl_starving(const struct adapter *adapter,
236c098b026SHariprasad Shenai 			       const struct sge_fl *fl)
237f7917c00SJeff Kirsher {
238c098b026SHariprasad Shenai 	const struct sge *s = &adapter->sge;
239c098b026SHariprasad Shenai 
240c098b026SHariprasad Shenai 	return fl->avail - fl->pend_cred <= s->fl_starve_thres;
241f7917c00SJeff Kirsher }
242f7917c00SJeff Kirsher 
243a6ec572bSAtul Gupta int cxgb4_map_skb(struct device *dev, const struct sk_buff *skb,
244f7917c00SJeff Kirsher 		  dma_addr_t *addr)
245f7917c00SJeff Kirsher {
246f7917c00SJeff Kirsher 	const skb_frag_t *fp, *end;
247f7917c00SJeff Kirsher 	const struct skb_shared_info *si;
248f7917c00SJeff Kirsher 
249f7917c00SJeff Kirsher 	*addr = dma_map_single(dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE);
250f7917c00SJeff Kirsher 	if (dma_mapping_error(dev, *addr))
251f7917c00SJeff Kirsher 		goto out_err;
252f7917c00SJeff Kirsher 
253f7917c00SJeff Kirsher 	si = skb_shinfo(skb);
254f7917c00SJeff Kirsher 	end = &si->frags[si->nr_frags];
255f7917c00SJeff Kirsher 
256f7917c00SJeff Kirsher 	for (fp = si->frags; fp < end; fp++) {
257e91b0f24SIan Campbell 		*++addr = skb_frag_dma_map(dev, fp, 0, skb_frag_size(fp),
258e91b0f24SIan Campbell 					   DMA_TO_DEVICE);
259f7917c00SJeff Kirsher 		if (dma_mapping_error(dev, *addr))
260f7917c00SJeff Kirsher 			goto unwind;
261f7917c00SJeff Kirsher 	}
262f7917c00SJeff Kirsher 	return 0;
263f7917c00SJeff Kirsher 
264f7917c00SJeff Kirsher unwind:
265f7917c00SJeff Kirsher 	while (fp-- > si->frags)
2669e903e08SEric Dumazet 		dma_unmap_page(dev, *--addr, skb_frag_size(fp), DMA_TO_DEVICE);
267f7917c00SJeff Kirsher 
268f7917c00SJeff Kirsher 	dma_unmap_single(dev, addr[-1], skb_headlen(skb), DMA_TO_DEVICE);
269f7917c00SJeff Kirsher out_err:
270f7917c00SJeff Kirsher 	return -ENOMEM;
271f7917c00SJeff Kirsher }
272a6ec572bSAtul Gupta EXPORT_SYMBOL(cxgb4_map_skb);
273f7917c00SJeff Kirsher 
274f7917c00SJeff Kirsher static void unmap_skb(struct device *dev, const struct sk_buff *skb,
275f7917c00SJeff Kirsher 		      const dma_addr_t *addr)
276f7917c00SJeff Kirsher {
277f7917c00SJeff Kirsher 	const skb_frag_t *fp, *end;
278f7917c00SJeff Kirsher 	const struct skb_shared_info *si;
279f7917c00SJeff Kirsher 
280f7917c00SJeff Kirsher 	dma_unmap_single(dev, *addr++, skb_headlen(skb), DMA_TO_DEVICE);
281f7917c00SJeff Kirsher 
282f7917c00SJeff Kirsher 	si = skb_shinfo(skb);
283f7917c00SJeff Kirsher 	end = &si->frags[si->nr_frags];
284f7917c00SJeff Kirsher 	for (fp = si->frags; fp < end; fp++)
2859e903e08SEric Dumazet 		dma_unmap_page(dev, *addr++, skb_frag_size(fp), DMA_TO_DEVICE);
286f7917c00SJeff Kirsher }
287f7917c00SJeff Kirsher 
288b1396c2bSRahul Lakkireddy #ifdef CONFIG_NEED_DMA_MAP_STATE
289f7917c00SJeff Kirsher /**
290f7917c00SJeff Kirsher  *	deferred_unmap_destructor - unmap a packet when it is freed
291f7917c00SJeff Kirsher  *	@skb: the packet
292f7917c00SJeff Kirsher  *
293f7917c00SJeff Kirsher  *	This is the packet destructor used for Tx packets that need to remain
294f7917c00SJeff Kirsher  *	mapped until they are freed rather than until their Tx descriptors are
295f7917c00SJeff Kirsher  *	freed.
296f7917c00SJeff Kirsher  */
297f7917c00SJeff Kirsher static void deferred_unmap_destructor(struct sk_buff *skb)
298f7917c00SJeff Kirsher {
299f7917c00SJeff Kirsher 	unmap_skb(skb->dev->dev.parent, skb, (dma_addr_t *)skb->head);
300f7917c00SJeff Kirsher }
301f7917c00SJeff Kirsher #endif
302f7917c00SJeff Kirsher 
303f7917c00SJeff Kirsher /**
304f7917c00SJeff Kirsher  *	free_tx_desc - reclaims Tx descriptors and their buffers
30529bbf5d7SRahul Lakkireddy  *	@adap: the adapter
306f7917c00SJeff Kirsher  *	@q: the Tx queue to reclaim descriptors from
307f7917c00SJeff Kirsher  *	@n: the number of descriptors to reclaim
308f7917c00SJeff Kirsher  *	@unmap: whether the buffers should be unmapped for DMA
309f7917c00SJeff Kirsher  *
310f7917c00SJeff Kirsher  *	Reclaims Tx descriptors from an SGE Tx queue and frees the associated
311f7917c00SJeff Kirsher  *	Tx buffers.  Called with the Tx queue lock held.
312f7917c00SJeff Kirsher  */
313ab677ff4SHariprasad Shenai void free_tx_desc(struct adapter *adap, struct sge_txq *q,
314f7917c00SJeff Kirsher 		  unsigned int n, bool unmap)
315f7917c00SJeff Kirsher {
316f7917c00SJeff Kirsher 	unsigned int cidx = q->cidx;
3170ed96b46SRahul Lakkireddy 	struct tx_sw_desc *d;
318f7917c00SJeff Kirsher 
319f7917c00SJeff Kirsher 	d = &q->sdesc[cidx];
320f7917c00SJeff Kirsher 	while (n--) {
321f7917c00SJeff Kirsher 		if (d->skb) {                       /* an SGL is present */
3220ed96b46SRahul Lakkireddy 			if (unmap && d->addr[0]) {
3230ed96b46SRahul Lakkireddy 				unmap_skb(adap->pdev_dev, d->skb, d->addr);
3240ed96b46SRahul Lakkireddy 				memset(d->addr, 0, sizeof(d->addr));
3250ed96b46SRahul Lakkireddy 			}
326a7525198SEric W. Biederman 			dev_consume_skb_any(d->skb);
327f7917c00SJeff Kirsher 			d->skb = NULL;
328f7917c00SJeff Kirsher 		}
329f7917c00SJeff Kirsher 		++d;
330f7917c00SJeff Kirsher 		if (++cidx == q->size) {
331f7917c00SJeff Kirsher 			cidx = 0;
332f7917c00SJeff Kirsher 			d = q->sdesc;
333f7917c00SJeff Kirsher 		}
334f7917c00SJeff Kirsher 	}
335f7917c00SJeff Kirsher 	q->cidx = cidx;
336f7917c00SJeff Kirsher }
337f7917c00SJeff Kirsher 
338f7917c00SJeff Kirsher /*
339f7917c00SJeff Kirsher  * Return the number of reclaimable descriptors in a Tx queue.
340f7917c00SJeff Kirsher  */
341f7917c00SJeff Kirsher static inline int reclaimable(const struct sge_txq *q)
342f7917c00SJeff Kirsher {
3436aa7de05SMark Rutland 	int hw_cidx = ntohs(READ_ONCE(q->stat->cidx));
344f7917c00SJeff Kirsher 	hw_cidx -= q->cidx;
345f7917c00SJeff Kirsher 	return hw_cidx < 0 ? hw_cidx + q->size : hw_cidx;
346f7917c00SJeff Kirsher }
347f7917c00SJeff Kirsher 
348f7917c00SJeff Kirsher /**
349d429005fSVishal Kulkarni  *	reclaim_completed_tx - reclaims completed TX Descriptors
350d429005fSVishal Kulkarni  *	@adap: the adapter
351d429005fSVishal Kulkarni  *	@q: the Tx queue to reclaim completed descriptors from
352d429005fSVishal Kulkarni  *	@maxreclaim: the maximum number of TX Descriptors to reclaim or -1
353d429005fSVishal Kulkarni  *	@unmap: whether the buffers should be unmapped for DMA
354d429005fSVishal Kulkarni  *
355d429005fSVishal Kulkarni  *	Reclaims Tx Descriptors that the SGE has indicated it has processed,
356d429005fSVishal Kulkarni  *	and frees the associated buffers if possible.  If @max == -1, then
357d429005fSVishal Kulkarni  *	we'll use a defaiult maximum.  Called with the TX Queue locked.
358d429005fSVishal Kulkarni  */
359d429005fSVishal Kulkarni static inline int reclaim_completed_tx(struct adapter *adap, struct sge_txq *q,
360d429005fSVishal Kulkarni 				       int maxreclaim, bool unmap)
361d429005fSVishal Kulkarni {
362d429005fSVishal Kulkarni 	int reclaim = reclaimable(q);
363d429005fSVishal Kulkarni 
364d429005fSVishal Kulkarni 	if (reclaim) {
365d429005fSVishal Kulkarni 		/*
366d429005fSVishal Kulkarni 		 * Limit the amount of clean up work we do at a time to keep
367d429005fSVishal Kulkarni 		 * the Tx lock hold time O(1).
368d429005fSVishal Kulkarni 		 */
369d429005fSVishal Kulkarni 		if (maxreclaim < 0)
370d429005fSVishal Kulkarni 			maxreclaim = MAX_TX_RECLAIM;
371d429005fSVishal Kulkarni 		if (reclaim > maxreclaim)
372d429005fSVishal Kulkarni 			reclaim = maxreclaim;
373d429005fSVishal Kulkarni 
374d429005fSVishal Kulkarni 		free_tx_desc(adap, q, reclaim, unmap);
375d429005fSVishal Kulkarni 		q->in_use -= reclaim;
376d429005fSVishal Kulkarni 	}
377d429005fSVishal Kulkarni 
378d429005fSVishal Kulkarni 	return reclaim;
379d429005fSVishal Kulkarni }
380d429005fSVishal Kulkarni 
381d429005fSVishal Kulkarni /**
382a6ec572bSAtul Gupta  *	cxgb4_reclaim_completed_tx - reclaims completed Tx descriptors
383f7917c00SJeff Kirsher  *	@adap: the adapter
384f7917c00SJeff Kirsher  *	@q: the Tx queue to reclaim completed descriptors from
385f7917c00SJeff Kirsher  *	@unmap: whether the buffers should be unmapped for DMA
386f7917c00SJeff Kirsher  *
387f7917c00SJeff Kirsher  *	Reclaims Tx descriptors that the SGE has indicated it has processed,
388f7917c00SJeff Kirsher  *	and frees the associated buffers if possible.  Called with the Tx
389f7917c00SJeff Kirsher  *	queue locked.
390f7917c00SJeff Kirsher  */
391d429005fSVishal Kulkarni void cxgb4_reclaim_completed_tx(struct adapter *adap, struct sge_txq *q,
392f7917c00SJeff Kirsher 				bool unmap)
393f7917c00SJeff Kirsher {
394d429005fSVishal Kulkarni 	(void)reclaim_completed_tx(adap, q, -1, unmap);
395f7917c00SJeff Kirsher }
396a6ec572bSAtul Gupta EXPORT_SYMBOL(cxgb4_reclaim_completed_tx);
397f7917c00SJeff Kirsher 
39852367a76SVipul Pandya static inline int get_buf_size(struct adapter *adapter,
39952367a76SVipul Pandya 			       const struct rx_sw_desc *d)
400f7917c00SJeff Kirsher {
40152367a76SVipul Pandya 	struct sge *s = &adapter->sge;
40252367a76SVipul Pandya 	unsigned int rx_buf_size_idx = d->dma_addr & RX_BUF_SIZE;
40352367a76SVipul Pandya 	int buf_size;
40452367a76SVipul Pandya 
40552367a76SVipul Pandya 	switch (rx_buf_size_idx) {
40652367a76SVipul Pandya 	case RX_SMALL_PG_BUF:
40752367a76SVipul Pandya 		buf_size = PAGE_SIZE;
40852367a76SVipul Pandya 		break;
40952367a76SVipul Pandya 
41052367a76SVipul Pandya 	case RX_LARGE_PG_BUF:
41152367a76SVipul Pandya 		buf_size = PAGE_SIZE << s->fl_pg_order;
41252367a76SVipul Pandya 		break;
41352367a76SVipul Pandya 
41452367a76SVipul Pandya 	case RX_SMALL_MTU_BUF:
41552367a76SVipul Pandya 		buf_size = FL_MTU_SMALL_BUFSIZE(adapter);
41652367a76SVipul Pandya 		break;
41752367a76SVipul Pandya 
41852367a76SVipul Pandya 	case RX_LARGE_MTU_BUF:
41952367a76SVipul Pandya 		buf_size = FL_MTU_LARGE_BUFSIZE(adapter);
42052367a76SVipul Pandya 		break;
42152367a76SVipul Pandya 
42252367a76SVipul Pandya 	default:
423047a013fSArnd Bergmann 		BUG();
42452367a76SVipul Pandya 	}
42552367a76SVipul Pandya 
42652367a76SVipul Pandya 	return buf_size;
427f7917c00SJeff Kirsher }
428f7917c00SJeff Kirsher 
429f7917c00SJeff Kirsher /**
430f7917c00SJeff Kirsher  *	free_rx_bufs - free the Rx buffers on an SGE free list
431f7917c00SJeff Kirsher  *	@adap: the adapter
432f7917c00SJeff Kirsher  *	@q: the SGE free list to free buffers from
433f7917c00SJeff Kirsher  *	@n: how many buffers to free
434f7917c00SJeff Kirsher  *
435f7917c00SJeff Kirsher  *	Release the next @n buffers on an SGE free-buffer Rx queue.   The
436f7917c00SJeff Kirsher  *	buffers must be made inaccessible to HW before calling this function.
437f7917c00SJeff Kirsher  */
438f7917c00SJeff Kirsher static void free_rx_bufs(struct adapter *adap, struct sge_fl *q, int n)
439f7917c00SJeff Kirsher {
440f7917c00SJeff Kirsher 	while (n--) {
441f7917c00SJeff Kirsher 		struct rx_sw_desc *d = &q->sdesc[q->cidx];
442f7917c00SJeff Kirsher 
443f7917c00SJeff Kirsher 		if (is_buf_mapped(d))
444f7917c00SJeff Kirsher 			dma_unmap_page(adap->pdev_dev, get_buf_addr(d),
44552367a76SVipul Pandya 				       get_buf_size(adap, d),
44652367a76SVipul Pandya 				       PCI_DMA_FROMDEVICE);
447f7917c00SJeff Kirsher 		put_page(d->page);
448f7917c00SJeff Kirsher 		d->page = NULL;
449f7917c00SJeff Kirsher 		if (++q->cidx == q->size)
450f7917c00SJeff Kirsher 			q->cidx = 0;
451f7917c00SJeff Kirsher 		q->avail--;
452f7917c00SJeff Kirsher 	}
453f7917c00SJeff Kirsher }
454f7917c00SJeff Kirsher 
455f7917c00SJeff Kirsher /**
456f7917c00SJeff Kirsher  *	unmap_rx_buf - unmap the current Rx buffer on an SGE free list
457f7917c00SJeff Kirsher  *	@adap: the adapter
458f7917c00SJeff Kirsher  *	@q: the SGE free list
459f7917c00SJeff Kirsher  *
460f7917c00SJeff Kirsher  *	Unmap the current buffer on an SGE free-buffer Rx queue.   The
461f7917c00SJeff Kirsher  *	buffer must be made inaccessible to HW before calling this function.
462f7917c00SJeff Kirsher  *
463f7917c00SJeff Kirsher  *	This is similar to @free_rx_bufs above but does not free the buffer.
464f7917c00SJeff Kirsher  *	Do note that the FL still loses any further access to the buffer.
465f7917c00SJeff Kirsher  */
466f7917c00SJeff Kirsher static void unmap_rx_buf(struct adapter *adap, struct sge_fl *q)
467f7917c00SJeff Kirsher {
468f7917c00SJeff Kirsher 	struct rx_sw_desc *d = &q->sdesc[q->cidx];
469f7917c00SJeff Kirsher 
470f7917c00SJeff Kirsher 	if (is_buf_mapped(d))
471f7917c00SJeff Kirsher 		dma_unmap_page(adap->pdev_dev, get_buf_addr(d),
47252367a76SVipul Pandya 			       get_buf_size(adap, d), PCI_DMA_FROMDEVICE);
473f7917c00SJeff Kirsher 	d->page = NULL;
474f7917c00SJeff Kirsher 	if (++q->cidx == q->size)
475f7917c00SJeff Kirsher 		q->cidx = 0;
476f7917c00SJeff Kirsher 	q->avail--;
477f7917c00SJeff Kirsher }
478f7917c00SJeff Kirsher 
479f7917c00SJeff Kirsher static inline void ring_fl_db(struct adapter *adap, struct sge_fl *q)
480f7917c00SJeff Kirsher {
481f7917c00SJeff Kirsher 	if (q->pend_cred >= 8) {
4823ccc6cf7SHariprasad Shenai 		u32 val = adap->params.arch.sge_fl_db;
4833ccc6cf7SHariprasad Shenai 
484f612b815SHariprasad Shenai 		if (is_t4(adap->params.chip))
4853ccc6cf7SHariprasad Shenai 			val |= PIDX_V(q->pend_cred / 8);
486f612b815SHariprasad Shenai 		else
4873ccc6cf7SHariprasad Shenai 			val |= PIDX_T5_V(q->pend_cred / 8);
4881ecc7b7aSHariprasad Shenai 
4891ecc7b7aSHariprasad Shenai 		/* Make sure all memory writes to the Free List queue are
4901ecc7b7aSHariprasad Shenai 		 * committed before we tell the hardware about them.
4911ecc7b7aSHariprasad Shenai 		 */
492f7917c00SJeff Kirsher 		wmb();
493d63a6dcfSHariprasad Shenai 
494df64e4d3SHariprasad Shenai 		/* If we don't have access to the new User Doorbell (T5+), use
495df64e4d3SHariprasad Shenai 		 * the old doorbell mechanism; otherwise use the new BAR2
496df64e4d3SHariprasad Shenai 		 * mechanism.
497d63a6dcfSHariprasad Shenai 		 */
498df64e4d3SHariprasad Shenai 		if (unlikely(q->bar2_addr == NULL)) {
499f612b815SHariprasad Shenai 			t4_write_reg(adap, MYPF_REG(SGE_PF_KDOORBELL_A),
500f612b815SHariprasad Shenai 				     val | QID_V(q->cntxt_id));
501d63a6dcfSHariprasad Shenai 		} else {
502f612b815SHariprasad Shenai 			writel(val | QID_V(q->bar2_qid),
503df64e4d3SHariprasad Shenai 			       q->bar2_addr + SGE_UDB_KDOORBELL);
504d63a6dcfSHariprasad Shenai 
505d63a6dcfSHariprasad Shenai 			/* This Write memory Barrier will force the write to
506d63a6dcfSHariprasad Shenai 			 * the User Doorbell area to be flushed.
507d63a6dcfSHariprasad Shenai 			 */
508d63a6dcfSHariprasad Shenai 			wmb();
509d63a6dcfSHariprasad Shenai 		}
510f7917c00SJeff Kirsher 		q->pend_cred &= 7;
511f7917c00SJeff Kirsher 	}
512f7917c00SJeff Kirsher }
513f7917c00SJeff Kirsher 
514f7917c00SJeff Kirsher static inline void set_rx_sw_desc(struct rx_sw_desc *sd, struct page *pg,
515f7917c00SJeff Kirsher 				  dma_addr_t mapping)
516f7917c00SJeff Kirsher {
517f7917c00SJeff Kirsher 	sd->page = pg;
518f7917c00SJeff Kirsher 	sd->dma_addr = mapping;      /* includes size low bits */
519f7917c00SJeff Kirsher }
520f7917c00SJeff Kirsher 
521f7917c00SJeff Kirsher /**
522f7917c00SJeff Kirsher  *	refill_fl - refill an SGE Rx buffer ring
523f7917c00SJeff Kirsher  *	@adap: the adapter
524f7917c00SJeff Kirsher  *	@q: the ring to refill
525f7917c00SJeff Kirsher  *	@n: the number of new buffers to allocate
526f7917c00SJeff Kirsher  *	@gfp: the gfp flags for the allocations
527f7917c00SJeff Kirsher  *
528f7917c00SJeff Kirsher  *	(Re)populate an SGE free-buffer queue with up to @n new packet buffers,
529f7917c00SJeff Kirsher  *	allocated with the supplied gfp flags.  The caller must assure that
530f7917c00SJeff Kirsher  *	@n does not exceed the queue's capacity.  If afterwards the queue is
531f7917c00SJeff Kirsher  *	found critically low mark it as starving in the bitmap of starving FLs.
532f7917c00SJeff Kirsher  *
533f7917c00SJeff Kirsher  *	Returns the number of buffers allocated.
534f7917c00SJeff Kirsher  */
535f7917c00SJeff Kirsher static unsigned int refill_fl(struct adapter *adap, struct sge_fl *q, int n,
536f7917c00SJeff Kirsher 			      gfp_t gfp)
537f7917c00SJeff Kirsher {
53852367a76SVipul Pandya 	struct sge *s = &adap->sge;
539f7917c00SJeff Kirsher 	struct page *pg;
540f7917c00SJeff Kirsher 	dma_addr_t mapping;
541f7917c00SJeff Kirsher 	unsigned int cred = q->avail;
542f7917c00SJeff Kirsher 	__be64 *d = &q->desc[q->pidx];
543f7917c00SJeff Kirsher 	struct rx_sw_desc *sd = &q->sdesc[q->pidx];
544d52ce920SHariprasad Shenai 	int node;
545f7917c00SJeff Kirsher 
5465b377d11SHariprasad Shenai #ifdef CONFIG_DEBUG_FS
5475b377d11SHariprasad Shenai 	if (test_bit(q->cntxt_id - adap->sge.egr_start, adap->sge.blocked_fl))
5485b377d11SHariprasad Shenai 		goto out;
5495b377d11SHariprasad Shenai #endif
5505b377d11SHariprasad Shenai 
551aa9cd31cSAlexander Duyck 	gfp |= __GFP_NOWARN;
552d52ce920SHariprasad Shenai 	node = dev_to_node(adap->pdev_dev);
553f7917c00SJeff Kirsher 
55452367a76SVipul Pandya 	if (s->fl_pg_order == 0)
55552367a76SVipul Pandya 		goto alloc_small_pages;
55652367a76SVipul Pandya 
557f7917c00SJeff Kirsher 	/*
558f7917c00SJeff Kirsher 	 * Prefer large buffers
559f7917c00SJeff Kirsher 	 */
560f7917c00SJeff Kirsher 	while (n) {
561d52ce920SHariprasad Shenai 		pg = alloc_pages_node(node, gfp | __GFP_COMP, s->fl_pg_order);
562f7917c00SJeff Kirsher 		if (unlikely(!pg)) {
563f7917c00SJeff Kirsher 			q->large_alloc_failed++;
564f7917c00SJeff Kirsher 			break;       /* fall back to single pages */
565f7917c00SJeff Kirsher 		}
566f7917c00SJeff Kirsher 
567f7917c00SJeff Kirsher 		mapping = dma_map_page(adap->pdev_dev, pg, 0,
56852367a76SVipul Pandya 				       PAGE_SIZE << s->fl_pg_order,
569f7917c00SJeff Kirsher 				       PCI_DMA_FROMDEVICE);
570f7917c00SJeff Kirsher 		if (unlikely(dma_mapping_error(adap->pdev_dev, mapping))) {
57152367a76SVipul Pandya 			__free_pages(pg, s->fl_pg_order);
57270055dd0SHariprasad Shenai 			q->mapping_err++;
573f7917c00SJeff Kirsher 			goto out;   /* do not try small pages for this error */
574f7917c00SJeff Kirsher 		}
57552367a76SVipul Pandya 		mapping |= RX_LARGE_PG_BUF;
576f7917c00SJeff Kirsher 		*d++ = cpu_to_be64(mapping);
577f7917c00SJeff Kirsher 
578f7917c00SJeff Kirsher 		set_rx_sw_desc(sd, pg, mapping);
579f7917c00SJeff Kirsher 		sd++;
580f7917c00SJeff Kirsher 
581f7917c00SJeff Kirsher 		q->avail++;
582f7917c00SJeff Kirsher 		if (++q->pidx == q->size) {
583f7917c00SJeff Kirsher 			q->pidx = 0;
584f7917c00SJeff Kirsher 			sd = q->sdesc;
585f7917c00SJeff Kirsher 			d = q->desc;
586f7917c00SJeff Kirsher 		}
587f7917c00SJeff Kirsher 		n--;
588f7917c00SJeff Kirsher 	}
589f7917c00SJeff Kirsher 
59052367a76SVipul Pandya alloc_small_pages:
591f7917c00SJeff Kirsher 	while (n--) {
592d52ce920SHariprasad Shenai 		pg = alloc_pages_node(node, gfp, 0);
593f7917c00SJeff Kirsher 		if (unlikely(!pg)) {
594f7917c00SJeff Kirsher 			q->alloc_failed++;
595f7917c00SJeff Kirsher 			break;
596f7917c00SJeff Kirsher 		}
597f7917c00SJeff Kirsher 
598f7917c00SJeff Kirsher 		mapping = dma_map_page(adap->pdev_dev, pg, 0, PAGE_SIZE,
599f7917c00SJeff Kirsher 				       PCI_DMA_FROMDEVICE);
600f7917c00SJeff Kirsher 		if (unlikely(dma_mapping_error(adap->pdev_dev, mapping))) {
6011f2149c1SEric Dumazet 			put_page(pg);
60270055dd0SHariprasad Shenai 			q->mapping_err++;
603f7917c00SJeff Kirsher 			goto out;
604f7917c00SJeff Kirsher 		}
605f7917c00SJeff Kirsher 		*d++ = cpu_to_be64(mapping);
606f7917c00SJeff Kirsher 
607f7917c00SJeff Kirsher 		set_rx_sw_desc(sd, pg, mapping);
608f7917c00SJeff Kirsher 		sd++;
609f7917c00SJeff Kirsher 
610f7917c00SJeff Kirsher 		q->avail++;
611f7917c00SJeff Kirsher 		if (++q->pidx == q->size) {
612f7917c00SJeff Kirsher 			q->pidx = 0;
613f7917c00SJeff Kirsher 			sd = q->sdesc;
614f7917c00SJeff Kirsher 			d = q->desc;
615f7917c00SJeff Kirsher 		}
616f7917c00SJeff Kirsher 	}
617f7917c00SJeff Kirsher 
618f7917c00SJeff Kirsher out:	cred = q->avail - cred;
619f7917c00SJeff Kirsher 	q->pend_cred += cred;
620f7917c00SJeff Kirsher 	ring_fl_db(adap, q);
621f7917c00SJeff Kirsher 
622c098b026SHariprasad Shenai 	if (unlikely(fl_starving(adap, q))) {
623f7917c00SJeff Kirsher 		smp_wmb();
62470055dd0SHariprasad Shenai 		q->low++;
625f7917c00SJeff Kirsher 		set_bit(q->cntxt_id - adap->sge.egr_start,
626f7917c00SJeff Kirsher 			adap->sge.starving_fl);
627f7917c00SJeff Kirsher 	}
628f7917c00SJeff Kirsher 
629f7917c00SJeff Kirsher 	return cred;
630f7917c00SJeff Kirsher }
631f7917c00SJeff Kirsher 
632f7917c00SJeff Kirsher static inline void __refill_fl(struct adapter *adap, struct sge_fl *fl)
633f7917c00SJeff Kirsher {
634f7917c00SJeff Kirsher 	refill_fl(adap, fl, min(MAX_RX_REFILL, fl_cap(fl) - fl->avail),
635f7917c00SJeff Kirsher 		  GFP_ATOMIC);
636f7917c00SJeff Kirsher }
637f7917c00SJeff Kirsher 
638f7917c00SJeff Kirsher /**
639f7917c00SJeff Kirsher  *	alloc_ring - allocate resources for an SGE descriptor ring
640f7917c00SJeff Kirsher  *	@dev: the PCI device's core device
641f7917c00SJeff Kirsher  *	@nelem: the number of descriptors
642f7917c00SJeff Kirsher  *	@elem_size: the size of each descriptor
643f7917c00SJeff Kirsher  *	@sw_size: the size of the SW state associated with each ring element
644f7917c00SJeff Kirsher  *	@phys: the physical address of the allocated ring
645f7917c00SJeff Kirsher  *	@metadata: address of the array holding the SW state for the ring
646f7917c00SJeff Kirsher  *	@stat_size: extra space in HW ring for status information
647f7917c00SJeff Kirsher  *	@node: preferred node for memory allocations
648f7917c00SJeff Kirsher  *
649f7917c00SJeff Kirsher  *	Allocates resources for an SGE descriptor ring, such as Tx queues,
650f7917c00SJeff Kirsher  *	free buffer lists, or response queues.  Each SGE ring requires
651f7917c00SJeff Kirsher  *	space for its HW descriptors plus, optionally, space for the SW state
652f7917c00SJeff Kirsher  *	associated with each HW entry (the metadata).  The function returns
653f7917c00SJeff Kirsher  *	three values: the virtual address for the HW ring (the return value
654f7917c00SJeff Kirsher  *	of the function), the bus address of the HW ring, and the address
655f7917c00SJeff Kirsher  *	of the SW ring.
656f7917c00SJeff Kirsher  */
657f7917c00SJeff Kirsher static void *alloc_ring(struct device *dev, size_t nelem, size_t elem_size,
658f7917c00SJeff Kirsher 			size_t sw_size, dma_addr_t *phys, void *metadata,
659f7917c00SJeff Kirsher 			size_t stat_size, int node)
660f7917c00SJeff Kirsher {
661f7917c00SJeff Kirsher 	size_t len = nelem * elem_size + stat_size;
662f7917c00SJeff Kirsher 	void *s = NULL;
663750afb08SLuis Chamberlain 	void *p = dma_alloc_coherent(dev, len, phys, GFP_KERNEL);
664f7917c00SJeff Kirsher 
665f7917c00SJeff Kirsher 	if (!p)
666f7917c00SJeff Kirsher 		return NULL;
667f7917c00SJeff Kirsher 	if (sw_size) {
668590b5b7dSKees Cook 		s = kcalloc_node(sw_size, nelem, GFP_KERNEL, node);
669f7917c00SJeff Kirsher 
670f7917c00SJeff Kirsher 		if (!s) {
671f7917c00SJeff Kirsher 			dma_free_coherent(dev, len, p, *phys);
672f7917c00SJeff Kirsher 			return NULL;
673f7917c00SJeff Kirsher 		}
674f7917c00SJeff Kirsher 	}
675f7917c00SJeff Kirsher 	if (metadata)
676f7917c00SJeff Kirsher 		*(void **)metadata = s;
677f7917c00SJeff Kirsher 	return p;
678f7917c00SJeff Kirsher }
679f7917c00SJeff Kirsher 
680f7917c00SJeff Kirsher /**
681f7917c00SJeff Kirsher  *	sgl_len - calculates the size of an SGL of the given capacity
682f7917c00SJeff Kirsher  *	@n: the number of SGL entries
683f7917c00SJeff Kirsher  *
684f7917c00SJeff Kirsher  *	Calculates the number of flits needed for a scatter/gather list that
685f7917c00SJeff Kirsher  *	can hold the given number of entries.
686f7917c00SJeff Kirsher  */
687f7917c00SJeff Kirsher static inline unsigned int sgl_len(unsigned int n)
688f7917c00SJeff Kirsher {
6890aac3f56SHariprasad Shenai 	/* A Direct Scatter Gather List uses 32-bit lengths and 64-bit PCI DMA
6900aac3f56SHariprasad Shenai 	 * addresses.  The DSGL Work Request starts off with a 32-bit DSGL
6910aac3f56SHariprasad Shenai 	 * ULPTX header, then Length0, then Address0, then, for 1 <= i <= N,
6920aac3f56SHariprasad Shenai 	 * repeated sequences of { Length[i], Length[i+1], Address[i],
6930aac3f56SHariprasad Shenai 	 * Address[i+1] } (this ensures that all addresses are on 64-bit
6940aac3f56SHariprasad Shenai 	 * boundaries).  If N is even, then Length[N+1] should be set to 0 and
6950aac3f56SHariprasad Shenai 	 * Address[N+1] is omitted.
6960aac3f56SHariprasad Shenai 	 *
6970aac3f56SHariprasad Shenai 	 * The following calculation incorporates all of the above.  It's
6980aac3f56SHariprasad Shenai 	 * somewhat hard to follow but, briefly: the "+2" accounts for the
6990aac3f56SHariprasad Shenai 	 * first two flits which include the DSGL header, Length0 and
7000aac3f56SHariprasad Shenai 	 * Address0; the "(3*(n-1))/2" covers the main body of list entries (3
7010aac3f56SHariprasad Shenai 	 * flits for every pair of the remaining N) +1 if (n-1) is odd; and
7020aac3f56SHariprasad Shenai 	 * finally the "+((n-1)&1)" adds the one remaining flit needed if
7030aac3f56SHariprasad Shenai 	 * (n-1) is odd ...
7040aac3f56SHariprasad Shenai 	 */
705f7917c00SJeff Kirsher 	n--;
706f7917c00SJeff Kirsher 	return (3 * n) / 2 + (n & 1) + 2;
707f7917c00SJeff Kirsher }
708f7917c00SJeff Kirsher 
709f7917c00SJeff Kirsher /**
710f7917c00SJeff Kirsher  *	flits_to_desc - returns the num of Tx descriptors for the given flits
711f7917c00SJeff Kirsher  *	@n: the number of flits
712f7917c00SJeff Kirsher  *
713f7917c00SJeff Kirsher  *	Returns the number of Tx descriptors needed for the supplied number
714f7917c00SJeff Kirsher  *	of flits.
715f7917c00SJeff Kirsher  */
716f7917c00SJeff Kirsher static inline unsigned int flits_to_desc(unsigned int n)
717f7917c00SJeff Kirsher {
718f7917c00SJeff Kirsher 	BUG_ON(n > SGE_MAX_WR_LEN / 8);
719f7917c00SJeff Kirsher 	return DIV_ROUND_UP(n, 8);
720f7917c00SJeff Kirsher }
721f7917c00SJeff Kirsher 
722f7917c00SJeff Kirsher /**
723f7917c00SJeff Kirsher  *	is_eth_imm - can an Ethernet packet be sent as immediate data?
724f7917c00SJeff Kirsher  *	@skb: the packet
72529bbf5d7SRahul Lakkireddy  *	@chip_ver: chip version
726f7917c00SJeff Kirsher  *
727f7917c00SJeff Kirsher  *	Returns whether an Ethernet packet is small enough to fit as
7280034b298SKumar Sanghvi  *	immediate data. Return value corresponds to headroom required.
729f7917c00SJeff Kirsher  */
730d0a1299cSGanesh Goudar static inline int is_eth_imm(const struct sk_buff *skb, unsigned int chip_ver)
731f7917c00SJeff Kirsher {
732d0a1299cSGanesh Goudar 	int hdrlen = 0;
7330034b298SKumar Sanghvi 
734d0a1299cSGanesh Goudar 	if (skb->encapsulation && skb_shinfo(skb)->gso_size &&
735d0a1299cSGanesh Goudar 	    chip_ver > CHELSIO_T5) {
736d0a1299cSGanesh Goudar 		hdrlen = sizeof(struct cpl_tx_tnl_lso);
737d0a1299cSGanesh Goudar 		hdrlen += sizeof(struct cpl_tx_pkt_core);
7381a2a14fbSRahul Lakkireddy 	} else if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) {
7391a2a14fbSRahul Lakkireddy 		return 0;
740d0a1299cSGanesh Goudar 	} else {
741d0a1299cSGanesh Goudar 		hdrlen = skb_shinfo(skb)->gso_size ?
742d0a1299cSGanesh Goudar 			 sizeof(struct cpl_tx_pkt_lso_core) : 0;
7430034b298SKumar Sanghvi 		hdrlen += sizeof(struct cpl_tx_pkt);
744d0a1299cSGanesh Goudar 	}
7450034b298SKumar Sanghvi 	if (skb->len <= MAX_IMM_TX_PKT_LEN - hdrlen)
7460034b298SKumar Sanghvi 		return hdrlen;
7470034b298SKumar Sanghvi 	return 0;
748f7917c00SJeff Kirsher }
749f7917c00SJeff Kirsher 
750f7917c00SJeff Kirsher /**
751f7917c00SJeff Kirsher  *	calc_tx_flits - calculate the number of flits for a packet Tx WR
752f7917c00SJeff Kirsher  *	@skb: the packet
75329bbf5d7SRahul Lakkireddy  *	@chip_ver: chip version
754f7917c00SJeff Kirsher  *
755f7917c00SJeff Kirsher  *	Returns the number of flits needed for a Tx WR for the given Ethernet
756f7917c00SJeff Kirsher  *	packet, including the needed WR and CPL headers.
757f7917c00SJeff Kirsher  */
758d0a1299cSGanesh Goudar static inline unsigned int calc_tx_flits(const struct sk_buff *skb,
759d0a1299cSGanesh Goudar 					 unsigned int chip_ver)
760f7917c00SJeff Kirsher {
761f7917c00SJeff Kirsher 	unsigned int flits;
762d0a1299cSGanesh Goudar 	int hdrlen = is_eth_imm(skb, chip_ver);
763f7917c00SJeff Kirsher 
7640aac3f56SHariprasad Shenai 	/* If the skb is small enough, we can pump it out as a work request
7650aac3f56SHariprasad Shenai 	 * with only immediate data.  In that case we just have to have the
7660aac3f56SHariprasad Shenai 	 * TX Packet header plus the skb data in the Work Request.
7670aac3f56SHariprasad Shenai 	 */
7680aac3f56SHariprasad Shenai 
7690034b298SKumar Sanghvi 	if (hdrlen)
7700034b298SKumar Sanghvi 		return DIV_ROUND_UP(skb->len + hdrlen, sizeof(__be64));
771f7917c00SJeff Kirsher 
7720aac3f56SHariprasad Shenai 	/* Otherwise, we're going to have to construct a Scatter gather list
7730aac3f56SHariprasad Shenai 	 * of the skb body and fragments.  We also include the flits necessary
7740aac3f56SHariprasad Shenai 	 * for the TX Packet Work Request and CPL.  We always have a firmware
7750aac3f56SHariprasad Shenai 	 * Write Header (incorporated as part of the cpl_tx_pkt_lso and
7760aac3f56SHariprasad Shenai 	 * cpl_tx_pkt structures), followed by either a TX Packet Write CPL
7770aac3f56SHariprasad Shenai 	 * message or, if we're doing a Large Send Offload, an LSO CPL message
7780aac3f56SHariprasad Shenai 	 * with an embedded TX Packet Write CPL message.
7790aac3f56SHariprasad Shenai 	 */
780fd1754fbSHariprasad Shenai 	flits = sgl_len(skb_shinfo(skb)->nr_frags + 1);
781d0a1299cSGanesh Goudar 	if (skb_shinfo(skb)->gso_size) {
7821a2a14fbSRahul Lakkireddy 		if (skb->encapsulation && chip_ver > CHELSIO_T5) {
783d0a1299cSGanesh Goudar 			hdrlen = sizeof(struct fw_eth_tx_pkt_wr) +
784d0a1299cSGanesh Goudar 				 sizeof(struct cpl_tx_tnl_lso);
7851a2a14fbSRahul Lakkireddy 		} else if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) {
7861a2a14fbSRahul Lakkireddy 			u32 pkt_hdrlen;
7871a2a14fbSRahul Lakkireddy 
7881a2a14fbSRahul Lakkireddy 			pkt_hdrlen = eth_get_headlen(skb->dev, skb->data,
7891a2a14fbSRahul Lakkireddy 						     skb_headlen(skb));
7901a2a14fbSRahul Lakkireddy 			hdrlen = sizeof(struct fw_eth_tx_eo_wr) +
7911a2a14fbSRahul Lakkireddy 				 round_up(pkt_hdrlen, 16);
7921a2a14fbSRahul Lakkireddy 		} else {
793d0a1299cSGanesh Goudar 			hdrlen = sizeof(struct fw_eth_tx_pkt_wr) +
794d0a1299cSGanesh Goudar 				 sizeof(struct cpl_tx_pkt_lso_core);
7951a2a14fbSRahul Lakkireddy 		}
796d0a1299cSGanesh Goudar 
797d0a1299cSGanesh Goudar 		hdrlen += sizeof(struct cpl_tx_pkt_core);
798d0a1299cSGanesh Goudar 		flits += (hdrlen / sizeof(__be64));
799d0a1299cSGanesh Goudar 	} else {
8000aac3f56SHariprasad Shenai 		flits += (sizeof(struct fw_eth_tx_pkt_wr) +
8010aac3f56SHariprasad Shenai 			  sizeof(struct cpl_tx_pkt_core)) / sizeof(__be64);
802d0a1299cSGanesh Goudar 	}
803f7917c00SJeff Kirsher 	return flits;
804f7917c00SJeff Kirsher }
805f7917c00SJeff Kirsher 
806f7917c00SJeff Kirsher /**
807f7917c00SJeff Kirsher  *	calc_tx_descs - calculate the number of Tx descriptors for a packet
808f7917c00SJeff Kirsher  *	@skb: the packet
80929bbf5d7SRahul Lakkireddy  *	@chip_ver: chip version
810f7917c00SJeff Kirsher  *
811f7917c00SJeff Kirsher  *	Returns the number of Tx descriptors needed for the given Ethernet
812f7917c00SJeff Kirsher  *	packet, including the needed WR and CPL headers.
813f7917c00SJeff Kirsher  */
814d0a1299cSGanesh Goudar static inline unsigned int calc_tx_descs(const struct sk_buff *skb,
815d0a1299cSGanesh Goudar 					 unsigned int chip_ver)
816f7917c00SJeff Kirsher {
817d0a1299cSGanesh Goudar 	return flits_to_desc(calc_tx_flits(skb, chip_ver));
818f7917c00SJeff Kirsher }
819f7917c00SJeff Kirsher 
820f7917c00SJeff Kirsher /**
821a6ec572bSAtul Gupta  *	cxgb4_write_sgl - populate a scatter/gather list for a packet
822f7917c00SJeff Kirsher  *	@skb: the packet
823f7917c00SJeff Kirsher  *	@q: the Tx queue we are writing into
824f7917c00SJeff Kirsher  *	@sgl: starting location for writing the SGL
825f7917c00SJeff Kirsher  *	@end: points right after the end of the SGL
826f7917c00SJeff Kirsher  *	@start: start offset into skb main-body data to include in the SGL
827f7917c00SJeff Kirsher  *	@addr: the list of bus addresses for the SGL elements
828f7917c00SJeff Kirsher  *
829f7917c00SJeff Kirsher  *	Generates a gather list for the buffers that make up a packet.
830f7917c00SJeff Kirsher  *	The caller must provide adequate space for the SGL that will be written.
831f7917c00SJeff Kirsher  *	The SGL includes all of the packet's page fragments and the data in its
832f7917c00SJeff Kirsher  *	main body except for the first @start bytes.  @sgl must be 16-byte
833f7917c00SJeff Kirsher  *	aligned and within a Tx descriptor with available space.  @end points
834f7917c00SJeff Kirsher  *	right after the end of the SGL but does not account for any potential
835f7917c00SJeff Kirsher  *	wrap around, i.e., @end > @sgl.
836f7917c00SJeff Kirsher  */
837a6ec572bSAtul Gupta void cxgb4_write_sgl(const struct sk_buff *skb, struct sge_txq *q,
838f7917c00SJeff Kirsher 		     struct ulptx_sgl *sgl, u64 *end, unsigned int start,
839f7917c00SJeff Kirsher 		     const dma_addr_t *addr)
840f7917c00SJeff Kirsher {
841f7917c00SJeff Kirsher 	unsigned int i, len;
842f7917c00SJeff Kirsher 	struct ulptx_sge_pair *to;
843f7917c00SJeff Kirsher 	const struct skb_shared_info *si = skb_shinfo(skb);
844f7917c00SJeff Kirsher 	unsigned int nfrags = si->nr_frags;
845f7917c00SJeff Kirsher 	struct ulptx_sge_pair buf[MAX_SKB_FRAGS / 2 + 1];
846f7917c00SJeff Kirsher 
847f7917c00SJeff Kirsher 	len = skb_headlen(skb) - start;
848f7917c00SJeff Kirsher 	if (likely(len)) {
849f7917c00SJeff Kirsher 		sgl->len0 = htonl(len);
850f7917c00SJeff Kirsher 		sgl->addr0 = cpu_to_be64(addr[0] + start);
851f7917c00SJeff Kirsher 		nfrags++;
852f7917c00SJeff Kirsher 	} else {
8539e903e08SEric Dumazet 		sgl->len0 = htonl(skb_frag_size(&si->frags[0]));
854f7917c00SJeff Kirsher 		sgl->addr0 = cpu_to_be64(addr[1]);
855f7917c00SJeff Kirsher 	}
856f7917c00SJeff Kirsher 
857bdc590b9SHariprasad Shenai 	sgl->cmd_nsge = htonl(ULPTX_CMD_V(ULP_TX_SC_DSGL) |
858bdc590b9SHariprasad Shenai 			      ULPTX_NSGE_V(nfrags));
859f7917c00SJeff Kirsher 	if (likely(--nfrags == 0))
860f7917c00SJeff Kirsher 		return;
861f7917c00SJeff Kirsher 	/*
862f7917c00SJeff Kirsher 	 * Most of the complexity below deals with the possibility we hit the
863f7917c00SJeff Kirsher 	 * end of the queue in the middle of writing the SGL.  For this case
864f7917c00SJeff Kirsher 	 * only we create the SGL in a temporary buffer and then copy it.
865f7917c00SJeff Kirsher 	 */
866f7917c00SJeff Kirsher 	to = (u8 *)end > (u8 *)q->stat ? buf : sgl->sge;
867f7917c00SJeff Kirsher 
868f7917c00SJeff Kirsher 	for (i = (nfrags != si->nr_frags); nfrags >= 2; nfrags -= 2, to++) {
8699e903e08SEric Dumazet 		to->len[0] = cpu_to_be32(skb_frag_size(&si->frags[i]));
8709e903e08SEric Dumazet 		to->len[1] = cpu_to_be32(skb_frag_size(&si->frags[++i]));
871f7917c00SJeff Kirsher 		to->addr[0] = cpu_to_be64(addr[i]);
872f7917c00SJeff Kirsher 		to->addr[1] = cpu_to_be64(addr[++i]);
873f7917c00SJeff Kirsher 	}
874f7917c00SJeff Kirsher 	if (nfrags) {
8759e903e08SEric Dumazet 		to->len[0] = cpu_to_be32(skb_frag_size(&si->frags[i]));
876f7917c00SJeff Kirsher 		to->len[1] = cpu_to_be32(0);
877f7917c00SJeff Kirsher 		to->addr[0] = cpu_to_be64(addr[i + 1]);
878f7917c00SJeff Kirsher 	}
879f7917c00SJeff Kirsher 	if (unlikely((u8 *)end > (u8 *)q->stat)) {
880f7917c00SJeff Kirsher 		unsigned int part0 = (u8 *)q->stat - (u8 *)sgl->sge, part1;
881f7917c00SJeff Kirsher 
882f7917c00SJeff Kirsher 		if (likely(part0))
883f7917c00SJeff Kirsher 			memcpy(sgl->sge, buf, part0);
884f7917c00SJeff Kirsher 		part1 = (u8 *)end - (u8 *)q->stat;
885f7917c00SJeff Kirsher 		memcpy(q->desc, (u8 *)buf + part0, part1);
886f7917c00SJeff Kirsher 		end = (void *)q->desc + part1;
887f7917c00SJeff Kirsher 	}
888f7917c00SJeff Kirsher 	if ((uintptr_t)end & 8)           /* 0-pad to multiple of 16 */
88964699336SJoe Perches 		*end = 0;
890f7917c00SJeff Kirsher }
891a6ec572bSAtul Gupta EXPORT_SYMBOL(cxgb4_write_sgl);
892f7917c00SJeff Kirsher 
893df64e4d3SHariprasad Shenai /* This function copies 64 byte coalesced work request to
894df64e4d3SHariprasad Shenai  * memory mapped BAR2 space. For coalesced WR SGE fetches
895df64e4d3SHariprasad Shenai  * data from the FIFO instead of from Host.
89622adfe0aSSantosh Rastapur  */
897df64e4d3SHariprasad Shenai static void cxgb_pio_copy(u64 __iomem *dst, u64 *src)
89822adfe0aSSantosh Rastapur {
899df64e4d3SHariprasad Shenai 	int count = 8;
90022adfe0aSSantosh Rastapur 
90122adfe0aSSantosh Rastapur 	while (count) {
90222adfe0aSSantosh Rastapur 		writeq(*src, dst);
90322adfe0aSSantosh Rastapur 		src++;
90422adfe0aSSantosh Rastapur 		dst++;
90522adfe0aSSantosh Rastapur 		count--;
90622adfe0aSSantosh Rastapur 	}
90722adfe0aSSantosh Rastapur }
90822adfe0aSSantosh Rastapur 
909f7917c00SJeff Kirsher /**
910a6ec572bSAtul Gupta  *	cxgb4_ring_tx_db - check and potentially ring a Tx queue's doorbell
911f7917c00SJeff Kirsher  *	@adap: the adapter
912f7917c00SJeff Kirsher  *	@q: the Tx queue
913f7917c00SJeff Kirsher  *	@n: number of new descriptors to give to HW
914f7917c00SJeff Kirsher  *
915f7917c00SJeff Kirsher  *	Ring the doorbel for a Tx queue.
916f7917c00SJeff Kirsher  */
917a6ec572bSAtul Gupta inline void cxgb4_ring_tx_db(struct adapter *adap, struct sge_txq *q, int n)
918f7917c00SJeff Kirsher {
9191ecc7b7aSHariprasad Shenai 	/* Make sure that all writes to the TX Descriptors are committed
9201ecc7b7aSHariprasad Shenai 	 * before we tell the hardware about them.
9211ecc7b7aSHariprasad Shenai 	 */
9221ecc7b7aSHariprasad Shenai 	wmb();
923d63a6dcfSHariprasad Shenai 
924df64e4d3SHariprasad Shenai 	/* If we don't have access to the new User Doorbell (T5+), use the old
925df64e4d3SHariprasad Shenai 	 * doorbell mechanism; otherwise use the new BAR2 mechanism.
926df64e4d3SHariprasad Shenai 	 */
927df64e4d3SHariprasad Shenai 	if (unlikely(q->bar2_addr == NULL)) {
928f612b815SHariprasad Shenai 		u32 val = PIDX_V(n);
92905eb2389SSteve Wise 		unsigned long flags;
93022adfe0aSSantosh Rastapur 
931d63a6dcfSHariprasad Shenai 		/* For T4 we need to participate in the Doorbell Recovery
932d63a6dcfSHariprasad Shenai 		 * mechanism.
933d63a6dcfSHariprasad Shenai 		 */
93405eb2389SSteve Wise 		spin_lock_irqsave(&q->db_lock, flags);
935d63a6dcfSHariprasad Shenai 		if (!q->db_disabled)
936f612b815SHariprasad Shenai 			t4_write_reg(adap, MYPF_REG(SGE_PF_KDOORBELL_A),
937f612b815SHariprasad Shenai 				     QID_V(q->cntxt_id) | val);
938d63a6dcfSHariprasad Shenai 		else
93905eb2389SSteve Wise 			q->db_pidx_inc += n;
9403069ee9bSVipul Pandya 		q->db_pidx = q->pidx;
94105eb2389SSteve Wise 		spin_unlock_irqrestore(&q->db_lock, flags);
942d63a6dcfSHariprasad Shenai 	} else {
943f612b815SHariprasad Shenai 		u32 val = PIDX_T5_V(n);
944d63a6dcfSHariprasad Shenai 
945d63a6dcfSHariprasad Shenai 		/* T4 and later chips share the same PIDX field offset within
946d63a6dcfSHariprasad Shenai 		 * the doorbell, but T5 and later shrank the field in order to
947d63a6dcfSHariprasad Shenai 		 * gain a bit for Doorbell Priority.  The field was absurdly
948d63a6dcfSHariprasad Shenai 		 * large in the first place (14 bits) so we just use the T5
949d63a6dcfSHariprasad Shenai 		 * and later limits and warn if a Queue ID is too large.
950d63a6dcfSHariprasad Shenai 		 */
951f612b815SHariprasad Shenai 		WARN_ON(val & DBPRIO_F);
952d63a6dcfSHariprasad Shenai 
953df64e4d3SHariprasad Shenai 		/* If we're only writing a single TX Descriptor and we can use
954df64e4d3SHariprasad Shenai 		 * Inferred QID registers, we can use the Write Combining
955df64e4d3SHariprasad Shenai 		 * Gather Buffer; otherwise we use the simple doorbell.
956d63a6dcfSHariprasad Shenai 		 */
957df64e4d3SHariprasad Shenai 		if (n == 1 && q->bar2_qid == 0) {
958d63a6dcfSHariprasad Shenai 			int index = (q->pidx
959d63a6dcfSHariprasad Shenai 				     ? (q->pidx - 1)
960d63a6dcfSHariprasad Shenai 				     : (q->size - 1));
961df64e4d3SHariprasad Shenai 			u64 *wr = (u64 *)&q->desc[index];
962d63a6dcfSHariprasad Shenai 
963df64e4d3SHariprasad Shenai 			cxgb_pio_copy((u64 __iomem *)
964df64e4d3SHariprasad Shenai 				      (q->bar2_addr + SGE_UDB_WCDOORBELL),
965df64e4d3SHariprasad Shenai 				      wr);
966d63a6dcfSHariprasad Shenai 		} else {
967f612b815SHariprasad Shenai 			writel(val | QID_V(q->bar2_qid),
968df64e4d3SHariprasad Shenai 			       q->bar2_addr + SGE_UDB_KDOORBELL);
969d63a6dcfSHariprasad Shenai 		}
970d63a6dcfSHariprasad Shenai 
971d63a6dcfSHariprasad Shenai 		/* This Write Memory Barrier will force the write to the User
972d63a6dcfSHariprasad Shenai 		 * Doorbell area to be flushed.  This is needed to prevent
973d63a6dcfSHariprasad Shenai 		 * writes on different CPUs for the same queue from hitting
974d63a6dcfSHariprasad Shenai 		 * the adapter out of order.  This is required when some Work
975d63a6dcfSHariprasad Shenai 		 * Requests take the Write Combine Gather Buffer path (user
976d63a6dcfSHariprasad Shenai 		 * doorbell area offset [SGE_UDB_WCDOORBELL..+63]) and some
977d63a6dcfSHariprasad Shenai 		 * take the traditional path where we simply increment the
978d63a6dcfSHariprasad Shenai 		 * PIDX (User Doorbell area SGE_UDB_KDOORBELL) and have the
979d63a6dcfSHariprasad Shenai 		 * hardware DMA read the actual Work Request.
980d63a6dcfSHariprasad Shenai 		 */
981d63a6dcfSHariprasad Shenai 		wmb();
982d63a6dcfSHariprasad Shenai 	}
983f7917c00SJeff Kirsher }
984a6ec572bSAtul Gupta EXPORT_SYMBOL(cxgb4_ring_tx_db);
985f7917c00SJeff Kirsher 
986f7917c00SJeff Kirsher /**
987a6ec572bSAtul Gupta  *	cxgb4_inline_tx_skb - inline a packet's data into Tx descriptors
988f7917c00SJeff Kirsher  *	@skb: the packet
989f7917c00SJeff Kirsher  *	@q: the Tx queue where the packet will be inlined
990f7917c00SJeff Kirsher  *	@pos: starting position in the Tx queue where to inline the packet
991f7917c00SJeff Kirsher  *
992f7917c00SJeff Kirsher  *	Inline a packet's contents directly into Tx descriptors, starting at
993f7917c00SJeff Kirsher  *	the given position within the Tx DMA ring.
994f7917c00SJeff Kirsher  *	Most of the complexity of this operation is dealing with wrap arounds
995f7917c00SJeff Kirsher  *	in the middle of the packet we want to inline.
996f7917c00SJeff Kirsher  */
997a6ec572bSAtul Gupta void cxgb4_inline_tx_skb(const struct sk_buff *skb,
998a6ec572bSAtul Gupta 			 const struct sge_txq *q, void *pos)
999f7917c00SJeff Kirsher {
1000f7917c00SJeff Kirsher 	int left = (void *)q->stat - pos;
1001e383f248SAtul Gupta 	u64 *p;
1002f7917c00SJeff Kirsher 
1003f7917c00SJeff Kirsher 	if (likely(skb->len <= left)) {
1004f7917c00SJeff Kirsher 		if (likely(!skb->data_len))
1005f7917c00SJeff Kirsher 			skb_copy_from_linear_data(skb, pos, skb->len);
1006f7917c00SJeff Kirsher 		else
1007f7917c00SJeff Kirsher 			skb_copy_bits(skb, 0, pos, skb->len);
1008f7917c00SJeff Kirsher 		pos += skb->len;
1009f7917c00SJeff Kirsher 	} else {
1010f7917c00SJeff Kirsher 		skb_copy_bits(skb, 0, pos, left);
1011f7917c00SJeff Kirsher 		skb_copy_bits(skb, left, q->desc, skb->len - left);
1012f7917c00SJeff Kirsher 		pos = (void *)q->desc + (skb->len - left);
1013f7917c00SJeff Kirsher 	}
1014f7917c00SJeff Kirsher 
1015f7917c00SJeff Kirsher 	/* 0-pad to multiple of 16 */
1016f7917c00SJeff Kirsher 	p = PTR_ALIGN(pos, 8);
1017f7917c00SJeff Kirsher 	if ((uintptr_t)p & 8)
1018f7917c00SJeff Kirsher 		*p = 0;
1019f7917c00SJeff Kirsher }
1020a6ec572bSAtul Gupta EXPORT_SYMBOL(cxgb4_inline_tx_skb);
1021f7917c00SJeff Kirsher 
10228d0557d2SHariprasad Shenai static void *inline_tx_skb_header(const struct sk_buff *skb,
10238d0557d2SHariprasad Shenai 				  const struct sge_txq *q,  void *pos,
10248d0557d2SHariprasad Shenai 				  int length)
10258d0557d2SHariprasad Shenai {
10268d0557d2SHariprasad Shenai 	u64 *p;
10278d0557d2SHariprasad Shenai 	int left = (void *)q->stat - pos;
10288d0557d2SHariprasad Shenai 
10298d0557d2SHariprasad Shenai 	if (likely(length <= left)) {
10308d0557d2SHariprasad Shenai 		memcpy(pos, skb->data, length);
10318d0557d2SHariprasad Shenai 		pos += length;
10328d0557d2SHariprasad Shenai 	} else {
10338d0557d2SHariprasad Shenai 		memcpy(pos, skb->data, left);
10348d0557d2SHariprasad Shenai 		memcpy(q->desc, skb->data + left, length - left);
10358d0557d2SHariprasad Shenai 		pos = (void *)q->desc + (length - left);
10368d0557d2SHariprasad Shenai 	}
10378d0557d2SHariprasad Shenai 	/* 0-pad to multiple of 16 */
10388d0557d2SHariprasad Shenai 	p = PTR_ALIGN(pos, 8);
10398d0557d2SHariprasad Shenai 	if ((uintptr_t)p & 8) {
10408d0557d2SHariprasad Shenai 		*p = 0;
10418d0557d2SHariprasad Shenai 		return p + 1;
10428d0557d2SHariprasad Shenai 	}
10438d0557d2SHariprasad Shenai 	return p;
10448d0557d2SHariprasad Shenai }
10458d0557d2SHariprasad Shenai 
1046f7917c00SJeff Kirsher /*
1047f7917c00SJeff Kirsher  * Figure out what HW csum a packet wants and return the appropriate control
1048f7917c00SJeff Kirsher  * bits.
1049f7917c00SJeff Kirsher  */
10503ccc6cf7SHariprasad Shenai static u64 hwcsum(enum chip_type chip, const struct sk_buff *skb)
1051f7917c00SJeff Kirsher {
1052f7917c00SJeff Kirsher 	int csum_type;
1053c50ae55eSGanesh Goudar 	bool inner_hdr_csum = false;
1054c50ae55eSGanesh Goudar 	u16 proto, ver;
1055f7917c00SJeff Kirsher 
1056c50ae55eSGanesh Goudar 	if (skb->encapsulation &&
1057c50ae55eSGanesh Goudar 	    (CHELSIO_CHIP_VERSION(chip) > CHELSIO_T5))
1058c50ae55eSGanesh Goudar 		inner_hdr_csum = true;
1059c50ae55eSGanesh Goudar 
1060c50ae55eSGanesh Goudar 	if (inner_hdr_csum) {
1061c50ae55eSGanesh Goudar 		ver = inner_ip_hdr(skb)->version;
1062c50ae55eSGanesh Goudar 		proto = (ver == 4) ? inner_ip_hdr(skb)->protocol :
1063c50ae55eSGanesh Goudar 			inner_ipv6_hdr(skb)->nexthdr;
1064c50ae55eSGanesh Goudar 	} else {
1065c50ae55eSGanesh Goudar 		ver = ip_hdr(skb)->version;
1066c50ae55eSGanesh Goudar 		proto = (ver == 4) ? ip_hdr(skb)->protocol :
1067c50ae55eSGanesh Goudar 			ipv6_hdr(skb)->nexthdr;
1068c50ae55eSGanesh Goudar 	}
1069c50ae55eSGanesh Goudar 
1070c50ae55eSGanesh Goudar 	if (ver == 4) {
1071c50ae55eSGanesh Goudar 		if (proto == IPPROTO_TCP)
1072f7917c00SJeff Kirsher 			csum_type = TX_CSUM_TCPIP;
1073c50ae55eSGanesh Goudar 		else if (proto == IPPROTO_UDP)
1074f7917c00SJeff Kirsher 			csum_type = TX_CSUM_UDPIP;
1075f7917c00SJeff Kirsher 		else {
1076f7917c00SJeff Kirsher nocsum:			/*
1077f7917c00SJeff Kirsher 			 * unknown protocol, disable HW csum
1078f7917c00SJeff Kirsher 			 * and hope a bad packet is detected
1079f7917c00SJeff Kirsher 			 */
10801ecc7b7aSHariprasad Shenai 			return TXPKT_L4CSUM_DIS_F;
1081f7917c00SJeff Kirsher 		}
1082f7917c00SJeff Kirsher 	} else {
1083f7917c00SJeff Kirsher 		/*
1084f7917c00SJeff Kirsher 		 * this doesn't work with extension headers
1085f7917c00SJeff Kirsher 		 */
1086c50ae55eSGanesh Goudar 		if (proto == IPPROTO_TCP)
1087f7917c00SJeff Kirsher 			csum_type = TX_CSUM_TCPIP6;
1088c50ae55eSGanesh Goudar 		else if (proto == IPPROTO_UDP)
1089f7917c00SJeff Kirsher 			csum_type = TX_CSUM_UDPIP6;
1090f7917c00SJeff Kirsher 		else
1091f7917c00SJeff Kirsher 			goto nocsum;
1092f7917c00SJeff Kirsher 	}
1093f7917c00SJeff Kirsher 
10943ccc6cf7SHariprasad Shenai 	if (likely(csum_type >= TX_CSUM_TCPIP)) {
1095c50ae55eSGanesh Goudar 		int eth_hdr_len, l4_len;
1096c50ae55eSGanesh Goudar 		u64 hdr_len;
1097c50ae55eSGanesh Goudar 
1098c50ae55eSGanesh Goudar 		if (inner_hdr_csum) {
1099c50ae55eSGanesh Goudar 			/* This allows checksum offload for all encapsulated
1100c50ae55eSGanesh Goudar 			 * packets like GRE etc..
1101c50ae55eSGanesh Goudar 			 */
1102c50ae55eSGanesh Goudar 			l4_len = skb_inner_network_header_len(skb);
1103c50ae55eSGanesh Goudar 			eth_hdr_len = skb_inner_network_offset(skb) - ETH_HLEN;
1104c50ae55eSGanesh Goudar 		} else {
1105c50ae55eSGanesh Goudar 			l4_len = skb_network_header_len(skb);
1106c50ae55eSGanesh Goudar 			eth_hdr_len = skb_network_offset(skb) - ETH_HLEN;
1107c50ae55eSGanesh Goudar 		}
1108c50ae55eSGanesh Goudar 		hdr_len = TXPKT_IPHDR_LEN_V(l4_len);
11093ccc6cf7SHariprasad Shenai 
11103ccc6cf7SHariprasad Shenai 		if (CHELSIO_CHIP_VERSION(chip) <= CHELSIO_T5)
11113ccc6cf7SHariprasad Shenai 			hdr_len |= TXPKT_ETHHDR_LEN_V(eth_hdr_len);
11123ccc6cf7SHariprasad Shenai 		else
11133ccc6cf7SHariprasad Shenai 			hdr_len |= T6_TXPKT_ETHHDR_LEN_V(eth_hdr_len);
11143ccc6cf7SHariprasad Shenai 		return TXPKT_CSUM_TYPE_V(csum_type) | hdr_len;
11153ccc6cf7SHariprasad Shenai 	} else {
1116f7917c00SJeff Kirsher 		int start = skb_transport_offset(skb);
1117f7917c00SJeff Kirsher 
11181ecc7b7aSHariprasad Shenai 		return TXPKT_CSUM_TYPE_V(csum_type) |
11191ecc7b7aSHariprasad Shenai 			TXPKT_CSUM_START_V(start) |
11201ecc7b7aSHariprasad Shenai 			TXPKT_CSUM_LOC_V(start + skb->csum_offset);
1121f7917c00SJeff Kirsher 	}
1122f7917c00SJeff Kirsher }
1123f7917c00SJeff Kirsher 
1124f7917c00SJeff Kirsher static void eth_txq_stop(struct sge_eth_txq *q)
1125f7917c00SJeff Kirsher {
1126f7917c00SJeff Kirsher 	netif_tx_stop_queue(q->txq);
1127f7917c00SJeff Kirsher 	q->q.stops++;
1128f7917c00SJeff Kirsher }
1129f7917c00SJeff Kirsher 
1130f7917c00SJeff Kirsher static inline void txq_advance(struct sge_txq *q, unsigned int n)
1131f7917c00SJeff Kirsher {
1132f7917c00SJeff Kirsher 	q->in_use += n;
1133f7917c00SJeff Kirsher 	q->pidx += n;
1134f7917c00SJeff Kirsher 	if (q->pidx >= q->size)
1135f7917c00SJeff Kirsher 		q->pidx -= q->size;
1136f7917c00SJeff Kirsher }
1137f7917c00SJeff Kirsher 
113884a200b3SVarun Prakash #ifdef CONFIG_CHELSIO_T4_FCOE
113984a200b3SVarun Prakash static inline int
114084a200b3SVarun Prakash cxgb_fcoe_offload(struct sk_buff *skb, struct adapter *adap,
114184a200b3SVarun Prakash 		  const struct port_info *pi, u64 *cntrl)
114284a200b3SVarun Prakash {
114384a200b3SVarun Prakash 	const struct cxgb_fcoe *fcoe = &pi->fcoe;
114484a200b3SVarun Prakash 
114584a200b3SVarun Prakash 	if (!(fcoe->flags & CXGB_FCOE_ENABLED))
114684a200b3SVarun Prakash 		return 0;
114784a200b3SVarun Prakash 
114884a200b3SVarun Prakash 	if (skb->protocol != htons(ETH_P_FCOE))
114984a200b3SVarun Prakash 		return 0;
115084a200b3SVarun Prakash 
115184a200b3SVarun Prakash 	skb_reset_mac_header(skb);
115284a200b3SVarun Prakash 	skb->mac_len = sizeof(struct ethhdr);
115384a200b3SVarun Prakash 
115484a200b3SVarun Prakash 	skb_set_network_header(skb, skb->mac_len);
115584a200b3SVarun Prakash 	skb_set_transport_header(skb, skb->mac_len + sizeof(struct fcoe_hdr));
115684a200b3SVarun Prakash 
115784a200b3SVarun Prakash 	if (!cxgb_fcoe_sof_eof_supported(adap, skb))
115884a200b3SVarun Prakash 		return -ENOTSUPP;
115984a200b3SVarun Prakash 
116084a200b3SVarun Prakash 	/* FC CRC offload */
11611ecc7b7aSHariprasad Shenai 	*cntrl = TXPKT_CSUM_TYPE_V(TX_CSUM_FCOE) |
11621ecc7b7aSHariprasad Shenai 		     TXPKT_L4CSUM_DIS_F | TXPKT_IPCSUM_DIS_F |
11631ecc7b7aSHariprasad Shenai 		     TXPKT_CSUM_START_V(CXGB_FCOE_TXPKT_CSUM_START) |
11641ecc7b7aSHariprasad Shenai 		     TXPKT_CSUM_END_V(CXGB_FCOE_TXPKT_CSUM_END) |
11651ecc7b7aSHariprasad Shenai 		     TXPKT_CSUM_LOC_V(CXGB_FCOE_TXPKT_CSUM_END);
116684a200b3SVarun Prakash 	return 0;
116784a200b3SVarun Prakash }
116884a200b3SVarun Prakash #endif /* CONFIG_CHELSIO_T4_FCOE */
116984a200b3SVarun Prakash 
1170d0a1299cSGanesh Goudar /* Returns tunnel type if hardware supports offloading of the same.
1171d0a1299cSGanesh Goudar  * It is called only for T5 and onwards.
1172d0a1299cSGanesh Goudar  */
1173d0a1299cSGanesh Goudar enum cpl_tx_tnl_lso_type cxgb_encap_offload_supported(struct sk_buff *skb)
1174d0a1299cSGanesh Goudar {
1175d0a1299cSGanesh Goudar 	u8 l4_hdr = 0;
1176d0a1299cSGanesh Goudar 	enum cpl_tx_tnl_lso_type tnl_type = TX_TNL_TYPE_OPAQUE;
1177d0a1299cSGanesh Goudar 	struct port_info *pi = netdev_priv(skb->dev);
1178d0a1299cSGanesh Goudar 	struct adapter *adapter = pi->adapter;
1179d0a1299cSGanesh Goudar 
1180d0a1299cSGanesh Goudar 	if (skb->inner_protocol_type != ENCAP_TYPE_ETHER ||
1181d0a1299cSGanesh Goudar 	    skb->inner_protocol != htons(ETH_P_TEB))
1182d0a1299cSGanesh Goudar 		return tnl_type;
1183d0a1299cSGanesh Goudar 
1184d0a1299cSGanesh Goudar 	switch (vlan_get_protocol(skb)) {
1185d0a1299cSGanesh Goudar 	case htons(ETH_P_IP):
1186d0a1299cSGanesh Goudar 		l4_hdr = ip_hdr(skb)->protocol;
1187d0a1299cSGanesh Goudar 		break;
1188d0a1299cSGanesh Goudar 	case htons(ETH_P_IPV6):
1189d0a1299cSGanesh Goudar 		l4_hdr = ipv6_hdr(skb)->nexthdr;
1190d0a1299cSGanesh Goudar 		break;
1191d0a1299cSGanesh Goudar 	default:
1192d0a1299cSGanesh Goudar 		return tnl_type;
1193d0a1299cSGanesh Goudar 	}
1194d0a1299cSGanesh Goudar 
1195d0a1299cSGanesh Goudar 	switch (l4_hdr) {
1196d0a1299cSGanesh Goudar 	case IPPROTO_UDP:
1197d0a1299cSGanesh Goudar 		if (adapter->vxlan_port == udp_hdr(skb)->dest)
1198d0a1299cSGanesh Goudar 			tnl_type = TX_TNL_TYPE_VXLAN;
1199c746fc0eSGanesh Goudar 		else if (adapter->geneve_port == udp_hdr(skb)->dest)
1200c746fc0eSGanesh Goudar 			tnl_type = TX_TNL_TYPE_GENEVE;
1201d0a1299cSGanesh Goudar 		break;
1202d0a1299cSGanesh Goudar 	default:
1203d0a1299cSGanesh Goudar 		return tnl_type;
1204d0a1299cSGanesh Goudar 	}
1205d0a1299cSGanesh Goudar 
1206d0a1299cSGanesh Goudar 	return tnl_type;
1207d0a1299cSGanesh Goudar }
1208d0a1299cSGanesh Goudar 
1209d0a1299cSGanesh Goudar static inline void t6_fill_tnl_lso(struct sk_buff *skb,
1210d0a1299cSGanesh Goudar 				   struct cpl_tx_tnl_lso *tnl_lso,
1211d0a1299cSGanesh Goudar 				   enum cpl_tx_tnl_lso_type tnl_type)
1212d0a1299cSGanesh Goudar {
1213d0a1299cSGanesh Goudar 	u32 val;
1214d0a1299cSGanesh Goudar 	int in_eth_xtra_len;
1215d0a1299cSGanesh Goudar 	int l3hdr_len = skb_network_header_len(skb);
1216d0a1299cSGanesh Goudar 	int eth_xtra_len = skb_network_offset(skb) - ETH_HLEN;
1217d0a1299cSGanesh Goudar 	const struct skb_shared_info *ssi = skb_shinfo(skb);
1218d0a1299cSGanesh Goudar 	bool v6 = (ip_hdr(skb)->version == 6);
1219d0a1299cSGanesh Goudar 
1220d0a1299cSGanesh Goudar 	val = CPL_TX_TNL_LSO_OPCODE_V(CPL_TX_TNL_LSO) |
1221d0a1299cSGanesh Goudar 	      CPL_TX_TNL_LSO_FIRST_F |
1222d0a1299cSGanesh Goudar 	      CPL_TX_TNL_LSO_LAST_F |
1223d0a1299cSGanesh Goudar 	      (v6 ? CPL_TX_TNL_LSO_IPV6OUT_F : 0) |
1224d0a1299cSGanesh Goudar 	      CPL_TX_TNL_LSO_ETHHDRLENOUT_V(eth_xtra_len / 4) |
1225d0a1299cSGanesh Goudar 	      CPL_TX_TNL_LSO_IPHDRLENOUT_V(l3hdr_len / 4) |
1226d0a1299cSGanesh Goudar 	      (v6 ? 0 : CPL_TX_TNL_LSO_IPHDRCHKOUT_F) |
1227d0a1299cSGanesh Goudar 	      CPL_TX_TNL_LSO_IPLENSETOUT_F |
1228d0a1299cSGanesh Goudar 	      (v6 ? 0 : CPL_TX_TNL_LSO_IPIDINCOUT_F);
1229d0a1299cSGanesh Goudar 	tnl_lso->op_to_IpIdSplitOut = htonl(val);
1230d0a1299cSGanesh Goudar 
1231d0a1299cSGanesh Goudar 	tnl_lso->IpIdOffsetOut = 0;
1232d0a1299cSGanesh Goudar 
1233d0a1299cSGanesh Goudar 	/* Get the tunnel header length */
1234d0a1299cSGanesh Goudar 	val = skb_inner_mac_header(skb) - skb_mac_header(skb);
1235d0a1299cSGanesh Goudar 	in_eth_xtra_len = skb_inner_network_header(skb) -
1236d0a1299cSGanesh Goudar 			  skb_inner_mac_header(skb) - ETH_HLEN;
1237d0a1299cSGanesh Goudar 
1238d0a1299cSGanesh Goudar 	switch (tnl_type) {
1239d0a1299cSGanesh Goudar 	case TX_TNL_TYPE_VXLAN:
1240c746fc0eSGanesh Goudar 	case TX_TNL_TYPE_GENEVE:
1241d0a1299cSGanesh Goudar 		tnl_lso->UdpLenSetOut_to_TnlHdrLen =
1242d0a1299cSGanesh Goudar 			htons(CPL_TX_TNL_LSO_UDPCHKCLROUT_F |
1243d0a1299cSGanesh Goudar 			CPL_TX_TNL_LSO_UDPLENSETOUT_F);
1244d0a1299cSGanesh Goudar 		break;
1245d0a1299cSGanesh Goudar 	default:
1246d0a1299cSGanesh Goudar 		tnl_lso->UdpLenSetOut_to_TnlHdrLen = 0;
1247d0a1299cSGanesh Goudar 		break;
1248d0a1299cSGanesh Goudar 	}
1249d0a1299cSGanesh Goudar 
1250d0a1299cSGanesh Goudar 	tnl_lso->UdpLenSetOut_to_TnlHdrLen |=
1251d0a1299cSGanesh Goudar 		 htons(CPL_TX_TNL_LSO_TNLHDRLEN_V(val) |
1252d0a1299cSGanesh Goudar 		       CPL_TX_TNL_LSO_TNLTYPE_V(tnl_type));
1253d0a1299cSGanesh Goudar 
1254d0a1299cSGanesh Goudar 	tnl_lso->r1 = 0;
1255d0a1299cSGanesh Goudar 
1256d0a1299cSGanesh Goudar 	val = CPL_TX_TNL_LSO_ETHHDRLEN_V(in_eth_xtra_len / 4) |
1257d0a1299cSGanesh Goudar 	      CPL_TX_TNL_LSO_IPV6_V(inner_ip_hdr(skb)->version == 6) |
1258d0a1299cSGanesh Goudar 	      CPL_TX_TNL_LSO_IPHDRLEN_V(skb_inner_network_header_len(skb) / 4) |
1259d0a1299cSGanesh Goudar 	      CPL_TX_TNL_LSO_TCPHDRLEN_V(inner_tcp_hdrlen(skb) / 4);
1260d0a1299cSGanesh Goudar 	tnl_lso->Flow_to_TcpHdrLen = htonl(val);
1261d0a1299cSGanesh Goudar 
1262d0a1299cSGanesh Goudar 	tnl_lso->IpIdOffset = htons(0);
1263d0a1299cSGanesh Goudar 
1264d0a1299cSGanesh Goudar 	tnl_lso->IpIdSplit_to_Mss = htons(CPL_TX_TNL_LSO_MSS_V(ssi->gso_size));
1265d0a1299cSGanesh Goudar 	tnl_lso->TCPSeqOffset = htonl(0);
1266d0a1299cSGanesh Goudar 	tnl_lso->EthLenOffset_Size = htonl(CPL_TX_TNL_LSO_SIZE_V(skb->len));
1267d0a1299cSGanesh Goudar }
1268d0a1299cSGanesh Goudar 
12694846d533SRahul Lakkireddy static inline void *write_tso_wr(struct adapter *adap, struct sk_buff *skb,
12704846d533SRahul Lakkireddy 				 struct cpl_tx_pkt_lso_core *lso)
12714846d533SRahul Lakkireddy {
12724846d533SRahul Lakkireddy 	int eth_xtra_len = skb_network_offset(skb) - ETH_HLEN;
12734846d533SRahul Lakkireddy 	int l3hdr_len = skb_network_header_len(skb);
12744846d533SRahul Lakkireddy 	const struct skb_shared_info *ssi;
12754846d533SRahul Lakkireddy 	bool ipv6 = false;
12764846d533SRahul Lakkireddy 
12774846d533SRahul Lakkireddy 	ssi = skb_shinfo(skb);
12784846d533SRahul Lakkireddy 	if (ssi->gso_type & SKB_GSO_TCPV6)
12794846d533SRahul Lakkireddy 		ipv6 = true;
12804846d533SRahul Lakkireddy 
12814846d533SRahul Lakkireddy 	lso->lso_ctrl = htonl(LSO_OPCODE_V(CPL_TX_PKT_LSO) |
12824846d533SRahul Lakkireddy 			      LSO_FIRST_SLICE_F | LSO_LAST_SLICE_F |
12834846d533SRahul Lakkireddy 			      LSO_IPV6_V(ipv6) |
12844846d533SRahul Lakkireddy 			      LSO_ETHHDR_LEN_V(eth_xtra_len / 4) |
12854846d533SRahul Lakkireddy 			      LSO_IPHDR_LEN_V(l3hdr_len / 4) |
12864846d533SRahul Lakkireddy 			      LSO_TCPHDR_LEN_V(tcp_hdr(skb)->doff));
12874846d533SRahul Lakkireddy 	lso->ipid_ofst = htons(0);
12884846d533SRahul Lakkireddy 	lso->mss = htons(ssi->gso_size);
12894846d533SRahul Lakkireddy 	lso->seqno_offset = htonl(0);
12904846d533SRahul Lakkireddy 	if (is_t4(adap->params.chip))
12914846d533SRahul Lakkireddy 		lso->len = htonl(skb->len);
12924846d533SRahul Lakkireddy 	else
12934846d533SRahul Lakkireddy 		lso->len = htonl(LSO_T5_XFER_SIZE_V(skb->len));
12944846d533SRahul Lakkireddy 
12954846d533SRahul Lakkireddy 	return (void *)(lso + 1);
12964846d533SRahul Lakkireddy }
12974846d533SRahul Lakkireddy 
1298f7917c00SJeff Kirsher /**
1299d429005fSVishal Kulkarni  *	t4_sge_eth_txq_egress_update - handle Ethernet TX Queue update
1300d429005fSVishal Kulkarni  *	@adap: the adapter
1301d429005fSVishal Kulkarni  *	@eq: the Ethernet TX Queue
1302d429005fSVishal Kulkarni  *	@maxreclaim: the maximum number of TX Descriptors to reclaim or -1
1303d429005fSVishal Kulkarni  *
1304d429005fSVishal Kulkarni  *	We're typically called here to update the state of an Ethernet TX
1305d429005fSVishal Kulkarni  *	Queue with respect to the hardware's progress in consuming the TX
1306d429005fSVishal Kulkarni  *	Work Requests that we've put on that Egress Queue.  This happens
1307d429005fSVishal Kulkarni  *	when we get Egress Queue Update messages and also prophylactically
1308d429005fSVishal Kulkarni  *	in regular timer-based Ethernet TX Queue maintenance.
1309d429005fSVishal Kulkarni  */
1310d429005fSVishal Kulkarni int t4_sge_eth_txq_egress_update(struct adapter *adap, struct sge_eth_txq *eq,
1311d429005fSVishal Kulkarni 				 int maxreclaim)
1312d429005fSVishal Kulkarni {
1313f1f20a86SRahul Lakkireddy 	unsigned int reclaimed, hw_cidx;
1314d429005fSVishal Kulkarni 	struct sge_txq *q = &eq->q;
1315f1f20a86SRahul Lakkireddy 	int hw_in_use;
1316d429005fSVishal Kulkarni 
1317d429005fSVishal Kulkarni 	if (!q->in_use || !__netif_tx_trylock(eq->txq))
1318d429005fSVishal Kulkarni 		return 0;
1319d429005fSVishal Kulkarni 
1320d429005fSVishal Kulkarni 	/* Reclaim pending completed TX Descriptors. */
1321d429005fSVishal Kulkarni 	reclaimed = reclaim_completed_tx(adap, &eq->q, maxreclaim, true);
1322d429005fSVishal Kulkarni 
1323f1f20a86SRahul Lakkireddy 	hw_cidx = ntohs(READ_ONCE(q->stat->cidx));
1324f1f20a86SRahul Lakkireddy 	hw_in_use = q->pidx - hw_cidx;
1325f1f20a86SRahul Lakkireddy 	if (hw_in_use < 0)
1326f1f20a86SRahul Lakkireddy 		hw_in_use += q->size;
1327f1f20a86SRahul Lakkireddy 
1328d429005fSVishal Kulkarni 	/* If the TX Queue is currently stopped and there's now more than half
1329d429005fSVishal Kulkarni 	 * the queue available, restart it.  Otherwise bail out since the rest
1330d429005fSVishal Kulkarni 	 * of what we want do here is with the possibility of shipping any
1331d429005fSVishal Kulkarni 	 * currently buffered Coalesced TX Work Request.
1332d429005fSVishal Kulkarni 	 */
1333f1f20a86SRahul Lakkireddy 	if (netif_tx_queue_stopped(eq->txq) && hw_in_use < (q->size / 2)) {
1334d429005fSVishal Kulkarni 		netif_tx_wake_queue(eq->txq);
1335d429005fSVishal Kulkarni 		eq->q.restarts++;
1336d429005fSVishal Kulkarni 	}
1337d429005fSVishal Kulkarni 
1338d429005fSVishal Kulkarni 	__netif_tx_unlock(eq->txq);
1339d429005fSVishal Kulkarni 	return reclaimed;
1340d429005fSVishal Kulkarni }
1341d429005fSVishal Kulkarni 
1342b1396c2bSRahul Lakkireddy static inline int cxgb4_validate_skb(struct sk_buff *skb,
1343b1396c2bSRahul Lakkireddy 				     struct net_device *dev,
1344b1396c2bSRahul Lakkireddy 				     u32 min_pkt_len)
1345b1396c2bSRahul Lakkireddy {
1346b1396c2bSRahul Lakkireddy 	u32 max_pkt_len;
1347b1396c2bSRahul Lakkireddy 
1348b1396c2bSRahul Lakkireddy 	/* The chip min packet length is 10 octets but some firmware
1349b1396c2bSRahul Lakkireddy 	 * commands have a minimum packet length requirement. So, play
1350b1396c2bSRahul Lakkireddy 	 * safe and reject anything shorter than @min_pkt_len.
1351b1396c2bSRahul Lakkireddy 	 */
1352b1396c2bSRahul Lakkireddy 	if (unlikely(skb->len < min_pkt_len))
1353b1396c2bSRahul Lakkireddy 		return -EINVAL;
1354b1396c2bSRahul Lakkireddy 
1355b1396c2bSRahul Lakkireddy 	/* Discard the packet if the length is greater than mtu */
1356b1396c2bSRahul Lakkireddy 	max_pkt_len = ETH_HLEN + dev->mtu;
1357b1396c2bSRahul Lakkireddy 
1358b1396c2bSRahul Lakkireddy 	if (skb_vlan_tagged(skb))
1359b1396c2bSRahul Lakkireddy 		max_pkt_len += VLAN_HLEN;
1360b1396c2bSRahul Lakkireddy 
1361b1396c2bSRahul Lakkireddy 	if (!skb_shinfo(skb)->gso_size && (unlikely(skb->len > max_pkt_len)))
1362b1396c2bSRahul Lakkireddy 		return -EINVAL;
1363b1396c2bSRahul Lakkireddy 
1364b1396c2bSRahul Lakkireddy 	return 0;
1365b1396c2bSRahul Lakkireddy }
1366b1396c2bSRahul Lakkireddy 
13671a2a14fbSRahul Lakkireddy static void *write_eo_udp_wr(struct sk_buff *skb, struct fw_eth_tx_eo_wr *wr,
13681a2a14fbSRahul Lakkireddy 			     u32 hdr_len)
13691a2a14fbSRahul Lakkireddy {
13701a2a14fbSRahul Lakkireddy 	wr->u.udpseg.type = FW_ETH_TX_EO_TYPE_UDPSEG;
13711a2a14fbSRahul Lakkireddy 	wr->u.udpseg.ethlen = skb_network_offset(skb);
13721a2a14fbSRahul Lakkireddy 	wr->u.udpseg.iplen = cpu_to_be16(skb_network_header_len(skb));
13731a2a14fbSRahul Lakkireddy 	wr->u.udpseg.udplen = sizeof(struct udphdr);
13741a2a14fbSRahul Lakkireddy 	wr->u.udpseg.rtplen = 0;
13751a2a14fbSRahul Lakkireddy 	wr->u.udpseg.r4 = 0;
13761a2a14fbSRahul Lakkireddy 	if (skb_shinfo(skb)->gso_size)
13771a2a14fbSRahul Lakkireddy 		wr->u.udpseg.mss = cpu_to_be16(skb_shinfo(skb)->gso_size);
13781a2a14fbSRahul Lakkireddy 	else
13791a2a14fbSRahul Lakkireddy 		wr->u.udpseg.mss = cpu_to_be16(skb->len - hdr_len);
13801a2a14fbSRahul Lakkireddy 	wr->u.udpseg.schedpktsize = wr->u.udpseg.mss;
13811a2a14fbSRahul Lakkireddy 	wr->u.udpseg.plen = cpu_to_be32(skb->len - hdr_len);
13821a2a14fbSRahul Lakkireddy 
13831a2a14fbSRahul Lakkireddy 	return (void *)(wr + 1);
13841a2a14fbSRahul Lakkireddy }
13851a2a14fbSRahul Lakkireddy 
1386d429005fSVishal Kulkarni /**
1387d5fbda61SArjun Vynipadath  *	cxgb4_eth_xmit - add a packet to an Ethernet Tx queue
1388f7917c00SJeff Kirsher  *	@skb: the packet
1389f7917c00SJeff Kirsher  *	@dev: the egress net device
1390f7917c00SJeff Kirsher  *
1391f7917c00SJeff Kirsher  *	Add a packet to an SGE Ethernet Tx queue.  Runs with softirqs disabled.
1392f7917c00SJeff Kirsher  */
1393d5fbda61SArjun Vynipadath static netdev_tx_t cxgb4_eth_xmit(struct sk_buff *skb, struct net_device *dev)
1394f7917c00SJeff Kirsher {
1395b1396c2bSRahul Lakkireddy 	enum cpl_tx_tnl_lso_type tnl_type = TX_TNL_TYPE_OPAQUE;
1396b1396c2bSRahul Lakkireddy 	bool ptp_enabled = is_ptp_enabled(skb, dev);
13970ed96b46SRahul Lakkireddy 	unsigned int last_desc, flits, ndesc;
13981a2a14fbSRahul Lakkireddy 	u32 wr_mid, ctrl0, op, sgl_off = 0;
1399b1396c2bSRahul Lakkireddy 	const struct skb_shared_info *ssi;
14001a2a14fbSRahul Lakkireddy 	int len, qidx, credits, ret, left;
14010ed96b46SRahul Lakkireddy 	struct tx_sw_desc *sgl_sdesc;
14021a2a14fbSRahul Lakkireddy 	struct fw_eth_tx_eo_wr *eowr;
1403f7917c00SJeff Kirsher 	struct fw_eth_tx_pkt_wr *wr;
1404f7917c00SJeff Kirsher 	struct cpl_tx_pkt_core *cpl;
1405b1396c2bSRahul Lakkireddy 	const struct port_info *pi;
14060034b298SKumar Sanghvi 	bool immediate = false;
1407b1396c2bSRahul Lakkireddy 	u64 cntrl, *end, *sgl;
1408b1396c2bSRahul Lakkireddy 	struct sge_eth_txq *q;
1409d0a1299cSGanesh Goudar 	unsigned int chip_ver;
1410b1396c2bSRahul Lakkireddy 	struct adapter *adap;
1411d0a1299cSGanesh Goudar 
1412b1396c2bSRahul Lakkireddy 	ret = cxgb4_validate_skb(skb, dev, ETH_HLEN);
1413b1396c2bSRahul Lakkireddy 	if (ret)
1414637d3e99SHariprasad Shenai 		goto out_free;
1415637d3e99SHariprasad Shenai 
1416f7917c00SJeff Kirsher 	pi = netdev_priv(dev);
1417f7917c00SJeff Kirsher 	adap = pi->adapter;
1418a6ec572bSAtul Gupta 	ssi = skb_shinfo(skb);
1419a6ec572bSAtul Gupta #ifdef CONFIG_CHELSIO_IPSEC_INLINE
1420a6ec572bSAtul Gupta 	if (xfrm_offload(skb) && !ssi->gso_size)
1421a6ec572bSAtul Gupta 		return adap->uld[CXGB4_ULD_CRYPTO].tx_handler(skb, dev);
1422a6ec572bSAtul Gupta #endif /* CHELSIO_IPSEC_INLINE */
1423a6ec572bSAtul Gupta 
14245a4b9fe7SRohit Maheshwari #ifdef CONFIG_CHELSIO_TLS_DEVICE
14255a4b9fe7SRohit Maheshwari 	if (skb->decrypted)
14265a4b9fe7SRohit Maheshwari 		return adap->uld[CXGB4_ULD_CRYPTO].tx_handler(skb, dev);
14275a4b9fe7SRohit Maheshwari #endif /* CHELSIO_TLS_DEVICE */
14285a4b9fe7SRohit Maheshwari 
1429f7917c00SJeff Kirsher 	qidx = skb_get_queue_mapping(skb);
1430a4569504SAtul Gupta 	if (ptp_enabled) {
1431a4569504SAtul Gupta 		if (!(adap->ptp_tx_skb)) {
1432a4569504SAtul Gupta 			skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
1433a4569504SAtul Gupta 			adap->ptp_tx_skb = skb_get(skb);
1434a4569504SAtul Gupta 		} else {
1435a4569504SAtul Gupta 			goto out_free;
1436a4569504SAtul Gupta 		}
1437a4569504SAtul Gupta 		q = &adap->sge.ptptxq;
1438a4569504SAtul Gupta 	} else {
1439f7917c00SJeff Kirsher 		q = &adap->sge.ethtxq[qidx + pi->first_qset];
1440a4569504SAtul Gupta 	}
1441a4569504SAtul Gupta 	skb_tx_timestamp(skb);
1442f7917c00SJeff Kirsher 
1443d429005fSVishal Kulkarni 	reclaim_completed_tx(adap, &q->q, -1, true);
14441ecc7b7aSHariprasad Shenai 	cntrl = TXPKT_L4CSUM_DIS_F | TXPKT_IPCSUM_DIS_F;
144584a200b3SVarun Prakash 
144684a200b3SVarun Prakash #ifdef CONFIG_CHELSIO_T4_FCOE
1447b1396c2bSRahul Lakkireddy 	ret = cxgb_fcoe_offload(skb, adap, pi, &cntrl);
1448030c9882SRahul Lakkireddy 	if (unlikely(ret == -EOPNOTSUPP))
144984a200b3SVarun Prakash 		goto out_free;
145084a200b3SVarun Prakash #endif /* CONFIG_CHELSIO_T4_FCOE */
1451f7917c00SJeff Kirsher 
1452d0a1299cSGanesh Goudar 	chip_ver = CHELSIO_CHIP_VERSION(adap->params.chip);
1453d0a1299cSGanesh Goudar 	flits = calc_tx_flits(skb, chip_ver);
1454f7917c00SJeff Kirsher 	ndesc = flits_to_desc(flits);
1455f7917c00SJeff Kirsher 	credits = txq_avail(&q->q) - ndesc;
1456f7917c00SJeff Kirsher 
1457f7917c00SJeff Kirsher 	if (unlikely(credits < 0)) {
1458f7917c00SJeff Kirsher 		eth_txq_stop(q);
1459f7917c00SJeff Kirsher 		dev_err(adap->pdev_dev,
1460f7917c00SJeff Kirsher 			"%s: Tx ring %u full while queue awake!\n",
1461f7917c00SJeff Kirsher 			dev->name, qidx);
1462f7917c00SJeff Kirsher 		return NETDEV_TX_BUSY;
1463f7917c00SJeff Kirsher 	}
1464f7917c00SJeff Kirsher 
1465d0a1299cSGanesh Goudar 	if (is_eth_imm(skb, chip_ver))
14660034b298SKumar Sanghvi 		immediate = true;
14670034b298SKumar Sanghvi 
1468d0a1299cSGanesh Goudar 	if (skb->encapsulation && chip_ver > CHELSIO_T5)
1469d0a1299cSGanesh Goudar 		tnl_type = cxgb_encap_offload_supported(skb);
1470d0a1299cSGanesh Goudar 
14710ed96b46SRahul Lakkireddy 	last_desc = q->q.pidx + ndesc - 1;
14720ed96b46SRahul Lakkireddy 	if (last_desc >= q->q.size)
14730ed96b46SRahul Lakkireddy 		last_desc -= q->q.size;
14740ed96b46SRahul Lakkireddy 	sgl_sdesc = &q->q.sdesc[last_desc];
14750ed96b46SRahul Lakkireddy 
14760034b298SKumar Sanghvi 	if (!immediate &&
14770ed96b46SRahul Lakkireddy 	    unlikely(cxgb4_map_skb(adap->pdev_dev, skb, sgl_sdesc->addr) < 0)) {
14780ed96b46SRahul Lakkireddy 		memset(sgl_sdesc->addr, 0, sizeof(sgl_sdesc->addr));
1479f7917c00SJeff Kirsher 		q->mapping_err++;
1480f7917c00SJeff Kirsher 		goto out_free;
1481f7917c00SJeff Kirsher 	}
1482f7917c00SJeff Kirsher 
1483e2ac9628SHariprasad Shenai 	wr_mid = FW_WR_LEN16_V(DIV_ROUND_UP(flits, 2));
1484f7917c00SJeff Kirsher 	if (unlikely(credits < ETHTXQ_STOP_THRES)) {
1485d429005fSVishal Kulkarni 		/* After we're done injecting the Work Request for this
1486d429005fSVishal Kulkarni 		 * packet, we'll be below our "stop threshold" so stop the TX
1487d429005fSVishal Kulkarni 		 * Queue now and schedule a request for an SGE Egress Queue
1488d429005fSVishal Kulkarni 		 * Update message. The queue will get started later on when
1489d429005fSVishal Kulkarni 		 * the firmware processes this Work Request and sends us an
1490d429005fSVishal Kulkarni 		 * Egress Queue Status Update message indicating that space
1491d429005fSVishal Kulkarni 		 * has opened up.
1492d429005fSVishal Kulkarni 		 */
1493f7917c00SJeff Kirsher 		eth_txq_stop(q);
1494e2ac9628SHariprasad Shenai 		wr_mid |= FW_WR_EQUEQ_F | FW_WR_EQUIQ_F;
1495f7917c00SJeff Kirsher 	}
1496f7917c00SJeff Kirsher 
1497f7917c00SJeff Kirsher 	wr = (void *)&q->q.desc[q->q.pidx];
14981a2a14fbSRahul Lakkireddy 	eowr = (void *)&q->q.desc[q->q.pidx];
1499f7917c00SJeff Kirsher 	wr->equiq_to_len16 = htonl(wr_mid);
1500f7917c00SJeff Kirsher 	wr->r3 = cpu_to_be64(0);
15011a2a14fbSRahul Lakkireddy 	if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4)
15021a2a14fbSRahul Lakkireddy 		end = (u64 *)eowr + flits;
15031a2a14fbSRahul Lakkireddy 	else
1504f7917c00SJeff Kirsher 		end = (u64 *)wr + flits;
1505f7917c00SJeff Kirsher 
15060034b298SKumar Sanghvi 	len = immediate ? skb->len : 0;
1507a6076fcdSGanesh Goudar 	len += sizeof(*cpl);
15081a2a14fbSRahul Lakkireddy 	if (ssi->gso_size && !(ssi->gso_type & SKB_GSO_UDP_L4)) {
1509a6076fcdSGanesh Goudar 		struct cpl_tx_pkt_lso_core *lso = (void *)(wr + 1);
1510d0a1299cSGanesh Goudar 		struct cpl_tx_tnl_lso *tnl_lso = (void *)(wr + 1);
1511f7917c00SJeff Kirsher 
1512d0a1299cSGanesh Goudar 		if (tnl_type)
1513d0a1299cSGanesh Goudar 			len += sizeof(*tnl_lso);
1514d0a1299cSGanesh Goudar 		else
15150034b298SKumar Sanghvi 			len += sizeof(*lso);
1516d0a1299cSGanesh Goudar 
1517e2ac9628SHariprasad Shenai 		wr->op_immdlen = htonl(FW_WR_OP_V(FW_ETH_TX_PKT_WR) |
1518e2ac9628SHariprasad Shenai 				       FW_WR_IMMDLEN_V(len));
1519d0a1299cSGanesh Goudar 		if (tnl_type) {
1520d0a1299cSGanesh Goudar 			struct iphdr *iph = ip_hdr(skb);
1521d0a1299cSGanesh Goudar 
1522d0a1299cSGanesh Goudar 			t6_fill_tnl_lso(skb, tnl_lso, tnl_type);
1523d0a1299cSGanesh Goudar 			cpl = (void *)(tnl_lso + 1);
1524d0a1299cSGanesh Goudar 			/* Driver is expected to compute partial checksum that
1525d0a1299cSGanesh Goudar 			 * does not include the IP Total Length.
1526d0a1299cSGanesh Goudar 			 */
1527d0a1299cSGanesh Goudar 			if (iph->version == 4) {
1528d0a1299cSGanesh Goudar 				iph->check = 0;
1529d0a1299cSGanesh Goudar 				iph->tot_len = 0;
15302f667016SRahul Lakkireddy 				iph->check = ~ip_fast_csum((u8 *)iph, iph->ihl);
1531d0a1299cSGanesh Goudar 			}
1532d0a1299cSGanesh Goudar 			if (skb->ip_summed == CHECKSUM_PARTIAL)
1533d0a1299cSGanesh Goudar 				cntrl = hwcsum(adap->params.chip, skb);
1534d0a1299cSGanesh Goudar 		} else {
15354846d533SRahul Lakkireddy 			cpl = write_tso_wr(adap, skb, lso);
15364846d533SRahul Lakkireddy 			cntrl = hwcsum(adap->params.chip, skb);
1537d0a1299cSGanesh Goudar 		}
1538c50ae55eSGanesh Goudar 		sgl = (u64 *)(cpl + 1); /* sgl start here */
1539f7917c00SJeff Kirsher 		q->tso++;
1540f7917c00SJeff Kirsher 		q->tx_cso += ssi->gso_segs;
15411a2a14fbSRahul Lakkireddy 	} else if (ssi->gso_size) {
15421a2a14fbSRahul Lakkireddy 		u64 *start;
15431a2a14fbSRahul Lakkireddy 		u32 hdrlen;
15441a2a14fbSRahul Lakkireddy 
15451a2a14fbSRahul Lakkireddy 		hdrlen = eth_get_headlen(dev, skb->data, skb_headlen(skb));
15461a2a14fbSRahul Lakkireddy 		len += hdrlen;
15471a2a14fbSRahul Lakkireddy 		wr->op_immdlen = cpu_to_be32(FW_WR_OP_V(FW_ETH_TX_EO_WR) |
15481a2a14fbSRahul Lakkireddy 					     FW_ETH_TX_EO_WR_IMMDLEN_V(len));
15491a2a14fbSRahul Lakkireddy 		cpl = write_eo_udp_wr(skb, eowr, hdrlen);
15501a2a14fbSRahul Lakkireddy 		cntrl = hwcsum(adap->params.chip, skb);
15511a2a14fbSRahul Lakkireddy 
15521a2a14fbSRahul Lakkireddy 		start = (u64 *)(cpl + 1);
15531a2a14fbSRahul Lakkireddy 		sgl = (u64 *)inline_tx_skb_header(skb, &q->q, (void *)start,
15541a2a14fbSRahul Lakkireddy 						  hdrlen);
15551a2a14fbSRahul Lakkireddy 		if (unlikely(start > sgl)) {
15561a2a14fbSRahul Lakkireddy 			left = (u8 *)end - (u8 *)q->q.stat;
15571a2a14fbSRahul Lakkireddy 			end = (void *)q->q.desc + left;
15581a2a14fbSRahul Lakkireddy 		}
15591a2a14fbSRahul Lakkireddy 		sgl_off = hdrlen;
15601a2a14fbSRahul Lakkireddy 		q->uso++;
15611a2a14fbSRahul Lakkireddy 		q->tx_cso += ssi->gso_segs;
1562f7917c00SJeff Kirsher 	} else {
1563a4569504SAtul Gupta 		if (ptp_enabled)
1564a4569504SAtul Gupta 			op = FW_PTP_TX_PKT_WR;
1565a4569504SAtul Gupta 		else
1566a4569504SAtul Gupta 			op = FW_ETH_TX_PKT_WR;
1567a4569504SAtul Gupta 		wr->op_immdlen = htonl(FW_WR_OP_V(op) |
1568e2ac9628SHariprasad Shenai 				       FW_WR_IMMDLEN_V(len));
1569f7917c00SJeff Kirsher 		cpl = (void *)(wr + 1);
1570c50ae55eSGanesh Goudar 		sgl = (u64 *)(cpl + 1);
1571f7917c00SJeff Kirsher 		if (skb->ip_summed == CHECKSUM_PARTIAL) {
15723ccc6cf7SHariprasad Shenai 			cntrl = hwcsum(adap->params.chip, skb) |
15733ccc6cf7SHariprasad Shenai 				TXPKT_IPCSUM_DIS_F;
1574f7917c00SJeff Kirsher 			q->tx_cso++;
157584a200b3SVarun Prakash 		}
1576f7917c00SJeff Kirsher 	}
1577f7917c00SJeff Kirsher 
15781a2a14fbSRahul Lakkireddy 	if (unlikely((u8 *)sgl >= (u8 *)q->q.stat)) {
15791a2a14fbSRahul Lakkireddy 		/* If current position is already at the end of the
15801a2a14fbSRahul Lakkireddy 		 * txq, reset the current to point to start of the queue
15811a2a14fbSRahul Lakkireddy 		 * and update the end ptr as well.
15821a2a14fbSRahul Lakkireddy 		 */
15831a2a14fbSRahul Lakkireddy 		left = (u8 *)end - (u8 *)q->q.stat;
15841a2a14fbSRahul Lakkireddy 		end = (void *)q->q.desc + left;
15851a2a14fbSRahul Lakkireddy 		sgl = (void *)q->q.desc;
15861a2a14fbSRahul Lakkireddy 	}
15871a2a14fbSRahul Lakkireddy 
1588df8a39deSJiri Pirko 	if (skb_vlan_tag_present(skb)) {
1589f7917c00SJeff Kirsher 		q->vlan_ins++;
15901ecc7b7aSHariprasad Shenai 		cntrl |= TXPKT_VLAN_VLD_F | TXPKT_VLAN_V(skb_vlan_tag_get(skb));
159184a200b3SVarun Prakash #ifdef CONFIG_CHELSIO_T4_FCOE
159284a200b3SVarun Prakash 		if (skb->protocol == htons(ETH_P_FCOE))
15931ecc7b7aSHariprasad Shenai 			cntrl |= TXPKT_VLAN_V(
159484a200b3SVarun Prakash 				 ((skb->priority & 0x7) << VLAN_PRIO_SHIFT));
159584a200b3SVarun Prakash #endif /* CONFIG_CHELSIO_T4_FCOE */
1596f7917c00SJeff Kirsher 	}
1597f7917c00SJeff Kirsher 
1598397665daSAnish Bhatt 	ctrl0 = TXPKT_OPCODE_V(CPL_TX_PKT_XT) | TXPKT_INTF_V(pi->tx_chan) |
1599397665daSAnish Bhatt 		TXPKT_PF_V(adap->pf);
1600a4569504SAtul Gupta 	if (ptp_enabled)
1601a4569504SAtul Gupta 		ctrl0 |= TXPKT_TSTAMP_F;
1602397665daSAnish Bhatt #ifdef CONFIG_CHELSIO_T4_DCB
1603397665daSAnish Bhatt 	if (is_t4(adap->params.chip))
1604397665daSAnish Bhatt 		ctrl0 |= TXPKT_OVLAN_IDX_V(q->dcb_prio);
1605397665daSAnish Bhatt 	else
1606397665daSAnish Bhatt 		ctrl0 |= TXPKT_T5_OVLAN_IDX_V(q->dcb_prio);
1607397665daSAnish Bhatt #endif
1608397665daSAnish Bhatt 	cpl->ctrl0 = htonl(ctrl0);
1609f7917c00SJeff Kirsher 	cpl->pack = htons(0);
1610f7917c00SJeff Kirsher 	cpl->len = htons(skb->len);
1611f7917c00SJeff Kirsher 	cpl->ctrl1 = cpu_to_be64(cntrl);
1612f7917c00SJeff Kirsher 
16130034b298SKumar Sanghvi 	if (immediate) {
1614c50ae55eSGanesh Goudar 		cxgb4_inline_tx_skb(skb, &q->q, sgl);
1615a7525198SEric W. Biederman 		dev_consume_skb_any(skb);
1616f7917c00SJeff Kirsher 	} else {
16171a2a14fbSRahul Lakkireddy 		cxgb4_write_sgl(skb, &q->q, (void *)sgl, end, sgl_off,
16180ed96b46SRahul Lakkireddy 				sgl_sdesc->addr);
1619f7917c00SJeff Kirsher 		skb_orphan(skb);
16200ed96b46SRahul Lakkireddy 		sgl_sdesc->skb = skb;
1621f7917c00SJeff Kirsher 	}
1622f7917c00SJeff Kirsher 
1623f7917c00SJeff Kirsher 	txq_advance(&q->q, ndesc);
1624f7917c00SJeff Kirsher 
1625a6ec572bSAtul Gupta 	cxgb4_ring_tx_db(adap, &q->q, ndesc);
1626f7917c00SJeff Kirsher 	return NETDEV_TX_OK;
1627b1396c2bSRahul Lakkireddy 
1628b1396c2bSRahul Lakkireddy out_free:
1629b1396c2bSRahul Lakkireddy 	dev_kfree_skb_any(skb);
1630b1396c2bSRahul Lakkireddy 	return NETDEV_TX_OK;
1631f7917c00SJeff Kirsher }
1632f7917c00SJeff Kirsher 
1633d5fbda61SArjun Vynipadath /* Constants ... */
1634d5fbda61SArjun Vynipadath enum {
1635d5fbda61SArjun Vynipadath 	/* Egress Queue sizes, producer and consumer indices are all in units
1636d5fbda61SArjun Vynipadath 	 * of Egress Context Units bytes.  Note that as far as the hardware is
1637d5fbda61SArjun Vynipadath 	 * concerned, the free list is an Egress Queue (the host produces free
1638d5fbda61SArjun Vynipadath 	 * buffers which the hardware consumes) and free list entries are
1639d5fbda61SArjun Vynipadath 	 * 64-bit PCI DMA addresses.
1640d5fbda61SArjun Vynipadath 	 */
1641d5fbda61SArjun Vynipadath 	EQ_UNIT = SGE_EQ_IDXSIZE,
1642d5fbda61SArjun Vynipadath 	FL_PER_EQ_UNIT = EQ_UNIT / sizeof(__be64),
1643d5fbda61SArjun Vynipadath 	TXD_PER_EQ_UNIT = EQ_UNIT / sizeof(__be64),
1644d5fbda61SArjun Vynipadath 
1645d5fbda61SArjun Vynipadath 	T4VF_ETHTXQ_MAX_HDR = (sizeof(struct fw_eth_tx_pkt_vm_wr) +
1646d5fbda61SArjun Vynipadath 			       sizeof(struct cpl_tx_pkt_lso_core) +
1647d5fbda61SArjun Vynipadath 			       sizeof(struct cpl_tx_pkt_core)) / sizeof(__be64),
1648d5fbda61SArjun Vynipadath };
1649d5fbda61SArjun Vynipadath 
1650d5fbda61SArjun Vynipadath /**
1651d5fbda61SArjun Vynipadath  *	t4vf_is_eth_imm - can an Ethernet packet be sent as immediate data?
1652d5fbda61SArjun Vynipadath  *	@skb: the packet
1653d5fbda61SArjun Vynipadath  *
1654d5fbda61SArjun Vynipadath  *	Returns whether an Ethernet packet is small enough to fit completely as
1655d5fbda61SArjun Vynipadath  *	immediate data.
1656d5fbda61SArjun Vynipadath  */
1657d5fbda61SArjun Vynipadath static inline int t4vf_is_eth_imm(const struct sk_buff *skb)
1658d5fbda61SArjun Vynipadath {
1659d5fbda61SArjun Vynipadath 	/* The VF Driver uses the FW_ETH_TX_PKT_VM_WR firmware Work Request
1660d5fbda61SArjun Vynipadath 	 * which does not accommodate immediate data.  We could dike out all
1661d5fbda61SArjun Vynipadath 	 * of the support code for immediate data but that would tie our hands
1662d5fbda61SArjun Vynipadath 	 * too much if we ever want to enhace the firmware.  It would also
1663d5fbda61SArjun Vynipadath 	 * create more differences between the PF and VF Drivers.
1664d5fbda61SArjun Vynipadath 	 */
1665d5fbda61SArjun Vynipadath 	return false;
1666d5fbda61SArjun Vynipadath }
1667d5fbda61SArjun Vynipadath 
1668d5fbda61SArjun Vynipadath /**
1669d5fbda61SArjun Vynipadath  *	t4vf_calc_tx_flits - calculate the number of flits for a packet TX WR
1670d5fbda61SArjun Vynipadath  *	@skb: the packet
1671d5fbda61SArjun Vynipadath  *
1672d5fbda61SArjun Vynipadath  *	Returns the number of flits needed for a TX Work Request for the
1673d5fbda61SArjun Vynipadath  *	given Ethernet packet, including the needed WR and CPL headers.
1674d5fbda61SArjun Vynipadath  */
1675d5fbda61SArjun Vynipadath static inline unsigned int t4vf_calc_tx_flits(const struct sk_buff *skb)
1676d5fbda61SArjun Vynipadath {
1677d5fbda61SArjun Vynipadath 	unsigned int flits;
1678d5fbda61SArjun Vynipadath 
1679d5fbda61SArjun Vynipadath 	/* If the skb is small enough, we can pump it out as a work request
1680d5fbda61SArjun Vynipadath 	 * with only immediate data.  In that case we just have to have the
1681d5fbda61SArjun Vynipadath 	 * TX Packet header plus the skb data in the Work Request.
1682d5fbda61SArjun Vynipadath 	 */
1683d5fbda61SArjun Vynipadath 	if (t4vf_is_eth_imm(skb))
1684d5fbda61SArjun Vynipadath 		return DIV_ROUND_UP(skb->len + sizeof(struct cpl_tx_pkt),
1685d5fbda61SArjun Vynipadath 				    sizeof(__be64));
1686d5fbda61SArjun Vynipadath 
1687d5fbda61SArjun Vynipadath 	/* Otherwise, we're going to have to construct a Scatter gather list
1688d5fbda61SArjun Vynipadath 	 * of the skb body and fragments.  We also include the flits necessary
1689d5fbda61SArjun Vynipadath 	 * for the TX Packet Work Request and CPL.  We always have a firmware
1690d5fbda61SArjun Vynipadath 	 * Write Header (incorporated as part of the cpl_tx_pkt_lso and
1691d5fbda61SArjun Vynipadath 	 * cpl_tx_pkt structures), followed by either a TX Packet Write CPL
1692d5fbda61SArjun Vynipadath 	 * message or, if we're doing a Large Send Offload, an LSO CPL message
1693d5fbda61SArjun Vynipadath 	 * with an embedded TX Packet Write CPL message.
1694d5fbda61SArjun Vynipadath 	 */
1695d5fbda61SArjun Vynipadath 	flits = sgl_len(skb_shinfo(skb)->nr_frags + 1);
1696d5fbda61SArjun Vynipadath 	if (skb_shinfo(skb)->gso_size)
1697d5fbda61SArjun Vynipadath 		flits += (sizeof(struct fw_eth_tx_pkt_vm_wr) +
1698d5fbda61SArjun Vynipadath 			  sizeof(struct cpl_tx_pkt_lso_core) +
1699d5fbda61SArjun Vynipadath 			  sizeof(struct cpl_tx_pkt_core)) / sizeof(__be64);
1700d5fbda61SArjun Vynipadath 	else
1701d5fbda61SArjun Vynipadath 		flits += (sizeof(struct fw_eth_tx_pkt_vm_wr) +
1702d5fbda61SArjun Vynipadath 			  sizeof(struct cpl_tx_pkt_core)) / sizeof(__be64);
1703d5fbda61SArjun Vynipadath 	return flits;
1704d5fbda61SArjun Vynipadath }
1705d5fbda61SArjun Vynipadath 
1706d5fbda61SArjun Vynipadath /**
1707d5fbda61SArjun Vynipadath  *	cxgb4_vf_eth_xmit - add a packet to an Ethernet TX queue
1708d5fbda61SArjun Vynipadath  *	@skb: the packet
1709d5fbda61SArjun Vynipadath  *	@dev: the egress net device
1710d5fbda61SArjun Vynipadath  *
1711d5fbda61SArjun Vynipadath  *	Add a packet to an SGE Ethernet TX queue.  Runs with softirqs disabled.
1712d5fbda61SArjun Vynipadath  */
1713d5fbda61SArjun Vynipadath static netdev_tx_t cxgb4_vf_eth_xmit(struct sk_buff *skb,
1714d5fbda61SArjun Vynipadath 				     struct net_device *dev)
1715d5fbda61SArjun Vynipadath {
17160ed96b46SRahul Lakkireddy 	unsigned int last_desc, flits, ndesc;
1717d5fbda61SArjun Vynipadath 	const struct skb_shared_info *ssi;
1718d5fbda61SArjun Vynipadath 	struct fw_eth_tx_pkt_vm_wr *wr;
17190ed96b46SRahul Lakkireddy 	struct tx_sw_desc *sgl_sdesc;
1720d5fbda61SArjun Vynipadath 	struct cpl_tx_pkt_core *cpl;
1721d5fbda61SArjun Vynipadath 	const struct port_info *pi;
1722d5fbda61SArjun Vynipadath 	struct sge_eth_txq *txq;
1723d5fbda61SArjun Vynipadath 	struct adapter *adapter;
1724b1396c2bSRahul Lakkireddy 	int qidx, credits, ret;
1725b1396c2bSRahul Lakkireddy 	size_t fw_hdr_copy_len;
1726d5fbda61SArjun Vynipadath 	u64 cntrl, *end;
1727d5fbda61SArjun Vynipadath 	u32 wr_mid;
1728d5fbda61SArjun Vynipadath 
1729d5fbda61SArjun Vynipadath 	/* The chip minimum packet length is 10 octets but the firmware
1730d5fbda61SArjun Vynipadath 	 * command that we are using requires that we copy the Ethernet header
1731d5fbda61SArjun Vynipadath 	 * (including the VLAN tag) into the header so we reject anything
1732d5fbda61SArjun Vynipadath 	 * smaller than that ...
1733d5fbda61SArjun Vynipadath 	 */
1734b1396c2bSRahul Lakkireddy 	fw_hdr_copy_len = sizeof(wr->ethmacdst) + sizeof(wr->ethmacsrc) +
1735b1396c2bSRahul Lakkireddy 			  sizeof(wr->ethtype) + sizeof(wr->vlantci);
1736b1396c2bSRahul Lakkireddy 	ret = cxgb4_validate_skb(skb, dev, fw_hdr_copy_len);
1737b1396c2bSRahul Lakkireddy 	if (ret)
1738d5fbda61SArjun Vynipadath 		goto out_free;
1739d5fbda61SArjun Vynipadath 
1740d5fbda61SArjun Vynipadath 	/* Figure out which TX Queue we're going to use. */
1741d5fbda61SArjun Vynipadath 	pi = netdev_priv(dev);
1742d5fbda61SArjun Vynipadath 	adapter = pi->adapter;
1743d5fbda61SArjun Vynipadath 	qidx = skb_get_queue_mapping(skb);
1744d5fbda61SArjun Vynipadath 	WARN_ON(qidx >= pi->nqsets);
1745d5fbda61SArjun Vynipadath 	txq = &adapter->sge.ethtxq[pi->first_qset + qidx];
1746d5fbda61SArjun Vynipadath 
1747d5fbda61SArjun Vynipadath 	/* Take this opportunity to reclaim any TX Descriptors whose DMA
1748d5fbda61SArjun Vynipadath 	 * transfers have completed.
1749d5fbda61SArjun Vynipadath 	 */
1750d429005fSVishal Kulkarni 	reclaim_completed_tx(adapter, &txq->q, -1, true);
1751d5fbda61SArjun Vynipadath 
1752d5fbda61SArjun Vynipadath 	/* Calculate the number of flits and TX Descriptors we're going to
1753d5fbda61SArjun Vynipadath 	 * need along with how many TX Descriptors will be left over after
1754d5fbda61SArjun Vynipadath 	 * we inject our Work Request.
1755d5fbda61SArjun Vynipadath 	 */
1756d5fbda61SArjun Vynipadath 	flits = t4vf_calc_tx_flits(skb);
1757d5fbda61SArjun Vynipadath 	ndesc = flits_to_desc(flits);
1758d5fbda61SArjun Vynipadath 	credits = txq_avail(&txq->q) - ndesc;
1759d5fbda61SArjun Vynipadath 
1760d5fbda61SArjun Vynipadath 	if (unlikely(credits < 0)) {
1761d5fbda61SArjun Vynipadath 		/* Not enough room for this packet's Work Request.  Stop the
1762d5fbda61SArjun Vynipadath 		 * TX Queue and return a "busy" condition.  The queue will get
1763d5fbda61SArjun Vynipadath 		 * started later on when the firmware informs us that space
1764d5fbda61SArjun Vynipadath 		 * has opened up.
1765d5fbda61SArjun Vynipadath 		 */
1766d5fbda61SArjun Vynipadath 		eth_txq_stop(txq);
1767d5fbda61SArjun Vynipadath 		dev_err(adapter->pdev_dev,
1768d5fbda61SArjun Vynipadath 			"%s: TX ring %u full while queue awake!\n",
1769d5fbda61SArjun Vynipadath 			dev->name, qidx);
1770d5fbda61SArjun Vynipadath 		return NETDEV_TX_BUSY;
1771d5fbda61SArjun Vynipadath 	}
1772d5fbda61SArjun Vynipadath 
17730ed96b46SRahul Lakkireddy 	last_desc = txq->q.pidx + ndesc - 1;
17740ed96b46SRahul Lakkireddy 	if (last_desc >= txq->q.size)
17750ed96b46SRahul Lakkireddy 		last_desc -= txq->q.size;
17760ed96b46SRahul Lakkireddy 	sgl_sdesc = &txq->q.sdesc[last_desc];
17770ed96b46SRahul Lakkireddy 
1778d5fbda61SArjun Vynipadath 	if (!t4vf_is_eth_imm(skb) &&
17790ed96b46SRahul Lakkireddy 	    unlikely(cxgb4_map_skb(adapter->pdev_dev, skb,
17800ed96b46SRahul Lakkireddy 				   sgl_sdesc->addr) < 0)) {
1781d5fbda61SArjun Vynipadath 		/* We need to map the skb into PCI DMA space (because it can't
1782d5fbda61SArjun Vynipadath 		 * be in-lined directly into the Work Request) and the mapping
1783d5fbda61SArjun Vynipadath 		 * operation failed.  Record the error and drop the packet.
1784d5fbda61SArjun Vynipadath 		 */
17850ed96b46SRahul Lakkireddy 		memset(sgl_sdesc->addr, 0, sizeof(sgl_sdesc->addr));
1786d5fbda61SArjun Vynipadath 		txq->mapping_err++;
1787d5fbda61SArjun Vynipadath 		goto out_free;
1788d5fbda61SArjun Vynipadath 	}
1789d5fbda61SArjun Vynipadath 
1790d5fbda61SArjun Vynipadath 	wr_mid = FW_WR_LEN16_V(DIV_ROUND_UP(flits, 2));
1791d5fbda61SArjun Vynipadath 	if (unlikely(credits < ETHTXQ_STOP_THRES)) {
1792d5fbda61SArjun Vynipadath 		/* After we're done injecting the Work Request for this
1793d5fbda61SArjun Vynipadath 		 * packet, we'll be below our "stop threshold" so stop the TX
1794d5fbda61SArjun Vynipadath 		 * Queue now and schedule a request for an SGE Egress Queue
1795d5fbda61SArjun Vynipadath 		 * Update message.  The queue will get started later on when
1796d5fbda61SArjun Vynipadath 		 * the firmware processes this Work Request and sends us an
1797d5fbda61SArjun Vynipadath 		 * Egress Queue Status Update message indicating that space
1798d5fbda61SArjun Vynipadath 		 * has opened up.
1799d5fbda61SArjun Vynipadath 		 */
1800d5fbda61SArjun Vynipadath 		eth_txq_stop(txq);
1801d5fbda61SArjun Vynipadath 		wr_mid |= FW_WR_EQUEQ_F | FW_WR_EQUIQ_F;
1802d5fbda61SArjun Vynipadath 	}
1803d5fbda61SArjun Vynipadath 
1804d5fbda61SArjun Vynipadath 	/* Start filling in our Work Request.  Note that we do _not_ handle
1805d5fbda61SArjun Vynipadath 	 * the WR Header wrapping around the TX Descriptor Ring.  If our
1806d5fbda61SArjun Vynipadath 	 * maximum header size ever exceeds one TX Descriptor, we'll need to
1807d5fbda61SArjun Vynipadath 	 * do something else here.
1808d5fbda61SArjun Vynipadath 	 */
1809d5fbda61SArjun Vynipadath 	WARN_ON(DIV_ROUND_UP(T4VF_ETHTXQ_MAX_HDR, TXD_PER_EQ_UNIT) > 1);
1810d5fbda61SArjun Vynipadath 	wr = (void *)&txq->q.desc[txq->q.pidx];
1811d5fbda61SArjun Vynipadath 	wr->equiq_to_len16 = cpu_to_be32(wr_mid);
1812d5fbda61SArjun Vynipadath 	wr->r3[0] = cpu_to_be32(0);
1813d5fbda61SArjun Vynipadath 	wr->r3[1] = cpu_to_be32(0);
1814d5fbda61SArjun Vynipadath 	skb_copy_from_linear_data(skb, (void *)wr->ethmacdst, fw_hdr_copy_len);
1815d5fbda61SArjun Vynipadath 	end = (u64 *)wr + flits;
1816d5fbda61SArjun Vynipadath 
1817d5fbda61SArjun Vynipadath 	/* If this is a Large Send Offload packet we'll put in an LSO CPL
1818d5fbda61SArjun Vynipadath 	 * message with an encapsulated TX Packet CPL message.  Otherwise we
1819d5fbda61SArjun Vynipadath 	 * just use a TX Packet CPL message.
1820d5fbda61SArjun Vynipadath 	 */
1821d5fbda61SArjun Vynipadath 	ssi = skb_shinfo(skb);
1822d5fbda61SArjun Vynipadath 	if (ssi->gso_size) {
1823d5fbda61SArjun Vynipadath 		struct cpl_tx_pkt_lso_core *lso = (void *)(wr + 1);
1824d5fbda61SArjun Vynipadath 		bool v6 = (ssi->gso_type & SKB_GSO_TCPV6) != 0;
1825d5fbda61SArjun Vynipadath 		int l3hdr_len = skb_network_header_len(skb);
1826d5fbda61SArjun Vynipadath 		int eth_xtra_len = skb_network_offset(skb) - ETH_HLEN;
1827d5fbda61SArjun Vynipadath 
1828d5fbda61SArjun Vynipadath 		wr->op_immdlen =
1829d5fbda61SArjun Vynipadath 			cpu_to_be32(FW_WR_OP_V(FW_ETH_TX_PKT_VM_WR) |
1830d5fbda61SArjun Vynipadath 				    FW_WR_IMMDLEN_V(sizeof(*lso) +
1831d5fbda61SArjun Vynipadath 						    sizeof(*cpl)));
1832d5fbda61SArjun Vynipadath 		 /* Fill in the LSO CPL message. */
1833d5fbda61SArjun Vynipadath 		lso->lso_ctrl =
1834d5fbda61SArjun Vynipadath 			cpu_to_be32(LSO_OPCODE_V(CPL_TX_PKT_LSO) |
1835d5fbda61SArjun Vynipadath 				    LSO_FIRST_SLICE_F |
1836d5fbda61SArjun Vynipadath 				    LSO_LAST_SLICE_F |
1837d5fbda61SArjun Vynipadath 				    LSO_IPV6_V(v6) |
1838d5fbda61SArjun Vynipadath 				    LSO_ETHHDR_LEN_V(eth_xtra_len / 4) |
1839d5fbda61SArjun Vynipadath 				    LSO_IPHDR_LEN_V(l3hdr_len / 4) |
1840d5fbda61SArjun Vynipadath 				    LSO_TCPHDR_LEN_V(tcp_hdr(skb)->doff));
1841d5fbda61SArjun Vynipadath 		lso->ipid_ofst = cpu_to_be16(0);
1842d5fbda61SArjun Vynipadath 		lso->mss = cpu_to_be16(ssi->gso_size);
1843d5fbda61SArjun Vynipadath 		lso->seqno_offset = cpu_to_be32(0);
1844d5fbda61SArjun Vynipadath 		if (is_t4(adapter->params.chip))
1845d5fbda61SArjun Vynipadath 			lso->len = cpu_to_be32(skb->len);
1846d5fbda61SArjun Vynipadath 		else
1847d5fbda61SArjun Vynipadath 			lso->len = cpu_to_be32(LSO_T5_XFER_SIZE_V(skb->len));
1848d5fbda61SArjun Vynipadath 
1849d5fbda61SArjun Vynipadath 		/* Set up TX Packet CPL pointer, control word and perform
1850d5fbda61SArjun Vynipadath 		 * accounting.
1851d5fbda61SArjun Vynipadath 		 */
1852d5fbda61SArjun Vynipadath 		cpl = (void *)(lso + 1);
1853d5fbda61SArjun Vynipadath 
1854d5fbda61SArjun Vynipadath 		if (CHELSIO_CHIP_VERSION(adapter->params.chip) <= CHELSIO_T5)
1855d5fbda61SArjun Vynipadath 			cntrl = TXPKT_ETHHDR_LEN_V(eth_xtra_len);
1856d5fbda61SArjun Vynipadath 		else
1857d5fbda61SArjun Vynipadath 			cntrl = T6_TXPKT_ETHHDR_LEN_V(eth_xtra_len);
1858d5fbda61SArjun Vynipadath 
1859d5fbda61SArjun Vynipadath 		cntrl |= TXPKT_CSUM_TYPE_V(v6 ?
1860d5fbda61SArjun Vynipadath 					   TX_CSUM_TCPIP6 : TX_CSUM_TCPIP) |
1861d5fbda61SArjun Vynipadath 			 TXPKT_IPHDR_LEN_V(l3hdr_len);
1862d5fbda61SArjun Vynipadath 		txq->tso++;
1863d5fbda61SArjun Vynipadath 		txq->tx_cso += ssi->gso_segs;
1864d5fbda61SArjun Vynipadath 	} else {
1865d5fbda61SArjun Vynipadath 		int len;
1866d5fbda61SArjun Vynipadath 
1867d5fbda61SArjun Vynipadath 		len = (t4vf_is_eth_imm(skb)
1868d5fbda61SArjun Vynipadath 		       ? skb->len + sizeof(*cpl)
1869d5fbda61SArjun Vynipadath 		       : sizeof(*cpl));
1870d5fbda61SArjun Vynipadath 		wr->op_immdlen =
1871d5fbda61SArjun Vynipadath 			cpu_to_be32(FW_WR_OP_V(FW_ETH_TX_PKT_VM_WR) |
1872d5fbda61SArjun Vynipadath 				    FW_WR_IMMDLEN_V(len));
1873d5fbda61SArjun Vynipadath 
1874d5fbda61SArjun Vynipadath 		/* Set up TX Packet CPL pointer, control word and perform
1875d5fbda61SArjun Vynipadath 		 * accounting.
1876d5fbda61SArjun Vynipadath 		 */
1877d5fbda61SArjun Vynipadath 		cpl = (void *)(wr + 1);
1878d5fbda61SArjun Vynipadath 		if (skb->ip_summed == CHECKSUM_PARTIAL) {
1879d5fbda61SArjun Vynipadath 			cntrl = hwcsum(adapter->params.chip, skb) |
1880d5fbda61SArjun Vynipadath 				TXPKT_IPCSUM_DIS_F;
1881d5fbda61SArjun Vynipadath 			txq->tx_cso++;
1882d5fbda61SArjun Vynipadath 		} else {
1883d5fbda61SArjun Vynipadath 			cntrl = TXPKT_L4CSUM_DIS_F | TXPKT_IPCSUM_DIS_F;
1884d5fbda61SArjun Vynipadath 		}
1885d5fbda61SArjun Vynipadath 	}
1886d5fbda61SArjun Vynipadath 
1887d5fbda61SArjun Vynipadath 	/* If there's a VLAN tag present, add that to the list of things to
1888d5fbda61SArjun Vynipadath 	 * do in this Work Request.
1889d5fbda61SArjun Vynipadath 	 */
1890d5fbda61SArjun Vynipadath 	if (skb_vlan_tag_present(skb)) {
1891d5fbda61SArjun Vynipadath 		txq->vlan_ins++;
1892d5fbda61SArjun Vynipadath 		cntrl |= TXPKT_VLAN_VLD_F | TXPKT_VLAN_V(skb_vlan_tag_get(skb));
1893d5fbda61SArjun Vynipadath 	}
1894d5fbda61SArjun Vynipadath 
1895d5fbda61SArjun Vynipadath 	 /* Fill in the TX Packet CPL message header. */
1896d5fbda61SArjun Vynipadath 	cpl->ctrl0 = cpu_to_be32(TXPKT_OPCODE_V(CPL_TX_PKT_XT) |
1897d5fbda61SArjun Vynipadath 				 TXPKT_INTF_V(pi->port_id) |
1898d5fbda61SArjun Vynipadath 				 TXPKT_PF_V(0));
1899d5fbda61SArjun Vynipadath 	cpl->pack = cpu_to_be16(0);
1900d5fbda61SArjun Vynipadath 	cpl->len = cpu_to_be16(skb->len);
1901d5fbda61SArjun Vynipadath 	cpl->ctrl1 = cpu_to_be64(cntrl);
1902d5fbda61SArjun Vynipadath 
1903d5fbda61SArjun Vynipadath 	/* Fill in the body of the TX Packet CPL message with either in-lined
1904d5fbda61SArjun Vynipadath 	 * data or a Scatter/Gather List.
1905d5fbda61SArjun Vynipadath 	 */
1906d5fbda61SArjun Vynipadath 	if (t4vf_is_eth_imm(skb)) {
1907d5fbda61SArjun Vynipadath 		/* In-line the packet's data and free the skb since we don't
1908d5fbda61SArjun Vynipadath 		 * need it any longer.
1909d5fbda61SArjun Vynipadath 		 */
1910d5fbda61SArjun Vynipadath 		cxgb4_inline_tx_skb(skb, &txq->q, cpl + 1);
1911d5fbda61SArjun Vynipadath 		dev_consume_skb_any(skb);
1912d5fbda61SArjun Vynipadath 	} else {
1913d5fbda61SArjun Vynipadath 		/* Write the skb's Scatter/Gather list into the TX Packet CPL
1914d5fbda61SArjun Vynipadath 		 * message and retain a pointer to the skb so we can free it
1915d5fbda61SArjun Vynipadath 		 * later when its DMA completes.  (We store the skb pointer
1916d5fbda61SArjun Vynipadath 		 * in the Software Descriptor corresponding to the last TX
1917d5fbda61SArjun Vynipadath 		 * Descriptor used by the Work Request.)
1918d5fbda61SArjun Vynipadath 		 *
1919d5fbda61SArjun Vynipadath 		 * The retained skb will be freed when the corresponding TX
1920d5fbda61SArjun Vynipadath 		 * Descriptors are reclaimed after their DMAs complete.
1921d5fbda61SArjun Vynipadath 		 * However, this could take quite a while since, in general,
1922d5fbda61SArjun Vynipadath 		 * the hardware is set up to be lazy about sending DMA
1923d5fbda61SArjun Vynipadath 		 * completion notifications to us and we mostly perform TX
1924d5fbda61SArjun Vynipadath 		 * reclaims in the transmit routine.
1925d5fbda61SArjun Vynipadath 		 *
1926d5fbda61SArjun Vynipadath 		 * This is good for performamce but means that we rely on new
1927d5fbda61SArjun Vynipadath 		 * TX packets arriving to run the destructors of completed
1928d5fbda61SArjun Vynipadath 		 * packets, which open up space in their sockets' send queues.
1929d5fbda61SArjun Vynipadath 		 * Sometimes we do not get such new packets causing TX to
1930d5fbda61SArjun Vynipadath 		 * stall.  A single UDP transmitter is a good example of this
1931d5fbda61SArjun Vynipadath 		 * situation.  We have a clean up timer that periodically
1932d5fbda61SArjun Vynipadath 		 * reclaims completed packets but it doesn't run often enough
1933d5fbda61SArjun Vynipadath 		 * (nor do we want it to) to prevent lengthy stalls.  A
1934d5fbda61SArjun Vynipadath 		 * solution to this problem is to run the destructor early,
1935d5fbda61SArjun Vynipadath 		 * after the packet is queued but before it's DMAd.  A con is
1936d5fbda61SArjun Vynipadath 		 * that we lie to socket memory accounting, but the amount of
1937d5fbda61SArjun Vynipadath 		 * extra memory is reasonable (limited by the number of TX
1938d5fbda61SArjun Vynipadath 		 * descriptors), the packets do actually get freed quickly by
1939d5fbda61SArjun Vynipadath 		 * new packets almost always, and for protocols like TCP that
1940d5fbda61SArjun Vynipadath 		 * wait for acks to really free up the data the extra memory
1941d5fbda61SArjun Vynipadath 		 * is even less.  On the positive side we run the destructors
1942d5fbda61SArjun Vynipadath 		 * on the sending CPU rather than on a potentially different
1943d5fbda61SArjun Vynipadath 		 * completing CPU, usually a good thing.
1944d5fbda61SArjun Vynipadath 		 *
1945d5fbda61SArjun Vynipadath 		 * Run the destructor before telling the DMA engine about the
1946d5fbda61SArjun Vynipadath 		 * packet to make sure it doesn't complete and get freed
1947d5fbda61SArjun Vynipadath 		 * prematurely.
1948d5fbda61SArjun Vynipadath 		 */
1949d5fbda61SArjun Vynipadath 		struct ulptx_sgl *sgl = (struct ulptx_sgl *)(cpl + 1);
1950d5fbda61SArjun Vynipadath 		struct sge_txq *tq = &txq->q;
1951d5fbda61SArjun Vynipadath 
1952d5fbda61SArjun Vynipadath 		/* If the Work Request header was an exact multiple of our TX
1953d5fbda61SArjun Vynipadath 		 * Descriptor length, then it's possible that the starting SGL
1954d5fbda61SArjun Vynipadath 		 * pointer lines up exactly with the end of our TX Descriptor
1955d5fbda61SArjun Vynipadath 		 * ring.  If that's the case, wrap around to the beginning
1956d5fbda61SArjun Vynipadath 		 * here ...
1957d5fbda61SArjun Vynipadath 		 */
1958d5fbda61SArjun Vynipadath 		if (unlikely((void *)sgl == (void *)tq->stat)) {
1959d5fbda61SArjun Vynipadath 			sgl = (void *)tq->desc;
1960d5fbda61SArjun Vynipadath 			end = (void *)((void *)tq->desc +
1961d5fbda61SArjun Vynipadath 				       ((void *)end - (void *)tq->stat));
1962d5fbda61SArjun Vynipadath 		}
1963d5fbda61SArjun Vynipadath 
19640ed96b46SRahul Lakkireddy 		cxgb4_write_sgl(skb, tq, sgl, end, 0, sgl_sdesc->addr);
1965d5fbda61SArjun Vynipadath 		skb_orphan(skb);
19660ed96b46SRahul Lakkireddy 		sgl_sdesc->skb = skb;
1967d5fbda61SArjun Vynipadath 	}
1968d5fbda61SArjun Vynipadath 
1969d5fbda61SArjun Vynipadath 	/* Advance our internal TX Queue state, tell the hardware about
1970d5fbda61SArjun Vynipadath 	 * the new TX descriptors and return success.
1971d5fbda61SArjun Vynipadath 	 */
1972d5fbda61SArjun Vynipadath 	txq_advance(&txq->q, ndesc);
1973d5fbda61SArjun Vynipadath 
1974d5fbda61SArjun Vynipadath 	cxgb4_ring_tx_db(adapter, &txq->q, ndesc);
1975d5fbda61SArjun Vynipadath 	return NETDEV_TX_OK;
1976d5fbda61SArjun Vynipadath 
1977d5fbda61SArjun Vynipadath out_free:
1978d5fbda61SArjun Vynipadath 	/* An error of some sort happened.  Free the TX skb and tell the
1979d5fbda61SArjun Vynipadath 	 * OS that we've "dealt" with the packet ...
1980d5fbda61SArjun Vynipadath 	 */
1981d5fbda61SArjun Vynipadath 	dev_kfree_skb_any(skb);
1982d5fbda61SArjun Vynipadath 	return NETDEV_TX_OK;
1983d5fbda61SArjun Vynipadath }
1984d5fbda61SArjun Vynipadath 
19854846d533SRahul Lakkireddy /**
19864846d533SRahul Lakkireddy  * reclaim_completed_tx_imm - reclaim completed control-queue Tx descs
19874846d533SRahul Lakkireddy  * @q: the SGE control Tx queue
19884846d533SRahul Lakkireddy  *
19894846d533SRahul Lakkireddy  * This is a variant of cxgb4_reclaim_completed_tx() that is used
19904846d533SRahul Lakkireddy  * for Tx queues that send only immediate data (presently just
19914846d533SRahul Lakkireddy  * the control queues) and	thus do not have any sk_buffs to release.
19924846d533SRahul Lakkireddy  */
19934846d533SRahul Lakkireddy static inline void reclaim_completed_tx_imm(struct sge_txq *q)
19944846d533SRahul Lakkireddy {
19954846d533SRahul Lakkireddy 	int hw_cidx = ntohs(READ_ONCE(q->stat->cidx));
19964846d533SRahul Lakkireddy 	int reclaim = hw_cidx - q->cidx;
19974846d533SRahul Lakkireddy 
19984846d533SRahul Lakkireddy 	if (reclaim < 0)
19994846d533SRahul Lakkireddy 		reclaim += q->size;
20004846d533SRahul Lakkireddy 
20014846d533SRahul Lakkireddy 	q->in_use -= reclaim;
20024846d533SRahul Lakkireddy 	q->cidx = hw_cidx;
20034846d533SRahul Lakkireddy }
20044846d533SRahul Lakkireddy 
2005b1396c2bSRahul Lakkireddy static inline void eosw_txq_advance_index(u32 *idx, u32 n, u32 max)
2006b1396c2bSRahul Lakkireddy {
2007b1396c2bSRahul Lakkireddy 	u32 val = *idx + n;
2008b1396c2bSRahul Lakkireddy 
2009b1396c2bSRahul Lakkireddy 	if (val >= max)
2010b1396c2bSRahul Lakkireddy 		val -= max;
2011b1396c2bSRahul Lakkireddy 
2012b1396c2bSRahul Lakkireddy 	*idx = val;
2013b1396c2bSRahul Lakkireddy }
2014b1396c2bSRahul Lakkireddy 
2015b1396c2bSRahul Lakkireddy void cxgb4_eosw_txq_free_desc(struct adapter *adap,
2016b1396c2bSRahul Lakkireddy 			      struct sge_eosw_txq *eosw_txq, u32 ndesc)
2017b1396c2bSRahul Lakkireddy {
20180ed96b46SRahul Lakkireddy 	struct tx_sw_desc *d;
2019b1396c2bSRahul Lakkireddy 
2020b1396c2bSRahul Lakkireddy 	d = &eosw_txq->desc[eosw_txq->last_cidx];
2021b1396c2bSRahul Lakkireddy 	while (ndesc--) {
2022b1396c2bSRahul Lakkireddy 		if (d->skb) {
2023b1396c2bSRahul Lakkireddy 			if (d->addr[0]) {
2024b1396c2bSRahul Lakkireddy 				unmap_skb(adap->pdev_dev, d->skb, d->addr);
2025b1396c2bSRahul Lakkireddy 				memset(d->addr, 0, sizeof(d->addr));
2026b1396c2bSRahul Lakkireddy 			}
2027b1396c2bSRahul Lakkireddy 			dev_consume_skb_any(d->skb);
2028b1396c2bSRahul Lakkireddy 			d->skb = NULL;
2029b1396c2bSRahul Lakkireddy 		}
2030b1396c2bSRahul Lakkireddy 		eosw_txq_advance_index(&eosw_txq->last_cidx, 1,
2031b1396c2bSRahul Lakkireddy 				       eosw_txq->ndesc);
2032b1396c2bSRahul Lakkireddy 		d = &eosw_txq->desc[eosw_txq->last_cidx];
2033b1396c2bSRahul Lakkireddy 	}
2034b1396c2bSRahul Lakkireddy }
2035b1396c2bSRahul Lakkireddy 
20364846d533SRahul Lakkireddy static inline void eosw_txq_advance(struct sge_eosw_txq *eosw_txq, u32 n)
20374846d533SRahul Lakkireddy {
20384846d533SRahul Lakkireddy 	eosw_txq_advance_index(&eosw_txq->pidx, n, eosw_txq->ndesc);
20394846d533SRahul Lakkireddy 	eosw_txq->inuse += n;
20404846d533SRahul Lakkireddy }
20414846d533SRahul Lakkireddy 
20424846d533SRahul Lakkireddy static inline int eosw_txq_enqueue(struct sge_eosw_txq *eosw_txq,
20434846d533SRahul Lakkireddy 				   struct sk_buff *skb)
20444846d533SRahul Lakkireddy {
20454846d533SRahul Lakkireddy 	if (eosw_txq->inuse == eosw_txq->ndesc)
20464846d533SRahul Lakkireddy 		return -ENOMEM;
20474846d533SRahul Lakkireddy 
20484846d533SRahul Lakkireddy 	eosw_txq->desc[eosw_txq->pidx].skb = skb;
20494846d533SRahul Lakkireddy 	return 0;
20504846d533SRahul Lakkireddy }
20514846d533SRahul Lakkireddy 
20524846d533SRahul Lakkireddy static inline struct sk_buff *eosw_txq_peek(struct sge_eosw_txq *eosw_txq)
20534846d533SRahul Lakkireddy {
20544846d533SRahul Lakkireddy 	return eosw_txq->desc[eosw_txq->last_pidx].skb;
20554846d533SRahul Lakkireddy }
20564846d533SRahul Lakkireddy 
20574846d533SRahul Lakkireddy static inline u8 ethofld_calc_tx_flits(struct adapter *adap,
20584846d533SRahul Lakkireddy 				       struct sk_buff *skb, u32 hdr_len)
20594846d533SRahul Lakkireddy {
20604846d533SRahul Lakkireddy 	u8 flits, nsgl = 0;
20614846d533SRahul Lakkireddy 	u32 wrlen;
20624846d533SRahul Lakkireddy 
20634846d533SRahul Lakkireddy 	wrlen = sizeof(struct fw_eth_tx_eo_wr) + sizeof(struct cpl_tx_pkt_core);
20641a2a14fbSRahul Lakkireddy 	if (skb_shinfo(skb)->gso_size &&
20651a2a14fbSRahul Lakkireddy 	    !(skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4))
20664846d533SRahul Lakkireddy 		wrlen += sizeof(struct cpl_tx_pkt_lso_core);
20674846d533SRahul Lakkireddy 
20684846d533SRahul Lakkireddy 	wrlen += roundup(hdr_len, 16);
20694846d533SRahul Lakkireddy 
20704846d533SRahul Lakkireddy 	/* Packet headers + WR + CPLs */
20714846d533SRahul Lakkireddy 	flits = DIV_ROUND_UP(wrlen, 8);
20724846d533SRahul Lakkireddy 
20731a2a14fbSRahul Lakkireddy 	if (skb_shinfo(skb)->nr_frags > 0) {
20741a2a14fbSRahul Lakkireddy 		if (skb_headlen(skb) - hdr_len)
20751a2a14fbSRahul Lakkireddy 			nsgl = sgl_len(skb_shinfo(skb)->nr_frags + 1);
20761a2a14fbSRahul Lakkireddy 		else
20774846d533SRahul Lakkireddy 			nsgl = sgl_len(skb_shinfo(skb)->nr_frags);
20781a2a14fbSRahul Lakkireddy 	} else if (skb->len - hdr_len) {
20794846d533SRahul Lakkireddy 		nsgl = sgl_len(1);
20801a2a14fbSRahul Lakkireddy 	}
20814846d533SRahul Lakkireddy 
20824846d533SRahul Lakkireddy 	return flits + nsgl;
20834846d533SRahul Lakkireddy }
20844846d533SRahul Lakkireddy 
20854f1d9726SRahul Lakkireddy static void *write_eo_wr(struct adapter *adap, struct sge_eosw_txq *eosw_txq,
20864846d533SRahul Lakkireddy 			 struct sk_buff *skb, struct fw_eth_tx_eo_wr *wr,
20874846d533SRahul Lakkireddy 			 u32 hdr_len, u32 wrlen)
20884846d533SRahul Lakkireddy {
20894846d533SRahul Lakkireddy 	const struct skb_shared_info *ssi = skb_shinfo(skb);
20904846d533SRahul Lakkireddy 	struct cpl_tx_pkt_core *cpl;
20914846d533SRahul Lakkireddy 	u32 immd_len, wrlen16;
20924846d533SRahul Lakkireddy 	bool compl = false;
20931a2a14fbSRahul Lakkireddy 	u8 ver, proto;
20941a2a14fbSRahul Lakkireddy 
20951a2a14fbSRahul Lakkireddy 	ver = ip_hdr(skb)->version;
20961a2a14fbSRahul Lakkireddy 	proto = (ver == 6) ? ipv6_hdr(skb)->nexthdr : ip_hdr(skb)->protocol;
20974846d533SRahul Lakkireddy 
20984846d533SRahul Lakkireddy 	wrlen16 = DIV_ROUND_UP(wrlen, 16);
20994846d533SRahul Lakkireddy 	immd_len = sizeof(struct cpl_tx_pkt_core);
21001a2a14fbSRahul Lakkireddy 	if (skb_shinfo(skb)->gso_size &&
21011a2a14fbSRahul Lakkireddy 	    !(skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4))
21024846d533SRahul Lakkireddy 		immd_len += sizeof(struct cpl_tx_pkt_lso_core);
21034846d533SRahul Lakkireddy 	immd_len += hdr_len;
21044846d533SRahul Lakkireddy 
21054846d533SRahul Lakkireddy 	if (!eosw_txq->ncompl ||
21064f1d9726SRahul Lakkireddy 	    (eosw_txq->last_compl + wrlen16) >=
21074f1d9726SRahul Lakkireddy 	    (adap->params.ofldq_wr_cred / 2)) {
21084846d533SRahul Lakkireddy 		compl = true;
21094846d533SRahul Lakkireddy 		eosw_txq->ncompl++;
21104846d533SRahul Lakkireddy 		eosw_txq->last_compl = 0;
21114846d533SRahul Lakkireddy 	}
21124846d533SRahul Lakkireddy 
21134846d533SRahul Lakkireddy 	wr->op_immdlen = cpu_to_be32(FW_WR_OP_V(FW_ETH_TX_EO_WR) |
21144846d533SRahul Lakkireddy 				     FW_ETH_TX_EO_WR_IMMDLEN_V(immd_len) |
21154846d533SRahul Lakkireddy 				     FW_WR_COMPL_V(compl));
21164846d533SRahul Lakkireddy 	wr->equiq_to_len16 = cpu_to_be32(FW_WR_LEN16_V(wrlen16) |
21174846d533SRahul Lakkireddy 					 FW_WR_FLOWID_V(eosw_txq->hwtid));
21184846d533SRahul Lakkireddy 	wr->r3 = 0;
21191a2a14fbSRahul Lakkireddy 	if (proto == IPPROTO_UDP) {
21201a2a14fbSRahul Lakkireddy 		cpl = write_eo_udp_wr(skb, wr, hdr_len);
21211a2a14fbSRahul Lakkireddy 	} else {
21224846d533SRahul Lakkireddy 		wr->u.tcpseg.type = FW_ETH_TX_EO_TYPE_TCPSEG;
21234846d533SRahul Lakkireddy 		wr->u.tcpseg.ethlen = skb_network_offset(skb);
21244846d533SRahul Lakkireddy 		wr->u.tcpseg.iplen = cpu_to_be16(skb_network_header_len(skb));
21254846d533SRahul Lakkireddy 		wr->u.tcpseg.tcplen = tcp_hdrlen(skb);
21264846d533SRahul Lakkireddy 		wr->u.tcpseg.tsclk_tsoff = 0;
21274846d533SRahul Lakkireddy 		wr->u.tcpseg.r4 = 0;
21284846d533SRahul Lakkireddy 		wr->u.tcpseg.r5 = 0;
21294846d533SRahul Lakkireddy 		wr->u.tcpseg.plen = cpu_to_be32(skb->len - hdr_len);
21304846d533SRahul Lakkireddy 
21314846d533SRahul Lakkireddy 		if (ssi->gso_size) {
21324846d533SRahul Lakkireddy 			struct cpl_tx_pkt_lso_core *lso = (void *)(wr + 1);
21334846d533SRahul Lakkireddy 
21344846d533SRahul Lakkireddy 			wr->u.tcpseg.mss = cpu_to_be16(ssi->gso_size);
21354846d533SRahul Lakkireddy 			cpl = write_tso_wr(adap, skb, lso);
21364846d533SRahul Lakkireddy 		} else {
21374846d533SRahul Lakkireddy 			wr->u.tcpseg.mss = cpu_to_be16(0xffff);
21384846d533SRahul Lakkireddy 			cpl = (void *)(wr + 1);
21394846d533SRahul Lakkireddy 		}
21401a2a14fbSRahul Lakkireddy 	}
21414846d533SRahul Lakkireddy 
21424846d533SRahul Lakkireddy 	eosw_txq->cred -= wrlen16;
21434846d533SRahul Lakkireddy 	eosw_txq->last_compl += wrlen16;
21444846d533SRahul Lakkireddy 	return cpl;
21454846d533SRahul Lakkireddy }
21464846d533SRahul Lakkireddy 
21474f1d9726SRahul Lakkireddy static int ethofld_hard_xmit(struct net_device *dev,
21484846d533SRahul Lakkireddy 			     struct sge_eosw_txq *eosw_txq)
21494846d533SRahul Lakkireddy {
21504846d533SRahul Lakkireddy 	struct port_info *pi = netdev2pinfo(dev);
21514846d533SRahul Lakkireddy 	struct adapter *adap = netdev2adap(dev);
21524846d533SRahul Lakkireddy 	u32 wrlen, wrlen16, hdr_len, data_len;
21530e395b3cSRahul Lakkireddy 	enum sge_eosw_state next_state;
21544846d533SRahul Lakkireddy 	u64 cntrl, *start, *end, *sgl;
21554846d533SRahul Lakkireddy 	struct sge_eohw_txq *eohw_txq;
21564846d533SRahul Lakkireddy 	struct cpl_tx_pkt_core *cpl;
21574846d533SRahul Lakkireddy 	struct fw_eth_tx_eo_wr *wr;
21580e395b3cSRahul Lakkireddy 	bool skip_eotx_wr = false;
21590ed96b46SRahul Lakkireddy 	struct tx_sw_desc *d;
21604846d533SRahul Lakkireddy 	struct sk_buff *skb;
21614f1d9726SRahul Lakkireddy 	int left, ret = 0;
21624846d533SRahul Lakkireddy 	u8 flits, ndesc;
21634846d533SRahul Lakkireddy 
21644846d533SRahul Lakkireddy 	eohw_txq = &adap->sge.eohw_txq[eosw_txq->hwqid];
21654846d533SRahul Lakkireddy 	spin_lock(&eohw_txq->lock);
21664846d533SRahul Lakkireddy 	reclaim_completed_tx_imm(&eohw_txq->q);
21674846d533SRahul Lakkireddy 
21684846d533SRahul Lakkireddy 	d = &eosw_txq->desc[eosw_txq->last_pidx];
21694846d533SRahul Lakkireddy 	skb = d->skb;
21704846d533SRahul Lakkireddy 	skb_tx_timestamp(skb);
21714846d533SRahul Lakkireddy 
21724846d533SRahul Lakkireddy 	wr = (struct fw_eth_tx_eo_wr *)&eohw_txq->q.desc[eohw_txq->q.pidx];
21730e395b3cSRahul Lakkireddy 	if (unlikely(eosw_txq->state != CXGB4_EO_STATE_ACTIVE &&
21740e395b3cSRahul Lakkireddy 		     eosw_txq->last_pidx == eosw_txq->flowc_idx)) {
21750e395b3cSRahul Lakkireddy 		hdr_len = skb->len;
21760e395b3cSRahul Lakkireddy 		data_len = 0;
21770e395b3cSRahul Lakkireddy 		flits = DIV_ROUND_UP(hdr_len, 8);
21780e395b3cSRahul Lakkireddy 		if (eosw_txq->state == CXGB4_EO_STATE_FLOWC_OPEN_SEND)
21790e395b3cSRahul Lakkireddy 			next_state = CXGB4_EO_STATE_FLOWC_OPEN_REPLY;
21800e395b3cSRahul Lakkireddy 		else
21810e395b3cSRahul Lakkireddy 			next_state = CXGB4_EO_STATE_FLOWC_CLOSE_REPLY;
21820e395b3cSRahul Lakkireddy 		skip_eotx_wr = true;
21830e395b3cSRahul Lakkireddy 	} else {
21844846d533SRahul Lakkireddy 		hdr_len = eth_get_headlen(dev, skb->data, skb_headlen(skb));
21854846d533SRahul Lakkireddy 		data_len = skb->len - hdr_len;
21864846d533SRahul Lakkireddy 		flits = ethofld_calc_tx_flits(adap, skb, hdr_len);
21870e395b3cSRahul Lakkireddy 	}
21884846d533SRahul Lakkireddy 	ndesc = flits_to_desc(flits);
21894846d533SRahul Lakkireddy 	wrlen = flits * 8;
21904846d533SRahul Lakkireddy 	wrlen16 = DIV_ROUND_UP(wrlen, 16);
21914846d533SRahul Lakkireddy 
21924f1d9726SRahul Lakkireddy 	left = txq_avail(&eohw_txq->q) - ndesc;
21934f1d9726SRahul Lakkireddy 
21944f1d9726SRahul Lakkireddy 	/* If there are no descriptors left in hardware queues or no
21954f1d9726SRahul Lakkireddy 	 * CPL credits left in software queues, then wait for them
21964f1d9726SRahul Lakkireddy 	 * to come back and retry again. Note that we always request
21974f1d9726SRahul Lakkireddy 	 * for credits update via interrupt for every half credits
21984f1d9726SRahul Lakkireddy 	 * consumed. So, the interrupt will eventually restore the
21994f1d9726SRahul Lakkireddy 	 * credits and invoke the Tx path again.
22004846d533SRahul Lakkireddy 	 */
22014f1d9726SRahul Lakkireddy 	if (unlikely(left < 0 || wrlen16 > eosw_txq->cred)) {
22024f1d9726SRahul Lakkireddy 		ret = -ENOMEM;
22034846d533SRahul Lakkireddy 		goto out_unlock;
22044f1d9726SRahul Lakkireddy 	}
22054846d533SRahul Lakkireddy 
22060e395b3cSRahul Lakkireddy 	if (unlikely(skip_eotx_wr)) {
22070e395b3cSRahul Lakkireddy 		start = (u64 *)wr;
22080e395b3cSRahul Lakkireddy 		eosw_txq->state = next_state;
220969422a7eSRahul Lakkireddy 		eosw_txq->cred -= wrlen16;
221069422a7eSRahul Lakkireddy 		eosw_txq->ncompl++;
221169422a7eSRahul Lakkireddy 		eosw_txq->last_compl = 0;
22120e395b3cSRahul Lakkireddy 		goto write_wr_headers;
22130e395b3cSRahul Lakkireddy 	}
22140e395b3cSRahul Lakkireddy 
22154846d533SRahul Lakkireddy 	cpl = write_eo_wr(adap, eosw_txq, skb, wr, hdr_len, wrlen);
22164846d533SRahul Lakkireddy 	cntrl = hwcsum(adap->params.chip, skb);
22174846d533SRahul Lakkireddy 	if (skb_vlan_tag_present(skb))
22184846d533SRahul Lakkireddy 		cntrl |= TXPKT_VLAN_VLD_F | TXPKT_VLAN_V(skb_vlan_tag_get(skb));
22194846d533SRahul Lakkireddy 
22204846d533SRahul Lakkireddy 	cpl->ctrl0 = cpu_to_be32(TXPKT_OPCODE_V(CPL_TX_PKT_XT) |
22214846d533SRahul Lakkireddy 				 TXPKT_INTF_V(pi->tx_chan) |
22224846d533SRahul Lakkireddy 				 TXPKT_PF_V(adap->pf));
22234846d533SRahul Lakkireddy 	cpl->pack = 0;
22244846d533SRahul Lakkireddy 	cpl->len = cpu_to_be16(skb->len);
22254846d533SRahul Lakkireddy 	cpl->ctrl1 = cpu_to_be64(cntrl);
22264846d533SRahul Lakkireddy 
22274846d533SRahul Lakkireddy 	start = (u64 *)(cpl + 1);
22284846d533SRahul Lakkireddy 
22290e395b3cSRahul Lakkireddy write_wr_headers:
22304846d533SRahul Lakkireddy 	sgl = (u64 *)inline_tx_skb_header(skb, &eohw_txq->q, (void *)start,
22314846d533SRahul Lakkireddy 					  hdr_len);
22324846d533SRahul Lakkireddy 	if (data_len) {
22334f1d9726SRahul Lakkireddy 		ret = cxgb4_map_skb(adap->pdev_dev, skb, d->addr);
22344f1d9726SRahul Lakkireddy 		if (unlikely(ret)) {
22354846d533SRahul Lakkireddy 			memset(d->addr, 0, sizeof(d->addr));
22364846d533SRahul Lakkireddy 			eohw_txq->mapping_err++;
22374846d533SRahul Lakkireddy 			goto out_unlock;
22384846d533SRahul Lakkireddy 		}
22394846d533SRahul Lakkireddy 
22404846d533SRahul Lakkireddy 		end = (u64 *)wr + flits;
22414846d533SRahul Lakkireddy 		if (unlikely(start > sgl)) {
22424846d533SRahul Lakkireddy 			left = (u8 *)end - (u8 *)eohw_txq->q.stat;
22434846d533SRahul Lakkireddy 			end = (void *)eohw_txq->q.desc + left;
22444846d533SRahul Lakkireddy 		}
22454846d533SRahul Lakkireddy 
22464846d533SRahul Lakkireddy 		if (unlikely((u8 *)sgl >= (u8 *)eohw_txq->q.stat)) {
22474846d533SRahul Lakkireddy 			/* If current position is already at the end of the
22484846d533SRahul Lakkireddy 			 * txq, reset the current to point to start of the queue
22494846d533SRahul Lakkireddy 			 * and update the end ptr as well.
22504846d533SRahul Lakkireddy 			 */
22514846d533SRahul Lakkireddy 			left = (u8 *)end - (u8 *)eohw_txq->q.stat;
22524846d533SRahul Lakkireddy 
22534846d533SRahul Lakkireddy 			end = (void *)eohw_txq->q.desc + left;
22544846d533SRahul Lakkireddy 			sgl = (void *)eohw_txq->q.desc;
22554846d533SRahul Lakkireddy 		}
22564846d533SRahul Lakkireddy 
22574846d533SRahul Lakkireddy 		cxgb4_write_sgl(skb, &eohw_txq->q, (void *)sgl, end, hdr_len,
22584846d533SRahul Lakkireddy 				d->addr);
22594846d533SRahul Lakkireddy 	}
22604846d533SRahul Lakkireddy 
22618311f0beSRahul Lakkireddy 	if (skb_shinfo(skb)->gso_size) {
22628311f0beSRahul Lakkireddy 		if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4)
22638311f0beSRahul Lakkireddy 			eohw_txq->uso++;
22648311f0beSRahul Lakkireddy 		else
22658311f0beSRahul Lakkireddy 			eohw_txq->tso++;
22668311f0beSRahul Lakkireddy 		eohw_txq->tx_cso += skb_shinfo(skb)->gso_segs;
22678311f0beSRahul Lakkireddy 	} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
22688311f0beSRahul Lakkireddy 		eohw_txq->tx_cso++;
22698311f0beSRahul Lakkireddy 	}
22708311f0beSRahul Lakkireddy 
22718311f0beSRahul Lakkireddy 	if (skb_vlan_tag_present(skb))
22728311f0beSRahul Lakkireddy 		eohw_txq->vlan_ins++;
22738311f0beSRahul Lakkireddy 
22744846d533SRahul Lakkireddy 	txq_advance(&eohw_txq->q, ndesc);
22754846d533SRahul Lakkireddy 	cxgb4_ring_tx_db(adap, &eohw_txq->q, ndesc);
22764846d533SRahul Lakkireddy 	eosw_txq_advance_index(&eosw_txq->last_pidx, 1, eosw_txq->ndesc);
22774846d533SRahul Lakkireddy 
22784846d533SRahul Lakkireddy out_unlock:
22794846d533SRahul Lakkireddy 	spin_unlock(&eohw_txq->lock);
22804f1d9726SRahul Lakkireddy 	return ret;
22814846d533SRahul Lakkireddy }
22824846d533SRahul Lakkireddy 
22834846d533SRahul Lakkireddy static void ethofld_xmit(struct net_device *dev, struct sge_eosw_txq *eosw_txq)
22844846d533SRahul Lakkireddy {
22854846d533SRahul Lakkireddy 	struct sk_buff *skb;
22864f1d9726SRahul Lakkireddy 	int pktcount, ret;
22874846d533SRahul Lakkireddy 
22884846d533SRahul Lakkireddy 	switch (eosw_txq->state) {
22894846d533SRahul Lakkireddy 	case CXGB4_EO_STATE_ACTIVE:
22900e395b3cSRahul Lakkireddy 	case CXGB4_EO_STATE_FLOWC_OPEN_SEND:
22910e395b3cSRahul Lakkireddy 	case CXGB4_EO_STATE_FLOWC_CLOSE_SEND:
22924846d533SRahul Lakkireddy 		pktcount = eosw_txq->pidx - eosw_txq->last_pidx;
22934846d533SRahul Lakkireddy 		if (pktcount < 0)
22944846d533SRahul Lakkireddy 			pktcount += eosw_txq->ndesc;
22954846d533SRahul Lakkireddy 		break;
22960e395b3cSRahul Lakkireddy 	case CXGB4_EO_STATE_FLOWC_OPEN_REPLY:
22970e395b3cSRahul Lakkireddy 	case CXGB4_EO_STATE_FLOWC_CLOSE_REPLY:
22984846d533SRahul Lakkireddy 	case CXGB4_EO_STATE_CLOSED:
22994846d533SRahul Lakkireddy 	default:
23004846d533SRahul Lakkireddy 		return;
2301272630feSRahul Lakkireddy 	}
23024846d533SRahul Lakkireddy 
23034846d533SRahul Lakkireddy 	while (pktcount--) {
23044846d533SRahul Lakkireddy 		skb = eosw_txq_peek(eosw_txq);
23054846d533SRahul Lakkireddy 		if (!skb) {
23064846d533SRahul Lakkireddy 			eosw_txq_advance_index(&eosw_txq->last_pidx, 1,
23074846d533SRahul Lakkireddy 					       eosw_txq->ndesc);
23084846d533SRahul Lakkireddy 			continue;
23094846d533SRahul Lakkireddy 		}
23104846d533SRahul Lakkireddy 
23114f1d9726SRahul Lakkireddy 		ret = ethofld_hard_xmit(dev, eosw_txq);
23124f1d9726SRahul Lakkireddy 		if (ret)
23134f1d9726SRahul Lakkireddy 			break;
23144846d533SRahul Lakkireddy 	}
23154846d533SRahul Lakkireddy }
23164846d533SRahul Lakkireddy 
2317b1396c2bSRahul Lakkireddy static netdev_tx_t cxgb4_ethofld_xmit(struct sk_buff *skb,
2318b1396c2bSRahul Lakkireddy 				      struct net_device *dev)
2319b1396c2bSRahul Lakkireddy {
23204846d533SRahul Lakkireddy 	struct cxgb4_tc_port_mqprio *tc_port_mqprio;
23214846d533SRahul Lakkireddy 	struct port_info *pi = netdev2pinfo(dev);
23224846d533SRahul Lakkireddy 	struct adapter *adap = netdev2adap(dev);
23234846d533SRahul Lakkireddy 	struct sge_eosw_txq *eosw_txq;
23244846d533SRahul Lakkireddy 	u32 qid;
2325b1396c2bSRahul Lakkireddy 	int ret;
2326b1396c2bSRahul Lakkireddy 
2327b1396c2bSRahul Lakkireddy 	ret = cxgb4_validate_skb(skb, dev, ETH_HLEN);
2328b1396c2bSRahul Lakkireddy 	if (ret)
2329b1396c2bSRahul Lakkireddy 		goto out_free;
2330b1396c2bSRahul Lakkireddy 
23314846d533SRahul Lakkireddy 	tc_port_mqprio = &adap->tc_mqprio->port_mqprio[pi->port_id];
23324846d533SRahul Lakkireddy 	qid = skb_get_queue_mapping(skb) - pi->nqsets;
23334846d533SRahul Lakkireddy 	eosw_txq = &tc_port_mqprio->eosw_txq[qid];
23344846d533SRahul Lakkireddy 	spin_lock_bh(&eosw_txq->lock);
23354846d533SRahul Lakkireddy 	if (eosw_txq->state != CXGB4_EO_STATE_ACTIVE)
23364846d533SRahul Lakkireddy 		goto out_unlock;
23374846d533SRahul Lakkireddy 
23384846d533SRahul Lakkireddy 	ret = eosw_txq_enqueue(eosw_txq, skb);
23394846d533SRahul Lakkireddy 	if (ret)
23404846d533SRahul Lakkireddy 		goto out_unlock;
23414846d533SRahul Lakkireddy 
23424846d533SRahul Lakkireddy 	/* SKB is queued for processing until credits are available.
23434846d533SRahul Lakkireddy 	 * So, call the destructor now and we'll free the skb later
23444846d533SRahul Lakkireddy 	 * after it has been successfully transmitted.
23454846d533SRahul Lakkireddy 	 */
23464846d533SRahul Lakkireddy 	skb_orphan(skb);
23474846d533SRahul Lakkireddy 
23484846d533SRahul Lakkireddy 	eosw_txq_advance(eosw_txq, 1);
23494846d533SRahul Lakkireddy 	ethofld_xmit(dev, eosw_txq);
23504846d533SRahul Lakkireddy 	spin_unlock_bh(&eosw_txq->lock);
23514846d533SRahul Lakkireddy 	return NETDEV_TX_OK;
23524846d533SRahul Lakkireddy 
23534846d533SRahul Lakkireddy out_unlock:
23544846d533SRahul Lakkireddy 	spin_unlock_bh(&eosw_txq->lock);
2355b1396c2bSRahul Lakkireddy out_free:
2356b1396c2bSRahul Lakkireddy 	dev_kfree_skb_any(skb);
2357b1396c2bSRahul Lakkireddy 	return NETDEV_TX_OK;
2358b1396c2bSRahul Lakkireddy }
2359b1396c2bSRahul Lakkireddy 
2360d5fbda61SArjun Vynipadath netdev_tx_t t4_start_xmit(struct sk_buff *skb, struct net_device *dev)
2361d5fbda61SArjun Vynipadath {
2362d5fbda61SArjun Vynipadath 	struct port_info *pi = netdev_priv(dev);
2363b1396c2bSRahul Lakkireddy 	u16 qid = skb_get_queue_mapping(skb);
2364d5fbda61SArjun Vynipadath 
2365d5fbda61SArjun Vynipadath 	if (unlikely(pi->eth_flags & PRIV_FLAG_PORT_TX_VM))
2366d5fbda61SArjun Vynipadath 		return cxgb4_vf_eth_xmit(skb, dev);
2367d5fbda61SArjun Vynipadath 
2368b1396c2bSRahul Lakkireddy 	if (unlikely(qid >= pi->nqsets))
2369b1396c2bSRahul Lakkireddy 		return cxgb4_ethofld_xmit(skb, dev);
2370b1396c2bSRahul Lakkireddy 
2371030c9882SRahul Lakkireddy 	if (is_ptp_enabled(skb, dev)) {
2372030c9882SRahul Lakkireddy 		struct adapter *adap = netdev2adap(dev);
2373030c9882SRahul Lakkireddy 		netdev_tx_t ret;
2374030c9882SRahul Lakkireddy 
2375030c9882SRahul Lakkireddy 		spin_lock(&adap->ptp_lock);
2376030c9882SRahul Lakkireddy 		ret = cxgb4_eth_xmit(skb, dev);
2377030c9882SRahul Lakkireddy 		spin_unlock(&adap->ptp_lock);
2378030c9882SRahul Lakkireddy 		return ret;
2379030c9882SRahul Lakkireddy 	}
2380030c9882SRahul Lakkireddy 
2381d5fbda61SArjun Vynipadath 	return cxgb4_eth_xmit(skb, dev);
2382d5fbda61SArjun Vynipadath }
2383d5fbda61SArjun Vynipadath 
238469422a7eSRahul Lakkireddy static void eosw_txq_flush_pending_skbs(struct sge_eosw_txq *eosw_txq)
238569422a7eSRahul Lakkireddy {
238669422a7eSRahul Lakkireddy 	int pktcount = eosw_txq->pidx - eosw_txq->last_pidx;
238769422a7eSRahul Lakkireddy 	int pidx = eosw_txq->pidx;
238869422a7eSRahul Lakkireddy 	struct sk_buff *skb;
238969422a7eSRahul Lakkireddy 
239069422a7eSRahul Lakkireddy 	if (!pktcount)
239169422a7eSRahul Lakkireddy 		return;
239269422a7eSRahul Lakkireddy 
239369422a7eSRahul Lakkireddy 	if (pktcount < 0)
239469422a7eSRahul Lakkireddy 		pktcount += eosw_txq->ndesc;
239569422a7eSRahul Lakkireddy 
239669422a7eSRahul Lakkireddy 	while (pktcount--) {
239769422a7eSRahul Lakkireddy 		pidx--;
239869422a7eSRahul Lakkireddy 		if (pidx < 0)
239969422a7eSRahul Lakkireddy 			pidx += eosw_txq->ndesc;
240069422a7eSRahul Lakkireddy 
240169422a7eSRahul Lakkireddy 		skb = eosw_txq->desc[pidx].skb;
240269422a7eSRahul Lakkireddy 		if (skb) {
240369422a7eSRahul Lakkireddy 			dev_consume_skb_any(skb);
240469422a7eSRahul Lakkireddy 			eosw_txq->desc[pidx].skb = NULL;
240569422a7eSRahul Lakkireddy 			eosw_txq->inuse--;
240669422a7eSRahul Lakkireddy 		}
240769422a7eSRahul Lakkireddy 	}
240869422a7eSRahul Lakkireddy 
240969422a7eSRahul Lakkireddy 	eosw_txq->pidx = eosw_txq->last_pidx + 1;
241069422a7eSRahul Lakkireddy }
241169422a7eSRahul Lakkireddy 
2412f7917c00SJeff Kirsher /**
24130e395b3cSRahul Lakkireddy  * cxgb4_ethofld_send_flowc - Send ETHOFLD flowc request to bind eotid to tc.
241429bbf5d7SRahul Lakkireddy  * @dev: netdevice
241529bbf5d7SRahul Lakkireddy  * @eotid: ETHOFLD tid to bind/unbind
241629bbf5d7SRahul Lakkireddy  * @tc: traffic class. If set to FW_SCHED_CLS_NONE, then unbinds the @eotid
24170e395b3cSRahul Lakkireddy  *
24180e395b3cSRahul Lakkireddy  * Send a FLOWC work request to bind an ETHOFLD TID to a traffic class.
24190e395b3cSRahul Lakkireddy  * If @tc is set to FW_SCHED_CLS_NONE, then the @eotid is unbound from
24200e395b3cSRahul Lakkireddy  * a traffic class.
24210e395b3cSRahul Lakkireddy  */
24220e395b3cSRahul Lakkireddy int cxgb4_ethofld_send_flowc(struct net_device *dev, u32 eotid, u32 tc)
24230e395b3cSRahul Lakkireddy {
24240e395b3cSRahul Lakkireddy 	struct port_info *pi = netdev2pinfo(dev);
24250e395b3cSRahul Lakkireddy 	struct adapter *adap = netdev2adap(dev);
24260e395b3cSRahul Lakkireddy 	enum sge_eosw_state next_state;
24270e395b3cSRahul Lakkireddy 	struct sge_eosw_txq *eosw_txq;
24280e395b3cSRahul Lakkireddy 	u32 len, len16, nparams = 6;
24290e395b3cSRahul Lakkireddy 	struct fw_flowc_wr *flowc;
24300e395b3cSRahul Lakkireddy 	struct eotid_entry *entry;
24310e395b3cSRahul Lakkireddy 	struct sge_ofld_rxq *rxq;
24320e395b3cSRahul Lakkireddy 	struct sk_buff *skb;
24330e395b3cSRahul Lakkireddy 	int ret = 0;
24340e395b3cSRahul Lakkireddy 
2435a422d5ffSGustavo A. R. Silva 	len = struct_size(flowc, mnemval, nparams);
24360e395b3cSRahul Lakkireddy 	len16 = DIV_ROUND_UP(len, 16);
24370e395b3cSRahul Lakkireddy 
24380e395b3cSRahul Lakkireddy 	entry = cxgb4_lookup_eotid(&adap->tids, eotid);
24390e395b3cSRahul Lakkireddy 	if (!entry)
24400e395b3cSRahul Lakkireddy 		return -ENOMEM;
24410e395b3cSRahul Lakkireddy 
24420e395b3cSRahul Lakkireddy 	eosw_txq = (struct sge_eosw_txq *)entry->data;
24430e395b3cSRahul Lakkireddy 	if (!eosw_txq)
24440e395b3cSRahul Lakkireddy 		return -ENOMEM;
24450e395b3cSRahul Lakkireddy 
24460e395b3cSRahul Lakkireddy 	skb = alloc_skb(len, GFP_KERNEL);
24470e395b3cSRahul Lakkireddy 	if (!skb)
24480e395b3cSRahul Lakkireddy 		return -ENOMEM;
24490e395b3cSRahul Lakkireddy 
24500e395b3cSRahul Lakkireddy 	spin_lock_bh(&eosw_txq->lock);
24510e395b3cSRahul Lakkireddy 	if (tc != FW_SCHED_CLS_NONE) {
24520e395b3cSRahul Lakkireddy 		if (eosw_txq->state != CXGB4_EO_STATE_CLOSED)
24530e395b3cSRahul Lakkireddy 			goto out_unlock;
24540e395b3cSRahul Lakkireddy 
24550e395b3cSRahul Lakkireddy 		next_state = CXGB4_EO_STATE_FLOWC_OPEN_SEND;
24560e395b3cSRahul Lakkireddy 	} else {
24570e395b3cSRahul Lakkireddy 		if (eosw_txq->state != CXGB4_EO_STATE_ACTIVE)
24580e395b3cSRahul Lakkireddy 			goto out_unlock;
24590e395b3cSRahul Lakkireddy 
24600e395b3cSRahul Lakkireddy 		next_state = CXGB4_EO_STATE_FLOWC_CLOSE_SEND;
24610e395b3cSRahul Lakkireddy 	}
24620e395b3cSRahul Lakkireddy 
24630e395b3cSRahul Lakkireddy 	flowc = __skb_put(skb, len);
24640e395b3cSRahul Lakkireddy 	memset(flowc, 0, len);
24650e395b3cSRahul Lakkireddy 
24660e395b3cSRahul Lakkireddy 	rxq = &adap->sge.eohw_rxq[eosw_txq->hwqid];
24670e395b3cSRahul Lakkireddy 	flowc->flowid_len16 = cpu_to_be32(FW_WR_LEN16_V(len16) |
24680e395b3cSRahul Lakkireddy 					  FW_WR_FLOWID_V(eosw_txq->hwtid));
24690e395b3cSRahul Lakkireddy 	flowc->op_to_nparams = cpu_to_be32(FW_WR_OP_V(FW_FLOWC_WR) |
24700e395b3cSRahul Lakkireddy 					   FW_FLOWC_WR_NPARAMS_V(nparams) |
24710e395b3cSRahul Lakkireddy 					   FW_WR_COMPL_V(1));
24720e395b3cSRahul Lakkireddy 	flowc->mnemval[0].mnemonic = FW_FLOWC_MNEM_PFNVFN;
24730e395b3cSRahul Lakkireddy 	flowc->mnemval[0].val = cpu_to_be32(FW_PFVF_CMD_PFN_V(adap->pf));
24740e395b3cSRahul Lakkireddy 	flowc->mnemval[1].mnemonic = FW_FLOWC_MNEM_CH;
24750e395b3cSRahul Lakkireddy 	flowc->mnemval[1].val = cpu_to_be32(pi->tx_chan);
24760e395b3cSRahul Lakkireddy 	flowc->mnemval[2].mnemonic = FW_FLOWC_MNEM_PORT;
24770e395b3cSRahul Lakkireddy 	flowc->mnemval[2].val = cpu_to_be32(pi->tx_chan);
24780e395b3cSRahul Lakkireddy 	flowc->mnemval[3].mnemonic = FW_FLOWC_MNEM_IQID;
24790e395b3cSRahul Lakkireddy 	flowc->mnemval[3].val = cpu_to_be32(rxq->rspq.abs_id);
24800e395b3cSRahul Lakkireddy 	flowc->mnemval[4].mnemonic = FW_FLOWC_MNEM_SCHEDCLASS;
24810e395b3cSRahul Lakkireddy 	flowc->mnemval[4].val = cpu_to_be32(tc);
24820e395b3cSRahul Lakkireddy 	flowc->mnemval[5].mnemonic = FW_FLOWC_MNEM_EOSTATE;
24830e395b3cSRahul Lakkireddy 	flowc->mnemval[5].val = cpu_to_be32(tc == FW_SCHED_CLS_NONE ?
24840e395b3cSRahul Lakkireddy 					    FW_FLOWC_MNEM_EOSTATE_CLOSING :
24850e395b3cSRahul Lakkireddy 					    FW_FLOWC_MNEM_EOSTATE_ESTABLISHED);
24860e395b3cSRahul Lakkireddy 
248769422a7eSRahul Lakkireddy 	/* Free up any pending skbs to ensure there's room for
248869422a7eSRahul Lakkireddy 	 * termination FLOWC.
248969422a7eSRahul Lakkireddy 	 */
249069422a7eSRahul Lakkireddy 	if (tc == FW_SCHED_CLS_NONE)
249169422a7eSRahul Lakkireddy 		eosw_txq_flush_pending_skbs(eosw_txq);
24920e395b3cSRahul Lakkireddy 
24930e395b3cSRahul Lakkireddy 	ret = eosw_txq_enqueue(eosw_txq, skb);
24940e395b3cSRahul Lakkireddy 	if (ret) {
24950e395b3cSRahul Lakkireddy 		dev_consume_skb_any(skb);
24960e395b3cSRahul Lakkireddy 		goto out_unlock;
24970e395b3cSRahul Lakkireddy 	}
24980e395b3cSRahul Lakkireddy 
24990e395b3cSRahul Lakkireddy 	eosw_txq->state = next_state;
25000e395b3cSRahul Lakkireddy 	eosw_txq->flowc_idx = eosw_txq->pidx;
25010e395b3cSRahul Lakkireddy 	eosw_txq_advance(eosw_txq, 1);
25020e395b3cSRahul Lakkireddy 	ethofld_xmit(dev, eosw_txq);
25030e395b3cSRahul Lakkireddy 
25040e395b3cSRahul Lakkireddy out_unlock:
25050e395b3cSRahul Lakkireddy 	spin_unlock_bh(&eosw_txq->lock);
25060e395b3cSRahul Lakkireddy 	return ret;
25070e395b3cSRahul Lakkireddy }
25080e395b3cSRahul Lakkireddy 
25090e395b3cSRahul Lakkireddy /**
2510f7917c00SJeff Kirsher  *	is_imm - check whether a packet can be sent as immediate data
2511f7917c00SJeff Kirsher  *	@skb: the packet
2512f7917c00SJeff Kirsher  *
2513f7917c00SJeff Kirsher  *	Returns true if a packet can be sent as a WR with immediate data.
2514f7917c00SJeff Kirsher  */
2515f7917c00SJeff Kirsher static inline int is_imm(const struct sk_buff *skb)
2516f7917c00SJeff Kirsher {
2517f7917c00SJeff Kirsher 	return skb->len <= MAX_CTRL_WR_LEN;
2518f7917c00SJeff Kirsher }
2519f7917c00SJeff Kirsher 
2520f7917c00SJeff Kirsher /**
2521f7917c00SJeff Kirsher  *	ctrlq_check_stop - check if a control queue is full and should stop
2522f7917c00SJeff Kirsher  *	@q: the queue
2523f7917c00SJeff Kirsher  *	@wr: most recent WR written to the queue
2524f7917c00SJeff Kirsher  *
2525f7917c00SJeff Kirsher  *	Check if a control queue has become full and should be stopped.
2526f7917c00SJeff Kirsher  *	We clean up control queue descriptors very lazily, only when we are out.
2527f7917c00SJeff Kirsher  *	If the queue is still full after reclaiming any completed descriptors
2528f7917c00SJeff Kirsher  *	we suspend it and have the last WR wake it up.
2529f7917c00SJeff Kirsher  */
2530f7917c00SJeff Kirsher static void ctrlq_check_stop(struct sge_ctrl_txq *q, struct fw_wr_hdr *wr)
2531f7917c00SJeff Kirsher {
2532f7917c00SJeff Kirsher 	reclaim_completed_tx_imm(&q->q);
2533f7917c00SJeff Kirsher 	if (unlikely(txq_avail(&q->q) < TXQ_STOP_THRES)) {
2534e2ac9628SHariprasad Shenai 		wr->lo |= htonl(FW_WR_EQUEQ_F | FW_WR_EQUIQ_F);
2535f7917c00SJeff Kirsher 		q->q.stops++;
2536f7917c00SJeff Kirsher 		q->full = 1;
2537f7917c00SJeff Kirsher 	}
2538f7917c00SJeff Kirsher }
2539f7917c00SJeff Kirsher 
25407235ffaeSVishal Kulkarni #define CXGB4_SELFTEST_LB_STR "CHELSIO_SELFTEST"
25417235ffaeSVishal Kulkarni 
25427235ffaeSVishal Kulkarni int cxgb4_selftest_lb_pkt(struct net_device *netdev)
25437235ffaeSVishal Kulkarni {
25447235ffaeSVishal Kulkarni 	struct port_info *pi = netdev_priv(netdev);
25457235ffaeSVishal Kulkarni 	struct adapter *adap = pi->adapter;
25467235ffaeSVishal Kulkarni 	struct cxgb4_ethtool_lb_test *lb;
25477235ffaeSVishal Kulkarni 	int ret, i = 0, pkt_len, credits;
25487235ffaeSVishal Kulkarni 	struct fw_eth_tx_pkt_wr *wr;
25497235ffaeSVishal Kulkarni 	struct cpl_tx_pkt_core *cpl;
25507235ffaeSVishal Kulkarni 	u32 ctrl0, ndesc, flits;
25517235ffaeSVishal Kulkarni 	struct sge_eth_txq *q;
25527235ffaeSVishal Kulkarni 	u8 *sgl;
25537235ffaeSVishal Kulkarni 
25547235ffaeSVishal Kulkarni 	pkt_len = ETH_HLEN + sizeof(CXGB4_SELFTEST_LB_STR);
25557235ffaeSVishal Kulkarni 
25567235ffaeSVishal Kulkarni 	flits = DIV_ROUND_UP(pkt_len + sizeof(struct cpl_tx_pkt) +
25577235ffaeSVishal Kulkarni 			     sizeof(*wr), sizeof(__be64));
25587235ffaeSVishal Kulkarni 	ndesc = flits_to_desc(flits);
25597235ffaeSVishal Kulkarni 
25607235ffaeSVishal Kulkarni 	lb = &pi->ethtool_lb;
25617235ffaeSVishal Kulkarni 	lb->loopback = 1;
25627235ffaeSVishal Kulkarni 
25637235ffaeSVishal Kulkarni 	q = &adap->sge.ethtxq[pi->first_qset];
25647235ffaeSVishal Kulkarni 
25657235ffaeSVishal Kulkarni 	reclaim_completed_tx(adap, &q->q, -1, true);
25667235ffaeSVishal Kulkarni 	credits = txq_avail(&q->q) - ndesc;
25677235ffaeSVishal Kulkarni 	if (unlikely(credits < 0))
25687235ffaeSVishal Kulkarni 		return -ENOMEM;
25697235ffaeSVishal Kulkarni 
25707235ffaeSVishal Kulkarni 	wr = (void *)&q->q.desc[q->q.pidx];
25717235ffaeSVishal Kulkarni 	memset(wr, 0, sizeof(struct tx_desc));
25727235ffaeSVishal Kulkarni 
25737235ffaeSVishal Kulkarni 	wr->op_immdlen = htonl(FW_WR_OP_V(FW_ETH_TX_PKT_WR) |
25747235ffaeSVishal Kulkarni 			       FW_WR_IMMDLEN_V(pkt_len +
25757235ffaeSVishal Kulkarni 			       sizeof(*cpl)));
25767235ffaeSVishal Kulkarni 	wr->equiq_to_len16 = htonl(FW_WR_LEN16_V(DIV_ROUND_UP(flits, 2)));
25777235ffaeSVishal Kulkarni 	wr->r3 = cpu_to_be64(0);
25787235ffaeSVishal Kulkarni 
25797235ffaeSVishal Kulkarni 	cpl = (void *)(wr + 1);
25807235ffaeSVishal Kulkarni 	sgl = (u8 *)(cpl + 1);
25817235ffaeSVishal Kulkarni 
25827235ffaeSVishal Kulkarni 	ctrl0 = TXPKT_OPCODE_V(CPL_TX_PKT_XT) | TXPKT_PF_V(adap->pf) |
25837235ffaeSVishal Kulkarni 		TXPKT_INTF_V(pi->tx_chan + 4);
25847235ffaeSVishal Kulkarni 
25857235ffaeSVishal Kulkarni 	cpl->ctrl0 = htonl(ctrl0);
25867235ffaeSVishal Kulkarni 	cpl->pack = htons(0);
25877235ffaeSVishal Kulkarni 	cpl->len = htons(pkt_len);
25887235ffaeSVishal Kulkarni 	cpl->ctrl1 = cpu_to_be64(TXPKT_L4CSUM_DIS_F | TXPKT_IPCSUM_DIS_F);
25897235ffaeSVishal Kulkarni 
25907235ffaeSVishal Kulkarni 	eth_broadcast_addr(sgl);
25917235ffaeSVishal Kulkarni 	i += ETH_ALEN;
25927235ffaeSVishal Kulkarni 	ether_addr_copy(&sgl[i], netdev->dev_addr);
25937235ffaeSVishal Kulkarni 	i += ETH_ALEN;
25947235ffaeSVishal Kulkarni 
25957235ffaeSVishal Kulkarni 	snprintf(&sgl[i], sizeof(CXGB4_SELFTEST_LB_STR), "%s",
25967235ffaeSVishal Kulkarni 		 CXGB4_SELFTEST_LB_STR);
25977235ffaeSVishal Kulkarni 
25987235ffaeSVishal Kulkarni 	init_completion(&lb->completion);
25997235ffaeSVishal Kulkarni 	txq_advance(&q->q, ndesc);
26007235ffaeSVishal Kulkarni 	cxgb4_ring_tx_db(adap, &q->q, ndesc);
26017235ffaeSVishal Kulkarni 
26027235ffaeSVishal Kulkarni 	/* wait for the pkt to return */
26037235ffaeSVishal Kulkarni 	ret = wait_for_completion_timeout(&lb->completion, 10 * HZ);
26047235ffaeSVishal Kulkarni 	if (!ret)
26057235ffaeSVishal Kulkarni 		ret = -ETIMEDOUT;
26067235ffaeSVishal Kulkarni 	else
26077235ffaeSVishal Kulkarni 		ret = lb->result;
26087235ffaeSVishal Kulkarni 
26097235ffaeSVishal Kulkarni 	lb->loopback = 0;
26107235ffaeSVishal Kulkarni 
26117235ffaeSVishal Kulkarni 	return ret;
26127235ffaeSVishal Kulkarni }
26137235ffaeSVishal Kulkarni 
2614f7917c00SJeff Kirsher /**
2615f7917c00SJeff Kirsher  *	ctrl_xmit - send a packet through an SGE control Tx queue
2616f7917c00SJeff Kirsher  *	@q: the control queue
2617f7917c00SJeff Kirsher  *	@skb: the packet
2618f7917c00SJeff Kirsher  *
2619f7917c00SJeff Kirsher  *	Send a packet through an SGE control Tx queue.  Packets sent through
2620f7917c00SJeff Kirsher  *	a control queue must fit entirely as immediate data.
2621f7917c00SJeff Kirsher  */
2622f7917c00SJeff Kirsher static int ctrl_xmit(struct sge_ctrl_txq *q, struct sk_buff *skb)
2623f7917c00SJeff Kirsher {
2624f7917c00SJeff Kirsher 	unsigned int ndesc;
2625f7917c00SJeff Kirsher 	struct fw_wr_hdr *wr;
2626f7917c00SJeff Kirsher 
2627f7917c00SJeff Kirsher 	if (unlikely(!is_imm(skb))) {
2628f7917c00SJeff Kirsher 		WARN_ON(1);
2629f7917c00SJeff Kirsher 		dev_kfree_skb(skb);
2630f7917c00SJeff Kirsher 		return NET_XMIT_DROP;
2631f7917c00SJeff Kirsher 	}
2632f7917c00SJeff Kirsher 
2633f7917c00SJeff Kirsher 	ndesc = DIV_ROUND_UP(skb->len, sizeof(struct tx_desc));
2634f7917c00SJeff Kirsher 	spin_lock(&q->sendq.lock);
2635f7917c00SJeff Kirsher 
2636f7917c00SJeff Kirsher 	if (unlikely(q->full)) {
2637f7917c00SJeff Kirsher 		skb->priority = ndesc;                  /* save for restart */
2638f7917c00SJeff Kirsher 		__skb_queue_tail(&q->sendq, skb);
2639f7917c00SJeff Kirsher 		spin_unlock(&q->sendq.lock);
2640f7917c00SJeff Kirsher 		return NET_XMIT_CN;
2641f7917c00SJeff Kirsher 	}
2642f7917c00SJeff Kirsher 
2643f7917c00SJeff Kirsher 	wr = (struct fw_wr_hdr *)&q->q.desc[q->q.pidx];
2644a6ec572bSAtul Gupta 	cxgb4_inline_tx_skb(skb, &q->q, wr);
2645f7917c00SJeff Kirsher 
2646f7917c00SJeff Kirsher 	txq_advance(&q->q, ndesc);
2647f7917c00SJeff Kirsher 	if (unlikely(txq_avail(&q->q) < TXQ_STOP_THRES))
2648f7917c00SJeff Kirsher 		ctrlq_check_stop(q, wr);
2649f7917c00SJeff Kirsher 
2650a6ec572bSAtul Gupta 	cxgb4_ring_tx_db(q->adap, &q->q, ndesc);
2651f7917c00SJeff Kirsher 	spin_unlock(&q->sendq.lock);
2652f7917c00SJeff Kirsher 
2653f7917c00SJeff Kirsher 	kfree_skb(skb);
2654f7917c00SJeff Kirsher 	return NET_XMIT_SUCCESS;
2655f7917c00SJeff Kirsher }
2656f7917c00SJeff Kirsher 
2657f7917c00SJeff Kirsher /**
2658f7917c00SJeff Kirsher  *	restart_ctrlq - restart a suspended control queue
2659f7917c00SJeff Kirsher  *	@data: the control queue to restart
2660f7917c00SJeff Kirsher  *
2661f7917c00SJeff Kirsher  *	Resumes transmission on a suspended Tx control queue.
2662f7917c00SJeff Kirsher  */
2663f7917c00SJeff Kirsher static void restart_ctrlq(unsigned long data)
2664f7917c00SJeff Kirsher {
2665f7917c00SJeff Kirsher 	struct sk_buff *skb;
2666f7917c00SJeff Kirsher 	unsigned int written = 0;
2667f7917c00SJeff Kirsher 	struct sge_ctrl_txq *q = (struct sge_ctrl_txq *)data;
2668f7917c00SJeff Kirsher 
2669f7917c00SJeff Kirsher 	spin_lock(&q->sendq.lock);
2670f7917c00SJeff Kirsher 	reclaim_completed_tx_imm(&q->q);
2671f7917c00SJeff Kirsher 	BUG_ON(txq_avail(&q->q) < TXQ_STOP_THRES);  /* q should be empty */
2672f7917c00SJeff Kirsher 
2673f7917c00SJeff Kirsher 	while ((skb = __skb_dequeue(&q->sendq)) != NULL) {
2674f7917c00SJeff Kirsher 		struct fw_wr_hdr *wr;
2675f7917c00SJeff Kirsher 		unsigned int ndesc = skb->priority;     /* previously saved */
2676f7917c00SJeff Kirsher 
2677a4011fd4SHariprasad Shenai 		written += ndesc;
2678a4011fd4SHariprasad Shenai 		/* Write descriptors and free skbs outside the lock to limit
2679f7917c00SJeff Kirsher 		 * wait times.  q->full is still set so new skbs will be queued.
2680f7917c00SJeff Kirsher 		 */
2681a4011fd4SHariprasad Shenai 		wr = (struct fw_wr_hdr *)&q->q.desc[q->q.pidx];
2682a4011fd4SHariprasad Shenai 		txq_advance(&q->q, ndesc);
2683f7917c00SJeff Kirsher 		spin_unlock(&q->sendq.lock);
2684f7917c00SJeff Kirsher 
2685a6ec572bSAtul Gupta 		cxgb4_inline_tx_skb(skb, &q->q, wr);
2686f7917c00SJeff Kirsher 		kfree_skb(skb);
2687f7917c00SJeff Kirsher 
2688f7917c00SJeff Kirsher 		if (unlikely(txq_avail(&q->q) < TXQ_STOP_THRES)) {
2689f7917c00SJeff Kirsher 			unsigned long old = q->q.stops;
2690f7917c00SJeff Kirsher 
2691f7917c00SJeff Kirsher 			ctrlq_check_stop(q, wr);
2692f7917c00SJeff Kirsher 			if (q->q.stops != old) {          /* suspended anew */
2693f7917c00SJeff Kirsher 				spin_lock(&q->sendq.lock);
2694f7917c00SJeff Kirsher 				goto ringdb;
2695f7917c00SJeff Kirsher 			}
2696f7917c00SJeff Kirsher 		}
2697f7917c00SJeff Kirsher 		if (written > 16) {
2698a6ec572bSAtul Gupta 			cxgb4_ring_tx_db(q->adap, &q->q, written);
2699f7917c00SJeff Kirsher 			written = 0;
2700f7917c00SJeff Kirsher 		}
2701f7917c00SJeff Kirsher 		spin_lock(&q->sendq.lock);
2702f7917c00SJeff Kirsher 	}
2703f7917c00SJeff Kirsher 	q->full = 0;
2704a6ec572bSAtul Gupta ringdb:
2705a6ec572bSAtul Gupta 	if (written)
2706a6ec572bSAtul Gupta 		cxgb4_ring_tx_db(q->adap, &q->q, written);
2707f7917c00SJeff Kirsher 	spin_unlock(&q->sendq.lock);
2708f7917c00SJeff Kirsher }
2709f7917c00SJeff Kirsher 
2710f7917c00SJeff Kirsher /**
2711f7917c00SJeff Kirsher  *	t4_mgmt_tx - send a management message
2712f7917c00SJeff Kirsher  *	@adap: the adapter
2713f7917c00SJeff Kirsher  *	@skb: the packet containing the management message
2714f7917c00SJeff Kirsher  *
2715f7917c00SJeff Kirsher  *	Send a management message through control queue 0.
2716f7917c00SJeff Kirsher  */
2717f7917c00SJeff Kirsher int t4_mgmt_tx(struct adapter *adap, struct sk_buff *skb)
2718f7917c00SJeff Kirsher {
2719f7917c00SJeff Kirsher 	int ret;
2720f7917c00SJeff Kirsher 
2721f7917c00SJeff Kirsher 	local_bh_disable();
2722f7917c00SJeff Kirsher 	ret = ctrl_xmit(&adap->sge.ctrlq[0], skb);
2723f7917c00SJeff Kirsher 	local_bh_enable();
2724f7917c00SJeff Kirsher 	return ret;
2725f7917c00SJeff Kirsher }
2726f7917c00SJeff Kirsher 
2727f7917c00SJeff Kirsher /**
2728f7917c00SJeff Kirsher  *	is_ofld_imm - check whether a packet can be sent as immediate data
2729f7917c00SJeff Kirsher  *	@skb: the packet
2730f7917c00SJeff Kirsher  *
2731f7917c00SJeff Kirsher  *	Returns true if a packet can be sent as an offload WR with immediate
2732f7917c00SJeff Kirsher  *	data.  We currently use the same limit as for Ethernet packets.
2733f7917c00SJeff Kirsher  */
2734f7917c00SJeff Kirsher static inline int is_ofld_imm(const struct sk_buff *skb)
2735f7917c00SJeff Kirsher {
27362f47d580SHarsh Jain 	struct work_request_hdr *req = (struct work_request_hdr *)skb->data;
27372f47d580SHarsh Jain 	unsigned long opcode = FW_WR_OP_G(ntohl(req->wr_hi));
27382f47d580SHarsh Jain 
27392f47d580SHarsh Jain 	if (opcode == FW_CRYPTO_LOOKASIDE_WR)
27402f47d580SHarsh Jain 		return skb->len <= SGE_MAX_WR_LEN;
27412f47d580SHarsh Jain 	else
2742f7917c00SJeff Kirsher 		return skb->len <= MAX_IMM_TX_PKT_LEN;
2743f7917c00SJeff Kirsher }
2744f7917c00SJeff Kirsher 
2745f7917c00SJeff Kirsher /**
2746f7917c00SJeff Kirsher  *	calc_tx_flits_ofld - calculate # of flits for an offload packet
2747f7917c00SJeff Kirsher  *	@skb: the packet
2748f7917c00SJeff Kirsher  *
2749f7917c00SJeff Kirsher  *	Returns the number of flits needed for the given offload packet.
2750f7917c00SJeff Kirsher  *	These packets are already fully constructed and no additional headers
2751f7917c00SJeff Kirsher  *	will be added.
2752f7917c00SJeff Kirsher  */
2753f7917c00SJeff Kirsher static inline unsigned int calc_tx_flits_ofld(const struct sk_buff *skb)
2754f7917c00SJeff Kirsher {
2755f7917c00SJeff Kirsher 	unsigned int flits, cnt;
2756f7917c00SJeff Kirsher 
2757f7917c00SJeff Kirsher 	if (is_ofld_imm(skb))
2758f7917c00SJeff Kirsher 		return DIV_ROUND_UP(skb->len, 8);
2759f7917c00SJeff Kirsher 
2760f7917c00SJeff Kirsher 	flits = skb_transport_offset(skb) / 8U;   /* headers */
2761f7917c00SJeff Kirsher 	cnt = skb_shinfo(skb)->nr_frags;
276215dd16c2SLi RongQing 	if (skb_tail_pointer(skb) != skb_transport_header(skb))
2763f7917c00SJeff Kirsher 		cnt++;
2764f7917c00SJeff Kirsher 	return flits + sgl_len(cnt);
2765f7917c00SJeff Kirsher }
2766f7917c00SJeff Kirsher 
2767f7917c00SJeff Kirsher /**
2768f7917c00SJeff Kirsher  *	txq_stop_maperr - stop a Tx queue due to I/O MMU exhaustion
2769f7917c00SJeff Kirsher  *	@q: the queue to stop
2770f7917c00SJeff Kirsher  *
2771f7917c00SJeff Kirsher  *	Mark a Tx queue stopped due to I/O MMU exhaustion and resulting
2772f7917c00SJeff Kirsher  *	inability to map packets.  A periodic timer attempts to restart
2773f7917c00SJeff Kirsher  *	queues so marked.
2774f7917c00SJeff Kirsher  */
2775ab677ff4SHariprasad Shenai static void txq_stop_maperr(struct sge_uld_txq *q)
2776f7917c00SJeff Kirsher {
2777f7917c00SJeff Kirsher 	q->mapping_err++;
2778f7917c00SJeff Kirsher 	q->q.stops++;
2779f7917c00SJeff Kirsher 	set_bit(q->q.cntxt_id - q->adap->sge.egr_start,
2780f7917c00SJeff Kirsher 		q->adap->sge.txq_maperr);
2781f7917c00SJeff Kirsher }
2782f7917c00SJeff Kirsher 
2783f7917c00SJeff Kirsher /**
2784f7917c00SJeff Kirsher  *	ofldtxq_stop - stop an offload Tx queue that has become full
2785f7917c00SJeff Kirsher  *	@q: the queue to stop
2786e383f248SAtul Gupta  *	@wr: the Work Request causing the queue to become full
2787f7917c00SJeff Kirsher  *
2788f7917c00SJeff Kirsher  *	Stops an offload Tx queue that has become full and modifies the packet
2789f7917c00SJeff Kirsher  *	being written to request a wakeup.
2790f7917c00SJeff Kirsher  */
2791e383f248SAtul Gupta static void ofldtxq_stop(struct sge_uld_txq *q, struct fw_wr_hdr *wr)
2792f7917c00SJeff Kirsher {
2793e2ac9628SHariprasad Shenai 	wr->lo |= htonl(FW_WR_EQUEQ_F | FW_WR_EQUIQ_F);
2794f7917c00SJeff Kirsher 	q->q.stops++;
2795f7917c00SJeff Kirsher 	q->full = 1;
2796f7917c00SJeff Kirsher }
2797f7917c00SJeff Kirsher 
2798f7917c00SJeff Kirsher /**
2799126fca64SHariprasad Shenai  *	service_ofldq - service/restart a suspended offload queue
2800f7917c00SJeff Kirsher  *	@q: the offload queue
2801f7917c00SJeff Kirsher  *
2802126fca64SHariprasad Shenai  *	Services an offload Tx queue by moving packets from its Pending Send
2803126fca64SHariprasad Shenai  *	Queue to the Hardware TX ring.  The function starts and ends with the
2804126fca64SHariprasad Shenai  *	Send Queue locked, but drops the lock while putting the skb at the
2805126fca64SHariprasad Shenai  *	head of the Send Queue onto the Hardware TX Ring.  Dropping the lock
2806126fca64SHariprasad Shenai  *	allows more skbs to be added to the Send Queue by other threads.
2807126fca64SHariprasad Shenai  *	The packet being processed at the head of the Pending Send Queue is
2808126fca64SHariprasad Shenai  *	left on the queue in case we experience DMA Mapping errors, etc.
2809126fca64SHariprasad Shenai  *	and need to give up and restart later.
2810126fca64SHariprasad Shenai  *
2811126fca64SHariprasad Shenai  *	service_ofldq() can be thought of as a task which opportunistically
2812126fca64SHariprasad Shenai  *	uses other threads execution contexts.  We use the Offload Queue
2813126fca64SHariprasad Shenai  *	boolean "service_ofldq_running" to make sure that only one instance
2814126fca64SHariprasad Shenai  *	is ever running at a time ...
2815f7917c00SJeff Kirsher  */
2816ab677ff4SHariprasad Shenai static void service_ofldq(struct sge_uld_txq *q)
2817cae9566aSJules Irenge 	__must_hold(&q->sendq.lock)
2818f7917c00SJeff Kirsher {
28198d0557d2SHariprasad Shenai 	u64 *pos, *before, *end;
2820f7917c00SJeff Kirsher 	int credits;
2821f7917c00SJeff Kirsher 	struct sk_buff *skb;
28228d0557d2SHariprasad Shenai 	struct sge_txq *txq;
28238d0557d2SHariprasad Shenai 	unsigned int left;
2824f7917c00SJeff Kirsher 	unsigned int written = 0;
2825f7917c00SJeff Kirsher 	unsigned int flits, ndesc;
2826f7917c00SJeff Kirsher 
2827126fca64SHariprasad Shenai 	/* If another thread is currently in service_ofldq() processing the
2828126fca64SHariprasad Shenai 	 * Pending Send Queue then there's nothing to do. Otherwise, flag
2829126fca64SHariprasad Shenai 	 * that we're doing the work and continue.  Examining/modifying
2830126fca64SHariprasad Shenai 	 * the Offload Queue boolean "service_ofldq_running" must be done
2831126fca64SHariprasad Shenai 	 * while holding the Pending Send Queue Lock.
2832126fca64SHariprasad Shenai 	 */
2833126fca64SHariprasad Shenai 	if (q->service_ofldq_running)
2834126fca64SHariprasad Shenai 		return;
2835126fca64SHariprasad Shenai 	q->service_ofldq_running = true;
2836126fca64SHariprasad Shenai 
2837f7917c00SJeff Kirsher 	while ((skb = skb_peek(&q->sendq)) != NULL && !q->full) {
2838126fca64SHariprasad Shenai 		/* We drop the lock while we're working with the skb at the
2839126fca64SHariprasad Shenai 		 * head of the Pending Send Queue.  This allows more skbs to
2840126fca64SHariprasad Shenai 		 * be added to the Pending Send Queue while we're working on
2841126fca64SHariprasad Shenai 		 * this one.  We don't need to lock to guard the TX Ring
2842126fca64SHariprasad Shenai 		 * updates because only one thread of execution is ever
2843126fca64SHariprasad Shenai 		 * allowed into service_ofldq() at a time.
2844f7917c00SJeff Kirsher 		 */
2845f7917c00SJeff Kirsher 		spin_unlock(&q->sendq.lock);
2846f7917c00SJeff Kirsher 
2847a6ec572bSAtul Gupta 		cxgb4_reclaim_completed_tx(q->adap, &q->q, false);
2848f7917c00SJeff Kirsher 
2849f7917c00SJeff Kirsher 		flits = skb->priority;                /* previously saved */
2850f7917c00SJeff Kirsher 		ndesc = flits_to_desc(flits);
2851f7917c00SJeff Kirsher 		credits = txq_avail(&q->q) - ndesc;
2852f7917c00SJeff Kirsher 		BUG_ON(credits < 0);
2853f7917c00SJeff Kirsher 		if (unlikely(credits < TXQ_STOP_THRES))
2854e383f248SAtul Gupta 			ofldtxq_stop(q, (struct fw_wr_hdr *)skb->data);
2855f7917c00SJeff Kirsher 
2856f7917c00SJeff Kirsher 		pos = (u64 *)&q->q.desc[q->q.pidx];
2857f7917c00SJeff Kirsher 		if (is_ofld_imm(skb))
2858a6ec572bSAtul Gupta 			cxgb4_inline_tx_skb(skb, &q->q, pos);
2859a6ec572bSAtul Gupta 		else if (cxgb4_map_skb(q->adap->pdev_dev, skb,
2860f7917c00SJeff Kirsher 				       (dma_addr_t *)skb->head)) {
2861f7917c00SJeff Kirsher 			txq_stop_maperr(q);
2862f7917c00SJeff Kirsher 			spin_lock(&q->sendq.lock);
2863f7917c00SJeff Kirsher 			break;
2864f7917c00SJeff Kirsher 		} else {
2865f7917c00SJeff Kirsher 			int last_desc, hdr_len = skb_transport_offset(skb);
2866f7917c00SJeff Kirsher 
28678d0557d2SHariprasad Shenai 			/* The WR headers  may not fit within one descriptor.
28688d0557d2SHariprasad Shenai 			 * So we need to deal with wrap-around here.
28698d0557d2SHariprasad Shenai 			 */
28708d0557d2SHariprasad Shenai 			before = (u64 *)pos;
28718d0557d2SHariprasad Shenai 			end = (u64 *)pos + flits;
28728d0557d2SHariprasad Shenai 			txq = &q->q;
28738d0557d2SHariprasad Shenai 			pos = (void *)inline_tx_skb_header(skb, &q->q,
28748d0557d2SHariprasad Shenai 							   (void *)pos,
28758d0557d2SHariprasad Shenai 							   hdr_len);
28768d0557d2SHariprasad Shenai 			if (before > (u64 *)pos) {
28778d0557d2SHariprasad Shenai 				left = (u8 *)end - (u8 *)txq->stat;
28788d0557d2SHariprasad Shenai 				end = (void *)txq->desc + left;
28798d0557d2SHariprasad Shenai 			}
28808d0557d2SHariprasad Shenai 
28818d0557d2SHariprasad Shenai 			/* If current position is already at the end of the
28828d0557d2SHariprasad Shenai 			 * ofld queue, reset the current to point to
28838d0557d2SHariprasad Shenai 			 * start of the queue and update the end ptr as well.
28848d0557d2SHariprasad Shenai 			 */
28858d0557d2SHariprasad Shenai 			if (pos == (u64 *)txq->stat) {
28868d0557d2SHariprasad Shenai 				left = (u8 *)end - (u8 *)txq->stat;
28878d0557d2SHariprasad Shenai 				end = (void *)txq->desc + left;
28888d0557d2SHariprasad Shenai 				pos = (void *)txq->desc;
28898d0557d2SHariprasad Shenai 			}
28908d0557d2SHariprasad Shenai 
2891a6ec572bSAtul Gupta 			cxgb4_write_sgl(skb, &q->q, (void *)pos,
28928d0557d2SHariprasad Shenai 					end, hdr_len,
2893f7917c00SJeff Kirsher 					(dma_addr_t *)skb->head);
2894f7917c00SJeff Kirsher #ifdef CONFIG_NEED_DMA_MAP_STATE
2895f7917c00SJeff Kirsher 			skb->dev = q->adap->port[0];
2896f7917c00SJeff Kirsher 			skb->destructor = deferred_unmap_destructor;
2897f7917c00SJeff Kirsher #endif
2898f7917c00SJeff Kirsher 			last_desc = q->q.pidx + ndesc - 1;
2899f7917c00SJeff Kirsher 			if (last_desc >= q->q.size)
2900f7917c00SJeff Kirsher 				last_desc -= q->q.size;
2901f7917c00SJeff Kirsher 			q->q.sdesc[last_desc].skb = skb;
2902f7917c00SJeff Kirsher 		}
2903f7917c00SJeff Kirsher 
2904f7917c00SJeff Kirsher 		txq_advance(&q->q, ndesc);
2905f7917c00SJeff Kirsher 		written += ndesc;
2906f7917c00SJeff Kirsher 		if (unlikely(written > 32)) {
2907a6ec572bSAtul Gupta 			cxgb4_ring_tx_db(q->adap, &q->q, written);
2908f7917c00SJeff Kirsher 			written = 0;
2909f7917c00SJeff Kirsher 		}
2910f7917c00SJeff Kirsher 
2911126fca64SHariprasad Shenai 		/* Reacquire the Pending Send Queue Lock so we can unlink the
2912126fca64SHariprasad Shenai 		 * skb we've just successfully transferred to the TX Ring and
2913126fca64SHariprasad Shenai 		 * loop for the next skb which may be at the head of the
2914126fca64SHariprasad Shenai 		 * Pending Send Queue.
2915126fca64SHariprasad Shenai 		 */
2916f7917c00SJeff Kirsher 		spin_lock(&q->sendq.lock);
2917f7917c00SJeff Kirsher 		__skb_unlink(skb, &q->sendq);
2918f7917c00SJeff Kirsher 		if (is_ofld_imm(skb))
2919f7917c00SJeff Kirsher 			kfree_skb(skb);
2920f7917c00SJeff Kirsher 	}
2921f7917c00SJeff Kirsher 	if (likely(written))
2922a6ec572bSAtul Gupta 		cxgb4_ring_tx_db(q->adap, &q->q, written);
2923126fca64SHariprasad Shenai 
2924126fca64SHariprasad Shenai 	/*Indicate that no thread is processing the Pending Send Queue
2925126fca64SHariprasad Shenai 	 * currently.
2926126fca64SHariprasad Shenai 	 */
2927126fca64SHariprasad Shenai 	q->service_ofldq_running = false;
2928f7917c00SJeff Kirsher }
2929f7917c00SJeff Kirsher 
2930f7917c00SJeff Kirsher /**
2931f7917c00SJeff Kirsher  *	ofld_xmit - send a packet through an offload queue
2932f7917c00SJeff Kirsher  *	@q: the Tx offload queue
2933f7917c00SJeff Kirsher  *	@skb: the packet
2934f7917c00SJeff Kirsher  *
2935f7917c00SJeff Kirsher  *	Send an offload packet through an SGE offload queue.
2936f7917c00SJeff Kirsher  */
2937ab677ff4SHariprasad Shenai static int ofld_xmit(struct sge_uld_txq *q, struct sk_buff *skb)
2938f7917c00SJeff Kirsher {
2939f7917c00SJeff Kirsher 	skb->priority = calc_tx_flits_ofld(skb);       /* save for restart */
2940f7917c00SJeff Kirsher 	spin_lock(&q->sendq.lock);
2941126fca64SHariprasad Shenai 
2942126fca64SHariprasad Shenai 	/* Queue the new skb onto the Offload Queue's Pending Send Queue.  If
2943126fca64SHariprasad Shenai 	 * that results in this new skb being the only one on the queue, start
2944126fca64SHariprasad Shenai 	 * servicing it.  If there are other skbs already on the list, then
2945126fca64SHariprasad Shenai 	 * either the queue is currently being processed or it's been stopped
2946126fca64SHariprasad Shenai 	 * for some reason and it'll be restarted at a later time.  Restart
2947126fca64SHariprasad Shenai 	 * paths are triggered by events like experiencing a DMA Mapping Error
2948126fca64SHariprasad Shenai 	 * or filling the Hardware TX Ring.
2949126fca64SHariprasad Shenai 	 */
2950f7917c00SJeff Kirsher 	__skb_queue_tail(&q->sendq, skb);
2951f7917c00SJeff Kirsher 	if (q->sendq.qlen == 1)
2952f7917c00SJeff Kirsher 		service_ofldq(q);
2953126fca64SHariprasad Shenai 
2954f7917c00SJeff Kirsher 	spin_unlock(&q->sendq.lock);
2955f7917c00SJeff Kirsher 	return NET_XMIT_SUCCESS;
2956f7917c00SJeff Kirsher }
2957f7917c00SJeff Kirsher 
2958f7917c00SJeff Kirsher /**
2959f7917c00SJeff Kirsher  *	restart_ofldq - restart a suspended offload queue
2960f7917c00SJeff Kirsher  *	@data: the offload queue to restart
2961f7917c00SJeff Kirsher  *
2962f7917c00SJeff Kirsher  *	Resumes transmission on a suspended Tx offload queue.
2963f7917c00SJeff Kirsher  */
2964f7917c00SJeff Kirsher static void restart_ofldq(unsigned long data)
2965f7917c00SJeff Kirsher {
2966ab677ff4SHariprasad Shenai 	struct sge_uld_txq *q = (struct sge_uld_txq *)data;
2967f7917c00SJeff Kirsher 
2968f7917c00SJeff Kirsher 	spin_lock(&q->sendq.lock);
2969f7917c00SJeff Kirsher 	q->full = 0;            /* the queue actually is completely empty now */
2970f7917c00SJeff Kirsher 	service_ofldq(q);
2971f7917c00SJeff Kirsher 	spin_unlock(&q->sendq.lock);
2972f7917c00SJeff Kirsher }
2973f7917c00SJeff Kirsher 
2974f7917c00SJeff Kirsher /**
2975f7917c00SJeff Kirsher  *	skb_txq - return the Tx queue an offload packet should use
2976f7917c00SJeff Kirsher  *	@skb: the packet
2977f7917c00SJeff Kirsher  *
2978f7917c00SJeff Kirsher  *	Returns the Tx queue an offload packet should use as indicated by bits
2979f7917c00SJeff Kirsher  *	1-15 in the packet's queue_mapping.
2980f7917c00SJeff Kirsher  */
2981f7917c00SJeff Kirsher static inline unsigned int skb_txq(const struct sk_buff *skb)
2982f7917c00SJeff Kirsher {
2983f7917c00SJeff Kirsher 	return skb->queue_mapping >> 1;
2984f7917c00SJeff Kirsher }
2985f7917c00SJeff Kirsher 
2986f7917c00SJeff Kirsher /**
2987f7917c00SJeff Kirsher  *	is_ctrl_pkt - return whether an offload packet is a control packet
2988f7917c00SJeff Kirsher  *	@skb: the packet
2989f7917c00SJeff Kirsher  *
2990f7917c00SJeff Kirsher  *	Returns whether an offload packet should use an OFLD or a CTRL
2991f7917c00SJeff Kirsher  *	Tx queue as indicated by bit 0 in the packet's queue_mapping.
2992f7917c00SJeff Kirsher  */
2993f7917c00SJeff Kirsher static inline unsigned int is_ctrl_pkt(const struct sk_buff *skb)
2994f7917c00SJeff Kirsher {
2995f7917c00SJeff Kirsher 	return skb->queue_mapping & 1;
2996f7917c00SJeff Kirsher }
2997f7917c00SJeff Kirsher 
2998ab677ff4SHariprasad Shenai static inline int uld_send(struct adapter *adap, struct sk_buff *skb,
2999ab677ff4SHariprasad Shenai 			   unsigned int tx_uld_type)
3000f7917c00SJeff Kirsher {
3001ab677ff4SHariprasad Shenai 	struct sge_uld_txq_info *txq_info;
3002ab677ff4SHariprasad Shenai 	struct sge_uld_txq *txq;
3003f7917c00SJeff Kirsher 	unsigned int idx = skb_txq(skb);
3004f7917c00SJeff Kirsher 
30054fe44dd7SKumar Sanghvi 	if (unlikely(is_ctrl_pkt(skb))) {
30064fe44dd7SKumar Sanghvi 		/* Single ctrl queue is a requirement for LE workaround path */
30074fe44dd7SKumar Sanghvi 		if (adap->tids.nsftids)
30084fe44dd7SKumar Sanghvi 			idx = 0;
3009f7917c00SJeff Kirsher 		return ctrl_xmit(&adap->sge.ctrlq[idx], skb);
30104fe44dd7SKumar Sanghvi 	}
30110d4b729dSArjun V 
30120d4b729dSArjun V 	txq_info = adap->sge.uld_txq_info[tx_uld_type];
30130d4b729dSArjun V 	if (unlikely(!txq_info)) {
30140d4b729dSArjun V 		WARN_ON(true);
30150d4b729dSArjun V 		return NET_XMIT_DROP;
30160d4b729dSArjun V 	}
30170d4b729dSArjun V 
30180d4b729dSArjun V 	txq = &txq_info->uldtxq[idx];
3019ab677ff4SHariprasad Shenai 	return ofld_xmit(txq, skb);
3020f7917c00SJeff Kirsher }
3021f7917c00SJeff Kirsher 
3022f7917c00SJeff Kirsher /**
3023f7917c00SJeff Kirsher  *	t4_ofld_send - send an offload packet
3024f7917c00SJeff Kirsher  *	@adap: the adapter
3025f7917c00SJeff Kirsher  *	@skb: the packet
3026f7917c00SJeff Kirsher  *
3027f7917c00SJeff Kirsher  *	Sends an offload packet.  We use the packet queue_mapping to select the
3028f7917c00SJeff Kirsher  *	appropriate Tx queue as follows: bit 0 indicates whether the packet
3029f7917c00SJeff Kirsher  *	should be sent as regular or control, bits 1-15 select the queue.
3030f7917c00SJeff Kirsher  */
3031f7917c00SJeff Kirsher int t4_ofld_send(struct adapter *adap, struct sk_buff *skb)
3032f7917c00SJeff Kirsher {
3033f7917c00SJeff Kirsher 	int ret;
3034f7917c00SJeff Kirsher 
3035f7917c00SJeff Kirsher 	local_bh_disable();
3036ab677ff4SHariprasad Shenai 	ret = uld_send(adap, skb, CXGB4_TX_OFLD);
3037f7917c00SJeff Kirsher 	local_bh_enable();
3038f7917c00SJeff Kirsher 	return ret;
3039f7917c00SJeff Kirsher }
3040f7917c00SJeff Kirsher 
3041f7917c00SJeff Kirsher /**
3042f7917c00SJeff Kirsher  *	cxgb4_ofld_send - send an offload packet
3043f7917c00SJeff Kirsher  *	@dev: the net device
3044f7917c00SJeff Kirsher  *	@skb: the packet
3045f7917c00SJeff Kirsher  *
3046f7917c00SJeff Kirsher  *	Sends an offload packet.  This is an exported version of @t4_ofld_send,
3047f7917c00SJeff Kirsher  *	intended for ULDs.
3048f7917c00SJeff Kirsher  */
3049f7917c00SJeff Kirsher int cxgb4_ofld_send(struct net_device *dev, struct sk_buff *skb)
3050f7917c00SJeff Kirsher {
3051f7917c00SJeff Kirsher 	return t4_ofld_send(netdev2adap(dev), skb);
3052f7917c00SJeff Kirsher }
3053f7917c00SJeff Kirsher EXPORT_SYMBOL(cxgb4_ofld_send);
3054f7917c00SJeff Kirsher 
3055e383f248SAtul Gupta static void *inline_tx_header(const void *src,
3056e383f248SAtul Gupta 			      const struct sge_txq *q,
3057e383f248SAtul Gupta 			      void *pos, int length)
3058e383f248SAtul Gupta {
3059e383f248SAtul Gupta 	int left = (void *)q->stat - pos;
3060e383f248SAtul Gupta 	u64 *p;
3061e383f248SAtul Gupta 
3062e383f248SAtul Gupta 	if (likely(length <= left)) {
3063e383f248SAtul Gupta 		memcpy(pos, src, length);
3064e383f248SAtul Gupta 		pos += length;
3065e383f248SAtul Gupta 	} else {
3066e383f248SAtul Gupta 		memcpy(pos, src, left);
3067e383f248SAtul Gupta 		memcpy(q->desc, src + left, length - left);
3068e383f248SAtul Gupta 		pos = (void *)q->desc + (length - left);
3069e383f248SAtul Gupta 	}
3070e383f248SAtul Gupta 	/* 0-pad to multiple of 16 */
3071e383f248SAtul Gupta 	p = PTR_ALIGN(pos, 8);
3072e383f248SAtul Gupta 	if ((uintptr_t)p & 8) {
3073e383f248SAtul Gupta 		*p = 0;
3074e383f248SAtul Gupta 		return p + 1;
3075e383f248SAtul Gupta 	}
3076e383f248SAtul Gupta 	return p;
3077e383f248SAtul Gupta }
3078e383f248SAtul Gupta 
3079e383f248SAtul Gupta /**
3080e383f248SAtul Gupta  *      ofld_xmit_direct - copy a WR into offload queue
3081e383f248SAtul Gupta  *      @q: the Tx offload queue
3082e383f248SAtul Gupta  *      @src: location of WR
3083e383f248SAtul Gupta  *      @len: WR length
3084e383f248SAtul Gupta  *
3085e383f248SAtul Gupta  *      Copy an immediate WR into an uncontended SGE offload queue.
3086e383f248SAtul Gupta  */
3087e383f248SAtul Gupta static int ofld_xmit_direct(struct sge_uld_txq *q, const void *src,
3088e383f248SAtul Gupta 			    unsigned int len)
3089e383f248SAtul Gupta {
3090e383f248SAtul Gupta 	unsigned int ndesc;
3091e383f248SAtul Gupta 	int credits;
3092e383f248SAtul Gupta 	u64 *pos;
3093e383f248SAtul Gupta 
3094e383f248SAtul Gupta 	/* Use the lower limit as the cut-off */
3095e383f248SAtul Gupta 	if (len > MAX_IMM_OFLD_TX_DATA_WR_LEN) {
3096e383f248SAtul Gupta 		WARN_ON(1);
3097e383f248SAtul Gupta 		return NET_XMIT_DROP;
3098e383f248SAtul Gupta 	}
3099e383f248SAtul Gupta 
3100e383f248SAtul Gupta 	/* Don't return NET_XMIT_CN here as the current
3101e383f248SAtul Gupta 	 * implementation doesn't queue the request
3102e383f248SAtul Gupta 	 * using an skb when the following conditions not met
3103e383f248SAtul Gupta 	 */
3104e383f248SAtul Gupta 	if (!spin_trylock(&q->sendq.lock))
3105e383f248SAtul Gupta 		return NET_XMIT_DROP;
3106e383f248SAtul Gupta 
3107e383f248SAtul Gupta 	if (q->full || !skb_queue_empty(&q->sendq) ||
3108e383f248SAtul Gupta 	    q->service_ofldq_running) {
3109e383f248SAtul Gupta 		spin_unlock(&q->sendq.lock);
3110e383f248SAtul Gupta 		return NET_XMIT_DROP;
3111e383f248SAtul Gupta 	}
3112e383f248SAtul Gupta 	ndesc = flits_to_desc(DIV_ROUND_UP(len, 8));
3113e383f248SAtul Gupta 	credits = txq_avail(&q->q) - ndesc;
3114e383f248SAtul Gupta 	pos = (u64 *)&q->q.desc[q->q.pidx];
3115e383f248SAtul Gupta 
3116e383f248SAtul Gupta 	/* ofldtxq_stop modifies WR header in-situ */
3117e383f248SAtul Gupta 	inline_tx_header(src, &q->q, pos, len);
3118e383f248SAtul Gupta 	if (unlikely(credits < TXQ_STOP_THRES))
3119e383f248SAtul Gupta 		ofldtxq_stop(q, (struct fw_wr_hdr *)pos);
3120e383f248SAtul Gupta 	txq_advance(&q->q, ndesc);
3121e383f248SAtul Gupta 	cxgb4_ring_tx_db(q->adap, &q->q, ndesc);
3122e383f248SAtul Gupta 
3123e383f248SAtul Gupta 	spin_unlock(&q->sendq.lock);
3124e383f248SAtul Gupta 	return NET_XMIT_SUCCESS;
3125e383f248SAtul Gupta }
3126e383f248SAtul Gupta 
3127e383f248SAtul Gupta int cxgb4_immdata_send(struct net_device *dev, unsigned int idx,
3128e383f248SAtul Gupta 		       const void *src, unsigned int len)
3129e383f248SAtul Gupta {
3130e383f248SAtul Gupta 	struct sge_uld_txq_info *txq_info;
3131e383f248SAtul Gupta 	struct sge_uld_txq *txq;
3132e383f248SAtul Gupta 	struct adapter *adap;
3133e383f248SAtul Gupta 	int ret;
3134e383f248SAtul Gupta 
3135e383f248SAtul Gupta 	adap = netdev2adap(dev);
3136e383f248SAtul Gupta 
3137e383f248SAtul Gupta 	local_bh_disable();
3138e383f248SAtul Gupta 	txq_info = adap->sge.uld_txq_info[CXGB4_TX_OFLD];
3139e383f248SAtul Gupta 	if (unlikely(!txq_info)) {
3140e383f248SAtul Gupta 		WARN_ON(true);
3141e383f248SAtul Gupta 		local_bh_enable();
3142e383f248SAtul Gupta 		return NET_XMIT_DROP;
3143e383f248SAtul Gupta 	}
3144e383f248SAtul Gupta 	txq = &txq_info->uldtxq[idx];
3145e383f248SAtul Gupta 
3146e383f248SAtul Gupta 	ret = ofld_xmit_direct(txq, src, len);
3147e383f248SAtul Gupta 	local_bh_enable();
3148e383f248SAtul Gupta 	return net_xmit_eval(ret);
3149e383f248SAtul Gupta }
3150e383f248SAtul Gupta EXPORT_SYMBOL(cxgb4_immdata_send);
3151e383f248SAtul Gupta 
3152ab677ff4SHariprasad Shenai /**
3153ab677ff4SHariprasad Shenai  *	t4_crypto_send - send crypto packet
3154ab677ff4SHariprasad Shenai  *	@adap: the adapter
3155ab677ff4SHariprasad Shenai  *	@skb: the packet
3156ab677ff4SHariprasad Shenai  *
3157ab677ff4SHariprasad Shenai  *	Sends crypto packet.  We use the packet queue_mapping to select the
3158ab677ff4SHariprasad Shenai  *	appropriate Tx queue as follows: bit 0 indicates whether the packet
3159ab677ff4SHariprasad Shenai  *	should be sent as regular or control, bits 1-15 select the queue.
3160ab677ff4SHariprasad Shenai  */
3161ab677ff4SHariprasad Shenai static int t4_crypto_send(struct adapter *adap, struct sk_buff *skb)
3162ab677ff4SHariprasad Shenai {
3163ab677ff4SHariprasad Shenai 	int ret;
3164ab677ff4SHariprasad Shenai 
3165ab677ff4SHariprasad Shenai 	local_bh_disable();
3166ab677ff4SHariprasad Shenai 	ret = uld_send(adap, skb, CXGB4_TX_CRYPTO);
3167ab677ff4SHariprasad Shenai 	local_bh_enable();
3168ab677ff4SHariprasad Shenai 	return ret;
3169ab677ff4SHariprasad Shenai }
3170ab677ff4SHariprasad Shenai 
3171ab677ff4SHariprasad Shenai /**
3172ab677ff4SHariprasad Shenai  *	cxgb4_crypto_send - send crypto packet
3173ab677ff4SHariprasad Shenai  *	@dev: the net device
3174ab677ff4SHariprasad Shenai  *	@skb: the packet
3175ab677ff4SHariprasad Shenai  *
3176ab677ff4SHariprasad Shenai  *	Sends crypto packet.  This is an exported version of @t4_crypto_send,
3177ab677ff4SHariprasad Shenai  *	intended for ULDs.
3178ab677ff4SHariprasad Shenai  */
3179ab677ff4SHariprasad Shenai int cxgb4_crypto_send(struct net_device *dev, struct sk_buff *skb)
3180ab677ff4SHariprasad Shenai {
3181ab677ff4SHariprasad Shenai 	return t4_crypto_send(netdev2adap(dev), skb);
3182ab677ff4SHariprasad Shenai }
3183ab677ff4SHariprasad Shenai EXPORT_SYMBOL(cxgb4_crypto_send);
3184ab677ff4SHariprasad Shenai 
3185e91b0f24SIan Campbell static inline void copy_frags(struct sk_buff *skb,
3186f7917c00SJeff Kirsher 			      const struct pkt_gl *gl, unsigned int offset)
3187f7917c00SJeff Kirsher {
3188e91b0f24SIan Campbell 	int i;
3189f7917c00SJeff Kirsher 
3190f7917c00SJeff Kirsher 	/* usually there's just one frag */
3191e91b0f24SIan Campbell 	__skb_fill_page_desc(skb, 0, gl->frags[0].page,
3192e91b0f24SIan Campbell 			     gl->frags[0].offset + offset,
3193e91b0f24SIan Campbell 			     gl->frags[0].size - offset);
3194e91b0f24SIan Campbell 	skb_shinfo(skb)->nr_frags = gl->nfrags;
3195e91b0f24SIan Campbell 	for (i = 1; i < gl->nfrags; i++)
3196e91b0f24SIan Campbell 		__skb_fill_page_desc(skb, i, gl->frags[i].page,
3197e91b0f24SIan Campbell 				     gl->frags[i].offset,
3198e91b0f24SIan Campbell 				     gl->frags[i].size);
3199f7917c00SJeff Kirsher 
3200f7917c00SJeff Kirsher 	/* get a reference to the last page, we don't own it */
3201e91b0f24SIan Campbell 	get_page(gl->frags[gl->nfrags - 1].page);
3202f7917c00SJeff Kirsher }
3203f7917c00SJeff Kirsher 
3204f7917c00SJeff Kirsher /**
3205f7917c00SJeff Kirsher  *	cxgb4_pktgl_to_skb - build an sk_buff from a packet gather list
3206f7917c00SJeff Kirsher  *	@gl: the gather list
3207f7917c00SJeff Kirsher  *	@skb_len: size of sk_buff main body if it carries fragments
3208f7917c00SJeff Kirsher  *	@pull_len: amount of data to move to the sk_buff's main body
3209f7917c00SJeff Kirsher  *
3210f7917c00SJeff Kirsher  *	Builds an sk_buff from the given packet gather list.  Returns the
3211f7917c00SJeff Kirsher  *	sk_buff or %NULL if sk_buff allocation failed.
3212f7917c00SJeff Kirsher  */
3213f7917c00SJeff Kirsher struct sk_buff *cxgb4_pktgl_to_skb(const struct pkt_gl *gl,
3214f7917c00SJeff Kirsher 				   unsigned int skb_len, unsigned int pull_len)
3215f7917c00SJeff Kirsher {
3216f7917c00SJeff Kirsher 	struct sk_buff *skb;
3217f7917c00SJeff Kirsher 
3218f7917c00SJeff Kirsher 	/*
3219f7917c00SJeff Kirsher 	 * Below we rely on RX_COPY_THRES being less than the smallest Rx buffer
3220f7917c00SJeff Kirsher 	 * size, which is expected since buffers are at least PAGE_SIZEd.
3221f7917c00SJeff Kirsher 	 * In this case packets up to RX_COPY_THRES have only one fragment.
3222f7917c00SJeff Kirsher 	 */
3223f7917c00SJeff Kirsher 	if (gl->tot_len <= RX_COPY_THRES) {
3224f7917c00SJeff Kirsher 		skb = dev_alloc_skb(gl->tot_len);
3225f7917c00SJeff Kirsher 		if (unlikely(!skb))
3226f7917c00SJeff Kirsher 			goto out;
3227f7917c00SJeff Kirsher 		__skb_put(skb, gl->tot_len);
3228f7917c00SJeff Kirsher 		skb_copy_to_linear_data(skb, gl->va, gl->tot_len);
3229f7917c00SJeff Kirsher 	} else {
3230f7917c00SJeff Kirsher 		skb = dev_alloc_skb(skb_len);
3231f7917c00SJeff Kirsher 		if (unlikely(!skb))
3232f7917c00SJeff Kirsher 			goto out;
3233f7917c00SJeff Kirsher 		__skb_put(skb, pull_len);
3234f7917c00SJeff Kirsher 		skb_copy_to_linear_data(skb, gl->va, pull_len);
3235f7917c00SJeff Kirsher 
3236e91b0f24SIan Campbell 		copy_frags(skb, gl, pull_len);
3237f7917c00SJeff Kirsher 		skb->len = gl->tot_len;
3238f7917c00SJeff Kirsher 		skb->data_len = skb->len - pull_len;
3239f7917c00SJeff Kirsher 		skb->truesize += skb->data_len;
3240f7917c00SJeff Kirsher 	}
3241f7917c00SJeff Kirsher out:	return skb;
3242f7917c00SJeff Kirsher }
3243f7917c00SJeff Kirsher EXPORT_SYMBOL(cxgb4_pktgl_to_skb);
3244f7917c00SJeff Kirsher 
3245f7917c00SJeff Kirsher /**
3246f7917c00SJeff Kirsher  *	t4_pktgl_free - free a packet gather list
3247f7917c00SJeff Kirsher  *	@gl: the gather list
3248f7917c00SJeff Kirsher  *
3249f7917c00SJeff Kirsher  *	Releases the pages of a packet gather list.  We do not own the last
3250f7917c00SJeff Kirsher  *	page on the list and do not free it.
3251f7917c00SJeff Kirsher  */
3252f7917c00SJeff Kirsher static void t4_pktgl_free(const struct pkt_gl *gl)
3253f7917c00SJeff Kirsher {
3254f7917c00SJeff Kirsher 	int n;
3255e91b0f24SIan Campbell 	const struct page_frag *p;
3256f7917c00SJeff Kirsher 
3257f7917c00SJeff Kirsher 	for (p = gl->frags, n = gl->nfrags - 1; n--; p++)
3258f7917c00SJeff Kirsher 		put_page(p->page);
3259f7917c00SJeff Kirsher }
3260f7917c00SJeff Kirsher 
3261f7917c00SJeff Kirsher /*
3262f7917c00SJeff Kirsher  * Process an MPS trace packet.  Give it an unused protocol number so it won't
3263f7917c00SJeff Kirsher  * be delivered to anyone and send it to the stack for capture.
3264f7917c00SJeff Kirsher  */
3265f7917c00SJeff Kirsher static noinline int handle_trace_pkt(struct adapter *adap,
3266f7917c00SJeff Kirsher 				     const struct pkt_gl *gl)
3267f7917c00SJeff Kirsher {
3268f7917c00SJeff Kirsher 	struct sk_buff *skb;
3269f7917c00SJeff Kirsher 
3270f7917c00SJeff Kirsher 	skb = cxgb4_pktgl_to_skb(gl, RX_PULL_LEN, RX_PULL_LEN);
3271f7917c00SJeff Kirsher 	if (unlikely(!skb)) {
3272f7917c00SJeff Kirsher 		t4_pktgl_free(gl);
3273f7917c00SJeff Kirsher 		return 0;
3274f7917c00SJeff Kirsher 	}
3275f7917c00SJeff Kirsher 
3276d14807ddSHariprasad Shenai 	if (is_t4(adap->params.chip))
32770a57a536SSantosh Rastapur 		__skb_pull(skb, sizeof(struct cpl_trace_pkt));
32780a57a536SSantosh Rastapur 	else
32790a57a536SSantosh Rastapur 		__skb_pull(skb, sizeof(struct cpl_t5_trace_pkt));
32800a57a536SSantosh Rastapur 
3281f7917c00SJeff Kirsher 	skb_reset_mac_header(skb);
3282f7917c00SJeff Kirsher 	skb->protocol = htons(0xffff);
3283f7917c00SJeff Kirsher 	skb->dev = adap->port[0];
3284f7917c00SJeff Kirsher 	netif_receive_skb(skb);
3285f7917c00SJeff Kirsher 	return 0;
3286f7917c00SJeff Kirsher }
3287f7917c00SJeff Kirsher 
32885e2a5ebcSHariprasad Shenai /**
32895e2a5ebcSHariprasad Shenai  * cxgb4_sgetim_to_hwtstamp - convert sge time stamp to hw time stamp
32905e2a5ebcSHariprasad Shenai  * @adap: the adapter
32915e2a5ebcSHariprasad Shenai  * @hwtstamps: time stamp structure to update
32925e2a5ebcSHariprasad Shenai  * @sgetstamp: 60bit iqe timestamp
32935e2a5ebcSHariprasad Shenai  *
32945e2a5ebcSHariprasad Shenai  * Every ingress queue entry has the 60-bit timestamp, convert that timestamp
32955e2a5ebcSHariprasad Shenai  * which is in Core Clock ticks into ktime_t and assign it
32965e2a5ebcSHariprasad Shenai  **/
32975e2a5ebcSHariprasad Shenai static void cxgb4_sgetim_to_hwtstamp(struct adapter *adap,
32985e2a5ebcSHariprasad Shenai 				     struct skb_shared_hwtstamps *hwtstamps,
32995e2a5ebcSHariprasad Shenai 				     u64 sgetstamp)
33005e2a5ebcSHariprasad Shenai {
33015e2a5ebcSHariprasad Shenai 	u64 ns;
33025e2a5ebcSHariprasad Shenai 	u64 tmp = (sgetstamp * 1000 * 1000 + adap->params.vpd.cclk / 2);
33035e2a5ebcSHariprasad Shenai 
33045e2a5ebcSHariprasad Shenai 	ns = div_u64(tmp, adap->params.vpd.cclk);
33055e2a5ebcSHariprasad Shenai 
33065e2a5ebcSHariprasad Shenai 	memset(hwtstamps, 0, sizeof(*hwtstamps));
33075e2a5ebcSHariprasad Shenai 	hwtstamps->hwtstamp = ns_to_ktime(ns);
33085e2a5ebcSHariprasad Shenai }
33095e2a5ebcSHariprasad Shenai 
3310f7917c00SJeff Kirsher static void do_gro(struct sge_eth_rxq *rxq, const struct pkt_gl *gl,
3311c50ae55eSGanesh Goudar 		   const struct cpl_rx_pkt *pkt, unsigned long tnl_hdr_len)
3312f7917c00SJeff Kirsher {
331352367a76SVipul Pandya 	struct adapter *adapter = rxq->rspq.adap;
331452367a76SVipul Pandya 	struct sge *s = &adapter->sge;
33155e2a5ebcSHariprasad Shenai 	struct port_info *pi;
3316f7917c00SJeff Kirsher 	int ret;
3317f7917c00SJeff Kirsher 	struct sk_buff *skb;
3318f7917c00SJeff Kirsher 
3319f7917c00SJeff Kirsher 	skb = napi_get_frags(&rxq->rspq.napi);
3320f7917c00SJeff Kirsher 	if (unlikely(!skb)) {
3321f7917c00SJeff Kirsher 		t4_pktgl_free(gl);
3322f7917c00SJeff Kirsher 		rxq->stats.rx_drops++;
3323f7917c00SJeff Kirsher 		return;
3324f7917c00SJeff Kirsher 	}
3325f7917c00SJeff Kirsher 
332652367a76SVipul Pandya 	copy_frags(skb, gl, s->pktshift);
3327c50ae55eSGanesh Goudar 	if (tnl_hdr_len)
3328c50ae55eSGanesh Goudar 		skb->csum_level = 1;
332952367a76SVipul Pandya 	skb->len = gl->tot_len - s->pktshift;
3330f7917c00SJeff Kirsher 	skb->data_len = skb->len;
3331f7917c00SJeff Kirsher 	skb->truesize += skb->data_len;
3332f7917c00SJeff Kirsher 	skb->ip_summed = CHECKSUM_UNNECESSARY;
3333f7917c00SJeff Kirsher 	skb_record_rx_queue(skb, rxq->rspq.idx);
33345e2a5ebcSHariprasad Shenai 	pi = netdev_priv(skb->dev);
33355e2a5ebcSHariprasad Shenai 	if (pi->rxtstamp)
33365e2a5ebcSHariprasad Shenai 		cxgb4_sgetim_to_hwtstamp(adapter, skb_hwtstamps(skb),
33375e2a5ebcSHariprasad Shenai 					 gl->sgetstamp);
3338f7917c00SJeff Kirsher 	if (rxq->rspq.netdev->features & NETIF_F_RXHASH)
33398264989cSTom Herbert 		skb_set_hash(skb, (__force u32)pkt->rsshdr.hash_val,
33408264989cSTom Herbert 			     PKT_HASH_TYPE_L3);
3341f7917c00SJeff Kirsher 
3342f7917c00SJeff Kirsher 	if (unlikely(pkt->vlan_ex)) {
334386a9bad3SPatrick McHardy 		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), ntohs(pkt->vlan));
3344f7917c00SJeff Kirsher 		rxq->stats.vlan_ex++;
3345f7917c00SJeff Kirsher 	}
3346f7917c00SJeff Kirsher 	ret = napi_gro_frags(&rxq->rspq.napi);
3347f7917c00SJeff Kirsher 	if (ret == GRO_HELD)
3348f7917c00SJeff Kirsher 		rxq->stats.lro_pkts++;
3349f7917c00SJeff Kirsher 	else if (ret == GRO_MERGED || ret == GRO_MERGED_FREE)
3350f7917c00SJeff Kirsher 		rxq->stats.lro_merged++;
3351f7917c00SJeff Kirsher 	rxq->stats.pkts++;
3352f7917c00SJeff Kirsher 	rxq->stats.rx_cso++;
3353f7917c00SJeff Kirsher }
3354f7917c00SJeff Kirsher 
3355a4569504SAtul Gupta enum {
3356a4569504SAtul Gupta 	RX_NON_PTP_PKT = 0,
3357a4569504SAtul Gupta 	RX_PTP_PKT_SUC = 1,
3358a4569504SAtul Gupta 	RX_PTP_PKT_ERR = 2
3359a4569504SAtul Gupta };
3360a4569504SAtul Gupta 
3361a4569504SAtul Gupta /**
3362a4569504SAtul Gupta  *     t4_systim_to_hwstamp - read hardware time stamp
336329bbf5d7SRahul Lakkireddy  *     @adapter: the adapter
3364a4569504SAtul Gupta  *     @skb: the packet
3365a4569504SAtul Gupta  *
3366a4569504SAtul Gupta  *     Read Time Stamp from MPS packet and insert in skb which
3367a4569504SAtul Gupta  *     is forwarded to PTP application
3368a4569504SAtul Gupta  */
3369a4569504SAtul Gupta static noinline int t4_systim_to_hwstamp(struct adapter *adapter,
3370a4569504SAtul Gupta 					 struct sk_buff *skb)
3371a4569504SAtul Gupta {
3372a4569504SAtul Gupta 	struct skb_shared_hwtstamps *hwtstamps;
3373a4569504SAtul Gupta 	struct cpl_rx_mps_pkt *cpl = NULL;
3374a4569504SAtul Gupta 	unsigned char *data;
3375a4569504SAtul Gupta 	int offset;
3376a4569504SAtul Gupta 
3377a4569504SAtul Gupta 	cpl = (struct cpl_rx_mps_pkt *)skb->data;
3378a4569504SAtul Gupta 	if (!(CPL_RX_MPS_PKT_TYPE_G(ntohl(cpl->op_to_r1_hi)) &
3379a4569504SAtul Gupta 	     X_CPL_RX_MPS_PKT_TYPE_PTP))
3380a4569504SAtul Gupta 		return RX_PTP_PKT_ERR;
3381a4569504SAtul Gupta 
3382a4569504SAtul Gupta 	data = skb->data + sizeof(*cpl);
3383a4569504SAtul Gupta 	skb_pull(skb, 2 * sizeof(u64) + sizeof(struct cpl_rx_mps_pkt));
3384a4569504SAtul Gupta 	offset = ETH_HLEN + IPV4_HLEN(skb->data) + UDP_HLEN;
3385a4569504SAtul Gupta 	if (skb->len < offset + OFF_PTP_SEQUENCE_ID + sizeof(short))
3386a4569504SAtul Gupta 		return RX_PTP_PKT_ERR;
3387a4569504SAtul Gupta 
3388a4569504SAtul Gupta 	hwtstamps = skb_hwtstamps(skb);
3389a4569504SAtul Gupta 	memset(hwtstamps, 0, sizeof(*hwtstamps));
3390589b1c9cSRahul Lakkireddy 	hwtstamps->hwtstamp = ns_to_ktime(get_unaligned_be64(data));
3391a4569504SAtul Gupta 
3392a4569504SAtul Gupta 	return RX_PTP_PKT_SUC;
3393a4569504SAtul Gupta }
3394a4569504SAtul Gupta 
3395a4569504SAtul Gupta /**
3396a4569504SAtul Gupta  *     t4_rx_hststamp - Recv PTP Event Message
339729bbf5d7SRahul Lakkireddy  *     @adapter: the adapter
3398a4569504SAtul Gupta  *     @rsp: the response queue descriptor holding the RX_PKT message
339929bbf5d7SRahul Lakkireddy  *     @rxq: the response queue holding the RX_PKT message
3400a4569504SAtul Gupta  *     @skb: the packet
3401a4569504SAtul Gupta  *
3402a4569504SAtul Gupta  *     PTP enabled and MPS packet, read HW timestamp
3403a4569504SAtul Gupta  */
3404a4569504SAtul Gupta static int t4_rx_hststamp(struct adapter *adapter, const __be64 *rsp,
3405a4569504SAtul Gupta 			  struct sge_eth_rxq *rxq, struct sk_buff *skb)
3406a4569504SAtul Gupta {
3407a4569504SAtul Gupta 	int ret;
3408a4569504SAtul Gupta 
3409a4569504SAtul Gupta 	if (unlikely((*(u8 *)rsp == CPL_RX_MPS_PKT) &&
3410a4569504SAtul Gupta 		     !is_t4(adapter->params.chip))) {
3411a4569504SAtul Gupta 		ret = t4_systim_to_hwstamp(adapter, skb);
3412a4569504SAtul Gupta 		if (ret == RX_PTP_PKT_ERR) {
3413a4569504SAtul Gupta 			kfree_skb(skb);
3414a4569504SAtul Gupta 			rxq->stats.rx_drops++;
3415a4569504SAtul Gupta 		}
3416a4569504SAtul Gupta 		return ret;
3417a4569504SAtul Gupta 	}
3418a4569504SAtul Gupta 	return RX_NON_PTP_PKT;
3419a4569504SAtul Gupta }
3420a4569504SAtul Gupta 
3421a4569504SAtul Gupta /**
3422a4569504SAtul Gupta  *      t4_tx_hststamp - Loopback PTP Transmit Event Message
342329bbf5d7SRahul Lakkireddy  *      @adapter: the adapter
3424a4569504SAtul Gupta  *      @skb: the packet
3425a4569504SAtul Gupta  *      @dev: the ingress net device
3426a4569504SAtul Gupta  *
3427a4569504SAtul Gupta  *      Read hardware timestamp for the loopback PTP Tx event message
3428a4569504SAtul Gupta  */
3429a4569504SAtul Gupta static int t4_tx_hststamp(struct adapter *adapter, struct sk_buff *skb,
3430a4569504SAtul Gupta 			  struct net_device *dev)
3431a4569504SAtul Gupta {
3432a4569504SAtul Gupta 	struct port_info *pi = netdev_priv(dev);
3433a4569504SAtul Gupta 
3434a4569504SAtul Gupta 	if (!is_t4(adapter->params.chip) && adapter->ptp_tx_skb) {
3435a4569504SAtul Gupta 		cxgb4_ptp_read_hwstamp(adapter, pi);
3436a4569504SAtul Gupta 		kfree_skb(skb);
3437a4569504SAtul Gupta 		return 0;
3438a4569504SAtul Gupta 	}
3439a4569504SAtul Gupta 	return 1;
3440a4569504SAtul Gupta }
3441a4569504SAtul Gupta 
3442f7917c00SJeff Kirsher /**
3443d429005fSVishal Kulkarni  *	t4_tx_completion_handler - handle CPL_SGE_EGR_UPDATE messages
3444d429005fSVishal Kulkarni  *	@rspq: Ethernet RX Response Queue associated with Ethernet TX Queue
3445d429005fSVishal Kulkarni  *	@rsp: Response Entry pointer into Response Queue
3446d429005fSVishal Kulkarni  *	@gl: Gather List pointer
3447d429005fSVishal Kulkarni  *
3448d429005fSVishal Kulkarni  *	For adapters which support the SGE Doorbell Queue Timer facility,
3449d429005fSVishal Kulkarni  *	we configure the Ethernet TX Queues to send CIDX Updates to the
3450d429005fSVishal Kulkarni  *	Associated Ethernet RX Response Queue with CPL_SGE_EGR_UPDATE
3451d429005fSVishal Kulkarni  *	messages.  This adds a small load to PCIe Link RX bandwidth and,
3452d429005fSVishal Kulkarni  *	potentially, higher CPU Interrupt load, but allows us to respond
3453d429005fSVishal Kulkarni  *	much more quickly to the CIDX Updates.  This is important for
3454d429005fSVishal Kulkarni  *	Upper Layer Software which isn't willing to have a large amount
3455d429005fSVishal Kulkarni  *	of TX Data outstanding before receiving DMA Completions.
3456d429005fSVishal Kulkarni  */
3457d429005fSVishal Kulkarni static void t4_tx_completion_handler(struct sge_rspq *rspq,
3458d429005fSVishal Kulkarni 				     const __be64 *rsp,
3459d429005fSVishal Kulkarni 				     const struct pkt_gl *gl)
3460d429005fSVishal Kulkarni {
3461d429005fSVishal Kulkarni 	u8 opcode = ((const struct rss_header *)rsp)->opcode;
3462d429005fSVishal Kulkarni 	struct port_info *pi = netdev_priv(rspq->netdev);
3463d429005fSVishal Kulkarni 	struct adapter *adapter = rspq->adap;
3464d429005fSVishal Kulkarni 	struct sge *s = &adapter->sge;
3465d429005fSVishal Kulkarni 	struct sge_eth_txq *txq;
3466d429005fSVishal Kulkarni 
3467d429005fSVishal Kulkarni 	/* skip RSS header */
3468d429005fSVishal Kulkarni 	rsp++;
3469d429005fSVishal Kulkarni 
3470d429005fSVishal Kulkarni 	/* FW can send EGR_UPDATEs encapsulated in a CPL_FW4_MSG.
3471d429005fSVishal Kulkarni 	 */
3472d429005fSVishal Kulkarni 	if (unlikely(opcode == CPL_FW4_MSG &&
3473d429005fSVishal Kulkarni 		     ((const struct cpl_fw4_msg *)rsp)->type ==
3474d429005fSVishal Kulkarni 							FW_TYPE_RSSCPL)) {
3475d429005fSVishal Kulkarni 		rsp++;
3476d429005fSVishal Kulkarni 		opcode = ((const struct rss_header *)rsp)->opcode;
3477d429005fSVishal Kulkarni 		rsp++;
3478d429005fSVishal Kulkarni 	}
3479d429005fSVishal Kulkarni 
3480d429005fSVishal Kulkarni 	if (unlikely(opcode != CPL_SGE_EGR_UPDATE)) {
3481d429005fSVishal Kulkarni 		pr_info("%s: unexpected FW4/CPL %#x on Rx queue\n",
3482d429005fSVishal Kulkarni 			__func__, opcode);
3483d429005fSVishal Kulkarni 		return;
3484d429005fSVishal Kulkarni 	}
3485d429005fSVishal Kulkarni 
3486d429005fSVishal Kulkarni 	txq = &s->ethtxq[pi->first_qset + rspq->idx];
3487d429005fSVishal Kulkarni 	t4_sge_eth_txq_egress_update(adapter, txq, -1);
3488d429005fSVishal Kulkarni }
3489d429005fSVishal Kulkarni 
34907235ffaeSVishal Kulkarni static int cxgb4_validate_lb_pkt(struct port_info *pi, const struct pkt_gl *si)
34917235ffaeSVishal Kulkarni {
34927235ffaeSVishal Kulkarni 	struct adapter *adap = pi->adapter;
34937235ffaeSVishal Kulkarni 	struct cxgb4_ethtool_lb_test *lb;
34947235ffaeSVishal Kulkarni 	struct sge *s = &adap->sge;
34957235ffaeSVishal Kulkarni 	struct net_device *netdev;
34967235ffaeSVishal Kulkarni 	u8 *data;
34977235ffaeSVishal Kulkarni 	int i;
34987235ffaeSVishal Kulkarni 
34997235ffaeSVishal Kulkarni 	netdev = adap->port[pi->port_id];
35007235ffaeSVishal Kulkarni 	lb = &pi->ethtool_lb;
35017235ffaeSVishal Kulkarni 	data = si->va + s->pktshift;
35027235ffaeSVishal Kulkarni 
35037235ffaeSVishal Kulkarni 	i = ETH_ALEN;
35047235ffaeSVishal Kulkarni 	if (!ether_addr_equal(data + i, netdev->dev_addr))
35057235ffaeSVishal Kulkarni 		return -1;
35067235ffaeSVishal Kulkarni 
35077235ffaeSVishal Kulkarni 	i += ETH_ALEN;
35087235ffaeSVishal Kulkarni 	if (strcmp(&data[i], CXGB4_SELFTEST_LB_STR))
35097235ffaeSVishal Kulkarni 		lb->result = -EIO;
35107235ffaeSVishal Kulkarni 
35117235ffaeSVishal Kulkarni 	complete(&lb->completion);
35127235ffaeSVishal Kulkarni 	return 0;
35137235ffaeSVishal Kulkarni }
35147235ffaeSVishal Kulkarni 
3515d429005fSVishal Kulkarni /**
3516f7917c00SJeff Kirsher  *	t4_ethrx_handler - process an ingress ethernet packet
3517f7917c00SJeff Kirsher  *	@q: the response queue that received the packet
3518f7917c00SJeff Kirsher  *	@rsp: the response queue descriptor holding the RX_PKT message
3519f7917c00SJeff Kirsher  *	@si: the gather list of packet fragments
3520f7917c00SJeff Kirsher  *
3521f7917c00SJeff Kirsher  *	Process an ingress ethernet packet and deliver it to the stack.
3522f7917c00SJeff Kirsher  */
3523f7917c00SJeff Kirsher int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp,
3524f7917c00SJeff Kirsher 		     const struct pkt_gl *si)
3525f7917c00SJeff Kirsher {
3526f7917c00SJeff Kirsher 	bool csum_ok;
3527f7917c00SJeff Kirsher 	struct sk_buff *skb;
3528f7917c00SJeff Kirsher 	const struct cpl_rx_pkt *pkt;
3529f7917c00SJeff Kirsher 	struct sge_eth_rxq *rxq = container_of(q, struct sge_eth_rxq, rspq);
3530a4569504SAtul Gupta 	struct adapter *adapter = q->adap;
353152367a76SVipul Pandya 	struct sge *s = &q->adap->sge;
3532d14807ddSHariprasad Shenai 	int cpl_trace_pkt = is_t4(q->adap->params.chip) ?
35330a57a536SSantosh Rastapur 			    CPL_TRACE_PKT : CPL_TRACE_PKT_T5;
3534c50ae55eSGanesh Goudar 	u16 err_vec, tnl_hdr_len = 0;
353584a200b3SVarun Prakash 	struct port_info *pi;
3536a4569504SAtul Gupta 	int ret = 0;
3537f7917c00SJeff Kirsher 
35387235ffaeSVishal Kulkarni 	pi = netdev_priv(q->netdev);
3539d429005fSVishal Kulkarni 	/* If we're looking at TX Queue CIDX Update, handle that separately
3540d429005fSVishal Kulkarni 	 * and return.
3541d429005fSVishal Kulkarni 	 */
3542d429005fSVishal Kulkarni 	if (unlikely((*(u8 *)rsp == CPL_FW4_MSG) ||
3543d429005fSVishal Kulkarni 		     (*(u8 *)rsp == CPL_SGE_EGR_UPDATE))) {
3544d429005fSVishal Kulkarni 		t4_tx_completion_handler(q, rsp, si);
3545d429005fSVishal Kulkarni 		return 0;
3546d429005fSVishal Kulkarni 	}
3547d429005fSVishal Kulkarni 
35480a57a536SSantosh Rastapur 	if (unlikely(*(u8 *)rsp == cpl_trace_pkt))
3549f7917c00SJeff Kirsher 		return handle_trace_pkt(q->adap, si);
3550f7917c00SJeff Kirsher 
3551f7917c00SJeff Kirsher 	pkt = (const struct cpl_rx_pkt *)rsp;
35528eb9f2f9SArjun V 	/* Compressed error vector is enabled for T6 only */
3553c50ae55eSGanesh Goudar 	if (q->adap->params.tp.rx_pkt_encap) {
35548eb9f2f9SArjun V 		err_vec = T6_COMPR_RXERR_VEC_G(be16_to_cpu(pkt->err_vec));
3555c50ae55eSGanesh Goudar 		tnl_hdr_len = T6_RX_TNLHDR_LEN_G(ntohs(pkt->err_vec));
3556c50ae55eSGanesh Goudar 	} else {
35578eb9f2f9SArjun V 		err_vec = be16_to_cpu(pkt->err_vec);
3558c50ae55eSGanesh Goudar 	}
35598eb9f2f9SArjun V 
35608eb9f2f9SArjun V 	csum_ok = pkt->csum_calc && !err_vec &&
3561cca2822dSHariprasad Shenai 		  (q->netdev->features & NETIF_F_RXCSUM);
3562992bea8eSGanesh Goudar 
3563992bea8eSGanesh Goudar 	if (err_vec)
3564992bea8eSGanesh Goudar 		rxq->stats.bad_rx_pkts++;
3565992bea8eSGanesh Goudar 
35667235ffaeSVishal Kulkarni 	if (unlikely(pi->ethtool_lb.loopback && pkt->iff >= NCHAN)) {
35677235ffaeSVishal Kulkarni 		ret = cxgb4_validate_lb_pkt(pi, si);
35687235ffaeSVishal Kulkarni 		if (!ret)
35697235ffaeSVishal Kulkarni 			return 0;
35707235ffaeSVishal Kulkarni 	}
35717235ffaeSVishal Kulkarni 
3572c50ae55eSGanesh Goudar 	if (((pkt->l2info & htonl(RXF_TCP_F)) ||
3573c50ae55eSGanesh Goudar 	     tnl_hdr_len) &&
3574f7917c00SJeff Kirsher 	    (q->netdev->features & NETIF_F_GRO) && csum_ok && !pkt->ip_frag) {
3575c50ae55eSGanesh Goudar 		do_gro(rxq, si, pkt, tnl_hdr_len);
3576f7917c00SJeff Kirsher 		return 0;
3577f7917c00SJeff Kirsher 	}
3578f7917c00SJeff Kirsher 
3579f7917c00SJeff Kirsher 	skb = cxgb4_pktgl_to_skb(si, RX_PKT_SKB_LEN, RX_PULL_LEN);
3580f7917c00SJeff Kirsher 	if (unlikely(!skb)) {
3581f7917c00SJeff Kirsher 		t4_pktgl_free(si);
3582f7917c00SJeff Kirsher 		rxq->stats.rx_drops++;
3583f7917c00SJeff Kirsher 		return 0;
3584f7917c00SJeff Kirsher 	}
3585f7917c00SJeff Kirsher 
3586a4569504SAtul Gupta 	/* Handle PTP Event Rx packet */
3587a4569504SAtul Gupta 	if (unlikely(pi->ptp_enable)) {
3588a4569504SAtul Gupta 		ret = t4_rx_hststamp(adapter, rsp, rxq, skb);
3589a4569504SAtul Gupta 		if (ret == RX_PTP_PKT_ERR)
3590a4569504SAtul Gupta 			return 0;
3591a4569504SAtul Gupta 	}
3592a4569504SAtul Gupta 	if (likely(!ret))
3593a4569504SAtul Gupta 		__skb_pull(skb, s->pktshift); /* remove ethernet header pad */
3594a4569504SAtul Gupta 
3595a4569504SAtul Gupta 	/* Handle the PTP Event Tx Loopback packet */
3596a4569504SAtul Gupta 	if (unlikely(pi->ptp_enable && !ret &&
3597a4569504SAtul Gupta 		     (pkt->l2info & htonl(RXF_UDP_F)) &&
3598a4569504SAtul Gupta 		     cxgb4_ptp_is_ptp_rx(skb))) {
3599a4569504SAtul Gupta 		if (!t4_tx_hststamp(adapter, skb, q->netdev))
3600a4569504SAtul Gupta 			return 0;
3601a4569504SAtul Gupta 	}
3602a4569504SAtul Gupta 
3603f7917c00SJeff Kirsher 	skb->protocol = eth_type_trans(skb, q->netdev);
3604f7917c00SJeff Kirsher 	skb_record_rx_queue(skb, q->idx);
3605f7917c00SJeff Kirsher 	if (skb->dev->features & NETIF_F_RXHASH)
36068264989cSTom Herbert 		skb_set_hash(skb, (__force u32)pkt->rsshdr.hash_val,
36078264989cSTom Herbert 			     PKT_HASH_TYPE_L3);
3608f7917c00SJeff Kirsher 
3609f7917c00SJeff Kirsher 	rxq->stats.pkts++;
3610f7917c00SJeff Kirsher 
36115e2a5ebcSHariprasad Shenai 	if (pi->rxtstamp)
36125e2a5ebcSHariprasad Shenai 		cxgb4_sgetim_to_hwtstamp(q->adap, skb_hwtstamps(skb),
36135e2a5ebcSHariprasad Shenai 					 si->sgetstamp);
3614bdc590b9SHariprasad Shenai 	if (csum_ok && (pkt->l2info & htonl(RXF_UDP_F | RXF_TCP_F))) {
3615f7917c00SJeff Kirsher 		if (!pkt->ip_frag) {
3616f7917c00SJeff Kirsher 			skb->ip_summed = CHECKSUM_UNNECESSARY;
3617f7917c00SJeff Kirsher 			rxq->stats.rx_cso++;
3618bdc590b9SHariprasad Shenai 		} else if (pkt->l2info & htonl(RXF_IP_F)) {
3619f7917c00SJeff Kirsher 			__sum16 c = (__force __sum16)pkt->csum;
3620f7917c00SJeff Kirsher 			skb->csum = csum_unfold(c);
3621c50ae55eSGanesh Goudar 
3622c50ae55eSGanesh Goudar 			if (tnl_hdr_len) {
3623c50ae55eSGanesh Goudar 				skb->ip_summed = CHECKSUM_UNNECESSARY;
3624c50ae55eSGanesh Goudar 				skb->csum_level = 1;
3625c50ae55eSGanesh Goudar 			} else {
3626f7917c00SJeff Kirsher 				skb->ip_summed = CHECKSUM_COMPLETE;
3627c50ae55eSGanesh Goudar 			}
3628f7917c00SJeff Kirsher 			rxq->stats.rx_cso++;
3629f7917c00SJeff Kirsher 		}
363084a200b3SVarun Prakash 	} else {
3631f7917c00SJeff Kirsher 		skb_checksum_none_assert(skb);
363284a200b3SVarun Prakash #ifdef CONFIG_CHELSIO_T4_FCOE
363384a200b3SVarun Prakash #define CPL_RX_PKT_FLAGS (RXF_PSH_F | RXF_SYN_F | RXF_UDP_F | \
363484a200b3SVarun Prakash 			  RXF_TCP_F | RXF_IP_F | RXF_IP6_F | RXF_LRO_F)
363584a200b3SVarun Prakash 
363684a200b3SVarun Prakash 		if (!(pkt->l2info & cpu_to_be32(CPL_RX_PKT_FLAGS))) {
363784a200b3SVarun Prakash 			if ((pkt->l2info & cpu_to_be32(RXF_FCOE_F)) &&
363884a200b3SVarun Prakash 			    (pi->fcoe.flags & CXGB_FCOE_ENABLED)) {
36398eb9f2f9SArjun V 				if (q->adap->params.tp.rx_pkt_encap)
36408eb9f2f9SArjun V 					csum_ok = err_vec &
36418eb9f2f9SArjun V 						  T6_COMPR_RXERR_SUM_F;
36428eb9f2f9SArjun V 				else
36438eb9f2f9SArjun V 					csum_ok = err_vec & RXERR_CSUM_F;
36448eb9f2f9SArjun V 				if (!csum_ok)
364584a200b3SVarun Prakash 					skb->ip_summed = CHECKSUM_UNNECESSARY;
364684a200b3SVarun Prakash 			}
364784a200b3SVarun Prakash 		}
364884a200b3SVarun Prakash 
364984a200b3SVarun Prakash #undef CPL_RX_PKT_FLAGS
365084a200b3SVarun Prakash #endif /* CONFIG_CHELSIO_T4_FCOE */
365184a200b3SVarun Prakash 	}
3652f7917c00SJeff Kirsher 
3653f7917c00SJeff Kirsher 	if (unlikely(pkt->vlan_ex)) {
365486a9bad3SPatrick McHardy 		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), ntohs(pkt->vlan));
3655f7917c00SJeff Kirsher 		rxq->stats.vlan_ex++;
3656f7917c00SJeff Kirsher 	}
36573a336cb1SHariprasad Shenai 	skb_mark_napi_id(skb, &q->napi);
3658f7917c00SJeff Kirsher 	netif_receive_skb(skb);
3659f7917c00SJeff Kirsher 	return 0;
3660f7917c00SJeff Kirsher }
3661f7917c00SJeff Kirsher 
3662f7917c00SJeff Kirsher /**
3663f7917c00SJeff Kirsher  *	restore_rx_bufs - put back a packet's Rx buffers
3664f7917c00SJeff Kirsher  *	@si: the packet gather list
3665f7917c00SJeff Kirsher  *	@q: the SGE free list
3666f7917c00SJeff Kirsher  *	@frags: number of FL buffers to restore
3667f7917c00SJeff Kirsher  *
3668f7917c00SJeff Kirsher  *	Puts back on an FL the Rx buffers associated with @si.  The buffers
3669f7917c00SJeff Kirsher  *	have already been unmapped and are left unmapped, we mark them so to
3670f7917c00SJeff Kirsher  *	prevent further unmapping attempts.
3671f7917c00SJeff Kirsher  *
3672f7917c00SJeff Kirsher  *	This function undoes a series of @unmap_rx_buf calls when we find out
3673f7917c00SJeff Kirsher  *	that the current packet can't be processed right away afterall and we
3674f7917c00SJeff Kirsher  *	need to come back to it later.  This is a very rare event and there's
3675f7917c00SJeff Kirsher  *	no effort to make this particularly efficient.
3676f7917c00SJeff Kirsher  */
3677f7917c00SJeff Kirsher static void restore_rx_bufs(const struct pkt_gl *si, struct sge_fl *q,
3678f7917c00SJeff Kirsher 			    int frags)
3679f7917c00SJeff Kirsher {
3680f7917c00SJeff Kirsher 	struct rx_sw_desc *d;
3681f7917c00SJeff Kirsher 
3682f7917c00SJeff Kirsher 	while (frags--) {
3683f7917c00SJeff Kirsher 		if (q->cidx == 0)
3684f7917c00SJeff Kirsher 			q->cidx = q->size - 1;
3685f7917c00SJeff Kirsher 		else
3686f7917c00SJeff Kirsher 			q->cidx--;
3687f7917c00SJeff Kirsher 		d = &q->sdesc[q->cidx];
3688f7917c00SJeff Kirsher 		d->page = si->frags[frags].page;
3689f7917c00SJeff Kirsher 		d->dma_addr |= RX_UNMAPPED_BUF;
3690f7917c00SJeff Kirsher 		q->avail++;
3691f7917c00SJeff Kirsher 	}
3692f7917c00SJeff Kirsher }
3693f7917c00SJeff Kirsher 
3694f7917c00SJeff Kirsher /**
3695f7917c00SJeff Kirsher  *	is_new_response - check if a response is newly written
3696f7917c00SJeff Kirsher  *	@r: the response descriptor
3697f7917c00SJeff Kirsher  *	@q: the response queue
3698f7917c00SJeff Kirsher  *
3699f7917c00SJeff Kirsher  *	Returns true if a response descriptor contains a yet unprocessed
3700f7917c00SJeff Kirsher  *	response.
3701f7917c00SJeff Kirsher  */
3702f7917c00SJeff Kirsher static inline bool is_new_response(const struct rsp_ctrl *r,
3703f7917c00SJeff Kirsher 				   const struct sge_rspq *q)
3704f7917c00SJeff Kirsher {
37051ecc7b7aSHariprasad Shenai 	return (r->type_gen >> RSPD_GEN_S) == q->gen;
3706f7917c00SJeff Kirsher }
3707f7917c00SJeff Kirsher 
3708f7917c00SJeff Kirsher /**
3709f7917c00SJeff Kirsher  *	rspq_next - advance to the next entry in a response queue
3710f7917c00SJeff Kirsher  *	@q: the queue
3711f7917c00SJeff Kirsher  *
3712f7917c00SJeff Kirsher  *	Updates the state of a response queue to advance it to the next entry.
3713f7917c00SJeff Kirsher  */
3714f7917c00SJeff Kirsher static inline void rspq_next(struct sge_rspq *q)
3715f7917c00SJeff Kirsher {
3716f7917c00SJeff Kirsher 	q->cur_desc = (void *)q->cur_desc + q->iqe_len;
3717f7917c00SJeff Kirsher 	if (unlikely(++q->cidx == q->size)) {
3718f7917c00SJeff Kirsher 		q->cidx = 0;
3719f7917c00SJeff Kirsher 		q->gen ^= 1;
3720f7917c00SJeff Kirsher 		q->cur_desc = q->desc;
3721f7917c00SJeff Kirsher 	}
3722f7917c00SJeff Kirsher }
3723f7917c00SJeff Kirsher 
3724f7917c00SJeff Kirsher /**
3725f7917c00SJeff Kirsher  *	process_responses - process responses from an SGE response queue
3726f7917c00SJeff Kirsher  *	@q: the ingress queue to process
3727f7917c00SJeff Kirsher  *	@budget: how many responses can be processed in this round
3728f7917c00SJeff Kirsher  *
3729f7917c00SJeff Kirsher  *	Process responses from an SGE response queue up to the supplied budget.
3730f7917c00SJeff Kirsher  *	Responses include received packets as well as control messages from FW
3731f7917c00SJeff Kirsher  *	or HW.
3732f7917c00SJeff Kirsher  *
3733f7917c00SJeff Kirsher  *	Additionally choose the interrupt holdoff time for the next interrupt
3734f7917c00SJeff Kirsher  *	on this queue.  If the system is under memory shortage use a fairly
3735f7917c00SJeff Kirsher  *	long delay to help recovery.
3736f7917c00SJeff Kirsher  */
3737f7917c00SJeff Kirsher static int process_responses(struct sge_rspq *q, int budget)
3738f7917c00SJeff Kirsher {
3739f7917c00SJeff Kirsher 	int ret, rsp_type;
3740f7917c00SJeff Kirsher 	int budget_left = budget;
3741f7917c00SJeff Kirsher 	const struct rsp_ctrl *rc;
3742f7917c00SJeff Kirsher 	struct sge_eth_rxq *rxq = container_of(q, struct sge_eth_rxq, rspq);
374352367a76SVipul Pandya 	struct adapter *adapter = q->adap;
374452367a76SVipul Pandya 	struct sge *s = &adapter->sge;
3745f7917c00SJeff Kirsher 
3746f7917c00SJeff Kirsher 	while (likely(budget_left)) {
3747f7917c00SJeff Kirsher 		rc = (void *)q->cur_desc + (q->iqe_len - sizeof(*rc));
37482337ba42SVarun Prakash 		if (!is_new_response(rc, q)) {
37492337ba42SVarun Prakash 			if (q->flush_handler)
37502337ba42SVarun Prakash 				q->flush_handler(q);
3751f7917c00SJeff Kirsher 			break;
37522337ba42SVarun Prakash 		}
3753f7917c00SJeff Kirsher 
3754019be1cfSAlexander Duyck 		dma_rmb();
37551ecc7b7aSHariprasad Shenai 		rsp_type = RSPD_TYPE_G(rc->type_gen);
37561ecc7b7aSHariprasad Shenai 		if (likely(rsp_type == RSPD_TYPE_FLBUF_X)) {
3757e91b0f24SIan Campbell 			struct page_frag *fp;
3758f7917c00SJeff Kirsher 			struct pkt_gl si;
3759f7917c00SJeff Kirsher 			const struct rx_sw_desc *rsd;
3760f7917c00SJeff Kirsher 			u32 len = ntohl(rc->pldbuflen_qid), bufsz, frags;
3761f7917c00SJeff Kirsher 
37621ecc7b7aSHariprasad Shenai 			if (len & RSPD_NEWBUF_F) {
3763f7917c00SJeff Kirsher 				if (likely(q->offset > 0)) {
3764f7917c00SJeff Kirsher 					free_rx_bufs(q->adap, &rxq->fl, 1);
3765f7917c00SJeff Kirsher 					q->offset = 0;
3766f7917c00SJeff Kirsher 				}
37671ecc7b7aSHariprasad Shenai 				len = RSPD_LEN_G(len);
3768f7917c00SJeff Kirsher 			}
3769f7917c00SJeff Kirsher 			si.tot_len = len;
3770f7917c00SJeff Kirsher 
3771f7917c00SJeff Kirsher 			/* gather packet fragments */
3772f7917c00SJeff Kirsher 			for (frags = 0, fp = si.frags; ; frags++, fp++) {
3773f7917c00SJeff Kirsher 				rsd = &rxq->fl.sdesc[rxq->fl.cidx];
377452367a76SVipul Pandya 				bufsz = get_buf_size(adapter, rsd);
3775f7917c00SJeff Kirsher 				fp->page = rsd->page;
3776e91b0f24SIan Campbell 				fp->offset = q->offset;
3777e91b0f24SIan Campbell 				fp->size = min(bufsz, len);
3778e91b0f24SIan Campbell 				len -= fp->size;
3779f7917c00SJeff Kirsher 				if (!len)
3780f7917c00SJeff Kirsher 					break;
3781f7917c00SJeff Kirsher 				unmap_rx_buf(q->adap, &rxq->fl);
3782f7917c00SJeff Kirsher 			}
3783f7917c00SJeff Kirsher 
37845e2a5ebcSHariprasad Shenai 			si.sgetstamp = SGE_TIMESTAMP_G(
37855e2a5ebcSHariprasad Shenai 					be64_to_cpu(rc->last_flit));
3786f7917c00SJeff Kirsher 			/*
3787f7917c00SJeff Kirsher 			 * Last buffer remains mapped so explicitly make it
3788f7917c00SJeff Kirsher 			 * coherent for CPU access.
3789f7917c00SJeff Kirsher 			 */
3790f7917c00SJeff Kirsher 			dma_sync_single_for_cpu(q->adap->pdev_dev,
3791f7917c00SJeff Kirsher 						get_buf_addr(rsd),
3792e91b0f24SIan Campbell 						fp->size, DMA_FROM_DEVICE);
3793f7917c00SJeff Kirsher 
3794f7917c00SJeff Kirsher 			si.va = page_address(si.frags[0].page) +
3795e91b0f24SIan Campbell 				si.frags[0].offset;
3796f7917c00SJeff Kirsher 			prefetch(si.va);
3797f7917c00SJeff Kirsher 
3798f7917c00SJeff Kirsher 			si.nfrags = frags + 1;
3799f7917c00SJeff Kirsher 			ret = q->handler(q, q->cur_desc, &si);
3800f7917c00SJeff Kirsher 			if (likely(ret == 0))
380152367a76SVipul Pandya 				q->offset += ALIGN(fp->size, s->fl_align);
3802f7917c00SJeff Kirsher 			else
3803f7917c00SJeff Kirsher 				restore_rx_bufs(&si, &rxq->fl, frags);
38041ecc7b7aSHariprasad Shenai 		} else if (likely(rsp_type == RSPD_TYPE_CPL_X)) {
3805f7917c00SJeff Kirsher 			ret = q->handler(q, q->cur_desc, NULL);
3806f7917c00SJeff Kirsher 		} else {
3807f7917c00SJeff Kirsher 			ret = q->handler(q, (const __be64 *)rc, CXGB4_MSG_AN);
3808f7917c00SJeff Kirsher 		}
3809f7917c00SJeff Kirsher 
3810f7917c00SJeff Kirsher 		if (unlikely(ret)) {
3811f7917c00SJeff Kirsher 			/* couldn't process descriptor, back off for recovery */
38121ecc7b7aSHariprasad Shenai 			q->next_intr_params = QINTR_TIMER_IDX_V(NOMEM_TMR_IDX);
3813f7917c00SJeff Kirsher 			break;
3814f7917c00SJeff Kirsher 		}
3815f7917c00SJeff Kirsher 
3816f7917c00SJeff Kirsher 		rspq_next(q);
3817f7917c00SJeff Kirsher 		budget_left--;
3818f7917c00SJeff Kirsher 	}
3819f7917c00SJeff Kirsher 
3820da08e425SHariprasad Shenai 	if (q->offset >= 0 && fl_cap(&rxq->fl) - rxq->fl.avail >= 16)
3821f7917c00SJeff Kirsher 		__refill_fl(q->adap, &rxq->fl);
3822f7917c00SJeff Kirsher 	return budget - budget_left;
3823f7917c00SJeff Kirsher }
3824f7917c00SJeff Kirsher 
3825f7917c00SJeff Kirsher /**
3826f7917c00SJeff Kirsher  *	napi_rx_handler - the NAPI handler for Rx processing
3827f7917c00SJeff Kirsher  *	@napi: the napi instance
3828f7917c00SJeff Kirsher  *	@budget: how many packets we can process in this round
3829f7917c00SJeff Kirsher  *
3830f7917c00SJeff Kirsher  *	Handler for new data events when using NAPI.  This does not need any
3831f7917c00SJeff Kirsher  *	locking or protection from interrupts as data interrupts are off at
3832f7917c00SJeff Kirsher  *	this point and other adapter interrupts do not interfere (the latter
3833f7917c00SJeff Kirsher  *	in not a concern at all with MSI-X as non-data interrupts then have
3834f7917c00SJeff Kirsher  *	a separate handler).
3835f7917c00SJeff Kirsher  */
3836f7917c00SJeff Kirsher static int napi_rx_handler(struct napi_struct *napi, int budget)
3837f7917c00SJeff Kirsher {
3838f7917c00SJeff Kirsher 	unsigned int params;
3839f7917c00SJeff Kirsher 	struct sge_rspq *q = container_of(napi, struct sge_rspq, napi);
38403a336cb1SHariprasad Shenai 	int work_done;
3841d63a6dcfSHariprasad Shenai 	u32 val;
3842f7917c00SJeff Kirsher 
38433a336cb1SHariprasad Shenai 	work_done = process_responses(q, budget);
3844f7917c00SJeff Kirsher 	if (likely(work_done < budget)) {
3845e553ec3fSHariprasad Shenai 		int timer_index;
3846e553ec3fSHariprasad Shenai 
3847812787b8SHariprasad Shenai 		napi_complete_done(napi, work_done);
38481ecc7b7aSHariprasad Shenai 		timer_index = QINTR_TIMER_IDX_G(q->next_intr_params);
3849e553ec3fSHariprasad Shenai 
3850e553ec3fSHariprasad Shenai 		if (q->adaptive_rx) {
3851e553ec3fSHariprasad Shenai 			if (work_done > max(timer_pkt_quota[timer_index],
3852e553ec3fSHariprasad Shenai 					    MIN_NAPI_WORK))
3853e553ec3fSHariprasad Shenai 				timer_index = (timer_index + 1);
3854e553ec3fSHariprasad Shenai 			else
3855e553ec3fSHariprasad Shenai 				timer_index = timer_index - 1;
3856e553ec3fSHariprasad Shenai 
3857e553ec3fSHariprasad Shenai 			timer_index = clamp(timer_index, 0, SGE_TIMERREGS - 1);
38581ecc7b7aSHariprasad Shenai 			q->next_intr_params =
38591ecc7b7aSHariprasad Shenai 					QINTR_TIMER_IDX_V(timer_index) |
38601ecc7b7aSHariprasad Shenai 					QINTR_CNT_EN_V(0);
3861e553ec3fSHariprasad Shenai 			params = q->next_intr_params;
3862e553ec3fSHariprasad Shenai 		} else {
3863f7917c00SJeff Kirsher 			params = q->next_intr_params;
3864f7917c00SJeff Kirsher 			q->next_intr_params = q->intr_params;
3865e553ec3fSHariprasad Shenai 		}
3866f7917c00SJeff Kirsher 	} else
38671ecc7b7aSHariprasad Shenai 		params = QINTR_TIMER_IDX_V(7);
3868f7917c00SJeff Kirsher 
3869f612b815SHariprasad Shenai 	val = CIDXINC_V(work_done) | SEINTARM_V(params);
3870df64e4d3SHariprasad Shenai 
3871df64e4d3SHariprasad Shenai 	/* If we don't have access to the new User GTS (T5+), use the old
3872df64e4d3SHariprasad Shenai 	 * doorbell mechanism; otherwise use the new BAR2 mechanism.
3873df64e4d3SHariprasad Shenai 	 */
3874df64e4d3SHariprasad Shenai 	if (unlikely(q->bar2_addr == NULL)) {
3875f612b815SHariprasad Shenai 		t4_write_reg(q->adap, MYPF_REG(SGE_PF_GTS_A),
3876f612b815SHariprasad Shenai 			     val | INGRESSQID_V((u32)q->cntxt_id));
3877d63a6dcfSHariprasad Shenai 	} else {
3878f612b815SHariprasad Shenai 		writel(val | INGRESSQID_V(q->bar2_qid),
3879df64e4d3SHariprasad Shenai 		       q->bar2_addr + SGE_UDB_GTS);
3880d63a6dcfSHariprasad Shenai 		wmb();
3881d63a6dcfSHariprasad Shenai 	}
3882f7917c00SJeff Kirsher 	return work_done;
3883f7917c00SJeff Kirsher }
3884f7917c00SJeff Kirsher 
3885b1396c2bSRahul Lakkireddy void cxgb4_ethofld_restart(unsigned long data)
3886b1396c2bSRahul Lakkireddy {
3887b1396c2bSRahul Lakkireddy 	struct sge_eosw_txq *eosw_txq = (struct sge_eosw_txq *)data;
3888b1396c2bSRahul Lakkireddy 	int pktcount;
3889b1396c2bSRahul Lakkireddy 
3890b1396c2bSRahul Lakkireddy 	spin_lock(&eosw_txq->lock);
3891b1396c2bSRahul Lakkireddy 	pktcount = eosw_txq->cidx - eosw_txq->last_cidx;
3892b1396c2bSRahul Lakkireddy 	if (pktcount < 0)
3893b1396c2bSRahul Lakkireddy 		pktcount += eosw_txq->ndesc;
3894b1396c2bSRahul Lakkireddy 
38954846d533SRahul Lakkireddy 	if (pktcount) {
3896b1396c2bSRahul Lakkireddy 		cxgb4_eosw_txq_free_desc(netdev2adap(eosw_txq->netdev),
3897b1396c2bSRahul Lakkireddy 					 eosw_txq, pktcount);
38984846d533SRahul Lakkireddy 		eosw_txq->inuse -= pktcount;
38994846d533SRahul Lakkireddy 	}
39004846d533SRahul Lakkireddy 
39014846d533SRahul Lakkireddy 	/* There may be some packets waiting for completions. So,
39024846d533SRahul Lakkireddy 	 * attempt to send these packets now.
39034846d533SRahul Lakkireddy 	 */
39044846d533SRahul Lakkireddy 	ethofld_xmit(eosw_txq->netdev, eosw_txq);
3905b1396c2bSRahul Lakkireddy 	spin_unlock(&eosw_txq->lock);
3906b1396c2bSRahul Lakkireddy }
3907b1396c2bSRahul Lakkireddy 
39084846d533SRahul Lakkireddy /* cxgb4_ethofld_rx_handler - Process ETHOFLD Tx completions
39094846d533SRahul Lakkireddy  * @q: the response queue that received the packet
39104846d533SRahul Lakkireddy  * @rsp: the response queue descriptor holding the CPL message
39114846d533SRahul Lakkireddy  * @si: the gather list of packet fragments
39124846d533SRahul Lakkireddy  *
39134846d533SRahul Lakkireddy  * Process a ETHOFLD Tx completion. Increment the cidx here, but
39144846d533SRahul Lakkireddy  * free up the descriptors in a tasklet later.
39154846d533SRahul Lakkireddy  */
39164846d533SRahul Lakkireddy int cxgb4_ethofld_rx_handler(struct sge_rspq *q, const __be64 *rsp,
39174846d533SRahul Lakkireddy 			     const struct pkt_gl *si)
39184846d533SRahul Lakkireddy {
39194846d533SRahul Lakkireddy 	u8 opcode = ((const struct rss_header *)rsp)->opcode;
39204846d533SRahul Lakkireddy 
39214846d533SRahul Lakkireddy 	/* skip RSS header */
39224846d533SRahul Lakkireddy 	rsp++;
39234846d533SRahul Lakkireddy 
39244846d533SRahul Lakkireddy 	if (opcode == CPL_FW4_ACK) {
39254846d533SRahul Lakkireddy 		const struct cpl_fw4_ack *cpl;
39264846d533SRahul Lakkireddy 		struct sge_eosw_txq *eosw_txq;
39274846d533SRahul Lakkireddy 		struct eotid_entry *entry;
39284846d533SRahul Lakkireddy 		struct sk_buff *skb;
39294846d533SRahul Lakkireddy 		u32 hdr_len, eotid;
39304846d533SRahul Lakkireddy 		u8 flits, wrlen16;
39314846d533SRahul Lakkireddy 		int credits;
39324846d533SRahul Lakkireddy 
39334846d533SRahul Lakkireddy 		cpl = (const struct cpl_fw4_ack *)rsp;
39344846d533SRahul Lakkireddy 		eotid = CPL_FW4_ACK_FLOWID_G(ntohl(OPCODE_TID(cpl))) -
39354846d533SRahul Lakkireddy 			q->adap->tids.eotid_base;
39364846d533SRahul Lakkireddy 		entry = cxgb4_lookup_eotid(&q->adap->tids, eotid);
39374846d533SRahul Lakkireddy 		if (!entry)
39384846d533SRahul Lakkireddy 			goto out_done;
39394846d533SRahul Lakkireddy 
39404846d533SRahul Lakkireddy 		eosw_txq = (struct sge_eosw_txq *)entry->data;
39414846d533SRahul Lakkireddy 		if (!eosw_txq)
39424846d533SRahul Lakkireddy 			goto out_done;
39434846d533SRahul Lakkireddy 
39444846d533SRahul Lakkireddy 		spin_lock(&eosw_txq->lock);
39454846d533SRahul Lakkireddy 		credits = cpl->credits;
39464846d533SRahul Lakkireddy 		while (credits > 0) {
39474846d533SRahul Lakkireddy 			skb = eosw_txq->desc[eosw_txq->cidx].skb;
39484846d533SRahul Lakkireddy 			if (!skb)
39494846d533SRahul Lakkireddy 				break;
39504846d533SRahul Lakkireddy 
39510e395b3cSRahul Lakkireddy 			if (unlikely((eosw_txq->state ==
39520e395b3cSRahul Lakkireddy 				      CXGB4_EO_STATE_FLOWC_OPEN_REPLY ||
39530e395b3cSRahul Lakkireddy 				      eosw_txq->state ==
39540e395b3cSRahul Lakkireddy 				      CXGB4_EO_STATE_FLOWC_CLOSE_REPLY) &&
39550e395b3cSRahul Lakkireddy 				     eosw_txq->cidx == eosw_txq->flowc_idx)) {
39560e395b3cSRahul Lakkireddy 				flits = DIV_ROUND_UP(skb->len, 8);
39570e395b3cSRahul Lakkireddy 				if (eosw_txq->state ==
39580e395b3cSRahul Lakkireddy 				    CXGB4_EO_STATE_FLOWC_OPEN_REPLY)
39590e395b3cSRahul Lakkireddy 					eosw_txq->state = CXGB4_EO_STATE_ACTIVE;
39600e395b3cSRahul Lakkireddy 				else
39610e395b3cSRahul Lakkireddy 					eosw_txq->state = CXGB4_EO_STATE_CLOSED;
39620e395b3cSRahul Lakkireddy 				complete(&eosw_txq->completion);
39630e395b3cSRahul Lakkireddy 			} else {
39640e395b3cSRahul Lakkireddy 				hdr_len = eth_get_headlen(eosw_txq->netdev,
39650e395b3cSRahul Lakkireddy 							  skb->data,
39664846d533SRahul Lakkireddy 							  skb_headlen(skb));
39670e395b3cSRahul Lakkireddy 				flits = ethofld_calc_tx_flits(q->adap, skb,
39680e395b3cSRahul Lakkireddy 							      hdr_len);
39690e395b3cSRahul Lakkireddy 			}
39704846d533SRahul Lakkireddy 			eosw_txq_advance_index(&eosw_txq->cidx, 1,
39714846d533SRahul Lakkireddy 					       eosw_txq->ndesc);
39724846d533SRahul Lakkireddy 			wrlen16 = DIV_ROUND_UP(flits * 8, 16);
39734846d533SRahul Lakkireddy 			credits -= wrlen16;
39744846d533SRahul Lakkireddy 		}
39754846d533SRahul Lakkireddy 
39764846d533SRahul Lakkireddy 		eosw_txq->cred += cpl->credits;
39774846d533SRahul Lakkireddy 		eosw_txq->ncompl--;
39784846d533SRahul Lakkireddy 
39794846d533SRahul Lakkireddy 		spin_unlock(&eosw_txq->lock);
39804846d533SRahul Lakkireddy 
39814846d533SRahul Lakkireddy 		/* Schedule a tasklet to reclaim SKBs and restart ETHOFLD Tx,
39824846d533SRahul Lakkireddy 		 * if there were packets waiting for completion.
39834846d533SRahul Lakkireddy 		 */
39844846d533SRahul Lakkireddy 		tasklet_schedule(&eosw_txq->qresume_tsk);
39854846d533SRahul Lakkireddy 	}
39864846d533SRahul Lakkireddy 
39874846d533SRahul Lakkireddy out_done:
39884846d533SRahul Lakkireddy 	return 0;
39894846d533SRahul Lakkireddy }
39904846d533SRahul Lakkireddy 
3991f7917c00SJeff Kirsher /*
3992f7917c00SJeff Kirsher  * The MSI-X interrupt handler for an SGE response queue.
3993f7917c00SJeff Kirsher  */
3994f7917c00SJeff Kirsher irqreturn_t t4_sge_intr_msix(int irq, void *cookie)
3995f7917c00SJeff Kirsher {
3996f7917c00SJeff Kirsher 	struct sge_rspq *q = cookie;
3997f7917c00SJeff Kirsher 
3998f7917c00SJeff Kirsher 	napi_schedule(&q->napi);
3999f7917c00SJeff Kirsher 	return IRQ_HANDLED;
4000f7917c00SJeff Kirsher }
4001f7917c00SJeff Kirsher 
4002f7917c00SJeff Kirsher /*
4003f7917c00SJeff Kirsher  * Process the indirect interrupt entries in the interrupt queue and kick off
4004f7917c00SJeff Kirsher  * NAPI for each queue that has generated an entry.
4005f7917c00SJeff Kirsher  */
4006f7917c00SJeff Kirsher static unsigned int process_intrq(struct adapter *adap)
4007f7917c00SJeff Kirsher {
4008f7917c00SJeff Kirsher 	unsigned int credits;
4009f7917c00SJeff Kirsher 	const struct rsp_ctrl *rc;
4010f7917c00SJeff Kirsher 	struct sge_rspq *q = &adap->sge.intrq;
4011d63a6dcfSHariprasad Shenai 	u32 val;
4012f7917c00SJeff Kirsher 
4013f7917c00SJeff Kirsher 	spin_lock(&adap->sge.intrq_lock);
4014f7917c00SJeff Kirsher 	for (credits = 0; ; credits++) {
4015f7917c00SJeff Kirsher 		rc = (void *)q->cur_desc + (q->iqe_len - sizeof(*rc));
4016f7917c00SJeff Kirsher 		if (!is_new_response(rc, q))
4017f7917c00SJeff Kirsher 			break;
4018f7917c00SJeff Kirsher 
4019019be1cfSAlexander Duyck 		dma_rmb();
40201ecc7b7aSHariprasad Shenai 		if (RSPD_TYPE_G(rc->type_gen) == RSPD_TYPE_INTR_X) {
4021f7917c00SJeff Kirsher 			unsigned int qid = ntohl(rc->pldbuflen_qid);
4022f7917c00SJeff Kirsher 
4023f7917c00SJeff Kirsher 			qid -= adap->sge.ingr_start;
4024f7917c00SJeff Kirsher 			napi_schedule(&adap->sge.ingr_map[qid]->napi);
4025f7917c00SJeff Kirsher 		}
4026f7917c00SJeff Kirsher 
4027f7917c00SJeff Kirsher 		rspq_next(q);
4028f7917c00SJeff Kirsher 	}
4029f7917c00SJeff Kirsher 
4030f612b815SHariprasad Shenai 	val =  CIDXINC_V(credits) | SEINTARM_V(q->intr_params);
4031df64e4d3SHariprasad Shenai 
4032df64e4d3SHariprasad Shenai 	/* If we don't have access to the new User GTS (T5+), use the old
4033df64e4d3SHariprasad Shenai 	 * doorbell mechanism; otherwise use the new BAR2 mechanism.
4034df64e4d3SHariprasad Shenai 	 */
4035df64e4d3SHariprasad Shenai 	if (unlikely(q->bar2_addr == NULL)) {
4036f612b815SHariprasad Shenai 		t4_write_reg(adap, MYPF_REG(SGE_PF_GTS_A),
4037f612b815SHariprasad Shenai 			     val | INGRESSQID_V(q->cntxt_id));
4038d63a6dcfSHariprasad Shenai 	} else {
4039f612b815SHariprasad Shenai 		writel(val | INGRESSQID_V(q->bar2_qid),
4040df64e4d3SHariprasad Shenai 		       q->bar2_addr + SGE_UDB_GTS);
4041d63a6dcfSHariprasad Shenai 		wmb();
4042d63a6dcfSHariprasad Shenai 	}
4043f7917c00SJeff Kirsher 	spin_unlock(&adap->sge.intrq_lock);
4044f7917c00SJeff Kirsher 	return credits;
4045f7917c00SJeff Kirsher }
4046f7917c00SJeff Kirsher 
4047f7917c00SJeff Kirsher /*
4048f7917c00SJeff Kirsher  * The MSI interrupt handler, which handles data events from SGE response queues
4049f7917c00SJeff Kirsher  * as well as error and other async events as they all use the same MSI vector.
4050f7917c00SJeff Kirsher  */
4051f7917c00SJeff Kirsher static irqreturn_t t4_intr_msi(int irq, void *cookie)
4052f7917c00SJeff Kirsher {
4053f7917c00SJeff Kirsher 	struct adapter *adap = cookie;
4054f7917c00SJeff Kirsher 
405580f61f19SArjun Vynipadath 	if (adap->flags & CXGB4_MASTER_PF)
4056f7917c00SJeff Kirsher 		t4_slow_intr_handler(adap);
4057f7917c00SJeff Kirsher 	process_intrq(adap);
4058f7917c00SJeff Kirsher 	return IRQ_HANDLED;
4059f7917c00SJeff Kirsher }
4060f7917c00SJeff Kirsher 
4061f7917c00SJeff Kirsher /*
4062f7917c00SJeff Kirsher  * Interrupt handler for legacy INTx interrupts.
4063f7917c00SJeff Kirsher  * Handles data events from SGE response queues as well as error and other
4064f7917c00SJeff Kirsher  * async events as they all use the same interrupt line.
4065f7917c00SJeff Kirsher  */
4066f7917c00SJeff Kirsher static irqreturn_t t4_intr_intx(int irq, void *cookie)
4067f7917c00SJeff Kirsher {
4068f7917c00SJeff Kirsher 	struct adapter *adap = cookie;
4069f7917c00SJeff Kirsher 
4070f061de42SHariprasad Shenai 	t4_write_reg(adap, MYPF_REG(PCIE_PF_CLI_A), 0);
407180f61f19SArjun Vynipadath 	if (((adap->flags & CXGB4_MASTER_PF) && t4_slow_intr_handler(adap)) |
4072c3c7b121SHariprasad Shenai 	    process_intrq(adap))
4073f7917c00SJeff Kirsher 		return IRQ_HANDLED;
4074f7917c00SJeff Kirsher 	return IRQ_NONE;             /* probably shared interrupt */
4075f7917c00SJeff Kirsher }
4076f7917c00SJeff Kirsher 
4077f7917c00SJeff Kirsher /**
4078f7917c00SJeff Kirsher  *	t4_intr_handler - select the top-level interrupt handler
4079f7917c00SJeff Kirsher  *	@adap: the adapter
4080f7917c00SJeff Kirsher  *
4081f7917c00SJeff Kirsher  *	Selects the top-level interrupt handler based on the type of interrupts
4082f7917c00SJeff Kirsher  *	(MSI-X, MSI, or INTx).
4083f7917c00SJeff Kirsher  */
4084f7917c00SJeff Kirsher irq_handler_t t4_intr_handler(struct adapter *adap)
4085f7917c00SJeff Kirsher {
408680f61f19SArjun Vynipadath 	if (adap->flags & CXGB4_USING_MSIX)
4087f7917c00SJeff Kirsher 		return t4_sge_intr_msix;
408880f61f19SArjun Vynipadath 	if (adap->flags & CXGB4_USING_MSI)
4089f7917c00SJeff Kirsher 		return t4_intr_msi;
4090f7917c00SJeff Kirsher 	return t4_intr_intx;
4091f7917c00SJeff Kirsher }
4092f7917c00SJeff Kirsher 
40930e23daebSKees Cook static void sge_rx_timer_cb(struct timer_list *t)
4094f7917c00SJeff Kirsher {
4095f7917c00SJeff Kirsher 	unsigned long m;
4096a3bfb617SHariprasad Shenai 	unsigned int i;
40970e23daebSKees Cook 	struct adapter *adap = from_timer(adap, t, sge.rx_timer);
4098f7917c00SJeff Kirsher 	struct sge *s = &adap->sge;
4099f7917c00SJeff Kirsher 
41004b8e27a8SHariprasad Shenai 	for (i = 0; i < BITS_TO_LONGS(s->egr_sz); i++)
4101f7917c00SJeff Kirsher 		for (m = s->starving_fl[i]; m; m &= m - 1) {
4102f7917c00SJeff Kirsher 			struct sge_eth_rxq *rxq;
4103f7917c00SJeff Kirsher 			unsigned int id = __ffs(m) + i * BITS_PER_LONG;
4104f7917c00SJeff Kirsher 			struct sge_fl *fl = s->egr_map[id];
4105f7917c00SJeff Kirsher 
4106f7917c00SJeff Kirsher 			clear_bit(id, s->starving_fl);
41074e857c58SPeter Zijlstra 			smp_mb__after_atomic();
4108f7917c00SJeff Kirsher 
4109c098b026SHariprasad Shenai 			if (fl_starving(adap, fl)) {
4110f7917c00SJeff Kirsher 				rxq = container_of(fl, struct sge_eth_rxq, fl);
4111f7917c00SJeff Kirsher 				if (napi_reschedule(&rxq->rspq.napi))
4112f7917c00SJeff Kirsher 					fl->starving++;
4113f7917c00SJeff Kirsher 				else
4114f7917c00SJeff Kirsher 					set_bit(id, s->starving_fl);
4115f7917c00SJeff Kirsher 			}
4116f7917c00SJeff Kirsher 		}
4117a3bfb617SHariprasad Shenai 	/* The remainder of the SGE RX Timer Callback routine is dedicated to
4118a3bfb617SHariprasad Shenai 	 * global Master PF activities like checking for chip ingress stalls,
4119a3bfb617SHariprasad Shenai 	 * etc.
41200f4d201fSKumar Sanghvi 	 */
412180f61f19SArjun Vynipadath 	if (!(adap->flags & CXGB4_MASTER_PF))
4122a3bfb617SHariprasad Shenai 		goto done;
41230f4d201fSKumar Sanghvi 
4124a3bfb617SHariprasad Shenai 	t4_idma_monitor(adap, &s->idma_monitor, HZ, RX_QCHECK_PERIOD);
41250f4d201fSKumar Sanghvi 
4126a3bfb617SHariprasad Shenai done:
4127f7917c00SJeff Kirsher 	mod_timer(&s->rx_timer, jiffies + RX_QCHECK_PERIOD);
4128f7917c00SJeff Kirsher }
4129f7917c00SJeff Kirsher 
41300e23daebSKees Cook static void sge_tx_timer_cb(struct timer_list *t)
4131f7917c00SJeff Kirsher {
41320e23daebSKees Cook 	struct adapter *adap = from_timer(adap, t, sge.tx_timer);
4133f7917c00SJeff Kirsher 	struct sge *s = &adap->sge;
4134d429005fSVishal Kulkarni 	unsigned long m, period;
4135d429005fSVishal Kulkarni 	unsigned int i, budget;
4136f7917c00SJeff Kirsher 
41374b8e27a8SHariprasad Shenai 	for (i = 0; i < BITS_TO_LONGS(s->egr_sz); i++)
4138f7917c00SJeff Kirsher 		for (m = s->txq_maperr[i]; m; m &= m - 1) {
4139f7917c00SJeff Kirsher 			unsigned long id = __ffs(m) + i * BITS_PER_LONG;
4140ab677ff4SHariprasad Shenai 			struct sge_uld_txq *txq = s->egr_map[id];
4141f7917c00SJeff Kirsher 
4142f7917c00SJeff Kirsher 			clear_bit(id, s->txq_maperr);
4143f7917c00SJeff Kirsher 			tasklet_schedule(&txq->qresume_tsk);
4144f7917c00SJeff Kirsher 		}
4145f7917c00SJeff Kirsher 
4146a4569504SAtul Gupta 	if (!is_t4(adap->params.chip)) {
4147a4569504SAtul Gupta 		struct sge_eth_txq *q = &s->ptptxq;
4148a4569504SAtul Gupta 		int avail;
4149a4569504SAtul Gupta 
4150a4569504SAtul Gupta 		spin_lock(&adap->ptp_lock);
4151a4569504SAtul Gupta 		avail = reclaimable(&q->q);
4152a4569504SAtul Gupta 
4153a4569504SAtul Gupta 		if (avail) {
4154a4569504SAtul Gupta 			free_tx_desc(adap, &q->q, avail, false);
4155a4569504SAtul Gupta 			q->q.in_use -= avail;
4156a4569504SAtul Gupta 		}
4157a4569504SAtul Gupta 		spin_unlock(&adap->ptp_lock);
4158a4569504SAtul Gupta 	}
4159a4569504SAtul Gupta 
4160f7917c00SJeff Kirsher 	budget = MAX_TIMER_TX_RECLAIM;
4161f7917c00SJeff Kirsher 	i = s->ethtxq_rover;
4162f7917c00SJeff Kirsher 	do {
4163d429005fSVishal Kulkarni 		budget -= t4_sge_eth_txq_egress_update(adap, &s->ethtxq[i],
4164d429005fSVishal Kulkarni 						       budget);
4165d429005fSVishal Kulkarni 		if (!budget)
4166d429005fSVishal Kulkarni 			break;
4167f7917c00SJeff Kirsher 
4168f7917c00SJeff Kirsher 		if (++i >= s->ethqsets)
4169f7917c00SJeff Kirsher 			i = 0;
4170d429005fSVishal Kulkarni 	} while (i != s->ethtxq_rover);
4171f7917c00SJeff Kirsher 	s->ethtxq_rover = i;
4172d429005fSVishal Kulkarni 
4173d429005fSVishal Kulkarni 	if (budget == 0) {
4174d429005fSVishal Kulkarni 		/* If we found too many reclaimable packets schedule a timer
4175d429005fSVishal Kulkarni 		 * in the near future to continue where we left off.
4176d429005fSVishal Kulkarni 		 */
4177d429005fSVishal Kulkarni 		period = 2;
4178d429005fSVishal Kulkarni 	} else {
4179d429005fSVishal Kulkarni 		/* We reclaimed all reclaimable TX Descriptors, so reschedule
4180d429005fSVishal Kulkarni 		 * at the normal period.
4181d429005fSVishal Kulkarni 		 */
4182d429005fSVishal Kulkarni 		period = TX_QCHECK_PERIOD;
4183d429005fSVishal Kulkarni 	}
4184d429005fSVishal Kulkarni 
4185d429005fSVishal Kulkarni 	mod_timer(&s->tx_timer, jiffies + period);
4186f7917c00SJeff Kirsher }
4187f7917c00SJeff Kirsher 
4188d63a6dcfSHariprasad Shenai /**
4189df64e4d3SHariprasad Shenai  *	bar2_address - return the BAR2 address for an SGE Queue's Registers
4190df64e4d3SHariprasad Shenai  *	@adapter: the adapter
4191df64e4d3SHariprasad Shenai  *	@qid: the SGE Queue ID
4192df64e4d3SHariprasad Shenai  *	@qtype: the SGE Queue Type (Egress or Ingress)
4193df64e4d3SHariprasad Shenai  *	@pbar2_qid: BAR2 Queue ID or 0 for Queue ID inferred SGE Queues
4194d63a6dcfSHariprasad Shenai  *
4195df64e4d3SHariprasad Shenai  *	Returns the BAR2 address for the SGE Queue Registers associated with
4196df64e4d3SHariprasad Shenai  *	@qid.  If BAR2 SGE Registers aren't available, returns NULL.  Also
4197df64e4d3SHariprasad Shenai  *	returns the BAR2 Queue ID to be used with writes to the BAR2 SGE
4198df64e4d3SHariprasad Shenai  *	Queue Registers.  If the BAR2 Queue ID is 0, then "Inferred Queue ID"
4199df64e4d3SHariprasad Shenai  *	Registers are supported (e.g. the Write Combining Doorbell Buffer).
4200d63a6dcfSHariprasad Shenai  */
4201df64e4d3SHariprasad Shenai static void __iomem *bar2_address(struct adapter *adapter,
4202df64e4d3SHariprasad Shenai 				  unsigned int qid,
4203df64e4d3SHariprasad Shenai 				  enum t4_bar2_qtype qtype,
4204df64e4d3SHariprasad Shenai 				  unsigned int *pbar2_qid)
4205d63a6dcfSHariprasad Shenai {
4206df64e4d3SHariprasad Shenai 	u64 bar2_qoffset;
4207df64e4d3SHariprasad Shenai 	int ret;
4208d63a6dcfSHariprasad Shenai 
4209e0456717SLinus Torvalds 	ret = t4_bar2_sge_qregs(adapter, qid, qtype, 0,
4210df64e4d3SHariprasad Shenai 				&bar2_qoffset, pbar2_qid);
4211df64e4d3SHariprasad Shenai 	if (ret)
4212df64e4d3SHariprasad Shenai 		return NULL;
4213d63a6dcfSHariprasad Shenai 
4214df64e4d3SHariprasad Shenai 	return adapter->bar2 + bar2_qoffset;
4215d63a6dcfSHariprasad Shenai }
4216d63a6dcfSHariprasad Shenai 
4217145ef8a5SHariprasad Shenai /* @intr_idx: MSI/MSI-X vector if >=0, -(absolute qid + 1) if < 0
4218145ef8a5SHariprasad Shenai  * @cong: < 0 -> no congestion feedback, >= 0 -> congestion channel map
4219145ef8a5SHariprasad Shenai  */
4220f7917c00SJeff Kirsher int t4_sge_alloc_rxq(struct adapter *adap, struct sge_rspq *iq, bool fwevtq,
4221f7917c00SJeff Kirsher 		     struct net_device *dev, int intr_idx,
42222337ba42SVarun Prakash 		     struct sge_fl *fl, rspq_handler_t hnd,
42232337ba42SVarun Prakash 		     rspq_flush_handler_t flush_hnd, int cong)
4224f7917c00SJeff Kirsher {
4225f7917c00SJeff Kirsher 	int ret, flsz = 0;
4226f7917c00SJeff Kirsher 	struct fw_iq_cmd c;
422752367a76SVipul Pandya 	struct sge *s = &adap->sge;
4228f7917c00SJeff Kirsher 	struct port_info *pi = netdev_priv(dev);
422980f61f19SArjun Vynipadath 	int relaxed = !(adap->flags & CXGB4_ROOT_NO_RELAXED_ORDERING);
4230f7917c00SJeff Kirsher 
4231f7917c00SJeff Kirsher 	/* Size needs to be multiple of 16, including status entry. */
4232f7917c00SJeff Kirsher 	iq->size = roundup(iq->size, 16);
4233f7917c00SJeff Kirsher 
4234f7917c00SJeff Kirsher 	iq->desc = alloc_ring(adap->pdev_dev, iq->size, iq->iqe_len, 0,
42350ac5b708SHariprasad Shenai 			      &iq->phys_addr, NULL, 0,
42360ac5b708SHariprasad Shenai 			      dev_to_node(adap->pdev_dev));
4237f7917c00SJeff Kirsher 	if (!iq->desc)
4238f7917c00SJeff Kirsher 		return -ENOMEM;
4239f7917c00SJeff Kirsher 
4240f7917c00SJeff Kirsher 	memset(&c, 0, sizeof(c));
4241e2ac9628SHariprasad Shenai 	c.op_to_vfn = htonl(FW_CMD_OP_V(FW_IQ_CMD) | FW_CMD_REQUEST_F |
4242e2ac9628SHariprasad Shenai 			    FW_CMD_WRITE_F | FW_CMD_EXEC_F |
4243b2612722SHariprasad Shenai 			    FW_IQ_CMD_PFN_V(adap->pf) | FW_IQ_CMD_VFN_V(0));
42446e4b51a6SHariprasad Shenai 	c.alloc_to_len16 = htonl(FW_IQ_CMD_ALLOC_F | FW_IQ_CMD_IQSTART_F |
4245f7917c00SJeff Kirsher 				 FW_LEN16(c));
42466e4b51a6SHariprasad Shenai 	c.type_to_iqandstindex = htonl(FW_IQ_CMD_TYPE_V(FW_IQ_TYPE_FL_INT_CAP) |
42476e4b51a6SHariprasad Shenai 		FW_IQ_CMD_IQASYNCH_V(fwevtq) | FW_IQ_CMD_VIID_V(pi->viid) |
42481ecc7b7aSHariprasad Shenai 		FW_IQ_CMD_IQANDST_V(intr_idx < 0) |
42491ecc7b7aSHariprasad Shenai 		FW_IQ_CMD_IQANUD_V(UPDATEDELIVERY_INTERRUPT_X) |
42506e4b51a6SHariprasad Shenai 		FW_IQ_CMD_IQANDSTINDEX_V(intr_idx >= 0 ? intr_idx :
4251f7917c00SJeff Kirsher 							-intr_idx - 1));
42526e4b51a6SHariprasad Shenai 	c.iqdroprss_to_iqesize = htons(FW_IQ_CMD_IQPCIECH_V(pi->tx_chan) |
42536e4b51a6SHariprasad Shenai 		FW_IQ_CMD_IQGTSMODE_F |
42546e4b51a6SHariprasad Shenai 		FW_IQ_CMD_IQINTCNTTHRESH_V(iq->pktcnt_idx) |
42556e4b51a6SHariprasad Shenai 		FW_IQ_CMD_IQESIZE_V(ilog2(iq->iqe_len) - 4));
4256f7917c00SJeff Kirsher 	c.iqsize = htons(iq->size);
4257f7917c00SJeff Kirsher 	c.iqaddr = cpu_to_be64(iq->phys_addr);
4258145ef8a5SHariprasad Shenai 	if (cong >= 0)
42598dce04f1SArjun Vynipadath 		c.iqns_to_fl0congen = htonl(FW_IQ_CMD_IQFLINTCONGEN_F |
42608dce04f1SArjun Vynipadath 				FW_IQ_CMD_IQTYPE_V(cong ? FW_IQ_IQTYPE_NIC
42618dce04f1SArjun Vynipadath 							:  FW_IQ_IQTYPE_OFLD));
4262f7917c00SJeff Kirsher 
4263f7917c00SJeff Kirsher 	if (fl) {
4264d429005fSVishal Kulkarni 		unsigned int chip_ver =
4265d429005fSVishal Kulkarni 			CHELSIO_CHIP_VERSION(adap->params.chip);
42663ccc6cf7SHariprasad Shenai 
426713432997SHariprasad Shenai 		/* Allocate the ring for the hardware free list (with space
426813432997SHariprasad Shenai 		 * for its status page) along with the associated software
426913432997SHariprasad Shenai 		 * descriptor ring.  The free list size needs to be a multiple
427013432997SHariprasad Shenai 		 * of the Egress Queue Unit and at least 2 Egress Units larger
427113432997SHariprasad Shenai 		 * than the SGE's Egress Congrestion Threshold
427213432997SHariprasad Shenai 		 * (fl_starve_thres - 1).
427313432997SHariprasad Shenai 		 */
427413432997SHariprasad Shenai 		if (fl->size < s->fl_starve_thres - 1 + 2 * 8)
427513432997SHariprasad Shenai 			fl->size = s->fl_starve_thres - 1 + 2 * 8;
4276f7917c00SJeff Kirsher 		fl->size = roundup(fl->size, 8);
4277f7917c00SJeff Kirsher 		fl->desc = alloc_ring(adap->pdev_dev, fl->size, sizeof(__be64),
4278f7917c00SJeff Kirsher 				      sizeof(struct rx_sw_desc), &fl->addr,
42790ac5b708SHariprasad Shenai 				      &fl->sdesc, s->stat_len,
42800ac5b708SHariprasad Shenai 				      dev_to_node(adap->pdev_dev));
4281f7917c00SJeff Kirsher 		if (!fl->desc)
4282f7917c00SJeff Kirsher 			goto fl_nomem;
4283f7917c00SJeff Kirsher 
428452367a76SVipul Pandya 		flsz = fl->size / 8 + s->stat_len / sizeof(struct tx_desc);
4285145ef8a5SHariprasad Shenai 		c.iqns_to_fl0congen |= htonl(FW_IQ_CMD_FL0PACKEN_F |
4286b0ba9d5fSCasey Leedom 					     FW_IQ_CMD_FL0FETCHRO_V(relaxed) |
4287b0ba9d5fSCasey Leedom 					     FW_IQ_CMD_FL0DATARO_V(relaxed) |
42886e4b51a6SHariprasad Shenai 					     FW_IQ_CMD_FL0PADEN_F);
4289145ef8a5SHariprasad Shenai 		if (cong >= 0)
4290145ef8a5SHariprasad Shenai 			c.iqns_to_fl0congen |=
4291145ef8a5SHariprasad Shenai 				htonl(FW_IQ_CMD_FL0CNGCHMAP_V(cong) |
4292145ef8a5SHariprasad Shenai 				      FW_IQ_CMD_FL0CONGCIF_F |
4293145ef8a5SHariprasad Shenai 				      FW_IQ_CMD_FL0CONGEN_F);
4294edadad80SHariprasad Shenai 		/* In T6, for egress queue type FL there is internal overhead
4295edadad80SHariprasad Shenai 		 * of 16B for header going into FLM module.  Hence the maximum
4296edadad80SHariprasad Shenai 		 * allowed burst size is 448 bytes.  For T4/T5, the hardware
4297edadad80SHariprasad Shenai 		 * doesn't coalesce fetch requests if more than 64 bytes of
4298edadad80SHariprasad Shenai 		 * Free List pointers are provided, so we use a 128-byte Fetch
4299edadad80SHariprasad Shenai 		 * Burst Minimum there (T6 implements coalescing so we can use
4300edadad80SHariprasad Shenai 		 * the smaller 64-byte value there).
4301edadad80SHariprasad Shenai 		 */
43021ecc7b7aSHariprasad Shenai 		c.fl0dcaen_to_fl0cidxfthresh =
4303d429005fSVishal Kulkarni 			htons(FW_IQ_CMD_FL0FBMIN_V(chip_ver <= CHELSIO_T5 ?
4304edadad80SHariprasad Shenai 						   FETCHBURSTMIN_128B_X :
4305d429005fSVishal Kulkarni 						   FETCHBURSTMIN_64B_T6_X) |
4306d429005fSVishal Kulkarni 			      FW_IQ_CMD_FL0FBMAX_V((chip_ver <= CHELSIO_T5) ?
43073ccc6cf7SHariprasad Shenai 						   FETCHBURSTMAX_512B_X :
43083ccc6cf7SHariprasad Shenai 						   FETCHBURSTMAX_256B_X));
4309f7917c00SJeff Kirsher 		c.fl0size = htons(flsz);
4310f7917c00SJeff Kirsher 		c.fl0addr = cpu_to_be64(fl->addr);
4311f7917c00SJeff Kirsher 	}
4312f7917c00SJeff Kirsher 
4313b2612722SHariprasad Shenai 	ret = t4_wr_mbox(adap, adap->mbox, &c, sizeof(c), &c);
4314f7917c00SJeff Kirsher 	if (ret)
4315f7917c00SJeff Kirsher 		goto err;
4316f7917c00SJeff Kirsher 
4317f7917c00SJeff Kirsher 	netif_napi_add(dev, &iq->napi, napi_rx_handler, 64);
4318f7917c00SJeff Kirsher 	iq->cur_desc = iq->desc;
4319f7917c00SJeff Kirsher 	iq->cidx = 0;
4320f7917c00SJeff Kirsher 	iq->gen = 1;
4321f7917c00SJeff Kirsher 	iq->next_intr_params = iq->intr_params;
4322f7917c00SJeff Kirsher 	iq->cntxt_id = ntohs(c.iqid);
4323f7917c00SJeff Kirsher 	iq->abs_id = ntohs(c.physiqid);
4324df64e4d3SHariprasad Shenai 	iq->bar2_addr = bar2_address(adap,
4325df64e4d3SHariprasad Shenai 				     iq->cntxt_id,
4326df64e4d3SHariprasad Shenai 				     T4_BAR2_QTYPE_INGRESS,
4327df64e4d3SHariprasad Shenai 				     &iq->bar2_qid);
4328f7917c00SJeff Kirsher 	iq->size--;                           /* subtract status entry */
4329f7917c00SJeff Kirsher 	iq->netdev = dev;
4330f7917c00SJeff Kirsher 	iq->handler = hnd;
43312337ba42SVarun Prakash 	iq->flush_handler = flush_hnd;
43322337ba42SVarun Prakash 
43332337ba42SVarun Prakash 	memset(&iq->lro_mgr, 0, sizeof(struct t4_lro_mgr));
43342337ba42SVarun Prakash 	skb_queue_head_init(&iq->lro_mgr.lroq);
4335f7917c00SJeff Kirsher 
4336f7917c00SJeff Kirsher 	/* set offset to -1 to distinguish ingress queues without FL */
4337f7917c00SJeff Kirsher 	iq->offset = fl ? 0 : -1;
4338f7917c00SJeff Kirsher 
4339f7917c00SJeff Kirsher 	adap->sge.ingr_map[iq->cntxt_id - adap->sge.ingr_start] = iq;
4340f7917c00SJeff Kirsher 
4341f7917c00SJeff Kirsher 	if (fl) {
4342f7917c00SJeff Kirsher 		fl->cntxt_id = ntohs(c.fl0id);
4343f7917c00SJeff Kirsher 		fl->avail = fl->pend_cred = 0;
4344f7917c00SJeff Kirsher 		fl->pidx = fl->cidx = 0;
4345f7917c00SJeff Kirsher 		fl->alloc_failed = fl->large_alloc_failed = fl->starving = 0;
4346f7917c00SJeff Kirsher 		adap->sge.egr_map[fl->cntxt_id - adap->sge.egr_start] = fl;
4347d63a6dcfSHariprasad Shenai 
4348df64e4d3SHariprasad Shenai 		/* Note, we must initialize the BAR2 Free List User Doorbell
4349df64e4d3SHariprasad Shenai 		 * information before refilling the Free List!
4350d63a6dcfSHariprasad Shenai 		 */
4351df64e4d3SHariprasad Shenai 		fl->bar2_addr = bar2_address(adap,
4352df64e4d3SHariprasad Shenai 					     fl->cntxt_id,
4353df64e4d3SHariprasad Shenai 					     T4_BAR2_QTYPE_EGRESS,
4354df64e4d3SHariprasad Shenai 					     &fl->bar2_qid);
4355f7917c00SJeff Kirsher 		refill_fl(adap, fl, fl_cap(fl), GFP_KERNEL);
4356f7917c00SJeff Kirsher 	}
4357b8b1ae99SHariprasad Shenai 
4358b8b1ae99SHariprasad Shenai 	/* For T5 and later we attempt to set up the Congestion Manager values
4359b8b1ae99SHariprasad Shenai 	 * of the new RX Ethernet Queue.  This should really be handled by
4360b8b1ae99SHariprasad Shenai 	 * firmware because it's more complex than any host driver wants to
4361b8b1ae99SHariprasad Shenai 	 * get involved with and it's different per chip and this is almost
4362b8b1ae99SHariprasad Shenai 	 * certainly wrong.  Firmware would be wrong as well, but it would be
4363b8b1ae99SHariprasad Shenai 	 * a lot easier to fix in one place ...  For now we do something very
4364b8b1ae99SHariprasad Shenai 	 * simple (and hopefully less wrong).
4365b8b1ae99SHariprasad Shenai 	 */
4366b8b1ae99SHariprasad Shenai 	if (!is_t4(adap->params.chip) && cong >= 0) {
43672216d014SHariprasad Shenai 		u32 param, val, ch_map = 0;
4368b8b1ae99SHariprasad Shenai 		int i;
43692216d014SHariprasad Shenai 		u16 cng_ch_bits_log = adap->params.arch.cng_ch_bits_log;
4370b8b1ae99SHariprasad Shenai 
4371b8b1ae99SHariprasad Shenai 		param = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DMAQ) |
4372b8b1ae99SHariprasad Shenai 			 FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_DMAQ_CONM_CTXT) |
4373b8b1ae99SHariprasad Shenai 			 FW_PARAMS_PARAM_YZ_V(iq->cntxt_id));
4374b8b1ae99SHariprasad Shenai 		if (cong == 0) {
4375b8b1ae99SHariprasad Shenai 			val = CONMCTXT_CNGTPMODE_V(CONMCTXT_CNGTPMODE_QUEUE_X);
4376b8b1ae99SHariprasad Shenai 		} else {
4377b8b1ae99SHariprasad Shenai 			val =
4378b8b1ae99SHariprasad Shenai 			    CONMCTXT_CNGTPMODE_V(CONMCTXT_CNGTPMODE_CHANNEL_X);
4379b8b1ae99SHariprasad Shenai 			for (i = 0; i < 4; i++) {
4380b8b1ae99SHariprasad Shenai 				if (cong & (1 << i))
43812216d014SHariprasad Shenai 					ch_map |= 1 << (i << cng_ch_bits_log);
4382b8b1ae99SHariprasad Shenai 			}
43832216d014SHariprasad Shenai 			val |= CONMCTXT_CNGCHMAP_V(ch_map);
4384b8b1ae99SHariprasad Shenai 		}
4385b2612722SHariprasad Shenai 		ret = t4_set_params(adap, adap->mbox, adap->pf, 0, 1,
4386b8b1ae99SHariprasad Shenai 				    &param, &val);
4387b8b1ae99SHariprasad Shenai 		if (ret)
4388b8b1ae99SHariprasad Shenai 			dev_warn(adap->pdev_dev, "Failed to set Congestion"
4389b8b1ae99SHariprasad Shenai 				 " Manager Context for Ingress Queue %d: %d\n",
4390b8b1ae99SHariprasad Shenai 				 iq->cntxt_id, -ret);
4391b8b1ae99SHariprasad Shenai 	}
4392b8b1ae99SHariprasad Shenai 
4393f7917c00SJeff Kirsher 	return 0;
4394f7917c00SJeff Kirsher 
4395f7917c00SJeff Kirsher fl_nomem:
4396f7917c00SJeff Kirsher 	ret = -ENOMEM;
4397f7917c00SJeff Kirsher err:
4398f7917c00SJeff Kirsher 	if (iq->desc) {
4399f7917c00SJeff Kirsher 		dma_free_coherent(adap->pdev_dev, iq->size * iq->iqe_len,
4400f7917c00SJeff Kirsher 				  iq->desc, iq->phys_addr);
4401f7917c00SJeff Kirsher 		iq->desc = NULL;
4402f7917c00SJeff Kirsher 	}
4403f7917c00SJeff Kirsher 	if (fl && fl->desc) {
4404f7917c00SJeff Kirsher 		kfree(fl->sdesc);
4405f7917c00SJeff Kirsher 		fl->sdesc = NULL;
4406f7917c00SJeff Kirsher 		dma_free_coherent(adap->pdev_dev, flsz * sizeof(struct tx_desc),
4407f7917c00SJeff Kirsher 				  fl->desc, fl->addr);
4408f7917c00SJeff Kirsher 		fl->desc = NULL;
4409f7917c00SJeff Kirsher 	}
4410f7917c00SJeff Kirsher 	return ret;
4411f7917c00SJeff Kirsher }
4412f7917c00SJeff Kirsher 
4413f7917c00SJeff Kirsher static void init_txq(struct adapter *adap, struct sge_txq *q, unsigned int id)
4414f7917c00SJeff Kirsher {
441522adfe0aSSantosh Rastapur 	q->cntxt_id = id;
4416df64e4d3SHariprasad Shenai 	q->bar2_addr = bar2_address(adap,
4417df64e4d3SHariprasad Shenai 				    q->cntxt_id,
4418df64e4d3SHariprasad Shenai 				    T4_BAR2_QTYPE_EGRESS,
4419df64e4d3SHariprasad Shenai 				    &q->bar2_qid);
4420f7917c00SJeff Kirsher 	q->in_use = 0;
4421f7917c00SJeff Kirsher 	q->cidx = q->pidx = 0;
4422f7917c00SJeff Kirsher 	q->stops = q->restarts = 0;
4423f7917c00SJeff Kirsher 	q->stat = (void *)&q->desc[q->size];
44243069ee9bSVipul Pandya 	spin_lock_init(&q->db_lock);
4425f7917c00SJeff Kirsher 	adap->sge.egr_map[id - adap->sge.egr_start] = q;
4426f7917c00SJeff Kirsher }
4427f7917c00SJeff Kirsher 
4428d429005fSVishal Kulkarni /**
4429d429005fSVishal Kulkarni  *	t4_sge_alloc_eth_txq - allocate an Ethernet TX Queue
4430d429005fSVishal Kulkarni  *	@adap: the adapter
4431d429005fSVishal Kulkarni  *	@txq: the SGE Ethernet TX Queue to initialize
4432d429005fSVishal Kulkarni  *	@dev: the Linux Network Device
4433d429005fSVishal Kulkarni  *	@netdevq: the corresponding Linux TX Queue
4434d429005fSVishal Kulkarni  *	@iqid: the Ingress Queue to which to deliver CIDX Update messages
4435d429005fSVishal Kulkarni  *	@dbqt: whether this TX Queue will use the SGE Doorbell Queue Timers
4436d429005fSVishal Kulkarni  */
4437f7917c00SJeff Kirsher int t4_sge_alloc_eth_txq(struct adapter *adap, struct sge_eth_txq *txq,
4438f7917c00SJeff Kirsher 			 struct net_device *dev, struct netdev_queue *netdevq,
4439d429005fSVishal Kulkarni 			 unsigned int iqid, u8 dbqt)
4440f7917c00SJeff Kirsher {
4441d429005fSVishal Kulkarni 	unsigned int chip_ver = CHELSIO_CHIP_VERSION(adap->params.chip);
4442f7917c00SJeff Kirsher 	struct port_info *pi = netdev_priv(dev);
4443d429005fSVishal Kulkarni 	struct sge *s = &adap->sge;
4444d429005fSVishal Kulkarni 	struct fw_eq_eth_cmd c;
4445d429005fSVishal Kulkarni 	int ret, nentries;
4446f7917c00SJeff Kirsher 
4447f7917c00SJeff Kirsher 	/* Add status entries */
444852367a76SVipul Pandya 	nentries = txq->q.size + s->stat_len / sizeof(struct tx_desc);
4449f7917c00SJeff Kirsher 
4450f7917c00SJeff Kirsher 	txq->q.desc = alloc_ring(adap->pdev_dev, txq->q.size,
4451f7917c00SJeff Kirsher 			sizeof(struct tx_desc), sizeof(struct tx_sw_desc),
445252367a76SVipul Pandya 			&txq->q.phys_addr, &txq->q.sdesc, s->stat_len,
4453f7917c00SJeff Kirsher 			netdev_queue_numa_node_read(netdevq));
4454f7917c00SJeff Kirsher 	if (!txq->q.desc)
4455f7917c00SJeff Kirsher 		return -ENOMEM;
4456f7917c00SJeff Kirsher 
4457f7917c00SJeff Kirsher 	memset(&c, 0, sizeof(c));
4458e2ac9628SHariprasad Shenai 	c.op_to_vfn = htonl(FW_CMD_OP_V(FW_EQ_ETH_CMD) | FW_CMD_REQUEST_F |
4459e2ac9628SHariprasad Shenai 			    FW_CMD_WRITE_F | FW_CMD_EXEC_F |
4460b2612722SHariprasad Shenai 			    FW_EQ_ETH_CMD_PFN_V(adap->pf) |
44616e4b51a6SHariprasad Shenai 			    FW_EQ_ETH_CMD_VFN_V(0));
44626e4b51a6SHariprasad Shenai 	c.alloc_to_len16 = htonl(FW_EQ_ETH_CMD_ALLOC_F |
44636e4b51a6SHariprasad Shenai 				 FW_EQ_ETH_CMD_EQSTART_F | FW_LEN16(c));
4464d429005fSVishal Kulkarni 
4465d429005fSVishal Kulkarni 	/* For TX Ethernet Queues using the SGE Doorbell Queue Timer
4466d429005fSVishal Kulkarni 	 * mechanism, we use Ingress Queue messages for Hardware Consumer
4467d429005fSVishal Kulkarni 	 * Index Updates on the TX Queue.  Otherwise we have the Hardware
4468d429005fSVishal Kulkarni 	 * write the CIDX Updates into the Status Page at the end of the
4469d429005fSVishal Kulkarni 	 * TX Queue.
4470d429005fSVishal Kulkarni 	 */
44717c3bebc3SRaju Rangoju 	c.autoequiqe_to_viid = htonl(FW_EQ_ETH_CMD_AUTOEQUEQE_F |
44726e4b51a6SHariprasad Shenai 				     FW_EQ_ETH_CMD_VIID_V(pi->viid));
4473d429005fSVishal Kulkarni 
44741ecc7b7aSHariprasad Shenai 	c.fetchszm_to_iqid =
44757c3bebc3SRaju Rangoju 		htonl(FW_EQ_ETH_CMD_HOSTFCMODE_V(HOSTFCMODE_STATUS_PAGE_X) |
44766e4b51a6SHariprasad Shenai 		      FW_EQ_ETH_CMD_PCIECHN_V(pi->tx_chan) |
44771ecc7b7aSHariprasad Shenai 		      FW_EQ_ETH_CMD_FETCHRO_F | FW_EQ_ETH_CMD_IQID_V(iqid));
4478d429005fSVishal Kulkarni 
4479d429005fSVishal Kulkarni 	/* Note that the CIDX Flush Threshold should match MAX_TX_RECLAIM. */
44801ecc7b7aSHariprasad Shenai 	c.dcaen_to_eqsize =
4481d429005fSVishal Kulkarni 		htonl(FW_EQ_ETH_CMD_FBMIN_V(chip_ver <= CHELSIO_T5
4482d429005fSVishal Kulkarni 					    ? FETCHBURSTMIN_64B_X
4483d429005fSVishal Kulkarni 					    : FETCHBURSTMIN_64B_T6_X) |
44841ecc7b7aSHariprasad Shenai 		      FW_EQ_ETH_CMD_FBMAX_V(FETCHBURSTMAX_512B_X) |
44851ecc7b7aSHariprasad Shenai 		      FW_EQ_ETH_CMD_CIDXFTHRESH_V(CIDXFLUSHTHRESH_32_X) |
44866e4b51a6SHariprasad Shenai 		      FW_EQ_ETH_CMD_EQSIZE_V(nentries));
4487d429005fSVishal Kulkarni 
4488f7917c00SJeff Kirsher 	c.eqaddr = cpu_to_be64(txq->q.phys_addr);
4489f7917c00SJeff Kirsher 
4490d429005fSVishal Kulkarni 	/* If we're using the SGE Doorbell Queue Timer mechanism, pass in the
4491d429005fSVishal Kulkarni 	 * currently configured Timer Index.  THis can be changed later via an
4492d429005fSVishal Kulkarni 	 * ethtool -C tx-usecs {Timer Val} command.  Note that the SGE
4493d429005fSVishal Kulkarni 	 * Doorbell Queue mode is currently automatically enabled in the
4494d429005fSVishal Kulkarni 	 * Firmware by setting either AUTOEQUEQE or AUTOEQUIQE ...
4495d429005fSVishal Kulkarni 	 */
4496d429005fSVishal Kulkarni 	if (dbqt)
4497d429005fSVishal Kulkarni 		c.timeren_timerix =
4498d429005fSVishal Kulkarni 			cpu_to_be32(FW_EQ_ETH_CMD_TIMEREN_F |
4499d429005fSVishal Kulkarni 				    FW_EQ_ETH_CMD_TIMERIX_V(txq->dbqtimerix));
4500d429005fSVishal Kulkarni 
4501b2612722SHariprasad Shenai 	ret = t4_wr_mbox(adap, adap->mbox, &c, sizeof(c), &c);
4502f7917c00SJeff Kirsher 	if (ret) {
4503f7917c00SJeff Kirsher 		kfree(txq->q.sdesc);
4504f7917c00SJeff Kirsher 		txq->q.sdesc = NULL;
4505f7917c00SJeff Kirsher 		dma_free_coherent(adap->pdev_dev,
4506f7917c00SJeff Kirsher 				  nentries * sizeof(struct tx_desc),
4507f7917c00SJeff Kirsher 				  txq->q.desc, txq->q.phys_addr);
4508f7917c00SJeff Kirsher 		txq->q.desc = NULL;
4509f7917c00SJeff Kirsher 		return ret;
4510f7917c00SJeff Kirsher 	}
4511f7917c00SJeff Kirsher 
4512ab677ff4SHariprasad Shenai 	txq->q.q_type = CXGB4_TXQ_ETH;
45136e4b51a6SHariprasad Shenai 	init_txq(adap, &txq->q, FW_EQ_ETH_CMD_EQID_G(ntohl(c.eqid_pkd)));
4514f7917c00SJeff Kirsher 	txq->txq = netdevq;
45151a2a14fbSRahul Lakkireddy 	txq->tso = 0;
45161a2a14fbSRahul Lakkireddy 	txq->uso = 0;
45171a2a14fbSRahul Lakkireddy 	txq->tx_cso = 0;
45181a2a14fbSRahul Lakkireddy 	txq->vlan_ins = 0;
4519f7917c00SJeff Kirsher 	txq->mapping_err = 0;
4520d429005fSVishal Kulkarni 	txq->dbqt = dbqt;
4521d429005fSVishal Kulkarni 
4522f7917c00SJeff Kirsher 	return 0;
4523f7917c00SJeff Kirsher }
4524f7917c00SJeff Kirsher 
4525f7917c00SJeff Kirsher int t4_sge_alloc_ctrl_txq(struct adapter *adap, struct sge_ctrl_txq *txq,
4526f7917c00SJeff Kirsher 			  struct net_device *dev, unsigned int iqid,
4527f7917c00SJeff Kirsher 			  unsigned int cmplqid)
4528f7917c00SJeff Kirsher {
4529d429005fSVishal Kulkarni 	unsigned int chip_ver = CHELSIO_CHIP_VERSION(adap->params.chip);
4530f7917c00SJeff Kirsher 	struct port_info *pi = netdev_priv(dev);
4531d429005fSVishal Kulkarni 	struct sge *s = &adap->sge;
4532d429005fSVishal Kulkarni 	struct fw_eq_ctrl_cmd c;
4533d429005fSVishal Kulkarni 	int ret, nentries;
4534f7917c00SJeff Kirsher 
4535f7917c00SJeff Kirsher 	/* Add status entries */
453652367a76SVipul Pandya 	nentries = txq->q.size + s->stat_len / sizeof(struct tx_desc);
4537f7917c00SJeff Kirsher 
4538f7917c00SJeff Kirsher 	txq->q.desc = alloc_ring(adap->pdev_dev, nentries,
4539f7917c00SJeff Kirsher 				 sizeof(struct tx_desc), 0, &txq->q.phys_addr,
4540982b81ebSHariprasad Shenai 				 NULL, 0, dev_to_node(adap->pdev_dev));
4541f7917c00SJeff Kirsher 	if (!txq->q.desc)
4542f7917c00SJeff Kirsher 		return -ENOMEM;
4543f7917c00SJeff Kirsher 
4544e2ac9628SHariprasad Shenai 	c.op_to_vfn = htonl(FW_CMD_OP_V(FW_EQ_CTRL_CMD) | FW_CMD_REQUEST_F |
4545e2ac9628SHariprasad Shenai 			    FW_CMD_WRITE_F | FW_CMD_EXEC_F |
4546b2612722SHariprasad Shenai 			    FW_EQ_CTRL_CMD_PFN_V(adap->pf) |
45476e4b51a6SHariprasad Shenai 			    FW_EQ_CTRL_CMD_VFN_V(0));
45486e4b51a6SHariprasad Shenai 	c.alloc_to_len16 = htonl(FW_EQ_CTRL_CMD_ALLOC_F |
45496e4b51a6SHariprasad Shenai 				 FW_EQ_CTRL_CMD_EQSTART_F | FW_LEN16(c));
45506e4b51a6SHariprasad Shenai 	c.cmpliqid_eqid = htonl(FW_EQ_CTRL_CMD_CMPLIQID_V(cmplqid));
4551f7917c00SJeff Kirsher 	c.physeqid_pkd = htonl(0);
45521ecc7b7aSHariprasad Shenai 	c.fetchszm_to_iqid =
45531ecc7b7aSHariprasad Shenai 		htonl(FW_EQ_CTRL_CMD_HOSTFCMODE_V(HOSTFCMODE_STATUS_PAGE_X) |
45546e4b51a6SHariprasad Shenai 		      FW_EQ_CTRL_CMD_PCIECHN_V(pi->tx_chan) |
45551ecc7b7aSHariprasad Shenai 		      FW_EQ_CTRL_CMD_FETCHRO_F | FW_EQ_CTRL_CMD_IQID_V(iqid));
45561ecc7b7aSHariprasad Shenai 	c.dcaen_to_eqsize =
4557d429005fSVishal Kulkarni 		htonl(FW_EQ_CTRL_CMD_FBMIN_V(chip_ver <= CHELSIO_T5
4558d429005fSVishal Kulkarni 					     ? FETCHBURSTMIN_64B_X
4559d429005fSVishal Kulkarni 					     : FETCHBURSTMIN_64B_T6_X) |
45601ecc7b7aSHariprasad Shenai 		      FW_EQ_CTRL_CMD_FBMAX_V(FETCHBURSTMAX_512B_X) |
45611ecc7b7aSHariprasad Shenai 		      FW_EQ_CTRL_CMD_CIDXFTHRESH_V(CIDXFLUSHTHRESH_32_X) |
45626e4b51a6SHariprasad Shenai 		      FW_EQ_CTRL_CMD_EQSIZE_V(nentries));
4563f7917c00SJeff Kirsher 	c.eqaddr = cpu_to_be64(txq->q.phys_addr);
4564f7917c00SJeff Kirsher 
4565b2612722SHariprasad Shenai 	ret = t4_wr_mbox(adap, adap->mbox, &c, sizeof(c), &c);
4566f7917c00SJeff Kirsher 	if (ret) {
4567f7917c00SJeff Kirsher 		dma_free_coherent(adap->pdev_dev,
4568f7917c00SJeff Kirsher 				  nentries * sizeof(struct tx_desc),
4569f7917c00SJeff Kirsher 				  txq->q.desc, txq->q.phys_addr);
4570f7917c00SJeff Kirsher 		txq->q.desc = NULL;
4571f7917c00SJeff Kirsher 		return ret;
4572f7917c00SJeff Kirsher 	}
4573f7917c00SJeff Kirsher 
4574ab677ff4SHariprasad Shenai 	txq->q.q_type = CXGB4_TXQ_CTRL;
45756e4b51a6SHariprasad Shenai 	init_txq(adap, &txq->q, FW_EQ_CTRL_CMD_EQID_G(ntohl(c.cmpliqid_eqid)));
4576f7917c00SJeff Kirsher 	txq->adap = adap;
4577f7917c00SJeff Kirsher 	skb_queue_head_init(&txq->sendq);
4578f7917c00SJeff Kirsher 	tasklet_init(&txq->qresume_tsk, restart_ctrlq, (unsigned long)txq);
4579f7917c00SJeff Kirsher 	txq->full = 0;
4580f7917c00SJeff Kirsher 	return 0;
4581f7917c00SJeff Kirsher }
4582f7917c00SJeff Kirsher 
45830fbc81b3SHariprasad Shenai int t4_sge_mod_ctrl_txq(struct adapter *adap, unsigned int eqid,
45840fbc81b3SHariprasad Shenai 			unsigned int cmplqid)
45850fbc81b3SHariprasad Shenai {
45860fbc81b3SHariprasad Shenai 	u32 param, val;
45870fbc81b3SHariprasad Shenai 
45880fbc81b3SHariprasad Shenai 	param = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DMAQ) |
45890fbc81b3SHariprasad Shenai 		 FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_DMAQ_EQ_CMPLIQID_CTRL) |
45900fbc81b3SHariprasad Shenai 		 FW_PARAMS_PARAM_YZ_V(eqid));
45910fbc81b3SHariprasad Shenai 	val = cmplqid;
45920fbc81b3SHariprasad Shenai 	return t4_set_params(adap, adap->mbox, adap->pf, 0, 1, &param, &val);
45930fbc81b3SHariprasad Shenai }
45940fbc81b3SHariprasad Shenai 
45952d0cb84dSRahul Lakkireddy static int t4_sge_alloc_ofld_txq(struct adapter *adap, struct sge_txq *q,
45962d0cb84dSRahul Lakkireddy 				 struct net_device *dev, u32 cmd, u32 iqid)
4597f7917c00SJeff Kirsher {
4598d429005fSVishal Kulkarni 	unsigned int chip_ver = CHELSIO_CHIP_VERSION(adap->params.chip);
4599f7917c00SJeff Kirsher 	struct port_info *pi = netdev_priv(dev);
46002d0cb84dSRahul Lakkireddy 	struct sge *s = &adap->sge;
46012d0cb84dSRahul Lakkireddy 	struct fw_eq_ofld_cmd c;
46022d0cb84dSRahul Lakkireddy 	u32 fb_min, nentries;
46032d0cb84dSRahul Lakkireddy 	int ret;
4604f7917c00SJeff Kirsher 
4605f7917c00SJeff Kirsher 	/* Add status entries */
46062d0cb84dSRahul Lakkireddy 	nentries = q->size + s->stat_len / sizeof(struct tx_desc);
46072d0cb84dSRahul Lakkireddy 	q->desc = alloc_ring(adap->pdev_dev, q->size, sizeof(struct tx_desc),
46082d0cb84dSRahul Lakkireddy 			     sizeof(struct tx_sw_desc), &q->phys_addr,
46092d0cb84dSRahul Lakkireddy 			     &q->sdesc, s->stat_len, NUMA_NO_NODE);
46102d0cb84dSRahul Lakkireddy 	if (!q->desc)
4611f7917c00SJeff Kirsher 		return -ENOMEM;
4612f7917c00SJeff Kirsher 
46132d0cb84dSRahul Lakkireddy 	if (chip_ver <= CHELSIO_T5)
46142d0cb84dSRahul Lakkireddy 		fb_min = FETCHBURSTMIN_64B_X;
46152d0cb84dSRahul Lakkireddy 	else
46162d0cb84dSRahul Lakkireddy 		fb_min = FETCHBURSTMIN_64B_T6_X;
46172d0cb84dSRahul Lakkireddy 
4618f7917c00SJeff Kirsher 	memset(&c, 0, sizeof(c));
4619ab677ff4SHariprasad Shenai 	c.op_to_vfn = htonl(FW_CMD_OP_V(cmd) | FW_CMD_REQUEST_F |
4620e2ac9628SHariprasad Shenai 			    FW_CMD_WRITE_F | FW_CMD_EXEC_F |
4621b2612722SHariprasad Shenai 			    FW_EQ_OFLD_CMD_PFN_V(adap->pf) |
46226e4b51a6SHariprasad Shenai 			    FW_EQ_OFLD_CMD_VFN_V(0));
46236e4b51a6SHariprasad Shenai 	c.alloc_to_len16 = htonl(FW_EQ_OFLD_CMD_ALLOC_F |
46246e4b51a6SHariprasad Shenai 				 FW_EQ_OFLD_CMD_EQSTART_F | FW_LEN16(c));
46251ecc7b7aSHariprasad Shenai 	c.fetchszm_to_iqid =
46261ecc7b7aSHariprasad Shenai 		htonl(FW_EQ_OFLD_CMD_HOSTFCMODE_V(HOSTFCMODE_STATUS_PAGE_X) |
46276e4b51a6SHariprasad Shenai 		      FW_EQ_OFLD_CMD_PCIECHN_V(pi->tx_chan) |
46281ecc7b7aSHariprasad Shenai 		      FW_EQ_OFLD_CMD_FETCHRO_F | FW_EQ_OFLD_CMD_IQID_V(iqid));
46291ecc7b7aSHariprasad Shenai 	c.dcaen_to_eqsize =
46302d0cb84dSRahul Lakkireddy 		htonl(FW_EQ_OFLD_CMD_FBMIN_V(fb_min) |
46311ecc7b7aSHariprasad Shenai 		      FW_EQ_OFLD_CMD_FBMAX_V(FETCHBURSTMAX_512B_X) |
46321ecc7b7aSHariprasad Shenai 		      FW_EQ_OFLD_CMD_CIDXFTHRESH_V(CIDXFLUSHTHRESH_32_X) |
46336e4b51a6SHariprasad Shenai 		      FW_EQ_OFLD_CMD_EQSIZE_V(nentries));
46342d0cb84dSRahul Lakkireddy 	c.eqaddr = cpu_to_be64(q->phys_addr);
4635f7917c00SJeff Kirsher 
4636b2612722SHariprasad Shenai 	ret = t4_wr_mbox(adap, adap->mbox, &c, sizeof(c), &c);
4637f7917c00SJeff Kirsher 	if (ret) {
46382d0cb84dSRahul Lakkireddy 		kfree(q->sdesc);
46392d0cb84dSRahul Lakkireddy 		q->sdesc = NULL;
4640f7917c00SJeff Kirsher 		dma_free_coherent(adap->pdev_dev,
4641f7917c00SJeff Kirsher 				  nentries * sizeof(struct tx_desc),
46422d0cb84dSRahul Lakkireddy 				  q->desc, q->phys_addr);
46432d0cb84dSRahul Lakkireddy 		q->desc = NULL;
4644f7917c00SJeff Kirsher 		return ret;
4645f7917c00SJeff Kirsher 	}
4646f7917c00SJeff Kirsher 
46472d0cb84dSRahul Lakkireddy 	init_txq(adap, q, FW_EQ_OFLD_CMD_EQID_G(ntohl(c.eqid_pkd)));
46482d0cb84dSRahul Lakkireddy 	return 0;
46492d0cb84dSRahul Lakkireddy }
46502d0cb84dSRahul Lakkireddy 
46512d0cb84dSRahul Lakkireddy int t4_sge_alloc_uld_txq(struct adapter *adap, struct sge_uld_txq *txq,
46522d0cb84dSRahul Lakkireddy 			 struct net_device *dev, unsigned int iqid,
46532d0cb84dSRahul Lakkireddy 			 unsigned int uld_type)
46542d0cb84dSRahul Lakkireddy {
46552d0cb84dSRahul Lakkireddy 	u32 cmd = FW_EQ_OFLD_CMD;
46562d0cb84dSRahul Lakkireddy 	int ret;
46572d0cb84dSRahul Lakkireddy 
46582d0cb84dSRahul Lakkireddy 	if (unlikely(uld_type == CXGB4_TX_CRYPTO))
46592d0cb84dSRahul Lakkireddy 		cmd = FW_EQ_CTRL_CMD;
46602d0cb84dSRahul Lakkireddy 
46612d0cb84dSRahul Lakkireddy 	ret = t4_sge_alloc_ofld_txq(adap, &txq->q, dev, cmd, iqid);
46622d0cb84dSRahul Lakkireddy 	if (ret)
46632d0cb84dSRahul Lakkireddy 		return ret;
46642d0cb84dSRahul Lakkireddy 
4665ab677ff4SHariprasad Shenai 	txq->q.q_type = CXGB4_TXQ_ULD;
4666f7917c00SJeff Kirsher 	txq->adap = adap;
4667f7917c00SJeff Kirsher 	skb_queue_head_init(&txq->sendq);
4668f7917c00SJeff Kirsher 	tasklet_init(&txq->qresume_tsk, restart_ofldq, (unsigned long)txq);
4669f7917c00SJeff Kirsher 	txq->full = 0;
4670f7917c00SJeff Kirsher 	txq->mapping_err = 0;
4671f7917c00SJeff Kirsher 	return 0;
4672f7917c00SJeff Kirsher }
4673f7917c00SJeff Kirsher 
46742d0cb84dSRahul Lakkireddy int t4_sge_alloc_ethofld_txq(struct adapter *adap, struct sge_eohw_txq *txq,
46752d0cb84dSRahul Lakkireddy 			     struct net_device *dev, u32 iqid)
46762d0cb84dSRahul Lakkireddy {
46772d0cb84dSRahul Lakkireddy 	int ret;
46782d0cb84dSRahul Lakkireddy 
46792d0cb84dSRahul Lakkireddy 	ret = t4_sge_alloc_ofld_txq(adap, &txq->q, dev, FW_EQ_OFLD_CMD, iqid);
46802d0cb84dSRahul Lakkireddy 	if (ret)
46812d0cb84dSRahul Lakkireddy 		return ret;
46822d0cb84dSRahul Lakkireddy 
46832d0cb84dSRahul Lakkireddy 	txq->q.q_type = CXGB4_TXQ_ULD;
46842d0cb84dSRahul Lakkireddy 	spin_lock_init(&txq->lock);
46852d0cb84dSRahul Lakkireddy 	txq->adap = adap;
46862d0cb84dSRahul Lakkireddy 	txq->tso = 0;
46878311f0beSRahul Lakkireddy 	txq->uso = 0;
46882d0cb84dSRahul Lakkireddy 	txq->tx_cso = 0;
46892d0cb84dSRahul Lakkireddy 	txq->vlan_ins = 0;
46902d0cb84dSRahul Lakkireddy 	txq->mapping_err = 0;
46912d0cb84dSRahul Lakkireddy 	return 0;
46922d0cb84dSRahul Lakkireddy }
46932d0cb84dSRahul Lakkireddy 
4694ab677ff4SHariprasad Shenai void free_txq(struct adapter *adap, struct sge_txq *q)
4695f7917c00SJeff Kirsher {
469652367a76SVipul Pandya 	struct sge *s = &adap->sge;
469752367a76SVipul Pandya 
4698f7917c00SJeff Kirsher 	dma_free_coherent(adap->pdev_dev,
469952367a76SVipul Pandya 			  q->size * sizeof(struct tx_desc) + s->stat_len,
4700f7917c00SJeff Kirsher 			  q->desc, q->phys_addr);
4701f7917c00SJeff Kirsher 	q->cntxt_id = 0;
4702f7917c00SJeff Kirsher 	q->sdesc = NULL;
4703f7917c00SJeff Kirsher 	q->desc = NULL;
4704f7917c00SJeff Kirsher }
4705f7917c00SJeff Kirsher 
470694cdb8bbSHariprasad Shenai void free_rspq_fl(struct adapter *adap, struct sge_rspq *rq,
4707f7917c00SJeff Kirsher 		  struct sge_fl *fl)
4708f7917c00SJeff Kirsher {
470952367a76SVipul Pandya 	struct sge *s = &adap->sge;
4710f7917c00SJeff Kirsher 	unsigned int fl_id = fl ? fl->cntxt_id : 0xffff;
4711f7917c00SJeff Kirsher 
4712f7917c00SJeff Kirsher 	adap->sge.ingr_map[rq->cntxt_id - adap->sge.ingr_start] = NULL;
4713b2612722SHariprasad Shenai 	t4_iq_free(adap, adap->mbox, adap->pf, 0, FW_IQ_TYPE_FL_INT_CAP,
4714f7917c00SJeff Kirsher 		   rq->cntxt_id, fl_id, 0xffff);
4715f7917c00SJeff Kirsher 	dma_free_coherent(adap->pdev_dev, (rq->size + 1) * rq->iqe_len,
4716f7917c00SJeff Kirsher 			  rq->desc, rq->phys_addr);
4717f7917c00SJeff Kirsher 	netif_napi_del(&rq->napi);
4718f7917c00SJeff Kirsher 	rq->netdev = NULL;
4719f7917c00SJeff Kirsher 	rq->cntxt_id = rq->abs_id = 0;
4720f7917c00SJeff Kirsher 	rq->desc = NULL;
4721f7917c00SJeff Kirsher 
4722f7917c00SJeff Kirsher 	if (fl) {
4723f7917c00SJeff Kirsher 		free_rx_bufs(adap, fl, fl->avail);
472452367a76SVipul Pandya 		dma_free_coherent(adap->pdev_dev, fl->size * 8 + s->stat_len,
4725f7917c00SJeff Kirsher 				  fl->desc, fl->addr);
4726f7917c00SJeff Kirsher 		kfree(fl->sdesc);
4727f7917c00SJeff Kirsher 		fl->sdesc = NULL;
4728f7917c00SJeff Kirsher 		fl->cntxt_id = 0;
4729f7917c00SJeff Kirsher 		fl->desc = NULL;
4730f7917c00SJeff Kirsher 	}
4731f7917c00SJeff Kirsher }
4732f7917c00SJeff Kirsher 
4733f7917c00SJeff Kirsher /**
47345fa76694SHariprasad Shenai  *      t4_free_ofld_rxqs - free a block of consecutive Rx queues
47355fa76694SHariprasad Shenai  *      @adap: the adapter
47365fa76694SHariprasad Shenai  *      @n: number of queues
47375fa76694SHariprasad Shenai  *      @q: pointer to first queue
47385fa76694SHariprasad Shenai  *
47395fa76694SHariprasad Shenai  *      Release the resources of a consecutive block of offload Rx queues.
47405fa76694SHariprasad Shenai  */
47415fa76694SHariprasad Shenai void t4_free_ofld_rxqs(struct adapter *adap, int n, struct sge_ofld_rxq *q)
47425fa76694SHariprasad Shenai {
47435fa76694SHariprasad Shenai 	for ( ; n; n--, q++)
47445fa76694SHariprasad Shenai 		if (q->rspq.desc)
47455fa76694SHariprasad Shenai 			free_rspq_fl(adap, &q->rspq,
47465fa76694SHariprasad Shenai 				     q->fl.size ? &q->fl : NULL);
47475fa76694SHariprasad Shenai }
47485fa76694SHariprasad Shenai 
47492d0cb84dSRahul Lakkireddy void t4_sge_free_ethofld_txq(struct adapter *adap, struct sge_eohw_txq *txq)
47502d0cb84dSRahul Lakkireddy {
47512d0cb84dSRahul Lakkireddy 	if (txq->q.desc) {
47522d0cb84dSRahul Lakkireddy 		t4_ofld_eq_free(adap, adap->mbox, adap->pf, 0,
47532d0cb84dSRahul Lakkireddy 				txq->q.cntxt_id);
47542d0cb84dSRahul Lakkireddy 		free_tx_desc(adap, &txq->q, txq->q.in_use, false);
47552d0cb84dSRahul Lakkireddy 		kfree(txq->q.sdesc);
47562d0cb84dSRahul Lakkireddy 		free_txq(adap, &txq->q);
47572d0cb84dSRahul Lakkireddy 	}
47582d0cb84dSRahul Lakkireddy }
47592d0cb84dSRahul Lakkireddy 
47605fa76694SHariprasad Shenai /**
4761f7917c00SJeff Kirsher  *	t4_free_sge_resources - free SGE resources
4762f7917c00SJeff Kirsher  *	@adap: the adapter
4763f7917c00SJeff Kirsher  *
4764f7917c00SJeff Kirsher  *	Frees resources used by the SGE queue sets.
4765f7917c00SJeff Kirsher  */
4766f7917c00SJeff Kirsher void t4_free_sge_resources(struct adapter *adap)
4767f7917c00SJeff Kirsher {
4768f7917c00SJeff Kirsher 	int i;
4769ebf4dc2bSHariprasad Shenai 	struct sge_eth_rxq *eq;
4770ebf4dc2bSHariprasad Shenai 	struct sge_eth_txq *etq;
4771ebf4dc2bSHariprasad Shenai 
4772ebf4dc2bSHariprasad Shenai 	/* stop all Rx queues in order to start them draining */
4773ebf4dc2bSHariprasad Shenai 	for (i = 0; i < adap->sge.ethqsets; i++) {
4774ebf4dc2bSHariprasad Shenai 		eq = &adap->sge.ethrxq[i];
4775ebf4dc2bSHariprasad Shenai 		if (eq->rspq.desc)
4776ebf4dc2bSHariprasad Shenai 			t4_iq_stop(adap, adap->mbox, adap->pf, 0,
4777ebf4dc2bSHariprasad Shenai 				   FW_IQ_TYPE_FL_INT_CAP,
4778ebf4dc2bSHariprasad Shenai 				   eq->rspq.cntxt_id,
4779ebf4dc2bSHariprasad Shenai 				   eq->fl.size ? eq->fl.cntxt_id : 0xffff,
4780ebf4dc2bSHariprasad Shenai 				   0xffff);
4781ebf4dc2bSHariprasad Shenai 	}
4782f7917c00SJeff Kirsher 
4783f7917c00SJeff Kirsher 	/* clean up Ethernet Tx/Rx queues */
4784ebf4dc2bSHariprasad Shenai 	for (i = 0; i < adap->sge.ethqsets; i++) {
4785ebf4dc2bSHariprasad Shenai 		eq = &adap->sge.ethrxq[i];
4786f7917c00SJeff Kirsher 		if (eq->rspq.desc)
47875fa76694SHariprasad Shenai 			free_rspq_fl(adap, &eq->rspq,
47885fa76694SHariprasad Shenai 				     eq->fl.size ? &eq->fl : NULL);
478976c3a552SRahul Lakkireddy 		if (eq->msix) {
479076c3a552SRahul Lakkireddy 			cxgb4_free_msix_idx_in_bmap(adap, eq->msix->idx);
479176c3a552SRahul Lakkireddy 			eq->msix = NULL;
479276c3a552SRahul Lakkireddy 		}
4793ebf4dc2bSHariprasad Shenai 
4794ebf4dc2bSHariprasad Shenai 		etq = &adap->sge.ethtxq[i];
4795f7917c00SJeff Kirsher 		if (etq->q.desc) {
4796b2612722SHariprasad Shenai 			t4_eth_eq_free(adap, adap->mbox, adap->pf, 0,
4797f7917c00SJeff Kirsher 				       etq->q.cntxt_id);
4798fbe80776SHariprasad Shenai 			__netif_tx_lock_bh(etq->txq);
4799f7917c00SJeff Kirsher 			free_tx_desc(adap, &etq->q, etq->q.in_use, true);
4800fbe80776SHariprasad Shenai 			__netif_tx_unlock_bh(etq->txq);
4801f7917c00SJeff Kirsher 			kfree(etq->q.sdesc);
4802f7917c00SJeff Kirsher 			free_txq(adap, &etq->q);
4803f7917c00SJeff Kirsher 		}
4804f7917c00SJeff Kirsher 	}
4805f7917c00SJeff Kirsher 
4806f7917c00SJeff Kirsher 	/* clean up control Tx queues */
4807f7917c00SJeff Kirsher 	for (i = 0; i < ARRAY_SIZE(adap->sge.ctrlq); i++) {
4808f7917c00SJeff Kirsher 		struct sge_ctrl_txq *cq = &adap->sge.ctrlq[i];
4809f7917c00SJeff Kirsher 
4810f7917c00SJeff Kirsher 		if (cq->q.desc) {
4811f7917c00SJeff Kirsher 			tasklet_kill(&cq->qresume_tsk);
4812b2612722SHariprasad Shenai 			t4_ctrl_eq_free(adap, adap->mbox, adap->pf, 0,
4813f7917c00SJeff Kirsher 					cq->q.cntxt_id);
4814f7917c00SJeff Kirsher 			__skb_queue_purge(&cq->sendq);
4815f7917c00SJeff Kirsher 			free_txq(adap, &cq->q);
4816f7917c00SJeff Kirsher 		}
4817f7917c00SJeff Kirsher 	}
4818f7917c00SJeff Kirsher 
481976c3a552SRahul Lakkireddy 	if (adap->sge.fw_evtq.desc) {
4820f7917c00SJeff Kirsher 		free_rspq_fl(adap, &adap->sge.fw_evtq, NULL);
482176c3a552SRahul Lakkireddy 		if (adap->sge.fwevtq_msix_idx >= 0)
482276c3a552SRahul Lakkireddy 			cxgb4_free_msix_idx_in_bmap(adap,
482376c3a552SRahul Lakkireddy 						    adap->sge.fwevtq_msix_idx);
482476c3a552SRahul Lakkireddy 	}
482576c3a552SRahul Lakkireddy 
482676c3a552SRahul Lakkireddy 	if (adap->sge.nd_msix_idx >= 0)
482776c3a552SRahul Lakkireddy 		cxgb4_free_msix_idx_in_bmap(adap, adap->sge.nd_msix_idx);
4828f7917c00SJeff Kirsher 
4829f7917c00SJeff Kirsher 	if (adap->sge.intrq.desc)
4830f7917c00SJeff Kirsher 		free_rspq_fl(adap, &adap->sge.intrq, NULL);
4831f7917c00SJeff Kirsher 
4832a4569504SAtul Gupta 	if (!is_t4(adap->params.chip)) {
4833a4569504SAtul Gupta 		etq = &adap->sge.ptptxq;
4834a4569504SAtul Gupta 		if (etq->q.desc) {
4835a4569504SAtul Gupta 			t4_eth_eq_free(adap, adap->mbox, adap->pf, 0,
4836a4569504SAtul Gupta 				       etq->q.cntxt_id);
4837a4569504SAtul Gupta 			spin_lock_bh(&adap->ptp_lock);
4838a4569504SAtul Gupta 			free_tx_desc(adap, &etq->q, etq->q.in_use, true);
4839a4569504SAtul Gupta 			spin_unlock_bh(&adap->ptp_lock);
4840a4569504SAtul Gupta 			kfree(etq->q.sdesc);
4841a4569504SAtul Gupta 			free_txq(adap, &etq->q);
4842a4569504SAtul Gupta 		}
4843a4569504SAtul Gupta 	}
4844a4569504SAtul Gupta 
4845f7917c00SJeff Kirsher 	/* clear the reverse egress queue map */
48464b8e27a8SHariprasad Shenai 	memset(adap->sge.egr_map, 0,
48474b8e27a8SHariprasad Shenai 	       adap->sge.egr_sz * sizeof(*adap->sge.egr_map));
4848f7917c00SJeff Kirsher }
4849f7917c00SJeff Kirsher 
4850f7917c00SJeff Kirsher void t4_sge_start(struct adapter *adap)
4851f7917c00SJeff Kirsher {
4852f7917c00SJeff Kirsher 	adap->sge.ethtxq_rover = 0;
4853f7917c00SJeff Kirsher 	mod_timer(&adap->sge.rx_timer, jiffies + RX_QCHECK_PERIOD);
4854f7917c00SJeff Kirsher 	mod_timer(&adap->sge.tx_timer, jiffies + TX_QCHECK_PERIOD);
4855f7917c00SJeff Kirsher }
4856f7917c00SJeff Kirsher 
4857f7917c00SJeff Kirsher /**
4858f7917c00SJeff Kirsher  *	t4_sge_stop - disable SGE operation
4859f7917c00SJeff Kirsher  *	@adap: the adapter
4860f7917c00SJeff Kirsher  *
4861f7917c00SJeff Kirsher  *	Stop tasklets and timers associated with the DMA engine.  Note that
4862f7917c00SJeff Kirsher  *	this is effective only if measures have been taken to disable any HW
4863f7917c00SJeff Kirsher  *	events that may restart them.
4864f7917c00SJeff Kirsher  */
4865f7917c00SJeff Kirsher void t4_sge_stop(struct adapter *adap)
4866f7917c00SJeff Kirsher {
4867f7917c00SJeff Kirsher 	int i;
4868f7917c00SJeff Kirsher 	struct sge *s = &adap->sge;
4869f7917c00SJeff Kirsher 
4870f7917c00SJeff Kirsher 	if (in_interrupt())  /* actions below require waiting */
4871f7917c00SJeff Kirsher 		return;
4872f7917c00SJeff Kirsher 
4873f7917c00SJeff Kirsher 	if (s->rx_timer.function)
4874f7917c00SJeff Kirsher 		del_timer_sync(&s->rx_timer);
4875f7917c00SJeff Kirsher 	if (s->tx_timer.function)
4876f7917c00SJeff Kirsher 		del_timer_sync(&s->tx_timer);
4877f7917c00SJeff Kirsher 
4878ab677ff4SHariprasad Shenai 	if (is_offload(adap)) {
4879ab677ff4SHariprasad Shenai 		struct sge_uld_txq_info *txq_info;
4880f7917c00SJeff Kirsher 
4881ab677ff4SHariprasad Shenai 		txq_info = adap->sge.uld_txq_info[CXGB4_TX_OFLD];
4882ab677ff4SHariprasad Shenai 		if (txq_info) {
4883ab677ff4SHariprasad Shenai 			struct sge_uld_txq *txq = txq_info->uldtxq;
4884ab677ff4SHariprasad Shenai 
4885ab677ff4SHariprasad Shenai 			for_each_ofldtxq(&adap->sge, i) {
4886ab677ff4SHariprasad Shenai 				if (txq->q.desc)
4887ab677ff4SHariprasad Shenai 					tasklet_kill(&txq->qresume_tsk);
4888f7917c00SJeff Kirsher 			}
4889ab677ff4SHariprasad Shenai 		}
4890ab677ff4SHariprasad Shenai 	}
4891ab677ff4SHariprasad Shenai 
4892ab677ff4SHariprasad Shenai 	if (is_pci_uld(adap)) {
4893ab677ff4SHariprasad Shenai 		struct sge_uld_txq_info *txq_info;
4894ab677ff4SHariprasad Shenai 
4895ab677ff4SHariprasad Shenai 		txq_info = adap->sge.uld_txq_info[CXGB4_TX_CRYPTO];
4896ab677ff4SHariprasad Shenai 		if (txq_info) {
4897ab677ff4SHariprasad Shenai 			struct sge_uld_txq *txq = txq_info->uldtxq;
4898ab677ff4SHariprasad Shenai 
4899ab677ff4SHariprasad Shenai 			for_each_ofldtxq(&adap->sge, i) {
4900ab677ff4SHariprasad Shenai 				if (txq->q.desc)
4901ab677ff4SHariprasad Shenai 					tasklet_kill(&txq->qresume_tsk);
4902ab677ff4SHariprasad Shenai 			}
4903ab677ff4SHariprasad Shenai 		}
4904ab677ff4SHariprasad Shenai 	}
4905ab677ff4SHariprasad Shenai 
4906f7917c00SJeff Kirsher 	for (i = 0; i < ARRAY_SIZE(s->ctrlq); i++) {
4907f7917c00SJeff Kirsher 		struct sge_ctrl_txq *cq = &s->ctrlq[i];
4908f7917c00SJeff Kirsher 
4909f7917c00SJeff Kirsher 		if (cq->q.desc)
4910f7917c00SJeff Kirsher 			tasklet_kill(&cq->qresume_tsk);
4911f7917c00SJeff Kirsher 	}
4912f7917c00SJeff Kirsher }
4913f7917c00SJeff Kirsher 
4914f7917c00SJeff Kirsher /**
491506640310SHariprasad Shenai  *	t4_sge_init_soft - grab core SGE values needed by SGE code
4916f7917c00SJeff Kirsher  *	@adap: the adapter
4917f7917c00SJeff Kirsher  *
491806640310SHariprasad Shenai  *	We need to grab the SGE operating parameters that we need to have
491906640310SHariprasad Shenai  *	in order to do our job and make sure we can live with them.
4920f7917c00SJeff Kirsher  */
4921f7917c00SJeff Kirsher 
492252367a76SVipul Pandya static int t4_sge_init_soft(struct adapter *adap)
492352367a76SVipul Pandya {
492452367a76SVipul Pandya 	struct sge *s = &adap->sge;
492552367a76SVipul Pandya 	u32 fl_small_pg, fl_large_pg, fl_small_mtu, fl_large_mtu;
492652367a76SVipul Pandya 	u32 timer_value_0_and_1, timer_value_2_and_3, timer_value_4_and_5;
492752367a76SVipul Pandya 	u32 ingress_rx_threshold;
492852367a76SVipul Pandya 
492952367a76SVipul Pandya 	/*
493052367a76SVipul Pandya 	 * Verify that CPL messages are going to the Ingress Queue for
493152367a76SVipul Pandya 	 * process_responses() and that only packet data is going to the
493252367a76SVipul Pandya 	 * Free Lists.
493352367a76SVipul Pandya 	 */
4934f612b815SHariprasad Shenai 	if ((t4_read_reg(adap, SGE_CONTROL_A) & RXPKTCPLMODE_F) !=
4935f612b815SHariprasad Shenai 	    RXPKTCPLMODE_V(RXPKTCPLMODE_SPLIT_X)) {
493652367a76SVipul Pandya 		dev_err(adap->pdev_dev, "bad SGE CPL MODE\n");
493752367a76SVipul Pandya 		return -EINVAL;
493852367a76SVipul Pandya 	}
493952367a76SVipul Pandya 
494052367a76SVipul Pandya 	/*
494152367a76SVipul Pandya 	 * Validate the Host Buffer Register Array indices that we want to
494252367a76SVipul Pandya 	 * use ...
494352367a76SVipul Pandya 	 *
494452367a76SVipul Pandya 	 * XXX Note that we should really read through the Host Buffer Size
494552367a76SVipul Pandya 	 * XXX register array and find the indices of the Buffer Sizes which
494652367a76SVipul Pandya 	 * XXX meet our needs!
494752367a76SVipul Pandya 	 */
494852367a76SVipul Pandya 	#define READ_FL_BUF(x) \
4949f612b815SHariprasad Shenai 		t4_read_reg(adap, SGE_FL_BUFFER_SIZE0_A+(x)*sizeof(u32))
495052367a76SVipul Pandya 
495152367a76SVipul Pandya 	fl_small_pg = READ_FL_BUF(RX_SMALL_PG_BUF);
495252367a76SVipul Pandya 	fl_large_pg = READ_FL_BUF(RX_LARGE_PG_BUF);
495352367a76SVipul Pandya 	fl_small_mtu = READ_FL_BUF(RX_SMALL_MTU_BUF);
495452367a76SVipul Pandya 	fl_large_mtu = READ_FL_BUF(RX_LARGE_MTU_BUF);
495552367a76SVipul Pandya 
495692ddcc7bSKumar Sanghvi 	/* We only bother using the Large Page logic if the Large Page Buffer
495792ddcc7bSKumar Sanghvi 	 * is larger than our Page Size Buffer.
495892ddcc7bSKumar Sanghvi 	 */
495992ddcc7bSKumar Sanghvi 	if (fl_large_pg <= fl_small_pg)
496092ddcc7bSKumar Sanghvi 		fl_large_pg = 0;
496192ddcc7bSKumar Sanghvi 
496252367a76SVipul Pandya 	#undef READ_FL_BUF
496352367a76SVipul Pandya 
496492ddcc7bSKumar Sanghvi 	/* The Page Size Buffer must be exactly equal to our Page Size and the
496592ddcc7bSKumar Sanghvi 	 * Large Page Size Buffer should be 0 (per above) or a power of 2.
496692ddcc7bSKumar Sanghvi 	 */
496752367a76SVipul Pandya 	if (fl_small_pg != PAGE_SIZE ||
496892ddcc7bSKumar Sanghvi 	    (fl_large_pg & (fl_large_pg-1)) != 0) {
496952367a76SVipul Pandya 		dev_err(adap->pdev_dev, "bad SGE FL page buffer sizes [%d, %d]\n",
497052367a76SVipul Pandya 			fl_small_pg, fl_large_pg);
497152367a76SVipul Pandya 		return -EINVAL;
497252367a76SVipul Pandya 	}
497352367a76SVipul Pandya 	if (fl_large_pg)
497452367a76SVipul Pandya 		s->fl_pg_order = ilog2(fl_large_pg) - PAGE_SHIFT;
497552367a76SVipul Pandya 
497652367a76SVipul Pandya 	if (fl_small_mtu < FL_MTU_SMALL_BUFSIZE(adap) ||
497752367a76SVipul Pandya 	    fl_large_mtu < FL_MTU_LARGE_BUFSIZE(adap)) {
497852367a76SVipul Pandya 		dev_err(adap->pdev_dev, "bad SGE FL MTU sizes [%d, %d]\n",
497952367a76SVipul Pandya 			fl_small_mtu, fl_large_mtu);
498052367a76SVipul Pandya 		return -EINVAL;
498152367a76SVipul Pandya 	}
498252367a76SVipul Pandya 
498352367a76SVipul Pandya 	/*
498452367a76SVipul Pandya 	 * Retrieve our RX interrupt holdoff timer values and counter
498552367a76SVipul Pandya 	 * threshold values from the SGE parameters.
498652367a76SVipul Pandya 	 */
4987f061de42SHariprasad Shenai 	timer_value_0_and_1 = t4_read_reg(adap, SGE_TIMER_VALUE_0_AND_1_A);
4988f061de42SHariprasad Shenai 	timer_value_2_and_3 = t4_read_reg(adap, SGE_TIMER_VALUE_2_AND_3_A);
4989f061de42SHariprasad Shenai 	timer_value_4_and_5 = t4_read_reg(adap, SGE_TIMER_VALUE_4_AND_5_A);
499052367a76SVipul Pandya 	s->timer_val[0] = core_ticks_to_us(adap,
4991f061de42SHariprasad Shenai 		TIMERVALUE0_G(timer_value_0_and_1));
499252367a76SVipul Pandya 	s->timer_val[1] = core_ticks_to_us(adap,
4993f061de42SHariprasad Shenai 		TIMERVALUE1_G(timer_value_0_and_1));
499452367a76SVipul Pandya 	s->timer_val[2] = core_ticks_to_us(adap,
4995f061de42SHariprasad Shenai 		TIMERVALUE2_G(timer_value_2_and_3));
499652367a76SVipul Pandya 	s->timer_val[3] = core_ticks_to_us(adap,
4997f061de42SHariprasad Shenai 		TIMERVALUE3_G(timer_value_2_and_3));
499852367a76SVipul Pandya 	s->timer_val[4] = core_ticks_to_us(adap,
4999f061de42SHariprasad Shenai 		TIMERVALUE4_G(timer_value_4_and_5));
500052367a76SVipul Pandya 	s->timer_val[5] = core_ticks_to_us(adap,
5001f061de42SHariprasad Shenai 		TIMERVALUE5_G(timer_value_4_and_5));
500252367a76SVipul Pandya 
5003f612b815SHariprasad Shenai 	ingress_rx_threshold = t4_read_reg(adap, SGE_INGRESS_RX_THRESHOLD_A);
5004f612b815SHariprasad Shenai 	s->counter_val[0] = THRESHOLD_0_G(ingress_rx_threshold);
5005f612b815SHariprasad Shenai 	s->counter_val[1] = THRESHOLD_1_G(ingress_rx_threshold);
5006f612b815SHariprasad Shenai 	s->counter_val[2] = THRESHOLD_2_G(ingress_rx_threshold);
5007f612b815SHariprasad Shenai 	s->counter_val[3] = THRESHOLD_3_G(ingress_rx_threshold);
500852367a76SVipul Pandya 
500952367a76SVipul Pandya 	return 0;
501052367a76SVipul Pandya }
501152367a76SVipul Pandya 
501206640310SHariprasad Shenai /**
501306640310SHariprasad Shenai  *     t4_sge_init - initialize SGE
501406640310SHariprasad Shenai  *     @adap: the adapter
501506640310SHariprasad Shenai  *
501606640310SHariprasad Shenai  *     Perform low-level SGE code initialization needed every time after a
501706640310SHariprasad Shenai  *     chip reset.
501852367a76SVipul Pandya  */
501952367a76SVipul Pandya int t4_sge_init(struct adapter *adap)
502052367a76SVipul Pandya {
502152367a76SVipul Pandya 	struct sge *s = &adap->sge;
5022acac5962SHariprasad Shenai 	u32 sge_control, sge_conm_ctrl;
5023c2b955e0SKumar Sanghvi 	int ret, egress_threshold;
502452367a76SVipul Pandya 
502552367a76SVipul Pandya 	/*
502652367a76SVipul Pandya 	 * Ingress Padding Boundary and Egress Status Page Size are set up by
502752367a76SVipul Pandya 	 * t4_fixup_host_params().
502852367a76SVipul Pandya 	 */
5029f612b815SHariprasad Shenai 	sge_control = t4_read_reg(adap, SGE_CONTROL_A);
5030f612b815SHariprasad Shenai 	s->pktshift = PKTSHIFT_G(sge_control);
5031f612b815SHariprasad Shenai 	s->stat_len = (sge_control & EGRSTATUSPAGESIZE_F) ? 128 : 64;
5032ce8f407aSHariprasad Shenai 
5033acac5962SHariprasad Shenai 	s->fl_align = t4_fl_pkt_align(adap);
503452367a76SVipul Pandya 	ret = t4_sge_init_soft(adap);
503552367a76SVipul Pandya 	if (ret < 0)
503652367a76SVipul Pandya 		return ret;
503752367a76SVipul Pandya 
503852367a76SVipul Pandya 	/*
503952367a76SVipul Pandya 	 * A FL with <= fl_starve_thres buffers is starving and a periodic
504052367a76SVipul Pandya 	 * timer will attempt to refill it.  This needs to be larger than the
504152367a76SVipul Pandya 	 * SGE's Egress Congestion Threshold.  If it isn't, then we can get
504252367a76SVipul Pandya 	 * stuck waiting for new packets while the SGE is waiting for us to
504352367a76SVipul Pandya 	 * give it more Free List entries.  (Note that the SGE's Egress
5044c2b955e0SKumar Sanghvi 	 * Congestion Threshold is in units of 2 Free List pointers.) For T4,
5045c2b955e0SKumar Sanghvi 	 * there was only a single field to control this.  For T5 there's the
5046c2b955e0SKumar Sanghvi 	 * original field which now only applies to Unpacked Mode Free List
5047c2b955e0SKumar Sanghvi 	 * buffers and a new field which only applies to Packed Mode Free List
5048c2b955e0SKumar Sanghvi 	 * buffers.
504952367a76SVipul Pandya 	 */
5050f612b815SHariprasad Shenai 	sge_conm_ctrl = t4_read_reg(adap, SGE_CONM_CTRL_A);
5051676d6a75SHariprasad Shenai 	switch (CHELSIO_CHIP_VERSION(adap->params.chip)) {
5052676d6a75SHariprasad Shenai 	case CHELSIO_T4:
5053f612b815SHariprasad Shenai 		egress_threshold = EGRTHRESHOLD_G(sge_conm_ctrl);
5054676d6a75SHariprasad Shenai 		break;
5055676d6a75SHariprasad Shenai 	case CHELSIO_T5:
5056f612b815SHariprasad Shenai 		egress_threshold = EGRTHRESHOLDPACKING_G(sge_conm_ctrl);
5057676d6a75SHariprasad Shenai 		break;
5058676d6a75SHariprasad Shenai 	case CHELSIO_T6:
5059676d6a75SHariprasad Shenai 		egress_threshold = T6_EGRTHRESHOLDPACKING_G(sge_conm_ctrl);
5060676d6a75SHariprasad Shenai 		break;
5061676d6a75SHariprasad Shenai 	default:
5062676d6a75SHariprasad Shenai 		dev_err(adap->pdev_dev, "Unsupported Chip version %d\n",
5063676d6a75SHariprasad Shenai 			CHELSIO_CHIP_VERSION(adap->params.chip));
5064676d6a75SHariprasad Shenai 		return -EINVAL;
5065676d6a75SHariprasad Shenai 	}
5066c2b955e0SKumar Sanghvi 	s->fl_starve_thres = 2*egress_threshold + 1;
506752367a76SVipul Pandya 
5068a3bfb617SHariprasad Shenai 	t4_idma_monitor_init(adap, &s->idma_monitor);
5069a3bfb617SHariprasad Shenai 
50701ecc7b7aSHariprasad Shenai 	/* Set up timers used for recuring callbacks to process RX and TX
50711ecc7b7aSHariprasad Shenai 	 * administrative tasks.
50721ecc7b7aSHariprasad Shenai 	 */
50730e23daebSKees Cook 	timer_setup(&s->rx_timer, sge_rx_timer_cb, 0);
50740e23daebSKees Cook 	timer_setup(&s->tx_timer, sge_tx_timer_cb, 0);
5075a3bfb617SHariprasad Shenai 
5076f7917c00SJeff Kirsher 	spin_lock_init(&s->intrq_lock);
507752367a76SVipul Pandya 
507852367a76SVipul Pandya 	return 0;
5079f7917c00SJeff Kirsher }
5080