Newer
Older
* Copyright (c) 2005-2008 Chelsio, Inc. All rights reserved.
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/if_vlan.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/prefetch.h>
#include "common.h"
#include "regs.h"
#include "sge_defs.h"
#include "t3_cpl.h"
#include "firmware_exports.h"
#include "cxgb3_offload.h"
#define USE_GTS 0
#define SGE_RX_SM_BUF_SIZE 1536
#define SGE_RX_COPY_THRES 256
#define SGE_PG_RSVD SMP_CACHE_BYTES
* Page chunk size for FL0 buffers if FL0 is to be populated with page chunks.
* It must be a divisor of PAGE_SIZE. If set to 0 FL0 will use sk_buffs
* directly.
#define FL0_PG_ALLOC_SIZE (PAGE_SIZE << FL0_PG_ORDER)
#define FL1_PG_CHUNK_SIZE (PAGE_SIZE > 8192 ? 16384 : 8192)
#define FL1_PG_ORDER (PAGE_SIZE > 8192 ? 0 : 1)
#define FL1_PG_ALLOC_SIZE (PAGE_SIZE << FL1_PG_ORDER)
#define RX_RECLAIM_PERIOD (HZ/4)
/*
* Max number of Rx buffers we replenish at a time.
*/
#define MAX_RX_REFILL 16U
/*
* Period of the Tx buffer reclaim timer. This timer does not need to run
* frequently as Tx buffers are usually reclaimed by new Tx packets.
*/
#define TX_RECLAIM_PERIOD (HZ / 4)
#define TX_RECLAIM_TIMER_CHUNK 64U
#define TX_RECLAIM_CHUNK 16U
/* WR size in bytes */
#define WR_LEN (WR_FLITS * 8)
/*
* Types of Tx queues in each queue set. Order here matters, do not change.
*/
enum { TXQ_ETH, TXQ_OFLD, TXQ_CTRL };
/* Values for sge_txq.flags */
enum {
TXQ_RUNNING = 1 << 0, /* fetch engine is running */
TXQ_LAST_PKT_DB = 1 << 1, /* last packet rang the doorbell */
};
struct tx_desc {
};
struct rx_desc {
__be32 addr_lo;
__be32 len_gen;
__be32 gen2;
__be32 addr_hi;
};
struct tx_sw_desc { /* SW state per Tx descriptor */
struct sk_buff *skb;
u8 eop; /* set if last descriptor for packet */
u8 addr_idx; /* buffer index of first SGL entry in descriptor */
u8 fragidx; /* first page fragment associated with descriptor */
s8 sflit; /* start flit of first SGL entry in descriptor */
struct rx_sw_desc { /* SW state per Rx descriptor */
DEFINE_DMA_UNMAP_ADDR(dma_addr);
};
struct rsp_desc { /* response queue descriptor */
struct rss_header rss_hdr;
__be32 flags;
__be32 len_cq;
u8 imm_data[47];
u8 intr_gen;
};
/*
* Holds unmapping information for Tx packets that need deferred unmapping.
* This structure lives at skb->head and must be allocated by callers.
*/
struct deferred_unmap_info {
struct pci_dev *pdev;
dma_addr_t addr[MAX_SKB_FRAGS + 1];
};
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
/*
* Maps a number of flits to the number of Tx descriptors that can hold them.
* The formula is
*
* desc = 1 + (flits - 2) / (WR_FLITS - 1).
*
* HW allows up to 4 descriptors to be combined into a WR.
*/
static u8 flit_desc_map[] = {
0,
#if SGE_NUM_GENBITS == 1
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
#elif SGE_NUM_GENBITS == 2
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
#else
# error "SGE_NUM_GENBITS must be 1 or 2"
#endif
};
static inline struct sge_qset *fl_to_qset(const struct sge_fl *q, int qidx)
{
return container_of(q, struct sge_qset, fl[qidx]);
}
static inline struct sge_qset *rspq_to_qset(const struct sge_rspq *q)
{
return container_of(q, struct sge_qset, rspq);
}
static inline struct sge_qset *txq_to_qset(const struct sge_txq *q, int qidx)
{
return container_of(q, struct sge_qset, txq[qidx]);
}
/**
* refill_rspq - replenish an SGE response queue
* @adapter: the adapter
* @q: the response queue to replenish
* @credits: how many new responses to make available
*
* Replenishes a response queue by making the supplied number of responses
* available to HW.
*/
static inline void refill_rspq(struct adapter *adapter,
const struct sge_rspq *q, unsigned int credits)
{
t3_write_reg(adapter, A_SG_RSPQ_CREDIT_RETURN,
V_RSPQ(q->cntxt_id) | V_CREDITS(credits));
}
/**
* need_skb_unmap - does the platform need unmapping of sk_buffs?
*
* Returns true if the platform needs sk_buff unmapping. The compiler
* optimizes away unnecessary code if this returns true.
*/
static inline int need_skb_unmap(void)
{
#ifdef CONFIG_NEED_DMA_MAP_STATE
return 1;
#else
return 0;
#endif
}
/**
* unmap_skb - unmap a packet main body and its page fragments
* @skb: the packet
* @q: the Tx queue containing Tx descriptors for the packet
* @cidx: index of Tx descriptor
* @pdev: the PCI device
*
* Unmap the main body of an sk_buff and its page fragments, if any.
* Because of the fairly complicated structure of our SGLs and the desire
* to conserve space for metadata, the information necessary to unmap an
* sk_buff is spread across the sk_buff itself (buffer lengths), the HW Tx
* descriptors (the physical addresses of the various data buffers), and
* the SW descriptor state (assorted indices). The send functions
* initialize the indices for the first packet descriptor so we can unmap
* the buffers held in the first Tx descriptor here, and we have enough
* information at this point to set the state for the next Tx descriptor.
*
* Note that it is possible to clean up the first descriptor of a packet
* before the send routines have written the next descriptors, but this
* race does not cause any problem. We just end up writing the unmapping
* info for the descriptor first.
*/
static inline void unmap_skb(struct sk_buff *skb, struct sge_txq *q,
unsigned int cidx, struct pci_dev *pdev)
{
const struct sg_ent *sgp;
struct tx_sw_desc *d = &q->sdesc[cidx];
int nfrags, frag_idx, curflit, j = d->addr_idx;
sgp = (struct sg_ent *)&q->desc[cidx].flit[d->sflit];
frag_idx = d->fragidx;
if (frag_idx == 0 && skb_headlen(skb)) {
pci_unmap_single(pdev, be64_to_cpu(sgp->addr[0]),
skb_headlen(skb), PCI_DMA_TODEVICE);
nfrags = skb_shinfo(skb)->nr_frags;
while (frag_idx < nfrags && curflit < WR_FLITS) {
pci_unmap_page(pdev, be64_to_cpu(sgp->addr[j]),
skb_shinfo(skb)->frags[frag_idx].size,
PCI_DMA_TODEVICE);
j ^= 1;
if (j == 0) {
sgp++;
curflit++;
}
curflit++;
frag_idx++;
}
if (frag_idx < nfrags) { /* SGL continues into next Tx descriptor */
d = cidx + 1 == q->size ? q->sdesc : d + 1;
d->fragidx = frag_idx;
d->addr_idx = j;
d->sflit = curflit - WR_FLITS - j; /* sflit can be -1 */
}
}
/**
* free_tx_desc - reclaims Tx descriptors and their buffers
* @adapter: the adapter
* @q: the Tx queue to reclaim descriptors from
* @n: the number of descriptors to reclaim
*
* Reclaims Tx descriptors from an SGE Tx queue and frees the associated
* Tx buffers. Called with the Tx queue lock held.
*/
static void free_tx_desc(struct adapter *adapter, struct sge_txq *q,
unsigned int n)
{
struct tx_sw_desc *d;
struct pci_dev *pdev = adapter->pdev;
unsigned int cidx = q->cidx;
const int need_unmap = need_skb_unmap() &&
q->cntxt_id >= FW_TUNNEL_SGEEC_START;
d = &q->sdesc[cidx];
while (n--) {
if (d->skb) { /* an SGL is present */
unmap_skb(d->skb, q, cidx, pdev);
}
++d;
if (++cidx == q->size) {
cidx = 0;
d = q->sdesc;
}
}
q->cidx = cidx;
}
/**
* reclaim_completed_tx - reclaims completed Tx descriptors
* @adapter: the adapter
* @q: the Tx queue to reclaim completed descriptors from
* @chunk: maximum number of descriptors to reclaim
*
* Reclaims Tx descriptors that the SGE has indicated it has processed,
* and frees the associated buffers if possible. Called with the Tx
* queue's lock held.
*/
static inline unsigned int reclaim_completed_tx(struct adapter *adapter,
struct sge_txq *q,
unsigned int chunk)
{
unsigned int reclaim = q->processed - q->cleaned;
if (reclaim) {
free_tx_desc(adapter, q, reclaim);
q->cleaned += reclaim;
q->in_use -= reclaim;
}
return q->processed - q->cleaned;
}
/**
* should_restart_tx - are there enough resources to restart a Tx queue?
* @q: the Tx queue
*
* Checks if there are enough descriptors to restart a suspended Tx queue.
*/
static inline int should_restart_tx(const struct sge_txq *q)
{
unsigned int r = q->processed - q->cleaned;
return q->in_use - r < (q->size >> 1);
}
static void clear_rx_desc(struct pci_dev *pdev, const struct sge_fl *q,
struct rx_sw_desc *d)
if (q->use_pages && d->pg_chunk.page) {
(*d->pg_chunk.p_cnt)--;
if (!*d->pg_chunk.p_cnt)
pci_unmap_page(pdev,
q->alloc_size, PCI_DMA_FROMDEVICE);
put_page(d->pg_chunk.page);
d->pg_chunk.page = NULL;
} else {
pci_unmap_single(pdev, dma_unmap_addr(d, dma_addr),
q->buf_size, PCI_DMA_FROMDEVICE);
kfree_skb(d->skb);
d->skb = NULL;
}
}
/**
* free_rx_bufs - free the Rx buffers on an SGE free list
* @pdev: the PCI device associated with the adapter
* @rxq: the SGE free list to clean up
*
* Release the buffers on an SGE free-buffer Rx queue. HW fetching from
* this queue should be stopped before calling this function.
*/
static void free_rx_bufs(struct pci_dev *pdev, struct sge_fl *q)
{
unsigned int cidx = q->cidx;
while (q->credits--) {
struct rx_sw_desc *d = &q->sdesc[cidx];
clear_rx_desc(pdev, q, d);
if (++cidx == q->size)
cidx = 0;
}
__free_pages(q->pg_chunk.page, q->order);
}
/**
* add_one_rx_buf - add a packet buffer to a free-buffer list
* @len: the buffer length
* @d: the HW Rx descriptor to write
* @sd: the SW Rx descriptor to write
* @gen: the generation bit value
* @pdev: the PCI device associated with the adapter
*
* Add a buffer of the given length to the supplied HW and SW Rx
* descriptors.
*/
static inline int add_one_rx_buf(void *va, unsigned int len,
struct rx_desc *d, struct rx_sw_desc *sd,
unsigned int gen, struct pci_dev *pdev)
{
dma_addr_t mapping;
mapping = pci_map_single(pdev, va, len, PCI_DMA_FROMDEVICE);
if (unlikely(pci_dma_mapping_error(pdev, mapping)))
dma_unmap_addr_set(sd, dma_addr, mapping);
d->addr_lo = cpu_to_be32(mapping);
d->addr_hi = cpu_to_be32((u64) mapping >> 32);
wmb();
d->len_gen = cpu_to_be32(V_FLD_GEN1(gen));
d->gen2 = cpu_to_be32(V_FLD_GEN2(gen));
static inline int add_one_rx_chunk(dma_addr_t mapping, struct rx_desc *d,
unsigned int gen)
{
d->addr_lo = cpu_to_be32(mapping);
d->addr_hi = cpu_to_be32((u64) mapping >> 32);
wmb();
d->len_gen = cpu_to_be32(V_FLD_GEN1(gen));
d->gen2 = cpu_to_be32(V_FLD_GEN2(gen));
return 0;
}
static int alloc_pg_chunk(struct adapter *adapter, struct sge_fl *q,
struct rx_sw_desc *sd, gfp_t gfp,
dma_addr_t mapping;
q->pg_chunk.page = alloc_pages(gfp, order);
if (unlikely(!q->pg_chunk.page))
return -ENOMEM;
q->pg_chunk.va = page_address(q->pg_chunk.page);
q->pg_chunk.p_cnt = q->pg_chunk.va + (PAGE_SIZE << order) -
SGE_PG_RSVD;
mapping = pci_map_page(adapter->pdev, q->pg_chunk.page,
0, q->alloc_size, PCI_DMA_FROMDEVICE);
prefetch(sd->pg_chunk.p_cnt);
if (q->pg_chunk.offset == (PAGE_SIZE << order))
q->pg_chunk.page = NULL;
else {
q->pg_chunk.va += q->buf_size;
get_page(q->pg_chunk.page);
}
if (sd->pg_chunk.offset == 0)
*sd->pg_chunk.p_cnt = 1;
else
*sd->pg_chunk.p_cnt += 1;
static inline void ring_fl_db(struct adapter *adap, struct sge_fl *q)
{
if (q->pend_cred >= q->credits / 4) {
q->pend_cred = 0;
t3_write_reg(adap, A_SG_KDOORBELL, V_EGRCNTX(q->cntxt_id));
}
}
/**
* refill_fl - refill an SGE free-buffer list
* @adapter: the adapter
* @q: the free-list to refill
* @n: the number of new buffers to allocate
* @gfp: the gfp flags for allocating new buffers
*
* (Re)populate an SGE free-buffer list with up to @n new packet buffers,
* allocated with the supplied gfp flags. The caller must assure that
* @n does not exceed the queue's capacity.
*/
static int refill_fl(struct adapter *adap, struct sge_fl *q, int n, gfp_t gfp)
{
struct rx_sw_desc *sd = &q->sdesc[q->pidx];
struct rx_desc *d = &q->desc[q->pidx];
dma_addr_t mapping;
if (unlikely(alloc_pg_chunk(adap, q, sd, gfp,
q->order))) {
mapping = sd->pg_chunk.mapping + sd->pg_chunk.offset;
dma_unmap_addr_set(sd, dma_addr, mapping);
add_one_rx_chunk(mapping, d, q->gen);
pci_dma_sync_single_for_device(adap->pdev, mapping,
q->buf_size - SGE_PG_RSVD,
PCI_DMA_FROMDEVICE);
struct sk_buff *skb = alloc_skb(q->buf_size, gfp);
err = add_one_rx_buf(buf_start, q->buf_size, d, sd,
q->gen, adap->pdev);
if (unlikely(err)) {
clear_rx_desc(adap->pdev, q, sd);
break;
}
d++;
sd++;
if (++q->pidx == q->size) {
q->pidx = 0;
q->gen ^= 1;
sd = q->sdesc;
d = q->desc;
}
q->credits += count;
q->pend_cred += count;
ring_fl_db(adap, q);
}
static inline void __refill_fl(struct adapter *adap, struct sge_fl *fl)
{
refill_fl(adap, fl, min(MAX_RX_REFILL, fl->size - fl->credits),
GFP_ATOMIC | __GFP_COMP);
}
/**
* recycle_rx_buf - recycle a receive buffer
* @adapter: the adapter
* @q: the SGE free list
* @idx: index of buffer to recycle
*
* Recycles the specified buffer on the given free list by adding it at
* the next available slot on the list.
*/
static void recycle_rx_buf(struct adapter *adap, struct sge_fl *q,
unsigned int idx)
{
struct rx_desc *from = &q->desc[idx];
struct rx_desc *to = &q->desc[q->pidx];
to->addr_lo = from->addr_lo; /* already big endian */
to->addr_hi = from->addr_hi; /* likewise */
wmb();
to->len_gen = cpu_to_be32(V_FLD_GEN1(q->gen));
to->gen2 = cpu_to_be32(V_FLD_GEN2(q->gen));
if (++q->pidx == q->size) {
q->pidx = 0;
q->gen ^= 1;
}
q->credits++;
q->pend_cred++;
ring_fl_db(adap, q);
}
/**
* alloc_ring - allocate resources for an SGE descriptor ring
* @pdev: the PCI device
* @nelem: the number of descriptors
* @elem_size: the size of each descriptor
* @sw_size: the size of the SW state associated with each ring element
* @phys: the physical address of the allocated ring
* @metadata: address of the array holding the SW state for the ring
*
* Allocates resources for an SGE descriptor ring, such as Tx queues,
* free buffer lists, or response queues. Each SGE ring requires
* space for its HW descriptors plus, optionally, space for the SW state
* associated with each HW entry (the metadata). The function returns
* three values: the virtual address for the HW ring (the return value
* of the function), the physical address of the HW ring, and the address
* of the SW ring.
*/
static void *alloc_ring(struct pci_dev *pdev, size_t nelem, size_t elem_size,
size_t sw_size, dma_addr_t * phys, void *metadata)
{
size_t len = nelem * elem_size;
void *s = NULL;
void *p = dma_alloc_coherent(&pdev->dev, len, phys, GFP_KERNEL);
if (!p)
return NULL;
s = kcalloc(nelem, sw_size, GFP_KERNEL);
if (!s) {
dma_free_coherent(&pdev->dev, len, p, *phys);
return NULL;
}
*(void **)metadata = s;
memset(p, 0, len);
return p;
}
/**
* t3_reset_qset - reset a sge qset
* @q: the queue set
*
* Reset the qset structure.
* the NAPI structure is preserved in the event of
* the qset's reincarnation, for example during EEH recovery.
*/
static void t3_reset_qset(struct sge_qset *q)
{
if (q->adap &&
!(q->adap->flags & NAPI_INIT)) {
memset(q, 0, sizeof(*q));
return;
}
q->adap = NULL;
memset(&q->rspq, 0, sizeof(q->rspq));
memset(q->fl, 0, sizeof(struct sge_fl) * SGE_RXQ_PER_SET);
memset(q->txq, 0, sizeof(struct sge_txq) * SGE_TXQ_PER_SET);
q->txq_stopped = 0;
q->tx_reclaim_timer.function = NULL; /* for t3_stop_sge_timers() */
q->rx_reclaim_timer.function = NULL;
q->nomem = 0;
napi_free_frags(&q->napi);
/**
* free_qset - free the resources of an SGE queue set
* @adapter: the adapter owning the queue set
* @q: the queue set
*
* Release the HW and SW resources associated with an SGE queue set, such
* as HW contexts, packet buffers, and descriptor rings. Traffic to the
* queue set must be quiesced prior to calling this.
*/
static void t3_free_qset(struct adapter *adapter, struct sge_qset *q)
{
int i;
struct pci_dev *pdev = adapter->pdev;
for (i = 0; i < SGE_RXQ_PER_SET; ++i)
if (q->fl[i].desc) {
spin_lock_irq(&adapter->sge.reg_lock);
t3_sge_disable_fl(adapter, q->fl[i].cntxt_id);
spin_unlock_irq(&adapter->sge.reg_lock);
free_rx_bufs(pdev, &q->fl[i]);
kfree(q->fl[i].sdesc);
dma_free_coherent(&pdev->dev,
q->fl[i].size *
sizeof(struct rx_desc), q->fl[i].desc,
q->fl[i].phys_addr);
}
for (i = 0; i < SGE_TXQ_PER_SET; ++i)
if (q->txq[i].desc) {
spin_lock_irq(&adapter->sge.reg_lock);
t3_sge_enable_ecntxt(adapter, q->txq[i].cntxt_id, 0);
spin_unlock_irq(&adapter->sge.reg_lock);
if (q->txq[i].sdesc) {
free_tx_desc(adapter, &q->txq[i],
q->txq[i].in_use);
kfree(q->txq[i].sdesc);
}
dma_free_coherent(&pdev->dev,
q->txq[i].size *
sizeof(struct tx_desc),
q->txq[i].desc, q->txq[i].phys_addr);
__skb_queue_purge(&q->txq[i].sendq);
}
if (q->rspq.desc) {
spin_lock_irq(&adapter->sge.reg_lock);
t3_sge_disable_rspcntxt(adapter, q->rspq.cntxt_id);
spin_unlock_irq(&adapter->sge.reg_lock);
dma_free_coherent(&pdev->dev,
q->rspq.size * sizeof(struct rsp_desc),
q->rspq.desc, q->rspq.phys_addr);
}
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
}
/**
* init_qset_cntxt - initialize an SGE queue set context info
* @qs: the queue set
* @id: the queue set id
*
* Initializes the TIDs and context ids for the queues of a queue set.
*/
static void init_qset_cntxt(struct sge_qset *qs, unsigned int id)
{
qs->rspq.cntxt_id = id;
qs->fl[0].cntxt_id = 2 * id;
qs->fl[1].cntxt_id = 2 * id + 1;
qs->txq[TXQ_ETH].cntxt_id = FW_TUNNEL_SGEEC_START + id;
qs->txq[TXQ_ETH].token = FW_TUNNEL_TID_START + id;
qs->txq[TXQ_OFLD].cntxt_id = FW_OFLD_SGEEC_START + id;
qs->txq[TXQ_CTRL].cntxt_id = FW_CTRL_SGEEC_START + id;
qs->txq[TXQ_CTRL].token = FW_CTRL_TID_START + id;
}
/**
* sgl_len - calculates the size of an SGL of the given capacity
* @n: the number of SGL entries
*
* Calculates the number of flits needed for a scatter/gather list that
* can hold the given number of entries.
*/
static inline unsigned int sgl_len(unsigned int n)
{
/* alternatively: 3 * (n / 2) + 2 * (n & 1) */
return (3 * n) / 2 + (n & 1);
}
/**
* flits_to_desc - returns the num of Tx descriptors for the given flits
* @n: the number of flits
*
* Calculates the number of Tx descriptors needed for the supplied number
* of flits.
*/
static inline unsigned int flits_to_desc(unsigned int n)
{
BUG_ON(n >= ARRAY_SIZE(flit_desc_map));
return flit_desc_map[n];
}
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
/**
* get_packet - return the next ingress packet buffer from a free list
* @adap: the adapter that received the packet
* @fl: the SGE free list holding the packet
* @len: the packet length including any SGE padding
* @drop_thres: # of remaining buffers before we start dropping packets
*
* Get the next packet from a free list and complete setup of the
* sk_buff. If the packet is small we make a copy and recycle the
* original buffer, otherwise we use the original buffer itself. If a
* positive drop threshold is supplied packets are dropped and their
* buffers recycled if (a) the number of remaining buffers is under the
* threshold and the packet is too big to copy, or (b) the packet should
* be copied but there is no memory for the copy.
*/
static struct sk_buff *get_packet(struct adapter *adap, struct sge_fl *fl,
unsigned int len, unsigned int drop_thres)
{
struct sk_buff *skb = NULL;
struct rx_sw_desc *sd = &fl->sdesc[fl->cidx];
prefetch(sd->skb->data);
fl->credits--;
if (len <= SGE_RX_COPY_THRES) {
skb = alloc_skb(len, GFP_ATOMIC);
if (likely(skb != NULL)) {
__skb_put(skb, len);
pci_dma_sync_single_for_cpu(adap->pdev,
dma_unmap_addr(sd, dma_addr), len,
PCI_DMA_FROMDEVICE);
memcpy(skb->data, sd->skb->data, len);
pci_dma_sync_single_for_device(adap->pdev,
dma_unmap_addr(sd, dma_addr), len,
PCI_DMA_FROMDEVICE);
} else if (!drop_thres)
goto use_orig_buf;
recycle:
recycle_rx_buf(adap, fl, fl->cidx);
return skb;
}
if (unlikely(fl->credits < drop_thres) &&
refill_fl(adap, fl, min(MAX_RX_REFILL, fl->size - fl->credits - 1),
GFP_ATOMIC | __GFP_COMP) == 0)
pci_unmap_single(adap->pdev, dma_unmap_addr(sd, dma_addr),
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
fl->buf_size, PCI_DMA_FROMDEVICE);
skb = sd->skb;
skb_put(skb, len);
__refill_fl(adap, fl);
return skb;
}
/**
* get_packet_pg - return the next ingress packet buffer from a free list
* @adap: the adapter that received the packet
* @fl: the SGE free list holding the packet
* @len: the packet length including any SGE padding
* @drop_thres: # of remaining buffers before we start dropping packets
*
* Get the next packet from a free list populated with page chunks.
* If the packet is small we make a copy and recycle the original buffer,
* otherwise we attach the original buffer as a page fragment to a fresh
* sk_buff. If a positive drop threshold is supplied packets are dropped
* and their buffers recycled if (a) the number of remaining buffers is
* under the threshold and the packet is too big to copy, or (b) there's
* no system memory.
*
* Note: this function is similar to @get_packet but deals with Rx buffers
* that are page chunks rather than sk_buffs.
*/
static struct sk_buff *get_packet_pg(struct adapter *adap, struct sge_fl *fl,
struct sge_rspq *q, unsigned int len,
unsigned int drop_thres)
struct sk_buff *newskb, *skb;
struct rx_sw_desc *sd = &fl->sdesc[fl->cidx];
dma_addr_t dma_addr = dma_unmap_addr(sd, dma_addr);
newskb = skb = q->pg_skb;
if (!skb && (len <= SGE_RX_COPY_THRES)) {
newskb = alloc_skb(len, GFP_ATOMIC);
if (likely(newskb != NULL)) {
__skb_put(newskb, len);
pci_dma_sync_single_for_cpu(adap->pdev, dma_addr, len,
memcpy(newskb->data, sd->pg_chunk.va, len);
pci_dma_sync_single_for_device(adap->pdev, dma_addr,
len,
PCI_DMA_FROMDEVICE);
} else if (!drop_thres)
return NULL;
recycle:
fl->credits--;
recycle_rx_buf(adap, fl, fl->cidx);
q->rx_recycle_buf++;
return newskb;
if (unlikely(q->rx_recycle_buf || (!skb && fl->credits <= drop_thres)))
prefetch(sd->pg_chunk.p_cnt);
if (!drop_thres)
return NULL;
goto recycle;
}
pci_dma_sync_single_for_cpu(adap->pdev, dma_addr, len,
PCI_DMA_FROMDEVICE);
(*sd->pg_chunk.p_cnt)--;
if (!*sd->pg_chunk.p_cnt && sd->pg_chunk.page != fl->pg_chunk.page)
pci_unmap_page(adap->pdev,
fl->alloc_size,
PCI_DMA_FROMDEVICE);
if (!skb) {
__skb_put(newskb, SGE_RX_PULL_LEN);
memcpy(newskb->data, sd->pg_chunk.va, SGE_RX_PULL_LEN);
skb_fill_page_desc(newskb, 0, sd->pg_chunk.page,
sd->pg_chunk.offset + SGE_RX_PULL_LEN,
len - SGE_RX_PULL_LEN);
newskb->len = len;
newskb->data_len = len - SGE_RX_PULL_LEN;
newskb->truesize += newskb->data_len;
} else {
skb_fill_page_desc(newskb, skb_shinfo(newskb)->nr_frags,
sd->pg_chunk.page,
sd->pg_chunk.offset, len);
newskb->len += len;
newskb->data_len += len;
fl->credits--;
/*
* We do not refill FLs here, we let the caller do it to overlap a
* prefetch.
*/
/**
* get_imm_packet - return the next ingress packet buffer from a response
* @resp: the response descriptor containing the packet data
*
* Return a packet containing the immediate data of the given response.
*/
static inline struct sk_buff *get_imm_packet(const struct rsp_desc *resp)
{
struct sk_buff *skb = alloc_skb(IMMED_PKT_SIZE, GFP_ATOMIC);
if (skb) {
__skb_put(skb, IMMED_PKT_SIZE);
skb_copy_to_linear_data(skb, resp->imm_data, IMMED_PKT_SIZE);
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
}
return skb;
}
/**
* calc_tx_descs - calculate the number of Tx descriptors for a packet
* @skb: the packet
*
* Returns the number of Tx descriptors needed for the given Ethernet
* packet. Ethernet packets require addition of WR and CPL headers.
*/
static inline unsigned int calc_tx_descs(const struct sk_buff *skb)
{
unsigned int flits;
if (skb->len <= WR_LEN - sizeof(struct cpl_tx_pkt))
return 1;
flits = sgl_len(skb_shinfo(skb)->nr_frags + 1) + 2;
if (skb_shinfo(skb)->gso_size)
flits++;
return flits_to_desc(flits);
}
/**
* make_sgl - populate a scatter/gather list for a packet
* @skb: the packet
* @sgp: the SGL to populate
* @start: start address of skb main body data to include in the SGL
* @len: length of skb main body data to include in the SGL
* @pdev: the PCI device
*
* Generates a scatter/gather list for the buffers that make up a packet
* and returns the SGL size in 8-byte words. The caller must size the SGL
* appropriately.
*/
static inline unsigned int make_sgl(const struct sk_buff *skb,
struct sg_ent *sgp, unsigned char *start,
unsigned int len, struct pci_dev *pdev)
{
dma_addr_t mapping;
unsigned int i, j = 0, nfrags;
if (len) {
mapping = pci_map_single(pdev, start, len, PCI_DMA_TODEVICE);
sgp->len[0] = cpu_to_be32(len);
sgp->addr[0] = cpu_to_be64(mapping);
j = 1;
}
nfrags = skb_shinfo(skb)->nr_frags;
for (i = 0; i < nfrags; i++) {
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
mapping = pci_map_page(pdev, frag->page, frag->page_offset,
frag->size, PCI_DMA_TODEVICE);
sgp->len[j] = cpu_to_be32(frag->size);
sgp->addr[j] = cpu_to_be64(mapping);
j ^= 1;
if (j == 0)
++sgp;
}
if (j)
sgp->len[j] = 0;
return ((nfrags + (len != 0)) * 3) / 2 + j;
}
/**
* check_ring_tx_db - check and potentially ring a Tx queue's doorbell
* @adap: the adapter
* @q: the Tx queue
*
* Ring the doorbel if a Tx queue is asleep. There is a natural race,