Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7f7f5316 authored by Andy Fleming's avatar Andy Fleming Committed by Jeff Garzik
Browse files

[PATCH] Gianfar update and sysfs support



This seems to have gotten lost, so I'll resend.

Signed-off-by: default avatarAndy Fleming <afleming@freescale.com>

* Added sysfs support to gianfar for modifying FIFO and stashing parameters
* Updated driver to support 10 Mbit, full duplex operation
* Improved comments throughout
* Cleaned up and optimized offloading code
* Fixed a bug where rx buffers were being improperly mapped and unmapped
* (only manifested if cache-coherency was off)
* Added support for using the eTSEC exact-match MAC registers
* Bumped the version to 1.3
* Added support for distinguishing between reduced 100 and 10 Mbit modes
* Modified default coalescing values to lower latency
* Added documentation
Signed-off-by: default avatarJeff Garzik <jgarzik@pobox.com>
parent fed5eccd
Loading
Loading
Loading
Loading
+72 −0
Original line number Diff line number Diff line
The Gianfar Ethernet Driver
Sysfs File description

Author: Andy Fleming <afleming@freescale.com>
Updated: 2005-07-28

SYSFS

Several of the features of the gianfar driver are controlled
through sysfs files.  These are:

bd_stash:
To stash RX Buffer Descriptors in the L2, echo 'on' or '1' to
bd_stash, echo 'off' or '0' to disable

rx_stash_len:
To stash the first n bytes of the packet in L2, echo the number
of bytes to buf_stash_len.  echo 0 to disable.

WARNING: You could really screw these up if you set them too low or high!
fifo_threshold:
To change the number of bytes the controller needs in the
fifo before it starts transmission, echo the number of bytes to 
fifo_thresh.  Range should be 0-511.

fifo_starve:
When the FIFO has less than this many bytes during a transmit, it
enters starve mode, and increases the priority of TX memory
transactions.  To change, echo the number of bytes to
fifo_starve.  Range should be 0-511.

fifo_starve_off:
Once in starve mode, the FIFO remains there until it has this
many bytes.  To change, echo the number of bytes to
fifo_starve_off.  Range should be 0-511.

CHECKSUM OFFLOADING

The eTSEC controller (first included in parts from late 2005 like
the 8548) has the ability to perform TCP, UDP, and IP checksums
in hardware.  The Linux kernel only offloads the TCP and UDP
checksums (and always performs the pseudo header checksums), so
the driver only supports checksumming for TCP/IP and UDP/IP
packets.  Use ethtool to enable or disable this feature for RX
and TX.

VLAN

In order to use VLAN, please consult Linux documentation on
configuring VLANs.  The gianfar driver supports hardware insertion and
extraction of VLAN headers, but not filtering.  Filtering will be
done by the kernel.

MULTICASTING

The gianfar driver supports using the group hash table on the
TSEC (and the extended hash table on the eTSEC) for multicast
filtering.  On the eTSEC, the exact-match MAC registers are used
before the hash tables.  See Linux documentation on how to join
multicast groups.

PADDING

The gianfar driver supports padding received frames with 2 bytes
to align the IP header to a 16-byte boundary, when supported by
hardware.

ETHTOOL

The gianfar driver supports the use of ethtool for many
configuration options.  You must run ethtool only on currently
open interfaces.  See ethtool documentation for details.
+4 −1
Original line number Diff line number Diff line
@@ -13,7 +13,10 @@ obj-$(CONFIG_CHELSIO_T1) += chelsio/
obj-$(CONFIG_BONDING) += bonding/
obj-$(CONFIG_GIANFAR) += gianfar_driver.o

gianfar_driver-objs := gianfar.o gianfar_ethtool.o gianfar_mii.o
gianfar_driver-objs := gianfar.o \
		gianfar_ethtool.o \
		gianfar_mii.o \
		gianfar_sysfs.o

#
# link order important here
+152 −79
Original line number Diff line number Diff line
@@ -2,7 +2,8 @@
 * drivers/net/gianfar.c
 *
 * Gianfar Ethernet Driver
 * Driver for FEC on MPC8540 and TSEC on MPC8540/MPC8560
 * This driver is designed for the non-CPM ethernet controllers
 * on the 85xx and 83xx family of integrated processors
 * Based on 8260_io/fcc_enet.c
 *
 * Author: Andy Fleming
@@ -22,8 +23,6 @@
 *  B-V +1.62
 *
 *  Theory of operation
 *  This driver is designed for the non-CPM ethernet controllers
 *  on the 85xx and 83xx family of integrated processors
 *
 *  The driver is initialized through platform_device.  Structures which
 *  define the configuration needed by the board are defined in a
@@ -110,7 +109,7 @@
#endif

const char gfar_driver_name[] = "Gianfar Ethernet";
const char gfar_driver_version[] = "1.2";
const char gfar_driver_version[] = "1.3";

static int gfar_enet_open(struct net_device *dev);
static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev);
@@ -139,6 +138,10 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int l
static void gfar_vlan_rx_register(struct net_device *netdev,
		                struct vlan_group *grp);
static void gfar_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
void gfar_halt(struct net_device *dev);
void gfar_start(struct net_device *dev);
static void gfar_clear_exact_match(struct net_device *dev);
static void gfar_set_mac_for_addr(struct net_device *dev, int num, u8 *addr);

extern struct ethtool_ops gfar_ethtool_ops;

@@ -146,12 +149,10 @@ MODULE_AUTHOR("Freescale Semiconductor, Inc");
MODULE_DESCRIPTION("Gianfar Ethernet Driver");
MODULE_LICENSE("GPL");

int gfar_uses_fcb(struct gfar_private *priv)
/* Returns 1 if incoming frames use an FCB */
static inline int gfar_uses_fcb(struct gfar_private *priv)
{
	if (priv->vlan_enable || priv->rx_csum_enable)
		return 1;
	else
		return 0;
	return (priv->vlan_enable || priv->rx_csum_enable);
}

/* Set up the ethernet device structure, private data,
@@ -320,15 +321,10 @@ static int gfar_probe(struct platform_device *pdev)
	else
		priv->padding = 0;

	dev->hard_header_len += priv->padding;

	if (dev->features & NETIF_F_IP_CSUM)
		dev->hard_header_len += GMAC_FCB_LEN;

	priv->rx_buffer_size = DEFAULT_RX_BUFFER_SIZE;
#ifdef CONFIG_GFAR_BUFSTASH
	priv->rx_stash_size = STASH_LENGTH;
#endif
	priv->tx_ring_size = DEFAULT_TX_RING_SIZE;
	priv->rx_ring_size = DEFAULT_RX_RING_SIZE;

@@ -350,6 +346,9 @@ static int gfar_probe(struct platform_device *pdev)
		goto register_fail;
	}

	/* Create all the sysfs files */
	gfar_init_sysfs(dev);

	/* Print out the device info */
	printk(KERN_INFO DEVICE_NAME, dev->name);
	for (idx = 0; idx < 6; idx++)
@@ -357,8 +356,7 @@ static int gfar_probe(struct platform_device *pdev)
	printk("\n");

	/* Even more device info helps when determining which kernel */
	/* provided which set of benchmarks.  Since this is global for all */
	/* devices, we only print it once */
	/* provided which set of benchmarks. */
#ifdef CONFIG_GFAR_NAPI
	printk(KERN_INFO "%s: Running with NAPI enabled\n", dev->name);
#else
@@ -463,19 +461,9 @@ static void init_registers(struct net_device *dev)
	/* Initialize the max receive buffer length */
	gfar_write(&priv->regs->mrblr, priv->rx_buffer_size);

#ifdef CONFIG_GFAR_BUFSTASH
	/* If we are stashing buffers, we need to set the
	 * extraction length to the size of the buffer */
	gfar_write(&priv->regs->attreli, priv->rx_stash_size << 16);
#endif

	/* Initialize the Minimum Frame Length Register */
	gfar_write(&priv->regs->minflr, MINFLR_INIT_SETTINGS);

	/* Setup Attributes so that snooping is on for rx */
	gfar_write(&priv->regs->attr, ATTR_INIT_SETTINGS);
	gfar_write(&priv->regs->attreli, ATTRELI_INIT_SETTINGS);

	/* Assign the TBI an address which won't conflict with the PHYs */
	gfar_write(&priv->regs->tbipa, TBIPA_VALUE);
}
@@ -577,8 +565,7 @@ static void free_skb_resources(struct gfar_private *priv)
		for (i = 0; i < priv->rx_ring_size; i++) {
			if (priv->rx_skbuff[i]) {
				dma_unmap_single(NULL, rxbdp->bufPtr,
						priv->rx_buffer_size
						+ RXBUF_ALIGNMENT,
						priv->rx_buffer_size,
						DMA_FROM_DEVICE);

				dev_kfree_skb_any(priv->rx_skbuff[i]);
@@ -636,6 +623,7 @@ int startup_gfar(struct net_device *dev)
	struct gfar *regs = priv->regs;
	int err = 0;
	u32 rctrl = 0;
	u32 attrs = 0;

	gfar_write(&regs->imask, IMASK_INIT_CLEAR);

@@ -795,18 +783,50 @@ int startup_gfar(struct net_device *dev)
	if (priv->rx_csum_enable)
		rctrl |= RCTRL_CHECKSUMMING;

	if (priv->extended_hash)
	if (priv->extended_hash) {
		rctrl |= RCTRL_EXTHASH;

		gfar_clear_exact_match(dev);
		rctrl |= RCTRL_EMEN;
	}

	if (priv->vlan_enable)
		rctrl |= RCTRL_VLAN;

	if (priv->padding) {
		rctrl &= ~RCTRL_PAL_MASK;
		rctrl |= RCTRL_PADDING(priv->padding);
	}

	/* Init rctrl based on our settings */
	gfar_write(&priv->regs->rctrl, rctrl);

	if (dev->features & NETIF_F_IP_CSUM)
		gfar_write(&priv->regs->tctrl, TCTRL_INIT_CSUM);

	/* Set the extraction length and index */
	attrs = ATTRELI_EL(priv->rx_stash_size) |
		ATTRELI_EI(priv->rx_stash_index);

	gfar_write(&priv->regs->attreli, attrs);

	/* Start with defaults, and add stashing or locking
	 * depending on the approprate variables */
	attrs = ATTR_INIT_SETTINGS;

	if (priv->bd_stash_en)
		attrs |= ATTR_BDSTASH;

	if (priv->rx_stash_size != 0)
		attrs |= ATTR_BUFSTASH;

	gfar_write(&priv->regs->attr, attrs);

	gfar_write(&priv->regs->fifo_tx_thr, priv->fifo_threshold);
	gfar_write(&priv->regs->fifo_tx_starve, priv->fifo_starve);
	gfar_write(&priv->regs->fifo_tx_starve_shutoff, priv->fifo_starve_off);

	/* Start the controller */
	gfar_start(dev);

	return 0;
@@ -851,34 +871,32 @@ static int gfar_enet_open(struct net_device *dev)
	return err;
}

static struct txfcb *gfar_add_fcb(struct sk_buff *skb, struct txbd8 *bdp)
static inline struct txfcb *gfar_add_fcb(struct sk_buff *skb, struct txbd8 *bdp)
{
	struct txfcb *fcb = (struct txfcb *)skb_push (skb, GMAC_FCB_LEN);

	memset(fcb, 0, GMAC_FCB_LEN);

	/* Flag the bd so the controller looks for the FCB */
	bdp->status |= TXBD_TOE;

	return fcb;
}

static inline void gfar_tx_checksum(struct sk_buff *skb, struct txfcb *fcb)
{
	int len;
	u8 flags = 0;

	/* If we're here, it's a IP packet with a TCP or UDP
	 * payload.  We set it to checksum, using a pseudo-header
	 * we provide
	 */
	fcb->ip = 1;
	fcb->tup = 1;
	fcb->ctu = 1;
	fcb->nph = 1;
	flags = TXFCB_DEFAULT;

	/* Notify the controller what the protocol is */
	if (skb->nh.iph->protocol == IPPROTO_UDP)
		fcb->udp = 1;
	/* Tell the controller what the protocol is */
	/* And provide the already calculated phcs */
	if (skb->nh.iph->protocol == IPPROTO_UDP) {
		flags |= TXFCB_UDP;
		fcb->phcs = skb->h.uh->check;
	} else
		fcb->phcs = skb->h.th->check;

	/* l3os is the distance between the start of the
	 * frame (skb->data) and the start of the IP hdr.
@@ -887,17 +905,12 @@ static inline void gfar_tx_checksum(struct sk_buff *skb, struct txfcb *fcb)
	fcb->l3os = (u16)(skb->nh.raw - skb->data - GMAC_FCB_LEN);
	fcb->l4os = (u16)(skb->h.raw - skb->nh.raw);

	len = skb->nh.iph->tot_len - fcb->l4os;

	/* Provide the pseudoheader csum */
	fcb->phcs = ~csum_tcpudp_magic(skb->nh.iph->saddr,
			skb->nh.iph->daddr, len,
			skb->nh.iph->protocol, 0);
	fcb->flags = flags;
}

void gfar_tx_vlan(struct sk_buff *skb, struct txfcb *fcb)
void inline gfar_tx_vlan(struct sk_buff *skb, struct txfcb *fcb)
{
	fcb->vln = 1;
	fcb->flags |= TXFCB_VLN;
	fcb->vlctl = vlan_tx_tag_get(skb);
}

@@ -908,6 +921,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
	struct gfar_private *priv = netdev_priv(dev);
	struct txfcb *fcb = NULL;
	struct txbd8 *txbdp;
	u16 status;

	/* Update transmit stats */
	priv->stats.tx_bytes += skb->len;
@@ -919,19 +933,22 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
	txbdp = priv->cur_tx;

	/* Clear all but the WRAP status flags */
	txbdp->status &= TXBD_WRAP;
	status = txbdp->status & TXBD_WRAP;

	/* Set up checksumming */
	if ((dev->features & NETIF_F_IP_CSUM)
			&& (CHECKSUM_HW == skb->ip_summed)) {
	if (likely((dev->features & NETIF_F_IP_CSUM)
			&& (CHECKSUM_HW == skb->ip_summed))) {
		fcb = gfar_add_fcb(skb, txbdp);
		status |= TXBD_TOE;
		gfar_tx_checksum(skb, fcb);
	}

	if (priv->vlan_enable &&
			unlikely(priv->vlgrp && vlan_tx_tag_present(skb))) {
		if (NULL == fcb)
		if (unlikely(NULL == fcb)) {
			fcb = gfar_add_fcb(skb, txbdp);
			status |= TXBD_TOE;
		}

		gfar_tx_vlan(skb, fcb);
	}
@@ -949,14 +966,16 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
	    (priv->skb_curtx + 1) & TX_RING_MOD_MASK(priv->tx_ring_size);

	/* Flag the BD as interrupt-causing */
	txbdp->status |= TXBD_INTERRUPT;
	status |= TXBD_INTERRUPT;

	/* Flag the BD as ready to go, last in frame, and  */
	/* in need of CRC */
	txbdp->status |= (TXBD_READY | TXBD_LAST | TXBD_CRC);
	status |= (TXBD_READY | TXBD_LAST | TXBD_CRC);

	dev->trans_start = jiffies;

	txbdp->status = status;

	/* If this was the last BD in the ring, the next one */
	/* is at the beginning of the ring */
	if (txbdp->status & TXBD_WRAP)
@@ -1010,21 +1029,7 @@ static struct net_device_stats * gfar_get_stats(struct net_device *dev)
/* Changes the mac address if the controller is not running. */
int gfar_set_mac_address(struct net_device *dev)
{
	struct gfar_private *priv = netdev_priv(dev);
	int i;
	char tmpbuf[MAC_ADDR_LEN];
	u32 tempval;

	/* Now copy it into the mac registers backwards, cuz */
	/* little endian is silly */
	for (i = 0; i < MAC_ADDR_LEN; i++)
		tmpbuf[MAC_ADDR_LEN - 1 - i] = dev->dev_addr[i];

	gfar_write(&priv->regs->macstnaddr1, *((u32 *) (tmpbuf)));

	tempval = *((u32 *) (tmpbuf + 4));

	gfar_write(&priv->regs->macstnaddr2, tempval);
	gfar_set_mac_for_addr(dev, 0, dev->dev_addr);

	return 0;
}
@@ -1110,7 +1115,7 @@ static int gfar_change_mtu(struct net_device *dev, int new_mtu)
	    INCREMENTAL_BUFFER_SIZE;

	/* Only stop and start the controller if it isn't already
	 * stopped */
	 * stopped, and we changed something */
	if ((oldsize != tempsize) && (dev->flags & IFF_UP))
		stop_gfar(dev);

@@ -1220,6 +1225,7 @@ static irqreturn_t gfar_transmit(int irq, void *dev_id, struct pt_regs *regs)

struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp)
{
	unsigned int alignamount;
	struct gfar_private *priv = netdev_priv(dev);
	struct sk_buff *skb = NULL;
	unsigned int timeout = SKB_ALLOC_TIMEOUT;
@@ -1231,18 +1237,18 @@ struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp)
	if (NULL == skb)
		return NULL;

	alignamount = RXBUF_ALIGNMENT -
		(((unsigned) skb->data) & (RXBUF_ALIGNMENT - 1));

	/* We need the data buffer to be aligned properly.  We will reserve
	 * as many bytes as needed to align the data properly
	 */
	skb_reserve(skb,
		    RXBUF_ALIGNMENT -
		    (((unsigned) skb->data) & (RXBUF_ALIGNMENT - 1)));
	skb_reserve(skb, alignamount);

	skb->dev = dev;

	bdp->bufPtr = dma_map_single(NULL, skb->data,
			priv->rx_buffer_size + RXBUF_ALIGNMENT,
			DMA_FROM_DEVICE);
			priv->rx_buffer_size, DMA_FROM_DEVICE);

	bdp->length = 0;

@@ -1350,7 +1356,7 @@ static inline void gfar_rx_checksum(struct sk_buff *skb, struct rxfcb *fcb)
	/* If valid headers were found, and valid sums
	 * were verified, then we tell the kernel that no
	 * checksumming is necessary.  Otherwise, it is */
	if (fcb->cip && !fcb->eip && fcb->ctu && !fcb->etu)
	if ((fcb->flags & RXFCB_CSUM_MASK) == (RXFCB_CIP | RXFCB_CTU))
		skb->ip_summed = CHECKSUM_UNNECESSARY;
	else
		skb->ip_summed = CHECKSUM_NONE;
@@ -1401,7 +1407,7 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
		skb->protocol = eth_type_trans(skb, dev);

		/* Send the packet up the stack */
		if (unlikely(priv->vlgrp && fcb->vln))
		if (unlikely(priv->vlgrp && (fcb->flags & RXFCB_VLN)))
			ret = gfar_rx_vlan(skb, priv->vlgrp, fcb->vlctl);
		else
			ret = RECEIVE(skb);
@@ -1620,6 +1626,7 @@ static void adjust_link(struct net_device *dev)
	spin_lock_irqsave(&priv->lock, flags);
	if (phydev->link) {
		u32 tempval = gfar_read(&regs->maccfg2);
		u32 ecntrl = gfar_read(&regs->ecntrl);

		/* Now we make sure that we can be in full duplex mode.
		 * If not, we operate in half-duplex mode. */
@@ -1644,6 +1651,13 @@ static void adjust_link(struct net_device *dev)
			case 10:
				tempval =
				    ((tempval & ~(MACCFG2_IF)) | MACCFG2_MII);

				/* Reduced mode distinguishes
				 * between 10 and 100 */
				if (phydev->speed == SPEED_100)
					ecntrl |= ECNTRL_R100;
				else
					ecntrl &= ~(ECNTRL_R100);
				break;
			default:
				if (netif_msg_link(priv))
@@ -1657,6 +1671,7 @@ static void adjust_link(struct net_device *dev)
		}

		gfar_write(&regs->maccfg2, tempval);
		gfar_write(&regs->ecntrl, ecntrl);

		if (!priv->oldlink) {
			new_state = 1;
@@ -1721,6 +1736,9 @@ static void gfar_set_multi(struct net_device *dev)
		gfar_write(&regs->gaddr6, 0xffffffff);
		gfar_write(&regs->gaddr7, 0xffffffff);
	} else {
		int em_num;
		int idx;

		/* zero out the hash */
		gfar_write(&regs->igaddr0, 0x0);
		gfar_write(&regs->igaddr1, 0x0);
@@ -1739,11 +1757,28 @@ static void gfar_set_multi(struct net_device *dev)
		gfar_write(&regs->gaddr6, 0x0);
		gfar_write(&regs->gaddr7, 0x0);

		/* If we have extended hash tables, we need to
		 * clear the exact match registers to prepare for
		 * setting them */
		if (priv->extended_hash) {
			em_num = GFAR_EM_NUM + 1;
			gfar_clear_exact_match(dev);
			idx = 1;
		} else {
			idx = 0;
			em_num = 0;
		}

		if(dev->mc_count == 0)
			return;

		/* Parse the list, and set the appropriate bits */
		for(mc_ptr = dev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) {
			if (idx < em_num) {
				gfar_set_mac_for_addr(dev, idx,
						mc_ptr->dmi_addr);
				idx++;
			} else
				gfar_set_hash_for_addr(dev, mc_ptr->dmi_addr);
		}
	}
@@ -1751,6 +1786,18 @@ static void gfar_set_multi(struct net_device *dev)
	return;
}


/* Clears each of the exact match registers to zero, so they
 * don't interfere with normal reception */
static void gfar_clear_exact_match(struct net_device *dev)
{
	int idx;
	u8 zero_arr[MAC_ADDR_LEN] = {0,0,0,0,0,0};

	for(idx = 1;idx < GFAR_EM_NUM + 1;idx++)
		gfar_set_mac_for_addr(dev, idx, (u8 *)zero_arr);
}

/* Set the appropriate hash bit for the given addr */
/* The algorithm works like so:
 * 1) Take the Destination Address (ie the multicast address), and
@@ -1781,6 +1828,32 @@ static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr)
	return;
}


/* There are multiple MAC Address register pairs on some controllers
 * This function sets the numth pair to a given address
 */
static void gfar_set_mac_for_addr(struct net_device *dev, int num, u8 *addr)
{
	struct gfar_private *priv = netdev_priv(dev);
	int idx;
	char tmpbuf[MAC_ADDR_LEN];
	u32 tempval;
	u32 *macptr = &priv->regs->macstnaddr1;

	macptr += num*2;

	/* Now copy it into the mac registers backwards, cuz */
	/* little endian is silly */
	for (idx = 0; idx < MAC_ADDR_LEN; idx++)
		tmpbuf[MAC_ADDR_LEN - 1 - idx] = addr[idx];

	gfar_write(macptr, *((u32 *) (tmpbuf)));

	tempval = *((u32 *) (tmpbuf + 4));

	gfar_write(macptr+1, tempval);
}

/* GFAR error interrupt handler */
static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs)
{
+38 −31
Original line number Diff line number Diff line
@@ -90,12 +90,26 @@ extern const char gfar_driver_version[];
#define GFAR_RX_MAX_RING_SIZE   256
#define GFAR_TX_MAX_RING_SIZE   256

#define GFAR_MAX_FIFO_THRESHOLD 511
#define GFAR_MAX_FIFO_STARVE	511
#define GFAR_MAX_FIFO_STARVE_OFF 511

#define DEFAULT_RX_BUFFER_SIZE  1536
#define TX_RING_MOD_MASK(size) (size-1)
#define RX_RING_MOD_MASK(size) (size-1)
#define JUMBO_BUFFER_SIZE 9728
#define JUMBO_FRAME_SIZE 9600

#define DEFAULT_FIFO_TX_THR 0x100
#define DEFAULT_FIFO_TX_STARVE 0x40
#define DEFAULT_FIFO_TX_STARVE_OFF 0x80
#define DEFAULT_BD_STASH 1
#define DEFAULT_STASH_LENGTH	64
#define DEFAULT_STASH_INDEX	0

/* The number of Exact Match registers */
#define GFAR_EM_NUM	15

/* Latency of interface clock in nanoseconds */
/* Interface clock latency , in this case, means the
 * time described by a value of 1 in the interrupt
@@ -112,11 +126,11 @@ extern const char gfar_driver_version[];

#define DEFAULT_TX_COALESCE 1
#define DEFAULT_TXCOUNT	16
#define DEFAULT_TXTIME	400
#define DEFAULT_TXTIME	4

#define DEFAULT_RX_COALESCE 1
#define DEFAULT_RXCOUNT	16
#define DEFAULT_RXTIME	400
#define DEFAULT_RXTIME	4

#define TBIPA_VALUE		0x1f
#define MIIMCFG_INIT_VALUE	0x00000007
@@ -147,6 +161,7 @@ extern const char gfar_driver_version[];

#define ECNTRL_INIT_SETTINGS	0x00001000
#define ECNTRL_TBI_MODE         0x00000020
#define ECNTRL_R100		0x00000008

#define MRBLR_INIT_SETTINGS	DEFAULT_RX_BUFFER_SIZE

@@ -181,10 +196,12 @@ extern const char gfar_driver_version[];
#define RCTRL_PRSDEP_MASK	0x000000c0
#define RCTRL_PRSDEP_INIT	0x000000c0
#define RCTRL_PROM		0x00000008
#define RCTRL_EMEN		0x00000002
#define RCTRL_CHECKSUMMING	(RCTRL_IPCSEN \
		| RCTRL_TUCSEN | RCTRL_PRSDEP_INIT)
#define RCTRL_EXTHASH		(RCTRL_GHTX)
#define RCTRL_VLAN		(RCTRL_PRSDEP_INIT)
#define RCTRL_PADDING(x)	((x << 16) & RCTRL_PAL_MASK)


#define RSTAT_CLEAR_RHALT       0x00800000
@@ -251,28 +268,26 @@ extern const char gfar_driver_version[];
		IMASK_XFUN | IMASK_RXC | IMASK_BABT | IMASK_DPE \
		| IMASK_PERR)

/* Fifo management */
#define FIFO_TX_THR_MASK	0x01ff
#define FIFO_TX_STARVE_MASK	0x01ff
#define FIFO_TX_STARVE_OFF_MASK	0x01ff

/* Attribute fields */

/* This enables rx snooping for buffers and descriptors */
#ifdef CONFIG_GFAR_BDSTASH
#define ATTR_BDSTASH		0x00000800
#else
#define ATTR_BDSTASH		0x00000000
#endif

#ifdef CONFIG_GFAR_BUFSTASH
#define ATTR_BUFSTASH		0x00004000
#define STASH_LENGTH		64
#else
#define ATTR_BUFSTASH		0x00000000
#endif

#define ATTR_SNOOPING		0x000000c0
#define ATTR_INIT_SETTINGS      (ATTR_SNOOPING \
		| ATTR_BDSTASH | ATTR_BUFSTASH)
#define ATTR_INIT_SETTINGS      ATTR_SNOOPING

#define ATTRELI_INIT_SETTINGS   0x0
#define ATTRELI_EL_MASK		0x3fff0000
#define ATTRELI_EL(x) (x << 16)
#define ATTRELI_EI_MASK		0x00003fff
#define ATTRELI_EI(x) (x)


/* TxBD status field bits */
@@ -328,6 +343,7 @@ extern const char gfar_driver_version[];
#define RXFCB_CTU		0x0400
#define RXFCB_EIP		0x0200
#define RXFCB_ETU		0x0100
#define RXFCB_CSUM_MASK		0x0f00
#define RXFCB_PERR_MASK		0x000c
#define RXFCB_PERR_BADL3	0x0008

@@ -339,14 +355,7 @@ struct txbd8
};

struct txfcb {
	u8	vln:1,
		ip:1,
		ip6:1,
		tup:1,
		udp:1,
		cip:1,
		ctu:1,
		nph:1;
	u8	flags;
	u8	reserved;
	u8	l4os;	/* Level 4 Header Offset */
	u8	l3os; 	/* Level 3 Header Offset */
@@ -362,14 +371,7 @@ struct rxbd8
};

struct rxfcb {
	u16	vln:1,
		ip:1,
		ip6:1,
		tup:1,
		cip:1,
		ctu:1,
		eip:1,
		etu:1;
	u16	flags;
	u8	rq;	/* Receive Queue index */
	u8	pro;	/* Layer 4 Protocol */
	u16	reserved;
@@ -688,12 +690,17 @@ struct gfar_private {
	spinlock_t lock;
	unsigned int rx_buffer_size;
	unsigned int rx_stash_size;
	unsigned int rx_stash_index;
	unsigned int tx_ring_size;
	unsigned int rx_ring_size;
	unsigned int fifo_threshold;
	unsigned int fifo_starve;
	unsigned int fifo_starve_off;

	unsigned char vlan_enable:1,
		rx_csum_enable:1,
		extended_hash:1;
		extended_hash:1,
		bd_stash_en:1;
	unsigned short padding;
	struct vlan_group *vlgrp;
	/* Info structure initialized by board setup code */
@@ -731,6 +738,6 @@ extern void stop_gfar(struct net_device *dev);
extern void gfar_halt(struct net_device *dev);
extern void gfar_phy_test(struct mii_bus *bus, struct phy_device *phydev,
		int enable, u32 regnum, u32 read);
void gfar_setup_stashing(struct net_device *dev);
void gfar_init_sysfs(struct net_device *dev);

#endif /* __GIANFAR_H */
+1 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#define MII_READ_COMMAND       0x00000001

#define GFAR_SUPPORTED (SUPPORTED_10baseT_Half \
		| SUPPORTED_10baseT_Full \
		| SUPPORTED_100baseT_Half \
		| SUPPORTED_100baseT_Full \
		| SUPPORTED_Autoneg \
Loading