⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sge.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
/***************************************************************************** *                                                                           * * File: sge.c                                                               * * $Revision: 1.26 $                                                         * * $Date: 2005/06/21 18:29:48 $                                              * * Description:                                                              * *  DMA engine.                                                              * *  part of the Chelsio 10Gb Ethernet Driver.                                * *                                                                           * * This program is free software; you can redistribute it and/or modify      * * it under the terms of the GNU General Public License, version 2, as       * * published by the Free Software Foundation.                                * *                                                                           * * You should have received a copy of the GNU General Public License along   * * with this program; if not, write to the Free Software Foundation, Inc.,   * * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.                 * *                                                                           * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    * * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      * * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.                     * *                                                                           * * http://www.chelsio.com                                                    * *                                                                           * * Copyright (c) 2003 - 2005 Chelsio Communications, Inc.                    * * All rights reserved.                                                      * *                                                                           * * Maintainers: maintainers@chelsio.com                                      * *                                                                           * * Authors: Dimitrios Michailidis   <dm@chelsio.com>                         * *          Tina Yang               <tainay@chelsio.com>                     * *          Felix Marti             <felix@chelsio.com>                      * *          Scott Bardone           <sbardone@chelsio.com>                   * *          Kurt Ottaway            <kottaway@chelsio.com>                   * *          Frank DiMambro          <frank@chelsio.com>                      * *                                                                           * * History:                                                                  * *                                                                           * ****************************************************************************/#include "common.h"#include <linux/config.h>#include <linux/types.h>#include <linux/errno.h>#include <linux/pci.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/if_vlan.h>#include <linux/skbuff.h>#include <linux/init.h>#include <linux/mm.h>#include <linux/ip.h>#include <linux/in.h>#include <linux/if_arp.h>#include "cpl5_cmd.h"#include "sge.h"#include "regs.h"#include "espi.h"#ifdef NETIF_F_TSO#include <linux/tcp.h>#endif#define SGE_CMDQ_N		2#define SGE_FREELQ_N		2#define SGE_CMDQ0_E_N		1024#define SGE_CMDQ1_E_N		128#define SGE_FREEL_SIZE		4096#define SGE_JUMBO_FREEL_SIZE	512#define SGE_FREEL_REFILL_THRESH	16#define SGE_RESPQ_E_N		1024#define SGE_INTRTIMER_NRES	1000#define SGE_RX_COPY_THRES	256#define SGE_RX_SM_BUF_SIZE	1536# define SGE_RX_DROP_THRES 2#define SGE_RESPQ_REPLENISH_THRES (SGE_RESPQ_E_N / 4)/* * 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)#ifndef NET_IP_ALIGN# define NET_IP_ALIGN 2#endif#define M_CMD_LEN       0x7fffffff#define V_CMD_LEN(v)    (v)#define G_CMD_LEN(v)    ((v) & M_CMD_LEN)#define V_CMD_GEN1(v)   ((v) << 31)#define V_CMD_GEN2(v)   (v)#define F_CMD_DATAVALID (1 << 1)#define F_CMD_SOP       (1 << 2)#define V_CMD_EOP(v)    ((v) << 3)/* * Command queue, receive buffer list, and response queue descriptors. */#if defined(__BIG_ENDIAN_BITFIELD)struct cmdQ_e {	u32 addr_lo;	u32 len_gen;	u32 flags;	u32 addr_hi;};struct freelQ_e {	u32 addr_lo;	u32 len_gen;	u32 gen2;	u32 addr_hi;};struct respQ_e {	u32 Qsleeping		: 4;	u32 Cmdq1CreditReturn	: 5;	u32 Cmdq1DmaComplete	: 5;	u32 Cmdq0CreditReturn	: 5;	u32 Cmdq0DmaComplete	: 5;	u32 FreelistQid		: 2;	u32 CreditValid		: 1;	u32 DataValid		: 1;	u32 Offload		: 1;	u32 Eop			: 1;	u32 Sop			: 1;	u32 GenerationBit	: 1;	u32 BufferLength;};#elif defined(__LITTLE_ENDIAN_BITFIELD)struct cmdQ_e {	u32 len_gen;	u32 addr_lo;	u32 addr_hi;	u32 flags;};struct freelQ_e {	u32 len_gen;	u32 addr_lo;	u32 addr_hi;	u32 gen2;};struct respQ_e {	u32 BufferLength;	u32 GenerationBit	: 1;	u32 Sop			: 1;	u32 Eop			: 1;	u32 Offload		: 1;	u32 DataValid		: 1;	u32 CreditValid		: 1;	u32 FreelistQid		: 2;	u32 Cmdq0DmaComplete	: 5;	u32 Cmdq0CreditReturn	: 5;	u32 Cmdq1DmaComplete	: 5;	u32 Cmdq1CreditReturn	: 5;	u32 Qsleeping		: 4;} ;#endif/* * SW Context Command and Freelist Queue Descriptors */struct cmdQ_ce {	struct sk_buff *skb;	DECLARE_PCI_UNMAP_ADDR(dma_addr);	DECLARE_PCI_UNMAP_LEN(dma_len);};struct freelQ_ce {	struct sk_buff *skb;	DECLARE_PCI_UNMAP_ADDR(dma_addr);	DECLARE_PCI_UNMAP_LEN(dma_len);};/* * SW command, freelist and response rings */struct cmdQ {	unsigned long   status;         /* HW DMA fetch status */	unsigned int    in_use;         /* # of in-use command descriptors */	unsigned int	size;	        /* # of descriptors */	unsigned int	processed;      /* total # of descs HW has processed */	unsigned int	cleaned;        /* total # of descs SW has reclaimed */	unsigned int	stop_thres;     /* SW TX queue suspend threshold */	u16		pidx;           /* producer index (SW) */	u16		cidx;           /* consumer index (HW) */	u8		genbit;         /* current generation (=valid) bit */	u8		sop;            /* is next entry start of packet? */	struct cmdQ_e  *entries;        /* HW command descriptor Q */	struct cmdQ_ce *centries;       /* SW command context descriptor Q */	spinlock_t	lock;           /* Lock to protect cmdQ enqueuing */	dma_addr_t	dma_addr;       /* DMA addr HW command descriptor Q */};struct freelQ {	unsigned int	credits;        /* # of available RX buffers */	unsigned int	size;	        /* free list capacity */	u16		pidx;           /* producer index (SW) */	u16		cidx;           /* consumer index (HW) */	u16		rx_buffer_size; /* Buffer size on this free list */	u16		dma_offset;     /* DMA offset to align IP headers */	u16		recycleq_idx;   /* skb recycle q to use */	u8		genbit;	        /* current generation (=valid) bit */	struct freelQ_e	*entries;       /* HW freelist descriptor Q */	struct freelQ_ce *centries;     /* SW freelist context descriptor Q */	dma_addr_t	dma_addr;       /* DMA addr HW freelist descriptor Q */};struct respQ {	unsigned int	credits;        /* credits to be returned to SGE */	unsigned int	size;	        /* # of response Q descriptors */	u16		cidx;	        /* consumer index (SW) */	u8		genbit;	        /* current generation(=valid) bit */	struct respQ_e *entries;        /* HW response descriptor Q */	dma_addr_t	dma_addr;       /* DMA addr HW response descriptor Q */};/* Bit flags for cmdQ.status */enum {	CMDQ_STAT_RUNNING = 1,          /* fetch engine is running */	CMDQ_STAT_LAST_PKT_DB = 2       /* last packet rung the doorbell */};/* * Main SGE data structure * * Interrupts are handled by a single CPU and it is likely that on a MP system * the application is migrated to another CPU. In that scenario, we try to * seperate the RX(in irq context) and TX state in order to decrease memory * contention. */struct sge {	struct adapter *adapter; 	/* adapter backpointer */	struct net_device *netdev;      /* netdevice backpointer */	struct freelQ 	freelQ[SGE_FREELQ_N]; /* buffer free lists */	struct respQ 	respQ;		/* response Q */	unsigned long   stopped_tx_queues; /* bitmap of suspended Tx queues */	unsigned int	rx_pkt_pad;     /* RX padding for L2 packets */	unsigned int	jumbo_fl;       /* jumbo freelist Q index */	unsigned int	intrtimer_nres;	/* no-resource interrupt timer */	unsigned int	fixed_intrtimer;/* non-adaptive interrupt timer */	struct timer_list tx_reclaim_timer; /* reclaims TX buffers */	struct timer_list espibug_timer;	unsigned int	espibug_timeout;	struct sk_buff	*espibug_skb;	u32		sge_control;	/* shadow value of sge control reg */	struct sge_intr_counts stats;	struct sge_port_stats port_stats[MAX_NPORTS];	struct cmdQ cmdQ[SGE_CMDQ_N] ____cacheline_aligned_in_smp;};/* * PIO to indicate that memory mapped Q contains valid descriptor(s). */static inline void doorbell_pio(struct adapter *adapter, u32 val){	wmb();	writel(val, adapter->regs + A_SG_DOORBELL);}/* * Frees all RX buffers on the freelist Q. The caller must make sure that * the SGE is turned off before calling this function. */static void free_freelQ_buffers(struct pci_dev *pdev, struct freelQ *q){	unsigned int cidx = q->cidx;	while (q->credits--) {		struct freelQ_ce *ce = &q->centries[cidx];		pci_unmap_single(pdev, pci_unmap_addr(ce, dma_addr),				 pci_unmap_len(ce, dma_len),				 PCI_DMA_FROMDEVICE);		dev_kfree_skb(ce->skb);		ce->skb = NULL;		if (++cidx == q->size)			cidx = 0;	}}/* * Free RX free list and response queue resources. */static void free_rx_resources(struct sge *sge){	struct pci_dev *pdev = sge->adapter->pdev;	unsigned int size, i;	if (sge->respQ.entries) {		size = sizeof(struct respQ_e) * sge->respQ.size;		pci_free_consistent(pdev, size, sge->respQ.entries,				    sge->respQ.dma_addr);	}	for (i = 0; i < SGE_FREELQ_N; i++) {		struct freelQ *q = &sge->freelQ[i];		if (q->centries) {			free_freelQ_buffers(pdev, q);			kfree(q->centries);		}		if (q->entries) {			size = sizeof(struct freelQ_e) * q->size;			pci_free_consistent(pdev, size, q->entries,					    q->dma_addr);		}	}}/* * Allocates basic RX resources, consisting of memory mapped freelist Qs and a * response queue. */static int alloc_rx_resources(struct sge *sge, struct sge_params *p){	struct pci_dev *pdev = sge->adapter->pdev;	unsigned int size, i;	for (i = 0; i < SGE_FREELQ_N; i++) {		struct freelQ *q = &sge->freelQ[i];		q->genbit = 1;		q->size = p->freelQ_size[i];		q->dma_offset = sge->rx_pkt_pad ? 0 : NET_IP_ALIGN;		size = sizeof(struct freelQ_e) * q->size;		q->entries = (struct freelQ_e *)			      pci_alloc_consistent(pdev, size, &q->dma_addr);		if (!q->entries)			goto err_no_mem;		memset(q->entries, 0, size);		size = sizeof(struct freelQ_ce) * q->size;		q->centries = kmalloc(size, GFP_KERNEL);		if (!q->centries)			goto err_no_mem;		memset(q->centries, 0, size);	}	/*	 * Calculate the buffer sizes for the two free lists.  FL0 accommodates	 * regular sized Ethernet frames, FL1 is sized not to exceed 16K,	 * including all the sk_buff overhead.	 *	 * Note: For T2 FL0 and FL1 are reversed.	 */	sge->freelQ[!sge->jumbo_fl].rx_buffer_size = SGE_RX_SM_BUF_SIZE +		sizeof(struct cpl_rx_data) +		sge->freelQ[!sge->jumbo_fl].dma_offset;	sge->freelQ[sge->jumbo_fl].rx_buffer_size = (16 * 1024) -		SKB_DATA_ALIGN(sizeof(struct skb_shared_info));	/*	 * Setup which skb recycle Q should be used when recycling buffers from	 * each free list.	 */	sge->freelQ[!sge->jumbo_fl].recycleq_idx = 0;	sge->freelQ[sge->jumbo_fl].recycleq_idx = 1;	sge->respQ.genbit = 1;	sge->respQ.size = SGE_RESPQ_E_N;	sge->respQ.credits = 0;	size = sizeof(struct respQ_e) * sge->respQ.size;	sge->respQ.entries = (struct respQ_e *)		pci_alloc_consistent(pdev, size, &sge->respQ.dma_addr);	if (!sge->respQ.entries)		goto err_no_mem;	memset(sge->respQ.entries, 0, size);	return 0;err_no_mem:	free_rx_resources(sge);	return -ENOMEM;}/* * Reclaims n TX descriptors and frees the buffers associated with them. */static void free_cmdQ_buffers(struct sge *sge, struct cmdQ *q, unsigned int n){	struct cmdQ_ce *ce;	struct pci_dev *pdev = sge->adapter->pdev;	unsigned int cidx = q->cidx;	q->in_use -= n;	ce = &q->centries[cidx];	while (n--) {		if (q->sop)			pci_unmap_single(pdev, pci_unmap_addr(ce, dma_addr),			 		 pci_unmap_len(ce, dma_len),					 PCI_DMA_TODEVICE);		else			pci_unmap_page(pdev, pci_unmap_addr(ce, dma_addr),			 	       pci_unmap_len(ce, dma_len),				       PCI_DMA_TODEVICE);		q->sop = 0;		if (ce->skb) {			dev_kfree_skb(ce->skb);			q->sop = 1;		}		ce++;		if (++cidx == q->size) {			cidx = 0;			ce = q->centries;		}	}	q->cidx = cidx;}/* * Free TX resources. * * Assumes that SGE is stopped and all interrupts are disabled. */static void free_tx_resources(struct sge *sge){	struct pci_dev *pdev = sge->adapter->pdev;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -