162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * Copyright (c) 2005-2008 Chelsio, Inc. All rights reserved.
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * This software is available to you under a choice of one of two
562306a36Sopenharmony_ci * licenses.  You may choose to be licensed under the terms of the GNU
662306a36Sopenharmony_ci * General Public License (GPL) Version 2, available from the file
762306a36Sopenharmony_ci * COPYING in the main directory of this source tree, or the
862306a36Sopenharmony_ci * OpenIB.org BSD license below:
962306a36Sopenharmony_ci *
1062306a36Sopenharmony_ci *     Redistribution and use in source and binary forms, with or
1162306a36Sopenharmony_ci *     without modification, are permitted provided that the following
1262306a36Sopenharmony_ci *     conditions are met:
1362306a36Sopenharmony_ci *
1462306a36Sopenharmony_ci *      - Redistributions of source code must retain the above
1562306a36Sopenharmony_ci *        copyright notice, this list of conditions and the following
1662306a36Sopenharmony_ci *        disclaimer.
1762306a36Sopenharmony_ci *
1862306a36Sopenharmony_ci *      - Redistributions in binary form must reproduce the above
1962306a36Sopenharmony_ci *        copyright notice, this list of conditions and the following
2062306a36Sopenharmony_ci *        disclaimer in the documentation and/or other materials
2162306a36Sopenharmony_ci *        provided with the distribution.
2262306a36Sopenharmony_ci *
2362306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
2462306a36Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2562306a36Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
2662306a36Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
2762306a36Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
2862306a36Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2962306a36Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
3062306a36Sopenharmony_ci * SOFTWARE.
3162306a36Sopenharmony_ci */
3262306a36Sopenharmony_ci#include <linux/skbuff.h>
3362306a36Sopenharmony_ci#include <linux/netdevice.h>
3462306a36Sopenharmony_ci#include <linux/etherdevice.h>
3562306a36Sopenharmony_ci#include <linux/if_vlan.h>
3662306a36Sopenharmony_ci#include <linux/ip.h>
3762306a36Sopenharmony_ci#include <linux/tcp.h>
3862306a36Sopenharmony_ci#include <linux/dma-mapping.h>
3962306a36Sopenharmony_ci#include <linux/slab.h>
4062306a36Sopenharmony_ci#include <linux/prefetch.h>
4162306a36Sopenharmony_ci#include <net/arp.h>
4262306a36Sopenharmony_ci#include "common.h"
4362306a36Sopenharmony_ci#include "regs.h"
4462306a36Sopenharmony_ci#include "sge_defs.h"
4562306a36Sopenharmony_ci#include "t3_cpl.h"
4662306a36Sopenharmony_ci#include "firmware_exports.h"
4762306a36Sopenharmony_ci#include "cxgb3_offload.h"
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci#define USE_GTS 0
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci#define SGE_RX_SM_BUF_SIZE 1536
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci#define SGE_RX_COPY_THRES  256
5462306a36Sopenharmony_ci#define SGE_RX_PULL_LEN    128
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci#define SGE_PG_RSVD SMP_CACHE_BYTES
5762306a36Sopenharmony_ci/*
5862306a36Sopenharmony_ci * Page chunk size for FL0 buffers if FL0 is to be populated with page chunks.
5962306a36Sopenharmony_ci * It must be a divisor of PAGE_SIZE.  If set to 0 FL0 will use sk_buffs
6062306a36Sopenharmony_ci * directly.
6162306a36Sopenharmony_ci */
6262306a36Sopenharmony_ci#define FL0_PG_CHUNK_SIZE  2048
6362306a36Sopenharmony_ci#define FL0_PG_ORDER 0
6462306a36Sopenharmony_ci#define FL0_PG_ALLOC_SIZE (PAGE_SIZE << FL0_PG_ORDER)
6562306a36Sopenharmony_ci#define FL1_PG_CHUNK_SIZE (PAGE_SIZE > 8192 ? 16384 : 8192)
6662306a36Sopenharmony_ci#define FL1_PG_ORDER (PAGE_SIZE > 8192 ? 0 : 1)
6762306a36Sopenharmony_ci#define FL1_PG_ALLOC_SIZE (PAGE_SIZE << FL1_PG_ORDER)
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci#define SGE_RX_DROP_THRES 16
7062306a36Sopenharmony_ci#define RX_RECLAIM_PERIOD (HZ/4)
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci/*
7362306a36Sopenharmony_ci * Max number of Rx buffers we replenish at a time.
7462306a36Sopenharmony_ci */
7562306a36Sopenharmony_ci#define MAX_RX_REFILL 16U
7662306a36Sopenharmony_ci/*
7762306a36Sopenharmony_ci * Period of the Tx buffer reclaim timer.  This timer does not need to run
7862306a36Sopenharmony_ci * frequently as Tx buffers are usually reclaimed by new Tx packets.
7962306a36Sopenharmony_ci */
8062306a36Sopenharmony_ci#define TX_RECLAIM_PERIOD (HZ / 4)
8162306a36Sopenharmony_ci#define TX_RECLAIM_TIMER_CHUNK 64U
8262306a36Sopenharmony_ci#define TX_RECLAIM_CHUNK 16U
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci/* WR size in bytes */
8562306a36Sopenharmony_ci#define WR_LEN (WR_FLITS * 8)
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci/*
8862306a36Sopenharmony_ci * Types of Tx queues in each queue set.  Order here matters, do not change.
8962306a36Sopenharmony_ci */
9062306a36Sopenharmony_cienum { TXQ_ETH, TXQ_OFLD, TXQ_CTRL };
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci/* Values for sge_txq.flags */
9362306a36Sopenharmony_cienum {
9462306a36Sopenharmony_ci	TXQ_RUNNING = 1 << 0,	/* fetch engine is running */
9562306a36Sopenharmony_ci	TXQ_LAST_PKT_DB = 1 << 1,	/* last packet rang the doorbell */
9662306a36Sopenharmony_ci};
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_cistruct tx_desc {
9962306a36Sopenharmony_ci	__be64 flit[TX_DESC_FLITS];
10062306a36Sopenharmony_ci};
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_cistruct rx_desc {
10362306a36Sopenharmony_ci	__be32 addr_lo;
10462306a36Sopenharmony_ci	__be32 len_gen;
10562306a36Sopenharmony_ci	__be32 gen2;
10662306a36Sopenharmony_ci	__be32 addr_hi;
10762306a36Sopenharmony_ci};
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_cistruct tx_sw_desc {		/* SW state per Tx descriptor */
11062306a36Sopenharmony_ci	struct sk_buff *skb;
11162306a36Sopenharmony_ci	u8 eop;       /* set if last descriptor for packet */
11262306a36Sopenharmony_ci	u8 addr_idx;  /* buffer index of first SGL entry in descriptor */
11362306a36Sopenharmony_ci	u8 fragidx;   /* first page fragment associated with descriptor */
11462306a36Sopenharmony_ci	s8 sflit;     /* start flit of first SGL entry in descriptor */
11562306a36Sopenharmony_ci};
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_cistruct rx_sw_desc {                /* SW state per Rx descriptor */
11862306a36Sopenharmony_ci	union {
11962306a36Sopenharmony_ci		struct sk_buff *skb;
12062306a36Sopenharmony_ci		struct fl_pg_chunk pg_chunk;
12162306a36Sopenharmony_ci	};
12262306a36Sopenharmony_ci	DEFINE_DMA_UNMAP_ADDR(dma_addr);
12362306a36Sopenharmony_ci};
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_cistruct rsp_desc {		/* response queue descriptor */
12662306a36Sopenharmony_ci	struct rss_header rss_hdr;
12762306a36Sopenharmony_ci	__be32 flags;
12862306a36Sopenharmony_ci	__be32 len_cq;
12962306a36Sopenharmony_ci	struct_group(immediate,
13062306a36Sopenharmony_ci		u8 imm_data[47];
13162306a36Sopenharmony_ci		u8 intr_gen;
13262306a36Sopenharmony_ci	);
13362306a36Sopenharmony_ci};
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci/*
13662306a36Sopenharmony_ci * Holds unmapping information for Tx packets that need deferred unmapping.
13762306a36Sopenharmony_ci * This structure lives at skb->head and must be allocated by callers.
13862306a36Sopenharmony_ci */
13962306a36Sopenharmony_cistruct deferred_unmap_info {
14062306a36Sopenharmony_ci	struct pci_dev *pdev;
14162306a36Sopenharmony_ci	dma_addr_t addr[MAX_SKB_FRAGS + 1];
14262306a36Sopenharmony_ci};
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci/*
14562306a36Sopenharmony_ci * Maps a number of flits to the number of Tx descriptors that can hold them.
14662306a36Sopenharmony_ci * The formula is
14762306a36Sopenharmony_ci *
14862306a36Sopenharmony_ci * desc = 1 + (flits - 2) / (WR_FLITS - 1).
14962306a36Sopenharmony_ci *
15062306a36Sopenharmony_ci * HW allows up to 4 descriptors to be combined into a WR.
15162306a36Sopenharmony_ci */
15262306a36Sopenharmony_cistatic u8 flit_desc_map[] = {
15362306a36Sopenharmony_ci	0,
15462306a36Sopenharmony_ci#if SGE_NUM_GENBITS == 1
15562306a36Sopenharmony_ci	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
15662306a36Sopenharmony_ci	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
15762306a36Sopenharmony_ci	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
15862306a36Sopenharmony_ci	4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
15962306a36Sopenharmony_ci#elif SGE_NUM_GENBITS == 2
16062306a36Sopenharmony_ci	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
16162306a36Sopenharmony_ci	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
16262306a36Sopenharmony_ci	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
16362306a36Sopenharmony_ci	4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
16462306a36Sopenharmony_ci#else
16562306a36Sopenharmony_ci# error "SGE_NUM_GENBITS must be 1 or 2"
16662306a36Sopenharmony_ci#endif
16762306a36Sopenharmony_ci};
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_cistatic inline struct sge_qset *rspq_to_qset(const struct sge_rspq *q)
17062306a36Sopenharmony_ci{
17162306a36Sopenharmony_ci	return container_of(q, struct sge_qset, rspq);
17262306a36Sopenharmony_ci}
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_cistatic inline struct sge_qset *txq_to_qset(const struct sge_txq *q, int qidx)
17562306a36Sopenharmony_ci{
17662306a36Sopenharmony_ci	return container_of(q, struct sge_qset, txq[qidx]);
17762306a36Sopenharmony_ci}
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci/**
18062306a36Sopenharmony_ci *	refill_rspq - replenish an SGE response queue
18162306a36Sopenharmony_ci *	@adapter: the adapter
18262306a36Sopenharmony_ci *	@q: the response queue to replenish
18362306a36Sopenharmony_ci *	@credits: how many new responses to make available
18462306a36Sopenharmony_ci *
18562306a36Sopenharmony_ci *	Replenishes a response queue by making the supplied number of responses
18662306a36Sopenharmony_ci *	available to HW.
18762306a36Sopenharmony_ci */
18862306a36Sopenharmony_cistatic inline void refill_rspq(struct adapter *adapter,
18962306a36Sopenharmony_ci			       const struct sge_rspq *q, unsigned int credits)
19062306a36Sopenharmony_ci{
19162306a36Sopenharmony_ci	rmb();
19262306a36Sopenharmony_ci	t3_write_reg(adapter, A_SG_RSPQ_CREDIT_RETURN,
19362306a36Sopenharmony_ci		     V_RSPQ(q->cntxt_id) | V_CREDITS(credits));
19462306a36Sopenharmony_ci}
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci/**
19762306a36Sopenharmony_ci *	need_skb_unmap - does the platform need unmapping of sk_buffs?
19862306a36Sopenharmony_ci *
19962306a36Sopenharmony_ci *	Returns true if the platform needs sk_buff unmapping.  The compiler
20062306a36Sopenharmony_ci *	optimizes away unnecessary code if this returns true.
20162306a36Sopenharmony_ci */
20262306a36Sopenharmony_cistatic inline int need_skb_unmap(void)
20362306a36Sopenharmony_ci{
20462306a36Sopenharmony_ci#ifdef CONFIG_NEED_DMA_MAP_STATE
20562306a36Sopenharmony_ci	return 1;
20662306a36Sopenharmony_ci#else
20762306a36Sopenharmony_ci	return 0;
20862306a36Sopenharmony_ci#endif
20962306a36Sopenharmony_ci}
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci/**
21262306a36Sopenharmony_ci *	unmap_skb - unmap a packet main body and its page fragments
21362306a36Sopenharmony_ci *	@skb: the packet
21462306a36Sopenharmony_ci *	@q: the Tx queue containing Tx descriptors for the packet
21562306a36Sopenharmony_ci *	@cidx: index of Tx descriptor
21662306a36Sopenharmony_ci *	@pdev: the PCI device
21762306a36Sopenharmony_ci *
21862306a36Sopenharmony_ci *	Unmap the main body of an sk_buff and its page fragments, if any.
21962306a36Sopenharmony_ci *	Because of the fairly complicated structure of our SGLs and the desire
22062306a36Sopenharmony_ci *	to conserve space for metadata, the information necessary to unmap an
22162306a36Sopenharmony_ci *	sk_buff is spread across the sk_buff itself (buffer lengths), the HW Tx
22262306a36Sopenharmony_ci *	descriptors (the physical addresses of the various data buffers), and
22362306a36Sopenharmony_ci *	the SW descriptor state (assorted indices).  The send functions
22462306a36Sopenharmony_ci *	initialize the indices for the first packet descriptor so we can unmap
22562306a36Sopenharmony_ci *	the buffers held in the first Tx descriptor here, and we have enough
22662306a36Sopenharmony_ci *	information at this point to set the state for the next Tx descriptor.
22762306a36Sopenharmony_ci *
22862306a36Sopenharmony_ci *	Note that it is possible to clean up the first descriptor of a packet
22962306a36Sopenharmony_ci *	before the send routines have written the next descriptors, but this
23062306a36Sopenharmony_ci *	race does not cause any problem.  We just end up writing the unmapping
23162306a36Sopenharmony_ci *	info for the descriptor first.
23262306a36Sopenharmony_ci */
23362306a36Sopenharmony_cistatic inline void unmap_skb(struct sk_buff *skb, struct sge_txq *q,
23462306a36Sopenharmony_ci			     unsigned int cidx, struct pci_dev *pdev)
23562306a36Sopenharmony_ci{
23662306a36Sopenharmony_ci	const struct sg_ent *sgp;
23762306a36Sopenharmony_ci	struct tx_sw_desc *d = &q->sdesc[cidx];
23862306a36Sopenharmony_ci	int nfrags, frag_idx, curflit, j = d->addr_idx;
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci	sgp = (struct sg_ent *)&q->desc[cidx].flit[d->sflit];
24162306a36Sopenharmony_ci	frag_idx = d->fragidx;
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	if (frag_idx == 0 && skb_headlen(skb)) {
24462306a36Sopenharmony_ci		dma_unmap_single(&pdev->dev, be64_to_cpu(sgp->addr[0]),
24562306a36Sopenharmony_ci				 skb_headlen(skb), DMA_TO_DEVICE);
24662306a36Sopenharmony_ci		j = 1;
24762306a36Sopenharmony_ci	}
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci	curflit = d->sflit + 1 + j;
25062306a36Sopenharmony_ci	nfrags = skb_shinfo(skb)->nr_frags;
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci	while (frag_idx < nfrags && curflit < WR_FLITS) {
25362306a36Sopenharmony_ci		dma_unmap_page(&pdev->dev, be64_to_cpu(sgp->addr[j]),
25462306a36Sopenharmony_ci			       skb_frag_size(&skb_shinfo(skb)->frags[frag_idx]),
25562306a36Sopenharmony_ci			       DMA_TO_DEVICE);
25662306a36Sopenharmony_ci		j ^= 1;
25762306a36Sopenharmony_ci		if (j == 0) {
25862306a36Sopenharmony_ci			sgp++;
25962306a36Sopenharmony_ci			curflit++;
26062306a36Sopenharmony_ci		}
26162306a36Sopenharmony_ci		curflit++;
26262306a36Sopenharmony_ci		frag_idx++;
26362306a36Sopenharmony_ci	}
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci	if (frag_idx < nfrags) {   /* SGL continues into next Tx descriptor */
26662306a36Sopenharmony_ci		d = cidx + 1 == q->size ? q->sdesc : d + 1;
26762306a36Sopenharmony_ci		d->fragidx = frag_idx;
26862306a36Sopenharmony_ci		d->addr_idx = j;
26962306a36Sopenharmony_ci		d->sflit = curflit - WR_FLITS - j; /* sflit can be -1 */
27062306a36Sopenharmony_ci	}
27162306a36Sopenharmony_ci}
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci/**
27462306a36Sopenharmony_ci *	free_tx_desc - reclaims Tx descriptors and their buffers
27562306a36Sopenharmony_ci *	@adapter: the adapter
27662306a36Sopenharmony_ci *	@q: the Tx queue to reclaim descriptors from
27762306a36Sopenharmony_ci *	@n: the number of descriptors to reclaim
27862306a36Sopenharmony_ci *
27962306a36Sopenharmony_ci *	Reclaims Tx descriptors from an SGE Tx queue and frees the associated
28062306a36Sopenharmony_ci *	Tx buffers.  Called with the Tx queue lock held.
28162306a36Sopenharmony_ci */
28262306a36Sopenharmony_cistatic void free_tx_desc(struct adapter *adapter, struct sge_txq *q,
28362306a36Sopenharmony_ci			 unsigned int n)
28462306a36Sopenharmony_ci{
28562306a36Sopenharmony_ci	struct tx_sw_desc *d;
28662306a36Sopenharmony_ci	struct pci_dev *pdev = adapter->pdev;
28762306a36Sopenharmony_ci	unsigned int cidx = q->cidx;
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ci	const int need_unmap = need_skb_unmap() &&
29062306a36Sopenharmony_ci			       q->cntxt_id >= FW_TUNNEL_SGEEC_START;
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci	d = &q->sdesc[cidx];
29362306a36Sopenharmony_ci	while (n--) {
29462306a36Sopenharmony_ci		if (d->skb) {	/* an SGL is present */
29562306a36Sopenharmony_ci			if (need_unmap)
29662306a36Sopenharmony_ci				unmap_skb(d->skb, q, cidx, pdev);
29762306a36Sopenharmony_ci			if (d->eop) {
29862306a36Sopenharmony_ci				dev_consume_skb_any(d->skb);
29962306a36Sopenharmony_ci				d->skb = NULL;
30062306a36Sopenharmony_ci			}
30162306a36Sopenharmony_ci		}
30262306a36Sopenharmony_ci		++d;
30362306a36Sopenharmony_ci		if (++cidx == q->size) {
30462306a36Sopenharmony_ci			cidx = 0;
30562306a36Sopenharmony_ci			d = q->sdesc;
30662306a36Sopenharmony_ci		}
30762306a36Sopenharmony_ci	}
30862306a36Sopenharmony_ci	q->cidx = cidx;
30962306a36Sopenharmony_ci}
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci/**
31262306a36Sopenharmony_ci *	reclaim_completed_tx - reclaims completed Tx descriptors
31362306a36Sopenharmony_ci *	@adapter: the adapter
31462306a36Sopenharmony_ci *	@q: the Tx queue to reclaim completed descriptors from
31562306a36Sopenharmony_ci *	@chunk: maximum number of descriptors to reclaim
31662306a36Sopenharmony_ci *
31762306a36Sopenharmony_ci *	Reclaims Tx descriptors that the SGE has indicated it has processed,
31862306a36Sopenharmony_ci *	and frees the associated buffers if possible.  Called with the Tx
31962306a36Sopenharmony_ci *	queue's lock held.
32062306a36Sopenharmony_ci */
32162306a36Sopenharmony_cistatic inline unsigned int reclaim_completed_tx(struct adapter *adapter,
32262306a36Sopenharmony_ci						struct sge_txq *q,
32362306a36Sopenharmony_ci						unsigned int chunk)
32462306a36Sopenharmony_ci{
32562306a36Sopenharmony_ci	unsigned int reclaim = q->processed - q->cleaned;
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	reclaim = min(chunk, reclaim);
32862306a36Sopenharmony_ci	if (reclaim) {
32962306a36Sopenharmony_ci		free_tx_desc(adapter, q, reclaim);
33062306a36Sopenharmony_ci		q->cleaned += reclaim;
33162306a36Sopenharmony_ci		q->in_use -= reclaim;
33262306a36Sopenharmony_ci	}
33362306a36Sopenharmony_ci	return q->processed - q->cleaned;
33462306a36Sopenharmony_ci}
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci/**
33762306a36Sopenharmony_ci *	should_restart_tx - are there enough resources to restart a Tx queue?
33862306a36Sopenharmony_ci *	@q: the Tx queue
33962306a36Sopenharmony_ci *
34062306a36Sopenharmony_ci *	Checks if there are enough descriptors to restart a suspended Tx queue.
34162306a36Sopenharmony_ci */
34262306a36Sopenharmony_cistatic inline int should_restart_tx(const struct sge_txq *q)
34362306a36Sopenharmony_ci{
34462306a36Sopenharmony_ci	unsigned int r = q->processed - q->cleaned;
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ci	return q->in_use - r < (q->size >> 1);
34762306a36Sopenharmony_ci}
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_cistatic void clear_rx_desc(struct pci_dev *pdev, const struct sge_fl *q,
35062306a36Sopenharmony_ci			  struct rx_sw_desc *d)
35162306a36Sopenharmony_ci{
35262306a36Sopenharmony_ci	if (q->use_pages && d->pg_chunk.page) {
35362306a36Sopenharmony_ci		(*d->pg_chunk.p_cnt)--;
35462306a36Sopenharmony_ci		if (!*d->pg_chunk.p_cnt)
35562306a36Sopenharmony_ci			dma_unmap_page(&pdev->dev, d->pg_chunk.mapping,
35662306a36Sopenharmony_ci				       q->alloc_size, DMA_FROM_DEVICE);
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci		put_page(d->pg_chunk.page);
35962306a36Sopenharmony_ci		d->pg_chunk.page = NULL;
36062306a36Sopenharmony_ci	} else {
36162306a36Sopenharmony_ci		dma_unmap_single(&pdev->dev, dma_unmap_addr(d, dma_addr),
36262306a36Sopenharmony_ci				 q->buf_size, DMA_FROM_DEVICE);
36362306a36Sopenharmony_ci		kfree_skb(d->skb);
36462306a36Sopenharmony_ci		d->skb = NULL;
36562306a36Sopenharmony_ci	}
36662306a36Sopenharmony_ci}
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ci/**
36962306a36Sopenharmony_ci *	free_rx_bufs - free the Rx buffers on an SGE free list
37062306a36Sopenharmony_ci *	@pdev: the PCI device associated with the adapter
37162306a36Sopenharmony_ci *	@q: the SGE free list to clean up
37262306a36Sopenharmony_ci *
37362306a36Sopenharmony_ci *	Release the buffers on an SGE free-buffer Rx queue.  HW fetching from
37462306a36Sopenharmony_ci *	this queue should be stopped before calling this function.
37562306a36Sopenharmony_ci */
37662306a36Sopenharmony_cistatic void free_rx_bufs(struct pci_dev *pdev, struct sge_fl *q)
37762306a36Sopenharmony_ci{
37862306a36Sopenharmony_ci	unsigned int cidx = q->cidx;
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci	while (q->credits--) {
38162306a36Sopenharmony_ci		struct rx_sw_desc *d = &q->sdesc[cidx];
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci
38462306a36Sopenharmony_ci		clear_rx_desc(pdev, q, d);
38562306a36Sopenharmony_ci		if (++cidx == q->size)
38662306a36Sopenharmony_ci			cidx = 0;
38762306a36Sopenharmony_ci	}
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_ci	if (q->pg_chunk.page) {
39062306a36Sopenharmony_ci		__free_pages(q->pg_chunk.page, q->order);
39162306a36Sopenharmony_ci		q->pg_chunk.page = NULL;
39262306a36Sopenharmony_ci	}
39362306a36Sopenharmony_ci}
39462306a36Sopenharmony_ci
39562306a36Sopenharmony_ci/**
39662306a36Sopenharmony_ci *	add_one_rx_buf - add a packet buffer to a free-buffer list
39762306a36Sopenharmony_ci *	@va:  buffer start VA
39862306a36Sopenharmony_ci *	@len: the buffer length
39962306a36Sopenharmony_ci *	@d: the HW Rx descriptor to write
40062306a36Sopenharmony_ci *	@sd: the SW Rx descriptor to write
40162306a36Sopenharmony_ci *	@gen: the generation bit value
40262306a36Sopenharmony_ci *	@pdev: the PCI device associated with the adapter
40362306a36Sopenharmony_ci *
40462306a36Sopenharmony_ci *	Add a buffer of the given length to the supplied HW and SW Rx
40562306a36Sopenharmony_ci *	descriptors.
40662306a36Sopenharmony_ci */
40762306a36Sopenharmony_cistatic inline int add_one_rx_buf(void *va, unsigned int len,
40862306a36Sopenharmony_ci				 struct rx_desc *d, struct rx_sw_desc *sd,
40962306a36Sopenharmony_ci				 unsigned int gen, struct pci_dev *pdev)
41062306a36Sopenharmony_ci{
41162306a36Sopenharmony_ci	dma_addr_t mapping;
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ci	mapping = dma_map_single(&pdev->dev, va, len, DMA_FROM_DEVICE);
41462306a36Sopenharmony_ci	if (unlikely(dma_mapping_error(&pdev->dev, mapping)))
41562306a36Sopenharmony_ci		return -ENOMEM;
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ci	dma_unmap_addr_set(sd, dma_addr, mapping);
41862306a36Sopenharmony_ci
41962306a36Sopenharmony_ci	d->addr_lo = cpu_to_be32(mapping);
42062306a36Sopenharmony_ci	d->addr_hi = cpu_to_be32((u64) mapping >> 32);
42162306a36Sopenharmony_ci	dma_wmb();
42262306a36Sopenharmony_ci	d->len_gen = cpu_to_be32(V_FLD_GEN1(gen));
42362306a36Sopenharmony_ci	d->gen2 = cpu_to_be32(V_FLD_GEN2(gen));
42462306a36Sopenharmony_ci	return 0;
42562306a36Sopenharmony_ci}
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_cistatic inline int add_one_rx_chunk(dma_addr_t mapping, struct rx_desc *d,
42862306a36Sopenharmony_ci				   unsigned int gen)
42962306a36Sopenharmony_ci{
43062306a36Sopenharmony_ci	d->addr_lo = cpu_to_be32(mapping);
43162306a36Sopenharmony_ci	d->addr_hi = cpu_to_be32((u64) mapping >> 32);
43262306a36Sopenharmony_ci	dma_wmb();
43362306a36Sopenharmony_ci	d->len_gen = cpu_to_be32(V_FLD_GEN1(gen));
43462306a36Sopenharmony_ci	d->gen2 = cpu_to_be32(V_FLD_GEN2(gen));
43562306a36Sopenharmony_ci	return 0;
43662306a36Sopenharmony_ci}
43762306a36Sopenharmony_ci
43862306a36Sopenharmony_cistatic int alloc_pg_chunk(struct adapter *adapter, struct sge_fl *q,
43962306a36Sopenharmony_ci			  struct rx_sw_desc *sd, gfp_t gfp,
44062306a36Sopenharmony_ci			  unsigned int order)
44162306a36Sopenharmony_ci{
44262306a36Sopenharmony_ci	if (!q->pg_chunk.page) {
44362306a36Sopenharmony_ci		dma_addr_t mapping;
44462306a36Sopenharmony_ci
44562306a36Sopenharmony_ci		q->pg_chunk.page = alloc_pages(gfp, order);
44662306a36Sopenharmony_ci		if (unlikely(!q->pg_chunk.page))
44762306a36Sopenharmony_ci			return -ENOMEM;
44862306a36Sopenharmony_ci		q->pg_chunk.va = page_address(q->pg_chunk.page);
44962306a36Sopenharmony_ci		q->pg_chunk.p_cnt = q->pg_chunk.va + (PAGE_SIZE << order) -
45062306a36Sopenharmony_ci				    SGE_PG_RSVD;
45162306a36Sopenharmony_ci		q->pg_chunk.offset = 0;
45262306a36Sopenharmony_ci		mapping = dma_map_page(&adapter->pdev->dev, q->pg_chunk.page,
45362306a36Sopenharmony_ci				       0, q->alloc_size, DMA_FROM_DEVICE);
45462306a36Sopenharmony_ci		if (unlikely(dma_mapping_error(&adapter->pdev->dev, mapping))) {
45562306a36Sopenharmony_ci			__free_pages(q->pg_chunk.page, order);
45662306a36Sopenharmony_ci			q->pg_chunk.page = NULL;
45762306a36Sopenharmony_ci			return -EIO;
45862306a36Sopenharmony_ci		}
45962306a36Sopenharmony_ci		q->pg_chunk.mapping = mapping;
46062306a36Sopenharmony_ci	}
46162306a36Sopenharmony_ci	sd->pg_chunk = q->pg_chunk;
46262306a36Sopenharmony_ci
46362306a36Sopenharmony_ci	prefetch(sd->pg_chunk.p_cnt);
46462306a36Sopenharmony_ci
46562306a36Sopenharmony_ci	q->pg_chunk.offset += q->buf_size;
46662306a36Sopenharmony_ci	if (q->pg_chunk.offset == (PAGE_SIZE << order))
46762306a36Sopenharmony_ci		q->pg_chunk.page = NULL;
46862306a36Sopenharmony_ci	else {
46962306a36Sopenharmony_ci		q->pg_chunk.va += q->buf_size;
47062306a36Sopenharmony_ci		get_page(q->pg_chunk.page);
47162306a36Sopenharmony_ci	}
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_ci	if (sd->pg_chunk.offset == 0)
47462306a36Sopenharmony_ci		*sd->pg_chunk.p_cnt = 1;
47562306a36Sopenharmony_ci	else
47662306a36Sopenharmony_ci		*sd->pg_chunk.p_cnt += 1;
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_ci	return 0;
47962306a36Sopenharmony_ci}
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_cistatic inline void ring_fl_db(struct adapter *adap, struct sge_fl *q)
48262306a36Sopenharmony_ci{
48362306a36Sopenharmony_ci	if (q->pend_cred >= q->credits / 4) {
48462306a36Sopenharmony_ci		q->pend_cred = 0;
48562306a36Sopenharmony_ci		wmb();
48662306a36Sopenharmony_ci		t3_write_reg(adap, A_SG_KDOORBELL, V_EGRCNTX(q->cntxt_id));
48762306a36Sopenharmony_ci	}
48862306a36Sopenharmony_ci}
48962306a36Sopenharmony_ci
49062306a36Sopenharmony_ci/**
49162306a36Sopenharmony_ci *	refill_fl - refill an SGE free-buffer list
49262306a36Sopenharmony_ci *	@adap: the adapter
49362306a36Sopenharmony_ci *	@q: the free-list to refill
49462306a36Sopenharmony_ci *	@n: the number of new buffers to allocate
49562306a36Sopenharmony_ci *	@gfp: the gfp flags for allocating new buffers
49662306a36Sopenharmony_ci *
49762306a36Sopenharmony_ci *	(Re)populate an SGE free-buffer list with up to @n new packet buffers,
49862306a36Sopenharmony_ci *	allocated with the supplied gfp flags.  The caller must assure that
49962306a36Sopenharmony_ci *	@n does not exceed the queue's capacity.
50062306a36Sopenharmony_ci */
50162306a36Sopenharmony_cistatic int refill_fl(struct adapter *adap, struct sge_fl *q, int n, gfp_t gfp)
50262306a36Sopenharmony_ci{
50362306a36Sopenharmony_ci	struct rx_sw_desc *sd = &q->sdesc[q->pidx];
50462306a36Sopenharmony_ci	struct rx_desc *d = &q->desc[q->pidx];
50562306a36Sopenharmony_ci	unsigned int count = 0;
50662306a36Sopenharmony_ci
50762306a36Sopenharmony_ci	while (n--) {
50862306a36Sopenharmony_ci		dma_addr_t mapping;
50962306a36Sopenharmony_ci		int err;
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_ci		if (q->use_pages) {
51262306a36Sopenharmony_ci			if (unlikely(alloc_pg_chunk(adap, q, sd, gfp,
51362306a36Sopenharmony_ci						    q->order))) {
51462306a36Sopenharmony_cinomem:				q->alloc_failed++;
51562306a36Sopenharmony_ci				break;
51662306a36Sopenharmony_ci			}
51762306a36Sopenharmony_ci			mapping = sd->pg_chunk.mapping + sd->pg_chunk.offset;
51862306a36Sopenharmony_ci			dma_unmap_addr_set(sd, dma_addr, mapping);
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_ci			add_one_rx_chunk(mapping, d, q->gen);
52162306a36Sopenharmony_ci			dma_sync_single_for_device(&adap->pdev->dev, mapping,
52262306a36Sopenharmony_ci						   q->buf_size - SGE_PG_RSVD,
52362306a36Sopenharmony_ci						   DMA_FROM_DEVICE);
52462306a36Sopenharmony_ci		} else {
52562306a36Sopenharmony_ci			void *buf_start;
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_ci			struct sk_buff *skb = alloc_skb(q->buf_size, gfp);
52862306a36Sopenharmony_ci			if (!skb)
52962306a36Sopenharmony_ci				goto nomem;
53062306a36Sopenharmony_ci
53162306a36Sopenharmony_ci			sd->skb = skb;
53262306a36Sopenharmony_ci			buf_start = skb->data;
53362306a36Sopenharmony_ci			err = add_one_rx_buf(buf_start, q->buf_size, d, sd,
53462306a36Sopenharmony_ci					     q->gen, adap->pdev);
53562306a36Sopenharmony_ci			if (unlikely(err)) {
53662306a36Sopenharmony_ci				clear_rx_desc(adap->pdev, q, sd);
53762306a36Sopenharmony_ci				break;
53862306a36Sopenharmony_ci			}
53962306a36Sopenharmony_ci		}
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_ci		d++;
54262306a36Sopenharmony_ci		sd++;
54362306a36Sopenharmony_ci		if (++q->pidx == q->size) {
54462306a36Sopenharmony_ci			q->pidx = 0;
54562306a36Sopenharmony_ci			q->gen ^= 1;
54662306a36Sopenharmony_ci			sd = q->sdesc;
54762306a36Sopenharmony_ci			d = q->desc;
54862306a36Sopenharmony_ci		}
54962306a36Sopenharmony_ci		count++;
55062306a36Sopenharmony_ci	}
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_ci	q->credits += count;
55362306a36Sopenharmony_ci	q->pend_cred += count;
55462306a36Sopenharmony_ci	ring_fl_db(adap, q);
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_ci	return count;
55762306a36Sopenharmony_ci}
55862306a36Sopenharmony_ci
55962306a36Sopenharmony_cistatic inline void __refill_fl(struct adapter *adap, struct sge_fl *fl)
56062306a36Sopenharmony_ci{
56162306a36Sopenharmony_ci	refill_fl(adap, fl, min(MAX_RX_REFILL, fl->size - fl->credits),
56262306a36Sopenharmony_ci		  GFP_ATOMIC | __GFP_COMP);
56362306a36Sopenharmony_ci}
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_ci/**
56662306a36Sopenharmony_ci *	recycle_rx_buf - recycle a receive buffer
56762306a36Sopenharmony_ci *	@adap: the adapter
56862306a36Sopenharmony_ci *	@q: the SGE free list
56962306a36Sopenharmony_ci *	@idx: index of buffer to recycle
57062306a36Sopenharmony_ci *
57162306a36Sopenharmony_ci *	Recycles the specified buffer on the given free list by adding it at
57262306a36Sopenharmony_ci *	the next available slot on the list.
57362306a36Sopenharmony_ci */
57462306a36Sopenharmony_cistatic void recycle_rx_buf(struct adapter *adap, struct sge_fl *q,
57562306a36Sopenharmony_ci			   unsigned int idx)
57662306a36Sopenharmony_ci{
57762306a36Sopenharmony_ci	struct rx_desc *from = &q->desc[idx];
57862306a36Sopenharmony_ci	struct rx_desc *to = &q->desc[q->pidx];
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_ci	q->sdesc[q->pidx] = q->sdesc[idx];
58162306a36Sopenharmony_ci	to->addr_lo = from->addr_lo;	/* already big endian */
58262306a36Sopenharmony_ci	to->addr_hi = from->addr_hi;	/* likewise */
58362306a36Sopenharmony_ci	dma_wmb();
58462306a36Sopenharmony_ci	to->len_gen = cpu_to_be32(V_FLD_GEN1(q->gen));
58562306a36Sopenharmony_ci	to->gen2 = cpu_to_be32(V_FLD_GEN2(q->gen));
58662306a36Sopenharmony_ci
58762306a36Sopenharmony_ci	if (++q->pidx == q->size) {
58862306a36Sopenharmony_ci		q->pidx = 0;
58962306a36Sopenharmony_ci		q->gen ^= 1;
59062306a36Sopenharmony_ci	}
59162306a36Sopenharmony_ci
59262306a36Sopenharmony_ci	q->credits++;
59362306a36Sopenharmony_ci	q->pend_cred++;
59462306a36Sopenharmony_ci	ring_fl_db(adap, q);
59562306a36Sopenharmony_ci}
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_ci/**
59862306a36Sopenharmony_ci *	alloc_ring - allocate resources for an SGE descriptor ring
59962306a36Sopenharmony_ci *	@pdev: the PCI device
60062306a36Sopenharmony_ci *	@nelem: the number of descriptors
60162306a36Sopenharmony_ci *	@elem_size: the size of each descriptor
60262306a36Sopenharmony_ci *	@sw_size: the size of the SW state associated with each ring element
60362306a36Sopenharmony_ci *	@phys: the physical address of the allocated ring
60462306a36Sopenharmony_ci *	@metadata: address of the array holding the SW state for the ring
60562306a36Sopenharmony_ci *
60662306a36Sopenharmony_ci *	Allocates resources for an SGE descriptor ring, such as Tx queues,
60762306a36Sopenharmony_ci *	free buffer lists, or response queues.  Each SGE ring requires
60862306a36Sopenharmony_ci *	space for its HW descriptors plus, optionally, space for the SW state
60962306a36Sopenharmony_ci *	associated with each HW entry (the metadata).  The function returns
61062306a36Sopenharmony_ci *	three values: the virtual address for the HW ring (the return value
61162306a36Sopenharmony_ci *	of the function), the physical address of the HW ring, and the address
61262306a36Sopenharmony_ci *	of the SW ring.
61362306a36Sopenharmony_ci */
61462306a36Sopenharmony_cistatic void *alloc_ring(struct pci_dev *pdev, size_t nelem, size_t elem_size,
61562306a36Sopenharmony_ci			size_t sw_size, dma_addr_t * phys, void *metadata)
61662306a36Sopenharmony_ci{
61762306a36Sopenharmony_ci	size_t len = nelem * elem_size;
61862306a36Sopenharmony_ci	void *s = NULL;
61962306a36Sopenharmony_ci	void *p = dma_alloc_coherent(&pdev->dev, len, phys, GFP_KERNEL);
62062306a36Sopenharmony_ci
62162306a36Sopenharmony_ci	if (!p)
62262306a36Sopenharmony_ci		return NULL;
62362306a36Sopenharmony_ci	if (sw_size && metadata) {
62462306a36Sopenharmony_ci		s = kcalloc(nelem, sw_size, GFP_KERNEL);
62562306a36Sopenharmony_ci
62662306a36Sopenharmony_ci		if (!s) {
62762306a36Sopenharmony_ci			dma_free_coherent(&pdev->dev, len, p, *phys);
62862306a36Sopenharmony_ci			return NULL;
62962306a36Sopenharmony_ci		}
63062306a36Sopenharmony_ci		*(void **)metadata = s;
63162306a36Sopenharmony_ci	}
63262306a36Sopenharmony_ci	return p;
63362306a36Sopenharmony_ci}
63462306a36Sopenharmony_ci
63562306a36Sopenharmony_ci/**
63662306a36Sopenharmony_ci *	t3_reset_qset - reset a sge qset
63762306a36Sopenharmony_ci *	@q: the queue set
63862306a36Sopenharmony_ci *
63962306a36Sopenharmony_ci *	Reset the qset structure.
64062306a36Sopenharmony_ci *	the NAPI structure is preserved in the event of
64162306a36Sopenharmony_ci *	the qset's reincarnation, for example during EEH recovery.
64262306a36Sopenharmony_ci */
64362306a36Sopenharmony_cistatic void t3_reset_qset(struct sge_qset *q)
64462306a36Sopenharmony_ci{
64562306a36Sopenharmony_ci	if (q->adap &&
64662306a36Sopenharmony_ci	    !(q->adap->flags & NAPI_INIT)) {
64762306a36Sopenharmony_ci		memset(q, 0, sizeof(*q));
64862306a36Sopenharmony_ci		return;
64962306a36Sopenharmony_ci	}
65062306a36Sopenharmony_ci
65162306a36Sopenharmony_ci	q->adap = NULL;
65262306a36Sopenharmony_ci	memset(&q->rspq, 0, sizeof(q->rspq));
65362306a36Sopenharmony_ci	memset(q->fl, 0, sizeof(struct sge_fl) * SGE_RXQ_PER_SET);
65462306a36Sopenharmony_ci	memset(q->txq, 0, sizeof(struct sge_txq) * SGE_TXQ_PER_SET);
65562306a36Sopenharmony_ci	q->txq_stopped = 0;
65662306a36Sopenharmony_ci	q->tx_reclaim_timer.function = NULL; /* for t3_stop_sge_timers() */
65762306a36Sopenharmony_ci	q->rx_reclaim_timer.function = NULL;
65862306a36Sopenharmony_ci	q->nomem = 0;
65962306a36Sopenharmony_ci	napi_free_frags(&q->napi);
66062306a36Sopenharmony_ci}
66162306a36Sopenharmony_ci
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_ci/**
66462306a36Sopenharmony_ci *	t3_free_qset - free the resources of an SGE queue set
66562306a36Sopenharmony_ci *	@adapter: the adapter owning the queue set
66662306a36Sopenharmony_ci *	@q: the queue set
66762306a36Sopenharmony_ci *
66862306a36Sopenharmony_ci *	Release the HW and SW resources associated with an SGE queue set, such
66962306a36Sopenharmony_ci *	as HW contexts, packet buffers, and descriptor rings.  Traffic to the
67062306a36Sopenharmony_ci *	queue set must be quiesced prior to calling this.
67162306a36Sopenharmony_ci */
67262306a36Sopenharmony_cistatic void t3_free_qset(struct adapter *adapter, struct sge_qset *q)
67362306a36Sopenharmony_ci{
67462306a36Sopenharmony_ci	int i;
67562306a36Sopenharmony_ci	struct pci_dev *pdev = adapter->pdev;
67662306a36Sopenharmony_ci
67762306a36Sopenharmony_ci	for (i = 0; i < SGE_RXQ_PER_SET; ++i)
67862306a36Sopenharmony_ci		if (q->fl[i].desc) {
67962306a36Sopenharmony_ci			spin_lock_irq(&adapter->sge.reg_lock);
68062306a36Sopenharmony_ci			t3_sge_disable_fl(adapter, q->fl[i].cntxt_id);
68162306a36Sopenharmony_ci			spin_unlock_irq(&adapter->sge.reg_lock);
68262306a36Sopenharmony_ci			free_rx_bufs(pdev, &q->fl[i]);
68362306a36Sopenharmony_ci			kfree(q->fl[i].sdesc);
68462306a36Sopenharmony_ci			dma_free_coherent(&pdev->dev,
68562306a36Sopenharmony_ci					  q->fl[i].size *
68662306a36Sopenharmony_ci					  sizeof(struct rx_desc), q->fl[i].desc,
68762306a36Sopenharmony_ci					  q->fl[i].phys_addr);
68862306a36Sopenharmony_ci		}
68962306a36Sopenharmony_ci
69062306a36Sopenharmony_ci	for (i = 0; i < SGE_TXQ_PER_SET; ++i)
69162306a36Sopenharmony_ci		if (q->txq[i].desc) {
69262306a36Sopenharmony_ci			spin_lock_irq(&adapter->sge.reg_lock);
69362306a36Sopenharmony_ci			t3_sge_enable_ecntxt(adapter, q->txq[i].cntxt_id, 0);
69462306a36Sopenharmony_ci			spin_unlock_irq(&adapter->sge.reg_lock);
69562306a36Sopenharmony_ci			if (q->txq[i].sdesc) {
69662306a36Sopenharmony_ci				free_tx_desc(adapter, &q->txq[i],
69762306a36Sopenharmony_ci					     q->txq[i].in_use);
69862306a36Sopenharmony_ci				kfree(q->txq[i].sdesc);
69962306a36Sopenharmony_ci			}
70062306a36Sopenharmony_ci			dma_free_coherent(&pdev->dev,
70162306a36Sopenharmony_ci					  q->txq[i].size *
70262306a36Sopenharmony_ci					  sizeof(struct tx_desc),
70362306a36Sopenharmony_ci					  q->txq[i].desc, q->txq[i].phys_addr);
70462306a36Sopenharmony_ci			__skb_queue_purge(&q->txq[i].sendq);
70562306a36Sopenharmony_ci		}
70662306a36Sopenharmony_ci
70762306a36Sopenharmony_ci	if (q->rspq.desc) {
70862306a36Sopenharmony_ci		spin_lock_irq(&adapter->sge.reg_lock);
70962306a36Sopenharmony_ci		t3_sge_disable_rspcntxt(adapter, q->rspq.cntxt_id);
71062306a36Sopenharmony_ci		spin_unlock_irq(&adapter->sge.reg_lock);
71162306a36Sopenharmony_ci		dma_free_coherent(&pdev->dev,
71262306a36Sopenharmony_ci				  q->rspq.size * sizeof(struct rsp_desc),
71362306a36Sopenharmony_ci				  q->rspq.desc, q->rspq.phys_addr);
71462306a36Sopenharmony_ci	}
71562306a36Sopenharmony_ci
71662306a36Sopenharmony_ci	t3_reset_qset(q);
71762306a36Sopenharmony_ci}
71862306a36Sopenharmony_ci
71962306a36Sopenharmony_ci/**
72062306a36Sopenharmony_ci *	init_qset_cntxt - initialize an SGE queue set context info
72162306a36Sopenharmony_ci *	@qs: the queue set
72262306a36Sopenharmony_ci *	@id: the queue set id
72362306a36Sopenharmony_ci *
72462306a36Sopenharmony_ci *	Initializes the TIDs and context ids for the queues of a queue set.
72562306a36Sopenharmony_ci */
72662306a36Sopenharmony_cistatic void init_qset_cntxt(struct sge_qset *qs, unsigned int id)
72762306a36Sopenharmony_ci{
72862306a36Sopenharmony_ci	qs->rspq.cntxt_id = id;
72962306a36Sopenharmony_ci	qs->fl[0].cntxt_id = 2 * id;
73062306a36Sopenharmony_ci	qs->fl[1].cntxt_id = 2 * id + 1;
73162306a36Sopenharmony_ci	qs->txq[TXQ_ETH].cntxt_id = FW_TUNNEL_SGEEC_START + id;
73262306a36Sopenharmony_ci	qs->txq[TXQ_ETH].token = FW_TUNNEL_TID_START + id;
73362306a36Sopenharmony_ci	qs->txq[TXQ_OFLD].cntxt_id = FW_OFLD_SGEEC_START + id;
73462306a36Sopenharmony_ci	qs->txq[TXQ_CTRL].cntxt_id = FW_CTRL_SGEEC_START + id;
73562306a36Sopenharmony_ci	qs->txq[TXQ_CTRL].token = FW_CTRL_TID_START + id;
73662306a36Sopenharmony_ci}
73762306a36Sopenharmony_ci
73862306a36Sopenharmony_ci/**
73962306a36Sopenharmony_ci *	sgl_len - calculates the size of an SGL of the given capacity
74062306a36Sopenharmony_ci *	@n: the number of SGL entries
74162306a36Sopenharmony_ci *
74262306a36Sopenharmony_ci *	Calculates the number of flits needed for a scatter/gather list that
74362306a36Sopenharmony_ci *	can hold the given number of entries.
74462306a36Sopenharmony_ci */
74562306a36Sopenharmony_cistatic inline unsigned int sgl_len(unsigned int n)
74662306a36Sopenharmony_ci{
74762306a36Sopenharmony_ci	/* alternatively: 3 * (n / 2) + 2 * (n & 1) */
74862306a36Sopenharmony_ci	return (3 * n) / 2 + (n & 1);
74962306a36Sopenharmony_ci}
75062306a36Sopenharmony_ci
75162306a36Sopenharmony_ci/**
75262306a36Sopenharmony_ci *	flits_to_desc - returns the num of Tx descriptors for the given flits
75362306a36Sopenharmony_ci *	@n: the number of flits
75462306a36Sopenharmony_ci *
75562306a36Sopenharmony_ci *	Calculates the number of Tx descriptors needed for the supplied number
75662306a36Sopenharmony_ci *	of flits.
75762306a36Sopenharmony_ci */
75862306a36Sopenharmony_cistatic inline unsigned int flits_to_desc(unsigned int n)
75962306a36Sopenharmony_ci{
76062306a36Sopenharmony_ci	BUG_ON(n >= ARRAY_SIZE(flit_desc_map));
76162306a36Sopenharmony_ci	return flit_desc_map[n];
76262306a36Sopenharmony_ci}
76362306a36Sopenharmony_ci
76462306a36Sopenharmony_ci/**
76562306a36Sopenharmony_ci *	get_packet - return the next ingress packet buffer from a free list
76662306a36Sopenharmony_ci *	@adap: the adapter that received the packet
76762306a36Sopenharmony_ci *	@fl: the SGE free list holding the packet
76862306a36Sopenharmony_ci *	@len: the packet length including any SGE padding
76962306a36Sopenharmony_ci *	@drop_thres: # of remaining buffers before we start dropping packets
77062306a36Sopenharmony_ci *
77162306a36Sopenharmony_ci *	Get the next packet from a free list and complete setup of the
77262306a36Sopenharmony_ci *	sk_buff.  If the packet is small we make a copy and recycle the
77362306a36Sopenharmony_ci *	original buffer, otherwise we use the original buffer itself.  If a
77462306a36Sopenharmony_ci *	positive drop threshold is supplied packets are dropped and their
77562306a36Sopenharmony_ci *	buffers recycled if (a) the number of remaining buffers is under the
77662306a36Sopenharmony_ci *	threshold and the packet is too big to copy, or (b) the packet should
77762306a36Sopenharmony_ci *	be copied but there is no memory for the copy.
77862306a36Sopenharmony_ci */
77962306a36Sopenharmony_cistatic struct sk_buff *get_packet(struct adapter *adap, struct sge_fl *fl,
78062306a36Sopenharmony_ci				  unsigned int len, unsigned int drop_thres)
78162306a36Sopenharmony_ci{
78262306a36Sopenharmony_ci	struct sk_buff *skb = NULL;
78362306a36Sopenharmony_ci	struct rx_sw_desc *sd = &fl->sdesc[fl->cidx];
78462306a36Sopenharmony_ci
78562306a36Sopenharmony_ci	prefetch(sd->skb->data);
78662306a36Sopenharmony_ci	fl->credits--;
78762306a36Sopenharmony_ci
78862306a36Sopenharmony_ci	if (len <= SGE_RX_COPY_THRES) {
78962306a36Sopenharmony_ci		skb = alloc_skb(len, GFP_ATOMIC);
79062306a36Sopenharmony_ci		if (likely(skb != NULL)) {
79162306a36Sopenharmony_ci			__skb_put(skb, len);
79262306a36Sopenharmony_ci			dma_sync_single_for_cpu(&adap->pdev->dev,
79362306a36Sopenharmony_ci						dma_unmap_addr(sd, dma_addr),
79462306a36Sopenharmony_ci						len, DMA_FROM_DEVICE);
79562306a36Sopenharmony_ci			memcpy(skb->data, sd->skb->data, len);
79662306a36Sopenharmony_ci			dma_sync_single_for_device(&adap->pdev->dev,
79762306a36Sopenharmony_ci						   dma_unmap_addr(sd, dma_addr),
79862306a36Sopenharmony_ci						   len, DMA_FROM_DEVICE);
79962306a36Sopenharmony_ci		} else if (!drop_thres)
80062306a36Sopenharmony_ci			goto use_orig_buf;
80162306a36Sopenharmony_cirecycle:
80262306a36Sopenharmony_ci		recycle_rx_buf(adap, fl, fl->cidx);
80362306a36Sopenharmony_ci		return skb;
80462306a36Sopenharmony_ci	}
80562306a36Sopenharmony_ci
80662306a36Sopenharmony_ci	if (unlikely(fl->credits < drop_thres) &&
80762306a36Sopenharmony_ci	    refill_fl(adap, fl, min(MAX_RX_REFILL, fl->size - fl->credits - 1),
80862306a36Sopenharmony_ci		      GFP_ATOMIC | __GFP_COMP) == 0)
80962306a36Sopenharmony_ci		goto recycle;
81062306a36Sopenharmony_ci
81162306a36Sopenharmony_ciuse_orig_buf:
81262306a36Sopenharmony_ci	dma_unmap_single(&adap->pdev->dev, dma_unmap_addr(sd, dma_addr),
81362306a36Sopenharmony_ci			 fl->buf_size, DMA_FROM_DEVICE);
81462306a36Sopenharmony_ci	skb = sd->skb;
81562306a36Sopenharmony_ci	skb_put(skb, len);
81662306a36Sopenharmony_ci	__refill_fl(adap, fl);
81762306a36Sopenharmony_ci	return skb;
81862306a36Sopenharmony_ci}
81962306a36Sopenharmony_ci
82062306a36Sopenharmony_ci/**
82162306a36Sopenharmony_ci *	get_packet_pg - return the next ingress packet buffer from a free list
82262306a36Sopenharmony_ci *	@adap: the adapter that received the packet
82362306a36Sopenharmony_ci *	@fl: the SGE free list holding the packet
82462306a36Sopenharmony_ci *	@q: the queue
82562306a36Sopenharmony_ci *	@len: the packet length including any SGE padding
82662306a36Sopenharmony_ci *	@drop_thres: # of remaining buffers before we start dropping packets
82762306a36Sopenharmony_ci *
82862306a36Sopenharmony_ci *	Get the next packet from a free list populated with page chunks.
82962306a36Sopenharmony_ci *	If the packet is small we make a copy and recycle the original buffer,
83062306a36Sopenharmony_ci *	otherwise we attach the original buffer as a page fragment to a fresh
83162306a36Sopenharmony_ci *	sk_buff.  If a positive drop threshold is supplied packets are dropped
83262306a36Sopenharmony_ci *	and their buffers recycled if (a) the number of remaining buffers is
83362306a36Sopenharmony_ci *	under the threshold and the packet is too big to copy, or (b) there's
83462306a36Sopenharmony_ci *	no system memory.
83562306a36Sopenharmony_ci *
83662306a36Sopenharmony_ci * 	Note: this function is similar to @get_packet but deals with Rx buffers
83762306a36Sopenharmony_ci * 	that are page chunks rather than sk_buffs.
83862306a36Sopenharmony_ci */
83962306a36Sopenharmony_cistatic struct sk_buff *get_packet_pg(struct adapter *adap, struct sge_fl *fl,
84062306a36Sopenharmony_ci				     struct sge_rspq *q, unsigned int len,
84162306a36Sopenharmony_ci				     unsigned int drop_thres)
84262306a36Sopenharmony_ci{
84362306a36Sopenharmony_ci	struct sk_buff *newskb, *skb;
84462306a36Sopenharmony_ci	struct rx_sw_desc *sd = &fl->sdesc[fl->cidx];
84562306a36Sopenharmony_ci
84662306a36Sopenharmony_ci	dma_addr_t dma_addr = dma_unmap_addr(sd, dma_addr);
84762306a36Sopenharmony_ci
84862306a36Sopenharmony_ci	newskb = skb = q->pg_skb;
84962306a36Sopenharmony_ci	if (!skb && (len <= SGE_RX_COPY_THRES)) {
85062306a36Sopenharmony_ci		newskb = alloc_skb(len, GFP_ATOMIC);
85162306a36Sopenharmony_ci		if (likely(newskb != NULL)) {
85262306a36Sopenharmony_ci			__skb_put(newskb, len);
85362306a36Sopenharmony_ci			dma_sync_single_for_cpu(&adap->pdev->dev, dma_addr,
85462306a36Sopenharmony_ci						len, DMA_FROM_DEVICE);
85562306a36Sopenharmony_ci			memcpy(newskb->data, sd->pg_chunk.va, len);
85662306a36Sopenharmony_ci			dma_sync_single_for_device(&adap->pdev->dev, dma_addr,
85762306a36Sopenharmony_ci						   len, DMA_FROM_DEVICE);
85862306a36Sopenharmony_ci		} else if (!drop_thres)
85962306a36Sopenharmony_ci			return NULL;
86062306a36Sopenharmony_cirecycle:
86162306a36Sopenharmony_ci		fl->credits--;
86262306a36Sopenharmony_ci		recycle_rx_buf(adap, fl, fl->cidx);
86362306a36Sopenharmony_ci		q->rx_recycle_buf++;
86462306a36Sopenharmony_ci		return newskb;
86562306a36Sopenharmony_ci	}
86662306a36Sopenharmony_ci
86762306a36Sopenharmony_ci	if (unlikely(q->rx_recycle_buf || (!skb && fl->credits <= drop_thres)))
86862306a36Sopenharmony_ci		goto recycle;
86962306a36Sopenharmony_ci
87062306a36Sopenharmony_ci	prefetch(sd->pg_chunk.p_cnt);
87162306a36Sopenharmony_ci
87262306a36Sopenharmony_ci	if (!skb)
87362306a36Sopenharmony_ci		newskb = alloc_skb(SGE_RX_PULL_LEN, GFP_ATOMIC);
87462306a36Sopenharmony_ci
87562306a36Sopenharmony_ci	if (unlikely(!newskb)) {
87662306a36Sopenharmony_ci		if (!drop_thres)
87762306a36Sopenharmony_ci			return NULL;
87862306a36Sopenharmony_ci		goto recycle;
87962306a36Sopenharmony_ci	}
88062306a36Sopenharmony_ci
88162306a36Sopenharmony_ci	dma_sync_single_for_cpu(&adap->pdev->dev, dma_addr, len,
88262306a36Sopenharmony_ci				DMA_FROM_DEVICE);
88362306a36Sopenharmony_ci	(*sd->pg_chunk.p_cnt)--;
88462306a36Sopenharmony_ci	if (!*sd->pg_chunk.p_cnt && sd->pg_chunk.page != fl->pg_chunk.page)
88562306a36Sopenharmony_ci		dma_unmap_page(&adap->pdev->dev, sd->pg_chunk.mapping,
88662306a36Sopenharmony_ci			       fl->alloc_size, DMA_FROM_DEVICE);
88762306a36Sopenharmony_ci	if (!skb) {
88862306a36Sopenharmony_ci		__skb_put(newskb, SGE_RX_PULL_LEN);
88962306a36Sopenharmony_ci		memcpy(newskb->data, sd->pg_chunk.va, SGE_RX_PULL_LEN);
89062306a36Sopenharmony_ci		skb_fill_page_desc(newskb, 0, sd->pg_chunk.page,
89162306a36Sopenharmony_ci				   sd->pg_chunk.offset + SGE_RX_PULL_LEN,
89262306a36Sopenharmony_ci				   len - SGE_RX_PULL_LEN);
89362306a36Sopenharmony_ci		newskb->len = len;
89462306a36Sopenharmony_ci		newskb->data_len = len - SGE_RX_PULL_LEN;
89562306a36Sopenharmony_ci		newskb->truesize += newskb->data_len;
89662306a36Sopenharmony_ci	} else {
89762306a36Sopenharmony_ci		skb_fill_page_desc(newskb, skb_shinfo(newskb)->nr_frags,
89862306a36Sopenharmony_ci				   sd->pg_chunk.page,
89962306a36Sopenharmony_ci				   sd->pg_chunk.offset, len);
90062306a36Sopenharmony_ci		newskb->len += len;
90162306a36Sopenharmony_ci		newskb->data_len += len;
90262306a36Sopenharmony_ci		newskb->truesize += len;
90362306a36Sopenharmony_ci	}
90462306a36Sopenharmony_ci
90562306a36Sopenharmony_ci	fl->credits--;
90662306a36Sopenharmony_ci	/*
90762306a36Sopenharmony_ci	 * We do not refill FLs here, we let the caller do it to overlap a
90862306a36Sopenharmony_ci	 * prefetch.
90962306a36Sopenharmony_ci	 */
91062306a36Sopenharmony_ci	return newskb;
91162306a36Sopenharmony_ci}
91262306a36Sopenharmony_ci
91362306a36Sopenharmony_ci/**
91462306a36Sopenharmony_ci *	get_imm_packet - return the next ingress packet buffer from a response
91562306a36Sopenharmony_ci *	@resp: the response descriptor containing the packet data
91662306a36Sopenharmony_ci *
91762306a36Sopenharmony_ci *	Return a packet containing the immediate data of the given response.
91862306a36Sopenharmony_ci */
91962306a36Sopenharmony_cistatic inline struct sk_buff *get_imm_packet(const struct rsp_desc *resp)
92062306a36Sopenharmony_ci{
92162306a36Sopenharmony_ci	struct sk_buff *skb = alloc_skb(IMMED_PKT_SIZE, GFP_ATOMIC);
92262306a36Sopenharmony_ci
92362306a36Sopenharmony_ci	if (skb) {
92462306a36Sopenharmony_ci		__skb_put(skb, IMMED_PKT_SIZE);
92562306a36Sopenharmony_ci		BUILD_BUG_ON(IMMED_PKT_SIZE != sizeof(resp->immediate));
92662306a36Sopenharmony_ci		skb_copy_to_linear_data(skb, &resp->immediate, IMMED_PKT_SIZE);
92762306a36Sopenharmony_ci	}
92862306a36Sopenharmony_ci	return skb;
92962306a36Sopenharmony_ci}
93062306a36Sopenharmony_ci
93162306a36Sopenharmony_ci/**
93262306a36Sopenharmony_ci *	calc_tx_descs - calculate the number of Tx descriptors for a packet
93362306a36Sopenharmony_ci *	@skb: the packet
93462306a36Sopenharmony_ci *
93562306a36Sopenharmony_ci * 	Returns the number of Tx descriptors needed for the given Ethernet
93662306a36Sopenharmony_ci * 	packet.  Ethernet packets require addition of WR and CPL headers.
93762306a36Sopenharmony_ci */
93862306a36Sopenharmony_cistatic inline unsigned int calc_tx_descs(const struct sk_buff *skb)
93962306a36Sopenharmony_ci{
94062306a36Sopenharmony_ci	unsigned int flits;
94162306a36Sopenharmony_ci
94262306a36Sopenharmony_ci	if (skb->len <= WR_LEN - sizeof(struct cpl_tx_pkt))
94362306a36Sopenharmony_ci		return 1;
94462306a36Sopenharmony_ci
94562306a36Sopenharmony_ci	flits = sgl_len(skb_shinfo(skb)->nr_frags + 1) + 2;
94662306a36Sopenharmony_ci	if (skb_shinfo(skb)->gso_size)
94762306a36Sopenharmony_ci		flits++;
94862306a36Sopenharmony_ci	return flits_to_desc(flits);
94962306a36Sopenharmony_ci}
95062306a36Sopenharmony_ci
95162306a36Sopenharmony_ci/*	map_skb - map a packet main body and its page fragments
95262306a36Sopenharmony_ci *	@pdev: the PCI device
95362306a36Sopenharmony_ci *	@skb: the packet
95462306a36Sopenharmony_ci *	@addr: placeholder to save the mapped addresses
95562306a36Sopenharmony_ci *
95662306a36Sopenharmony_ci *	map the main body of an sk_buff and its page fragments, if any.
95762306a36Sopenharmony_ci */
95862306a36Sopenharmony_cistatic int map_skb(struct pci_dev *pdev, const struct sk_buff *skb,
95962306a36Sopenharmony_ci		   dma_addr_t *addr)
96062306a36Sopenharmony_ci{
96162306a36Sopenharmony_ci	const skb_frag_t *fp, *end;
96262306a36Sopenharmony_ci	const struct skb_shared_info *si;
96362306a36Sopenharmony_ci
96462306a36Sopenharmony_ci	if (skb_headlen(skb)) {
96562306a36Sopenharmony_ci		*addr = dma_map_single(&pdev->dev, skb->data,
96662306a36Sopenharmony_ci				       skb_headlen(skb), DMA_TO_DEVICE);
96762306a36Sopenharmony_ci		if (dma_mapping_error(&pdev->dev, *addr))
96862306a36Sopenharmony_ci			goto out_err;
96962306a36Sopenharmony_ci		addr++;
97062306a36Sopenharmony_ci	}
97162306a36Sopenharmony_ci
97262306a36Sopenharmony_ci	si = skb_shinfo(skb);
97362306a36Sopenharmony_ci	end = &si->frags[si->nr_frags];
97462306a36Sopenharmony_ci
97562306a36Sopenharmony_ci	for (fp = si->frags; fp < end; fp++) {
97662306a36Sopenharmony_ci		*addr = skb_frag_dma_map(&pdev->dev, fp, 0, skb_frag_size(fp),
97762306a36Sopenharmony_ci					 DMA_TO_DEVICE);
97862306a36Sopenharmony_ci		if (dma_mapping_error(&pdev->dev, *addr))
97962306a36Sopenharmony_ci			goto unwind;
98062306a36Sopenharmony_ci		addr++;
98162306a36Sopenharmony_ci	}
98262306a36Sopenharmony_ci	return 0;
98362306a36Sopenharmony_ci
98462306a36Sopenharmony_ciunwind:
98562306a36Sopenharmony_ci	while (fp-- > si->frags)
98662306a36Sopenharmony_ci		dma_unmap_page(&pdev->dev, *--addr, skb_frag_size(fp),
98762306a36Sopenharmony_ci			       DMA_TO_DEVICE);
98862306a36Sopenharmony_ci
98962306a36Sopenharmony_ci	dma_unmap_single(&pdev->dev, addr[-1], skb_headlen(skb),
99062306a36Sopenharmony_ci			 DMA_TO_DEVICE);
99162306a36Sopenharmony_ciout_err:
99262306a36Sopenharmony_ci	return -ENOMEM;
99362306a36Sopenharmony_ci}
99462306a36Sopenharmony_ci
99562306a36Sopenharmony_ci/**
99662306a36Sopenharmony_ci *	write_sgl - populate a scatter/gather list for a packet
99762306a36Sopenharmony_ci *	@skb: the packet
99862306a36Sopenharmony_ci *	@sgp: the SGL to populate
99962306a36Sopenharmony_ci *	@start: start address of skb main body data to include in the SGL
100062306a36Sopenharmony_ci *	@len: length of skb main body data to include in the SGL
100162306a36Sopenharmony_ci *	@addr: the list of the mapped addresses
100262306a36Sopenharmony_ci *
100362306a36Sopenharmony_ci *	Copies the scatter/gather list for the buffers that make up a packet
100462306a36Sopenharmony_ci *	and returns the SGL size in 8-byte words.  The caller must size the SGL
100562306a36Sopenharmony_ci *	appropriately.
100662306a36Sopenharmony_ci */
100762306a36Sopenharmony_cistatic inline unsigned int write_sgl(const struct sk_buff *skb,
100862306a36Sopenharmony_ci				     struct sg_ent *sgp, unsigned char *start,
100962306a36Sopenharmony_ci				     unsigned int len, const dma_addr_t *addr)
101062306a36Sopenharmony_ci{
101162306a36Sopenharmony_ci	unsigned int i, j = 0, k = 0, nfrags;
101262306a36Sopenharmony_ci
101362306a36Sopenharmony_ci	if (len) {
101462306a36Sopenharmony_ci		sgp->len[0] = cpu_to_be32(len);
101562306a36Sopenharmony_ci		sgp->addr[j++] = cpu_to_be64(addr[k++]);
101662306a36Sopenharmony_ci	}
101762306a36Sopenharmony_ci
101862306a36Sopenharmony_ci	nfrags = skb_shinfo(skb)->nr_frags;
101962306a36Sopenharmony_ci	for (i = 0; i < nfrags; i++) {
102062306a36Sopenharmony_ci		const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
102162306a36Sopenharmony_ci
102262306a36Sopenharmony_ci		sgp->len[j] = cpu_to_be32(skb_frag_size(frag));
102362306a36Sopenharmony_ci		sgp->addr[j] = cpu_to_be64(addr[k++]);
102462306a36Sopenharmony_ci		j ^= 1;
102562306a36Sopenharmony_ci		if (j == 0)
102662306a36Sopenharmony_ci			++sgp;
102762306a36Sopenharmony_ci	}
102862306a36Sopenharmony_ci	if (j)
102962306a36Sopenharmony_ci		sgp->len[j] = 0;
103062306a36Sopenharmony_ci	return ((nfrags + (len != 0)) * 3) / 2 + j;
103162306a36Sopenharmony_ci}
103262306a36Sopenharmony_ci
103362306a36Sopenharmony_ci/**
103462306a36Sopenharmony_ci *	check_ring_tx_db - check and potentially ring a Tx queue's doorbell
103562306a36Sopenharmony_ci *	@adap: the adapter
103662306a36Sopenharmony_ci *	@q: the Tx queue
103762306a36Sopenharmony_ci *
103862306a36Sopenharmony_ci *	Ring the doorbel if a Tx queue is asleep.  There is a natural race,
103962306a36Sopenharmony_ci *	where the HW is going to sleep just after we checked, however,
104062306a36Sopenharmony_ci *	then the interrupt handler will detect the outstanding TX packet
104162306a36Sopenharmony_ci *	and ring the doorbell for us.
104262306a36Sopenharmony_ci *
104362306a36Sopenharmony_ci *	When GTS is disabled we unconditionally ring the doorbell.
104462306a36Sopenharmony_ci */
104562306a36Sopenharmony_cistatic inline void check_ring_tx_db(struct adapter *adap, struct sge_txq *q)
104662306a36Sopenharmony_ci{
104762306a36Sopenharmony_ci#if USE_GTS
104862306a36Sopenharmony_ci	clear_bit(TXQ_LAST_PKT_DB, &q->flags);
104962306a36Sopenharmony_ci	if (test_and_set_bit(TXQ_RUNNING, &q->flags) == 0) {
105062306a36Sopenharmony_ci		set_bit(TXQ_LAST_PKT_DB, &q->flags);
105162306a36Sopenharmony_ci		t3_write_reg(adap, A_SG_KDOORBELL,
105262306a36Sopenharmony_ci			     F_SELEGRCNTX | V_EGRCNTX(q->cntxt_id));
105362306a36Sopenharmony_ci	}
105462306a36Sopenharmony_ci#else
105562306a36Sopenharmony_ci	wmb();			/* write descriptors before telling HW */
105662306a36Sopenharmony_ci	t3_write_reg(adap, A_SG_KDOORBELL,
105762306a36Sopenharmony_ci		     F_SELEGRCNTX | V_EGRCNTX(q->cntxt_id));
105862306a36Sopenharmony_ci#endif
105962306a36Sopenharmony_ci}
106062306a36Sopenharmony_ci
106162306a36Sopenharmony_cistatic inline void wr_gen2(struct tx_desc *d, unsigned int gen)
106262306a36Sopenharmony_ci{
106362306a36Sopenharmony_ci#if SGE_NUM_GENBITS == 2
106462306a36Sopenharmony_ci	d->flit[TX_DESC_FLITS - 1] = cpu_to_be64(gen);
106562306a36Sopenharmony_ci#endif
106662306a36Sopenharmony_ci}
106762306a36Sopenharmony_ci
106862306a36Sopenharmony_ci/**
106962306a36Sopenharmony_ci *	write_wr_hdr_sgl - write a WR header and, optionally, SGL
107062306a36Sopenharmony_ci *	@ndesc: number of Tx descriptors spanned by the SGL
107162306a36Sopenharmony_ci *	@skb: the packet corresponding to the WR
107262306a36Sopenharmony_ci *	@d: first Tx descriptor to be written
107362306a36Sopenharmony_ci *	@pidx: index of above descriptors
107462306a36Sopenharmony_ci *	@q: the SGE Tx queue
107562306a36Sopenharmony_ci *	@sgl: the SGL
107662306a36Sopenharmony_ci *	@flits: number of flits to the start of the SGL in the first descriptor
107762306a36Sopenharmony_ci *	@sgl_flits: the SGL size in flits
107862306a36Sopenharmony_ci *	@gen: the Tx descriptor generation
107962306a36Sopenharmony_ci *	@wr_hi: top 32 bits of WR header based on WR type (big endian)
108062306a36Sopenharmony_ci *	@wr_lo: low 32 bits of WR header based on WR type (big endian)
108162306a36Sopenharmony_ci *
108262306a36Sopenharmony_ci *	Write a work request header and an associated SGL.  If the SGL is
108362306a36Sopenharmony_ci *	small enough to fit into one Tx descriptor it has already been written
108462306a36Sopenharmony_ci *	and we just need to write the WR header.  Otherwise we distribute the
108562306a36Sopenharmony_ci *	SGL across the number of descriptors it spans.
108662306a36Sopenharmony_ci */
108762306a36Sopenharmony_cistatic void write_wr_hdr_sgl(unsigned int ndesc, struct sk_buff *skb,
108862306a36Sopenharmony_ci			     struct tx_desc *d, unsigned int pidx,
108962306a36Sopenharmony_ci			     const struct sge_txq *q,
109062306a36Sopenharmony_ci			     const struct sg_ent *sgl,
109162306a36Sopenharmony_ci			     unsigned int flits, unsigned int sgl_flits,
109262306a36Sopenharmony_ci			     unsigned int gen, __be32 wr_hi,
109362306a36Sopenharmony_ci			     __be32 wr_lo)
109462306a36Sopenharmony_ci{
109562306a36Sopenharmony_ci	struct work_request_hdr *wrp = (struct work_request_hdr *)d;
109662306a36Sopenharmony_ci	struct tx_sw_desc *sd = &q->sdesc[pidx];
109762306a36Sopenharmony_ci
109862306a36Sopenharmony_ci	sd->skb = skb;
109962306a36Sopenharmony_ci	if (need_skb_unmap()) {
110062306a36Sopenharmony_ci		sd->fragidx = 0;
110162306a36Sopenharmony_ci		sd->addr_idx = 0;
110262306a36Sopenharmony_ci		sd->sflit = flits;
110362306a36Sopenharmony_ci	}
110462306a36Sopenharmony_ci
110562306a36Sopenharmony_ci	if (likely(ndesc == 1)) {
110662306a36Sopenharmony_ci		sd->eop = 1;
110762306a36Sopenharmony_ci		wrp->wr_hi = htonl(F_WR_SOP | F_WR_EOP | V_WR_DATATYPE(1) |
110862306a36Sopenharmony_ci				   V_WR_SGLSFLT(flits)) | wr_hi;
110962306a36Sopenharmony_ci		dma_wmb();
111062306a36Sopenharmony_ci		wrp->wr_lo = htonl(V_WR_LEN(flits + sgl_flits) |
111162306a36Sopenharmony_ci				   V_WR_GEN(gen)) | wr_lo;
111262306a36Sopenharmony_ci		wr_gen2(d, gen);
111362306a36Sopenharmony_ci	} else {
111462306a36Sopenharmony_ci		unsigned int ogen = gen;
111562306a36Sopenharmony_ci		const u64 *fp = (const u64 *)sgl;
111662306a36Sopenharmony_ci		struct work_request_hdr *wp = wrp;
111762306a36Sopenharmony_ci
111862306a36Sopenharmony_ci		wrp->wr_hi = htonl(F_WR_SOP | V_WR_DATATYPE(1) |
111962306a36Sopenharmony_ci				   V_WR_SGLSFLT(flits)) | wr_hi;
112062306a36Sopenharmony_ci
112162306a36Sopenharmony_ci		while (sgl_flits) {
112262306a36Sopenharmony_ci			unsigned int avail = WR_FLITS - flits;
112362306a36Sopenharmony_ci
112462306a36Sopenharmony_ci			if (avail > sgl_flits)
112562306a36Sopenharmony_ci				avail = sgl_flits;
112662306a36Sopenharmony_ci			memcpy(&d->flit[flits], fp, avail * sizeof(*fp));
112762306a36Sopenharmony_ci			sgl_flits -= avail;
112862306a36Sopenharmony_ci			ndesc--;
112962306a36Sopenharmony_ci			if (!sgl_flits)
113062306a36Sopenharmony_ci				break;
113162306a36Sopenharmony_ci
113262306a36Sopenharmony_ci			fp += avail;
113362306a36Sopenharmony_ci			d++;
113462306a36Sopenharmony_ci			sd->eop = 0;
113562306a36Sopenharmony_ci			sd++;
113662306a36Sopenharmony_ci			if (++pidx == q->size) {
113762306a36Sopenharmony_ci				pidx = 0;
113862306a36Sopenharmony_ci				gen ^= 1;
113962306a36Sopenharmony_ci				d = q->desc;
114062306a36Sopenharmony_ci				sd = q->sdesc;
114162306a36Sopenharmony_ci			}
114262306a36Sopenharmony_ci
114362306a36Sopenharmony_ci			sd->skb = skb;
114462306a36Sopenharmony_ci			wrp = (struct work_request_hdr *)d;
114562306a36Sopenharmony_ci			wrp->wr_hi = htonl(V_WR_DATATYPE(1) |
114662306a36Sopenharmony_ci					   V_WR_SGLSFLT(1)) | wr_hi;
114762306a36Sopenharmony_ci			wrp->wr_lo = htonl(V_WR_LEN(min(WR_FLITS,
114862306a36Sopenharmony_ci							sgl_flits + 1)) |
114962306a36Sopenharmony_ci					   V_WR_GEN(gen)) | wr_lo;
115062306a36Sopenharmony_ci			wr_gen2(d, gen);
115162306a36Sopenharmony_ci			flits = 1;
115262306a36Sopenharmony_ci		}
115362306a36Sopenharmony_ci		sd->eop = 1;
115462306a36Sopenharmony_ci		wrp->wr_hi |= htonl(F_WR_EOP);
115562306a36Sopenharmony_ci		dma_wmb();
115662306a36Sopenharmony_ci		wp->wr_lo = htonl(V_WR_LEN(WR_FLITS) | V_WR_GEN(ogen)) | wr_lo;
115762306a36Sopenharmony_ci		wr_gen2((struct tx_desc *)wp, ogen);
115862306a36Sopenharmony_ci		WARN_ON(ndesc != 0);
115962306a36Sopenharmony_ci	}
116062306a36Sopenharmony_ci}
116162306a36Sopenharmony_ci
116262306a36Sopenharmony_ci/**
116362306a36Sopenharmony_ci *	write_tx_pkt_wr - write a TX_PKT work request
116462306a36Sopenharmony_ci *	@adap: the adapter
116562306a36Sopenharmony_ci *	@skb: the packet to send
116662306a36Sopenharmony_ci *	@pi: the egress interface
116762306a36Sopenharmony_ci *	@pidx: index of the first Tx descriptor to write
116862306a36Sopenharmony_ci *	@gen: the generation value to use
116962306a36Sopenharmony_ci *	@q: the Tx queue
117062306a36Sopenharmony_ci *	@ndesc: number of descriptors the packet will occupy
117162306a36Sopenharmony_ci *	@compl: the value of the COMPL bit to use
117262306a36Sopenharmony_ci *	@addr: address
117362306a36Sopenharmony_ci *
117462306a36Sopenharmony_ci *	Generate a TX_PKT work request to send the supplied packet.
117562306a36Sopenharmony_ci */
117662306a36Sopenharmony_cistatic void write_tx_pkt_wr(struct adapter *adap, struct sk_buff *skb,
117762306a36Sopenharmony_ci			    const struct port_info *pi,
117862306a36Sopenharmony_ci			    unsigned int pidx, unsigned int gen,
117962306a36Sopenharmony_ci			    struct sge_txq *q, unsigned int ndesc,
118062306a36Sopenharmony_ci			    unsigned int compl, const dma_addr_t *addr)
118162306a36Sopenharmony_ci{
118262306a36Sopenharmony_ci	unsigned int flits, sgl_flits, cntrl, tso_info;
118362306a36Sopenharmony_ci	struct sg_ent *sgp, sgl[MAX_SKB_FRAGS / 2 + 1];
118462306a36Sopenharmony_ci	struct tx_desc *d = &q->desc[pidx];
118562306a36Sopenharmony_ci	struct cpl_tx_pkt *cpl = (struct cpl_tx_pkt *)d;
118662306a36Sopenharmony_ci
118762306a36Sopenharmony_ci	cpl->len = htonl(skb->len);
118862306a36Sopenharmony_ci	cntrl = V_TXPKT_INTF(pi->port_id);
118962306a36Sopenharmony_ci
119062306a36Sopenharmony_ci	if (skb_vlan_tag_present(skb))
119162306a36Sopenharmony_ci		cntrl |= F_TXPKT_VLAN_VLD | V_TXPKT_VLAN(skb_vlan_tag_get(skb));
119262306a36Sopenharmony_ci
119362306a36Sopenharmony_ci	tso_info = V_LSO_MSS(skb_shinfo(skb)->gso_size);
119462306a36Sopenharmony_ci	if (tso_info) {
119562306a36Sopenharmony_ci		int eth_type;
119662306a36Sopenharmony_ci		struct cpl_tx_pkt_lso *hdr = (struct cpl_tx_pkt_lso *)cpl;
119762306a36Sopenharmony_ci
119862306a36Sopenharmony_ci		d->flit[2] = 0;
119962306a36Sopenharmony_ci		cntrl |= V_TXPKT_OPCODE(CPL_TX_PKT_LSO);
120062306a36Sopenharmony_ci		hdr->cntrl = htonl(cntrl);
120162306a36Sopenharmony_ci		eth_type = skb_network_offset(skb) == ETH_HLEN ?
120262306a36Sopenharmony_ci		    CPL_ETH_II : CPL_ETH_II_VLAN;
120362306a36Sopenharmony_ci		tso_info |= V_LSO_ETH_TYPE(eth_type) |
120462306a36Sopenharmony_ci		    V_LSO_IPHDR_WORDS(ip_hdr(skb)->ihl) |
120562306a36Sopenharmony_ci		    V_LSO_TCPHDR_WORDS(tcp_hdr(skb)->doff);
120662306a36Sopenharmony_ci		hdr->lso_info = htonl(tso_info);
120762306a36Sopenharmony_ci		flits = 3;
120862306a36Sopenharmony_ci	} else {
120962306a36Sopenharmony_ci		cntrl |= V_TXPKT_OPCODE(CPL_TX_PKT);
121062306a36Sopenharmony_ci		cntrl |= F_TXPKT_IPCSUM_DIS;	/* SW calculates IP csum */
121162306a36Sopenharmony_ci		cntrl |= V_TXPKT_L4CSUM_DIS(skb->ip_summed != CHECKSUM_PARTIAL);
121262306a36Sopenharmony_ci		cpl->cntrl = htonl(cntrl);
121362306a36Sopenharmony_ci
121462306a36Sopenharmony_ci		if (skb->len <= WR_LEN - sizeof(*cpl)) {
121562306a36Sopenharmony_ci			q->sdesc[pidx].skb = NULL;
121662306a36Sopenharmony_ci			if (!skb->data_len)
121762306a36Sopenharmony_ci				skb_copy_from_linear_data(skb, &d->flit[2],
121862306a36Sopenharmony_ci							  skb->len);
121962306a36Sopenharmony_ci			else
122062306a36Sopenharmony_ci				skb_copy_bits(skb, 0, &d->flit[2], skb->len);
122162306a36Sopenharmony_ci
122262306a36Sopenharmony_ci			flits = (skb->len + 7) / 8 + 2;
122362306a36Sopenharmony_ci			cpl->wr.wr_hi = htonl(V_WR_BCNTLFLT(skb->len & 7) |
122462306a36Sopenharmony_ci					      V_WR_OP(FW_WROPCODE_TUNNEL_TX_PKT)
122562306a36Sopenharmony_ci					      | F_WR_SOP | F_WR_EOP | compl);
122662306a36Sopenharmony_ci			dma_wmb();
122762306a36Sopenharmony_ci			cpl->wr.wr_lo = htonl(V_WR_LEN(flits) | V_WR_GEN(gen) |
122862306a36Sopenharmony_ci					      V_WR_TID(q->token));
122962306a36Sopenharmony_ci			wr_gen2(d, gen);
123062306a36Sopenharmony_ci			dev_consume_skb_any(skb);
123162306a36Sopenharmony_ci			return;
123262306a36Sopenharmony_ci		}
123362306a36Sopenharmony_ci
123462306a36Sopenharmony_ci		flits = 2;
123562306a36Sopenharmony_ci	}
123662306a36Sopenharmony_ci
123762306a36Sopenharmony_ci	sgp = ndesc == 1 ? (struct sg_ent *)&d->flit[flits] : sgl;
123862306a36Sopenharmony_ci	sgl_flits = write_sgl(skb, sgp, skb->data, skb_headlen(skb), addr);
123962306a36Sopenharmony_ci
124062306a36Sopenharmony_ci	write_wr_hdr_sgl(ndesc, skb, d, pidx, q, sgl, flits, sgl_flits, gen,
124162306a36Sopenharmony_ci			 htonl(V_WR_OP(FW_WROPCODE_TUNNEL_TX_PKT) | compl),
124262306a36Sopenharmony_ci			 htonl(V_WR_TID(q->token)));
124362306a36Sopenharmony_ci}
124462306a36Sopenharmony_ci
124562306a36Sopenharmony_cistatic inline void t3_stop_tx_queue(struct netdev_queue *txq,
124662306a36Sopenharmony_ci				    struct sge_qset *qs, struct sge_txq *q)
124762306a36Sopenharmony_ci{
124862306a36Sopenharmony_ci	netif_tx_stop_queue(txq);
124962306a36Sopenharmony_ci	set_bit(TXQ_ETH, &qs->txq_stopped);
125062306a36Sopenharmony_ci	q->stops++;
125162306a36Sopenharmony_ci}
125262306a36Sopenharmony_ci
125362306a36Sopenharmony_ci/**
125462306a36Sopenharmony_ci *	t3_eth_xmit - add a packet to the Ethernet Tx queue
125562306a36Sopenharmony_ci *	@skb: the packet
125662306a36Sopenharmony_ci *	@dev: the egress net device
125762306a36Sopenharmony_ci *
125862306a36Sopenharmony_ci *	Add a packet to an SGE Tx queue.  Runs with softirqs disabled.
125962306a36Sopenharmony_ci */
126062306a36Sopenharmony_cinetdev_tx_t t3_eth_xmit(struct sk_buff *skb, struct net_device *dev)
126162306a36Sopenharmony_ci{
126262306a36Sopenharmony_ci	int qidx;
126362306a36Sopenharmony_ci	unsigned int ndesc, pidx, credits, gen, compl;
126462306a36Sopenharmony_ci	const struct port_info *pi = netdev_priv(dev);
126562306a36Sopenharmony_ci	struct adapter *adap = pi->adapter;
126662306a36Sopenharmony_ci	struct netdev_queue *txq;
126762306a36Sopenharmony_ci	struct sge_qset *qs;
126862306a36Sopenharmony_ci	struct sge_txq *q;
126962306a36Sopenharmony_ci	dma_addr_t addr[MAX_SKB_FRAGS + 1];
127062306a36Sopenharmony_ci
127162306a36Sopenharmony_ci	/*
127262306a36Sopenharmony_ci	 * The chip min packet length is 9 octets but play safe and reject
127362306a36Sopenharmony_ci	 * anything shorter than an Ethernet header.
127462306a36Sopenharmony_ci	 */
127562306a36Sopenharmony_ci	if (unlikely(skb->len < ETH_HLEN)) {
127662306a36Sopenharmony_ci		dev_kfree_skb_any(skb);
127762306a36Sopenharmony_ci		return NETDEV_TX_OK;
127862306a36Sopenharmony_ci	}
127962306a36Sopenharmony_ci
128062306a36Sopenharmony_ci	qidx = skb_get_queue_mapping(skb);
128162306a36Sopenharmony_ci	qs = &pi->qs[qidx];
128262306a36Sopenharmony_ci	q = &qs->txq[TXQ_ETH];
128362306a36Sopenharmony_ci	txq = netdev_get_tx_queue(dev, qidx);
128462306a36Sopenharmony_ci
128562306a36Sopenharmony_ci	reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK);
128662306a36Sopenharmony_ci
128762306a36Sopenharmony_ci	credits = q->size - q->in_use;
128862306a36Sopenharmony_ci	ndesc = calc_tx_descs(skb);
128962306a36Sopenharmony_ci
129062306a36Sopenharmony_ci	if (unlikely(credits < ndesc)) {
129162306a36Sopenharmony_ci		t3_stop_tx_queue(txq, qs, q);
129262306a36Sopenharmony_ci		dev_err(&adap->pdev->dev,
129362306a36Sopenharmony_ci			"%s: Tx ring %u full while queue awake!\n",
129462306a36Sopenharmony_ci			dev->name, q->cntxt_id & 7);
129562306a36Sopenharmony_ci		return NETDEV_TX_BUSY;
129662306a36Sopenharmony_ci	}
129762306a36Sopenharmony_ci
129862306a36Sopenharmony_ci	/* Check if ethernet packet can't be sent as immediate data */
129962306a36Sopenharmony_ci	if (skb->len > (WR_LEN - sizeof(struct cpl_tx_pkt))) {
130062306a36Sopenharmony_ci		if (unlikely(map_skb(adap->pdev, skb, addr) < 0)) {
130162306a36Sopenharmony_ci			dev_kfree_skb(skb);
130262306a36Sopenharmony_ci			return NETDEV_TX_OK;
130362306a36Sopenharmony_ci		}
130462306a36Sopenharmony_ci	}
130562306a36Sopenharmony_ci
130662306a36Sopenharmony_ci	q->in_use += ndesc;
130762306a36Sopenharmony_ci	if (unlikely(credits - ndesc < q->stop_thres)) {
130862306a36Sopenharmony_ci		t3_stop_tx_queue(txq, qs, q);
130962306a36Sopenharmony_ci
131062306a36Sopenharmony_ci		if (should_restart_tx(q) &&
131162306a36Sopenharmony_ci		    test_and_clear_bit(TXQ_ETH, &qs->txq_stopped)) {
131262306a36Sopenharmony_ci			q->restarts++;
131362306a36Sopenharmony_ci			netif_tx_start_queue(txq);
131462306a36Sopenharmony_ci		}
131562306a36Sopenharmony_ci	}
131662306a36Sopenharmony_ci
131762306a36Sopenharmony_ci	gen = q->gen;
131862306a36Sopenharmony_ci	q->unacked += ndesc;
131962306a36Sopenharmony_ci	compl = (q->unacked & 8) << (S_WR_COMPL - 3);
132062306a36Sopenharmony_ci	q->unacked &= 7;
132162306a36Sopenharmony_ci	pidx = q->pidx;
132262306a36Sopenharmony_ci	q->pidx += ndesc;
132362306a36Sopenharmony_ci	if (q->pidx >= q->size) {
132462306a36Sopenharmony_ci		q->pidx -= q->size;
132562306a36Sopenharmony_ci		q->gen ^= 1;
132662306a36Sopenharmony_ci	}
132762306a36Sopenharmony_ci
132862306a36Sopenharmony_ci	/* update port statistics */
132962306a36Sopenharmony_ci	if (skb->ip_summed == CHECKSUM_PARTIAL)
133062306a36Sopenharmony_ci		qs->port_stats[SGE_PSTAT_TX_CSUM]++;
133162306a36Sopenharmony_ci	if (skb_shinfo(skb)->gso_size)
133262306a36Sopenharmony_ci		qs->port_stats[SGE_PSTAT_TSO]++;
133362306a36Sopenharmony_ci	if (skb_vlan_tag_present(skb))
133462306a36Sopenharmony_ci		qs->port_stats[SGE_PSTAT_VLANINS]++;
133562306a36Sopenharmony_ci
133662306a36Sopenharmony_ci	/*
133762306a36Sopenharmony_ci	 * We do not use Tx completion interrupts to free DMAd Tx packets.
133862306a36Sopenharmony_ci	 * This is good for performance but means that we rely on new Tx
133962306a36Sopenharmony_ci	 * packets arriving to run the destructors of completed packets,
134062306a36Sopenharmony_ci	 * which open up space in their sockets' send queues.  Sometimes
134162306a36Sopenharmony_ci	 * we do not get such new packets causing Tx to stall.  A single
134262306a36Sopenharmony_ci	 * UDP transmitter is a good example of this situation.  We have
134362306a36Sopenharmony_ci	 * a clean up timer that periodically reclaims completed packets
134462306a36Sopenharmony_ci	 * but it doesn't run often enough (nor do we want it to) to prevent
134562306a36Sopenharmony_ci	 * lengthy stalls.  A solution to this problem is to run the
134662306a36Sopenharmony_ci	 * destructor early, after the packet is queued but before it's DMAd.
134762306a36Sopenharmony_ci	 * A cons is that we lie to socket memory accounting, but the amount
134862306a36Sopenharmony_ci	 * of extra memory is reasonable (limited by the number of Tx
134962306a36Sopenharmony_ci	 * descriptors), the packets do actually get freed quickly by new
135062306a36Sopenharmony_ci	 * packets almost always, and for protocols like TCP that wait for
135162306a36Sopenharmony_ci	 * acks to really free up the data the extra memory is even less.
135262306a36Sopenharmony_ci	 * On the positive side we run the destructors on the sending CPU
135362306a36Sopenharmony_ci	 * rather than on a potentially different completing CPU, usually a
135462306a36Sopenharmony_ci	 * good thing.  We also run them without holding our Tx queue lock,
135562306a36Sopenharmony_ci	 * unlike what reclaim_completed_tx() would otherwise do.
135662306a36Sopenharmony_ci	 *
135762306a36Sopenharmony_ci	 * Run the destructor before telling the DMA engine about the packet
135862306a36Sopenharmony_ci	 * to make sure it doesn't complete and get freed prematurely.
135962306a36Sopenharmony_ci	 */
136062306a36Sopenharmony_ci	if (likely(!skb_shared(skb)))
136162306a36Sopenharmony_ci		skb_orphan(skb);
136262306a36Sopenharmony_ci
136362306a36Sopenharmony_ci	write_tx_pkt_wr(adap, skb, pi, pidx, gen, q, ndesc, compl, addr);
136462306a36Sopenharmony_ci	check_ring_tx_db(adap, q);
136562306a36Sopenharmony_ci	return NETDEV_TX_OK;
136662306a36Sopenharmony_ci}
136762306a36Sopenharmony_ci
136862306a36Sopenharmony_ci/**
136962306a36Sopenharmony_ci *	write_imm - write a packet into a Tx descriptor as immediate data
137062306a36Sopenharmony_ci *	@d: the Tx descriptor to write
137162306a36Sopenharmony_ci *	@skb: the packet
137262306a36Sopenharmony_ci *	@len: the length of packet data to write as immediate data
137362306a36Sopenharmony_ci *	@gen: the generation bit value to write
137462306a36Sopenharmony_ci *
137562306a36Sopenharmony_ci *	Writes a packet as immediate data into a Tx descriptor.  The packet
137662306a36Sopenharmony_ci *	contains a work request at its beginning.  We must write the packet
137762306a36Sopenharmony_ci *	carefully so the SGE doesn't read it accidentally before it's written
137862306a36Sopenharmony_ci *	in its entirety.
137962306a36Sopenharmony_ci */
138062306a36Sopenharmony_cistatic inline void write_imm(struct tx_desc *d, struct sk_buff *skb,
138162306a36Sopenharmony_ci			     unsigned int len, unsigned int gen)
138262306a36Sopenharmony_ci{
138362306a36Sopenharmony_ci	struct work_request_hdr *from = (struct work_request_hdr *)skb->data;
138462306a36Sopenharmony_ci	struct work_request_hdr *to = (struct work_request_hdr *)d;
138562306a36Sopenharmony_ci
138662306a36Sopenharmony_ci	if (likely(!skb->data_len))
138762306a36Sopenharmony_ci		memcpy(&to[1], &from[1], len - sizeof(*from));
138862306a36Sopenharmony_ci	else
138962306a36Sopenharmony_ci		skb_copy_bits(skb, sizeof(*from), &to[1], len - sizeof(*from));
139062306a36Sopenharmony_ci
139162306a36Sopenharmony_ci	to->wr_hi = from->wr_hi | htonl(F_WR_SOP | F_WR_EOP |
139262306a36Sopenharmony_ci					V_WR_BCNTLFLT(len & 7));
139362306a36Sopenharmony_ci	dma_wmb();
139462306a36Sopenharmony_ci	to->wr_lo = from->wr_lo | htonl(V_WR_GEN(gen) |
139562306a36Sopenharmony_ci					V_WR_LEN((len + 7) / 8));
139662306a36Sopenharmony_ci	wr_gen2(d, gen);
139762306a36Sopenharmony_ci	kfree_skb(skb);
139862306a36Sopenharmony_ci}
139962306a36Sopenharmony_ci
140062306a36Sopenharmony_ci/**
140162306a36Sopenharmony_ci *	check_desc_avail - check descriptor availability on a send queue
140262306a36Sopenharmony_ci *	@adap: the adapter
140362306a36Sopenharmony_ci *	@q: the send queue
140462306a36Sopenharmony_ci *	@skb: the packet needing the descriptors
140562306a36Sopenharmony_ci *	@ndesc: the number of Tx descriptors needed
140662306a36Sopenharmony_ci *	@qid: the Tx queue number in its queue set (TXQ_OFLD or TXQ_CTRL)
140762306a36Sopenharmony_ci *
140862306a36Sopenharmony_ci *	Checks if the requested number of Tx descriptors is available on an
140962306a36Sopenharmony_ci *	SGE send queue.  If the queue is already suspended or not enough
141062306a36Sopenharmony_ci *	descriptors are available the packet is queued for later transmission.
141162306a36Sopenharmony_ci *	Must be called with the Tx queue locked.
141262306a36Sopenharmony_ci *
141362306a36Sopenharmony_ci *	Returns 0 if enough descriptors are available, 1 if there aren't
141462306a36Sopenharmony_ci *	enough descriptors and the packet has been queued, and 2 if the caller
141562306a36Sopenharmony_ci *	needs to retry because there weren't enough descriptors at the
141662306a36Sopenharmony_ci *	beginning of the call but some freed up in the mean time.
141762306a36Sopenharmony_ci */
141862306a36Sopenharmony_cistatic inline int check_desc_avail(struct adapter *adap, struct sge_txq *q,
141962306a36Sopenharmony_ci				   struct sk_buff *skb, unsigned int ndesc,
142062306a36Sopenharmony_ci				   unsigned int qid)
142162306a36Sopenharmony_ci{
142262306a36Sopenharmony_ci	if (unlikely(!skb_queue_empty(&q->sendq))) {
142362306a36Sopenharmony_ci	      addq_exit:__skb_queue_tail(&q->sendq, skb);
142462306a36Sopenharmony_ci		return 1;
142562306a36Sopenharmony_ci	}
142662306a36Sopenharmony_ci	if (unlikely(q->size - q->in_use < ndesc)) {
142762306a36Sopenharmony_ci		struct sge_qset *qs = txq_to_qset(q, qid);
142862306a36Sopenharmony_ci
142962306a36Sopenharmony_ci		set_bit(qid, &qs->txq_stopped);
143062306a36Sopenharmony_ci		smp_mb__after_atomic();
143162306a36Sopenharmony_ci
143262306a36Sopenharmony_ci		if (should_restart_tx(q) &&
143362306a36Sopenharmony_ci		    test_and_clear_bit(qid, &qs->txq_stopped))
143462306a36Sopenharmony_ci			return 2;
143562306a36Sopenharmony_ci
143662306a36Sopenharmony_ci		q->stops++;
143762306a36Sopenharmony_ci		goto addq_exit;
143862306a36Sopenharmony_ci	}
143962306a36Sopenharmony_ci	return 0;
144062306a36Sopenharmony_ci}
144162306a36Sopenharmony_ci
144262306a36Sopenharmony_ci/**
144362306a36Sopenharmony_ci *	reclaim_completed_tx_imm - reclaim completed control-queue Tx descs
144462306a36Sopenharmony_ci *	@q: the SGE control Tx queue
144562306a36Sopenharmony_ci *
144662306a36Sopenharmony_ci *	This is a variant of reclaim_completed_tx() that is used for Tx queues
144762306a36Sopenharmony_ci *	that send only immediate data (presently just the control queues) and
144862306a36Sopenharmony_ci *	thus do not have any sk_buffs to release.
144962306a36Sopenharmony_ci */
145062306a36Sopenharmony_cistatic inline void reclaim_completed_tx_imm(struct sge_txq *q)
145162306a36Sopenharmony_ci{
145262306a36Sopenharmony_ci	unsigned int reclaim = q->processed - q->cleaned;
145362306a36Sopenharmony_ci
145462306a36Sopenharmony_ci	q->in_use -= reclaim;
145562306a36Sopenharmony_ci	q->cleaned += reclaim;
145662306a36Sopenharmony_ci}
145762306a36Sopenharmony_ci
145862306a36Sopenharmony_cistatic inline int immediate(const struct sk_buff *skb)
145962306a36Sopenharmony_ci{
146062306a36Sopenharmony_ci	return skb->len <= WR_LEN;
146162306a36Sopenharmony_ci}
146262306a36Sopenharmony_ci
146362306a36Sopenharmony_ci/**
146462306a36Sopenharmony_ci *	ctrl_xmit - send a packet through an SGE control Tx queue
146562306a36Sopenharmony_ci *	@adap: the adapter
146662306a36Sopenharmony_ci *	@q: the control queue
146762306a36Sopenharmony_ci *	@skb: the packet
146862306a36Sopenharmony_ci *
146962306a36Sopenharmony_ci *	Send a packet through an SGE control Tx queue.  Packets sent through
147062306a36Sopenharmony_ci *	a control queue must fit entirely as immediate data in a single Tx
147162306a36Sopenharmony_ci *	descriptor and have no page fragments.
147262306a36Sopenharmony_ci */
147362306a36Sopenharmony_cistatic int ctrl_xmit(struct adapter *adap, struct sge_txq *q,
147462306a36Sopenharmony_ci		     struct sk_buff *skb)
147562306a36Sopenharmony_ci{
147662306a36Sopenharmony_ci	int ret;
147762306a36Sopenharmony_ci	struct work_request_hdr *wrp = (struct work_request_hdr *)skb->data;
147862306a36Sopenharmony_ci
147962306a36Sopenharmony_ci	if (unlikely(!immediate(skb))) {
148062306a36Sopenharmony_ci		WARN_ON(1);
148162306a36Sopenharmony_ci		dev_kfree_skb(skb);
148262306a36Sopenharmony_ci		return NET_XMIT_SUCCESS;
148362306a36Sopenharmony_ci	}
148462306a36Sopenharmony_ci
148562306a36Sopenharmony_ci	wrp->wr_hi |= htonl(F_WR_SOP | F_WR_EOP);
148662306a36Sopenharmony_ci	wrp->wr_lo = htonl(V_WR_TID(q->token));
148762306a36Sopenharmony_ci
148862306a36Sopenharmony_ci	spin_lock(&q->lock);
148962306a36Sopenharmony_ci      again:reclaim_completed_tx_imm(q);
149062306a36Sopenharmony_ci
149162306a36Sopenharmony_ci	ret = check_desc_avail(adap, q, skb, 1, TXQ_CTRL);
149262306a36Sopenharmony_ci	if (unlikely(ret)) {
149362306a36Sopenharmony_ci		if (ret == 1) {
149462306a36Sopenharmony_ci			spin_unlock(&q->lock);
149562306a36Sopenharmony_ci			return NET_XMIT_CN;
149662306a36Sopenharmony_ci		}
149762306a36Sopenharmony_ci		goto again;
149862306a36Sopenharmony_ci	}
149962306a36Sopenharmony_ci
150062306a36Sopenharmony_ci	write_imm(&q->desc[q->pidx], skb, skb->len, q->gen);
150162306a36Sopenharmony_ci
150262306a36Sopenharmony_ci	q->in_use++;
150362306a36Sopenharmony_ci	if (++q->pidx >= q->size) {
150462306a36Sopenharmony_ci		q->pidx = 0;
150562306a36Sopenharmony_ci		q->gen ^= 1;
150662306a36Sopenharmony_ci	}
150762306a36Sopenharmony_ci	spin_unlock(&q->lock);
150862306a36Sopenharmony_ci	wmb();
150962306a36Sopenharmony_ci	t3_write_reg(adap, A_SG_KDOORBELL,
151062306a36Sopenharmony_ci		     F_SELEGRCNTX | V_EGRCNTX(q->cntxt_id));
151162306a36Sopenharmony_ci	return NET_XMIT_SUCCESS;
151262306a36Sopenharmony_ci}
151362306a36Sopenharmony_ci
151462306a36Sopenharmony_ci/**
151562306a36Sopenharmony_ci *	restart_ctrlq - restart a suspended control queue
151662306a36Sopenharmony_ci *	@w: pointer to the work associated with this handler
151762306a36Sopenharmony_ci *
151862306a36Sopenharmony_ci *	Resumes transmission on a suspended Tx control queue.
151962306a36Sopenharmony_ci */
152062306a36Sopenharmony_cistatic void restart_ctrlq(struct work_struct *w)
152162306a36Sopenharmony_ci{
152262306a36Sopenharmony_ci	struct sk_buff *skb;
152362306a36Sopenharmony_ci	struct sge_qset *qs = container_of(w, struct sge_qset,
152462306a36Sopenharmony_ci					   txq[TXQ_CTRL].qresume_task);
152562306a36Sopenharmony_ci	struct sge_txq *q = &qs->txq[TXQ_CTRL];
152662306a36Sopenharmony_ci
152762306a36Sopenharmony_ci	spin_lock(&q->lock);
152862306a36Sopenharmony_ci      again:reclaim_completed_tx_imm(q);
152962306a36Sopenharmony_ci
153062306a36Sopenharmony_ci	while (q->in_use < q->size &&
153162306a36Sopenharmony_ci	       (skb = __skb_dequeue(&q->sendq)) != NULL) {
153262306a36Sopenharmony_ci
153362306a36Sopenharmony_ci		write_imm(&q->desc[q->pidx], skb, skb->len, q->gen);
153462306a36Sopenharmony_ci
153562306a36Sopenharmony_ci		if (++q->pidx >= q->size) {
153662306a36Sopenharmony_ci			q->pidx = 0;
153762306a36Sopenharmony_ci			q->gen ^= 1;
153862306a36Sopenharmony_ci		}
153962306a36Sopenharmony_ci		q->in_use++;
154062306a36Sopenharmony_ci	}
154162306a36Sopenharmony_ci
154262306a36Sopenharmony_ci	if (!skb_queue_empty(&q->sendq)) {
154362306a36Sopenharmony_ci		set_bit(TXQ_CTRL, &qs->txq_stopped);
154462306a36Sopenharmony_ci		smp_mb__after_atomic();
154562306a36Sopenharmony_ci
154662306a36Sopenharmony_ci		if (should_restart_tx(q) &&
154762306a36Sopenharmony_ci		    test_and_clear_bit(TXQ_CTRL, &qs->txq_stopped))
154862306a36Sopenharmony_ci			goto again;
154962306a36Sopenharmony_ci		q->stops++;
155062306a36Sopenharmony_ci	}
155162306a36Sopenharmony_ci
155262306a36Sopenharmony_ci	spin_unlock(&q->lock);
155362306a36Sopenharmony_ci	wmb();
155462306a36Sopenharmony_ci	t3_write_reg(qs->adap, A_SG_KDOORBELL,
155562306a36Sopenharmony_ci		     F_SELEGRCNTX | V_EGRCNTX(q->cntxt_id));
155662306a36Sopenharmony_ci}
155762306a36Sopenharmony_ci
155862306a36Sopenharmony_ci/*
155962306a36Sopenharmony_ci * Send a management message through control queue 0
156062306a36Sopenharmony_ci */
156162306a36Sopenharmony_ciint t3_mgmt_tx(struct adapter *adap, struct sk_buff *skb)
156262306a36Sopenharmony_ci{
156362306a36Sopenharmony_ci	int ret;
156462306a36Sopenharmony_ci	local_bh_disable();
156562306a36Sopenharmony_ci	ret = ctrl_xmit(adap, &adap->sge.qs[0].txq[TXQ_CTRL], skb);
156662306a36Sopenharmony_ci	local_bh_enable();
156762306a36Sopenharmony_ci
156862306a36Sopenharmony_ci	return ret;
156962306a36Sopenharmony_ci}
157062306a36Sopenharmony_ci
157162306a36Sopenharmony_ci/**
157262306a36Sopenharmony_ci *	deferred_unmap_destructor - unmap a packet when it is freed
157362306a36Sopenharmony_ci *	@skb: the packet
157462306a36Sopenharmony_ci *
157562306a36Sopenharmony_ci *	This is the packet destructor used for Tx packets that need to remain
157662306a36Sopenharmony_ci *	mapped until they are freed rather than until their Tx descriptors are
157762306a36Sopenharmony_ci *	freed.
157862306a36Sopenharmony_ci */
157962306a36Sopenharmony_cistatic void deferred_unmap_destructor(struct sk_buff *skb)
158062306a36Sopenharmony_ci{
158162306a36Sopenharmony_ci	int i;
158262306a36Sopenharmony_ci	const dma_addr_t *p;
158362306a36Sopenharmony_ci	const struct skb_shared_info *si;
158462306a36Sopenharmony_ci	const struct deferred_unmap_info *dui;
158562306a36Sopenharmony_ci
158662306a36Sopenharmony_ci	dui = (struct deferred_unmap_info *)skb->head;
158762306a36Sopenharmony_ci	p = dui->addr;
158862306a36Sopenharmony_ci
158962306a36Sopenharmony_ci	if (skb_tail_pointer(skb) - skb_transport_header(skb))
159062306a36Sopenharmony_ci		dma_unmap_single(&dui->pdev->dev, *p++,
159162306a36Sopenharmony_ci				 skb_tail_pointer(skb) - skb_transport_header(skb),
159262306a36Sopenharmony_ci				 DMA_TO_DEVICE);
159362306a36Sopenharmony_ci
159462306a36Sopenharmony_ci	si = skb_shinfo(skb);
159562306a36Sopenharmony_ci	for (i = 0; i < si->nr_frags; i++)
159662306a36Sopenharmony_ci		dma_unmap_page(&dui->pdev->dev, *p++,
159762306a36Sopenharmony_ci			       skb_frag_size(&si->frags[i]), DMA_TO_DEVICE);
159862306a36Sopenharmony_ci}
159962306a36Sopenharmony_ci
160062306a36Sopenharmony_cistatic void setup_deferred_unmapping(struct sk_buff *skb, struct pci_dev *pdev,
160162306a36Sopenharmony_ci				     const struct sg_ent *sgl, int sgl_flits)
160262306a36Sopenharmony_ci{
160362306a36Sopenharmony_ci	dma_addr_t *p;
160462306a36Sopenharmony_ci	struct deferred_unmap_info *dui;
160562306a36Sopenharmony_ci
160662306a36Sopenharmony_ci	dui = (struct deferred_unmap_info *)skb->head;
160762306a36Sopenharmony_ci	dui->pdev = pdev;
160862306a36Sopenharmony_ci	for (p = dui->addr; sgl_flits >= 3; sgl++, sgl_flits -= 3) {
160962306a36Sopenharmony_ci		*p++ = be64_to_cpu(sgl->addr[0]);
161062306a36Sopenharmony_ci		*p++ = be64_to_cpu(sgl->addr[1]);
161162306a36Sopenharmony_ci	}
161262306a36Sopenharmony_ci	if (sgl_flits)
161362306a36Sopenharmony_ci		*p = be64_to_cpu(sgl->addr[0]);
161462306a36Sopenharmony_ci}
161562306a36Sopenharmony_ci
161662306a36Sopenharmony_ci/**
161762306a36Sopenharmony_ci *	write_ofld_wr - write an offload work request
161862306a36Sopenharmony_ci *	@adap: the adapter
161962306a36Sopenharmony_ci *	@skb: the packet to send
162062306a36Sopenharmony_ci *	@q: the Tx queue
162162306a36Sopenharmony_ci *	@pidx: index of the first Tx descriptor to write
162262306a36Sopenharmony_ci *	@gen: the generation value to use
162362306a36Sopenharmony_ci *	@ndesc: number of descriptors the packet will occupy
162462306a36Sopenharmony_ci *	@addr: the address
162562306a36Sopenharmony_ci *
162662306a36Sopenharmony_ci *	Write an offload work request to send the supplied packet.  The packet
162762306a36Sopenharmony_ci *	data already carry the work request with most fields populated.
162862306a36Sopenharmony_ci */
162962306a36Sopenharmony_cistatic void write_ofld_wr(struct adapter *adap, struct sk_buff *skb,
163062306a36Sopenharmony_ci			  struct sge_txq *q, unsigned int pidx,
163162306a36Sopenharmony_ci			  unsigned int gen, unsigned int ndesc,
163262306a36Sopenharmony_ci			  const dma_addr_t *addr)
163362306a36Sopenharmony_ci{
163462306a36Sopenharmony_ci	unsigned int sgl_flits, flits;
163562306a36Sopenharmony_ci	struct work_request_hdr *from;
163662306a36Sopenharmony_ci	struct sg_ent *sgp, sgl[MAX_SKB_FRAGS / 2 + 1];
163762306a36Sopenharmony_ci	struct tx_desc *d = &q->desc[pidx];
163862306a36Sopenharmony_ci
163962306a36Sopenharmony_ci	if (immediate(skb)) {
164062306a36Sopenharmony_ci		q->sdesc[pidx].skb = NULL;
164162306a36Sopenharmony_ci		write_imm(d, skb, skb->len, gen);
164262306a36Sopenharmony_ci		return;
164362306a36Sopenharmony_ci	}
164462306a36Sopenharmony_ci
164562306a36Sopenharmony_ci	/* Only TX_DATA builds SGLs */
164662306a36Sopenharmony_ci
164762306a36Sopenharmony_ci	from = (struct work_request_hdr *)skb->data;
164862306a36Sopenharmony_ci	memcpy(&d->flit[1], &from[1],
164962306a36Sopenharmony_ci	       skb_transport_offset(skb) - sizeof(*from));
165062306a36Sopenharmony_ci
165162306a36Sopenharmony_ci	flits = skb_transport_offset(skb) / 8;
165262306a36Sopenharmony_ci	sgp = ndesc == 1 ? (struct sg_ent *)&d->flit[flits] : sgl;
165362306a36Sopenharmony_ci	sgl_flits = write_sgl(skb, sgp, skb_transport_header(skb),
165462306a36Sopenharmony_ci			      skb_tail_pointer(skb) - skb_transport_header(skb),
165562306a36Sopenharmony_ci			      addr);
165662306a36Sopenharmony_ci	if (need_skb_unmap()) {
165762306a36Sopenharmony_ci		setup_deferred_unmapping(skb, adap->pdev, sgp, sgl_flits);
165862306a36Sopenharmony_ci		skb->destructor = deferred_unmap_destructor;
165962306a36Sopenharmony_ci	}
166062306a36Sopenharmony_ci
166162306a36Sopenharmony_ci	write_wr_hdr_sgl(ndesc, skb, d, pidx, q, sgl, flits, sgl_flits,
166262306a36Sopenharmony_ci			 gen, from->wr_hi, from->wr_lo);
166362306a36Sopenharmony_ci}
166462306a36Sopenharmony_ci
166562306a36Sopenharmony_ci/**
166662306a36Sopenharmony_ci *	calc_tx_descs_ofld - calculate # of Tx descriptors for an offload packet
166762306a36Sopenharmony_ci *	@skb: the packet
166862306a36Sopenharmony_ci *
166962306a36Sopenharmony_ci * 	Returns the number of Tx descriptors needed for the given offload
167062306a36Sopenharmony_ci * 	packet.  These packets are already fully constructed.
167162306a36Sopenharmony_ci */
167262306a36Sopenharmony_cistatic inline unsigned int calc_tx_descs_ofld(const struct sk_buff *skb)
167362306a36Sopenharmony_ci{
167462306a36Sopenharmony_ci	unsigned int flits, cnt;
167562306a36Sopenharmony_ci
167662306a36Sopenharmony_ci	if (skb->len <= WR_LEN)
167762306a36Sopenharmony_ci		return 1;	/* packet fits as immediate data */
167862306a36Sopenharmony_ci
167962306a36Sopenharmony_ci	flits = skb_transport_offset(skb) / 8;	/* headers */
168062306a36Sopenharmony_ci	cnt = skb_shinfo(skb)->nr_frags;
168162306a36Sopenharmony_ci	if (skb_tail_pointer(skb) != skb_transport_header(skb))
168262306a36Sopenharmony_ci		cnt++;
168362306a36Sopenharmony_ci	return flits_to_desc(flits + sgl_len(cnt));
168462306a36Sopenharmony_ci}
168562306a36Sopenharmony_ci
168662306a36Sopenharmony_ci/**
168762306a36Sopenharmony_ci *	ofld_xmit - send a packet through an offload queue
168862306a36Sopenharmony_ci *	@adap: the adapter
168962306a36Sopenharmony_ci *	@q: the Tx offload queue
169062306a36Sopenharmony_ci *	@skb: the packet
169162306a36Sopenharmony_ci *
169262306a36Sopenharmony_ci *	Send an offload packet through an SGE offload queue.
169362306a36Sopenharmony_ci */
169462306a36Sopenharmony_cistatic int ofld_xmit(struct adapter *adap, struct sge_txq *q,
169562306a36Sopenharmony_ci		     struct sk_buff *skb)
169662306a36Sopenharmony_ci{
169762306a36Sopenharmony_ci	int ret;
169862306a36Sopenharmony_ci	unsigned int ndesc = calc_tx_descs_ofld(skb), pidx, gen;
169962306a36Sopenharmony_ci
170062306a36Sopenharmony_ci	spin_lock(&q->lock);
170162306a36Sopenharmony_ciagain:	reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK);
170262306a36Sopenharmony_ci
170362306a36Sopenharmony_ci	ret = check_desc_avail(adap, q, skb, ndesc, TXQ_OFLD);
170462306a36Sopenharmony_ci	if (unlikely(ret)) {
170562306a36Sopenharmony_ci		if (ret == 1) {
170662306a36Sopenharmony_ci			skb->priority = ndesc;	/* save for restart */
170762306a36Sopenharmony_ci			spin_unlock(&q->lock);
170862306a36Sopenharmony_ci			return NET_XMIT_CN;
170962306a36Sopenharmony_ci		}
171062306a36Sopenharmony_ci		goto again;
171162306a36Sopenharmony_ci	}
171262306a36Sopenharmony_ci
171362306a36Sopenharmony_ci	if (!immediate(skb) &&
171462306a36Sopenharmony_ci	    map_skb(adap->pdev, skb, (dma_addr_t *)skb->head)) {
171562306a36Sopenharmony_ci		spin_unlock(&q->lock);
171662306a36Sopenharmony_ci		return NET_XMIT_SUCCESS;
171762306a36Sopenharmony_ci	}
171862306a36Sopenharmony_ci
171962306a36Sopenharmony_ci	gen = q->gen;
172062306a36Sopenharmony_ci	q->in_use += ndesc;
172162306a36Sopenharmony_ci	pidx = q->pidx;
172262306a36Sopenharmony_ci	q->pidx += ndesc;
172362306a36Sopenharmony_ci	if (q->pidx >= q->size) {
172462306a36Sopenharmony_ci		q->pidx -= q->size;
172562306a36Sopenharmony_ci		q->gen ^= 1;
172662306a36Sopenharmony_ci	}
172762306a36Sopenharmony_ci	spin_unlock(&q->lock);
172862306a36Sopenharmony_ci
172962306a36Sopenharmony_ci	write_ofld_wr(adap, skb, q, pidx, gen, ndesc, (dma_addr_t *)skb->head);
173062306a36Sopenharmony_ci	check_ring_tx_db(adap, q);
173162306a36Sopenharmony_ci	return NET_XMIT_SUCCESS;
173262306a36Sopenharmony_ci}
173362306a36Sopenharmony_ci
173462306a36Sopenharmony_ci/**
173562306a36Sopenharmony_ci *	restart_offloadq - restart a suspended offload queue
173662306a36Sopenharmony_ci *	@w: pointer to the work associated with this handler
173762306a36Sopenharmony_ci *
173862306a36Sopenharmony_ci *	Resumes transmission on a suspended Tx offload queue.
173962306a36Sopenharmony_ci */
174062306a36Sopenharmony_cistatic void restart_offloadq(struct work_struct *w)
174162306a36Sopenharmony_ci{
174262306a36Sopenharmony_ci	struct sk_buff *skb;
174362306a36Sopenharmony_ci	struct sge_qset *qs = container_of(w, struct sge_qset,
174462306a36Sopenharmony_ci					   txq[TXQ_OFLD].qresume_task);
174562306a36Sopenharmony_ci	struct sge_txq *q = &qs->txq[TXQ_OFLD];
174662306a36Sopenharmony_ci	const struct port_info *pi = netdev_priv(qs->netdev);
174762306a36Sopenharmony_ci	struct adapter *adap = pi->adapter;
174862306a36Sopenharmony_ci	unsigned int written = 0;
174962306a36Sopenharmony_ci
175062306a36Sopenharmony_ci	spin_lock(&q->lock);
175162306a36Sopenharmony_ciagain:	reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK);
175262306a36Sopenharmony_ci
175362306a36Sopenharmony_ci	while ((skb = skb_peek(&q->sendq)) != NULL) {
175462306a36Sopenharmony_ci		unsigned int gen, pidx;
175562306a36Sopenharmony_ci		unsigned int ndesc = skb->priority;
175662306a36Sopenharmony_ci
175762306a36Sopenharmony_ci		if (unlikely(q->size - q->in_use < ndesc)) {
175862306a36Sopenharmony_ci			set_bit(TXQ_OFLD, &qs->txq_stopped);
175962306a36Sopenharmony_ci			smp_mb__after_atomic();
176062306a36Sopenharmony_ci
176162306a36Sopenharmony_ci			if (should_restart_tx(q) &&
176262306a36Sopenharmony_ci			    test_and_clear_bit(TXQ_OFLD, &qs->txq_stopped))
176362306a36Sopenharmony_ci				goto again;
176462306a36Sopenharmony_ci			q->stops++;
176562306a36Sopenharmony_ci			break;
176662306a36Sopenharmony_ci		}
176762306a36Sopenharmony_ci
176862306a36Sopenharmony_ci		if (!immediate(skb) &&
176962306a36Sopenharmony_ci		    map_skb(adap->pdev, skb, (dma_addr_t *)skb->head))
177062306a36Sopenharmony_ci			break;
177162306a36Sopenharmony_ci
177262306a36Sopenharmony_ci		gen = q->gen;
177362306a36Sopenharmony_ci		q->in_use += ndesc;
177462306a36Sopenharmony_ci		pidx = q->pidx;
177562306a36Sopenharmony_ci		q->pidx += ndesc;
177662306a36Sopenharmony_ci		written += ndesc;
177762306a36Sopenharmony_ci		if (q->pidx >= q->size) {
177862306a36Sopenharmony_ci			q->pidx -= q->size;
177962306a36Sopenharmony_ci			q->gen ^= 1;
178062306a36Sopenharmony_ci		}
178162306a36Sopenharmony_ci		__skb_unlink(skb, &q->sendq);
178262306a36Sopenharmony_ci		spin_unlock(&q->lock);
178362306a36Sopenharmony_ci
178462306a36Sopenharmony_ci		write_ofld_wr(adap, skb, q, pidx, gen, ndesc,
178562306a36Sopenharmony_ci			      (dma_addr_t *)skb->head);
178662306a36Sopenharmony_ci		spin_lock(&q->lock);
178762306a36Sopenharmony_ci	}
178862306a36Sopenharmony_ci	spin_unlock(&q->lock);
178962306a36Sopenharmony_ci
179062306a36Sopenharmony_ci#if USE_GTS
179162306a36Sopenharmony_ci	set_bit(TXQ_RUNNING, &q->flags);
179262306a36Sopenharmony_ci	set_bit(TXQ_LAST_PKT_DB, &q->flags);
179362306a36Sopenharmony_ci#endif
179462306a36Sopenharmony_ci	wmb();
179562306a36Sopenharmony_ci	if (likely(written))
179662306a36Sopenharmony_ci		t3_write_reg(adap, A_SG_KDOORBELL,
179762306a36Sopenharmony_ci			     F_SELEGRCNTX | V_EGRCNTX(q->cntxt_id));
179862306a36Sopenharmony_ci}
179962306a36Sopenharmony_ci
180062306a36Sopenharmony_ci/**
180162306a36Sopenharmony_ci *	queue_set - return the queue set a packet should use
180262306a36Sopenharmony_ci *	@skb: the packet
180362306a36Sopenharmony_ci *
180462306a36Sopenharmony_ci *	Maps a packet to the SGE queue set it should use.  The desired queue
180562306a36Sopenharmony_ci *	set is carried in bits 1-3 in the packet's priority.
180662306a36Sopenharmony_ci */
180762306a36Sopenharmony_cistatic inline int queue_set(const struct sk_buff *skb)
180862306a36Sopenharmony_ci{
180962306a36Sopenharmony_ci	return skb->priority >> 1;
181062306a36Sopenharmony_ci}
181162306a36Sopenharmony_ci
181262306a36Sopenharmony_ci/**
181362306a36Sopenharmony_ci *	is_ctrl_pkt - return whether an offload packet is a control packet
181462306a36Sopenharmony_ci *	@skb: the packet
181562306a36Sopenharmony_ci *
181662306a36Sopenharmony_ci *	Determines whether an offload packet should use an OFLD or a CTRL
181762306a36Sopenharmony_ci *	Tx queue.  This is indicated by bit 0 in the packet's priority.
181862306a36Sopenharmony_ci */
181962306a36Sopenharmony_cistatic inline int is_ctrl_pkt(const struct sk_buff *skb)
182062306a36Sopenharmony_ci{
182162306a36Sopenharmony_ci	return skb->priority & 1;
182262306a36Sopenharmony_ci}
182362306a36Sopenharmony_ci
182462306a36Sopenharmony_ci/**
182562306a36Sopenharmony_ci *	t3_offload_tx - send an offload packet
182662306a36Sopenharmony_ci *	@tdev: the offload device to send to
182762306a36Sopenharmony_ci *	@skb: the packet
182862306a36Sopenharmony_ci *
182962306a36Sopenharmony_ci *	Sends an offload packet.  We use the packet priority to select the
183062306a36Sopenharmony_ci *	appropriate Tx queue as follows: bit 0 indicates whether the packet
183162306a36Sopenharmony_ci *	should be sent as regular or control, bits 1-3 select the queue set.
183262306a36Sopenharmony_ci */
183362306a36Sopenharmony_ciint t3_offload_tx(struct t3cdev *tdev, struct sk_buff *skb)
183462306a36Sopenharmony_ci{
183562306a36Sopenharmony_ci	struct adapter *adap = tdev2adap(tdev);
183662306a36Sopenharmony_ci	struct sge_qset *qs = &adap->sge.qs[queue_set(skb)];
183762306a36Sopenharmony_ci
183862306a36Sopenharmony_ci	if (unlikely(is_ctrl_pkt(skb)))
183962306a36Sopenharmony_ci		return ctrl_xmit(adap, &qs->txq[TXQ_CTRL], skb);
184062306a36Sopenharmony_ci
184162306a36Sopenharmony_ci	return ofld_xmit(adap, &qs->txq[TXQ_OFLD], skb);
184262306a36Sopenharmony_ci}
184362306a36Sopenharmony_ci
184462306a36Sopenharmony_ci/**
184562306a36Sopenharmony_ci *	offload_enqueue - add an offload packet to an SGE offload receive queue
184662306a36Sopenharmony_ci *	@q: the SGE response queue
184762306a36Sopenharmony_ci *	@skb: the packet
184862306a36Sopenharmony_ci *
184962306a36Sopenharmony_ci *	Add a new offload packet to an SGE response queue's offload packet
185062306a36Sopenharmony_ci *	queue.  If the packet is the first on the queue it schedules the RX
185162306a36Sopenharmony_ci *	softirq to process the queue.
185262306a36Sopenharmony_ci */
185362306a36Sopenharmony_cistatic inline void offload_enqueue(struct sge_rspq *q, struct sk_buff *skb)
185462306a36Sopenharmony_ci{
185562306a36Sopenharmony_ci	int was_empty = skb_queue_empty(&q->rx_queue);
185662306a36Sopenharmony_ci
185762306a36Sopenharmony_ci	__skb_queue_tail(&q->rx_queue, skb);
185862306a36Sopenharmony_ci
185962306a36Sopenharmony_ci	if (was_empty) {
186062306a36Sopenharmony_ci		struct sge_qset *qs = rspq_to_qset(q);
186162306a36Sopenharmony_ci
186262306a36Sopenharmony_ci		napi_schedule(&qs->napi);
186362306a36Sopenharmony_ci	}
186462306a36Sopenharmony_ci}
186562306a36Sopenharmony_ci
186662306a36Sopenharmony_ci/**
186762306a36Sopenharmony_ci *	deliver_partial_bundle - deliver a (partial) bundle of Rx offload pkts
186862306a36Sopenharmony_ci *	@tdev: the offload device that will be receiving the packets
186962306a36Sopenharmony_ci *	@q: the SGE response queue that assembled the bundle
187062306a36Sopenharmony_ci *	@skbs: the partial bundle
187162306a36Sopenharmony_ci *	@n: the number of packets in the bundle
187262306a36Sopenharmony_ci *
187362306a36Sopenharmony_ci *	Delivers a (partial) bundle of Rx offload packets to an offload device.
187462306a36Sopenharmony_ci */
187562306a36Sopenharmony_cistatic inline void deliver_partial_bundle(struct t3cdev *tdev,
187662306a36Sopenharmony_ci					  struct sge_rspq *q,
187762306a36Sopenharmony_ci					  struct sk_buff *skbs[], int n)
187862306a36Sopenharmony_ci{
187962306a36Sopenharmony_ci	if (n) {
188062306a36Sopenharmony_ci		q->offload_bundles++;
188162306a36Sopenharmony_ci		tdev->recv(tdev, skbs, n);
188262306a36Sopenharmony_ci	}
188362306a36Sopenharmony_ci}
188462306a36Sopenharmony_ci
188562306a36Sopenharmony_ci/**
188662306a36Sopenharmony_ci *	ofld_poll - NAPI handler for offload packets in interrupt mode
188762306a36Sopenharmony_ci *	@napi: the network device doing the polling
188862306a36Sopenharmony_ci *	@budget: polling budget
188962306a36Sopenharmony_ci *
189062306a36Sopenharmony_ci *	The NAPI handler for offload packets when a response queue is serviced
189162306a36Sopenharmony_ci *	by the hard interrupt handler, i.e., when it's operating in non-polling
189262306a36Sopenharmony_ci *	mode.  Creates small packet batches and sends them through the offload
189362306a36Sopenharmony_ci *	receive handler.  Batches need to be of modest size as we do prefetches
189462306a36Sopenharmony_ci *	on the packets in each.
189562306a36Sopenharmony_ci */
189662306a36Sopenharmony_cistatic int ofld_poll(struct napi_struct *napi, int budget)
189762306a36Sopenharmony_ci{
189862306a36Sopenharmony_ci	struct sge_qset *qs = container_of(napi, struct sge_qset, napi);
189962306a36Sopenharmony_ci	struct sge_rspq *q = &qs->rspq;
190062306a36Sopenharmony_ci	struct adapter *adapter = qs->adap;
190162306a36Sopenharmony_ci	int work_done = 0;
190262306a36Sopenharmony_ci
190362306a36Sopenharmony_ci	while (work_done < budget) {
190462306a36Sopenharmony_ci		struct sk_buff *skb, *tmp, *skbs[RX_BUNDLE_SIZE];
190562306a36Sopenharmony_ci		struct sk_buff_head queue;
190662306a36Sopenharmony_ci		int ngathered;
190762306a36Sopenharmony_ci
190862306a36Sopenharmony_ci		spin_lock_irq(&q->lock);
190962306a36Sopenharmony_ci		__skb_queue_head_init(&queue);
191062306a36Sopenharmony_ci		skb_queue_splice_init(&q->rx_queue, &queue);
191162306a36Sopenharmony_ci		if (skb_queue_empty(&queue)) {
191262306a36Sopenharmony_ci			napi_complete_done(napi, work_done);
191362306a36Sopenharmony_ci			spin_unlock_irq(&q->lock);
191462306a36Sopenharmony_ci			return work_done;
191562306a36Sopenharmony_ci		}
191662306a36Sopenharmony_ci		spin_unlock_irq(&q->lock);
191762306a36Sopenharmony_ci
191862306a36Sopenharmony_ci		ngathered = 0;
191962306a36Sopenharmony_ci		skb_queue_walk_safe(&queue, skb, tmp) {
192062306a36Sopenharmony_ci			if (work_done >= budget)
192162306a36Sopenharmony_ci				break;
192262306a36Sopenharmony_ci			work_done++;
192362306a36Sopenharmony_ci
192462306a36Sopenharmony_ci			__skb_unlink(skb, &queue);
192562306a36Sopenharmony_ci			prefetch(skb->data);
192662306a36Sopenharmony_ci			skbs[ngathered] = skb;
192762306a36Sopenharmony_ci			if (++ngathered == RX_BUNDLE_SIZE) {
192862306a36Sopenharmony_ci				q->offload_bundles++;
192962306a36Sopenharmony_ci				adapter->tdev.recv(&adapter->tdev, skbs,
193062306a36Sopenharmony_ci						   ngathered);
193162306a36Sopenharmony_ci				ngathered = 0;
193262306a36Sopenharmony_ci			}
193362306a36Sopenharmony_ci		}
193462306a36Sopenharmony_ci		if (!skb_queue_empty(&queue)) {
193562306a36Sopenharmony_ci			/* splice remaining packets back onto Rx queue */
193662306a36Sopenharmony_ci			spin_lock_irq(&q->lock);
193762306a36Sopenharmony_ci			skb_queue_splice(&queue, &q->rx_queue);
193862306a36Sopenharmony_ci			spin_unlock_irq(&q->lock);
193962306a36Sopenharmony_ci		}
194062306a36Sopenharmony_ci		deliver_partial_bundle(&adapter->tdev, q, skbs, ngathered);
194162306a36Sopenharmony_ci	}
194262306a36Sopenharmony_ci
194362306a36Sopenharmony_ci	return work_done;
194462306a36Sopenharmony_ci}
194562306a36Sopenharmony_ci
194662306a36Sopenharmony_ci/**
194762306a36Sopenharmony_ci *	rx_offload - process a received offload packet
194862306a36Sopenharmony_ci *	@tdev: the offload device receiving the packet
194962306a36Sopenharmony_ci *	@rq: the response queue that received the packet
195062306a36Sopenharmony_ci *	@skb: the packet
195162306a36Sopenharmony_ci *	@rx_gather: a gather list of packets if we are building a bundle
195262306a36Sopenharmony_ci *	@gather_idx: index of the next available slot in the bundle
195362306a36Sopenharmony_ci *
195462306a36Sopenharmony_ci *	Process an ingress offload packet and add it to the offload ingress
195562306a36Sopenharmony_ci *	queue. 	Returns the index of the next available slot in the bundle.
195662306a36Sopenharmony_ci */
195762306a36Sopenharmony_cistatic inline int rx_offload(struct t3cdev *tdev, struct sge_rspq *rq,
195862306a36Sopenharmony_ci			     struct sk_buff *skb, struct sk_buff *rx_gather[],
195962306a36Sopenharmony_ci			     unsigned int gather_idx)
196062306a36Sopenharmony_ci{
196162306a36Sopenharmony_ci	skb_reset_mac_header(skb);
196262306a36Sopenharmony_ci	skb_reset_network_header(skb);
196362306a36Sopenharmony_ci	skb_reset_transport_header(skb);
196462306a36Sopenharmony_ci
196562306a36Sopenharmony_ci	if (rq->polling) {
196662306a36Sopenharmony_ci		rx_gather[gather_idx++] = skb;
196762306a36Sopenharmony_ci		if (gather_idx == RX_BUNDLE_SIZE) {
196862306a36Sopenharmony_ci			tdev->recv(tdev, rx_gather, RX_BUNDLE_SIZE);
196962306a36Sopenharmony_ci			gather_idx = 0;
197062306a36Sopenharmony_ci			rq->offload_bundles++;
197162306a36Sopenharmony_ci		}
197262306a36Sopenharmony_ci	} else
197362306a36Sopenharmony_ci		offload_enqueue(rq, skb);
197462306a36Sopenharmony_ci
197562306a36Sopenharmony_ci	return gather_idx;
197662306a36Sopenharmony_ci}
197762306a36Sopenharmony_ci
197862306a36Sopenharmony_ci/**
197962306a36Sopenharmony_ci *	restart_tx - check whether to restart suspended Tx queues
198062306a36Sopenharmony_ci *	@qs: the queue set to resume
198162306a36Sopenharmony_ci *
198262306a36Sopenharmony_ci *	Restarts suspended Tx queues of an SGE queue set if they have enough
198362306a36Sopenharmony_ci *	free resources to resume operation.
198462306a36Sopenharmony_ci */
198562306a36Sopenharmony_cistatic void restart_tx(struct sge_qset *qs)
198662306a36Sopenharmony_ci{
198762306a36Sopenharmony_ci	if (test_bit(TXQ_ETH, &qs->txq_stopped) &&
198862306a36Sopenharmony_ci	    should_restart_tx(&qs->txq[TXQ_ETH]) &&
198962306a36Sopenharmony_ci	    test_and_clear_bit(TXQ_ETH, &qs->txq_stopped)) {
199062306a36Sopenharmony_ci		qs->txq[TXQ_ETH].restarts++;
199162306a36Sopenharmony_ci		if (netif_running(qs->netdev))
199262306a36Sopenharmony_ci			netif_tx_wake_queue(qs->tx_q);
199362306a36Sopenharmony_ci	}
199462306a36Sopenharmony_ci
199562306a36Sopenharmony_ci	if (test_bit(TXQ_OFLD, &qs->txq_stopped) &&
199662306a36Sopenharmony_ci	    should_restart_tx(&qs->txq[TXQ_OFLD]) &&
199762306a36Sopenharmony_ci	    test_and_clear_bit(TXQ_OFLD, &qs->txq_stopped)) {
199862306a36Sopenharmony_ci		qs->txq[TXQ_OFLD].restarts++;
199962306a36Sopenharmony_ci
200062306a36Sopenharmony_ci		/* The work can be quite lengthy so we use driver's own queue */
200162306a36Sopenharmony_ci		queue_work(cxgb3_wq, &qs->txq[TXQ_OFLD].qresume_task);
200262306a36Sopenharmony_ci	}
200362306a36Sopenharmony_ci	if (test_bit(TXQ_CTRL, &qs->txq_stopped) &&
200462306a36Sopenharmony_ci	    should_restart_tx(&qs->txq[TXQ_CTRL]) &&
200562306a36Sopenharmony_ci	    test_and_clear_bit(TXQ_CTRL, &qs->txq_stopped)) {
200662306a36Sopenharmony_ci		qs->txq[TXQ_CTRL].restarts++;
200762306a36Sopenharmony_ci
200862306a36Sopenharmony_ci		/* The work can be quite lengthy so we use driver's own queue */
200962306a36Sopenharmony_ci		queue_work(cxgb3_wq, &qs->txq[TXQ_CTRL].qresume_task);
201062306a36Sopenharmony_ci	}
201162306a36Sopenharmony_ci}
201262306a36Sopenharmony_ci
201362306a36Sopenharmony_ci/**
201462306a36Sopenharmony_ci *	cxgb3_arp_process - process an ARP request probing a private IP address
201562306a36Sopenharmony_ci *	@pi: the port info
201662306a36Sopenharmony_ci *	@skb: the skbuff containing the ARP request
201762306a36Sopenharmony_ci *
201862306a36Sopenharmony_ci *	Check if the ARP request is probing the private IP address
201962306a36Sopenharmony_ci *	dedicated to iSCSI, generate an ARP reply if so.
202062306a36Sopenharmony_ci */
202162306a36Sopenharmony_cistatic void cxgb3_arp_process(struct port_info *pi, struct sk_buff *skb)
202262306a36Sopenharmony_ci{
202362306a36Sopenharmony_ci	struct net_device *dev = skb->dev;
202462306a36Sopenharmony_ci	struct arphdr *arp;
202562306a36Sopenharmony_ci	unsigned char *arp_ptr;
202662306a36Sopenharmony_ci	unsigned char *sha;
202762306a36Sopenharmony_ci	__be32 sip, tip;
202862306a36Sopenharmony_ci
202962306a36Sopenharmony_ci	if (!dev)
203062306a36Sopenharmony_ci		return;
203162306a36Sopenharmony_ci
203262306a36Sopenharmony_ci	skb_reset_network_header(skb);
203362306a36Sopenharmony_ci	arp = arp_hdr(skb);
203462306a36Sopenharmony_ci
203562306a36Sopenharmony_ci	if (arp->ar_op != htons(ARPOP_REQUEST))
203662306a36Sopenharmony_ci		return;
203762306a36Sopenharmony_ci
203862306a36Sopenharmony_ci	arp_ptr = (unsigned char *)(arp + 1);
203962306a36Sopenharmony_ci	sha = arp_ptr;
204062306a36Sopenharmony_ci	arp_ptr += dev->addr_len;
204162306a36Sopenharmony_ci	memcpy(&sip, arp_ptr, sizeof(sip));
204262306a36Sopenharmony_ci	arp_ptr += sizeof(sip);
204362306a36Sopenharmony_ci	arp_ptr += dev->addr_len;
204462306a36Sopenharmony_ci	memcpy(&tip, arp_ptr, sizeof(tip));
204562306a36Sopenharmony_ci
204662306a36Sopenharmony_ci	if (tip != pi->iscsi_ipv4addr)
204762306a36Sopenharmony_ci		return;
204862306a36Sopenharmony_ci
204962306a36Sopenharmony_ci	arp_send(ARPOP_REPLY, ETH_P_ARP, sip, dev, tip, sha,
205062306a36Sopenharmony_ci		 pi->iscsic.mac_addr, sha);
205162306a36Sopenharmony_ci
205262306a36Sopenharmony_ci}
205362306a36Sopenharmony_ci
205462306a36Sopenharmony_cistatic inline int is_arp(struct sk_buff *skb)
205562306a36Sopenharmony_ci{
205662306a36Sopenharmony_ci	return skb->protocol == htons(ETH_P_ARP);
205762306a36Sopenharmony_ci}
205862306a36Sopenharmony_ci
205962306a36Sopenharmony_cistatic void cxgb3_process_iscsi_prov_pack(struct port_info *pi,
206062306a36Sopenharmony_ci					struct sk_buff *skb)
206162306a36Sopenharmony_ci{
206262306a36Sopenharmony_ci	if (is_arp(skb)) {
206362306a36Sopenharmony_ci		cxgb3_arp_process(pi, skb);
206462306a36Sopenharmony_ci		return;
206562306a36Sopenharmony_ci	}
206662306a36Sopenharmony_ci
206762306a36Sopenharmony_ci	if (pi->iscsic.recv)
206862306a36Sopenharmony_ci		pi->iscsic.recv(pi, skb);
206962306a36Sopenharmony_ci
207062306a36Sopenharmony_ci}
207162306a36Sopenharmony_ci
207262306a36Sopenharmony_ci/**
207362306a36Sopenharmony_ci *	rx_eth - process an ingress ethernet packet
207462306a36Sopenharmony_ci *	@adap: the adapter
207562306a36Sopenharmony_ci *	@rq: the response queue that received the packet
207662306a36Sopenharmony_ci *	@skb: the packet
207762306a36Sopenharmony_ci *	@pad: padding
207862306a36Sopenharmony_ci *	@lro: large receive offload
207962306a36Sopenharmony_ci *
208062306a36Sopenharmony_ci *	Process an ingress ethernet packet and deliver it to the stack.
208162306a36Sopenharmony_ci *	The padding is 2 if the packet was delivered in an Rx buffer and 0
208262306a36Sopenharmony_ci *	if it was immediate data in a response.
208362306a36Sopenharmony_ci */
208462306a36Sopenharmony_cistatic void rx_eth(struct adapter *adap, struct sge_rspq *rq,
208562306a36Sopenharmony_ci		   struct sk_buff *skb, int pad, int lro)
208662306a36Sopenharmony_ci{
208762306a36Sopenharmony_ci	struct cpl_rx_pkt *p = (struct cpl_rx_pkt *)(skb->data + pad);
208862306a36Sopenharmony_ci	struct sge_qset *qs = rspq_to_qset(rq);
208962306a36Sopenharmony_ci	struct port_info *pi;
209062306a36Sopenharmony_ci
209162306a36Sopenharmony_ci	skb_pull(skb, sizeof(*p) + pad);
209262306a36Sopenharmony_ci	skb->protocol = eth_type_trans(skb, adap->port[p->iff]);
209362306a36Sopenharmony_ci	pi = netdev_priv(skb->dev);
209462306a36Sopenharmony_ci	if ((skb->dev->features & NETIF_F_RXCSUM) && p->csum_valid &&
209562306a36Sopenharmony_ci	    p->csum == htons(0xffff) && !p->fragment) {
209662306a36Sopenharmony_ci		qs->port_stats[SGE_PSTAT_RX_CSUM_GOOD]++;
209762306a36Sopenharmony_ci		skb->ip_summed = CHECKSUM_UNNECESSARY;
209862306a36Sopenharmony_ci	} else
209962306a36Sopenharmony_ci		skb_checksum_none_assert(skb);
210062306a36Sopenharmony_ci	skb_record_rx_queue(skb, qs - &adap->sge.qs[pi->first_qset]);
210162306a36Sopenharmony_ci
210262306a36Sopenharmony_ci	if (p->vlan_valid) {
210362306a36Sopenharmony_ci		qs->port_stats[SGE_PSTAT_VLANEX]++;
210462306a36Sopenharmony_ci		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), ntohs(p->vlan));
210562306a36Sopenharmony_ci	}
210662306a36Sopenharmony_ci	if (rq->polling) {
210762306a36Sopenharmony_ci		if (lro)
210862306a36Sopenharmony_ci			napi_gro_receive(&qs->napi, skb);
210962306a36Sopenharmony_ci		else {
211062306a36Sopenharmony_ci			if (unlikely(pi->iscsic.flags))
211162306a36Sopenharmony_ci				cxgb3_process_iscsi_prov_pack(pi, skb);
211262306a36Sopenharmony_ci			netif_receive_skb(skb);
211362306a36Sopenharmony_ci		}
211462306a36Sopenharmony_ci	} else
211562306a36Sopenharmony_ci		netif_rx(skb);
211662306a36Sopenharmony_ci}
211762306a36Sopenharmony_ci
211862306a36Sopenharmony_cistatic inline int is_eth_tcp(u32 rss)
211962306a36Sopenharmony_ci{
212062306a36Sopenharmony_ci	return G_HASHTYPE(ntohl(rss)) == RSS_HASH_4_TUPLE;
212162306a36Sopenharmony_ci}
212262306a36Sopenharmony_ci
212362306a36Sopenharmony_ci/**
212462306a36Sopenharmony_ci *	lro_add_page - add a page chunk to an LRO session
212562306a36Sopenharmony_ci *	@adap: the adapter
212662306a36Sopenharmony_ci *	@qs: the associated queue set
212762306a36Sopenharmony_ci *	@fl: the free list containing the page chunk to add
212862306a36Sopenharmony_ci *	@len: packet length
212962306a36Sopenharmony_ci *	@complete: Indicates the last fragment of a frame
213062306a36Sopenharmony_ci *
213162306a36Sopenharmony_ci *	Add a received packet contained in a page chunk to an existing LRO
213262306a36Sopenharmony_ci *	session.
213362306a36Sopenharmony_ci */
213462306a36Sopenharmony_cistatic void lro_add_page(struct adapter *adap, struct sge_qset *qs,
213562306a36Sopenharmony_ci			 struct sge_fl *fl, int len, int complete)
213662306a36Sopenharmony_ci{
213762306a36Sopenharmony_ci	struct rx_sw_desc *sd = &fl->sdesc[fl->cidx];
213862306a36Sopenharmony_ci	struct port_info *pi = netdev_priv(qs->netdev);
213962306a36Sopenharmony_ci	struct sk_buff *skb = NULL;
214062306a36Sopenharmony_ci	struct cpl_rx_pkt *cpl;
214162306a36Sopenharmony_ci	skb_frag_t *rx_frag;
214262306a36Sopenharmony_ci	int nr_frags;
214362306a36Sopenharmony_ci	int offset = 0;
214462306a36Sopenharmony_ci
214562306a36Sopenharmony_ci	if (!qs->nomem) {
214662306a36Sopenharmony_ci		skb = napi_get_frags(&qs->napi);
214762306a36Sopenharmony_ci		qs->nomem = !skb;
214862306a36Sopenharmony_ci	}
214962306a36Sopenharmony_ci
215062306a36Sopenharmony_ci	fl->credits--;
215162306a36Sopenharmony_ci
215262306a36Sopenharmony_ci	dma_sync_single_for_cpu(&adap->pdev->dev,
215362306a36Sopenharmony_ci				dma_unmap_addr(sd, dma_addr),
215462306a36Sopenharmony_ci				fl->buf_size - SGE_PG_RSVD, DMA_FROM_DEVICE);
215562306a36Sopenharmony_ci
215662306a36Sopenharmony_ci	(*sd->pg_chunk.p_cnt)--;
215762306a36Sopenharmony_ci	if (!*sd->pg_chunk.p_cnt && sd->pg_chunk.page != fl->pg_chunk.page)
215862306a36Sopenharmony_ci		dma_unmap_page(&adap->pdev->dev, sd->pg_chunk.mapping,
215962306a36Sopenharmony_ci			       fl->alloc_size, DMA_FROM_DEVICE);
216062306a36Sopenharmony_ci
216162306a36Sopenharmony_ci	if (!skb) {
216262306a36Sopenharmony_ci		put_page(sd->pg_chunk.page);
216362306a36Sopenharmony_ci		if (complete)
216462306a36Sopenharmony_ci			qs->nomem = 0;
216562306a36Sopenharmony_ci		return;
216662306a36Sopenharmony_ci	}
216762306a36Sopenharmony_ci
216862306a36Sopenharmony_ci	rx_frag = skb_shinfo(skb)->frags;
216962306a36Sopenharmony_ci	nr_frags = skb_shinfo(skb)->nr_frags;
217062306a36Sopenharmony_ci
217162306a36Sopenharmony_ci	if (!nr_frags) {
217262306a36Sopenharmony_ci		offset = 2 + sizeof(struct cpl_rx_pkt);
217362306a36Sopenharmony_ci		cpl = qs->lro_va = sd->pg_chunk.va + 2;
217462306a36Sopenharmony_ci
217562306a36Sopenharmony_ci		if ((qs->netdev->features & NETIF_F_RXCSUM) &&
217662306a36Sopenharmony_ci		     cpl->csum_valid && cpl->csum == htons(0xffff)) {
217762306a36Sopenharmony_ci			skb->ip_summed = CHECKSUM_UNNECESSARY;
217862306a36Sopenharmony_ci			qs->port_stats[SGE_PSTAT_RX_CSUM_GOOD]++;
217962306a36Sopenharmony_ci		} else
218062306a36Sopenharmony_ci			skb->ip_summed = CHECKSUM_NONE;
218162306a36Sopenharmony_ci	} else
218262306a36Sopenharmony_ci		cpl = qs->lro_va;
218362306a36Sopenharmony_ci
218462306a36Sopenharmony_ci	len -= offset;
218562306a36Sopenharmony_ci
218662306a36Sopenharmony_ci	rx_frag += nr_frags;
218762306a36Sopenharmony_ci	skb_frag_fill_page_desc(rx_frag, sd->pg_chunk.page,
218862306a36Sopenharmony_ci				sd->pg_chunk.offset + offset, len);
218962306a36Sopenharmony_ci
219062306a36Sopenharmony_ci	skb->len += len;
219162306a36Sopenharmony_ci	skb->data_len += len;
219262306a36Sopenharmony_ci	skb->truesize += len;
219362306a36Sopenharmony_ci	skb_shinfo(skb)->nr_frags++;
219462306a36Sopenharmony_ci
219562306a36Sopenharmony_ci	if (!complete)
219662306a36Sopenharmony_ci		return;
219762306a36Sopenharmony_ci
219862306a36Sopenharmony_ci	skb_record_rx_queue(skb, qs - &adap->sge.qs[pi->first_qset]);
219962306a36Sopenharmony_ci
220062306a36Sopenharmony_ci	if (cpl->vlan_valid) {
220162306a36Sopenharmony_ci		qs->port_stats[SGE_PSTAT_VLANEX]++;
220262306a36Sopenharmony_ci		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), ntohs(cpl->vlan));
220362306a36Sopenharmony_ci	}
220462306a36Sopenharmony_ci	napi_gro_frags(&qs->napi);
220562306a36Sopenharmony_ci}
220662306a36Sopenharmony_ci
220762306a36Sopenharmony_ci/**
220862306a36Sopenharmony_ci *	handle_rsp_cntrl_info - handles control information in a response
220962306a36Sopenharmony_ci *	@qs: the queue set corresponding to the response
221062306a36Sopenharmony_ci *	@flags: the response control flags
221162306a36Sopenharmony_ci *
221262306a36Sopenharmony_ci *	Handles the control information of an SGE response, such as GTS
221362306a36Sopenharmony_ci *	indications and completion credits for the queue set's Tx queues.
221462306a36Sopenharmony_ci *	HW coalesces credits, we don't do any extra SW coalescing.
221562306a36Sopenharmony_ci */
221662306a36Sopenharmony_cistatic inline void handle_rsp_cntrl_info(struct sge_qset *qs, u32 flags)
221762306a36Sopenharmony_ci{
221862306a36Sopenharmony_ci	unsigned int credits;
221962306a36Sopenharmony_ci
222062306a36Sopenharmony_ci#if USE_GTS
222162306a36Sopenharmony_ci	if (flags & F_RSPD_TXQ0_GTS)
222262306a36Sopenharmony_ci		clear_bit(TXQ_RUNNING, &qs->txq[TXQ_ETH].flags);
222362306a36Sopenharmony_ci#endif
222462306a36Sopenharmony_ci
222562306a36Sopenharmony_ci	credits = G_RSPD_TXQ0_CR(flags);
222662306a36Sopenharmony_ci	if (credits)
222762306a36Sopenharmony_ci		qs->txq[TXQ_ETH].processed += credits;
222862306a36Sopenharmony_ci
222962306a36Sopenharmony_ci	credits = G_RSPD_TXQ2_CR(flags);
223062306a36Sopenharmony_ci	if (credits)
223162306a36Sopenharmony_ci		qs->txq[TXQ_CTRL].processed += credits;
223262306a36Sopenharmony_ci
223362306a36Sopenharmony_ci# if USE_GTS
223462306a36Sopenharmony_ci	if (flags & F_RSPD_TXQ1_GTS)
223562306a36Sopenharmony_ci		clear_bit(TXQ_RUNNING, &qs->txq[TXQ_OFLD].flags);
223662306a36Sopenharmony_ci# endif
223762306a36Sopenharmony_ci	credits = G_RSPD_TXQ1_CR(flags);
223862306a36Sopenharmony_ci	if (credits)
223962306a36Sopenharmony_ci		qs->txq[TXQ_OFLD].processed += credits;
224062306a36Sopenharmony_ci}
224162306a36Sopenharmony_ci
224262306a36Sopenharmony_ci/**
224362306a36Sopenharmony_ci *	check_ring_db - check if we need to ring any doorbells
224462306a36Sopenharmony_ci *	@adap: the adapter
224562306a36Sopenharmony_ci *	@qs: the queue set whose Tx queues are to be examined
224662306a36Sopenharmony_ci *	@sleeping: indicates which Tx queue sent GTS
224762306a36Sopenharmony_ci *
224862306a36Sopenharmony_ci *	Checks if some of a queue set's Tx queues need to ring their doorbells
224962306a36Sopenharmony_ci *	to resume transmission after idling while they still have unprocessed
225062306a36Sopenharmony_ci *	descriptors.
225162306a36Sopenharmony_ci */
225262306a36Sopenharmony_cistatic void check_ring_db(struct adapter *adap, struct sge_qset *qs,
225362306a36Sopenharmony_ci			  unsigned int sleeping)
225462306a36Sopenharmony_ci{
225562306a36Sopenharmony_ci	if (sleeping & F_RSPD_TXQ0_GTS) {
225662306a36Sopenharmony_ci		struct sge_txq *txq = &qs->txq[TXQ_ETH];
225762306a36Sopenharmony_ci
225862306a36Sopenharmony_ci		if (txq->cleaned + txq->in_use != txq->processed &&
225962306a36Sopenharmony_ci		    !test_and_set_bit(TXQ_LAST_PKT_DB, &txq->flags)) {
226062306a36Sopenharmony_ci			set_bit(TXQ_RUNNING, &txq->flags);
226162306a36Sopenharmony_ci			t3_write_reg(adap, A_SG_KDOORBELL, F_SELEGRCNTX |
226262306a36Sopenharmony_ci				     V_EGRCNTX(txq->cntxt_id));
226362306a36Sopenharmony_ci		}
226462306a36Sopenharmony_ci	}
226562306a36Sopenharmony_ci
226662306a36Sopenharmony_ci	if (sleeping & F_RSPD_TXQ1_GTS) {
226762306a36Sopenharmony_ci		struct sge_txq *txq = &qs->txq[TXQ_OFLD];
226862306a36Sopenharmony_ci
226962306a36Sopenharmony_ci		if (txq->cleaned + txq->in_use != txq->processed &&
227062306a36Sopenharmony_ci		    !test_and_set_bit(TXQ_LAST_PKT_DB, &txq->flags)) {
227162306a36Sopenharmony_ci			set_bit(TXQ_RUNNING, &txq->flags);
227262306a36Sopenharmony_ci			t3_write_reg(adap, A_SG_KDOORBELL, F_SELEGRCNTX |
227362306a36Sopenharmony_ci				     V_EGRCNTX(txq->cntxt_id));
227462306a36Sopenharmony_ci		}
227562306a36Sopenharmony_ci	}
227662306a36Sopenharmony_ci}
227762306a36Sopenharmony_ci
227862306a36Sopenharmony_ci/**
227962306a36Sopenharmony_ci *	is_new_response - check if a response is newly written
228062306a36Sopenharmony_ci *	@r: the response descriptor
228162306a36Sopenharmony_ci *	@q: the response queue
228262306a36Sopenharmony_ci *
228362306a36Sopenharmony_ci *	Returns true if a response descriptor contains a yet unprocessed
228462306a36Sopenharmony_ci *	response.
228562306a36Sopenharmony_ci */
228662306a36Sopenharmony_cistatic inline int is_new_response(const struct rsp_desc *r,
228762306a36Sopenharmony_ci				  const struct sge_rspq *q)
228862306a36Sopenharmony_ci{
228962306a36Sopenharmony_ci	return (r->intr_gen & F_RSPD_GEN2) == q->gen;
229062306a36Sopenharmony_ci}
229162306a36Sopenharmony_ci
229262306a36Sopenharmony_cistatic inline void clear_rspq_bufstate(struct sge_rspq * const q)
229362306a36Sopenharmony_ci{
229462306a36Sopenharmony_ci	q->pg_skb = NULL;
229562306a36Sopenharmony_ci	q->rx_recycle_buf = 0;
229662306a36Sopenharmony_ci}
229762306a36Sopenharmony_ci
229862306a36Sopenharmony_ci#define RSPD_GTS_MASK  (F_RSPD_TXQ0_GTS | F_RSPD_TXQ1_GTS)
229962306a36Sopenharmony_ci#define RSPD_CTRL_MASK (RSPD_GTS_MASK | \
230062306a36Sopenharmony_ci			V_RSPD_TXQ0_CR(M_RSPD_TXQ0_CR) | \
230162306a36Sopenharmony_ci			V_RSPD_TXQ1_CR(M_RSPD_TXQ1_CR) | \
230262306a36Sopenharmony_ci			V_RSPD_TXQ2_CR(M_RSPD_TXQ2_CR))
230362306a36Sopenharmony_ci
230462306a36Sopenharmony_ci/* How long to delay the next interrupt in case of memory shortage, in 0.1us. */
230562306a36Sopenharmony_ci#define NOMEM_INTR_DELAY 2500
230662306a36Sopenharmony_ci
230762306a36Sopenharmony_ci/**
230862306a36Sopenharmony_ci *	process_responses - process responses from an SGE response queue
230962306a36Sopenharmony_ci *	@adap: the adapter
231062306a36Sopenharmony_ci *	@qs: the queue set to which the response queue belongs
231162306a36Sopenharmony_ci *	@budget: how many responses can be processed in this round
231262306a36Sopenharmony_ci *
231362306a36Sopenharmony_ci *	Process responses from an SGE response queue up to the supplied budget.
231462306a36Sopenharmony_ci *	Responses include received packets as well as credits and other events
231562306a36Sopenharmony_ci *	for the queues that belong to the response queue's queue set.
231662306a36Sopenharmony_ci *	A negative budget is effectively unlimited.
231762306a36Sopenharmony_ci *
231862306a36Sopenharmony_ci *	Additionally choose the interrupt holdoff time for the next interrupt
231962306a36Sopenharmony_ci *	on this queue.  If the system is under memory shortage use a fairly
232062306a36Sopenharmony_ci *	long delay to help recovery.
232162306a36Sopenharmony_ci */
232262306a36Sopenharmony_cistatic int process_responses(struct adapter *adap, struct sge_qset *qs,
232362306a36Sopenharmony_ci			     int budget)
232462306a36Sopenharmony_ci{
232562306a36Sopenharmony_ci	struct sge_rspq *q = &qs->rspq;
232662306a36Sopenharmony_ci	struct rsp_desc *r = &q->desc[q->cidx];
232762306a36Sopenharmony_ci	int budget_left = budget;
232862306a36Sopenharmony_ci	unsigned int sleeping = 0;
232962306a36Sopenharmony_ci	struct sk_buff *offload_skbs[RX_BUNDLE_SIZE];
233062306a36Sopenharmony_ci	int ngathered = 0;
233162306a36Sopenharmony_ci
233262306a36Sopenharmony_ci	q->next_holdoff = q->holdoff_tmr;
233362306a36Sopenharmony_ci
233462306a36Sopenharmony_ci	while (likely(budget_left && is_new_response(r, q))) {
233562306a36Sopenharmony_ci		int packet_complete, eth, ethpad = 2;
233662306a36Sopenharmony_ci		int lro = !!(qs->netdev->features & NETIF_F_GRO);
233762306a36Sopenharmony_ci		struct sk_buff *skb = NULL;
233862306a36Sopenharmony_ci		u32 len, flags;
233962306a36Sopenharmony_ci		__be32 rss_hi, rss_lo;
234062306a36Sopenharmony_ci
234162306a36Sopenharmony_ci		dma_rmb();
234262306a36Sopenharmony_ci		eth = r->rss_hdr.opcode == CPL_RX_PKT;
234362306a36Sopenharmony_ci		rss_hi = *(const __be32 *)r;
234462306a36Sopenharmony_ci		rss_lo = r->rss_hdr.rss_hash_val;
234562306a36Sopenharmony_ci		flags = ntohl(r->flags);
234662306a36Sopenharmony_ci
234762306a36Sopenharmony_ci		if (unlikely(flags & F_RSPD_ASYNC_NOTIF)) {
234862306a36Sopenharmony_ci			skb = alloc_skb(AN_PKT_SIZE, GFP_ATOMIC);
234962306a36Sopenharmony_ci			if (!skb)
235062306a36Sopenharmony_ci				goto no_mem;
235162306a36Sopenharmony_ci
235262306a36Sopenharmony_ci			__skb_put_data(skb, r, AN_PKT_SIZE);
235362306a36Sopenharmony_ci			skb->data[0] = CPL_ASYNC_NOTIF;
235462306a36Sopenharmony_ci			rss_hi = htonl(CPL_ASYNC_NOTIF << 24);
235562306a36Sopenharmony_ci			q->async_notif++;
235662306a36Sopenharmony_ci		} else if (flags & F_RSPD_IMM_DATA_VALID) {
235762306a36Sopenharmony_ci			skb = get_imm_packet(r);
235862306a36Sopenharmony_ci			if (unlikely(!skb)) {
235962306a36Sopenharmony_cino_mem:
236062306a36Sopenharmony_ci				q->next_holdoff = NOMEM_INTR_DELAY;
236162306a36Sopenharmony_ci				q->nomem++;
236262306a36Sopenharmony_ci				/* consume one credit since we tried */
236362306a36Sopenharmony_ci				budget_left--;
236462306a36Sopenharmony_ci				break;
236562306a36Sopenharmony_ci			}
236662306a36Sopenharmony_ci			q->imm_data++;
236762306a36Sopenharmony_ci			ethpad = 0;
236862306a36Sopenharmony_ci		} else if ((len = ntohl(r->len_cq)) != 0) {
236962306a36Sopenharmony_ci			struct sge_fl *fl;
237062306a36Sopenharmony_ci
237162306a36Sopenharmony_ci			lro &= eth && is_eth_tcp(rss_hi);
237262306a36Sopenharmony_ci
237362306a36Sopenharmony_ci			fl = (len & F_RSPD_FLQ) ? &qs->fl[1] : &qs->fl[0];
237462306a36Sopenharmony_ci			if (fl->use_pages) {
237562306a36Sopenharmony_ci				void *addr = fl->sdesc[fl->cidx].pg_chunk.va;
237662306a36Sopenharmony_ci
237762306a36Sopenharmony_ci				net_prefetch(addr);
237862306a36Sopenharmony_ci				__refill_fl(adap, fl);
237962306a36Sopenharmony_ci				if (lro > 0) {
238062306a36Sopenharmony_ci					lro_add_page(adap, qs, fl,
238162306a36Sopenharmony_ci						     G_RSPD_LEN(len),
238262306a36Sopenharmony_ci						     flags & F_RSPD_EOP);
238362306a36Sopenharmony_ci					goto next_fl;
238462306a36Sopenharmony_ci				}
238562306a36Sopenharmony_ci
238662306a36Sopenharmony_ci				skb = get_packet_pg(adap, fl, q,
238762306a36Sopenharmony_ci						    G_RSPD_LEN(len),
238862306a36Sopenharmony_ci						    eth ?
238962306a36Sopenharmony_ci						    SGE_RX_DROP_THRES : 0);
239062306a36Sopenharmony_ci				q->pg_skb = skb;
239162306a36Sopenharmony_ci			} else
239262306a36Sopenharmony_ci				skb = get_packet(adap, fl, G_RSPD_LEN(len),
239362306a36Sopenharmony_ci						 eth ? SGE_RX_DROP_THRES : 0);
239462306a36Sopenharmony_ci			if (unlikely(!skb)) {
239562306a36Sopenharmony_ci				if (!eth)
239662306a36Sopenharmony_ci					goto no_mem;
239762306a36Sopenharmony_ci				q->rx_drops++;
239862306a36Sopenharmony_ci			} else if (unlikely(r->rss_hdr.opcode == CPL_TRACE_PKT))
239962306a36Sopenharmony_ci				__skb_pull(skb, 2);
240062306a36Sopenharmony_cinext_fl:
240162306a36Sopenharmony_ci			if (++fl->cidx == fl->size)
240262306a36Sopenharmony_ci				fl->cidx = 0;
240362306a36Sopenharmony_ci		} else
240462306a36Sopenharmony_ci			q->pure_rsps++;
240562306a36Sopenharmony_ci
240662306a36Sopenharmony_ci		if (flags & RSPD_CTRL_MASK) {
240762306a36Sopenharmony_ci			sleeping |= flags & RSPD_GTS_MASK;
240862306a36Sopenharmony_ci			handle_rsp_cntrl_info(qs, flags);
240962306a36Sopenharmony_ci		}
241062306a36Sopenharmony_ci
241162306a36Sopenharmony_ci		r++;
241262306a36Sopenharmony_ci		if (unlikely(++q->cidx == q->size)) {
241362306a36Sopenharmony_ci			q->cidx = 0;
241462306a36Sopenharmony_ci			q->gen ^= 1;
241562306a36Sopenharmony_ci			r = q->desc;
241662306a36Sopenharmony_ci		}
241762306a36Sopenharmony_ci		prefetch(r);
241862306a36Sopenharmony_ci
241962306a36Sopenharmony_ci		if (++q->credits >= (q->size / 4)) {
242062306a36Sopenharmony_ci			refill_rspq(adap, q, q->credits);
242162306a36Sopenharmony_ci			q->credits = 0;
242262306a36Sopenharmony_ci		}
242362306a36Sopenharmony_ci
242462306a36Sopenharmony_ci		packet_complete = flags &
242562306a36Sopenharmony_ci				  (F_RSPD_EOP | F_RSPD_IMM_DATA_VALID |
242662306a36Sopenharmony_ci				   F_RSPD_ASYNC_NOTIF);
242762306a36Sopenharmony_ci
242862306a36Sopenharmony_ci		if (skb != NULL && packet_complete) {
242962306a36Sopenharmony_ci			if (eth)
243062306a36Sopenharmony_ci				rx_eth(adap, q, skb, ethpad, lro);
243162306a36Sopenharmony_ci			else {
243262306a36Sopenharmony_ci				q->offload_pkts++;
243362306a36Sopenharmony_ci				/* Preserve the RSS info in csum & priority */
243462306a36Sopenharmony_ci				skb->csum = rss_hi;
243562306a36Sopenharmony_ci				skb->priority = rss_lo;
243662306a36Sopenharmony_ci				ngathered = rx_offload(&adap->tdev, q, skb,
243762306a36Sopenharmony_ci						       offload_skbs,
243862306a36Sopenharmony_ci						       ngathered);
243962306a36Sopenharmony_ci			}
244062306a36Sopenharmony_ci
244162306a36Sopenharmony_ci			if (flags & F_RSPD_EOP)
244262306a36Sopenharmony_ci				clear_rspq_bufstate(q);
244362306a36Sopenharmony_ci		}
244462306a36Sopenharmony_ci		--budget_left;
244562306a36Sopenharmony_ci	}
244662306a36Sopenharmony_ci
244762306a36Sopenharmony_ci	deliver_partial_bundle(&adap->tdev, q, offload_skbs, ngathered);
244862306a36Sopenharmony_ci
244962306a36Sopenharmony_ci	if (sleeping)
245062306a36Sopenharmony_ci		check_ring_db(adap, qs, sleeping);
245162306a36Sopenharmony_ci
245262306a36Sopenharmony_ci	smp_mb();		/* commit Tx queue .processed updates */
245362306a36Sopenharmony_ci	if (unlikely(qs->txq_stopped != 0))
245462306a36Sopenharmony_ci		restart_tx(qs);
245562306a36Sopenharmony_ci
245662306a36Sopenharmony_ci	budget -= budget_left;
245762306a36Sopenharmony_ci	return budget;
245862306a36Sopenharmony_ci}
245962306a36Sopenharmony_ci
246062306a36Sopenharmony_cistatic inline int is_pure_response(const struct rsp_desc *r)
246162306a36Sopenharmony_ci{
246262306a36Sopenharmony_ci	__be32 n = r->flags & htonl(F_RSPD_ASYNC_NOTIF | F_RSPD_IMM_DATA_VALID);
246362306a36Sopenharmony_ci
246462306a36Sopenharmony_ci	return (n | r->len_cq) == 0;
246562306a36Sopenharmony_ci}
246662306a36Sopenharmony_ci
246762306a36Sopenharmony_ci/**
246862306a36Sopenharmony_ci *	napi_rx_handler - the NAPI handler for Rx processing
246962306a36Sopenharmony_ci *	@napi: the napi instance
247062306a36Sopenharmony_ci *	@budget: how many packets we can process in this round
247162306a36Sopenharmony_ci *
247262306a36Sopenharmony_ci *	Handler for new data events when using NAPI.
247362306a36Sopenharmony_ci */
247462306a36Sopenharmony_cistatic int napi_rx_handler(struct napi_struct *napi, int budget)
247562306a36Sopenharmony_ci{
247662306a36Sopenharmony_ci	struct sge_qset *qs = container_of(napi, struct sge_qset, napi);
247762306a36Sopenharmony_ci	struct adapter *adap = qs->adap;
247862306a36Sopenharmony_ci	int work_done = process_responses(adap, qs, budget);
247962306a36Sopenharmony_ci
248062306a36Sopenharmony_ci	if (likely(work_done < budget)) {
248162306a36Sopenharmony_ci		napi_complete_done(napi, work_done);
248262306a36Sopenharmony_ci
248362306a36Sopenharmony_ci		/*
248462306a36Sopenharmony_ci		 * Because we don't atomically flush the following
248562306a36Sopenharmony_ci		 * write it is possible that in very rare cases it can
248662306a36Sopenharmony_ci		 * reach the device in a way that races with a new
248762306a36Sopenharmony_ci		 * response being written plus an error interrupt
248862306a36Sopenharmony_ci		 * causing the NAPI interrupt handler below to return
248962306a36Sopenharmony_ci		 * unhandled status to the OS.  To protect against
249062306a36Sopenharmony_ci		 * this would require flushing the write and doing
249162306a36Sopenharmony_ci		 * both the write and the flush with interrupts off.
249262306a36Sopenharmony_ci		 * Way too expensive and unjustifiable given the
249362306a36Sopenharmony_ci		 * rarity of the race.
249462306a36Sopenharmony_ci		 *
249562306a36Sopenharmony_ci		 * The race cannot happen at all with MSI-X.
249662306a36Sopenharmony_ci		 */
249762306a36Sopenharmony_ci		t3_write_reg(adap, A_SG_GTS, V_RSPQ(qs->rspq.cntxt_id) |
249862306a36Sopenharmony_ci			     V_NEWTIMER(qs->rspq.next_holdoff) |
249962306a36Sopenharmony_ci			     V_NEWINDEX(qs->rspq.cidx));
250062306a36Sopenharmony_ci	}
250162306a36Sopenharmony_ci	return work_done;
250262306a36Sopenharmony_ci}
250362306a36Sopenharmony_ci
250462306a36Sopenharmony_ci/*
250562306a36Sopenharmony_ci * Returns true if the device is already scheduled for polling.
250662306a36Sopenharmony_ci */
250762306a36Sopenharmony_cistatic inline int napi_is_scheduled(struct napi_struct *napi)
250862306a36Sopenharmony_ci{
250962306a36Sopenharmony_ci	return test_bit(NAPI_STATE_SCHED, &napi->state);
251062306a36Sopenharmony_ci}
251162306a36Sopenharmony_ci
251262306a36Sopenharmony_ci/**
251362306a36Sopenharmony_ci *	process_pure_responses - process pure responses from a response queue
251462306a36Sopenharmony_ci *	@adap: the adapter
251562306a36Sopenharmony_ci *	@qs: the queue set owning the response queue
251662306a36Sopenharmony_ci *	@r: the first pure response to process
251762306a36Sopenharmony_ci *
251862306a36Sopenharmony_ci *	A simpler version of process_responses() that handles only pure (i.e.,
251962306a36Sopenharmony_ci *	non data-carrying) responses.  Such respones are too light-weight to
252062306a36Sopenharmony_ci *	justify calling a softirq under NAPI, so we handle them specially in
252162306a36Sopenharmony_ci *	the interrupt handler.  The function is called with a pointer to a
252262306a36Sopenharmony_ci *	response, which the caller must ensure is a valid pure response.
252362306a36Sopenharmony_ci *
252462306a36Sopenharmony_ci *	Returns 1 if it encounters a valid data-carrying response, 0 otherwise.
252562306a36Sopenharmony_ci */
252662306a36Sopenharmony_cistatic int process_pure_responses(struct adapter *adap, struct sge_qset *qs,
252762306a36Sopenharmony_ci				  struct rsp_desc *r)
252862306a36Sopenharmony_ci{
252962306a36Sopenharmony_ci	struct sge_rspq *q = &qs->rspq;
253062306a36Sopenharmony_ci	unsigned int sleeping = 0;
253162306a36Sopenharmony_ci
253262306a36Sopenharmony_ci	do {
253362306a36Sopenharmony_ci		u32 flags = ntohl(r->flags);
253462306a36Sopenharmony_ci
253562306a36Sopenharmony_ci		r++;
253662306a36Sopenharmony_ci		if (unlikely(++q->cidx == q->size)) {
253762306a36Sopenharmony_ci			q->cidx = 0;
253862306a36Sopenharmony_ci			q->gen ^= 1;
253962306a36Sopenharmony_ci			r = q->desc;
254062306a36Sopenharmony_ci		}
254162306a36Sopenharmony_ci		prefetch(r);
254262306a36Sopenharmony_ci
254362306a36Sopenharmony_ci		if (flags & RSPD_CTRL_MASK) {
254462306a36Sopenharmony_ci			sleeping |= flags & RSPD_GTS_MASK;
254562306a36Sopenharmony_ci			handle_rsp_cntrl_info(qs, flags);
254662306a36Sopenharmony_ci		}
254762306a36Sopenharmony_ci
254862306a36Sopenharmony_ci		q->pure_rsps++;
254962306a36Sopenharmony_ci		if (++q->credits >= (q->size / 4)) {
255062306a36Sopenharmony_ci			refill_rspq(adap, q, q->credits);
255162306a36Sopenharmony_ci			q->credits = 0;
255262306a36Sopenharmony_ci		}
255362306a36Sopenharmony_ci		if (!is_new_response(r, q))
255462306a36Sopenharmony_ci			break;
255562306a36Sopenharmony_ci		dma_rmb();
255662306a36Sopenharmony_ci	} while (is_pure_response(r));
255762306a36Sopenharmony_ci
255862306a36Sopenharmony_ci	if (sleeping)
255962306a36Sopenharmony_ci		check_ring_db(adap, qs, sleeping);
256062306a36Sopenharmony_ci
256162306a36Sopenharmony_ci	smp_mb();		/* commit Tx queue .processed updates */
256262306a36Sopenharmony_ci	if (unlikely(qs->txq_stopped != 0))
256362306a36Sopenharmony_ci		restart_tx(qs);
256462306a36Sopenharmony_ci
256562306a36Sopenharmony_ci	return is_new_response(r, q);
256662306a36Sopenharmony_ci}
256762306a36Sopenharmony_ci
256862306a36Sopenharmony_ci/**
256962306a36Sopenharmony_ci *	handle_responses - decide what to do with new responses in NAPI mode
257062306a36Sopenharmony_ci *	@adap: the adapter
257162306a36Sopenharmony_ci *	@q: the response queue
257262306a36Sopenharmony_ci *
257362306a36Sopenharmony_ci *	This is used by the NAPI interrupt handlers to decide what to do with
257462306a36Sopenharmony_ci *	new SGE responses.  If there are no new responses it returns -1.  If
257562306a36Sopenharmony_ci *	there are new responses and they are pure (i.e., non-data carrying)
257662306a36Sopenharmony_ci *	it handles them straight in hard interrupt context as they are very
257762306a36Sopenharmony_ci *	cheap and don't deliver any packets.  Finally, if there are any data
257862306a36Sopenharmony_ci *	signaling responses it schedules the NAPI handler.  Returns 1 if it
257962306a36Sopenharmony_ci *	schedules NAPI, 0 if all new responses were pure.
258062306a36Sopenharmony_ci *
258162306a36Sopenharmony_ci *	The caller must ascertain NAPI is not already running.
258262306a36Sopenharmony_ci */
258362306a36Sopenharmony_cistatic inline int handle_responses(struct adapter *adap, struct sge_rspq *q)
258462306a36Sopenharmony_ci{
258562306a36Sopenharmony_ci	struct sge_qset *qs = rspq_to_qset(q);
258662306a36Sopenharmony_ci	struct rsp_desc *r = &q->desc[q->cidx];
258762306a36Sopenharmony_ci
258862306a36Sopenharmony_ci	if (!is_new_response(r, q))
258962306a36Sopenharmony_ci		return -1;
259062306a36Sopenharmony_ci	dma_rmb();
259162306a36Sopenharmony_ci	if (is_pure_response(r) && process_pure_responses(adap, qs, r) == 0) {
259262306a36Sopenharmony_ci		t3_write_reg(adap, A_SG_GTS, V_RSPQ(q->cntxt_id) |
259362306a36Sopenharmony_ci			     V_NEWTIMER(q->holdoff_tmr) | V_NEWINDEX(q->cidx));
259462306a36Sopenharmony_ci		return 0;
259562306a36Sopenharmony_ci	}
259662306a36Sopenharmony_ci	napi_schedule(&qs->napi);
259762306a36Sopenharmony_ci	return 1;
259862306a36Sopenharmony_ci}
259962306a36Sopenharmony_ci
260062306a36Sopenharmony_ci/*
260162306a36Sopenharmony_ci * The MSI-X interrupt handler for an SGE response queue for the non-NAPI case
260262306a36Sopenharmony_ci * (i.e., response queue serviced in hard interrupt).
260362306a36Sopenharmony_ci */
260462306a36Sopenharmony_cistatic irqreturn_t t3_sge_intr_msix(int irq, void *cookie)
260562306a36Sopenharmony_ci{
260662306a36Sopenharmony_ci	struct sge_qset *qs = cookie;
260762306a36Sopenharmony_ci	struct adapter *adap = qs->adap;
260862306a36Sopenharmony_ci	struct sge_rspq *q = &qs->rspq;
260962306a36Sopenharmony_ci
261062306a36Sopenharmony_ci	spin_lock(&q->lock);
261162306a36Sopenharmony_ci	if (process_responses(adap, qs, -1) == 0)
261262306a36Sopenharmony_ci		q->unhandled_irqs++;
261362306a36Sopenharmony_ci	t3_write_reg(adap, A_SG_GTS, V_RSPQ(q->cntxt_id) |
261462306a36Sopenharmony_ci		     V_NEWTIMER(q->next_holdoff) | V_NEWINDEX(q->cidx));
261562306a36Sopenharmony_ci	spin_unlock(&q->lock);
261662306a36Sopenharmony_ci	return IRQ_HANDLED;
261762306a36Sopenharmony_ci}
261862306a36Sopenharmony_ci
261962306a36Sopenharmony_ci/*
262062306a36Sopenharmony_ci * The MSI-X interrupt handler for an SGE response queue for the NAPI case
262162306a36Sopenharmony_ci * (i.e., response queue serviced by NAPI polling).
262262306a36Sopenharmony_ci */
262362306a36Sopenharmony_cistatic irqreturn_t t3_sge_intr_msix_napi(int irq, void *cookie)
262462306a36Sopenharmony_ci{
262562306a36Sopenharmony_ci	struct sge_qset *qs = cookie;
262662306a36Sopenharmony_ci	struct sge_rspq *q = &qs->rspq;
262762306a36Sopenharmony_ci
262862306a36Sopenharmony_ci	spin_lock(&q->lock);
262962306a36Sopenharmony_ci
263062306a36Sopenharmony_ci	if (handle_responses(qs->adap, q) < 0)
263162306a36Sopenharmony_ci		q->unhandled_irqs++;
263262306a36Sopenharmony_ci	spin_unlock(&q->lock);
263362306a36Sopenharmony_ci	return IRQ_HANDLED;
263462306a36Sopenharmony_ci}
263562306a36Sopenharmony_ci
263662306a36Sopenharmony_ci/*
263762306a36Sopenharmony_ci * The non-NAPI MSI interrupt handler.  This needs to handle data events from
263862306a36Sopenharmony_ci * SGE response queues as well as error and other async events as they all use
263962306a36Sopenharmony_ci * the same MSI vector.  We use one SGE response queue per port in this mode
264062306a36Sopenharmony_ci * and protect all response queues with queue 0's lock.
264162306a36Sopenharmony_ci */
264262306a36Sopenharmony_cistatic irqreturn_t t3_intr_msi(int irq, void *cookie)
264362306a36Sopenharmony_ci{
264462306a36Sopenharmony_ci	int new_packets = 0;
264562306a36Sopenharmony_ci	struct adapter *adap = cookie;
264662306a36Sopenharmony_ci	struct sge_rspq *q = &adap->sge.qs[0].rspq;
264762306a36Sopenharmony_ci
264862306a36Sopenharmony_ci	spin_lock(&q->lock);
264962306a36Sopenharmony_ci
265062306a36Sopenharmony_ci	if (process_responses(adap, &adap->sge.qs[0], -1)) {
265162306a36Sopenharmony_ci		t3_write_reg(adap, A_SG_GTS, V_RSPQ(q->cntxt_id) |
265262306a36Sopenharmony_ci			     V_NEWTIMER(q->next_holdoff) | V_NEWINDEX(q->cidx));
265362306a36Sopenharmony_ci		new_packets = 1;
265462306a36Sopenharmony_ci	}
265562306a36Sopenharmony_ci
265662306a36Sopenharmony_ci	if (adap->params.nports == 2 &&
265762306a36Sopenharmony_ci	    process_responses(adap, &adap->sge.qs[1], -1)) {
265862306a36Sopenharmony_ci		struct sge_rspq *q1 = &adap->sge.qs[1].rspq;
265962306a36Sopenharmony_ci
266062306a36Sopenharmony_ci		t3_write_reg(adap, A_SG_GTS, V_RSPQ(q1->cntxt_id) |
266162306a36Sopenharmony_ci			     V_NEWTIMER(q1->next_holdoff) |
266262306a36Sopenharmony_ci			     V_NEWINDEX(q1->cidx));
266362306a36Sopenharmony_ci		new_packets = 1;
266462306a36Sopenharmony_ci	}
266562306a36Sopenharmony_ci
266662306a36Sopenharmony_ci	if (!new_packets && t3_slow_intr_handler(adap) == 0)
266762306a36Sopenharmony_ci		q->unhandled_irqs++;
266862306a36Sopenharmony_ci
266962306a36Sopenharmony_ci	spin_unlock(&q->lock);
267062306a36Sopenharmony_ci	return IRQ_HANDLED;
267162306a36Sopenharmony_ci}
267262306a36Sopenharmony_ci
267362306a36Sopenharmony_cistatic int rspq_check_napi(struct sge_qset *qs)
267462306a36Sopenharmony_ci{
267562306a36Sopenharmony_ci	struct sge_rspq *q = &qs->rspq;
267662306a36Sopenharmony_ci
267762306a36Sopenharmony_ci	if (!napi_is_scheduled(&qs->napi) &&
267862306a36Sopenharmony_ci	    is_new_response(&q->desc[q->cidx], q)) {
267962306a36Sopenharmony_ci		napi_schedule(&qs->napi);
268062306a36Sopenharmony_ci		return 1;
268162306a36Sopenharmony_ci	}
268262306a36Sopenharmony_ci	return 0;
268362306a36Sopenharmony_ci}
268462306a36Sopenharmony_ci
268562306a36Sopenharmony_ci/*
268662306a36Sopenharmony_ci * The MSI interrupt handler for the NAPI case (i.e., response queues serviced
268762306a36Sopenharmony_ci * by NAPI polling).  Handles data events from SGE response queues as well as
268862306a36Sopenharmony_ci * error and other async events as they all use the same MSI vector.  We use
268962306a36Sopenharmony_ci * one SGE response queue per port in this mode and protect all response
269062306a36Sopenharmony_ci * queues with queue 0's lock.
269162306a36Sopenharmony_ci */
269262306a36Sopenharmony_cistatic irqreturn_t t3_intr_msi_napi(int irq, void *cookie)
269362306a36Sopenharmony_ci{
269462306a36Sopenharmony_ci	int new_packets;
269562306a36Sopenharmony_ci	struct adapter *adap = cookie;
269662306a36Sopenharmony_ci	struct sge_rspq *q = &adap->sge.qs[0].rspq;
269762306a36Sopenharmony_ci
269862306a36Sopenharmony_ci	spin_lock(&q->lock);
269962306a36Sopenharmony_ci
270062306a36Sopenharmony_ci	new_packets = rspq_check_napi(&adap->sge.qs[0]);
270162306a36Sopenharmony_ci	if (adap->params.nports == 2)
270262306a36Sopenharmony_ci		new_packets += rspq_check_napi(&adap->sge.qs[1]);
270362306a36Sopenharmony_ci	if (!new_packets && t3_slow_intr_handler(adap) == 0)
270462306a36Sopenharmony_ci		q->unhandled_irqs++;
270562306a36Sopenharmony_ci
270662306a36Sopenharmony_ci	spin_unlock(&q->lock);
270762306a36Sopenharmony_ci	return IRQ_HANDLED;
270862306a36Sopenharmony_ci}
270962306a36Sopenharmony_ci
271062306a36Sopenharmony_ci/*
271162306a36Sopenharmony_ci * A helper function that processes responses and issues GTS.
271262306a36Sopenharmony_ci */
271362306a36Sopenharmony_cistatic inline int process_responses_gts(struct adapter *adap,
271462306a36Sopenharmony_ci					struct sge_rspq *rq)
271562306a36Sopenharmony_ci{
271662306a36Sopenharmony_ci	int work;
271762306a36Sopenharmony_ci
271862306a36Sopenharmony_ci	work = process_responses(adap, rspq_to_qset(rq), -1);
271962306a36Sopenharmony_ci	t3_write_reg(adap, A_SG_GTS, V_RSPQ(rq->cntxt_id) |
272062306a36Sopenharmony_ci		     V_NEWTIMER(rq->next_holdoff) | V_NEWINDEX(rq->cidx));
272162306a36Sopenharmony_ci	return work;
272262306a36Sopenharmony_ci}
272362306a36Sopenharmony_ci
272462306a36Sopenharmony_ci/*
272562306a36Sopenharmony_ci * The legacy INTx interrupt handler.  This needs to handle data events from
272662306a36Sopenharmony_ci * SGE response queues as well as error and other async events as they all use
272762306a36Sopenharmony_ci * the same interrupt pin.  We use one SGE response queue per port in this mode
272862306a36Sopenharmony_ci * and protect all response queues with queue 0's lock.
272962306a36Sopenharmony_ci */
273062306a36Sopenharmony_cistatic irqreturn_t t3_intr(int irq, void *cookie)
273162306a36Sopenharmony_ci{
273262306a36Sopenharmony_ci	int work_done, w0, w1;
273362306a36Sopenharmony_ci	struct adapter *adap = cookie;
273462306a36Sopenharmony_ci	struct sge_rspq *q0 = &adap->sge.qs[0].rspq;
273562306a36Sopenharmony_ci	struct sge_rspq *q1 = &adap->sge.qs[1].rspq;
273662306a36Sopenharmony_ci
273762306a36Sopenharmony_ci	spin_lock(&q0->lock);
273862306a36Sopenharmony_ci
273962306a36Sopenharmony_ci	w0 = is_new_response(&q0->desc[q0->cidx], q0);
274062306a36Sopenharmony_ci	w1 = adap->params.nports == 2 &&
274162306a36Sopenharmony_ci	    is_new_response(&q1->desc[q1->cidx], q1);
274262306a36Sopenharmony_ci
274362306a36Sopenharmony_ci	if (likely(w0 | w1)) {
274462306a36Sopenharmony_ci		t3_write_reg(adap, A_PL_CLI, 0);
274562306a36Sopenharmony_ci		t3_read_reg(adap, A_PL_CLI);	/* flush */
274662306a36Sopenharmony_ci
274762306a36Sopenharmony_ci		if (likely(w0))
274862306a36Sopenharmony_ci			process_responses_gts(adap, q0);
274962306a36Sopenharmony_ci
275062306a36Sopenharmony_ci		if (w1)
275162306a36Sopenharmony_ci			process_responses_gts(adap, q1);
275262306a36Sopenharmony_ci
275362306a36Sopenharmony_ci		work_done = w0 | w1;
275462306a36Sopenharmony_ci	} else
275562306a36Sopenharmony_ci		work_done = t3_slow_intr_handler(adap);
275662306a36Sopenharmony_ci
275762306a36Sopenharmony_ci	spin_unlock(&q0->lock);
275862306a36Sopenharmony_ci	return IRQ_RETVAL(work_done != 0);
275962306a36Sopenharmony_ci}
276062306a36Sopenharmony_ci
276162306a36Sopenharmony_ci/*
276262306a36Sopenharmony_ci * Interrupt handler for legacy INTx interrupts for T3B-based cards.
276362306a36Sopenharmony_ci * Handles data events from SGE response queues as well as error and other
276462306a36Sopenharmony_ci * async events as they all use the same interrupt pin.  We use one SGE
276562306a36Sopenharmony_ci * response queue per port in this mode and protect all response queues with
276662306a36Sopenharmony_ci * queue 0's lock.
276762306a36Sopenharmony_ci */
276862306a36Sopenharmony_cistatic irqreturn_t t3b_intr(int irq, void *cookie)
276962306a36Sopenharmony_ci{
277062306a36Sopenharmony_ci	u32 map;
277162306a36Sopenharmony_ci	struct adapter *adap = cookie;
277262306a36Sopenharmony_ci	struct sge_rspq *q0 = &adap->sge.qs[0].rspq;
277362306a36Sopenharmony_ci
277462306a36Sopenharmony_ci	t3_write_reg(adap, A_PL_CLI, 0);
277562306a36Sopenharmony_ci	map = t3_read_reg(adap, A_SG_DATA_INTR);
277662306a36Sopenharmony_ci
277762306a36Sopenharmony_ci	if (unlikely(!map))	/* shared interrupt, most likely */
277862306a36Sopenharmony_ci		return IRQ_NONE;
277962306a36Sopenharmony_ci
278062306a36Sopenharmony_ci	spin_lock(&q0->lock);
278162306a36Sopenharmony_ci
278262306a36Sopenharmony_ci	if (unlikely(map & F_ERRINTR))
278362306a36Sopenharmony_ci		t3_slow_intr_handler(adap);
278462306a36Sopenharmony_ci
278562306a36Sopenharmony_ci	if (likely(map & 1))
278662306a36Sopenharmony_ci		process_responses_gts(adap, q0);
278762306a36Sopenharmony_ci
278862306a36Sopenharmony_ci	if (map & 2)
278962306a36Sopenharmony_ci		process_responses_gts(adap, &adap->sge.qs[1].rspq);
279062306a36Sopenharmony_ci
279162306a36Sopenharmony_ci	spin_unlock(&q0->lock);
279262306a36Sopenharmony_ci	return IRQ_HANDLED;
279362306a36Sopenharmony_ci}
279462306a36Sopenharmony_ci
279562306a36Sopenharmony_ci/*
279662306a36Sopenharmony_ci * NAPI interrupt handler for legacy INTx interrupts for T3B-based cards.
279762306a36Sopenharmony_ci * Handles data events from SGE response queues as well as error and other
279862306a36Sopenharmony_ci * async events as they all use the same interrupt pin.  We use one SGE
279962306a36Sopenharmony_ci * response queue per port in this mode and protect all response queues with
280062306a36Sopenharmony_ci * queue 0's lock.
280162306a36Sopenharmony_ci */
280262306a36Sopenharmony_cistatic irqreturn_t t3b_intr_napi(int irq, void *cookie)
280362306a36Sopenharmony_ci{
280462306a36Sopenharmony_ci	u32 map;
280562306a36Sopenharmony_ci	struct adapter *adap = cookie;
280662306a36Sopenharmony_ci	struct sge_qset *qs0 = &adap->sge.qs[0];
280762306a36Sopenharmony_ci	struct sge_rspq *q0 = &qs0->rspq;
280862306a36Sopenharmony_ci
280962306a36Sopenharmony_ci	t3_write_reg(adap, A_PL_CLI, 0);
281062306a36Sopenharmony_ci	map = t3_read_reg(adap, A_SG_DATA_INTR);
281162306a36Sopenharmony_ci
281262306a36Sopenharmony_ci	if (unlikely(!map))	/* shared interrupt, most likely */
281362306a36Sopenharmony_ci		return IRQ_NONE;
281462306a36Sopenharmony_ci
281562306a36Sopenharmony_ci	spin_lock(&q0->lock);
281662306a36Sopenharmony_ci
281762306a36Sopenharmony_ci	if (unlikely(map & F_ERRINTR))
281862306a36Sopenharmony_ci		t3_slow_intr_handler(adap);
281962306a36Sopenharmony_ci
282062306a36Sopenharmony_ci	if (likely(map & 1))
282162306a36Sopenharmony_ci		napi_schedule(&qs0->napi);
282262306a36Sopenharmony_ci
282362306a36Sopenharmony_ci	if (map & 2)
282462306a36Sopenharmony_ci		napi_schedule(&adap->sge.qs[1].napi);
282562306a36Sopenharmony_ci
282662306a36Sopenharmony_ci	spin_unlock(&q0->lock);
282762306a36Sopenharmony_ci	return IRQ_HANDLED;
282862306a36Sopenharmony_ci}
282962306a36Sopenharmony_ci
283062306a36Sopenharmony_ci/**
283162306a36Sopenharmony_ci *	t3_intr_handler - select the top-level interrupt handler
283262306a36Sopenharmony_ci *	@adap: the adapter
283362306a36Sopenharmony_ci *	@polling: whether using NAPI to service response queues
283462306a36Sopenharmony_ci *
283562306a36Sopenharmony_ci *	Selects the top-level interrupt handler based on the type of interrupts
283662306a36Sopenharmony_ci *	(MSI-X, MSI, or legacy) and whether NAPI will be used to service the
283762306a36Sopenharmony_ci *	response queues.
283862306a36Sopenharmony_ci */
283962306a36Sopenharmony_ciirq_handler_t t3_intr_handler(struct adapter *adap, int polling)
284062306a36Sopenharmony_ci{
284162306a36Sopenharmony_ci	if (adap->flags & USING_MSIX)
284262306a36Sopenharmony_ci		return polling ? t3_sge_intr_msix_napi : t3_sge_intr_msix;
284362306a36Sopenharmony_ci	if (adap->flags & USING_MSI)
284462306a36Sopenharmony_ci		return polling ? t3_intr_msi_napi : t3_intr_msi;
284562306a36Sopenharmony_ci	if (adap->params.rev > 0)
284662306a36Sopenharmony_ci		return polling ? t3b_intr_napi : t3b_intr;
284762306a36Sopenharmony_ci	return t3_intr;
284862306a36Sopenharmony_ci}
284962306a36Sopenharmony_ci
285062306a36Sopenharmony_ci#define SGE_PARERR (F_CPPARITYERROR | F_OCPARITYERROR | F_RCPARITYERROR | \
285162306a36Sopenharmony_ci		    F_IRPARITYERROR | V_ITPARITYERROR(M_ITPARITYERROR) | \
285262306a36Sopenharmony_ci		    V_FLPARITYERROR(M_FLPARITYERROR) | F_LODRBPARITYERROR | \
285362306a36Sopenharmony_ci		    F_HIDRBPARITYERROR | F_LORCQPARITYERROR | \
285462306a36Sopenharmony_ci		    F_HIRCQPARITYERROR)
285562306a36Sopenharmony_ci#define SGE_FRAMINGERR (F_UC_REQ_FRAMINGERROR | F_R_REQ_FRAMINGERROR)
285662306a36Sopenharmony_ci#define SGE_FATALERR (SGE_PARERR | SGE_FRAMINGERR | F_RSPQCREDITOVERFOW | \
285762306a36Sopenharmony_ci		      F_RSPQDISABLED)
285862306a36Sopenharmony_ci
285962306a36Sopenharmony_ci/**
286062306a36Sopenharmony_ci *	t3_sge_err_intr_handler - SGE async event interrupt handler
286162306a36Sopenharmony_ci *	@adapter: the adapter
286262306a36Sopenharmony_ci *
286362306a36Sopenharmony_ci *	Interrupt handler for SGE asynchronous (non-data) events.
286462306a36Sopenharmony_ci */
286562306a36Sopenharmony_civoid t3_sge_err_intr_handler(struct adapter *adapter)
286662306a36Sopenharmony_ci{
286762306a36Sopenharmony_ci	unsigned int v, status = t3_read_reg(adapter, A_SG_INT_CAUSE) &
286862306a36Sopenharmony_ci				 ~F_FLEMPTY;
286962306a36Sopenharmony_ci
287062306a36Sopenharmony_ci	if (status & SGE_PARERR)
287162306a36Sopenharmony_ci		CH_ALERT(adapter, "SGE parity error (0x%x)\n",
287262306a36Sopenharmony_ci			 status & SGE_PARERR);
287362306a36Sopenharmony_ci	if (status & SGE_FRAMINGERR)
287462306a36Sopenharmony_ci		CH_ALERT(adapter, "SGE framing error (0x%x)\n",
287562306a36Sopenharmony_ci			 status & SGE_FRAMINGERR);
287662306a36Sopenharmony_ci
287762306a36Sopenharmony_ci	if (status & F_RSPQCREDITOVERFOW)
287862306a36Sopenharmony_ci		CH_ALERT(adapter, "SGE response queue credit overflow\n");
287962306a36Sopenharmony_ci
288062306a36Sopenharmony_ci	if (status & F_RSPQDISABLED) {
288162306a36Sopenharmony_ci		v = t3_read_reg(adapter, A_SG_RSPQ_FL_STATUS);
288262306a36Sopenharmony_ci
288362306a36Sopenharmony_ci		CH_ALERT(adapter,
288462306a36Sopenharmony_ci			 "packet delivered to disabled response queue "
288562306a36Sopenharmony_ci			 "(0x%x)\n", (v >> S_RSPQ0DISABLED) & 0xff);
288662306a36Sopenharmony_ci	}
288762306a36Sopenharmony_ci
288862306a36Sopenharmony_ci	if (status & (F_HIPIODRBDROPERR | F_LOPIODRBDROPERR))
288962306a36Sopenharmony_ci		queue_work(cxgb3_wq, &adapter->db_drop_task);
289062306a36Sopenharmony_ci
289162306a36Sopenharmony_ci	if (status & (F_HIPRIORITYDBFULL | F_LOPRIORITYDBFULL))
289262306a36Sopenharmony_ci		queue_work(cxgb3_wq, &adapter->db_full_task);
289362306a36Sopenharmony_ci
289462306a36Sopenharmony_ci	if (status & (F_HIPRIORITYDBEMPTY | F_LOPRIORITYDBEMPTY))
289562306a36Sopenharmony_ci		queue_work(cxgb3_wq, &adapter->db_empty_task);
289662306a36Sopenharmony_ci
289762306a36Sopenharmony_ci	t3_write_reg(adapter, A_SG_INT_CAUSE, status);
289862306a36Sopenharmony_ci	if (status &  SGE_FATALERR)
289962306a36Sopenharmony_ci		t3_fatal_err(adapter);
290062306a36Sopenharmony_ci}
290162306a36Sopenharmony_ci
290262306a36Sopenharmony_ci/**
290362306a36Sopenharmony_ci *	sge_timer_tx - perform periodic maintenance of an SGE qset
290462306a36Sopenharmony_ci *	@t: a timer list containing the SGE queue set to maintain
290562306a36Sopenharmony_ci *
290662306a36Sopenharmony_ci *	Runs periodically from a timer to perform maintenance of an SGE queue
290762306a36Sopenharmony_ci *	set.  It performs two tasks:
290862306a36Sopenharmony_ci *
290962306a36Sopenharmony_ci *	Cleans up any completed Tx descriptors that may still be pending.
291062306a36Sopenharmony_ci *	Normal descriptor cleanup happens when new packets are added to a Tx
291162306a36Sopenharmony_ci *	queue so this timer is relatively infrequent and does any cleanup only
291262306a36Sopenharmony_ci *	if the Tx queue has not seen any new packets in a while.  We make a
291362306a36Sopenharmony_ci *	best effort attempt to reclaim descriptors, in that we don't wait
291462306a36Sopenharmony_ci *	around if we cannot get a queue's lock (which most likely is because
291562306a36Sopenharmony_ci *	someone else is queueing new packets and so will also handle the clean
291662306a36Sopenharmony_ci *	up).  Since control queues use immediate data exclusively we don't
291762306a36Sopenharmony_ci *	bother cleaning them up here.
291862306a36Sopenharmony_ci *
291962306a36Sopenharmony_ci */
292062306a36Sopenharmony_cistatic void sge_timer_tx(struct timer_list *t)
292162306a36Sopenharmony_ci{
292262306a36Sopenharmony_ci	struct sge_qset *qs = from_timer(qs, t, tx_reclaim_timer);
292362306a36Sopenharmony_ci	struct port_info *pi = netdev_priv(qs->netdev);
292462306a36Sopenharmony_ci	struct adapter *adap = pi->adapter;
292562306a36Sopenharmony_ci	unsigned int tbd[SGE_TXQ_PER_SET] = {0, 0};
292662306a36Sopenharmony_ci	unsigned long next_period;
292762306a36Sopenharmony_ci
292862306a36Sopenharmony_ci	if (__netif_tx_trylock(qs->tx_q)) {
292962306a36Sopenharmony_ci                tbd[TXQ_ETH] = reclaim_completed_tx(adap, &qs->txq[TXQ_ETH],
293062306a36Sopenharmony_ci                                                     TX_RECLAIM_TIMER_CHUNK);
293162306a36Sopenharmony_ci		__netif_tx_unlock(qs->tx_q);
293262306a36Sopenharmony_ci	}
293362306a36Sopenharmony_ci
293462306a36Sopenharmony_ci	if (spin_trylock(&qs->txq[TXQ_OFLD].lock)) {
293562306a36Sopenharmony_ci		tbd[TXQ_OFLD] = reclaim_completed_tx(adap, &qs->txq[TXQ_OFLD],
293662306a36Sopenharmony_ci						     TX_RECLAIM_TIMER_CHUNK);
293762306a36Sopenharmony_ci		spin_unlock(&qs->txq[TXQ_OFLD].lock);
293862306a36Sopenharmony_ci	}
293962306a36Sopenharmony_ci
294062306a36Sopenharmony_ci	next_period = TX_RECLAIM_PERIOD >>
294162306a36Sopenharmony_ci                      (max(tbd[TXQ_ETH], tbd[TXQ_OFLD]) /
294262306a36Sopenharmony_ci                      TX_RECLAIM_TIMER_CHUNK);
294362306a36Sopenharmony_ci	mod_timer(&qs->tx_reclaim_timer, jiffies + next_period);
294462306a36Sopenharmony_ci}
294562306a36Sopenharmony_ci
294662306a36Sopenharmony_ci/**
294762306a36Sopenharmony_ci *	sge_timer_rx - perform periodic maintenance of an SGE qset
294862306a36Sopenharmony_ci *	@t: the timer list containing the SGE queue set to maintain
294962306a36Sopenharmony_ci *
295062306a36Sopenharmony_ci *	a) Replenishes Rx queues that have run out due to memory shortage.
295162306a36Sopenharmony_ci *	Normally new Rx buffers are added when existing ones are consumed but
295262306a36Sopenharmony_ci *	when out of memory a queue can become empty.  We try to add only a few
295362306a36Sopenharmony_ci *	buffers here, the queue will be replenished fully as these new buffers
295462306a36Sopenharmony_ci *	are used up if memory shortage has subsided.
295562306a36Sopenharmony_ci *
295662306a36Sopenharmony_ci *	b) Return coalesced response queue credits in case a response queue is
295762306a36Sopenharmony_ci *	starved.
295862306a36Sopenharmony_ci *
295962306a36Sopenharmony_ci */
296062306a36Sopenharmony_cistatic void sge_timer_rx(struct timer_list *t)
296162306a36Sopenharmony_ci{
296262306a36Sopenharmony_ci	spinlock_t *lock;
296362306a36Sopenharmony_ci	struct sge_qset *qs = from_timer(qs, t, rx_reclaim_timer);
296462306a36Sopenharmony_ci	struct port_info *pi = netdev_priv(qs->netdev);
296562306a36Sopenharmony_ci	struct adapter *adap = pi->adapter;
296662306a36Sopenharmony_ci	u32 status;
296762306a36Sopenharmony_ci
296862306a36Sopenharmony_ci	lock = adap->params.rev > 0 ?
296962306a36Sopenharmony_ci	       &qs->rspq.lock : &adap->sge.qs[0].rspq.lock;
297062306a36Sopenharmony_ci
297162306a36Sopenharmony_ci	if (!spin_trylock_irq(lock))
297262306a36Sopenharmony_ci		goto out;
297362306a36Sopenharmony_ci
297462306a36Sopenharmony_ci	if (napi_is_scheduled(&qs->napi))
297562306a36Sopenharmony_ci		goto unlock;
297662306a36Sopenharmony_ci
297762306a36Sopenharmony_ci	if (adap->params.rev < 4) {
297862306a36Sopenharmony_ci		status = t3_read_reg(adap, A_SG_RSPQ_FL_STATUS);
297962306a36Sopenharmony_ci
298062306a36Sopenharmony_ci		if (status & (1 << qs->rspq.cntxt_id)) {
298162306a36Sopenharmony_ci			qs->rspq.starved++;
298262306a36Sopenharmony_ci			if (qs->rspq.credits) {
298362306a36Sopenharmony_ci				qs->rspq.credits--;
298462306a36Sopenharmony_ci				refill_rspq(adap, &qs->rspq, 1);
298562306a36Sopenharmony_ci				qs->rspq.restarted++;
298662306a36Sopenharmony_ci				t3_write_reg(adap, A_SG_RSPQ_FL_STATUS,
298762306a36Sopenharmony_ci					     1 << qs->rspq.cntxt_id);
298862306a36Sopenharmony_ci			}
298962306a36Sopenharmony_ci		}
299062306a36Sopenharmony_ci	}
299162306a36Sopenharmony_ci
299262306a36Sopenharmony_ci	if (qs->fl[0].credits < qs->fl[0].size)
299362306a36Sopenharmony_ci		__refill_fl(adap, &qs->fl[0]);
299462306a36Sopenharmony_ci	if (qs->fl[1].credits < qs->fl[1].size)
299562306a36Sopenharmony_ci		__refill_fl(adap, &qs->fl[1]);
299662306a36Sopenharmony_ci
299762306a36Sopenharmony_ciunlock:
299862306a36Sopenharmony_ci	spin_unlock_irq(lock);
299962306a36Sopenharmony_ciout:
300062306a36Sopenharmony_ci	mod_timer(&qs->rx_reclaim_timer, jiffies + RX_RECLAIM_PERIOD);
300162306a36Sopenharmony_ci}
300262306a36Sopenharmony_ci
300362306a36Sopenharmony_ci/**
300462306a36Sopenharmony_ci *	t3_update_qset_coalesce - update coalescing settings for a queue set
300562306a36Sopenharmony_ci *	@qs: the SGE queue set
300662306a36Sopenharmony_ci *	@p: new queue set parameters
300762306a36Sopenharmony_ci *
300862306a36Sopenharmony_ci *	Update the coalescing settings for an SGE queue set.  Nothing is done
300962306a36Sopenharmony_ci *	if the queue set is not initialized yet.
301062306a36Sopenharmony_ci */
301162306a36Sopenharmony_civoid t3_update_qset_coalesce(struct sge_qset *qs, const struct qset_params *p)
301262306a36Sopenharmony_ci{
301362306a36Sopenharmony_ci	qs->rspq.holdoff_tmr = max(p->coalesce_usecs * 10, 1U);/* can't be 0 */
301462306a36Sopenharmony_ci	qs->rspq.polling = p->polling;
301562306a36Sopenharmony_ci	qs->napi.poll = p->polling ? napi_rx_handler : ofld_poll;
301662306a36Sopenharmony_ci}
301762306a36Sopenharmony_ci
301862306a36Sopenharmony_ci/**
301962306a36Sopenharmony_ci *	t3_sge_alloc_qset - initialize an SGE queue set
302062306a36Sopenharmony_ci *	@adapter: the adapter
302162306a36Sopenharmony_ci *	@id: the queue set id
302262306a36Sopenharmony_ci *	@nports: how many Ethernet ports will be using this queue set
302362306a36Sopenharmony_ci *	@irq_vec_idx: the IRQ vector index for response queue interrupts
302462306a36Sopenharmony_ci *	@p: configuration parameters for this queue set
302562306a36Sopenharmony_ci *	@ntxq: number of Tx queues for the queue set
302662306a36Sopenharmony_ci *	@dev: net device associated with this queue set
302762306a36Sopenharmony_ci *	@netdevq: net device TX queue associated with this queue set
302862306a36Sopenharmony_ci *
302962306a36Sopenharmony_ci *	Allocate resources and initialize an SGE queue set.  A queue set
303062306a36Sopenharmony_ci *	comprises a response queue, two Rx free-buffer queues, and up to 3
303162306a36Sopenharmony_ci *	Tx queues.  The Tx queues are assigned roles in the order Ethernet
303262306a36Sopenharmony_ci *	queue, offload queue, and control queue.
303362306a36Sopenharmony_ci */
303462306a36Sopenharmony_ciint t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports,
303562306a36Sopenharmony_ci		      int irq_vec_idx, const struct qset_params *p,
303662306a36Sopenharmony_ci		      int ntxq, struct net_device *dev,
303762306a36Sopenharmony_ci		      struct netdev_queue *netdevq)
303862306a36Sopenharmony_ci{
303962306a36Sopenharmony_ci	int i, avail, ret = -ENOMEM;
304062306a36Sopenharmony_ci	struct sge_qset *q = &adapter->sge.qs[id];
304162306a36Sopenharmony_ci
304262306a36Sopenharmony_ci	init_qset_cntxt(q, id);
304362306a36Sopenharmony_ci	timer_setup(&q->tx_reclaim_timer, sge_timer_tx, 0);
304462306a36Sopenharmony_ci	timer_setup(&q->rx_reclaim_timer, sge_timer_rx, 0);
304562306a36Sopenharmony_ci
304662306a36Sopenharmony_ci	q->fl[0].desc = alloc_ring(adapter->pdev, p->fl_size,
304762306a36Sopenharmony_ci				   sizeof(struct rx_desc),
304862306a36Sopenharmony_ci				   sizeof(struct rx_sw_desc),
304962306a36Sopenharmony_ci				   &q->fl[0].phys_addr, &q->fl[0].sdesc);
305062306a36Sopenharmony_ci	if (!q->fl[0].desc)
305162306a36Sopenharmony_ci		goto err;
305262306a36Sopenharmony_ci
305362306a36Sopenharmony_ci	q->fl[1].desc = alloc_ring(adapter->pdev, p->jumbo_size,
305462306a36Sopenharmony_ci				   sizeof(struct rx_desc),
305562306a36Sopenharmony_ci				   sizeof(struct rx_sw_desc),
305662306a36Sopenharmony_ci				   &q->fl[1].phys_addr, &q->fl[1].sdesc);
305762306a36Sopenharmony_ci	if (!q->fl[1].desc)
305862306a36Sopenharmony_ci		goto err;
305962306a36Sopenharmony_ci
306062306a36Sopenharmony_ci	q->rspq.desc = alloc_ring(adapter->pdev, p->rspq_size,
306162306a36Sopenharmony_ci				  sizeof(struct rsp_desc), 0,
306262306a36Sopenharmony_ci				  &q->rspq.phys_addr, NULL);
306362306a36Sopenharmony_ci	if (!q->rspq.desc)
306462306a36Sopenharmony_ci		goto err;
306562306a36Sopenharmony_ci
306662306a36Sopenharmony_ci	for (i = 0; i < ntxq; ++i) {
306762306a36Sopenharmony_ci		/*
306862306a36Sopenharmony_ci		 * The control queue always uses immediate data so does not
306962306a36Sopenharmony_ci		 * need to keep track of any sk_buffs.
307062306a36Sopenharmony_ci		 */
307162306a36Sopenharmony_ci		size_t sz = i == TXQ_CTRL ? 0 : sizeof(struct tx_sw_desc);
307262306a36Sopenharmony_ci
307362306a36Sopenharmony_ci		q->txq[i].desc = alloc_ring(adapter->pdev, p->txq_size[i],
307462306a36Sopenharmony_ci					    sizeof(struct tx_desc), sz,
307562306a36Sopenharmony_ci					    &q->txq[i].phys_addr,
307662306a36Sopenharmony_ci					    &q->txq[i].sdesc);
307762306a36Sopenharmony_ci		if (!q->txq[i].desc)
307862306a36Sopenharmony_ci			goto err;
307962306a36Sopenharmony_ci
308062306a36Sopenharmony_ci		q->txq[i].gen = 1;
308162306a36Sopenharmony_ci		q->txq[i].size = p->txq_size[i];
308262306a36Sopenharmony_ci		spin_lock_init(&q->txq[i].lock);
308362306a36Sopenharmony_ci		skb_queue_head_init(&q->txq[i].sendq);
308462306a36Sopenharmony_ci	}
308562306a36Sopenharmony_ci
308662306a36Sopenharmony_ci	INIT_WORK(&q->txq[TXQ_OFLD].qresume_task, restart_offloadq);
308762306a36Sopenharmony_ci	INIT_WORK(&q->txq[TXQ_CTRL].qresume_task, restart_ctrlq);
308862306a36Sopenharmony_ci
308962306a36Sopenharmony_ci	q->fl[0].gen = q->fl[1].gen = 1;
309062306a36Sopenharmony_ci	q->fl[0].size = p->fl_size;
309162306a36Sopenharmony_ci	q->fl[1].size = p->jumbo_size;
309262306a36Sopenharmony_ci
309362306a36Sopenharmony_ci	q->rspq.gen = 1;
309462306a36Sopenharmony_ci	q->rspq.size = p->rspq_size;
309562306a36Sopenharmony_ci	spin_lock_init(&q->rspq.lock);
309662306a36Sopenharmony_ci	skb_queue_head_init(&q->rspq.rx_queue);
309762306a36Sopenharmony_ci
309862306a36Sopenharmony_ci	q->txq[TXQ_ETH].stop_thres = nports *
309962306a36Sopenharmony_ci	    flits_to_desc(sgl_len(MAX_SKB_FRAGS + 1) + 3);
310062306a36Sopenharmony_ci
310162306a36Sopenharmony_ci#if FL0_PG_CHUNK_SIZE > 0
310262306a36Sopenharmony_ci	q->fl[0].buf_size = FL0_PG_CHUNK_SIZE;
310362306a36Sopenharmony_ci#else
310462306a36Sopenharmony_ci	q->fl[0].buf_size = SGE_RX_SM_BUF_SIZE + sizeof(struct cpl_rx_data);
310562306a36Sopenharmony_ci#endif
310662306a36Sopenharmony_ci#if FL1_PG_CHUNK_SIZE > 0
310762306a36Sopenharmony_ci	q->fl[1].buf_size = FL1_PG_CHUNK_SIZE;
310862306a36Sopenharmony_ci#else
310962306a36Sopenharmony_ci	q->fl[1].buf_size = is_offload(adapter) ?
311062306a36Sopenharmony_ci		(16 * 1024) - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) :
311162306a36Sopenharmony_ci		MAX_FRAME_SIZE + 2 + sizeof(struct cpl_rx_pkt);
311262306a36Sopenharmony_ci#endif
311362306a36Sopenharmony_ci
311462306a36Sopenharmony_ci	q->fl[0].use_pages = FL0_PG_CHUNK_SIZE > 0;
311562306a36Sopenharmony_ci	q->fl[1].use_pages = FL1_PG_CHUNK_SIZE > 0;
311662306a36Sopenharmony_ci	q->fl[0].order = FL0_PG_ORDER;
311762306a36Sopenharmony_ci	q->fl[1].order = FL1_PG_ORDER;
311862306a36Sopenharmony_ci	q->fl[0].alloc_size = FL0_PG_ALLOC_SIZE;
311962306a36Sopenharmony_ci	q->fl[1].alloc_size = FL1_PG_ALLOC_SIZE;
312062306a36Sopenharmony_ci
312162306a36Sopenharmony_ci	spin_lock_irq(&adapter->sge.reg_lock);
312262306a36Sopenharmony_ci
312362306a36Sopenharmony_ci	/* FL threshold comparison uses < */
312462306a36Sopenharmony_ci	ret = t3_sge_init_rspcntxt(adapter, q->rspq.cntxt_id, irq_vec_idx,
312562306a36Sopenharmony_ci				   q->rspq.phys_addr, q->rspq.size,
312662306a36Sopenharmony_ci				   q->fl[0].buf_size - SGE_PG_RSVD, 1, 0);
312762306a36Sopenharmony_ci	if (ret)
312862306a36Sopenharmony_ci		goto err_unlock;
312962306a36Sopenharmony_ci
313062306a36Sopenharmony_ci	for (i = 0; i < SGE_RXQ_PER_SET; ++i) {
313162306a36Sopenharmony_ci		ret = t3_sge_init_flcntxt(adapter, q->fl[i].cntxt_id, 0,
313262306a36Sopenharmony_ci					  q->fl[i].phys_addr, q->fl[i].size,
313362306a36Sopenharmony_ci					  q->fl[i].buf_size - SGE_PG_RSVD,
313462306a36Sopenharmony_ci					  p->cong_thres, 1, 0);
313562306a36Sopenharmony_ci		if (ret)
313662306a36Sopenharmony_ci			goto err_unlock;
313762306a36Sopenharmony_ci	}
313862306a36Sopenharmony_ci
313962306a36Sopenharmony_ci	ret = t3_sge_init_ecntxt(adapter, q->txq[TXQ_ETH].cntxt_id, USE_GTS,
314062306a36Sopenharmony_ci				 SGE_CNTXT_ETH, id, q->txq[TXQ_ETH].phys_addr,
314162306a36Sopenharmony_ci				 q->txq[TXQ_ETH].size, q->txq[TXQ_ETH].token,
314262306a36Sopenharmony_ci				 1, 0);
314362306a36Sopenharmony_ci	if (ret)
314462306a36Sopenharmony_ci		goto err_unlock;
314562306a36Sopenharmony_ci
314662306a36Sopenharmony_ci	if (ntxq > 1) {
314762306a36Sopenharmony_ci		ret = t3_sge_init_ecntxt(adapter, q->txq[TXQ_OFLD].cntxt_id,
314862306a36Sopenharmony_ci					 USE_GTS, SGE_CNTXT_OFLD, id,
314962306a36Sopenharmony_ci					 q->txq[TXQ_OFLD].phys_addr,
315062306a36Sopenharmony_ci					 q->txq[TXQ_OFLD].size, 0, 1, 0);
315162306a36Sopenharmony_ci		if (ret)
315262306a36Sopenharmony_ci			goto err_unlock;
315362306a36Sopenharmony_ci	}
315462306a36Sopenharmony_ci
315562306a36Sopenharmony_ci	if (ntxq > 2) {
315662306a36Sopenharmony_ci		ret = t3_sge_init_ecntxt(adapter, q->txq[TXQ_CTRL].cntxt_id, 0,
315762306a36Sopenharmony_ci					 SGE_CNTXT_CTRL, id,
315862306a36Sopenharmony_ci					 q->txq[TXQ_CTRL].phys_addr,
315962306a36Sopenharmony_ci					 q->txq[TXQ_CTRL].size,
316062306a36Sopenharmony_ci					 q->txq[TXQ_CTRL].token, 1, 0);
316162306a36Sopenharmony_ci		if (ret)
316262306a36Sopenharmony_ci			goto err_unlock;
316362306a36Sopenharmony_ci	}
316462306a36Sopenharmony_ci
316562306a36Sopenharmony_ci	spin_unlock_irq(&adapter->sge.reg_lock);
316662306a36Sopenharmony_ci
316762306a36Sopenharmony_ci	q->adap = adapter;
316862306a36Sopenharmony_ci	q->netdev = dev;
316962306a36Sopenharmony_ci	q->tx_q = netdevq;
317062306a36Sopenharmony_ci	t3_update_qset_coalesce(q, p);
317162306a36Sopenharmony_ci
317262306a36Sopenharmony_ci	avail = refill_fl(adapter, &q->fl[0], q->fl[0].size,
317362306a36Sopenharmony_ci			  GFP_KERNEL | __GFP_COMP);
317462306a36Sopenharmony_ci	if (!avail) {
317562306a36Sopenharmony_ci		CH_ALERT(adapter, "free list queue 0 initialization failed\n");
317662306a36Sopenharmony_ci		ret = -ENOMEM;
317762306a36Sopenharmony_ci		goto err;
317862306a36Sopenharmony_ci	}
317962306a36Sopenharmony_ci	if (avail < q->fl[0].size)
318062306a36Sopenharmony_ci		CH_WARN(adapter, "free list queue 0 enabled with %d credits\n",
318162306a36Sopenharmony_ci			avail);
318262306a36Sopenharmony_ci
318362306a36Sopenharmony_ci	avail = refill_fl(adapter, &q->fl[1], q->fl[1].size,
318462306a36Sopenharmony_ci			  GFP_KERNEL | __GFP_COMP);
318562306a36Sopenharmony_ci	if (avail < q->fl[1].size)
318662306a36Sopenharmony_ci		CH_WARN(adapter, "free list queue 1 enabled with %d credits\n",
318762306a36Sopenharmony_ci			avail);
318862306a36Sopenharmony_ci	refill_rspq(adapter, &q->rspq, q->rspq.size - 1);
318962306a36Sopenharmony_ci
319062306a36Sopenharmony_ci	t3_write_reg(adapter, A_SG_GTS, V_RSPQ(q->rspq.cntxt_id) |
319162306a36Sopenharmony_ci		     V_NEWTIMER(q->rspq.holdoff_tmr));
319262306a36Sopenharmony_ci
319362306a36Sopenharmony_ci	return 0;
319462306a36Sopenharmony_ci
319562306a36Sopenharmony_cierr_unlock:
319662306a36Sopenharmony_ci	spin_unlock_irq(&adapter->sge.reg_lock);
319762306a36Sopenharmony_cierr:
319862306a36Sopenharmony_ci	t3_free_qset(adapter, q);
319962306a36Sopenharmony_ci	return ret;
320062306a36Sopenharmony_ci}
320162306a36Sopenharmony_ci
320262306a36Sopenharmony_ci/**
320362306a36Sopenharmony_ci *      t3_start_sge_timers - start SGE timer call backs
320462306a36Sopenharmony_ci *      @adap: the adapter
320562306a36Sopenharmony_ci *
320662306a36Sopenharmony_ci *      Starts each SGE queue set's timer call back
320762306a36Sopenharmony_ci */
320862306a36Sopenharmony_civoid t3_start_sge_timers(struct adapter *adap)
320962306a36Sopenharmony_ci{
321062306a36Sopenharmony_ci	int i;
321162306a36Sopenharmony_ci
321262306a36Sopenharmony_ci	for (i = 0; i < SGE_QSETS; ++i) {
321362306a36Sopenharmony_ci		struct sge_qset *q = &adap->sge.qs[i];
321462306a36Sopenharmony_ci
321562306a36Sopenharmony_ci		if (q->tx_reclaim_timer.function)
321662306a36Sopenharmony_ci			mod_timer(&q->tx_reclaim_timer,
321762306a36Sopenharmony_ci				  jiffies + TX_RECLAIM_PERIOD);
321862306a36Sopenharmony_ci
321962306a36Sopenharmony_ci		if (q->rx_reclaim_timer.function)
322062306a36Sopenharmony_ci			mod_timer(&q->rx_reclaim_timer,
322162306a36Sopenharmony_ci				  jiffies + RX_RECLAIM_PERIOD);
322262306a36Sopenharmony_ci	}
322362306a36Sopenharmony_ci}
322462306a36Sopenharmony_ci
322562306a36Sopenharmony_ci/**
322662306a36Sopenharmony_ci *	t3_stop_sge_timers - stop SGE timer call backs
322762306a36Sopenharmony_ci *	@adap: the adapter
322862306a36Sopenharmony_ci *
322962306a36Sopenharmony_ci *	Stops each SGE queue set's timer call back
323062306a36Sopenharmony_ci */
323162306a36Sopenharmony_civoid t3_stop_sge_timers(struct adapter *adap)
323262306a36Sopenharmony_ci{
323362306a36Sopenharmony_ci	int i;
323462306a36Sopenharmony_ci
323562306a36Sopenharmony_ci	for (i = 0; i < SGE_QSETS; ++i) {
323662306a36Sopenharmony_ci		struct sge_qset *q = &adap->sge.qs[i];
323762306a36Sopenharmony_ci
323862306a36Sopenharmony_ci		if (q->tx_reclaim_timer.function)
323962306a36Sopenharmony_ci			del_timer_sync(&q->tx_reclaim_timer);
324062306a36Sopenharmony_ci		if (q->rx_reclaim_timer.function)
324162306a36Sopenharmony_ci			del_timer_sync(&q->rx_reclaim_timer);
324262306a36Sopenharmony_ci	}
324362306a36Sopenharmony_ci}
324462306a36Sopenharmony_ci
324562306a36Sopenharmony_ci/**
324662306a36Sopenharmony_ci *	t3_free_sge_resources - free SGE resources
324762306a36Sopenharmony_ci *	@adap: the adapter
324862306a36Sopenharmony_ci *
324962306a36Sopenharmony_ci *	Frees resources used by the SGE queue sets.
325062306a36Sopenharmony_ci */
325162306a36Sopenharmony_civoid t3_free_sge_resources(struct adapter *adap)
325262306a36Sopenharmony_ci{
325362306a36Sopenharmony_ci	int i;
325462306a36Sopenharmony_ci
325562306a36Sopenharmony_ci	for (i = 0; i < SGE_QSETS; ++i)
325662306a36Sopenharmony_ci		t3_free_qset(adap, &adap->sge.qs[i]);
325762306a36Sopenharmony_ci}
325862306a36Sopenharmony_ci
325962306a36Sopenharmony_ci/**
326062306a36Sopenharmony_ci *	t3_sge_start - enable SGE
326162306a36Sopenharmony_ci *	@adap: the adapter
326262306a36Sopenharmony_ci *
326362306a36Sopenharmony_ci *	Enables the SGE for DMAs.  This is the last step in starting packet
326462306a36Sopenharmony_ci *	transfers.
326562306a36Sopenharmony_ci */
326662306a36Sopenharmony_civoid t3_sge_start(struct adapter *adap)
326762306a36Sopenharmony_ci{
326862306a36Sopenharmony_ci	t3_set_reg_field(adap, A_SG_CONTROL, F_GLOBALENABLE, F_GLOBALENABLE);
326962306a36Sopenharmony_ci}
327062306a36Sopenharmony_ci
327162306a36Sopenharmony_ci/**
327262306a36Sopenharmony_ci *	t3_sge_stop_dma - Disable SGE DMA engine operation
327362306a36Sopenharmony_ci *	@adap: the adapter
327462306a36Sopenharmony_ci *
327562306a36Sopenharmony_ci *	Can be invoked from interrupt context e.g.  error handler.
327662306a36Sopenharmony_ci *
327762306a36Sopenharmony_ci *	Note that this function cannot disable the restart of works as
327862306a36Sopenharmony_ci *	it cannot wait if called from interrupt context, however the
327962306a36Sopenharmony_ci *	works will have no effect since the doorbells are disabled. The
328062306a36Sopenharmony_ci *	driver will call tg3_sge_stop() later from process context, at
328162306a36Sopenharmony_ci *	which time the works will be stopped if they are still running.
328262306a36Sopenharmony_ci */
328362306a36Sopenharmony_civoid t3_sge_stop_dma(struct adapter *adap)
328462306a36Sopenharmony_ci{
328562306a36Sopenharmony_ci	t3_set_reg_field(adap, A_SG_CONTROL, F_GLOBALENABLE, 0);
328662306a36Sopenharmony_ci}
328762306a36Sopenharmony_ci
328862306a36Sopenharmony_ci/**
328962306a36Sopenharmony_ci *	t3_sge_stop - disable SGE operation completly
329062306a36Sopenharmony_ci *	@adap: the adapter
329162306a36Sopenharmony_ci *
329262306a36Sopenharmony_ci *	Called from process context. Disables the DMA engine and any
329362306a36Sopenharmony_ci *	pending queue restart works.
329462306a36Sopenharmony_ci */
329562306a36Sopenharmony_civoid t3_sge_stop(struct adapter *adap)
329662306a36Sopenharmony_ci{
329762306a36Sopenharmony_ci	int i;
329862306a36Sopenharmony_ci
329962306a36Sopenharmony_ci	t3_sge_stop_dma(adap);
330062306a36Sopenharmony_ci
330162306a36Sopenharmony_ci	/* workqueues aren't initialized otherwise */
330262306a36Sopenharmony_ci	if (!(adap->flags & FULL_INIT_DONE))
330362306a36Sopenharmony_ci		return;
330462306a36Sopenharmony_ci	for (i = 0; i < SGE_QSETS; ++i) {
330562306a36Sopenharmony_ci		struct sge_qset *qs = &adap->sge.qs[i];
330662306a36Sopenharmony_ci
330762306a36Sopenharmony_ci		cancel_work_sync(&qs->txq[TXQ_OFLD].qresume_task);
330862306a36Sopenharmony_ci		cancel_work_sync(&qs->txq[TXQ_CTRL].qresume_task);
330962306a36Sopenharmony_ci	}
331062306a36Sopenharmony_ci}
331162306a36Sopenharmony_ci
331262306a36Sopenharmony_ci/**
331362306a36Sopenharmony_ci *	t3_sge_init - initialize SGE
331462306a36Sopenharmony_ci *	@adap: the adapter
331562306a36Sopenharmony_ci *	@p: the SGE parameters
331662306a36Sopenharmony_ci *
331762306a36Sopenharmony_ci *	Performs SGE initialization needed every time after a chip reset.
331862306a36Sopenharmony_ci *	We do not initialize any of the queue sets here, instead the driver
331962306a36Sopenharmony_ci *	top-level must request those individually.  We also do not enable DMA
332062306a36Sopenharmony_ci *	here, that should be done after the queues have been set up.
332162306a36Sopenharmony_ci */
332262306a36Sopenharmony_civoid t3_sge_init(struct adapter *adap, struct sge_params *p)
332362306a36Sopenharmony_ci{
332462306a36Sopenharmony_ci	unsigned int ctrl, ups = ffs(pci_resource_len(adap->pdev, 2) >> 12);
332562306a36Sopenharmony_ci
332662306a36Sopenharmony_ci	ctrl = F_DROPPKT | V_PKTSHIFT(2) | F_FLMODE | F_AVOIDCQOVFL |
332762306a36Sopenharmony_ci	    F_CQCRDTCTRL | F_CONGMODE | F_TNLFLMODE | F_FATLPERREN |
332862306a36Sopenharmony_ci	    V_HOSTPAGESIZE(PAGE_SHIFT - 11) | F_BIGENDIANINGRESS |
332962306a36Sopenharmony_ci	    V_USERSPACESIZE(ups ? ups - 1 : 0) | F_ISCSICOALESCING;
333062306a36Sopenharmony_ci#if SGE_NUM_GENBITS == 1
333162306a36Sopenharmony_ci	ctrl |= F_EGRGENCTRL;
333262306a36Sopenharmony_ci#endif
333362306a36Sopenharmony_ci	if (adap->params.rev > 0) {
333462306a36Sopenharmony_ci		if (!(adap->flags & (USING_MSIX | USING_MSI)))
333562306a36Sopenharmony_ci			ctrl |= F_ONEINTMULTQ | F_OPTONEINTMULTQ;
333662306a36Sopenharmony_ci	}
333762306a36Sopenharmony_ci	t3_write_reg(adap, A_SG_CONTROL, ctrl);
333862306a36Sopenharmony_ci	t3_write_reg(adap, A_SG_EGR_RCQ_DRB_THRSH, V_HIRCQDRBTHRSH(512) |
333962306a36Sopenharmony_ci		     V_LORCQDRBTHRSH(512));
334062306a36Sopenharmony_ci	t3_write_reg(adap, A_SG_TIMER_TICK, core_ticks_per_usec(adap) / 10);
334162306a36Sopenharmony_ci	t3_write_reg(adap, A_SG_CMDQ_CREDIT_TH, V_THRESHOLD(32) |
334262306a36Sopenharmony_ci		     V_TIMEOUT(200 * core_ticks_per_usec(adap)));
334362306a36Sopenharmony_ci	t3_write_reg(adap, A_SG_HI_DRB_HI_THRSH,
334462306a36Sopenharmony_ci		     adap->params.rev < T3_REV_C ? 1000 : 500);
334562306a36Sopenharmony_ci	t3_write_reg(adap, A_SG_HI_DRB_LO_THRSH, 256);
334662306a36Sopenharmony_ci	t3_write_reg(adap, A_SG_LO_DRB_HI_THRSH, 1000);
334762306a36Sopenharmony_ci	t3_write_reg(adap, A_SG_LO_DRB_LO_THRSH, 256);
334862306a36Sopenharmony_ci	t3_write_reg(adap, A_SG_OCO_BASE, V_BASE1(0xfff));
334962306a36Sopenharmony_ci	t3_write_reg(adap, A_SG_DRB_PRI_THRESH, 63 * 1024);
335062306a36Sopenharmony_ci}
335162306a36Sopenharmony_ci
335262306a36Sopenharmony_ci/**
335362306a36Sopenharmony_ci *	t3_sge_prep - one-time SGE initialization
335462306a36Sopenharmony_ci *	@adap: the associated adapter
335562306a36Sopenharmony_ci *	@p: SGE parameters
335662306a36Sopenharmony_ci *
335762306a36Sopenharmony_ci *	Performs one-time initialization of SGE SW state.  Includes determining
335862306a36Sopenharmony_ci *	defaults for the assorted SGE parameters, which admins can change until
335962306a36Sopenharmony_ci *	they are used to initialize the SGE.
336062306a36Sopenharmony_ci */
336162306a36Sopenharmony_civoid t3_sge_prep(struct adapter *adap, struct sge_params *p)
336262306a36Sopenharmony_ci{
336362306a36Sopenharmony_ci	int i;
336462306a36Sopenharmony_ci
336562306a36Sopenharmony_ci	p->max_pkt_size = (16 * 1024) - sizeof(struct cpl_rx_data) -
336662306a36Sopenharmony_ci	    SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
336762306a36Sopenharmony_ci
336862306a36Sopenharmony_ci	for (i = 0; i < SGE_QSETS; ++i) {
336962306a36Sopenharmony_ci		struct qset_params *q = p->qset + i;
337062306a36Sopenharmony_ci
337162306a36Sopenharmony_ci		q->polling = adap->params.rev > 0;
337262306a36Sopenharmony_ci		q->coalesce_usecs = 5;
337362306a36Sopenharmony_ci		q->rspq_size = 1024;
337462306a36Sopenharmony_ci		q->fl_size = 1024;
337562306a36Sopenharmony_ci		q->jumbo_size = 512;
337662306a36Sopenharmony_ci		q->txq_size[TXQ_ETH] = 1024;
337762306a36Sopenharmony_ci		q->txq_size[TXQ_OFLD] = 1024;
337862306a36Sopenharmony_ci		q->txq_size[TXQ_CTRL] = 256;
337962306a36Sopenharmony_ci		q->cong_thres = 0;
338062306a36Sopenharmony_ci	}
338162306a36Sopenharmony_ci
338262306a36Sopenharmony_ci	spin_lock_init(&adap->sge.reg_lock);
338362306a36Sopenharmony_ci}
3384