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

Commit 152b92db authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (55 commits)
  ISDN, hfcsusb: Don't leak in hfcsusb_ph_info()
  netpoll: call dev_put() on error in netpoll_setup()
  net: ep93xx_eth: fix DMA API violations
  net: ep93xx_eth: drop GFP_DMA from call to dma_alloc_coherent()
  net: ep93xx_eth: allocate buffers using kmalloc()
  net: ep93xx_eth: pass struct device to DMA API functions
  ep93xx: set DMA masks for the ep93xx_eth
  vlan: Fix the ingress VLAN_FLAG_REORDER_HDR check
  dl2k: EEPROM CRC calculation wrong endianess on bigendian machine
  NET: am79c961: fix assembler warnings
  NET: am79c961: ensure multicast filter is correctly set at open
  NET: am79c961: ensure asm() statements are marked volatile
  ethtool.h: fix typos
  ep93xx_eth: Update MAINTAINERS
  ipv4: Fix packet size calculation for raw IPsec packets in __ip_append_data
  netpoll: prevent netpoll setup on slave devices
  net: pmtu_expires fixes
  gianfar:localized filer table
  iwlegacy: fix channel switch locking
  mac80211: fix IBSS teardown race
  ...
parents b99ca60c 84860c72
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1739,7 +1739,7 @@ S: Supported
F:	drivers/net/enic/

CIRRUS LOGIC EP93XX ETHERNET DRIVER
M:	Lennert Buytenhek <kernel@wantstofly.org>
M:	Hartley Sweeten <hsweeten@visionengravers.com>
L:	netdev@vger.kernel.org
S:	Maintained
F:	drivers/net/arm/ep93xx_eth.c
+5 −1
Original line number Diff line number Diff line
@@ -402,11 +402,15 @@ static struct resource ep93xx_eth_resource[] = {
	}
};

static u64 ep93xx_eth_dma_mask = DMA_BIT_MASK(32);

static struct platform_device ep93xx_eth_device = {
	.name		= "ep93xx-eth",
	.id		= -1,
	.dev		= {
		.platform_data		= &ep93xx_eth_data,
		.coherent_dma_mask	= DMA_BIT_MASK(32),
		.dma_mask		= &ep93xx_eth_dma_mask,
	},
	.num_resources	= ARRAY_SIZE(ep93xx_eth_resource),
	.resource	= ep93xx_eth_resource,
+1 −0
Original line number Diff line number Diff line
@@ -283,6 +283,7 @@ hfcsusb_ph_info(struct hfcsusb *hw)
	_queue_data(&dch->dev.D, MPH_INFORMATION_IND, MISDN_ID_ANY,
		sizeof(struct ph_info_dch) + dch->dev.nrbchan *
		sizeof(struct ph_info_ch), phi, GFP_ATOMIC);
	kfree(phi);
}

/*
+65 −61
Original line number Diff line number Diff line
@@ -50,7 +50,7 @@ static const char version[] =
#ifdef __arm__
static void write_rreg(u_long base, u_int reg, u_int val)
{
	__asm__(
	asm volatile(
	"str%?h	%1, [%2]	@ NET_RAP\n\t"
	"str%?h	%0, [%2, #-4]	@ NET_RDP"
	:
@@ -60,7 +60,7 @@ static void write_rreg(u_long base, u_int reg, u_int val)
static inline unsigned short read_rreg(u_long base_addr, u_int reg)
{
	unsigned short v;
	__asm__(
	asm volatile(
	"str%?h	%1, [%2]	@ NET_RAP\n\t"
	"ldr%?h	%0, [%2, #-4]	@ NET_RDP"
	: "=r" (v)
@@ -70,7 +70,7 @@ static inline unsigned short read_rreg(u_long base_addr, u_int reg)

static inline void write_ireg(u_long base, u_int reg, u_int val)
{
	__asm__(
	asm volatile(
	"str%?h	%1, [%2]	@ NET_RAP\n\t"
	"str%?h	%0, [%2, #8]	@ NET_IDP"
	:
@@ -80,7 +80,7 @@ static inline void write_ireg(u_long base, u_int reg, u_int val)
static inline unsigned short read_ireg(u_long base_addr, u_int reg)
{
	u_short v;
	__asm__(
	asm volatile(
	"str%?h	%1, [%2]	@ NAT_RAP\n\t"
	"ldr%?h	%0, [%2, #8]	@ NET_IDP\n\t"
	: "=r" (v)
@@ -91,47 +91,48 @@ static inline unsigned short read_ireg(u_long base_addr, u_int reg)
#define am_writeword(dev,off,val) __raw_writew(val, ISAMEM_BASE + ((off) << 1))
#define am_readword(dev,off)      __raw_readw(ISAMEM_BASE + ((off) << 1))

static inline void
static void
am_writebuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned int length)
{
	offset = ISAMEM_BASE + (offset << 1);
	length = (length + 1) & ~1;
	if ((int)buf & 2) {
		__asm__ __volatile__("str%?h	%2, [%0], #4"
		asm volatile("str%?h	%2, [%0], #4"
		 : "=&r" (offset) : "0" (offset), "r" (buf[0] | (buf[1] << 8)));
		buf += 2;
		length -= 2;
	}
	while (length > 8) {
		unsigned int tmp, tmp2;
		__asm__ __volatile__(
			"ldm%?ia	%1!, {%2, %3}\n\t"
		register unsigned int tmp asm("r2"), tmp2 asm("r3");
		asm volatile(
			"ldm%?ia	%0!, {%1, %2}"
			: "+r" (buf), "=&r" (tmp), "=&r" (tmp2));
		length -= 8;
		asm volatile(
			"str%?h	%1, [%0], #4\n\t"
			"mov%?	%1, %1, lsr #16\n\t"
			"str%?h	%1, [%0], #4\n\t"
			"str%?h	%2, [%0], #4\n\t"
			"mov%?	%2, %2, lsr #16\n\t"
			"str%?h	%2, [%0], #4\n\t"
			"str%?h	%3, [%0], #4\n\t"
			"mov%?	%3, %3, lsr #16\n\t"
			"str%?h	%3, [%0], #4"
		: "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2)
		: "0" (offset), "1" (buf));
		length -= 8;
			"str%?h	%2, [%0], #4"
		: "+r" (offset), "=&r" (tmp), "=&r" (tmp2));
	}
	while (length > 0) {
		__asm__ __volatile__("str%?h	%2, [%0], #4"
		asm volatile("str%?h	%2, [%0], #4"
		 : "=&r" (offset) : "0" (offset), "r" (buf[0] | (buf[1] << 8)));
		buf += 2;
		length -= 2;
	}
}

static inline void
static void
am_readbuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned int length)
{
	offset = ISAMEM_BASE + (offset << 1);
	length = (length + 1) & ~1;
	if ((int)buf & 2) {
		unsigned int tmp;
		__asm__ __volatile__(
		asm volatile(
			"ldr%?h	%2, [%0], #4\n\t"
			"str%?b	%2, [%1], #1\n\t"
			"mov%?	%2, %2, lsr #8\n\t"
@@ -140,12 +141,12 @@ am_readbuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned
		length -= 2;
	}
	while (length > 8) {
		unsigned int tmp, tmp2, tmp3;
		__asm__ __volatile__(
		register unsigned int tmp asm("r2"), tmp2 asm("r3"), tmp3;
		asm volatile(
			"ldr%?h	%2, [%0], #4\n\t"
			"ldr%?h	%4, [%0], #4\n\t"
			"ldr%?h	%3, [%0], #4\n\t"
			"orr%?	%2, %2, %3, lsl #16\n\t"
			"ldr%?h	%3, [%0], #4\n\t"
			"orr%?	%2, %2, %4, lsl #16\n\t"
			"ldr%?h	%4, [%0], #4\n\t"
			"orr%?	%3, %3, %4, lsl #16\n\t"
			"stm%?ia	%1!, {%2, %3}"
@@ -155,7 +156,7 @@ am_readbuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned
	}
	while (length > 0) {
		unsigned int tmp;
		__asm__ __volatile__(
		asm volatile(
			"ldr%?h	%2, [%0], #4\n\t"
			"str%?b	%2, [%1], #1\n\t"
			"mov%?	%2, %2, lsr #8\n\t"
@@ -196,6 +197,42 @@ am79c961_ramtest(struct net_device *dev, unsigned int val)
	return errorcount;
}

static void am79c961_mc_hash(char *addr, u16 *hash)
{
	if (addr[0] & 0x01) {
		int idx, bit;
		u32 crc;

		crc = ether_crc_le(ETH_ALEN, addr);

		idx = crc >> 30;
		bit = (crc >> 26) & 15;

		hash[idx] |= 1 << bit;
	}
}

static unsigned int am79c961_get_rx_mode(struct net_device *dev, u16 *hash)
{
	unsigned int mode = MODE_PORT_10BT;

	if (dev->flags & IFF_PROMISC) {
		mode |= MODE_PROMISC;
		memset(hash, 0xff, 4 * sizeof(*hash));
	} else if (dev->flags & IFF_ALLMULTI) {
		memset(hash, 0xff, 4 * sizeof(*hash));
	} else {
		struct netdev_hw_addr *ha;

		memset(hash, 0, 4 * sizeof(*hash));

		netdev_for_each_mc_addr(ha, dev)
			am79c961_mc_hash(ha->addr, hash);
	}

	return mode;
}

static void
am79c961_init_for_open(struct net_device *dev)
{
@@ -203,6 +240,7 @@ am79c961_init_for_open(struct net_device *dev)
	unsigned long flags;
	unsigned char *p;
	u_int hdr_addr, first_free_addr;
	u16 multi_hash[4], mode = am79c961_get_rx_mode(dev, multi_hash);
	int i;

	/*
@@ -218,16 +256,12 @@ am79c961_init_for_open(struct net_device *dev)
	write_ireg (dev->base_addr, 2, 0x0000); /* MODE register selects media */

	for (i = LADRL; i <= LADRH; i++)
		write_rreg (dev->base_addr, i, 0);
		write_rreg (dev->base_addr, i, multi_hash[i - LADRL]);

	for (i = PADRL, p = dev->dev_addr; i <= PADRH; i++, p += 2)
		write_rreg (dev->base_addr, i, p[0] | (p[1] << 8));

	i = MODE_PORT_10BT;
	if (dev->flags & IFF_PROMISC)
		i |= MODE_PROMISC;

	write_rreg (dev->base_addr, MODE, i);
	write_rreg (dev->base_addr, MODE, mode);
	write_rreg (dev->base_addr, POLLINT, 0);
	write_rreg (dev->base_addr, SIZERXR, -RX_BUFFERS);
	write_rreg (dev->base_addr, SIZETXR, -TX_BUFFERS);
@@ -340,21 +374,6 @@ am79c961_close(struct net_device *dev)
	return 0;
}

static void am79c961_mc_hash(char *addr, unsigned short *hash)
{
	if (addr[0] & 0x01) {
		int idx, bit;
		u32 crc;

		crc = ether_crc_le(ETH_ALEN, addr);

		idx = crc >> 30;
		bit = (crc >> 26) & 15;

		hash[idx] |= 1 << bit;
	}
}

/*
 * Set or clear promiscuous/multicast mode filter for this adapter.
 */
@@ -362,24 +381,9 @@ static void am79c961_setmulticastlist (struct net_device *dev)
{
	struct dev_priv *priv = netdev_priv(dev);
	unsigned long flags;
	unsigned short multi_hash[4], mode;
	u16 multi_hash[4], mode = am79c961_get_rx_mode(dev, multi_hash);
	int i, stopped;

	mode = MODE_PORT_10BT;

	if (dev->flags & IFF_PROMISC) {
		mode |= MODE_PROMISC;
	} else if (dev->flags & IFF_ALLMULTI) {
		memset(multi_hash, 0xff, sizeof(multi_hash));
	} else {
		struct netdev_hw_addr *ha;

		memset(multi_hash, 0x00, sizeof(multi_hash));

		netdev_for_each_mc_addr(ha, dev)
			am79c961_mc_hash(ha->addr, multi_hash);
	}

	spin_lock_irqsave(&priv->chip_lock, flags);

	stopped = read_rreg(dev->base_addr, CSR0) & CSR0_STOP;
+41 −41
Original line number Diff line number Diff line
@@ -283,10 +283,14 @@ static int ep93xx_rx(struct net_device *dev, int processed, int budget)

		skb = dev_alloc_skb(length + 2);
		if (likely(skb != NULL)) {
			struct ep93xx_rdesc *rxd = &ep->descs->rdesc[entry];
			skb_reserve(skb, 2);
			dma_sync_single_for_cpu(NULL, ep->descs->rdesc[entry].buf_addr,
			dma_sync_single_for_cpu(dev->dev.parent, rxd->buf_addr,
						length, DMA_FROM_DEVICE);
			skb_copy_to_linear_data(skb, ep->rx_buf[entry], length);
			dma_sync_single_for_device(dev->dev.parent,
						   rxd->buf_addr, length,
						   DMA_FROM_DEVICE);
			skb_put(skb, length);
			skb->protocol = eth_type_trans(skb, dev);

@@ -348,6 +352,7 @@ poll_some_more:
static int ep93xx_xmit(struct sk_buff *skb, struct net_device *dev)
{
	struct ep93xx_priv *ep = netdev_priv(dev);
	struct ep93xx_tdesc *txd;
	int entry;

	if (unlikely(skb->len > MAX_PKT_SIZE)) {
@@ -359,11 +364,14 @@ static int ep93xx_xmit(struct sk_buff *skb, struct net_device *dev)
	entry = ep->tx_pointer;
	ep->tx_pointer = (ep->tx_pointer + 1) & (TX_QUEUE_ENTRIES - 1);

	ep->descs->tdesc[entry].tdesc1 =
		TDESC1_EOF | (entry << 16) | (skb->len & 0xfff);
	txd = &ep->descs->tdesc[entry];

	txd->tdesc1 = TDESC1_EOF | (entry << 16) | (skb->len & 0xfff);
	dma_sync_single_for_cpu(dev->dev.parent, txd->buf_addr, skb->len,
				DMA_TO_DEVICE);
	skb_copy_and_csum_dev(skb, ep->tx_buf[entry]);
	dma_sync_single_for_cpu(NULL, ep->descs->tdesc[entry].buf_addr,
				skb->len, DMA_TO_DEVICE);
	dma_sync_single_for_device(dev->dev.parent, txd->buf_addr, skb->len,
				   DMA_TO_DEVICE);
	dev_kfree_skb(skb);

	spin_lock_irq(&ep->tx_pending_lock);
@@ -457,89 +465,80 @@ static irqreturn_t ep93xx_irq(int irq, void *dev_id)

static void ep93xx_free_buffers(struct ep93xx_priv *ep)
{
	struct device *dev = ep->dev->dev.parent;
	int i;

	for (i = 0; i < RX_QUEUE_ENTRIES; i += 2) {
	for (i = 0; i < RX_QUEUE_ENTRIES; i++) {
		dma_addr_t d;

		d = ep->descs->rdesc[i].buf_addr;
		if (d)
			dma_unmap_single(NULL, d, PAGE_SIZE, DMA_FROM_DEVICE);
			dma_unmap_single(dev, d, PKT_BUF_SIZE, DMA_FROM_DEVICE);

		if (ep->rx_buf[i] != NULL)
			free_page((unsigned long)ep->rx_buf[i]);
			kfree(ep->rx_buf[i]);
	}

	for (i = 0; i < TX_QUEUE_ENTRIES; i += 2) {
	for (i = 0; i < TX_QUEUE_ENTRIES; i++) {
		dma_addr_t d;

		d = ep->descs->tdesc[i].buf_addr;
		if (d)
			dma_unmap_single(NULL, d, PAGE_SIZE, DMA_TO_DEVICE);
			dma_unmap_single(dev, d, PKT_BUF_SIZE, DMA_TO_DEVICE);

		if (ep->tx_buf[i] != NULL)
			free_page((unsigned long)ep->tx_buf[i]);
			kfree(ep->tx_buf[i]);
	}

	dma_free_coherent(NULL, sizeof(struct ep93xx_descs), ep->descs,
	dma_free_coherent(dev, sizeof(struct ep93xx_descs), ep->descs,
							ep->descs_dma_addr);
}

/*
 * The hardware enforces a sub-2K maximum packet size, so we put
 * two buffers on every hardware page.
 */
static int ep93xx_alloc_buffers(struct ep93xx_priv *ep)
{
	struct device *dev = ep->dev->dev.parent;
	int i;

	ep->descs = dma_alloc_coherent(NULL, sizeof(struct ep93xx_descs),
				&ep->descs_dma_addr, GFP_KERNEL | GFP_DMA);
	ep->descs = dma_alloc_coherent(dev, sizeof(struct ep93xx_descs),
				&ep->descs_dma_addr, GFP_KERNEL);
	if (ep->descs == NULL)
		return 1;

	for (i = 0; i < RX_QUEUE_ENTRIES; i += 2) {
		void *page;
	for (i = 0; i < RX_QUEUE_ENTRIES; i++) {
		void *buf;
		dma_addr_t d;

		page = (void *)__get_free_page(GFP_KERNEL | GFP_DMA);
		if (page == NULL)
		buf = kmalloc(PKT_BUF_SIZE, GFP_KERNEL);
		if (buf == NULL)
			goto err;

		d = dma_map_single(NULL, page, PAGE_SIZE, DMA_FROM_DEVICE);
		if (dma_mapping_error(NULL, d)) {
			free_page((unsigned long)page);
		d = dma_map_single(dev, buf, PKT_BUF_SIZE, DMA_FROM_DEVICE);
		if (dma_mapping_error(dev, d)) {
			kfree(buf);
			goto err;
		}

		ep->rx_buf[i] = page;
		ep->rx_buf[i] = buf;
		ep->descs->rdesc[i].buf_addr = d;
		ep->descs->rdesc[i].rdesc1 = (i << 16) | PKT_BUF_SIZE;

		ep->rx_buf[i + 1] = page + PKT_BUF_SIZE;
		ep->descs->rdesc[i + 1].buf_addr = d + PKT_BUF_SIZE;
		ep->descs->rdesc[i + 1].rdesc1 = ((i + 1) << 16) | PKT_BUF_SIZE;
	}

	for (i = 0; i < TX_QUEUE_ENTRIES; i += 2) {
		void *page;
	for (i = 0; i < TX_QUEUE_ENTRIES; i++) {
		void *buf;
		dma_addr_t d;

		page = (void *)__get_free_page(GFP_KERNEL | GFP_DMA);
		if (page == NULL)
		buf = kmalloc(PKT_BUF_SIZE, GFP_KERNEL);
		if (buf == NULL)
			goto err;

		d = dma_map_single(NULL, page, PAGE_SIZE, DMA_TO_DEVICE);
		if (dma_mapping_error(NULL, d)) {
			free_page((unsigned long)page);
		d = dma_map_single(dev, buf, PKT_BUF_SIZE, DMA_TO_DEVICE);
		if (dma_mapping_error(dev, d)) {
			kfree(buf);
			goto err;
		}

		ep->tx_buf[i] = page;
		ep->tx_buf[i] = buf;
		ep->descs->tdesc[i].buf_addr = d;

		ep->tx_buf[i + 1] = page + PKT_BUF_SIZE;
		ep->descs->tdesc[i + 1].buf_addr = d + PKT_BUF_SIZE;
	}

	return 0;
@@ -829,6 +828,7 @@ static int ep93xx_eth_probe(struct platform_device *pdev)
	}
	ep = netdev_priv(dev);
	ep->dev = dev;
	SET_NETDEV_DEV(dev, &pdev->dev);
	netif_napi_add(dev, &ep->napi, ep93xx_poll, 64);

	platform_set_drvdata(pdev, dev);
Loading