Netdev List
 help / color / mirror / Atom feed
* [PATCH 06/14] net/fec: put the ioremap cookie immediately into a void __iomem pointer
From: Uwe Kleine-König @ 2011-02-11 10:32 UTC (permalink / raw)
  To: netdev; +Cc: Shawn Guo, kernel
In-Reply-To: <1297420342-17739-1-git-send-email-u.kleine-koenig@pengutronix.de>

Saving it first into struct net_device->base_addr (which is an unsigned
long) is pointless and only needs to use more casts than necessary.

Noticed-by: Lothar Waßmann <LW@KARO-electronics.de>
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/net/fec.c |    9 ++++-----
 1 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index 9a25e1e..14eb660 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -1170,7 +1170,6 @@ static int fec_enet_init(struct net_device *dev)
 
 	spin_lock_init(&fep->hw_lock);
 
-	fep->hwp = (void __iomem *)dev->base_addr;
 	fep->netdev = dev;
 
 	/* Get the Ethernet address */
@@ -1387,10 +1386,10 @@ fec_probe(struct platform_device *pdev)
 	/* setup board info structure */
 	fep = netdev_priv(ndev);
 
-	ndev->base_addr = (unsigned long)ioremap(r->start, resource_size(r));
+	fep->hwp = ioremap(r->start, resource_size(r));
 	fep->pdev = pdev;
 
-	if (!ndev->base_addr) {
+	if (!fep->hwp) {
 		ret = -ENOMEM;
 		goto failed_ioremap;
 	}
@@ -1453,7 +1452,7 @@ failed_clk:
 			free_irq(irq, ndev);
 	}
 failed_irq:
-	iounmap((void __iomem *)ndev->base_addr);
+	iounmap(fep->hwp);
 failed_ioremap:
 	free_netdev(ndev);
 failed_alloc_etherdev:
@@ -1475,7 +1474,7 @@ fec_drv_remove(struct platform_device *pdev)
 	fec_enet_mii_remove(fep);
 	clk_disable(fep->clk);
 	clk_put(fep->clk);
-	iounmap((void __iomem *)ndev->base_addr);
+	iounmap(fep->hwp);
 	unregister_netdev(ndev);
 	free_netdev(ndev);
 
-- 
1.7.2.3


^ permalink raw reply related

* [PATCH 02/14] net/fec: release mem_region requested in probe in error path and remove
From: Uwe Kleine-König @ 2011-02-11 10:32 UTC (permalink / raw)
  To: netdev; +Cc: Shawn Guo, kernel
In-Reply-To: <1297420342-17739-1-git-send-email-u.kleine-koenig@pengutronix.de>

Noticed-by: Lothar Waßmann <LW@KARO-electronics.de>
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/net/fec.c |   14 ++++++++++++--
 1 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index 3e6e923..b079826 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -1377,8 +1377,10 @@ fec_probe(struct platform_device *pdev)
 
 	/* Init network device */
 	ndev = alloc_etherdev(sizeof(struct fec_enet_private));
-	if (!ndev)
-		return -ENOMEM;
+	if (!ndev) {
+		ret = -ENOMEM;
+		goto failed_alloc_etherdev;
+	}
 
 	SET_NETDEV_DEV(ndev, &pdev->dev);
 
@@ -1456,6 +1458,8 @@ failed_irq:
 	iounmap((void __iomem *)ndev->base_addr);
 failed_ioremap:
 	free_netdev(ndev);
+failed_alloc_etherdev:
+	release_mem_region(r->start, resource_size(r));
 
 	return ret;
 }
@@ -1465,6 +1469,7 @@ fec_drv_remove(struct platform_device *pdev)
 {
 	struct net_device *ndev = platform_get_drvdata(pdev);
 	struct fec_enet_private *fep = netdev_priv(ndev);
+	struct resource *r;
 
 	platform_set_drvdata(pdev, NULL);
 
@@ -1475,6 +1480,11 @@ fec_drv_remove(struct platform_device *pdev)
 	iounmap((void __iomem *)ndev->base_addr);
 	unregister_netdev(ndev);
 	free_netdev(ndev);
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	BUG_ON(!r);
+	release_mem_region(r->start, resource_size(r));
+
 	return 0;
 }
 
-- 
1.7.2.3


^ permalink raw reply related

* [PATCH 07/14] net/fec: consolidate all i.MX options to CONFIG_ARM
From: Uwe Kleine-König @ 2011-02-11 10:32 UTC (permalink / raw)
  To: netdev; +Cc: Shawn Guo, kernel
In-Reply-To: <1297420342-17739-1-git-send-email-u.kleine-koenig@pengutronix.de>

Moreover stop listing all i.MX platforms featuring a FEC, and use
the platform's config symbol that selects registration of a fec device
instead.  This might make it easier to add new platforms.

Set default = y for ARMs having a fec to reduce defconfig sizes.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/net/Kconfig |    3 ++-
 drivers/net/fec.c   |    5 ++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 0382332..65027a7 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1944,7 +1944,8 @@ config 68360_ENET
 config FEC
 	bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)"
 	depends on M523x || M527x || M5272 || M528x || M520x || M532x || \
-		MACH_MX27 || ARCH_MX35 || ARCH_MX25 || ARCH_MX5 || SOC_IMX28
+		IMX_HAVE_PLATFORM_FEC || MXS_HAVE_PLATFORM_FEC
+	default IMX_HAVE_PLATFORM_FEC || MXS_HAVE_PLATFORM_FEC if ARM
 	select PHYLIB
 	help
 	  Say Y here if you want to use the built-in 10/100 Fast ethernet
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index 14eb660..dd4e580 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -54,7 +54,7 @@
 
 #include "fec.h"
 
-#if defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28)
+#if defined(CONFIG_ARM)
 #define FEC_ALIGNMENT	0xf
 #else
 #define FEC_ALIGNMENT	0x3
@@ -147,8 +147,7 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
  * account when setting it.
  */
 #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
-    defined(CONFIG_M520x) || defined(CONFIG_M532x) || \
-    defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28)
+    defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM)
 #define	OPT_FRAME_SIZE	(PKT_MAXBUF_SIZE << 16)
 #else
 #define	OPT_FRAME_SIZE	0
-- 
1.7.2.3


^ permalink raw reply related

* [PATCH 09/14] net/fec: consistenly name struct net_device pointers "ndev"
From: Uwe Kleine-König @ 2011-02-11 10:32 UTC (permalink / raw)
  To: netdev; +Cc: Shawn Guo, kernel
In-Reply-To: <1297420342-17739-1-git-send-email-u.kleine-koenig@pengutronix.de>

A variable named "dev" usually (usually subjective) points to a struct
device.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/net/fec.c |  242 ++++++++++++++++++++++++++--------------------------
 1 files changed, 121 insertions(+), 121 deletions(-)

diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index d3dbff5..c70503a 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -206,11 +206,11 @@ struct fec_enet_private {
 };
 
 static irqreturn_t fec_enet_interrupt(int irq, void * dev_id);
-static void fec_enet_tx(struct net_device *dev);
-static void fec_enet_rx(struct net_device *dev);
-static int fec_enet_close(struct net_device *dev);
-static void fec_restart(struct net_device *dev, int duplex);
-static void fec_stop(struct net_device *dev);
+static void fec_enet_tx(struct net_device *ndev);
+static void fec_enet_rx(struct net_device *ndev);
+static int fec_enet_close(struct net_device *ndev);
+static void fec_restart(struct net_device *ndev, int duplex);
+static void fec_stop(struct net_device *ndev);
 
 /* FEC MII MMFR bits definition */
 #define FEC_MMFR_ST		(1 << 30)
@@ -238,9 +238,9 @@ static void *swap_buffer(void *bufaddr, int len)
 }
 
 static netdev_tx_t
-fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
+fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	const struct platform_device_id *id_entry =
 				platform_get_device_id(fep->pdev);
 	struct bufdesc *bdp;
@@ -261,9 +261,9 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	if (status & BD_ENET_TX_READY) {
 		/* Ooops.  All transmit buffers are full.  Bail out.
-		 * This should not happen, since dev->tbusy should be set.
+		 * This should not happen, since ndev->tbusy should be set.
 		 */
-		printk("%s: tx queue full!.\n", dev->name);
+		printk("%s: tx queue full!.\n", ndev->name);
 		spin_unlock_irqrestore(&fep->hw_lock, flags);
 		return NETDEV_TX_BUSY;
 	}
@@ -298,13 +298,13 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	/* Save skb pointer */
 	fep->tx_skbuff[fep->skb_cur] = skb;
 
-	dev->stats.tx_bytes += skb->len;
+	ndev->stats.tx_bytes += skb->len;
 	fep->skb_cur = (fep->skb_cur+1) & TX_RING_MOD_MASK;
 
 	/* Push the data cache so the CPM does not get stale memory
 	 * data.
 	 */
-	bdp->cbd_bufaddr = dma_map_single(&dev->dev, bufaddr,
+	bdp->cbd_bufaddr = dma_map_single(&ndev->dev, bufaddr,
 			FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE);
 
 	/* Send it on its way.  Tell FEC it's ready, interrupt when done,
@@ -325,7 +325,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	if (bdp == fep->dirty_tx) {
 		fep->tx_full = 1;
-		netif_stop_queue(dev);
+		netif_stop_queue(ndev);
 	}
 
 	fep->cur_tx = bdp;
@@ -336,22 +336,22 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 }
 
 static void
-fec_timeout(struct net_device *dev)
+fec_timeout(struct net_device *ndev)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 
-	dev->stats.tx_errors++;
+	ndev->stats.tx_errors++;
 
-	fec_restart(dev, fep->full_duplex);
-	netif_wake_queue(dev);
+	fec_restart(ndev, fep->full_duplex);
+	netif_wake_queue(ndev);
 }
 
 static irqreturn_t
-fec_enet_interrupt(int irq, void * dev_id)
+fec_enet_interrupt(int irq, void *dev_id)
 {
-	struct	net_device *dev = dev_id;
-	struct fec_enet_private *fep = netdev_priv(dev);
-	uint	int_events;
+	struct net_device *ndev = dev_id;
+	struct fec_enet_private *fep = netdev_priv(ndev);
+	uint int_events;
 	irqreturn_t ret = IRQ_NONE;
 
 	do {
@@ -360,7 +360,7 @@ fec_enet_interrupt(int irq, void * dev_id)
 
 		if (int_events & FEC_ENET_RXF) {
 			ret = IRQ_HANDLED;
-			fec_enet_rx(dev);
+			fec_enet_rx(ndev);
 		}
 
 		/* Transmit OK, or non-fatal error. Update the buffer
@@ -369,7 +369,7 @@ fec_enet_interrupt(int irq, void * dev_id)
 		 */
 		if (int_events & FEC_ENET_TXF) {
 			ret = IRQ_HANDLED;
-			fec_enet_tx(dev);
+			fec_enet_tx(ndev);
 		}
 
 		if (int_events & FEC_ENET_MII) {
@@ -383,14 +383,14 @@ fec_enet_interrupt(int irq, void * dev_id)
 
 
 static void
-fec_enet_tx(struct net_device *dev)
+fec_enet_tx(struct net_device *ndev)
 {
 	struct	fec_enet_private *fep;
 	struct bufdesc *bdp;
 	unsigned short status;
 	struct	sk_buff	*skb;
 
-	fep = netdev_priv(dev);
+	fep = netdev_priv(ndev);
 	spin_lock(&fep->hw_lock);
 	bdp = fep->dirty_tx;
 
@@ -398,7 +398,7 @@ fec_enet_tx(struct net_device *dev)
 		if (bdp == fep->cur_tx && fep->tx_full == 0)
 			break;
 
-		dma_unmap_single(&dev->dev, bdp->cbd_bufaddr, FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE);
+		dma_unmap_single(&ndev->dev, bdp->cbd_bufaddr, FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE);
 		bdp->cbd_bufaddr = 0;
 
 		skb = fep->tx_skbuff[fep->skb_dirty];
@@ -406,19 +406,19 @@ fec_enet_tx(struct net_device *dev)
 		if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC |
 				   BD_ENET_TX_RL | BD_ENET_TX_UN |
 				   BD_ENET_TX_CSL)) {
-			dev->stats.tx_errors++;
+			ndev->stats.tx_errors++;
 			if (status & BD_ENET_TX_HB)  /* No heartbeat */
-				dev->stats.tx_heartbeat_errors++;
+				ndev->stats.tx_heartbeat_errors++;
 			if (status & BD_ENET_TX_LC)  /* Late collision */
-				dev->stats.tx_window_errors++;
+				ndev->stats.tx_window_errors++;
 			if (status & BD_ENET_TX_RL)  /* Retrans limit */
-				dev->stats.tx_aborted_errors++;
+				ndev->stats.tx_aborted_errors++;
 			if (status & BD_ENET_TX_UN)  /* Underrun */
-				dev->stats.tx_fifo_errors++;
+				ndev->stats.tx_fifo_errors++;
 			if (status & BD_ENET_TX_CSL) /* Carrier lost */
-				dev->stats.tx_carrier_errors++;
+				ndev->stats.tx_carrier_errors++;
 		} else {
-			dev->stats.tx_packets++;
+			ndev->stats.tx_packets++;
 		}
 
 		if (status & BD_ENET_TX_READY)
@@ -428,7 +428,7 @@ fec_enet_tx(struct net_device *dev)
 		 * but we eventually sent the packet OK.
 		 */
 		if (status & BD_ENET_TX_DEF)
-			dev->stats.collisions++;
+			ndev->stats.collisions++;
 
 		/* Free the sk buffer associated with this last transmit */
 		dev_kfree_skb_any(skb);
@@ -445,8 +445,8 @@ fec_enet_tx(struct net_device *dev)
 		 */
 		if (fep->tx_full) {
 			fep->tx_full = 0;
-			if (netif_queue_stopped(dev))
-				netif_wake_queue(dev);
+			if (netif_queue_stopped(ndev))
+				netif_wake_queue(ndev);
 		}
 	}
 	fep->dirty_tx = bdp;
@@ -460,9 +460,9 @@ fec_enet_tx(struct net_device *dev)
  * effectively tossing the packet.
  */
 static void
-fec_enet_rx(struct net_device *dev)
+fec_enet_rx(struct net_device *ndev)
 {
-	struct	fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	const struct platform_device_id *id_entry =
 				platform_get_device_id(fep->pdev);
 	struct bufdesc *bdp;
@@ -496,17 +496,17 @@ fec_enet_rx(struct net_device *dev)
 		/* Check for errors. */
 		if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO |
 			   BD_ENET_RX_CR | BD_ENET_RX_OV)) {
-			dev->stats.rx_errors++;
+			ndev->stats.rx_errors++;
 			if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH)) {
 				/* Frame too long or too short. */
-				dev->stats.rx_length_errors++;
+				ndev->stats.rx_length_errors++;
 			}
 			if (status & BD_ENET_RX_NO)	/* Frame alignment */
-				dev->stats.rx_frame_errors++;
+				ndev->stats.rx_frame_errors++;
 			if (status & BD_ENET_RX_CR)	/* CRC Error */
-				dev->stats.rx_crc_errors++;
+				ndev->stats.rx_crc_errors++;
 			if (status & BD_ENET_RX_OV)	/* FIFO overrun */
-				dev->stats.rx_fifo_errors++;
+				ndev->stats.rx_fifo_errors++;
 		}
 
 		/* Report late collisions as a frame error.
@@ -514,15 +514,15 @@ fec_enet_rx(struct net_device *dev)
 		 * have in the buffer.  So, just drop this frame on the floor.
 		 */
 		if (status & BD_ENET_RX_CL) {
-			dev->stats.rx_errors++;
-			dev->stats.rx_frame_errors++;
+			ndev->stats.rx_errors++;
+			ndev->stats.rx_frame_errors++;
 			goto rx_processing_done;
 		}
 
 		/* Process the incoming frame. */
-		dev->stats.rx_packets++;
+		ndev->stats.rx_packets++;
 		pkt_len = bdp->cbd_datlen;
-		dev->stats.rx_bytes += pkt_len;
+		ndev->stats.rx_bytes += pkt_len;
 		data = (__u8*)__va(bdp->cbd_bufaddr);
 
 	        dma_unmap_single(NULL, bdp->cbd_bufaddr, bdp->cbd_datlen,
@@ -540,13 +540,13 @@ fec_enet_rx(struct net_device *dev)
 
 		if (unlikely(!skb)) {
 			printk("%s: Memory squeeze, dropping packet.\n",
-					dev->name);
-			dev->stats.rx_dropped++;
+					ndev->name);
+			ndev->stats.rx_dropped++;
 		} else {
 			skb_reserve(skb, NET_IP_ALIGN);
 			skb_put(skb, pkt_len - 4);	/* Make room */
 			skb_copy_to_linear_data(skb, data, pkt_len - 4);
-			skb->protocol = eth_type_trans(skb, dev);
+			skb->protocol = eth_type_trans(skb, ndev);
 			netif_rx(skb);
 		}
 
@@ -577,9 +577,9 @@ rx_processing_done:
 }
 
 /* ------------------------------------------------------------------------- */
-static void __inline__ fec_get_mac(struct net_device *dev)
+static void __inline__ fec_get_mac(struct net_device *ndev)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	struct fec_platform_data *pdata = fep->pdev->dev.platform_data;
 	unsigned char *iap, tmpaddr[ETH_ALEN];
 
@@ -615,11 +615,11 @@ static void __inline__ fec_get_mac(struct net_device *dev)
 		iap = &tmpaddr[0];
 	}
 
-	memcpy(dev->dev_addr, iap, ETH_ALEN);
+	memcpy(ndev->dev_addr, iap, ETH_ALEN);
 
 	/* Adjust MAC if using macaddr */
 	if (iap == macaddr)
-		 dev->dev_addr[ETH_ALEN-1] = macaddr[ETH_ALEN-1] + fep->pdev->id;
+		 ndev->dev_addr[ETH_ALEN-1] = macaddr[ETH_ALEN-1] + fep->pdev->id;
 }
 
 /* ------------------------------------------------------------------------- */
@@ -627,9 +627,9 @@ static void __inline__ fec_get_mac(struct net_device *dev)
 /*
  * Phy section
  */
-static void fec_enet_adjust_link(struct net_device *dev)
+static void fec_enet_adjust_link(struct net_device *ndev)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	struct phy_device *phy_dev = fep->phy_dev;
 	unsigned long flags;
 
@@ -646,7 +646,7 @@ static void fec_enet_adjust_link(struct net_device *dev)
 	/* Duplex link change */
 	if (phy_dev->link) {
 		if (fep->full_duplex != phy_dev->duplex) {
-			fec_restart(dev, phy_dev->duplex);
+			fec_restart(ndev, phy_dev->duplex);
 			status_change = 1;
 		}
 	}
@@ -655,9 +655,9 @@ static void fec_enet_adjust_link(struct net_device *dev)
 	if (phy_dev->link != fep->link) {
 		fep->link = phy_dev->link;
 		if (phy_dev->link)
-			fec_restart(dev, phy_dev->duplex);
+			fec_restart(ndev, phy_dev->duplex);
 		else
-			fec_stop(dev);
+			fec_stop(ndev);
 		status_change = 1;
 	}
 
@@ -726,9 +726,9 @@ static int fec_enet_mdio_reset(struct mii_bus *bus)
 	return 0;
 }
 
-static int fec_enet_mii_probe(struct net_device *dev)
+static int fec_enet_mii_probe(struct net_device *ndev)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	struct phy_device *phy_dev = NULL;
 	char mdio_bus_id[MII_BUS_ID_SIZE];
 	char phy_name[MII_BUS_ID_SIZE + 3];
@@ -753,16 +753,16 @@ static int fec_enet_mii_probe(struct net_device *dev)
 
 	if (phy_id >= PHY_MAX_ADDR) {
 		printk(KERN_INFO "%s: no PHY, assuming direct connection "
-			"to switch\n", dev->name);
+			"to switch\n", ndev->name);
 		strncpy(mdio_bus_id, "0", MII_BUS_ID_SIZE);
 		phy_id = 0;
 	}
 
 	snprintf(phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id);
-	phy_dev = phy_connect(dev, phy_name, &fec_enet_adjust_link, 0,
+	phy_dev = phy_connect(ndev, phy_name, &fec_enet_adjust_link, 0,
 		PHY_INTERFACE_MODE_MII);
 	if (IS_ERR(phy_dev)) {
-		printk(KERN_ERR "%s: could not attach to PHY\n", dev->name);
+		printk(KERN_ERR "%s: could not attach to PHY\n", ndev->name);
 		return PTR_ERR(phy_dev);
 	}
 
@@ -775,7 +775,7 @@ static int fec_enet_mii_probe(struct net_device *dev)
 	fep->full_duplex = 0;
 
 	printk(KERN_INFO "%s: Freescale FEC PHY driver [%s] "
-		"(mii_bus:phy_addr=%s, irq=%d)\n", dev->name,
+		"(mii_bus:phy_addr=%s, irq=%d)\n", ndev->name,
 		fep->phy_dev->drv->name, dev_name(&fep->phy_dev->dev),
 		fep->phy_dev->irq);
 
@@ -785,8 +785,8 @@ static int fec_enet_mii_probe(struct net_device *dev)
 static int fec_enet_mii_init(struct platform_device *pdev)
 {
 	static struct mii_bus *fec0_mii_bus;
-	struct net_device *dev = platform_get_drvdata(pdev);
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct net_device *ndev = platform_get_drvdata(pdev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	const struct platform_device_id *id_entry =
 				platform_get_device_id(fep->pdev);
 	int err = -ENXIO, i;
@@ -844,7 +844,7 @@ static int fec_enet_mii_init(struct platform_device *pdev)
 	for (i = 0; i < PHY_MAX_ADDR; i++)
 		fep->mii_bus->irq[i] = PHY_POLL;
 
-	platform_set_drvdata(dev, fep->mii_bus);
+	platform_set_drvdata(ndev, fep->mii_bus);
 
 	if (mdiobus_register(fep->mii_bus))
 		goto err_out_free_mdio_irq;
@@ -872,10 +872,10 @@ static void fec_enet_mii_remove(struct fec_enet_private *fep)
 	mdiobus_free(fep->mii_bus);
 }
 
-static int fec_enet_get_settings(struct net_device *dev,
+static int fec_enet_get_settings(struct net_device *ndev,
 				  struct ethtool_cmd *cmd)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	struct phy_device *phydev = fep->phy_dev;
 
 	if (!phydev)
@@ -884,10 +884,10 @@ static int fec_enet_get_settings(struct net_device *dev,
 	return phy_ethtool_gset(phydev, cmd);
 }
 
-static int fec_enet_set_settings(struct net_device *dev,
+static int fec_enet_set_settings(struct net_device *ndev,
 				 struct ethtool_cmd *cmd)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	struct phy_device *phydev = fep->phy_dev;
 
 	if (!phydev)
@@ -896,14 +896,14 @@ static int fec_enet_set_settings(struct net_device *dev,
 	return phy_ethtool_sset(phydev, cmd);
 }
 
-static void fec_enet_get_drvinfo(struct net_device *dev,
+static void fec_enet_get_drvinfo(struct net_device *ndev,
 				 struct ethtool_drvinfo *info)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 
 	strcpy(info->driver, fep->pdev->dev.driver->name);
 	strcpy(info->version, "Revision: 1.0");
-	strcpy(info->bus_info, dev_name(&dev->dev));
+	strcpy(info->bus_info, dev_name(&ndev->dev));
 }
 
 static struct ethtool_ops fec_enet_ethtool_ops = {
@@ -913,12 +913,12 @@ static struct ethtool_ops fec_enet_ethtool_ops = {
 	.get_link		= ethtool_op_get_link,
 };
 
-static int fec_enet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	struct phy_device *phydev = fep->phy_dev;
 
-	if (!netif_running(dev))
+	if (!netif_running(ndev))
 		return -EINVAL;
 
 	if (!phydev)
@@ -927,9 +927,9 @@ static int fec_enet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 	return phy_mii_ioctl(phydev, rq, cmd);
 }
 
-static void fec_enet_free_buffers(struct net_device *dev)
+static void fec_enet_free_buffers(struct net_device *ndev)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	int i;
 	struct sk_buff *skb;
 	struct bufdesc	*bdp;
@@ -939,7 +939,7 @@ static void fec_enet_free_buffers(struct net_device *dev)
 		skb = fep->rx_skbuff[i];
 
 		if (bdp->cbd_bufaddr)
-			dma_unmap_single(&dev->dev, bdp->cbd_bufaddr,
+			dma_unmap_single(&ndev->dev, bdp->cbd_bufaddr,
 					FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
 		if (skb)
 			dev_kfree_skb(skb);
@@ -951,9 +951,9 @@ static void fec_enet_free_buffers(struct net_device *dev)
 		kfree(fep->tx_bounce[i]);
 }
 
-static int fec_enet_alloc_buffers(struct net_device *dev)
+static int fec_enet_alloc_buffers(struct net_device *ndev)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	int i;
 	struct sk_buff *skb;
 	struct bufdesc	*bdp;
@@ -962,12 +962,12 @@ static int fec_enet_alloc_buffers(struct net_device *dev)
 	for (i = 0; i < RX_RING_SIZE; i++) {
 		skb = dev_alloc_skb(FEC_ENET_RX_FRSIZE);
 		if (!skb) {
-			fec_enet_free_buffers(dev);
+			fec_enet_free_buffers(ndev);
 			return -ENOMEM;
 		}
 		fep->rx_skbuff[i] = skb;
 
-		bdp->cbd_bufaddr = dma_map_single(&dev->dev, skb->data,
+		bdp->cbd_bufaddr = dma_map_single(&ndev->dev, skb->data,
 				FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
 		bdp->cbd_sc = BD_ENET_RX_EMPTY;
 		bdp++;
@@ -994,47 +994,47 @@ static int fec_enet_alloc_buffers(struct net_device *dev)
 }
 
 static int
-fec_enet_open(struct net_device *dev)
+fec_enet_open(struct net_device *ndev)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	int ret;
 
 	/* I should reset the ring buffers here, but I don't yet know
 	 * a simple way to do that.
 	 */
 
-	ret = fec_enet_alloc_buffers(dev);
+	ret = fec_enet_alloc_buffers(ndev);
 	if (ret)
 		return ret;
 
 	/* Probe and connect to PHY when open the interface */
-	ret = fec_enet_mii_probe(dev);
+	ret = fec_enet_mii_probe(ndev);
 	if (ret) {
-		fec_enet_free_buffers(dev);
+		fec_enet_free_buffers(ndev);
 		return ret;
 	}
 	phy_start(fep->phy_dev);
-	netif_start_queue(dev);
+	netif_start_queue(ndev);
 	fep->opened = 1;
 	return 0;
 }
 
 static int
-fec_enet_close(struct net_device *dev)
+fec_enet_close(struct net_device *ndev)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 
 	/* Don't know what to do yet. */
 	fep->opened = 0;
-	netif_stop_queue(dev);
-	fec_stop(dev);
+	netif_stop_queue(ndev);
+	fec_stop(ndev);
 
 	if (fep->phy_dev) {
 		phy_stop(fep->phy_dev);
 		phy_disconnect(fep->phy_dev);
 	}
 
-        fec_enet_free_buffers(dev);
+        fec_enet_free_buffers(ndev);
 
 	return 0;
 }
@@ -1052,14 +1052,14 @@ fec_enet_close(struct net_device *dev)
 #define HASH_BITS	6		/* #bits in hash */
 #define CRC32_POLY	0xEDB88320
 
-static void set_multicast_list(struct net_device *dev)
+static void set_multicast_list(struct net_device *ndev)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	struct netdev_hw_addr *ha;
 	unsigned int i, bit, data, crc, tmp;
 	unsigned char hash;
 
-	if (dev->flags & IFF_PROMISC) {
+	if (ndev->flags & IFF_PROMISC) {
 		tmp = readl(fep->hwp + FEC_R_CNTRL);
 		tmp |= 0x8;
 		writel(tmp, fep->hwp + FEC_R_CNTRL);
@@ -1070,7 +1070,7 @@ static void set_multicast_list(struct net_device *dev)
 	tmp &= ~0x8;
 	writel(tmp, fep->hwp + FEC_R_CNTRL);
 
-	if (dev->flags & IFF_ALLMULTI) {
+	if (ndev->flags & IFF_ALLMULTI) {
 		/* Catch all multicast addresses, so set the
 		 * filter to all 1's
 		 */
@@ -1085,7 +1085,7 @@ static void set_multicast_list(struct net_device *dev)
 	writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
 	writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
 
-	netdev_for_each_mc_addr(ha, dev) {
+	netdev_for_each_mc_addr(ha, ndev) {
 		/* Only support group multicast for now */
 		if (!(ha->addr[0] & 1))
 			continue;
@@ -1093,7 +1093,7 @@ static void set_multicast_list(struct net_device *dev)
 		/* calculate crc32 value of mac address */
 		crc = 0xffffffff;
 
-		for (i = 0; i < dev->addr_len; i++) {
+		for (i = 0; i < ndev->addr_len; i++) {
 			data = ha->addr[i];
 			for (bit = 0; bit < 8; bit++, data >>= 1) {
 				crc = (crc >> 1) ^
@@ -1120,20 +1120,20 @@ static void set_multicast_list(struct net_device *dev)
 
 /* Set a MAC change in hardware. */
 static int
-fec_set_mac_address(struct net_device *dev, void *p)
+fec_set_mac_address(struct net_device *ndev, void *p)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	struct sockaddr *addr = p;
 
 	if (!is_valid_ether_addr(addr->sa_data))
 		return -EADDRNOTAVAIL;
 
-	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+	memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len);
 
-	writel(dev->dev_addr[3] | (dev->dev_addr[2] << 8) |
-		(dev->dev_addr[1] << 16) | (dev->dev_addr[0] << 24),
+	writel(ndev->dev_addr[3] | (ndev->dev_addr[2] << 8) |
+		(ndev->dev_addr[1] << 16) | (ndev->dev_addr[0] << 24),
 		fep->hwp + FEC_ADDR_LOW);
-	writel((dev->dev_addr[5] << 16) | (dev->dev_addr[4] << 24),
+	writel((ndev->dev_addr[5] << 16) | (ndev->dev_addr[4] << 24),
 		fep->hwp + FEC_ADDR_HIGH);
 	return 0;
 }
@@ -1154,9 +1154,9 @@ static const struct net_device_ops fec_netdev_ops = {
   * XXX:  We need to clean up on failure exits here.
   *
   */
-static int fec_enet_init(struct net_device *dev)
+static int fec_enet_init(struct net_device *ndev)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	struct bufdesc *cbd_base;
 	struct bufdesc *bdp;
 	int i;
@@ -1171,19 +1171,19 @@ static int fec_enet_init(struct net_device *dev)
 
 	spin_lock_init(&fep->hw_lock);
 
-	fep->netdev = dev;
+	fep->netdev = ndev;
 
 	/* Get the Ethernet address */
-	fec_get_mac(dev);
+	fec_get_mac(ndev);
 
 	/* Set receive and transmit descriptor base. */
 	fep->rx_bd_base = cbd_base;
 	fep->tx_bd_base = cbd_base + RX_RING_SIZE;
 
 	/* The FEC Ethernet specific entries in the device structure */
-	dev->watchdog_timeo = TX_TIMEOUT;
-	dev->netdev_ops = &fec_netdev_ops;
-	dev->ethtool_ops = &fec_enet_ethtool_ops;
+	ndev->watchdog_timeo = TX_TIMEOUT;
+	ndev->netdev_ops = &fec_netdev_ops;
+	ndev->ethtool_ops = &fec_enet_ethtool_ops;
 
 	/* Initialize the receive buffer descriptors. */
 	bdp = fep->rx_bd_base;
@@ -1212,7 +1212,7 @@ static int fec_enet_init(struct net_device *dev)
 	bdp--;
 	bdp->cbd_sc |= BD_SC_WRAP;
 
-	fec_restart(dev, 0);
+	fec_restart(ndev, 0);
 
 	return 0;
 }
@@ -1222,9 +1222,9 @@ static int fec_enet_init(struct net_device *dev)
  * duplex.
  */
 static void
-fec_restart(struct net_device *dev, int duplex)
+fec_restart(struct net_device *ndev, int duplex)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	const struct platform_device_id *id_entry =
 				platform_get_device_id(fep->pdev);
 	int i;
@@ -1239,7 +1239,7 @@ fec_restart(struct net_device *dev, int duplex)
 	 * so need to reconfigure it.
 	 */
 	if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) {
-		memcpy(&temp_mac, dev->dev_addr, ETH_ALEN);
+		memcpy(&temp_mac, ndev->dev_addr, ETH_ALEN);
 		writel(cpu_to_be32(temp_mac[0]), fep->hwp + FEC_ADDR_LOW);
 		writel(cpu_to_be32(temp_mac[1]), fep->hwp + FEC_ADDR_HIGH);
 	}
@@ -1339,9 +1339,9 @@ fec_restart(struct net_device *dev, int duplex)
 }
 
 static void
-fec_stop(struct net_device *dev)
+fec_stop(struct net_device *ndev)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 
 	/* We cannot expect a graceful transmit stop without link !!! */
 	if (fep->link) {
-- 
1.7.2.3


^ permalink raw reply related

* [PATCH 14/14] net/fec: enable flow control and length check on enet-mac
From: Uwe Kleine-König @ 2011-02-11 10:32 UTC (permalink / raw)
  To: netdev; +Cc: Shawn Guo, kernel
In-Reply-To: <1297420342-17739-1-git-send-email-u.kleine-koenig@pengutronix.de>

Also optimize not to reread the value written to FEC_R_CNTRL.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/net/fec.c |   24 +++++++++++++-----------
 1 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index c322971..74798be 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -339,7 +339,8 @@ fec_restart(struct net_device *ndev, int duplex)
 	const struct platform_device_id *id_entry =
 				platform_get_device_id(fep->pdev);
 	int i;
-	u32 val, temp_mac[2];
+	u32 temp_mac[2];
+	u32 rcntl = OPT_FRAME_SIZE | 0x04;
 
 	/* Whack a reset.  We should wait for this. */
 	writel(1, fep->hwp + FEC_ECNTRL);
@@ -388,14 +389,14 @@ fec_restart(struct net_device *ndev, int duplex)
 
 	/* Enable MII mode */
 	if (duplex) {
-		/* MII enable / FD enable */
-		writel(OPT_FRAME_SIZE | 0x04, fep->hwp + FEC_R_CNTRL);
+		/* FD enable */
 		writel(0x04, fep->hwp + FEC_X_CNTRL);
 	} else {
-		/* MII enable / No Rcv on Xmit */
-		writel(OPT_FRAME_SIZE | 0x06, fep->hwp + FEC_R_CNTRL);
+		/* No Rcv on Xmit */
+		rcntl |= 0x02;
 		writel(0x0, fep->hwp + FEC_X_CNTRL);
 	}
+
 	fep->full_duplex = duplex;
 
 	/* Set MII speed */
@@ -406,21 +407,21 @@ fec_restart(struct net_device *ndev, int duplex)
 	 * differently on enet-mac.
 	 */
 	if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) {
-		val = readl(fep->hwp + FEC_R_CNTRL);
+		/* Enable flow control and length check */
+		rcntl |= 0x40000000 | 0x00000020;
 
 		/* MII or RMII */
 		if (fep->phy_interface == PHY_INTERFACE_MODE_RMII)
-			val |= (1 << 8);
+			rcntl |= (1 << 8);
 		else
-			val &= ~(1 << 8);
+			rcntl &= ~(1 << 8);
 
 		/* 10M or 100M */
 		if (fep->phy_dev && fep->phy_dev->speed == SPEED_100)
-			val &= ~(1 << 9);
+			rcntl &= ~(1 << 9);
 		else
-			val |= (1 << 9);
+			rcntl |= (1 << 9);
 
-		writel(val, fep->hwp + FEC_R_CNTRL);
 	} else {
 #ifdef FEC_MIIGSK_ENR
 		if (fep->phy_interface == PHY_INTERFACE_MODE_RMII) {
@@ -440,6 +441,7 @@ fec_restart(struct net_device *ndev, int duplex)
 		}
 #endif
 	}
+	writel(rcntl, fep->hwp + FEC_R_CNTRL);
 
 	/* And last, enable the transmit and receive processing */
 	writel(2, fep->hwp + FEC_ECNTRL);
-- 
1.7.2.3


^ permalink raw reply related

* [PATCH 13/14] net/fec: postpone unsetting driver data until the hardware is stopped
From: Uwe Kleine-König @ 2011-02-11 10:32 UTC (permalink / raw)
  To: netdev; +Cc: Shawn Guo, kernel
In-Reply-To: <1297420342-17739-1-git-send-email-u.kleine-koenig@pengutronix.de>

Noticed-by: Lothar Waßmann <LW@KARO-electronics.de>
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/net/fec.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index 0c984d6..c322971 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -1465,8 +1465,6 @@ fec_drv_remove(struct platform_device *pdev)
 	struct fec_enet_private *fep = netdev_priv(ndev);
 	struct resource *r;
 
-	platform_set_drvdata(pdev, NULL);
-
 	fec_stop(ndev);
 	fec_enet_mii_remove(fep);
 	clk_disable(fep->clk);
@@ -1479,6 +1477,8 @@ fec_drv_remove(struct platform_device *pdev)
 	BUG_ON(!r);
 	release_mem_region(r->start, resource_size(r));
 
+	platform_set_drvdata(pdev, NULL);
+
 	return 0;
 }
 
-- 
1.7.2.3


^ permalink raw reply related

* Re: [PATCH] ip_gre: Add IPPROTO_GRE to flowi in ipgre_tunnel_xmit
From: Changli Gao @ 2011-02-11 10:44 UTC (permalink / raw)
  To: Steffen Klassert; +Cc: David Miller, netdev
In-Reply-To: <20110211093040.GB29583@secunet.com>

On Fri, Feb 11, 2011 at 5:30 PM, Steffen Klassert
<steffen.klassert@secunet.com> wrote:
> Commit 5811662b15db018c740c57d037523683fd3e6123 accidentally
> removed the setting of IPPROTO_GRE from the struct flowi
> in ipgre_tunnel_xmit. This patch restores it.
>
> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Acked-by: Changli Gao <xiaosuo@gmail.com>

-- 
Regards,
Changli Gao(xiaosuo@gmail.com)

^ permalink raw reply

* Re: [PATCH 02/14] net/fec: release mem_region requested in probe in error path and remove
From: Uwe Kleine-König @ 2011-02-11 11:03 UTC (permalink / raw)
  To: netdev; +Cc: Shawn Guo, kernel
In-Reply-To: <1297420342-17739-2-git-send-email-u.kleine-koenig@pengutronix.de>

Hello,

On Fri, Feb 11, 2011 at 11:32:10AM +0100, Uwe Kleine-König wrote:
> Noticed-by: Lothar Waßmann <LW@KARO-electronics.de>
I changed that to Reported-by: in this and the other patches.
(this was Reported-by: Wolfram Sang via irc).  The updated patches can
be found at

	git://git.pengutronix.de/git/ukl/linux-2.6.git fec

.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply

* Re: [PATCH v5 0/4] Adding HID Feature Report Support to hidraw
From: Jiri Kosina @ 2011-02-11 14:02 UTC (permalink / raw)
  To: Gustavo F. Padovan
  Cc: Alan Ott, Marcel Holtmann, David S. Miller, Michael Poole,
	Eric Dumazet, linux-input, linux-kernel, linux-usb,
	linux-bluetooth, netdev
In-Reply-To: <20110210181441.GB2173@joana>

On Thu, 10 Feb 2011, Gustavo F. Padovan wrote:

> > > This patch adds Feature Report support for USB and Bluetooth HID devices
> > > through hidraw.
> > > 
> > > The first two patches prepare the bluetooth side for the change.
> > > 	a. Make sure the hidp_session() thread is started before
> > > 	   device's probe() functions are called.
> > > 	b. Wait for ACK/NAK on sent reports, and return proper
> > > 	   error codes.
> > > The third patch is the hidraw core and USB changes.
> > > The fourth patch is the Bluetooth changes.
> > > 
> > > Thanks to Antonio Ospite and Bill Good for providing testing and feedback.
> > > 
> > > 
> > > Alan Ott (4):
> > >   bt hidp: Move hid_add_device() call to after hidp_session() has
> > >     started.
> > >   bt hidp: Wait for ACK on Sent Reports
> > >   HID: Add Support for Setting and Getting Feature Reports from hidraw
> > >   Bluetooth hidp: Add support for hidraw HIDIOCGFEATURE and
> > >     HIDIOCSFEATURE
> > > 
> > >  drivers/hid/hidraw.c          |  106 +++++++++++++++++++-
> > >  drivers/hid/usbhid/hid-core.c |   35 +++++++
> > >  include/linux/hid.h           |    3 +
> > >  include/linux/hidraw.h        |    3 +
> > >  net/bluetooth/hidp/core.c     |  214 ++++++++++++++++++++++++++++++++++++++---
> > >  net/bluetooth/hidp/hidp.h     |   15 +++
> > 
> > Before proceeding with these patches, I'd really like to have comment 
> > (ideally 'Acked-by') from Marcel on the net/bluetooth/hidp part, 
> > obviously.
> 
> I have tested it and it seems ok to me and to Marcel. For net/bluetooth/
> 
> Acked-by: Gustavo F. Padovan <padovan@profusion.mobi>

Awesome, thanks a lot everyone for having this sorted out finally!

I will be taking the patchset through my tree.

-- 
Jiri Kosina
SUSE Labs, Novell Inc.

^ permalink raw reply

* [PATCH v2 09/13] can: pruss CAN driver.
From: Subhasish Ghosh @ 2011-02-11 14:51 UTC (permalink / raw)
  To: davinci-linux-open-source
  Cc: linux-arm-kernel, m-watkins, nsekhar, sachi, Subhasish Ghosh,
	Wolfgang Grandegger, open list:CAN NETWORK DRIVERS,
	open list:CAN NETWORK DRIVERS, open list
In-Reply-To: <1297435892-28278-1-git-send-email-subhasish@mistralsolutions.com>

This patch adds support for the CAN device emulated on PRUSS.

Signed-off-by: Subhasish Ghosh <subhasish@mistralsolutions.com>
---
 drivers/net/can/Kconfig                     |    1 +
 drivers/net/can/Makefile                    |    1 +
 drivers/net/can/da8xx_pruss/Kconfig         |   73 ++
 drivers/net/can/da8xx_pruss/Makefile        |    7 +
 drivers/net/can/da8xx_pruss/pruss_can.c     |  758 +++++++++++++++++
 drivers/net/can/da8xx_pruss/pruss_can_api.c | 1227 +++++++++++++++++++++++++++
 drivers/net/can/da8xx_pruss/pruss_can_api.h |  290 +++++++
 7 files changed, 2357 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/can/da8xx_pruss/Kconfig
 create mode 100644 drivers/net/can/da8xx_pruss/Makefile
 create mode 100644 drivers/net/can/da8xx_pruss/pruss_can.c
 create mode 100644 drivers/net/can/da8xx_pruss/pruss_can_api.c
 create mode 100644 drivers/net/can/da8xx_pruss/pruss_can_api.h

diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index d5a9db6..ae8f0f9 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -112,6 +112,7 @@ config PCH_CAN
 	  This driver can access CAN bus.
 
 source "drivers/net/can/mscan/Kconfig"
+source "drivers/net/can/da8xx_pruss/Kconfig"
 
 source "drivers/net/can/sja1000/Kconfig"
 
diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
index 07ca159..849cdbf 100644
--- a/drivers/net/can/Makefile
+++ b/drivers/net/can/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_CAN_SJA1000)	+= sja1000/
 obj-$(CONFIG_CAN_MSCAN)		+= mscan/
 obj-$(CONFIG_CAN_AT91)		+= at91_can.o
 obj-$(CONFIG_CAN_TI_HECC)	+= ti_hecc.o
+obj-$(CONFIG_CAN_TI_DA8XX_PRU)	+= da8xx_pruss/
 obj-$(CONFIG_CAN_MCP251X)	+= mcp251x.o
 obj-$(CONFIG_CAN_BFIN)		+= bfin_can.o
 obj-$(CONFIG_CAN_JANZ_ICAN3)	+= janz-ican3.o
diff --git a/drivers/net/can/da8xx_pruss/Kconfig b/drivers/net/can/da8xx_pruss/Kconfig
new file mode 100644
index 0000000..8b68f68
--- /dev/null
+++ b/drivers/net/can/da8xx_pruss/Kconfig
@@ -0,0 +1,73 @@
+#
+# CAN Lite Kernel Configuration
+#
+config CAN_TI_DA8XX_PRU
+	depends on CAN_DEV && ARCH_DAVINCI && ARCH_DAVINCI_DA850
+	tristate "PRU based CAN emulation for DA8XX"
+	---help---
+	Enable this to emulate a CAN controller on the PRU of DA8XX.
+	If not sure, mark N
+
+config DA8XX_PRU_CANID_MBX0
+	hex "CANID for mailbox 0"
+	depends on CAN_TI_DA8XX_PRU
+	default "0x123"
+	---help---
+	Enter the CANID for mailbox 0
+	Default value is set to 0x123, change this as required.
+
+config DA8XX_PRU_CANID_MBX1
+	hex "CANID for mailbox 1"
+	depends on CAN_TI_DA8XX_PRU
+	default "0x123"
+	 ---help---
+	Enter the CANID for mailbox 1
+	Default value is set to 0x123, change this as required.
+
+config DA8XX_PRU_CANID_MBX2
+	hex "CANID for mailbox 2"
+	depends on CAN_TI_DA8XX_PRU
+	default "0x123"
+	---help---
+	Enter the CANID for mailbox 2
+	Default value is set to 0x123, change this as required.
+
+config DA8XX_PRU_CANID_MBX3
+	hex "CANID for mailbox 3"
+	depends on CAN_TI_DA8XX_PRU
+	default "0x123"
+	---help---
+	Enter the CANID for mailbox 3
+	Default value is set to 0x123, change this as required.
+
+config DA8XX_PRU_CANID_MBX4
+	hex "CANID for mailbox 4"
+	depends on CAN_TI_DA8XX_PRU
+	default "0x123"
+	---help---
+	Enter the CANID for mailbox 4
+	Default value is set to 0x123, change this as required.
+
+config DA8XX_PRU_CANID_MBX5
+	hex "CANID for mailbox 5"
+	depends on CAN_TI_DA8XX_PRU
+	default "0x123"
+	---help---
+	Enter the CANID for mailbox 5
+	Default value is set to 0x123, change this as required.
+
+config DA8XX_PRU_CANID_MBX6
+	hex "CANID for mailbox 6"
+	depends on CAN_TI_DA8XX_PRU
+	default "0x123"
+	---help---
+	Enter the CANID for mailbox 6
+	Default value is set to 0x123, change this as required.
+
+config DA8XX_PRU_CANID_MBX7
+	hex "CANID for mailbox 7"
+	depends on CAN_TI_DA8XX_PRU
+	default "0x123"
+	---help---
+	Enter the CANID for mailbox 7
+	Default value is set to 0x123, change this as required.
diff --git a/drivers/net/can/da8xx_pruss/Makefile b/drivers/net/can/da8xx_pruss/Makefile
new file mode 100644
index 0000000..48f3055
--- /dev/null
+++ b/drivers/net/can/da8xx_pruss/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for CAN Lite emulation
+#
+can_emu-objs :=   pruss_can.o \
+                  pruss_can_api.o
+
+obj-$(CONFIG_CAN_TI_DA8XX_PRU)    += can_emu.o
diff --git a/drivers/net/can/da8xx_pruss/pruss_can.c b/drivers/net/can/da8xx_pruss/pruss_can.c
new file mode 100644
index 0000000..1b3afde
--- /dev/null
+++ b/drivers/net/can/da8xx_pruss/pruss_can.c
@@ -0,0 +1,758 @@
+/*
+ *  TI DA8XX PRU CAN Emulation device driver
+ *  Author: subhasish@mistralsolutions.com
+ *
+ *  This driver supports TI's PRU CAN Emulation and the
+ *  specs for the same is available at <http://www.ti.com>
+ *
+ *  Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License as
+ *  published by the Free Software Foundation version 2.
+ *
+ *  This program is distributed as is WITHOUT ANY WARRANTY of any
+ *  kind, whether express or implied; without even the implied warranty
+ *  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/platform_device.h>
+#include <linux/firmware.h>
+#include <linux/clk.h>
+#include <linux/types.h>
+
+#include <linux/can.h>
+#include <linux/can/dev.h>
+#include <linux/can/error.h>
+#include <mach/da8xx.h>
+#include "pruss_can_api.h"
+
+#define DRV_NAME "da8xx_pruss_can"
+#define DRV_DESC "TI PRU CAN Controller Driver v0.1"
+#define PRU_CAN_START		1
+#define PRU_CAN_STOP		0
+#define MB_MIN			0
+#define MB_MAX			7
+
+#define PRU_CANMID_IDE			BIT(29)	/* Extended frame format */
+
+#define PRU_CAN_ISR_BIT_CCI		BIT(15)
+#define PRU_CAN_ISR_BIT_ESI		BIT(14)
+#define PRU_CAN_ISR_BIT_SRDI		BIT(13)
+#define PRU_CAN_ISR_BIT_RRI		BIT(8)
+
+#define PRU_CAN_MBXSR_BIT_STATE		BIT(7)
+#define PRU_CAN_MBXSR_BIT_TC		BIT(6)
+#define PRU_CAN_MBXSR_BIT_ERR		BIT(5)
+#define PRU_CAN_MBXSR_BIT_OF		BIT(0)
+
+#define PRU_CAN_GSR_BIT_TXM		BIT(7)
+#define PRU_CAN_GSR_BIT_RXM		BIT(6)
+#define PRU_CAN_GSR_BIT_CM		BIT(5)
+#define PRU_CAN_GSR_BIT_EPM		BIT(4)
+#define PRU_CAN_GSR_BIT_BFM		BIT(3)
+#define RTR_MBX_NO			8
+#define MAX_INIT_RETRIES		20
+#define L138_PRU_ARM_FREQ		312000
+#define DFLT_PRU_FREQ			156000000
+#define DFLT_PRU_BITRATE		125000
+
+#define CONFIG_DA8XX_PRU_CANID_MBX0	0x123
+#define CONFIG_DA8XX_PRU_CANID_MBX1	0x123
+#define CONFIG_DA8XX_PRU_CANID_MBX2	0x123
+#define CONFIG_DA8XX_PRU_CANID_MBX3	0x123
+#define CONFIG_DA8XX_PRU_CANID_MBX4	0x123
+#define CONFIG_DA8XX_PRU_CANID_MBX5	0x123
+#define CONFIG_DA8XX_PRU_CANID_MBX6	0x123
+#define CONFIG_DA8XX_PRU_CANID_MBX7	0x123
+
+#ifdef __CAN_DEBUG
+#define __can_debug(fmt, args...) printk(KERN_DEBUG "can_debug: " fmt, ## args)
+#else
+#define __can_debug(fmt, args...)
+#endif
+#define __can_err(fmt, args...) printk(KERN_ERR "can_err: " fmt, ## args)
+
+/*
+ * omapl_pru can private data
+ */
+struct omapl_pru_can_priv {
+	struct can_priv can;
+	struct workqueue_struct *pru_can_wQ;
+	struct work_struct rx_work;
+	struct net_device *ndev;
+	struct device *dev; /* pdev->dev */
+	struct clk *clk_timer;
+	u32 timer_freq;
+	can_emu_app_hndl can_tx_hndl;
+	can_emu_app_hndl can_rx_hndl;
+	const struct firmware *fw_rx;
+	const struct firmware *fw_tx;
+	spinlock_t mbox_lock;
+	u32 trx_irq;
+	u32 tx_head;
+	u32 tx_tail;
+	u32 tx_next;
+	u32 rx_next;
+};
+
+static int omapl_pru_can_get_state(const struct net_device *ndev,
+				   enum can_state *state)
+{
+	struct omapl_pru_can_priv *priv = netdev_priv(ndev);
+	*state = priv->can.state;
+	return 0;
+}
+
+static int omapl_pru_can_set_bittiming(struct net_device *ndev)
+{
+	struct omapl_pru_can_priv *priv = netdev_priv(ndev);
+	struct can_bittiming *bt = &priv->can.bittiming;
+	long bit_error = 0;
+
+	if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) {
+		dev_warn(priv->dev, "WARN: Triple"
+			 "sampling not set due to h/w limitations");
+	}
+	if (pru_can_calc_timing(priv->dev, priv->can.clock.freq,
+				bt->bitrate) != 0)
+		return -EINVAL;
+	bit_error =
+	    (((priv->timer_freq / (priv->timer_freq / bt->bitrate)) -
+	      bt->bitrate) * 1000) / bt->bitrate;
+	if (bit_error) {
+		bit_error =
+		    (((priv->timer_freq / (priv->timer_freq / bt->bitrate)) -
+		      bt->bitrate) * 1000000) / bt->bitrate;
+		printk(KERN_INFO "\nBitrate error %ld.%ld%%\n",
+			bit_error / 10000, bit_error % 1000);
+	} else
+		printk(KERN_INFO "\nBitrate error 0.0%%\n");
+
+	return 0;
+}
+
+static void omapl_pru_can_stop(struct net_device *ndev)
+{
+	struct omapl_pru_can_priv *priv = netdev_priv(ndev);
+	u16 int_mask = 0;
+
+	pru_can_mask_ints(priv->dev, int_mask);	/* mask all ints */
+	pru_can_start_abort_tx(priv->dev, PRU_CAN_STOP);
+	priv->can.state = CAN_STATE_STOPPED;
+}
+
+/*
+ * This is to just set the can state to ERROR_ACTIVE
+ *	ip link set canX up type can bitrate 125000
+ */
+static void omapl_pru_can_start(struct net_device *ndev)
+{
+	struct omapl_pru_can_priv *priv = netdev_priv(ndev);
+	u16 int_mask = 0xFFFF;
+
+	if (priv->can.state != CAN_STATE_STOPPED)
+		omapl_pru_can_stop(ndev);
+
+	pru_can_mask_ints(priv->dev, int_mask);	/* unmask all ints */
+
+	pru_can_get_global_status(priv->dev, &priv->can_tx_hndl);
+	pru_can_get_global_status(priv->dev, &priv->can_rx_hndl);
+
+	if (PRU_CAN_GSR_BIT_EPM & priv->can_tx_hndl.u32globalstatus)
+		priv->can.state = CAN_STATE_ERROR_PASSIVE;
+	else if (PRU_CAN_GSR_BIT_BFM & priv->can_tx_hndl.u32globalstatus)
+		priv->can.state = CAN_STATE_BUS_OFF;
+	else
+		priv->can.state = CAN_STATE_ERROR_ACTIVE;
+}
+
+static int omapl_pru_can_set_mode(struct net_device *ndev, enum can_mode mode)
+{
+	int ret = 0;
+
+	switch (mode) {
+	case CAN_MODE_START:
+		omapl_pru_can_start(ndev);
+		if (netif_queue_stopped(ndev))
+			netif_wake_queue(ndev);
+		break;
+	case CAN_MODE_STOP:
+		omapl_pru_can_stop(ndev);
+		if (!netif_queue_stopped(ndev))
+			netif_stop_queue(ndev);
+		break;
+	default:
+		ret = -EOPNOTSUPP;
+		break;
+	}
+	return ret;
+}
+
+static netdev_tx_t omapl_pru_can_start_xmit(struct sk_buff *skb,
+					    struct net_device *ndev)
+{
+	struct omapl_pru_can_priv *priv = netdev_priv(ndev);
+	struct can_frame *cf = (struct can_frame *)skb->data;
+	int count;
+	u8 *data = cf->data;
+	u8 dlc = cf->can_dlc;
+	u8 *ptr8data = NULL;
+
+	netif_stop_queue(ndev);
+	if (cf->can_id & CAN_EFF_FLAG)	/* Extended frame format */
+		*((u32 *) &priv->can_tx_hndl.strcanmailbox) =
+		    (cf->can_id & CAN_EFF_MASK) | PRU_CANMID_IDE;
+	else			/* Standard frame format */
+		*((u32 *) &priv->can_tx_hndl.strcanmailbox) =
+		    (cf->can_id & CAN_SFF_MASK) << 18;
+
+	if (cf->can_id & CAN_RTR_FLAG)	/* Remote transmission request */
+		*((u32 *) &priv->can_tx_hndl.strcanmailbox) |= CAN_RTR_FLAG;
+
+	ptr8data = &priv->can_tx_hndl.strcanmailbox.u8data7 + (dlc - 1);
+	for (count = 0; count < (u8) dlc; count++) {
+		*ptr8data-- = *data++;
+	}
+	*((u32 *) &priv->can_tx_hndl.strcanmailbox.u16datalength) = (u32) dlc;
+/*
+ * search for the next available mbx
+ * if the next mbx is busy, then try the next + 1
+ * do this until the head is reached.
+ * if still unable to tx, stop accepting any packets
+ * if able to tx and the head is reached, then reset next to tail, i.e mbx0
+ * if head is not reached, then just point to the next mbx
+ */
+	for (; priv->tx_next <= priv->tx_head; priv->tx_next++) {
+		priv->can_tx_hndl.ecanmailboxnumber =
+		    (can_mailbox_number) priv->tx_next;
+		if (-1 == pru_can_write_data_to_mailbox(priv->dev,
+					&priv->can_tx_hndl)) {
+			if (priv->tx_next == priv->tx_head) {
+				priv->tx_next = priv->tx_tail;
+				if (!netif_queue_stopped(ndev))
+					netif_stop_queue(ndev);	/* IF stalled */
+				dev_err(priv->dev,
+					"%s: no tx mbx available", __func__);
+				return NETDEV_TX_BUSY;
+			} else
+				continue;
+		} else {
+			/* set transmit request */
+			pru_can_tx(priv->dev, priv->tx_next, CAN_TX_PRU_1);
+			pru_can_tx_mode_set(priv->dev, false, ecanreceive);
+			pru_can_tx_mode_set(priv->dev, true, ecantransmit);
+			pru_can_start_abort_tx(priv->dev, PRU_CAN_START);
+			priv->tx_next++;
+			can_put_echo_skb(skb, ndev, 0);
+			break;
+		}
+	}
+	if (priv->tx_next > priv->tx_head) {
+		priv->tx_next = priv->tx_tail;
+	}
+	return NETDEV_TX_OK;
+}
+
+static int omapl_pru_can_rx(struct net_device *ndev, u32 mbxno)
+{
+	struct omapl_pru_can_priv *priv = netdev_priv(ndev);
+	struct net_device_stats *stats = &ndev->stats;
+	struct can_frame *cf;
+	struct sk_buff *skb;
+	u32 pru_can_mbx_data;
+	u8 *data = NULL;
+	u8 *ptr8data = NULL;
+	int count = 0;
+
+	skb = alloc_can_skb(ndev, &cf);
+	if (!skb) {
+		if (printk_ratelimit())
+			dev_err(priv->dev,
+				"alloc_can_skb() failed\n");
+		return -ENOMEM;
+	}
+	data = cf->data;
+	/*      get payload */
+	priv->can_rx_hndl.ecanmailboxnumber = (can_mailbox_number) mbxno;
+	if (pru_can_get_data_from_mailbox(priv->dev, &priv->can_rx_hndl)) {
+		__can_err("failed to get data from mailbox\n");
+		return -EAGAIN;
+	}
+	/* give ownweship to pru */
+	pru_can_tx(priv->dev, mbxno, CAN_RX_PRU_0);
+
+	/* get data length code */
+	cf->can_dlc =
+	    get_can_dlc(*
+			((u32 *) &priv->can_rx_hndl.strcanmailbox.
+			 u16datalength) & 0xF);
+	if (cf->can_dlc <= 4) {
+		ptr8data =
+		    &priv->can_rx_hndl.strcanmailbox.u8data3 + (4 -
+								cf->can_dlc);
+		for (count = 0; count < cf->can_dlc; count++) {
+			*data++ = *ptr8data++;
+		}
+	} else {
+		ptr8data = &priv->can_rx_hndl.strcanmailbox.u8data3;
+		for (count = 0; count < 4; count++) {
+			*data++ = *ptr8data++;
+		}
+		ptr8data =
+		    &priv->can_rx_hndl.strcanmailbox.u8data4 - (cf->can_dlc -
+								5);
+		for (count = 0; count < cf->can_dlc - 4; count++) {
+			*data++ = *ptr8data++;
+		}
+	}
+
+	pru_can_mbx_data = *((u32 *) &priv->can_rx_hndl.strcanmailbox);
+	/* get id extended or std */
+	if (pru_can_mbx_data & PRU_CANMID_IDE)
+		cf->can_id = (pru_can_mbx_data & CAN_EFF_MASK) | CAN_EFF_FLAG;
+	else
+		cf->can_id = (pru_can_mbx_data >> 18) & CAN_SFF_MASK;
+
+	if (pru_can_mbx_data & CAN_RTR_FLAG)
+		cf->can_id |= CAN_RTR_FLAG;
+
+	netif_rx_ni(skb);
+	stats->rx_packets++;
+	stats->rx_bytes += cf->can_dlc;
+	return 0;
+}
+
+static int omapl_pru_can_err(struct net_device *ndev, int int_status,
+			     int err_status)
+{
+	struct omapl_pru_can_priv *priv = netdev_priv(ndev);
+	struct net_device_stats *stats = &ndev->stats;
+	struct can_frame *cf;
+	struct sk_buff *skb;
+	int tx_err_cnt, rx_err_cnt;
+
+	/* propogate the error condition to the can stack */
+	skb = alloc_can_err_skb(ndev, &cf);
+	if (!skb) {
+		if (printk_ratelimit())
+			dev_err(priv->dev,
+				"alloc_can_err_skb() failed\n");
+		return -ENOMEM;
+	}
+
+	if (err_status & PRU_CAN_GSR_BIT_EPM) {	/* error passive int */
+		priv->can.state = CAN_STATE_ERROR_PASSIVE;
+		++priv->can.can_stats.error_passive;
+		cf->can_id |= CAN_ERR_CRTL;
+		tx_err_cnt = pru_can_get_error_cnt(priv->dev, CAN_TX_PRU_1);
+		rx_err_cnt = pru_can_get_error_cnt(priv->dev, CAN_RX_PRU_0);
+		if (tx_err_cnt > 127)
+			cf->data[1] |= CAN_ERR_CRTL_TX_PASSIVE;
+		if (rx_err_cnt > 127)
+			cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE;
+
+		dev_dbg(priv->ndev->dev.parent, "Error passive interrupt\n");
+	}
+
+	if (err_status & PRU_CAN_GSR_BIT_BFM) {
+		priv->can.state = CAN_STATE_BUS_OFF;
+		cf->can_id |= CAN_ERR_BUSOFF;
+		/*
+		 *      Disable all interrupts in bus-off to avoid int hog
+		 *      this should be handled by the pru
+		 */
+		pru_can_mask_ints(priv->dev, 0xFFFF);
+		can_bus_off(ndev);
+		dev_dbg(priv->ndev->dev.parent, "Bus off mode\n");
+	}
+
+	netif_rx(skb);
+	stats->rx_packets++;
+	stats->rx_bytes += cf->can_dlc;
+	return 0;
+}
+
+void omapl_pru_can_rx_wQ(struct work_struct *work)
+{
+	struct omapl_pru_can_priv *priv = container_of(work,
+			struct omapl_pru_can_priv, rx_work);
+	struct net_device *ndev = priv->ndev;
+	u32 bit_set, mbxno = 0;
+
+	if (-1 == pru_can_get_intr_status(priv->dev, &priv->can_rx_hndl))
+		return;
+
+	if (PRU_CAN_ISR_BIT_RRI & priv->can_rx_hndl.u32interruptstatus) {
+		mbxno = RTR_MBX_NO;
+		omapl_pru_can_rx(ndev, mbxno);
+	} else {
+		/* Extract the mboxno from the status */
+		for (bit_set = 0; ((priv->can_rx_hndl.u32interruptstatus & 0xFF)
+						>> bit_set != 0); bit_set++)
+		;
+		if (0 == bit_set) {
+			dev_err(priv->dev,
+				"%s: invalid mailbox number: %X\n", __func__,
+				priv->can_rx_hndl.u32interruptstatus);
+		} else {
+			mbxno = bit_set - 1;
+			if (PRU_CAN_ISR_BIT_ESI & priv->can_rx_hndl.
+			    u32interruptstatus) {
+				pru_can_get_global_status(priv->dev,
+					&priv->can_rx_hndl);
+				omapl_pru_can_err(ndev,
+				priv->can_rx_hndl.u32interruptstatus,
+				priv->can_rx_hndl.u32globalstatus);
+			} else {
+				omapl_pru_can_rx(ndev, mbxno);
+			}
+		}
+	}
+}
+
+irqreturn_t omapl_tx_can_intr(int irq, void *dev_id)
+{
+	struct net_device *ndev = dev_id;
+	struct omapl_pru_can_priv *priv = netdev_priv(ndev);
+	struct net_device_stats *stats = &ndev->stats;
+	u32 bit_set, mbxno;
+
+	pru_can_get_intr_status(priv->dev, &priv->can_tx_hndl);
+	if ((PRU_CAN_ISR_BIT_CCI & priv->can_tx_hndl.u32interruptstatus)
+	    || (PRU_CAN_ISR_BIT_SRDI & priv->can_tx_hndl.u32interruptstatus)) {
+		__can_debug("tx_int_status = 0x%X\n",
+			    priv->can_tx_hndl.u32interruptstatus);
+		can_free_echo_skb(ndev, 0);
+	} else {
+		for (bit_set = 0; ((priv->can_tx_hndl.u32interruptstatus & 0xFF)
+						>> bit_set != 0); bit_set++)
+		;
+		if (0 == bit_set) {
+			__can_err("%s: invalid mailbox number\n", __func__);
+			can_free_echo_skb(ndev, 0);
+		} else {
+			mbxno = bit_set - 1;	/* mail box numbering starts from 0 */
+			if (PRU_CAN_ISR_BIT_ESI & priv->can_tx_hndl.
+			    u32interruptstatus) {
+				/* read gsr and ack pru */
+				pru_can_get_global_status(priv->dev, &priv->can_tx_hndl);
+				omapl_pru_can_err(ndev,
+						  priv->can_tx_hndl.
+						  u32interruptstatus,
+						  priv->can_tx_hndl.
+						  u32globalstatus);
+			} else {
+				stats->tx_packets++;
+				/* stats->tx_bytes += dlc; */
+				/*can_get_echo_skb(ndev, 0);*/
+			}
+		}
+	}
+	if (netif_queue_stopped(ndev))
+		netif_wake_queue(ndev);
+
+	can_get_echo_skb(ndev, 0);
+	pru_can_tx_mode_set(priv->dev, true, ecanreceive);
+	return IRQ_HANDLED;
+}
+
+irqreturn_t omapl_rx_can_intr(int irq, void *dev_id)
+{
+
+	struct net_device *ndev = dev_id;
+	struct omapl_pru_can_priv *priv = netdev_priv(ndev);
+	u32 intc_status = 0;
+
+	intc_status = pru_can_get_intc_status(priv->dev);
+	if (intc_status & 4)
+		return omapl_tx_can_intr(irq, dev_id);
+	if (intc_status & 2) {
+		if (!work_pending(&priv->rx_work))
+			queue_work(priv->pru_can_wQ, &priv->rx_work);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int omapl_pru_can_open(struct net_device *ndev)
+{
+	struct omapl_pru_can_priv *priv = netdev_priv(ndev);
+	int err;
+
+	/* register interrupt handler */
+	err = request_irq(priv->trx_irq, &omapl_rx_can_intr, IRQF_SHARED,
+			  "pru_can_irq", ndev);
+	if (err) {
+		dev_err(priv->dev, "error requesting rx interrupt\n");
+		goto exit_trx_irq;
+	}
+	/* common open */
+	err = open_candev(ndev);
+	if (err) {
+		dev_err(priv->dev, "open_candev() failed %d\n", err);
+		goto exit_open;
+	}
+
+	pru_can_emu_init(priv->dev, priv->can.clock.freq);
+	priv->tx_tail = MB_MIN;
+	priv->tx_head = MB_MAX;
+
+	pru_can_rx_id_map(priv->dev, CONFIG_DA8XX_PRU_CANID_MBX0, 0);
+	pru_can_rx_id_map(priv->dev, CONFIG_DA8XX_PRU_CANID_MBX1, 1);
+	pru_can_rx_id_map(priv->dev, CONFIG_DA8XX_PRU_CANID_MBX2, 2);
+	pru_can_rx_id_map(priv->dev, CONFIG_DA8XX_PRU_CANID_MBX3, 3);
+	pru_can_rx_id_map(priv->dev, CONFIG_DA8XX_PRU_CANID_MBX4, 4);
+	pru_can_rx_id_map(priv->dev, CONFIG_DA8XX_PRU_CANID_MBX5, 5);
+	pru_can_rx_id_map(priv->dev, CONFIG_DA8XX_PRU_CANID_MBX6, 6);
+	pru_can_rx_id_map(priv->dev, CONFIG_DA8XX_PRU_CANID_MBX7, 7);
+
+	omapl_pru_can_start(ndev);
+	netif_start_queue(ndev);
+	return 0;
+
+exit_open:
+	free_irq(priv->trx_irq, ndev);
+exit_trx_irq:
+	return err;
+}
+
+static int omapl_pru_can_close(struct net_device *ndev)
+{
+	struct omapl_pru_can_priv *priv = netdev_priv(ndev);
+
+	if (!netif_queue_stopped(ndev))
+		netif_stop_queue(ndev);
+
+	close_candev(ndev);
+
+	free_irq(priv->trx_irq, ndev);
+	return 0;
+}
+
+static const struct net_device_ops omapl_pru_can_netdev_ops = {
+	.ndo_open		= omapl_pru_can_open,
+	.ndo_stop		= omapl_pru_can_close,
+	.ndo_start_xmit		= omapl_pru_can_start_xmit,
+};
+
+static int __devinit omapl_pru_can_probe(struct platform_device *pdev)
+{
+	struct net_device *ndev = NULL;
+	const struct da8xx_pru_can_data *pdata;
+	struct omapl_pru_can_priv *priv = NULL;
+	struct device *dev = &pdev->dev;
+	u32 err;
+
+	pdata = dev->platform_data;
+	if (!pdata) {
+		dev_err(&pdev->dev, "platform data not found\n");
+		return -EINVAL;
+	}
+
+	ndev = alloc_candev(sizeof(struct omapl_pru_can_priv), MB_MAX + 1);
+	if (!ndev) {
+		dev_err(&pdev->dev, "alloc_candev failed\n");
+		err = -ENOMEM;
+		goto probe_exit;
+	}
+	priv = netdev_priv(ndev);
+
+	priv->trx_irq = platform_get_irq(to_platform_device(dev->parent), 0);
+	if (!priv->trx_irq) {
+		dev_err(&pdev->dev, "unable to get pru interrupt resources!\n");
+		err = -ENODEV;
+		goto probe_exit;
+	}
+
+	priv->ndev = ndev;
+	priv->dev = dev; /* priv->dev = pdev->dev */
+
+	priv->can.bittiming_const = NULL;
+	priv->can.do_set_bittiming = omapl_pru_can_set_bittiming;
+	priv->can.do_set_mode = omapl_pru_can_set_mode;
+	priv->can.do_get_state = omapl_pru_can_get_state;
+	priv->can_tx_hndl.u8prunumber = CAN_TX_PRU_1;
+	priv->can_rx_hndl.u8prunumber = CAN_RX_PRU_0;
+
+	/* we support local echo, no arp */
+	ndev->flags |= (IFF_ECHO | IFF_NOARP);
+
+	/* pdev->dev->device_private->driver_data = ndev */
+	platform_set_drvdata(pdev, ndev);
+	SET_NETDEV_DEV(ndev, &pdev->dev);
+	ndev->netdev_ops = &omapl_pru_can_netdev_ops;
+
+	priv->can.clock.freq = pruss_get_clk_freq(priv->dev);
+
+	priv->clk_timer = clk_get(&pdev->dev, "pll1_sysclk2");
+	if (IS_ERR(priv->clk_timer)) {
+		dev_err(&pdev->dev, "no timer clock available\n");
+		err = PTR_ERR(priv->clk_timer);
+		priv->clk_timer = NULL;
+		goto probe_exit_candev;
+	}
+	priv->timer_freq = clk_get_rate(priv->clk_timer);
+
+	err = register_candev(ndev);
+	if (err) {
+		dev_err(&pdev->dev, "register_candev() failed\n");
+		err = -ENODEV;
+		goto probe_exit_clk;
+	}
+
+	err = request_firmware(&priv->fw_tx, "PRU_CAN_Emulation_Tx.bin",
+			&pdev->dev);
+	if (err) {
+		dev_err(&pdev->dev, "can't load firmware\n");
+		err = -ENODEV;
+		goto probe_exit_clk;
+	}
+
+	dev_info(&pdev->dev, "fw_tx size %d. downloading...\n",
+		 priv->fw_tx->size);
+
+	err = request_firmware(&priv->fw_rx, "PRU_CAN_Emulation_Rx.bin",
+			&pdev->dev);
+	if (err) {
+		dev_err(&pdev->dev, "can't load firmware\n");
+		err = -ENODEV;
+		goto probe_release_fw;
+	}
+	dev_info(&pdev->dev, "fw_rx size %d. downloading...\n",
+		 priv->fw_rx->size);
+
+	/* init the pru */
+	pru_can_emu_init(priv->dev, priv->can.clock.freq);
+	udelay(200);
+
+	pruss_enable(priv->dev, CAN_RX_PRU_0);
+	pruss_enable(priv->dev, CAN_TX_PRU_1);
+
+	/* download firmware into pru */
+	err = pruss_load(priv->dev, CAN_RX_PRU_0,
+		(u32 *)priv->fw_rx->data, (priv->fw_rx->size / 4));
+	if (err) {
+		dev_err(&pdev->dev, "firmware download error\n");
+		err = -ENODEV;
+		goto probe_release_fw_1;
+	}
+	err = pruss_load(priv->dev, CAN_TX_PRU_1,
+		(u32 *)priv->fw_tx->data, (priv->fw_tx->size / 4));
+	if (err) {
+		dev_err(&pdev->dev, "firmware download error\n");
+		err = -ENODEV;
+		goto probe_release_fw_1;
+	}
+
+	if (pru_can_calc_timing(priv->dev, DFLT_PRU_FREQ,
+				DFLT_PRU_BITRATE) != 0)
+		return -EINVAL;
+
+	pruss_run(priv->dev, CAN_RX_PRU_0);
+	pruss_run(priv->dev, CAN_TX_PRU_1);
+
+	/*Create The Work Queue */
+	priv->pru_can_wQ = create_freezeable_workqueue("omapl_pru_wQ");
+	if (priv->pru_can_wQ == NULL) {
+		dev_err(&pdev->dev, "failed to create work queue\n");
+		err = -ENODEV;
+		goto probe_release_fw_1;
+	}
+
+	INIT_WORK(&priv->rx_work, omapl_pru_can_rx_wQ);
+	dev_info(&pdev->dev,
+		 "%s device registered (trx_irq = %d,  clk = %d)\n",
+		 DRV_NAME, priv->trx_irq, priv->can.clock.freq);
+
+	return 0;
+
+probe_release_fw_1:
+	release_firmware(priv->fw_rx);
+probe_release_fw:
+	release_firmware(priv->fw_tx);
+probe_exit_clk:
+	clk_put(priv->clk_timer);
+probe_exit_candev:
+	if (NULL != ndev)
+		free_candev(ndev);
+probe_exit:
+	return err;
+}
+
+static int __devexit omapl_pru_can_remove(struct platform_device *pdev)
+{
+	struct net_device *ndev = platform_get_drvdata(pdev);
+	struct omapl_pru_can_priv *priv = netdev_priv(ndev);
+
+	omapl_pru_can_stop(ndev);
+
+	pru_can_emu_exit(priv->dev);
+	release_firmware(priv->fw_tx);
+	release_firmware(priv->fw_rx);
+	clk_put(priv->clk_timer);
+	flush_workqueue(priv->pru_can_wQ);
+	destroy_workqueue(priv->pru_can_wQ);
+	unregister_candev(ndev);
+	free_candev(ndev);
+	platform_set_drvdata(pdev, NULL);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int omapl_pru_can_suspend(struct platform_device *pdev,
+			pm_message_t mesg)
+{
+	dev_info(&pdev->dev, "%s not yet implemented\n", __func__);
+	return 0;
+}
+
+static int omapl_pru_can_resume(struct platform_device *pdev)
+{
+	dev_info(&pdev->dev, "%s not yet implemented\n", __func__);
+	return 0;
+}
+#else
+#define omapl_pru_can_suspend NULL
+#define omapl_pru_can_resume NULL
+#endif /* CONFIG_PM */
+
+static struct platform_driver omapl_pru_can_driver = {
+	.probe		= omapl_pru_can_probe,
+	.remove		= __devexit_p(omapl_pru_can_remove),
+	.suspend	= omapl_pru_can_suspend,
+	.resume		= omapl_pru_can_resume,
+	.driver		= {
+		.name	= DRV_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init omapl_pru_can_init(void)
+{
+	__can_debug(KERN_INFO DRV_DESC "\n");
+	return platform_driver_register(&omapl_pru_can_driver);
+}
+
+module_init(omapl_pru_can_init);
+
+static void __exit omapl_pru_can_exit(void)
+{
+	__can_debug(KERN_INFO DRV_DESC " unloaded\n");
+	platform_driver_unregister(&omapl_pru_can_driver);
+}
+
+module_exit(omapl_pru_can_exit);
+
+MODULE_AUTHOR("Subhasish Ghosh <subhasish@mistralsolutions.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("omapl pru CAN netdevice driver");
diff --git a/drivers/net/can/da8xx_pruss/pruss_can_api.c b/drivers/net/can/da8xx_pruss/pruss_can_api.c
new file mode 100644
index 0000000..2f7438a
--- /dev/null
+++ b/drivers/net/can/da8xx_pruss/pruss_can_api.c
@@ -0,0 +1,1227 @@
+/*
+ * Copyright (C) 2010 Texas Instruments Incorporated
+ * Author: Wilfred Felix
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as  published by the
+ * Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
+ * whether express or implied; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include "pruss_can_api.h"
+
+static can_emu_drv_inst gstr_can_inst[ecanmaxinst];
+
+/*
+ * pru_can_set_brp()	Updates the  BRP register of PRU0
+ * and PRU1 of OMAP L138. This API will be called by the
+ * Application to updtae the BRP register of PRU0 and PRU1
+ *
+ * param	u16bitrateprescaler		The can bus bitrate
+ * prescaler value be set
+ *
+ * return   SUCCESS or FAILURE
+ */
+s16 pru_can_set_brp(struct device *dev, u16 u16bitrateprescaler)
+{
+
+	u32 u32offset;
+
+	if (u16bitrateprescaler > 255) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_RX_CLOCK_BRP_REGISTER);
+	pruss_writel(dev, u32offset, (u32 *) &u16bitrateprescaler, 1);
+
+	u32offset = (PRU_CAN_TX_CLOCK_BRP_REGISTER);
+	pruss_writel(dev, u32offset, (u32 *) &u16bitrateprescaler, 1);
+
+	return 0;
+
+}
+
+/*
+ * pru_can_set_bit_timing()		Updates the timing register
+ * of PRU0 and PRU1 of OMAP L138. This API will be called by
+ * the Application to updtae the timing register of PRU0 and PRU1
+ *
+ * param	pstrbittiming		Pointer to structure holding
+ * the bit timing values for can bus.
+ *
+ * return   SUCCESS or FAILURE
+ */
+s16 pru_can_set_bit_timing(struct device *dev,
+		can_bit_timing_consts *pstrbittiming)
+{
+
+	u32 u32offset;
+	u32 u32serregister;
+
+	u32serregister = 0;
+
+	if (pstrbittiming == NULL) {
+		return -1;
+	}
+
+	if ((pstrbittiming->u8syncjumpwidth > PRU_CAN_MAX_SJW) ||
+	    (pstrbittiming->u8phseg1 > PRU_CAN_MAX_PHSEG1) ||
+	    (pstrbittiming->u8phseg2 > PRU_CAN_MAX_PHSEG2)) {
+		return -1;
+	}
+
+	u32serregister = u32serregister |
+			((pstrbittiming->u8syncjumpwidth << 7) |
+			(pstrbittiming->u8phseg1 << 3) |
+			(pstrbittiming->u8phseg2));
+
+	u32offset = (PRU_CAN_TX_TIMING_REGISTER);
+	pruss_writel(dev, u32offset, (u32 *) &u32serregister, 1);
+
+	u32offset = (PRU_CAN_RX_TIMING_REGISTER);
+	pruss_writel(dev, u32offset, (u32 *) &u32serregister, 1);
+
+	return 0;
+}
+
+
+/*
+ * pru_can_calc_timing()
+ * Updates the  timing values of PRU0 and PRU1 of OMAP L138.
+ * This API will be called by the
+ * Application to updtae the timing values of PRU0 and PRU1
+ *
+ * return   SUCCESS or FAILURE
+ */
+
+s16 pru_can_calc_timing(struct device *dev, u32 pru_freq, u32 bit_rate)
+{
+	u16 u16phaseseg1;
+	u16 u16phaseseg2;
+	u32 u32offset;
+	u32 u32timing_value;
+	u32 u32setup_value;
+	u32timing_value = TIMER_CLK_FREQ / bit_rate;
+	u32offset = (PRU_CAN_TIMING_VAL_TX);
+	pruss_writel(dev, u32offset, (u32 *) &u32timing_value, 4);
+	pruss_readl(dev, u32offset, (u32 *) &u32timing_value, 4);
+	u32setup_value =
+	    (GPIO_SETUP_DELAY * (pru_freq / 1000000) / 1000) /
+	    DELAY_LOOP_LENGTH;
+	u32offset = (PRU_CAN_TIMING_VAL_TX_SJW);
+	pruss_writel(dev, u32offset, (u32 *) &u32setup_value, 4);
+	u16phaseseg1 = (u16) (u32timing_value / 2);
+	u16phaseseg2 = u32timing_value - u16phaseseg1;
+	u16phaseseg1 -= TIMER_SETUP_DELAY;
+	u16phaseseg2 -= TIMER_SETUP_DELAY;
+	u32setup_value = (u16phaseseg1 << 16) | u16phaseseg2;
+	u32offset = (PRU_CAN_TIMING_VAL_RX);
+	pruss_writel(dev, u32offset, (u32 *) &u32setup_value, 4);
+	u32offset = (PRU_CAN_TIMING_VAL_RX + 4);
+	pruss_writel(dev, u32offset, (u32 *) &u32timing_value, 4);
+
+	return 0;
+}
+
+/*
+ * pru_can_write_data_to_mailbox()
+ * Updates the transmit mailboxes of PRU1 of OMAP L138.
+ * This API will be called by the Application to update
+ * the transmit mailboxes of PRU1
+ *
+ * param  pu16canframedata	Can mailbox data buffer
+ *
+ * param  u8mailboxnum		Mailbox to be updated
+ *
+ * return SUCCESS or FAILURE
+ */
+s16 pru_can_write_data_to_mailbox(struct device *dev,
+			can_emu_app_hndl *pstremuapphndl)
+{
+	s16 s16subrtnretval;
+	u32 u32offset;
+
+	if (pstremuapphndl == NULL) {
+		return -1;
+	}
+
+	switch ((u8) pstremuapphndl->ecanmailboxnumber) {
+	case 0:
+		u32offset = (PRU_CAN_TX_MAILBOX0);
+		break;
+	case 1:
+		u32offset = (PRU_CAN_TX_MAILBOX1);
+		break;
+	case 2:
+		u32offset = (PRU_CAN_TX_MAILBOX2);
+		break;
+	case 3:
+		u32offset = (PRU_CAN_TX_MAILBOX3);
+		break;
+	case 4:
+		u32offset = (PRU_CAN_TX_MAILBOX4);
+		break;
+	case 5:
+		u32offset = (PRU_CAN_TX_MAILBOX5);
+		break;
+	case 6:
+		u32offset = (PRU_CAN_TX_MAILBOX6);
+		break;
+	case 7:
+		u32offset = (PRU_CAN_TX_MAILBOX7);
+		break;
+	default:
+		return -1;
+	}
+
+	s16subrtnretval = pruss_writel(dev, u32offset,
+		(u32 *) &(pstremuapphndl->strcanmailbox), 4);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+	return 0;
+}
+
+/*
+ * pru_can_get_data_from_mailbox()
+ * Receive data from the receive mailboxes of PRU0  of OMAP L138.
+ * This API will be called by the Application to get data from
+ * the receive mailboxes of PRU0
+ *
+ * param  pu16canframedata	Can mailbox data buffer
+ *
+ * param  u8mailboxnum		Mailbox to be updated
+ *
+ * return SUCCESS or FAILURE
+ */
+s16 pru_can_get_data_from_mailbox(struct device *dev,
+		can_emu_app_hndl *pstremuapphndl)
+{
+	s16 s16subrtnretval;
+	u32 u32offset;
+
+	if (pstremuapphndl == NULL) {
+		return -1;
+	}
+
+	switch ((u8) pstremuapphndl->ecanmailboxnumber) {
+	case 0:
+		u32offset = (PRU_CAN_RX_MAILBOX0);
+		break;
+	case 1:
+		u32offset = (PRU_CAN_RX_MAILBOX1);
+		break;
+	case 2:
+		u32offset = (PRU_CAN_RX_MAILBOX2);
+		break;
+	case 3:
+		u32offset = (PRU_CAN_RX_MAILBOX3);
+		break;
+	case 4:
+		u32offset = (PRU_CAN_RX_MAILBOX4);
+		break;
+	case 5:
+		u32offset = (PRU_CAN_RX_MAILBOX5);
+		break;
+	case 6:
+		u32offset = (PRU_CAN_RX_MAILBOX6);
+		break;
+	case 7:
+		u32offset = (PRU_CAN_RX_MAILBOX7);
+		break;
+	case 8:
+		u32offset = (PRU_CAN_RX_MAILBOX8);
+		break;
+	default:
+		return -1;
+	}
+
+	s16subrtnretval =
+	    pruss_readl(dev, u32offset,
+		  (u32 *) &(pstremuapphndl->strcanmailbox),
+				  4);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+	return 0;
+}
+
+/*
+ * pru_can_receive_id_map()
+ * Receive mailboxes ID Mapping of PRU0  of OMAP L138.
+ * This API will be called by the Application
+ * to map the IDs  to receive mailboxes of PRU0
+ *
+ * param  u32nodeid		Can node ID
+ *
+ * param  ecanmailboxno		Mailbox to be mapped
+ *
+ * return   SUCCESS or FAILURE
+ */
+s16 pru_can_rx_id_map(struct device *dev, u32 u32nodeid,
+		can_mailbox_number ecanmailboxno)
+{
+
+	pruss_writel(dev, (PRU_CAN_ID_MAP +
+		(((u8) ecanmailboxno) * 4)), (u32 *) &u32nodeid, 1);
+
+	return 0;
+}
+
+/*
+ * pru_can_get_intr_status()
+ * Gets the interrupts status register value.
+ * This API will be called by the Application
+ * to get the interrupts status register value
+ *
+ * param  u8prunumber	PRU number for which IntStatusReg
+ * has to be read
+ *
+ * return   SUCCESS or FAILURE
+ */
+s16 pru_can_get_intr_status(struct device *dev,
+		can_emu_app_hndl *pstremuapphndl)
+{
+	u32 u32offset;
+	s16 s16subrtnretval = -1;
+
+	if (pstremuapphndl == NULL) {
+		return -1;
+	}
+
+	if (pstremuapphndl->u8prunumber == DA8XX_PRUCORE_1) {
+		u32offset = (PRU_CAN_TX_INTERRUPT_STATUS_REGISTER);
+	} else if (pstremuapphndl->u8prunumber == DA8XX_PRUCORE_0) {
+		u32offset = (PRU_CAN_RX_INTERRUPT_STATUS_REGISTER);
+	} else {
+		return -1;
+	}
+
+	s16subrtnretval = pruss_readl(dev, u32offset,
+		(u32 *) &pstremuapphndl->u32interruptstatus, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	return 0;
+}
+
+/*
+ * pru_can_get_global_status()	Gets the globalstatus
+ * register value. This API will be called by the Application
+ * to  get the global status register value
+ *
+ * return   SUCCESS or FAILURE
+ */
+s16 pru_can_get_global_status(struct device *dev,
+		can_emu_app_hndl *pstremuapphndl)
+{
+	u32 u32offset;
+	int s16subrtnretval = -1;
+
+	if (pstremuapphndl == NULL) {
+		return -1;
+	}
+
+	if (pstremuapphndl->u8prunumber == DA8XX_PRUCORE_1) {
+		u32offset = (PRU_CAN_TX_GLOBAL_STATUS_REGISTER);
+	} else if (pstremuapphndl->u8prunumber == DA8XX_PRUCORE_0) {
+		u32offset = (PRU_CAN_RX_GLOBAL_STATUS_REGISTER);
+	} else {
+		return -1;
+	}
+
+	s16subrtnretval = pruss_readl(dev, u32offset,
+		(u32 *) &pstremuapphndl->u32globalstatus, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	return 0;
+}
+
+/*
+ * pru_can_get_mailbox_status()		Gets the mailbox status
+ * register value. This API will be called by the Application
+ * to get the mailbox status register value
+ *
+ * return   SUCCESS or FAILURE
+ */
+s16 pru_can_get_mailbox_status(struct device *dev,
+		can_emu_app_hndl *pstremuapphndl)
+{
+	u32 u32offset;
+	s16 s16subrtnretval = -1;
+
+	if (pstremuapphndl == NULL) {
+		return -1;
+	}
+
+	if (pstremuapphndl->u8prunumber == DA8XX_PRUCORE_1) {
+		switch (pstremuapphndl->ecanmailboxnumber) {
+		case 0:
+			u32offset = (PRU_CAN_TX_MAILBOX0_STATUS_REGISTER);
+			break;
+		case 1:
+			u32offset = (PRU_CAN_TX_MAILBOX1_STATUS_REGISTER);
+			break;
+		case 2:
+			u32offset = (PRU_CAN_TX_MAILBOX2_STATUS_REGISTER);
+			break;
+		case 3:
+			u32offset = (PRU_CAN_TX_MAILBOX3_STATUS_REGISTER);
+			break;
+		case 4:
+			u32offset = (PRU_CAN_TX_MAILBOX4_STATUS_REGISTER);
+			break;
+		case 5:
+			u32offset = (PRU_CAN_TX_MAILBOX5_STATUS_REGISTER);
+			break;
+		case 6:
+			u32offset = (PRU_CAN_TX_MAILBOX6_STATUS_REGISTER);
+			break;
+		case 7:
+			u32offset = (PRU_CAN_TX_MAILBOX7_STATUS_REGISTER);
+			break;
+		default:
+			return -1;
+		}
+	}
+
+	else if (pstremuapphndl->u8prunumber == DA8XX_PRUCORE_0) {
+		switch (pstremuapphndl->ecanmailboxnumber) {
+		case 0:
+			u32offset = (PRU_CAN_RX_MAILBOX0_STATUS_REGISTER);
+			break;
+		case 1:
+			u32offset = (PRU_CAN_RX_MAILBOX1_STATUS_REGISTER);
+			break;
+		case 2:
+			u32offset = (PRU_CAN_RX_MAILBOX2_STATUS_REGISTER);
+			break;
+		case 3:
+			u32offset = (PRU_CAN_RX_MAILBOX3_STATUS_REGISTER);
+			break;
+		case 4:
+			u32offset = (PRU_CAN_RX_MAILBOX4_STATUS_REGISTER);
+			break;
+		case 5:
+			u32offset = (PRU_CAN_RX_MAILBOX5_STATUS_REGISTER);
+			break;
+		case 6:
+			u32offset = (PRU_CAN_RX_MAILBOX6_STATUS_REGISTER);
+			break;
+		case 7:
+			u32offset = (PRU_CAN_RX_MAILBOX7_STATUS_REGISTER);
+			break;
+		case 8:
+			u32offset = (PRU_CAN_RX_MAILBOX8_STATUS_REGISTER);
+			break;
+		default:
+			return -1;
+		}
+	}
+
+	else {
+		return -1;
+	}
+
+	s16subrtnretval = pruss_readl(dev, u32offset,
+		(u32 *) &pstremuapphndl->u32mailboxstatus, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	return 0;
+}
+
+s16 pru_can_tx_mode_set(struct device *dev, bool btransfer_flag,
+				can_transfer_direction ecan_trx)
+{
+	u32 u32offset;
+	u32 u32value;
+
+	if (ecan_trx == ecantransmit) {
+		u32offset = (PRU_CAN_RX_GLOBAL_STATUS_REGISTER);
+		pruss_readl(dev, u32offset, &u32value, 1);
+		if (btransfer_flag == true) {
+			u32value &= 0x1F;
+			u32value |= 0x80;
+		} else {
+			u32value &= 0x7F;
+		}
+		pruss_writel(dev, u32offset, &u32value, 1);
+		u32offset = (PRU_CAN_TX_GLOBAL_STATUS_REGISTER);
+		pruss_writel(dev, u32offset, &u32value, 1);
+	} else if (ecan_trx == ecanreceive) {
+		u32offset = (PRU_CAN_RX_GLOBAL_STATUS_REGISTER);
+		pruss_readl(dev, u32offset, &u32value, 1);
+		if (btransfer_flag == true) {
+			u32value &= 0x1F;
+			u32value |= 0x40;
+		} else {
+			u32value &= 0xBF;
+		}
+		pruss_writel(dev, u32offset, &u32value, 1);
+		u32offset = (PRU_CAN_TX_GLOBAL_STATUS_REGISTER);
+		pruss_writel(dev, u32offset, &u32value, 1);
+	} else
+		return -1;
+
+	return 0;
+}
+
+/*
+ * pru_can_config_mode_set()		Sets the timing value
+ * for data transfer. This API will be called by the Application
+ * to set timing valus for data transfer
+ *
+ * return   SUCCESS or FAILURE
+ */
+s16 pru_can_config_mode_set(struct device *dev, bool bconfigmodeflag)
+{
+
+	u32 u32bitrateprescaler;
+	u32 u32canbittiming;
+
+	pruss_readl(dev, (PRU_CAN_TX_CLOCK_BRP_REGISTER),
+			(u32 *) &u32bitrateprescaler, 1);
+	pruss_readl(dev, (PRU_CAN_TX_TIMING_REGISTER),
+			(u32 *) &u32canbittiming, 1);
+
+	if (bconfigmodeflag == 1) {
+		pru_can_calc_timing(dev, u32canbittiming, u32bitrateprescaler);
+	}
+
+	else {
+		pru_can_calc_timing(dev, 0, 0);
+	}
+
+	return 0;
+}
+
+/*
+ * pru_can_emu_init()		Initializes the Can
+ * Emulation Parameters. This API will be called by the Application
+ * to Initialize the Can Emulation Parameters
+ *
+ * param    u32pruclock         PRU Clock value
+ *
+ * return   SUCCESS or FAILURE
+ */
+s16 pru_can_emu_init(struct device *dev, u32 u32pruclock)
+{
+	u32 u32offset;
+	u32 u32value;
+	s16 s16subrtnretval = -1;
+	u8 u8loop;
+
+	for (u8loop = 0; u8loop < (u8) ecanmaxinst; u8loop++) {
+		gstr_can_inst[u8loop].bcaninststate = (bool) 0;
+		gstr_can_inst[u8loop].ecantransferdirection =
+		    (can_transfer_direction) 0;
+		gstr_can_inst[u8loop].u32apphandlerptr = 0;
+	}
+
+	u32offset = (PRU_CAN_TX_GLOBAL_CONTROL_REGISTER & 0xFFFF);
+	u32value = 0x00000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_TX_GLOBAL_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000040;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+	u32offset = (PRU_CAN_RX_GLOBAL_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000040;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_TX_INTERRUPT_MASK_REGISTER & 0xFFFF);
+	u32value = 0x00004000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_TX_INTERRUPT_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_TX_MAILBOX0_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000001;
+	s16subrtnretval =
+	    pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_TX_MAILBOX1_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000001;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_TX_MAILBOX2_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000001;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_TX_MAILBOX3_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000001;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_TX_MAILBOX4_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000001;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_TX_MAILBOX5_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000001;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_TX_MAILBOX6_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000001;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_TX_MAILBOX7_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000001;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_TX_ERROR_COUNTER_REGISTER & 0xFFFF);
+	u32value = 0x00000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_TX_TIMING_REGISTER & 0xFFFF);
+	u32value = 0x00000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_TX_CLOCK_BRP_REGISTER & 0xFFFF);
+	u32value = 0x00000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_TX_ERROR_COUNTER_REGISTER & 0xFFFF);
+	u32value = 0x00000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRUSS_INTC_POLARITY0 & 0xFFFF);
+	u32value = 0xFFFFFFFF;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+	u32offset = (PRUSS_INTC_POLARITY1 & 0xFFFF);
+	u32value = 0xFFFFFFFF;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+	u32offset = (PRUSS_INTC_TYPE0 & 0xFFFF);
+	u32value = 0x1C000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+	u32offset = (PRUSS_INTC_TYPE1 & 0xFFFF);
+	u32value = 0x00000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRUSS_INTC_HSTINTENIDXCLR & 0xFFFF);
+	u32value = 0x0;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRUSS_INTC_GLBLEN & 0xFFFF);
+	u32value = 0x1;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+	/* tx intr map arm->pru */
+	u32offset = (PRUSS_INTC_HSTINTENIDXSET & 0xFFFF);
+	u32value = 0x0;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRUSS_INTC_HOSTMAP0 & 0xFFFF);
+	u32value = 0x03020100;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRUSS_INTC_HOSTMAP1 & 0xFFFF);
+	u32value = 0x07060504;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRUSS_INTC_HOSTMAP2 & 0xFFFF);
+	u32value = 0x0000908;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRUSS_INTC_CHANMAP0 & 0xFFFF);
+	u32value = 0;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRUSS_INTC_CHANMAP8 & 0xFFFF);
+	u32value = 0x00020200;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRUSS_INTC_STATIDXCLR & 0xFFFF);
+	u32value = 32;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRUSS_INTC_STATIDXCLR & 0xFFFF);
+	u32value = 19;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRUSS_INTC_ENIDXSET & 0xFFFF);
+	u32value = 19;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+	u32offset = (PRUSS_INTC_STATIDXCLR & 0xFFFF);
+	u32value = 18;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRUSS_INTC_ENIDXSET & 0xFFFF);
+	u32value = 18;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRUSS_INTC_STATIDXCLR & 0xFFFF);
+	u32value = 34;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRUSS_INTC_ENIDXSET & 0xFFFF);
+	u32value = 34;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRUSS_INTC_ENIDXSET & 0xFFFF);
+	u32value = 32;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRUSS_INTC_HOSTINTEN & 0xFFFF);
+	u32value = 0x5;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+/* PRU0 - Rx Internal Registers Initializations */
+
+	u32offset = (PRU_CAN_RX_GLOBAL_CONTROL_REGISTER & 0xFFFF);
+	u32value = 0x00000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_RX_GLOBAL_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000040;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_RX_INTERRUPT_MASK_REGISTER & 0xFFFF);
+	u32value = 0x00004000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_RX_INTERRUPT_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_RX_MAILBOX0_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_RX_MAILBOX1_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x0000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_RX_MAILBOX2_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_RX_MAILBOX3_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_RX_MAILBOX4_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_RX_MAILBOX5_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_RX_MAILBOX6_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_RX_MAILBOX7_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_RX_ERROR_COUNTER_REGISTER & 0xFFFF);
+	u32value = 0x00000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_RX_TIMING_REGISTER & 0xFFFF);
+	u32value = 0x0000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_RX_CLOCK_BRP_REGISTER & 0xFFFF);
+	u32value = 0x00000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+	return 0;
+}
+
+
+/*
+ * pru_can_emu_open()		Opens the can emu for
+ * application to use. This API will be called by the Application
+ * to Open the can emu for application to use.
+ *
+ * param	pstremuapphndl	Pointer to application handler
+ * structure
+ *
+ * return   SUCCESS or FAILURE
+ */
+s16 pru_can_emu_open(struct device *dev, can_emu_app_hndl *pstremuapphndl)
+{
+
+	if (pstremuapphndl == NULL) {
+		return -1;
+	}
+
+	if (gstr_can_inst[pstremuapphndl->ecaninstance].bcaninststate == 1) {
+		return -1;
+	}
+
+	gstr_can_inst[(u8) pstremuapphndl->ecaninstance].
+					bcaninststate = (bool)1;
+	gstr_can_inst[(u8) pstremuapphndl->
+		ecaninstance].ecantransferdirection =
+		(can_transfer_direction)(u8)pstremuapphndl->ecantransferdirection;
+	gstr_can_inst[(u8) pstremuapphndl->ecaninstance].
+		u32apphandlerptr = (u32) pstremuapphndl;
+
+	return 0;
+}
+
+
+/*
+ * brief    pru_can_emu_close()	Closes the can emu for other
+ * applications to use. This API will be called by the Application to Close
+ * the can emu for other applications to use
+ *
+ * param	pstremuapphndl	Pointer to application handler structure
+ *
+ * return   SUCCESS or FAILURE
+ */
+s16 pru_can_emu_close(struct device *dev, can_emu_app_hndl *pstremuapphndl)
+{
+
+	if (pstremuapphndl == NULL) {
+		return -1;
+	}
+	if (gstr_can_inst[pstremuapphndl->ecaninstance].bcaninststate == 0) {
+		return -1;
+	}
+	if ((u32) pstremuapphndl != gstr_can_inst[(u8) pstremuapphndl->
+			ecaninstance].u32apphandlerptr){
+		return -1;
+	}
+	gstr_can_inst[(u8) pstremuapphndl->ecaninstance].bcaninststate
+		= (bool) 0;
+	gstr_can_inst[(u8) pstremuapphndl->
+	ecaninstance].ecantransferdirection = (can_transfer_direction) 0;
+	gstr_can_inst[(u8) pstremuapphndl->ecaninstance].u32apphandlerptr = 0;
+
+	return 0;
+}
+
+/*
+ * brief    pru_can_emu_exit()	Diables all the PRUs
+ * This API will be called by the Application to disable all PRUs
+ * param	None
+ * return   SUCCESS or FAILURE
+ */
+s16 pru_can_emu_exit(struct device *dev)
+{
+	s16 s16subrtnretval;
+
+	s16subrtnretval = pruss_disable(dev, CAN_RX_PRU_0);
+	if (s16subrtnretval == -1)
+		return -1;
+	s16subrtnretval = pruss_disable(dev, CAN_TX_PRU_1);
+	if (s16subrtnretval == -1)
+		return -1;
+
+	return 0;
+}
+
+s16 pru_can_emu_sreset(struct device *dev)
+{
+	return 0;
+}
+
+s16 pru_can_tx(struct device *dev, u8 u8mailboxnumber, u8 u8prunumber)
+{
+	u32 u32offset = 0;
+	u32 u32value = 0;
+	s16 s16subrtnretval = -1;
+
+	if (DA8XX_PRUCORE_1 == u8prunumber) {
+		switch (u8mailboxnumber) {
+		case 0:
+			u32offset = (PRU_CAN_TX_MAILBOX0_STATUS_REGISTER & 0xFFFF);
+			u32value = 0x00000080;
+			s16subrtnretval = pruss_writel(dev, u32offset,
+					(u32 *) &u32value, 1);
+			if (s16subrtnretval == -1) {
+				return -1;
+			}
+			break;
+		case 1:
+			u32offset = (PRU_CAN_TX_MAILBOX1_STATUS_REGISTER & 0xFFFF);
+			u32value = 0x00000080;
+			s16subrtnretval = pruss_writel(dev, u32offset,
+						(u32 *) &u32value, 1);
+			if (s16subrtnretval == -1) {
+				return -1;
+			}
+			break;
+		case 2:
+			u32offset = (PRU_CAN_TX_MAILBOX2_STATUS_REGISTER & 0xFFFF);
+			u32value = 0x00000080;
+			s16subrtnretval = pruss_writel(dev, u32offset,
+						(u32 *) &u32value, 1);
+			if (s16subrtnretval == -1) {
+				return -1;
+			}
+			break;
+		case 3:
+			u32offset = (PRU_CAN_TX_MAILBOX3_STATUS_REGISTER & 0xFFFF);
+			u32value = 0x00000080;
+			s16subrtnretval = pruss_writel(dev, u32offset,
+						(u32 *) &u32value, 1);
+			if (s16subrtnretval == -1) {
+				return -1;
+			}
+			break;
+		case 4:
+			u32offset = (PRU_CAN_TX_MAILBOX4_STATUS_REGISTER & 0xFFFF);
+			u32value = 0x00000080;
+			s16subrtnretval = pruss_writel(dev, u32offset,
+						(u32 *) &u32value, 1);
+			if (s16subrtnretval == -1) {
+				return -1;
+			}
+			break;
+		case 5:
+			u32offset = (PRU_CAN_TX_MAILBOX5_STATUS_REGISTER & 0xFFFF);
+			u32value = 0x00000080;
+			s16subrtnretval = pruss_writel(dev, u32offset,
+						(u32 *) &u32value, 1);
+			if (s16subrtnretval == -1) {
+				return -1;
+			}
+			break;
+		case 6:
+			u32offset = (PRU_CAN_TX_MAILBOX6_STATUS_REGISTER & 0xFFFF);
+			u32value = 0x00000080;
+			s16subrtnretval = pruss_writel(dev, u32offset,
+						(u32 *) &u32value, 1);
+			if (s16subrtnretval == -1) {
+				return -1;
+			}
+			break;
+		case 7:
+			u32offset = (PRU_CAN_TX_MAILBOX7_STATUS_REGISTER & 0xFFFF);
+			u32value = 0x00000080;
+			s16subrtnretval = pruss_writel(dev, u32offset,
+						(u32 *) &u32value, 1);
+			if (s16subrtnretval == -1) {
+				return -1;
+			}
+			break;
+		default:
+			return -1;
+		}
+	} else {
+
+		u32offset = (PRU_CAN_RX_INTERRUPT_STATUS_REGISTER & 0xFFFF);
+		u32value = 0x00000000;
+		s16subrtnretval = pruss_readl(dev, u32offset,
+						(u32 *) &u32value, 1);
+		if (s16subrtnretval == -1) {
+			return -1;
+		}
+		u32value = u32value & ~(1 << u8mailboxnumber);
+		s16subrtnretval = pruss_writel(dev, u32offset,
+					(u32 *) &u32value, 1);
+		if (s16subrtnretval == -1) {
+			return -1;
+		}
+
+		switch (u8mailboxnumber) {
+		case 0:
+			u32offset = (PRU_CAN_RX_MAILBOX0_STATUS_REGISTER & 0xFFFF);
+			u32value = 0x00000000;
+			s16subrtnretval = pruss_writel(dev, u32offset,
+						(u32 *) &u32value, 1);
+			if (s16subrtnretval == -1) {
+				return -1;
+			}
+			break;
+		case 1:
+			u32offset = (PRU_CAN_RX_MAILBOX1_STATUS_REGISTER & 0xFFFF);
+			u32value = 0x00000000;
+			s16subrtnretval = pruss_writel(dev, u32offset,
+						(u32 *) &u32value, 1);
+			if (s16subrtnretval == -1) {
+				return -1;
+			}
+			break;
+		case 2:
+			u32offset = (PRU_CAN_RX_MAILBOX2_STATUS_REGISTER & 0xFFFF);
+			u32value = 0x00000000;
+			s16subrtnretval = pruss_writel(dev, u32offset,
+						(u32 *) &u32value, 1);
+			if (s16subrtnretval == -1) {
+				return -1;
+			}
+			break;
+		case 3:
+			u32offset = (PRU_CAN_RX_MAILBOX3_STATUS_REGISTER & 0xFFFF);
+			u32value = 0x00000000;
+			s16subrtnretval = pruss_writel(dev, u32offset,
+						(u32 *) &u32value, 1);
+			if (s16subrtnretval == -1) {
+				return -1;
+			}
+			break;
+		case 4:
+			u32offset = (PRU_CAN_RX_MAILBOX4_STATUS_REGISTER & 0xFFFF);
+			u32value = 0x00000000;
+			s16subrtnretval = pruss_writel(dev, u32offset,
+						(u32 *) &u32value, 1);
+			if (s16subrtnretval == -1) {
+				return -1;
+			}
+			break;
+		case 5:
+			u32offset = (PRU_CAN_RX_MAILBOX5_STATUS_REGISTER & 0xFFFF);
+			u32value = 0x00000000;
+			s16subrtnretval = pruss_writel(dev, u32offset,
+						(u32 *) &u32value, 1);
+			if (s16subrtnretval == -1) {
+				return -1;
+			}
+			break;
+		case 6:
+			u32offset = (PRU_CAN_RX_MAILBOX6_STATUS_REGISTER & 0xFFFF);
+			u32value = 0x00000000;
+			s16subrtnretval = pruss_writel(dev, u32offset,
+						(u32 *) &u32value, 1);
+			if (s16subrtnretval == -1) {
+				return -1;
+			}
+			break;
+		case 7:
+			u32offset = (PRU_CAN_RX_MAILBOX7_STATUS_REGISTER & 0xFFFF);
+			u32value = 0x00000000;
+			s16subrtnretval = pruss_writel(dev, u32offset,
+						(u32 *) &u32value, 1);
+			if (s16subrtnretval == -1) {
+				return -1;
+			}
+			break;
+		default:
+			return -1;
+		}
+	}
+	return 0;
+}
+
+s16 pru_can_start_abort_tx(struct device *dev, bool bcantransmitabortflag)
+{
+	u32 u32offset;
+	u32 u32value;
+	s16 s16subrtnretval;
+	u32offset = (PRUSS_INTC_STATIDXCLR & 0xFFFF);
+	u32value = 32;
+	s16subrtnretval = pruss_writel(dev, u32offset,
+					(u32 *) &u32value, 1);
+
+	u32offset = (PRUSS_INTC_ENIDXSET & 0xFFFF);
+	u32value = 32;
+	s16subrtnretval = pruss_writel(dev, u32offset,
+					(u32 *) &u32value, 1);
+
+	u32offset = (PRUSS_INTC_STATIDXSET & 0xFFFF);
+	u32value = 32;
+	s16subrtnretval = pruss_writel(dev, u32offset,
+					(u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+	return 0;
+}
+
+s16 pru_can_mask_ints(struct device *dev, u32 int_mask)
+{
+	return 0;
+}
+
+int pru_can_get_error_cnt(struct device *dev, u8 u8prunumber)
+{
+	return 0;
+}
+
+int pru_can_get_intc_status(struct device *dev)
+{
+	u32 u32offset = 0;
+	u32 u32getvalue = 0;
+	u32 u32clrvalue = 0;
+
+	u32offset = (PRUSS_INTC_STATCLRINT1 & 0xFFFF);
+	pruss_readl(dev, u32offset, (u32 *) &u32getvalue, 1);
+
+	if (u32getvalue & 4)
+		u32clrvalue = 34;	/* CLR Event 34 */
+
+	if (u32getvalue & 2)
+		u32clrvalue = 33;	/* CLR Event 33  */
+
+	if (u32clrvalue) {
+		u32offset = (PRUSS_INTC_STATIDXCLR & 0xFFFF);
+		pruss_writel(dev, u32offset, &u32clrvalue, 1);
+	} else
+		return -1;
+
+	return u32getvalue;
+}
diff --git a/drivers/net/can/da8xx_pruss/pruss_can_api.h b/drivers/net/can/da8xx_pruss/pruss_can_api.h
new file mode 100644
index 0000000..7550456
--- /dev/null
+++ b/drivers/net/can/da8xx_pruss/pruss_can_api.h
@@ -0,0 +1,290 @@
+/*
+ * Copyright (C) 2010 Texas Instruments Incorporated
+ * Author: Ganeshan N
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as  published by the
+ * Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
+ * whether express or implied; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef _PRU_CAN_API_H_
+#define _PRU_CAN_API_H_
+
+#include <linux/types.h>
+#include <linux/mfd/pruss/da8xx_pru.h>
+
+
+#define CAN_BIT_TIMINGS			(0x273)
+
+/* Timer Clock is sourced from DDR freq (PLL1 SYS CLK 2) */
+#define	TIMER_CLK_FREQ			132000000
+
+#define TIMER_SETUP_DELAY		14
+#define GPIO_SETUP_DELAY		150
+
+#define CAN_RX_PRU_0			PRUSS_NUM0
+#define CAN_TX_PRU_1			PRUSS_NUM1
+
+/* Number of Instruction in the Delay loop */
+#define DELAY_LOOP_LENGTH		2
+
+#define PRU1_BASE_ADDR			0x2000
+
+#define PRU_CAN_TX_GLOBAL_CONTROL_REGISTER		(PRU1_BASE_ADDR)
+#define PRU_CAN_TX_GLOBAL_STATUS_REGISTER		(PRU1_BASE_ADDR	+ 0x04)
+#define PRU_CAN_TX_INTERRUPT_MASK_REGISTER		(PRU1_BASE_ADDR	+ 0x08)
+#define PRU_CAN_TX_INTERRUPT_STATUS_REGISTER		(PRU1_BASE_ADDR	+ 0x0C)
+#define PRU_CAN_TX_MAILBOX0_STATUS_REGISTER		(PRU1_BASE_ADDR	+ 0x10)
+#define PRU_CAN_TX_MAILBOX1_STATUS_REGISTER		(PRU1_BASE_ADDR	+ 0x14)
+#define PRU_CAN_TX_MAILBOX2_STATUS_REGISTER		(PRU1_BASE_ADDR	+ 0x18)
+#define PRU_CAN_TX_MAILBOX3_STATUS_REGISTER		(PRU1_BASE_ADDR	+ 0x1C)
+#define PRU_CAN_TX_MAILBOX4_STATUS_REGISTER		(PRU1_BASE_ADDR	+ 0x20)
+#define PRU_CAN_TX_MAILBOX5_STATUS_REGISTER		(PRU1_BASE_ADDR	+ 0x24)
+#define PRU_CAN_TX_MAILBOX6_STATUS_REGISTER		(PRU1_BASE_ADDR	+ 0x28)
+#define PRU_CAN_TX_MAILBOX7_STATUS_REGISTER		(PRU1_BASE_ADDR	+ 0x2C)
+#define PRU_CAN_TX_ERROR_COUNTER_REGISTER		(PRU1_BASE_ADDR	+ 0x30)
+#define PRU_CAN_TX_TIMING_REGISTER			(PRU1_BASE_ADDR	+ 0x34)
+#define PRU_CAN_TX_CLOCK_BRP_REGISTER			(PRU1_BASE_ADDR	+ 0x38)
+
+#define PRU_CAN_TX_MAILBOX0				(PRU1_BASE_ADDR	+ 0x40)
+#define PRU_CAN_TX_MAILBOX1				(PRU1_BASE_ADDR	+ 0x50)
+#define PRU_CAN_TX_MAILBOX2				(PRU1_BASE_ADDR	+ 0x60)
+#define PRU_CAN_TX_MAILBOX3				(PRU1_BASE_ADDR	+ 0x70)
+#define PRU_CAN_TX_MAILBOX4				(PRU1_BASE_ADDR	+ 0x80)
+#define PRU_CAN_TX_MAILBOX5				(PRU1_BASE_ADDR	+ 0x90)
+#define PRU_CAN_TX_MAILBOX6				(PRU1_BASE_ADDR	+ 0xA0)
+#define PRU_CAN_TX_MAILBOX7				(PRU1_BASE_ADDR	+ 0xB0)
+
+#define PRU_CAN_TIMING_VAL_TX				(PRU1_BASE_ADDR	+ 0xC0)
+#define PRU_CAN_TIMING_VAL_TX_SJW			(PRU1_BASE_ADDR	+ 0xC4)
+#define PRU_CAN_TRANSMIT_FRAME				(PRU1_BASE_ADDR	+ 0xE0)
+
+#define PRU0_BASE_ADDR					0
+
+#define PRU_CAN_RX_GLOBAL_CONTROL_REGISTER		(PRU0_BASE_ADDR)
+#define PRU_CAN_RX_GLOBAL_STATUS_REGISTER		(PRU0_BASE_ADDR	+ 0x04)
+#define PRU_CAN_RX_INTERRUPT_MASK_REGISTER		(PRU0_BASE_ADDR	+ 0x08)
+#define PRU_CAN_RX_INTERRUPT_STATUS_REGISTER		(PRU0_BASE_ADDR	+ 0x0C)
+#define PRU_CAN_RX_MAILBOX0_STATUS_REGISTER		(PRU0_BASE_ADDR	+ 0x10)
+#define PRU_CAN_RX_MAILBOX1_STATUS_REGISTER		(PRU0_BASE_ADDR	+ 0x14)
+#define PRU_CAN_RX_MAILBOX2_STATUS_REGISTER		(PRU0_BASE_ADDR	+ 0x18)
+#define PRU_CAN_RX_MAILBOX3_STATUS_REGISTER		(PRU0_BASE_ADDR	+ 0x1C)
+#define PRU_CAN_RX_MAILBOX4_STATUS_REGISTER		(PRU0_BASE_ADDR	+ 0x20)
+#define PRU_CAN_RX_MAILBOX5_STATUS_REGISTER		(PRU0_BASE_ADDR	+ 0x24)
+#define PRU_CAN_RX_MAILBOX6_STATUS_REGISTER		(PRU0_BASE_ADDR	+ 0x28)
+#define PRU_CAN_RX_MAILBOX7_STATUS_REGISTER		(PRU0_BASE_ADDR	+ 0x2C)
+#define PRU_CAN_RX_MAILBOX8_STATUS_REGISTER		(PRU0_BASE_ADDR	+ 0x30)
+#define PRU_CAN_RX_ERROR_COUNTER_REGISTER		(PRU0_BASE_ADDR	+ 0x34)
+#define PRU_CAN_RX_TIMING_REGISTER			(PRU0_BASE_ADDR	+ 0x38)
+#define PRU_CAN_RX_CLOCK_BRP_REGISTER			(PRU0_BASE_ADDR	+ 0x3C)
+
+#define PRU_CAN_RX_MAILBOX0				(PRU0_BASE_ADDR	+ 0x40)
+#define PRU_CAN_RX_MAILBOX1				(PRU0_BASE_ADDR	+ 0x50)
+#define PRU_CAN_RX_MAILBOX2				(PRU0_BASE_ADDR	+ 0x60)
+#define PRU_CAN_RX_MAILBOX3				(PRU0_BASE_ADDR	+ 0x70)
+#define PRU_CAN_RX_MAILBOX4				(PRU0_BASE_ADDR	+ 0x80)
+#define PRU_CAN_RX_MAILBOX5				(PRU0_BASE_ADDR	+ 0x90)
+#define PRU_CAN_RX_MAILBOX6				(PRU0_BASE_ADDR	+ 0xA0)
+#define PRU_CAN_RX_MAILBOX7				(PRU0_BASE_ADDR	+ 0xB0)
+#define PRU_CAN_RX_MAILBOX8				(PRU0_BASE_ADDR	+ 0xC0)
+
+#define PRU_CAN_TIMING_VAL_RX				(PRU0_BASE_ADDR	+ 0xD0)
+#define PRU_CAN_RECEIVE_FRAME				(PRU0_BASE_ADDR	+ 0xD4)
+#define PRU_CAN_ID_MAP					(PRU0_BASE_ADDR	+ 0xF0)
+
+#define PRU_CAN_ERROR_ACTIVE				128
+
+#define CAN_ACK_FAILED					0xE
+#define CAN_ARBTR_FAIL					0xD
+#define CAN_BIT_ERROR					0xC
+#define CAN_TRANSMISSION_SUCCESS			0xA
+
+#define STD_DATA_FRAME					0x1
+#define EXTD_DATA_FRAME					0x2
+#define STD_REMOTE_FRAME				0x3
+#define EXTD_REMOTE_FRAME				0x4
+
+#define PRU_CAN_MAX_SJW					8
+#define PRU_CAN_MAX_PHSEG1				25
+#define PRU_CAN_MAX_PHSEG2				25
+
+#define DA8XX_PRUCANCORE_0_REGS				0x7000
+#define DA8XX_PRUCANCORE_1_REGS				0x7800
+#define PRU0_PROG_RAM_START_OFFSET			0x8000
+#define PRU1_PROG_RAM_START_OFFSET			0xC000
+#define PRU_CAN_INIT_MAX_TIMEOUT			0xFF
+
+typedef enum {
+	ecaninst0 = 0,
+	ecaninst1,
+	ecanmaxinst
+} can_instance_enum;
+
+typedef enum {
+	ecanmailbox0 = 0,
+	ecanmailbox1,
+	ecanmailbox2,
+	ecanmailbox3,
+	ecanmailbox4,
+	ecanmailbox5,
+	ecanmailbox6,
+	ecanmailbox7
+} can_mailbox_number;
+
+typedef enum {
+	ecandirectioninit = 0,
+	ecantransmit,
+	ecanreceive
+} can_transfer_direction;
+
+typedef struct {
+	u16 u16extendedidentifier;
+	u16 u16baseidentifier;
+	u8 u8data7;
+	u8 u8data6;
+	u8 u8data5;
+	u8 u8data4;
+	u8 u8data3;
+	u8 u8data2;
+	u8 u8data1;
+	u8 u8data0;
+	u16 u16datalength;
+	u16 u16crc;
+} can_mail_box_structure;
+
+typedef struct {
+	can_transfer_direction ecantransferdirection;
+} can_mailbox_config;
+
+typedef struct {
+	can_instance_enum ecaninstance;
+	can_transfer_direction ecantransferdirection;
+	can_mail_box_structure strcanmailbox;
+	can_mailbox_number ecanmailboxnumber;
+	u8 u8prunumber;
+	u32 u32globalstatus;
+	u32 u32interruptstatus;
+	u32 u32mailboxstatus;
+} can_emu_app_hndl;
+
+typedef struct {
+	bool bcaninststate;
+	can_transfer_direction ecantransferdirection;
+	u32 u32apphandlerptr;
+} can_emu_drv_inst;
+
+typedef struct {
+	u8 u8syncjumpwidth;
+	u8 u8phseg1;
+	u8 u8phseg2;
+} can_bit_timing_consts;
+
+/* Field Definition Macros  */
+
+/* CONTROL */
+
+/*
+ * pru_can_set_brp() Updates the  BRP register of PRU.
+ */
+s16 pru_can_set_brp(struct device *dev, u16 u16prescaler);
+
+/*
+ * pru_can_set_bit_timing() Updates the  timing register of PRU
+ */
+s16 pru_can_set_bit_timing(struct device *dev,
+			can_bit_timing_consts *pstrbittiming);
+
+/*
+ * pru_can_calc_timing() Updates the timing values of PRU
+ */
+s16 pru_can_calc_timing(struct device *dev,
+			u32 u32bittiming, u32 u32bitrateprescaler);
+
+/*
+ * pru_can_write_data_to_mailbox() Updates the transmit mailboxes of PRU1
+ */
+s16 pru_can_write_data_to_mailbox(struct device *dev,
+			can_emu_app_hndl *pstremuapphndl);
+
+/*
+ * pru_can_get_data_from_mailbox() Receive data from receive mailboxes
+ */
+s16 pru_can_get_data_from_mailbox(struct device *dev,
+			can_emu_app_hndl *pstremuapphndl);
+
+/*
+ * pru_can_rx_id_map() Receive mailboxes ID Mapping of PRU0
+ */
+s16 pru_can_rx_id_map(struct device *dev,
+			u32 u32nodeid, can_mailbox_number ecanmailboxno);
+
+/*
+ *pru_can_get_intr_status() Get interrupts status register value
+ */
+s16 pru_can_get_intr_status(struct device *dev,
+			can_emu_app_hndl *pstremuapphndl);
+
+
+/*
+ * pru_can_get_global_status() Get the globalstatus register value
+ */
+s16 pru_can_get_global_status(struct device *dev,
+			can_emu_app_hndl *pstremuapphndl);
+
+/*
+ * pru_can_get_mailbox_status() Get mailbox status reg value
+ */
+s16 pru_can_get_mailbox_status(struct device *dev,
+			can_emu_app_hndl *pstremuapphndl);
+
+/*
+ * pru_can_configuration_mode_set() Sets timing val for data transfer
+ */
+s16 pru_can_config_mode_set(struct device *dev,
+			bool bconfig_modeflag);
+
+/*
+ * pru_can_emu_init() Initializes Can Emulation Parameters
+ */
+s16 pru_can_emu_init(struct device *dev,
+			u32 u32pruclock);
+
+/*
+ * pru_can_emu_open() Opens can emu for application to use
+ */
+s16 pru_can_emu_open(struct device *dev,
+			can_emu_app_hndl *pstremuapphndl);
+
+/*
+ * pru_can_emu_close() Closes can emu for applications to use
+ */
+s16 pru_can_emu_close(struct device *dev,
+			can_emu_app_hndl *pstremuapphndl);
+
+/*
+ * pru_can_emu_exit() Diables all the PRUs
+ */
+s16 pru_can_emu_exit(struct device *dev);
+
+s16 pru_can_tx_mode_set(struct device *dev, bool btransfer_flag,
+			 can_transfer_direction ecan_trx);
+
+s16 pru_can_emu_sreset(struct device *dev);
+
+s16 pru_can_tx(struct device *dev,
+			u8 u8mailboxnumber, u8 u8prunumber);
+
+s16 pru_can_start_abort_tx(struct device *dev,
+			bool btxabort_flag);
+
+s16 pru_can_mask_ints(struct device *dev, u32 int_mask);
+
+s32 pru_can_get_error_cnt(struct device *dev, u8 u8prunumber);
+
+s32 pru_can_get_intc_status(struct device *dev);
+#endif
-- 
1.7.2.3


^ permalink raw reply related

* Re: [PATCH v2 09/13] can: pruss CAN driver.
From: Kurt Van Dijck @ 2011-02-11 15:06 UTC (permalink / raw)
  To: Subhasish Ghosh
  Cc: sachi-EvXpCiN+lbve9wHmmfpqLFaTQe2KTcn/,
	davinci-linux-open-source-VycZQUHpC/PFrsHnngEfi1aTQe2KTcn/,
	open list:CAN NETWORK DRIVERS, nsekhar-l0cyMroinI0, open list,
	open list:CAN NETWORK DRIVERS,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	m-watkins-l0cyMroinI0, Wolfgang Grandegger
In-Reply-To: <1297435892-28278-10-git-send-email-subhasish-EvXpCiN+lbve9wHmmfpqLFaTQe2KTcn/@public.gmane.org>

On Fri, Feb 11, 2011 at 08:21:28PM +0530, Subhasish Ghosh wrote:
> +config DA8XX_PRU_CANID_MBX0
> +	hex "CANID for mailbox 0"
> +	depends on CAN_TI_DA8XX_PRU
> +	default "0x123"
> +	---help---
> +	Enter the CANID for mailbox 0
> +	Default value is set to 0x123, change this as required.
> +
> +config DA8XX_PRU_CANID_MBX1
> +	hex "CANID for mailbox 1"
> +	depends on CAN_TI_DA8XX_PRU
> +	default "0x123"
> +	 ---help---
> +	Enter the CANID for mailbox 1
> +	Default value is set to 0x123, change this as required.
> +
> +config DA8XX_PRU_CANID_MBX2
> +	hex "CANID for mailbox 2"
> +	depends on CAN_TI_DA8XX_PRU
> +	default "0x123"
> +	---help---
> +	Enter the CANID for mailbox 2
> +	Default value is set to 0x123, change this as required.
> +
> +config DA8XX_PRU_CANID_MBX3
> +	hex "CANID for mailbox 3"
> +	depends on CAN_TI_DA8XX_PRU
> +	default "0x123"
> +	---help---
> +	Enter the CANID for mailbox 3
> +	Default value is set to 0x123, change this as required.
> +
> +config DA8XX_PRU_CANID_MBX4
> +	hex "CANID for mailbox 4"
> +	depends on CAN_TI_DA8XX_PRU
> +	default "0x123"
> +	---help---
> +	Enter the CANID for mailbox 4
> +	Default value is set to 0x123, change this as required.
> +
> +config DA8XX_PRU_CANID_MBX5
> +	hex "CANID for mailbox 5"
> +	depends on CAN_TI_DA8XX_PRU
> +	default "0x123"
> +	---help---
> +	Enter the CANID for mailbox 5
> +	Default value is set to 0x123, change this as required.
> +
> +config DA8XX_PRU_CANID_MBX6
> +	hex "CANID for mailbox 6"
> +	depends on CAN_TI_DA8XX_PRU
> +	default "0x123"
> +	---help---
> +	Enter the CANID for mailbox 6
> +	Default value is set to 0x123, change this as required.
> +
> +config DA8XX_PRU_CANID_MBX7
> +	hex "CANID for mailbox 7"
> +	depends on CAN_TI_DA8XX_PRU
> +	default "0x123"
> +	---help---
> +	Enter the CANID for mailbox 7
> +	Default value is set to 0x123, change this as required.
Why is filling the mailboxes the job of kernel config?

Regards,
Kurt

^ permalink raw reply

* Re: [PATCH v2 09/13] can: pruss CAN driver.
From: Kurt Van Dijck @ 2011-02-11 15:20 UTC (permalink / raw)
  To: Subhasish Ghosh
  Cc: sachi-EvXpCiN+lbve9wHmmfpqLFaTQe2KTcn/,
	davinci-linux-open-source-VycZQUHpC/PFrsHnngEfi1aTQe2KTcn/,
	open list:CAN NETWORK DRIVERS, nsekhar-l0cyMroinI0, open list,
	open list:CAN NETWORK DRIVERS,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	m-watkins-l0cyMroinI0, Wolfgang Grandegger
In-Reply-To: <1297435892-28278-10-git-send-email-subhasish-EvXpCiN+lbve9wHmmfpqLFaTQe2KTcn/@public.gmane.org>

Hi,

I looked a bit at the TX path:

On Fri, Feb 11, 2011 at 08:21:28PM +0530, Subhasish Ghosh wrote:
> +static int omapl_pru_can_set_bittiming(struct net_device *ndev)
> +{
> +	struct omapl_pru_can_priv *priv = netdev_priv(ndev);
> +	struct can_bittiming *bt = &priv->can.bittiming;
> +	long bit_error = 0;
> +
> +	if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) {
> +		dev_warn(priv->dev, "WARN: Triple"
> +			 "sampling not set due to h/w limitations");
You should not have enabled CAN_CTRLMODE_3_SAMPLES in the first place?
> +	}
> +	if (pru_can_calc_timing(priv->dev, priv->can.clock.freq,
> +				bt->bitrate) != 0)
> +		return -EINVAL;
> +	bit_error =
> +	    (((priv->timer_freq / (priv->timer_freq / bt->bitrate)) -
> +	      bt->bitrate) * 1000) / bt->bitrate;
> +	if (bit_error) {
> +		bit_error =
> +		    (((priv->timer_freq / (priv->timer_freq / bt->bitrate)) -
> +		      bt->bitrate) * 1000000) / bt->bitrate;
> +		printk(KERN_INFO "\nBitrate error %ld.%ld%%\n",
> +			bit_error / 10000, bit_error % 1000);
> +	} else
> +		printk(KERN_INFO "\nBitrate error 0.0%%\n");
> +
> +	return 0;
> +}
I wonder how much of this code is duplicated from drivers/net/can/dev.c ?

> +static netdev_tx_t omapl_pru_can_start_xmit(struct sk_buff *skb,
> +					    struct net_device *ndev)
> +{
> +	struct omapl_pru_can_priv *priv = netdev_priv(ndev);
> +	struct can_frame *cf = (struct can_frame *)skb->data;
> +	int count;
> +	u8 *data = cf->data;
> +	u8 dlc = cf->can_dlc;
> +	u8 *ptr8data = NULL;
> +
most drivers start with:
	if (can_dropped_invalid_skb(dev, skb))
		return NETDEV_TX_OK;

> +	netif_stop_queue(ndev);
why would you stop when you just resumed the queue?
> +	if (cf->can_id & CAN_EFF_FLAG)	/* Extended frame format */
> +		*((u32 *) &priv->can_tx_hndl.strcanmailbox) =
> +		    (cf->can_id & CAN_EFF_MASK) | PRU_CANMID_IDE;
> +	else			/* Standard frame format */
> +		*((u32 *) &priv->can_tx_hndl.strcanmailbox) =
> +		    (cf->can_id & CAN_SFF_MASK) << 18;
> +
> +	if (cf->can_id & CAN_RTR_FLAG)	/* Remote transmission request */
> +		*((u32 *) &priv->can_tx_hndl.strcanmailbox) |= CAN_RTR_FLAG;
> +
> +	ptr8data = &priv->can_tx_hndl.strcanmailbox.u8data7 + (dlc - 1);
> +	for (count = 0; count < (u8) dlc; count++) {
> +		*ptr8data-- = *data++;
> +	}
> +	*((u32 *) &priv->can_tx_hndl.strcanmailbox.u16datalength) = (u32) dlc;
> +/*
> + * search for the next available mbx
> + * if the next mbx is busy, then try the next + 1
> + * do this until the head is reached.
> + * if still unable to tx, stop accepting any packets
> + * if able to tx and the head is reached, then reset next to tail, i.e mbx0
> + * if head is not reached, then just point to the next mbx
> + */
> +	for (; priv->tx_next <= priv->tx_head; priv->tx_next++) {
> +		priv->can_tx_hndl.ecanmailboxnumber =
> +		    (can_mailbox_number) priv->tx_next;
> +		if (-1 == pru_can_write_data_to_mailbox(priv->dev,
> +					&priv->can_tx_hndl)) {
> +			if (priv->tx_next == priv->tx_head) {
> +				priv->tx_next = priv->tx_tail;
> +				if (!netif_queue_stopped(ndev))
If you get here, the queue is not stopped. This test is therefore useless.
> +					netif_stop_queue(ndev);	/* IF stalled */
> +				dev_err(priv->dev,
> +					"%s: no tx mbx available", __func__);
> +				return NETDEV_TX_BUSY;
> +			} else
> +				continue;
> +		} else {
> +			/* set transmit request */
> +			pru_can_tx(priv->dev, priv->tx_next, CAN_TX_PRU_1);
> +			pru_can_tx_mode_set(priv->dev, false, ecanreceive);
> +			pru_can_tx_mode_set(priv->dev, true, ecantransmit);
> +			pru_can_start_abort_tx(priv->dev, PRU_CAN_START);
> +			priv->tx_next++;
> +			can_put_echo_skb(skb, ndev, 0);
> +			break;
> +		}
> +	}
> +	if (priv->tx_next > priv->tx_head) {
> +		priv->tx_next = priv->tx_tail;
> +	}
> +	return NETDEV_TX_OK;
> +}
> +
> +

> +irqreturn_t omapl_tx_can_intr(int irq, void *dev_id)
> +{
> +	struct net_device *ndev = dev_id;
> +	struct omapl_pru_can_priv *priv = netdev_priv(ndev);
> +	struct net_device_stats *stats = &ndev->stats;
> +	u32 bit_set, mbxno;
> +
> +	pru_can_get_intr_status(priv->dev, &priv->can_tx_hndl);
> +	if ((PRU_CAN_ISR_BIT_CCI & priv->can_tx_hndl.u32interruptstatus)
> +	    || (PRU_CAN_ISR_BIT_SRDI & priv->can_tx_hndl.u32interruptstatus)) {
> +		__can_debug("tx_int_status = 0x%X\n",
> +			    priv->can_tx_hndl.u32interruptstatus);
> +		can_free_echo_skb(ndev, 0);
> +	} else {
> +		for (bit_set = 0; ((priv->can_tx_hndl.u32interruptstatus & 0xFF)
> +						>> bit_set != 0); bit_set++)
> +		;
> +		if (0 == bit_set) {
> +			__can_err("%s: invalid mailbox number\n", __func__);
> +			can_free_echo_skb(ndev, 0);
> +		} else {
> +			mbxno = bit_set - 1;	/* mail box numbering starts from 0 */
> +			if (PRU_CAN_ISR_BIT_ESI & priv->can_tx_hndl.
> +			    u32interruptstatus) {
> +				/* read gsr and ack pru */
> +				pru_can_get_global_status(priv->dev, &priv->can_tx_hndl);
> +				omapl_pru_can_err(ndev,
> +						  priv->can_tx_hndl.
> +						  u32interruptstatus,
> +						  priv->can_tx_hndl.
> +						  u32globalstatus);
> +			} else {
> +				stats->tx_packets++;
> +				/* stats->tx_bytes += dlc; */
> +				/*can_get_echo_skb(ndev, 0);*/
> +			}
> +		}
> +	}
> +	if (netif_queue_stopped(ndev))
you can call netif_wake_queue(ndev) multiple times, so there is no need
for netif_queue_stopped()
> +		netif_wake_queue(ndev);
> +
> +	can_get_echo_skb(ndev, 0);
> +	pru_can_tx_mode_set(priv->dev, true, ecanreceive);
> +	return IRQ_HANDLED;
> +}
> +
> +static int omapl_pru_can_open(struct net_device *ndev)
> +{
> +	struct omapl_pru_can_priv *priv = netdev_priv(ndev);
> +	int err;
> +
> +	/* register interrupt handler */
> +	err = request_irq(priv->trx_irq, &omapl_rx_can_intr, IRQF_SHARED,
> +			  "pru_can_irq", ndev);
you're doing a lot of work _in_ the irq handler. Maybe threaded irq?

> +static int omapl_pru_can_close(struct net_device *ndev)
> +{
> +	struct omapl_pru_can_priv *priv = netdev_priv(ndev);
> +
> +	if (!netif_queue_stopped(ndev))
check is not needed.
> +		netif_stop_queue(ndev);
> +
> +	close_candev(ndev);
> +
> +	free_irq(priv->trx_irq, ndev);
> +	return 0;
> +}
> +

Regards,
Kurt

^ permalink raw reply

* [patch net-next-2.6 1/4] net: extend netlink interface to handle generic slave management
From: Jiri Pirko @ 2011-02-11 15:21 UTC (permalink / raw)
  To: netdev; +Cc: davem, shemminger, kaber, fubar

Drivers like bridge and bonding uses their own way to manipulate with
underlink devices. This is an attempt to introduce common interface using
netlink.

Signed-off-by: Jiri Pirko <jpirko@redhat.com>
---
 include/linux/if_link.h   |   13 +++++++
 include/linux/netdevice.h |   22 ++++++++++++
 net/core/rtnetlink.c      |   81 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 116 insertions(+), 0 deletions(-)

diff --git a/include/linux/if_link.h b/include/linux/if_link.h
index f4a2e6b..48a5f95 100644
--- a/include/linux/if_link.h
+++ b/include/linux/if_link.h
@@ -136,6 +136,9 @@ enum {
 	IFLA_PORT_SELF,
 	IFLA_AF_SPEC,
 	IFLA_GROUP,		/* Group the device belongs to */
+	IFLA_SLAVE_LIST,
+	IFLA_SLAVE_ADD,
+	IFLA_SLAVE_DEL,
 	__IFLA_MAX
 };
 
@@ -379,4 +382,14 @@ struct ifla_port_vsi {
 	__u8 pad[3];
 };
 
+/* Slave devices management section */
+
+enum {
+	IFLA_SLAVE_UNSPEC,
+	IFLA_SLAVE_DEV,
+	__IFLA_SLAVE_MAX,
+};
+
+#define IFLA_SLAVE_MAX (__IFLA_SLAVE_MAX - 1)
+
 #endif /* _LINUX_IF_LINK_H */
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index c7d7074..844cb85 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -783,6 +783,21 @@ struct netdev_tc_txq {
  *	Set hardware filter for RFS.  rxq_index is the target queue index;
  *	flow_id is a flow ID to be passed to rps_may_expire_flow() later.
  *	Return the filter ID on success, or a negative error code.
+ *
+ *	Slave management functions (for bridge, bonding, etc). User should
+ *	make sure that slave list doesn't change within rtnl_lock.
+ * int (*ndo_add_slave)(struct net_device *dev, struct net_device *slave_dev);
+ *	Called to make another netdev an underlink.
+ *
+ * int (*ndo_del_slave)(struct net_device *dev, struct net_device *slave_dev);
+ *	Called to release previously enslaved netdev.
+ *
+ * int (*ndo_get_slave_count)(const struct net_device *dev);
+ *	Called to get number of enslaved devices.
+ *
+ * struct net_device * (*ndo_get_slave)(const struct net_device *dev,
+ *					int slave_index);
+ *	Called to get slave device by it's index.
  */
 #define HAVE_NET_DEVICE_OPS
 struct net_device_ops {
@@ -862,6 +877,13 @@ struct net_device_ops {
 						     u16 rxq_index,
 						     u32 flow_id);
 #endif
+	int			(*ndo_add_slave)(struct net_device *dev,
+						 struct net_device *slave_dev);
+	int			(*ndo_del_slave)(struct net_device *dev,
+						 struct net_device *slave_dev);
+	int			(*ndo_get_slave_count)(const struct net_device *dev);
+	struct net_device *	(*ndo_get_slave)(const struct net_device *dev,
+						 int slave_index);
 };
 
 /*
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index da0fe45..1402a3f 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -739,6 +739,20 @@ static size_t rtnl_port_size(const struct net_device *dev)
 		return port_self_size;
 }
 
+static size_t rtnl_slave_list_size(const struct net_device *dev)
+{
+	size_t slave_size = nla_total_size(sizeof(struct nlattr)) +
+			    nla_total_size(4);
+	size_t slave_list_size = nla_total_size(sizeof(struct nlattr));
+	int slave_count;
+
+	if (!dev->netdev_ops->ndo_get_slave_count ||
+	    !dev->netdev_ops->ndo_get_slave)
+		return 0;
+	slave_count = dev->netdev_ops->ndo_get_slave_count(dev);
+	return slave_list_size + slave_count * slave_size;
+}
+
 static noinline size_t if_nlmsg_size(const struct net_device *dev)
 {
 	return NLMSG_ALIGN(sizeof(struct ifinfomsg))
@@ -760,6 +774,7 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev)
 	       + nla_total_size(4) /* IFLA_NUM_VF */
 	       + rtnl_vfinfo_size(dev) /* IFLA_VFINFO_LIST */
 	       + rtnl_port_size(dev) /* IFLA_VF_PORTS + IFLA_PORT_SELF */
+	       + rtnl_slave_list_size(dev) /* IFLA_SLAVE_LIST */
 	       + rtnl_link_get_size(dev) /* IFLA_LINKINFO */
 	       + rtnl_link_get_af_size(dev); /* IFLA_AF_SPEC */
 }
@@ -839,6 +854,39 @@ static int rtnl_port_fill(struct sk_buff *skb, struct net_device *dev)
 	return 0;
 }
 
+static int rtnl_slave_list_fill(struct sk_buff *skb, struct net_device *dev)
+{
+	int slave_count;
+	int i;
+	struct nlattr *slave_list;
+
+	if (!dev->netdev_ops->ndo_get_slave_count ||
+	    !dev->netdev_ops->ndo_get_slave)
+		return 0;
+	slave_count = dev->netdev_ops->ndo_get_slave_count(dev);
+	slave_list = nla_nest_start(skb, IFLA_SLAVE_LIST);
+	if (!slave_list)
+		return -EMSGSIZE;
+	for (i = 0; i < slave_count; i++) {
+		struct net_device *slave_dev;
+
+		slave_dev = dev->netdev_ops->ndo_get_slave(dev, i);
+		if (!slave_dev) {
+			nla_nest_cancel(skb, slave_list);
+			goto nla_put_failure;
+		}
+		NLA_PUT_U32(skb, IFLA_SLAVE_DEV, slave_dev->ifindex);
+	}
+	nla_nest_end(skb, slave_list);
+
+	return 0;
+
+nla_put_failure:
+	nla_nest_cancel(skb, slave_list);
+	return -EMSGSIZE;
+
+}
+
 static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
 			    int type, u32 pid, u32 seq, u32 change,
 			    unsigned int flags)
@@ -953,6 +1001,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
 	if (rtnl_port_fill(skb, dev))
 		goto nla_put_failure;
 
+	if (rtnl_slave_list_fill(skb, dev))
+		goto nla_put_failure;
+
 	if (dev->rtnl_link_ops) {
 		if (rtnl_link_fill(skb, dev) < 0)
 			goto nla_put_failure;
@@ -1047,6 +1098,8 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = {
 	[IFLA_VF_PORTS]		= { .type = NLA_NESTED },
 	[IFLA_PORT_SELF]	= { .type = NLA_NESTED },
 	[IFLA_AF_SPEC]		= { .type = NLA_NESTED },
+	[IFLA_SLAVE_ADD]	= { .type = NLA_U32 },
+	[IFLA_SLAVE_DEL]	= { .type = NLA_U32 },
 };
 EXPORT_SYMBOL(ifla_policy);
 
@@ -1392,6 +1445,34 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
 			modified = 1;
 		}
 	}
+
+	if (tb[IFLA_SLAVE_ADD]) {
+		int ifindex = nla_get_u32(tb[IFLA_SLAVE_ADD]);
+		struct net_device *slave_dev;
+
+		err = -EOPNOTSUPP;
+		if (ops->ndo_add_slave) {
+			slave_dev = __dev_get_by_index(dev_net(dev), ifindex);
+			err = ops->ndo_add_slave(dev, slave_dev);
+		}
+		if (err < 0)
+			goto errout;
+		modified = 1;
+	}
+
+	if (tb[IFLA_SLAVE_DEL]) {
+		int ifindex = nla_get_u32(tb[IFLA_SLAVE_DEL]);
+		struct net_device *slave_dev;
+
+		err = -EOPNOTSUPP;
+		if (ops->ndo_del_slave) {
+			slave_dev = __dev_get_by_index(dev_net(dev), ifindex);
+			err = ops->ndo_del_slave(dev, slave_dev);
+		}
+		if (err < 0)
+			goto errout;
+		modified = 1;
+	}
 	err = 0;
 
 errout:
-- 
1.7.3.4


^ permalink raw reply related

* [patch iproute2 2/4] implement slave management operations
From: Jiri Pirko @ 2011-02-11 15:22 UTC (permalink / raw)
  To: netdev; +Cc: davem, shemminger, kaber, fubar
In-Reply-To: <20110211152125.GA2763@psychotron.brq.redhat.com>


Signed-off-by: Jiri Pirko <jpirko@redhat.com>
---
 ip/ipaddress.c |   22 ++++++++++++++++++++++
 ip/iplink.c    |   16 ++++++++++++++++
 2 files changed, 38 insertions(+), 0 deletions(-)

diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index a775ecd..7446b81 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -216,6 +216,18 @@ static void print_vfinfo(FILE *fp, struct rtattr *vfinfo)
 		fprintf(fp, ", tx rate %d (Mbps)", vf_tx_rate->rate);
 }
 
+static void print_slave_info(FILE *fp, struct rtattr *sl)
+{
+	SPRINT_BUF(b1);
+
+	if (sl->rta_type != IFLA_SLAVE_DEV) {
+		fprintf(stderr, "BUG: rta type is %d\n", sl->rta_type);
+		return;
+	}
+
+	fprintf(fp, " %s", ll_idx_n2a(*(int*)RTA_DATA(sl), b1));
+}
+
 int print_linkinfo(const struct sockaddr_nl *who,
 		   struct nlmsghdr *n, void *arg)
 {
@@ -420,6 +432,16 @@ int print_linkinfo(const struct sockaddr_nl *who,
 			print_vfinfo(fp, i);
 	}
 
+	if (tb[IFLA_SLAVE_LIST]) {
+		struct rtattr *i, *slave_list = tb[IFLA_SLAVE_LIST];
+		int rem = RTA_PAYLOAD(slave_list);
+		fprintf(fp, "\n    slaves:");
+		for (i = RTA_DATA(slave_list);
+		     RTA_OK(i, rem);
+		     i = RTA_NEXT(i, rem))
+			print_slave_info(fp, i);
+	}
+
 	fprintf(fp, "\n");
 	fflush(fp);
 	return 0;
diff --git a/ip/iplink.c b/ip/iplink.c
index cb2c4f5..02c48a2 100644
--- a/ip/iplink.c
+++ b/ip/iplink.c
@@ -71,6 +71,7 @@ void iplink_usage(void)
 	fprintf(stderr, "	                  [ vf NUM [ mac LLADDR ]\n");
 	fprintf(stderr, "				   [ vlan VLANID [ qos VLAN-QOS ] ]\n");
 	fprintf(stderr, "				   [ rate TXRATE ] ] \n");
+	fprintf(stderr, "			  [ slave [ { add | del } ] DEVICE ]\n");
 	fprintf(stderr, "       ip link show [ DEVICE ]\n");
 
 	if (iplink_have_newlink()) {
@@ -361,6 +362,21 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
 			if (len < 0)
 				return -1;
 			addattr_nest_end(&req->n, vflist);
+		} else if (matches(*argv, "slave") == 0) {
+			int type;
+			int ifindex;
+			NEXT_ARG();
+			if (strcmp(*argv, "add") == 0)
+				type = IFLA_SLAVE_ADD;
+			else if (strcmp(*argv, "del") == 0)
+				type = IFLA_SLAVE_DEL;
+			else
+				invarg("Invalid slave action\n", *argv);
+			NEXT_ARG();
+			ifindex = ll_name_to_index(*argv);
+			if (!ifindex)
+				invarg("Invalid slave device\n", *argv);
+			addattr_l(&req->n, sizeof(*req), type, &ifindex, 4);
 #ifdef IFF_DYNAMIC
 		} else if (matches(*argv, "dynamic") == 0) {
 			NEXT_ARG();
-- 
1.7.3.4


^ permalink raw reply related

* [patch net-next-2.6 3/4] bond: implement slave management operations
From: Jiri Pirko @ 2011-02-11 15:22 UTC (permalink / raw)
  To: netdev; +Cc: davem, shemminger, kaber, fubar
In-Reply-To: <20110211152125.GA2763@psychotron.brq.redhat.com>


Signed-off-by: Jiri Pirko <jpirko@redhat.com>
---
 drivers/net/bonding/bond_main.c |   38 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 38 insertions(+), 0 deletions(-)

diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 1df9f0e..f8e59f9 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -4285,6 +4285,40 @@ unwind:
 	return res;
 }
 
+static int bond_add_slave(struct net_device *bond_dev,
+			  struct net_device *slave_dev)
+{
+	return bond_enslave(bond_dev, slave_dev);
+}
+
+static int bond_del_slave(struct net_device *bond_dev,
+			  struct net_device *slave_dev)
+{
+	return bond_release(bond_dev, slave_dev);
+}
+
+static int bond_get_slave_count(const struct net_device *bond_dev)
+{
+	struct bonding *bond = netdev_priv(bond_dev);
+
+	return bond->slave_cnt;
+}
+
+static struct net_device *bond_get_slave(const struct net_device *bond_dev,
+					 int slave_index)
+{
+	struct bonding *bond = netdev_priv(bond_dev);
+	struct slave *slave;
+	int i;
+
+	/* no need to hold bond->lock here, protected against writers by rtnl */
+	bond_for_each_slave(bond, slave, i) {
+		if (slave_index == i)
+			return slave->dev;
+	}
+	return NULL;
+}
+
 static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev)
 {
 	struct bonding *bond = netdev_priv(bond_dev);
@@ -4657,6 +4691,10 @@ static const struct net_device_ops bond_netdev_ops = {
 	.ndo_netpoll_cleanup	= bond_netpoll_cleanup,
 	.ndo_poll_controller	= bond_poll_controller,
 #endif
+	.ndo_add_slave		= bond_add_slave,
+	.ndo_del_slave		= bond_del_slave,
+	.ndo_get_slave_count	= bond_get_slave_count,
+	.ndo_get_slave		= bond_get_slave,
 };
 
 static void bond_destructor(struct net_device *bond_dev)
-- 
1.7.3.4


^ permalink raw reply related

* [patch net-next-2.6 4/4] bridge: implement slave management operations
From: Jiri Pirko @ 2011-02-11 15:23 UTC (permalink / raw)
  To: netdev; +Cc: davem, shemminger, kaber, fubar
In-Reply-To: <20110211152125.GA2763@psychotron.brq.redhat.com>


Signed-off-by: Jiri Pirko <jpirko@redhat.com>
---
 net/bridge/br_device.c |   44 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 44 insertions(+), 0 deletions(-)

diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 5564435..5648002 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -297,6 +297,46 @@ void br_netpoll_disable(struct net_bridge_port *p)
 
 #endif
 
+static int br_add_slave(struct net_device *dev, struct net_device *slave_dev)
+{
+	struct net_bridge *br = netdev_priv(dev);
+
+	return br_add_if(br, slave_dev);
+}
+
+static int br_del_slave(struct net_device *dev, struct net_device *slave_dev)
+{
+	struct net_bridge *br = netdev_priv(dev);
+
+	return br_del_if(br, slave_dev);
+}
+
+static int br_get_slave_count(const struct net_device *dev)
+{
+	struct net_bridge *br = netdev_priv(dev);
+	struct net_bridge_port *p;
+	int i = 0;
+
+	list_for_each_entry(p, &br->port_list, list) {
+		i++;
+	}
+	return i;
+}
+
+static struct net_device *br_get_slave(const struct net_device *dev,
+				       int slave_index)
+{
+	struct net_bridge *br = netdev_priv(dev);
+	struct net_bridge_port *p;
+	int i = 0;
+
+	list_for_each_entry(p, &br->port_list, list) {
+		if (slave_index == i++)
+			return p->dev;
+	}
+	return NULL;
+}
+
 static const struct ethtool_ops br_ethtool_ops = {
 	.get_drvinfo    = br_getinfo,
 	.get_link	= ethtool_op_get_link,
@@ -326,6 +366,10 @@ static const struct net_device_ops br_netdev_ops = {
 	.ndo_netpoll_cleanup	 = br_netpoll_cleanup,
 	.ndo_poll_controller	 = br_poll_controller,
 #endif
+	.ndo_add_slave		 = br_add_slave,
+	.ndo_del_slave		 = br_del_slave,
+	.ndo_get_slave_count	 = br_get_slave_count,
+	.ndo_get_slave		 = br_get_slave,
 };
 
 static void br_dev_free(struct net_device *dev)
-- 
1.7.3.4


^ permalink raw reply related

* Re: [patch iproute2 2/4] implement slave management operations
From: Jiri Pirko @ 2011-02-11 15:27 UTC (permalink / raw)
  To: shemminger; +Cc: davem, kaber, fubar, netdev
In-Reply-To: <20110211152214.GB2763@psychotron.brq.redhat.com>

Stephen,

I did not include include/linux/if_link.h changes here as I saw in
history it's been done in the same way. If they are needed I can repost.

Thanks, Jirka

Fri, Feb 11, 2011 at 04:22:15PM CET, jpirko@redhat.com wrote:
>
>Signed-off-by: Jiri Pirko <jpirko@redhat.com>
>---
> ip/ipaddress.c |   22 ++++++++++++++++++++++
> ip/iplink.c    |   16 ++++++++++++++++
> 2 files changed, 38 insertions(+), 0 deletions(-)
>
>diff --git a/ip/ipaddress.c b/ip/ipaddress.c
>index a775ecd..7446b81 100644
>--- a/ip/ipaddress.c
>+++ b/ip/ipaddress.c
>@@ -216,6 +216,18 @@ static void print_vfinfo(FILE *fp, struct rtattr *vfinfo)
> 		fprintf(fp, ", tx rate %d (Mbps)", vf_tx_rate->rate);
> }
> 
>+static void print_slave_info(FILE *fp, struct rtattr *sl)
>+{
>+	SPRINT_BUF(b1);
>+
>+	if (sl->rta_type != IFLA_SLAVE_DEV) {
>+		fprintf(stderr, "BUG: rta type is %d\n", sl->rta_type);
>+		return;
>+	}
>+
>+	fprintf(fp, " %s", ll_idx_n2a(*(int*)RTA_DATA(sl), b1));
>+}
>+
> int print_linkinfo(const struct sockaddr_nl *who,
> 		   struct nlmsghdr *n, void *arg)
> {
>@@ -420,6 +432,16 @@ int print_linkinfo(const struct sockaddr_nl *who,
> 			print_vfinfo(fp, i);
> 	}
> 
>+	if (tb[IFLA_SLAVE_LIST]) {
>+		struct rtattr *i, *slave_list = tb[IFLA_SLAVE_LIST];
>+		int rem = RTA_PAYLOAD(slave_list);
>+		fprintf(fp, "\n    slaves:");
>+		for (i = RTA_DATA(slave_list);
>+		     RTA_OK(i, rem);
>+		     i = RTA_NEXT(i, rem))
>+			print_slave_info(fp, i);
>+	}
>+
> 	fprintf(fp, "\n");
> 	fflush(fp);
> 	return 0;
>diff --git a/ip/iplink.c b/ip/iplink.c
>index cb2c4f5..02c48a2 100644
>--- a/ip/iplink.c
>+++ b/ip/iplink.c
>@@ -71,6 +71,7 @@ void iplink_usage(void)
> 	fprintf(stderr, "	                  [ vf NUM [ mac LLADDR ]\n");
> 	fprintf(stderr, "				   [ vlan VLANID [ qos VLAN-QOS ] ]\n");
> 	fprintf(stderr, "				   [ rate TXRATE ] ] \n");
>+	fprintf(stderr, "			  [ slave [ { add | del } ] DEVICE ]\n");
> 	fprintf(stderr, "       ip link show [ DEVICE ]\n");
> 
> 	if (iplink_have_newlink()) {
>@@ -361,6 +362,21 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
> 			if (len < 0)
> 				return -1;
> 			addattr_nest_end(&req->n, vflist);
>+		} else if (matches(*argv, "slave") == 0) {
>+			int type;
>+			int ifindex;
>+			NEXT_ARG();
>+			if (strcmp(*argv, "add") == 0)
>+				type = IFLA_SLAVE_ADD;
>+			else if (strcmp(*argv, "del") == 0)
>+				type = IFLA_SLAVE_DEL;
>+			else
>+				invarg("Invalid slave action\n", *argv);
>+			NEXT_ARG();
>+			ifindex = ll_name_to_index(*argv);
>+			if (!ifindex)
>+				invarg("Invalid slave device\n", *argv);
>+			addattr_l(&req->n, sizeof(*req), type, &ifindex, 4);
> #ifdef IFF_DYNAMIC
> 		} else if (matches(*argv, "dynamic") == 0) {
> 			NEXT_ARG();
>-- 
>1.7.3.4
>

^ permalink raw reply

* Re: [PATCH 1/2] igb: Allow extra 4 bytes on RX for vlan tags.
From: Jeff Kirsher @ 2011-02-11 15:46 UTC (permalink / raw)
  To: greearb; +Cc: netdev
In-Reply-To: <1297375149-18458-1-git-send-email-greearb@candelatech.com>

On Thu, Feb 10, 2011 at 13:59,  <greearb@candelatech.com> wrote:
> From: Ben Greear <greearb@candelatech.com>
>
> This allows the NIC to receive 1518 byte (not counting
> FCS) packets when MTU is 1500, thus allowing 1500 MTU
> VLAN frames to be received.  Please note that no VLANs
> were actually configured on the NIC...it was just acting
> as pass-through device.
>
> Signed-off-by: Ben Greear <greearb@candelatech.com>
> ---
> :100644 100644 58c665b... 30c9cc6... M  drivers/net/igb/igb_main.c
>  drivers/net/igb/igb_main.c |    5 +++--
>  1 files changed, 3 insertions(+), 2 deletions(-)
>

Thanks Ben, I have added the patch to my queue of igb patches.

-- 
Cheers,
Jeff

^ permalink raw reply

* Re: [patch net-next-2.6 1/4] net: extend netlink interface to handle generic slave management
From: Patrick McHardy @ 2011-02-11 15:48 UTC (permalink / raw)
  To: Jiri Pirko; +Cc: netdev, davem, shemminger, fubar
In-Reply-To: <20110211152125.GA2763@psychotron.brq.redhat.com>

On 11.02.2011 16:21, Jiri Pirko wrote:
> Drivers like bridge and bonding uses their own way to manipulate with
> underlink devices. This is an attempt to introduce common interface using
> netlink.

Thanks for working on this, this has been on my TODO list for a
long time.

> --- a/include/linux/if_link.h
> +++ b/include/linux/if_link.h
> @@ -136,6 +136,9 @@ enum {
>  	IFLA_PORT_SELF,
>  	IFLA_AF_SPEC,
>  	IFLA_GROUP,		/* Group the device belongs to */
> +	IFLA_SLAVE_LIST,
> +	IFLA_SLAVE_ADD,
> +	IFLA_SLAVE_DEL,

I don't like this very much though, the attributes usually contain
data, not commands. We already have NEWLINK, DELLINK etc. on the
top level, the combinations of NEWLINK/NLM_F_CREAT and SLAVE_DEL
or DELLINK and SLAVE_ADD and so on simply don't make sense.

We usually also try to keep the interface symetrical in both
directions (a NEWLINK message from the kernel is identical to a
NEWLINK message from userspace, a DELLINK message as well besides
containing additional information), so using different attributes
for dumping slaves than for adding them seems wrong. If we can
dump all slaves in one message, it should also be possible to
enslave multiple devices using the same message.

What I originally had planned to support enslaving devices is to
make use of the IFLA_MASTER attribute. The IFLA_MASTER attribute
would contain the bond or bridge ifindex and the IFLA_IFNAME
attribute or ifindex would specify the slave device. All operations
would be performed on the slave device as usual, if the IFLA_MASTER
attribute is present we'd additionally call a master specific
callback for enslaving or releasing slave devices. Besides allowing
to keep messages symetrical, an additional benefit is that it would
be possible to create and enslave a device in a single step.



^ permalink raw reply

* Re: [net-next-2.6 00/16][pull request] Intel Wired LAN Driver Updates
From: Jeff Kirsher @ 2011-02-11 15:55 UTC (permalink / raw)
  To: davem; +Cc: Jeff Kirsher, netdev, gospo, bphilips
In-Reply-To: <1297168167-15755-1-git-send-email-jeffrey.t.kirsher@intel.com>

On Tue, Feb 8, 2011 at 04:29, Jeff Kirsher <jeffrey.t.kirsher@intel.com> wrote:
> The following series contains e1000e cleanup patches, the addition of igb
> PF support for i350 devices and several ixgbe cleanup patches.
>
> The following are changes since commit 2360d2e8f01043632d6b651672bec66c49892f94:
>  enic: Update MAINTAINERS
>
> and are available in the git repository at:
>  master.kernel.org:/pub/scm/linux/kernel/git/jkirsher/net-next-2.6 master
>
> Atita Shirwaikar (1):
>  ixgbe: Adding 100MB FULL support in ethtool
>
> Bruce Allan (4):
>  e1000e: replace unbounded sprintf with snprintf
>  e1000e: use correct pointer when memcpy'ing a 2-dimensional array
>  e1000e: do not wakeup Tx queue until ready
>  e1000e: return appropriate errors for 'ethtool -r'
>
> Carolyn Wyborny (1):
>  igb: Enable PF side of SR-IOV support for i350 devices
>
> Don Skidmore (3):
>  ixgbe: fix namespace issue with ixgbe_dcb_txq_to_tc
>  ixgbe: cleanup namespace complaint by removing little used function
>  ixgbe: cleanup ixgbe_init_mbx_params_pf namespace issue
>
> John Fastabend (7):
>  ixgbe: DCB, only reprogram HW if the FCoE priority is changed
>  ixgbe: DCB, remove round robin mode on 82598 devices
>  ixgbe: DCB, abstract out dcb_config from DCB hardware configuration
>  ixgbe: DCB, implement 802.1Qaz routines
>  ixgbe: DCB, do not reset on CEE pg changes
>  ixgbe: DCB, remove RESET bit it is no longer needed
>  ixgbe: dcb, use hardware independent routines
>
>  drivers/net/e1000e/ethtool.c        |   13 ++-
>  drivers/net/e1000e/netdev.c         |   13 +-
>  drivers/net/igb/e1000_82575.c       |   10 ++-
>  drivers/net/igb/e1000_mbx.c         |   38 +++----
>  drivers/net/igb/igb_main.c          |    9 +-
>  drivers/net/ixgbe/ixgbe.h           |    5 +-
>  drivers/net/ixgbe/ixgbe_common.h    |    4 +-
>  drivers/net/ixgbe/ixgbe_dcb.c       |  176 +++++++++++++++++++++++++++++-
>  drivers/net/ixgbe/ixgbe_dcb.h       |   10 ++-
>  drivers/net/ixgbe/ixgbe_dcb_82598.c |   94 ++++++++--------
>  drivers/net/ixgbe/ixgbe_dcb_82598.h |   23 ++++-
>  drivers/net/ixgbe/ixgbe_dcb_82599.c |  115 +++++++++++--------
>  drivers/net/ixgbe/ixgbe_dcb_82599.h |   24 ++++-
>  drivers/net/ixgbe/ixgbe_dcb_nl.c    |  211 ++++++++++++++++++++++++++--------
>  drivers/net/ixgbe/ixgbe_ethtool.c   |   34 ++++++-
>  drivers/net/ixgbe/ixgbe_main.c      |   18 +--
>  drivers/net/ixgbe/ixgbe_mbx.c       |    2 +
>  drivers/net/ixgbe/ixgbe_mbx.h       |    2 +
>  include/linux/dcbnl.h               |    5 +
>  19 files changed, 601 insertions(+), 205 deletions(-)
>
> --

I will drop patch 3 (e1000e: do not wakeup Tx queue until ready) while
Bruce takes a second look at the patch.  I will be re-posting a pull
request once I have updated my net-next tree without that patch.

-- 
Cheers,
Jeff

^ permalink raw reply

* Re: [patch net-next-2.6 3/4] bond: implement slave management operations
From: Jay Vosburgh @ 2011-02-11 17:19 UTC (permalink / raw)
  To: Jiri Pirko; +Cc: netdev, davem, shemminger, kaber
In-Reply-To: <20110211152257.GC2763@psychotron.brq.redhat.com>

Jiri Pirko <jpirko@redhat.com> wrote:

>Signed-off-by: Jiri Pirko <jpirko@redhat.com>
>---
> drivers/net/bonding/bond_main.c |   38 ++++++++++++++++++++++++++++++++++++++
> 1 files changed, 38 insertions(+), 0 deletions(-)
>
>diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
>index 1df9f0e..f8e59f9 100644
>--- a/drivers/net/bonding/bond_main.c
>+++ b/drivers/net/bonding/bond_main.c

	I think this would be better served by a new bond_netlink.c
file instead of cramming this into (the already huge) bond_main.c.  In
the long run, there will be a lot more netlink related code in bonding,
so I think it makes sense to give it a file of its own from the
beginning.

>@@ -4285,6 +4285,40 @@ unwind:
> 	return res;
> }
>
>+static int bond_add_slave(struct net_device *bond_dev,
>+			  struct net_device *slave_dev)
>+{
>+	return bond_enslave(bond_dev, slave_dev);
>+}
>+
>+static int bond_del_slave(struct net_device *bond_dev,
>+			  struct net_device *slave_dev)
>+{
>+	return bond_release(bond_dev, slave_dev);
>+}
>+
>+static int bond_get_slave_count(const struct net_device *bond_dev)
>+{
>+	struct bonding *bond = netdev_priv(bond_dev);
>+
>+	return bond->slave_cnt;
>+}
>+
>+static struct net_device *bond_get_slave(const struct net_device *bond_dev,
>+					 int slave_index)
>+{
>+	struct bonding *bond = netdev_priv(bond_dev);
>+	struct slave *slave;
>+	int i;
>+
>+	/* no need to hold bond->lock here, protected against writers by rtnl */
>+	bond_for_each_slave(bond, slave, i) {
>+		if (slave_index == i)
>+			return slave->dev;
>+	}
>+	return NULL;

	I think using the name "slave_index" for this variable is
confusing, since it isn't the ifindex of the slave.  This "index" is
used to iterate through the list of slaves, so perhaps "slave_num" or
"slave_position" is clearer.  The same comment applies to the equivalent
code for bridge.

	-J

>+}
>+
> static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev)
> {
> 	struct bonding *bond = netdev_priv(bond_dev);
>@@ -4657,6 +4691,10 @@ static const struct net_device_ops bond_netdev_ops = {
> 	.ndo_netpoll_cleanup	= bond_netpoll_cleanup,
> 	.ndo_poll_controller	= bond_poll_controller,
> #endif
>+	.ndo_add_slave		= bond_add_slave,
>+	.ndo_del_slave		= bond_del_slave,
>+	.ndo_get_slave_count	= bond_get_slave_count,
>+	.ndo_get_slave		= bond_get_slave,
> };
>
> static void bond_destructor(struct net_device *bond_dev)
>-- 
>1.7.3.4
>

---
	-Jay Vosburgh, IBM Linux Technology Center, fubar@us.ibm.com

^ permalink raw reply

* [net-next-2.6 v2 02/15] e1000e: use correct pointer when memcpy'ing a 2-dimensional array
From: Jeff Kirsher @ 2011-02-11 17:20 UTC (permalink / raw)
  To: davem; +Cc: Bruce Allan, netdev, gospo, bphilips, Jeff Kirsher
In-Reply-To: <1297444862-32091-1-git-send-email-jeffrey.t.kirsher@intel.com>

From: Bruce Allan <bruce.w.allan@intel.com>

*e1000_gstrings_test is not the same size as e1000_gstrings_test.

Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Tested-by: Jeff Pieper <jeffrey.e.pieper@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
 drivers/net/e1000e/ethtool.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c
index daa7fe4..0c08599 100644
--- a/drivers/net/e1000e/ethtool.c
+++ b/drivers/net/e1000e/ethtool.c
@@ -2006,7 +2006,7 @@ static void e1000_get_strings(struct net_device *netdev, u32 stringset,
 
 	switch (stringset) {
 	case ETH_SS_TEST:
-		memcpy(data, *e1000_gstrings_test, sizeof(e1000_gstrings_test));
+		memcpy(data, e1000_gstrings_test, sizeof(e1000_gstrings_test));
 		break;
 	case ETH_SS_STATS:
 		for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) {
-- 
1.7.4


^ permalink raw reply related

* [net-next-2.6 v2 00/15][pull request] Intel Wired LAN Driver Updates
From: Jeff Kirsher @ 2011-02-11 17:20 UTC (permalink / raw)
  To: davem; +Cc: Jeff Kirsher, netdev, gospo, bphilips

The following series contains e1000e cleanup patches, the addition of igb
PF support for i350 devices and several ixgbe cleanup patches.

v2 - drop "e1000e: do not wakeup Tx queue until ready" while Bruce takes a
second look at the patch.

The following are changes since commit 6431cbc25fa21635ee04eb0516ba6c51389fbfac:
  inet: Create a mechanism for upward inetpeer propagation into routes.

and are available in the git repository at:
  master.kernel.org:/pub/scm/linux/kernel/git/jkirsher/net-next-2.6 master

Atita Shirwaikar (1):
  ixgbe: Adding 100MB FULL support in ethtool

Bruce Allan (3):
  e1000e: replace unbounded sprintf with snprintf
  e1000e: use correct pointer when memcpy'ing a 2-dimensional array
  e1000e: return appropriate errors for 'ethtool -r'

Carolyn Wyborny (1):
  igb: Enable PF side of SR-IOV support for i350 devices

Don Skidmore (3):
  ixgbe: fix namespace issue with ixgbe_dcb_txq_to_tc
  ixgbe: cleanup namespace complaint by removing little used function
  ixgbe: cleanup ixgbe_init_mbx_params_pf namespace issue

John Fastabend (7):
  ixgbe: DCB, only reprogram HW if the FCoE priority is changed
  ixgbe: DCB, remove round robin mode on 82598 devices
  ixgbe: DCB, abstract out dcb_config from DCB hardware configuration
  ixgbe: DCB, implement 802.1Qaz routines
  ixgbe: DCB, do not reset on CEE pg changes
  ixgbe: DCB, remove RESET bit it is no longer needed
  ixgbe: DCB, use hardware independent routines

 drivers/net/e1000e/ethtool.c        |   13 ++-
 drivers/net/e1000e/netdev.c         |    8 +-
 drivers/net/igb/e1000_82575.c       |   10 ++-
 drivers/net/igb/e1000_mbx.c         |   38 +++----
 drivers/net/igb/igb_main.c          |    9 +-
 drivers/net/ixgbe/ixgbe.h           |    5 +-
 drivers/net/ixgbe/ixgbe_common.h    |    4 +-
 drivers/net/ixgbe/ixgbe_dcb.c       |  177 +++++++++++++++++++++++++++++-
 drivers/net/ixgbe/ixgbe_dcb.h       |   10 ++-
 drivers/net/ixgbe/ixgbe_dcb_82598.c |   94 ++++++++--------
 drivers/net/ixgbe/ixgbe_dcb_82598.h |   23 ++++-
 drivers/net/ixgbe/ixgbe_dcb_82599.c |  115 +++++++++++--------
 drivers/net/ixgbe/ixgbe_dcb_82599.h |   24 ++++-
 drivers/net/ixgbe/ixgbe_dcb_nl.c    |  211 ++++++++++++++++++++++++++--------
 drivers/net/ixgbe/ixgbe_ethtool.c   |   34 ++++++-
 drivers/net/ixgbe/ixgbe_main.c      |   22 ++--
 drivers/net/ixgbe/ixgbe_mbx.c       |    2 +
 drivers/net/ixgbe/ixgbe_mbx.h       |    2 +
 include/linux/dcbnl.h               |    5 +
 19 files changed, 605 insertions(+), 201 deletions(-)

-- 
1.7.4


^ permalink raw reply

* [net-next-2.6 v2 03/15] e1000e: return appropriate errors for 'ethtool -r'
From: Jeff Kirsher @ 2011-02-11 17:20 UTC (permalink / raw)
  To: davem; +Cc: Bruce Allan, netdev, gospo, bphilips, Jeff Kirsher
In-Reply-To: <1297444862-32091-1-git-send-email-jeffrey.t.kirsher@intel.com>

From: Bruce Allan <bruce.w.allan@intel.com>

...when invoked while interface is not up or when auto-negotiation is
disabled as done by other drivers.

Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Tested-by: Jeff Pieper <jeffrey.e.pieper@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
 drivers/net/e1000e/ethtool.c |   11 +++++++++--
 1 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c
index 0c08599..65ef9b5 100644
--- a/drivers/net/e1000e/ethtool.c
+++ b/drivers/net/e1000e/ethtool.c
@@ -1963,8 +1963,15 @@ static int e1000_set_coalesce(struct net_device *netdev,
 static int e1000_nway_reset(struct net_device *netdev)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
-	if (netif_running(netdev))
-		e1000e_reinit_locked(adapter);
+
+	if (!netif_running(netdev))
+		return -EAGAIN;
+
+	if (!adapter->hw.mac.autoneg)
+		return -EINVAL;
+
+	e1000e_reinit_locked(adapter);
+
 	return 0;
 }
 
-- 
1.7.4


^ permalink raw reply related

* [net-next-2.6 v2 01/15] e1000e: replace unbounded sprintf with snprintf
From: Jeff Kirsher @ 2011-02-11 17:20 UTC (permalink / raw)
  To: davem; +Cc: Bruce Allan, netdev, gospo, bphilips, Jeff Kirsher
In-Reply-To: <1297444862-32091-1-git-send-email-jeffrey.t.kirsher@intel.com>

From: Bruce Allan <bruce.w.allan@intel.com>

Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Tested-by: Jeff Pieper <jeffrey.e.pieper@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
 drivers/net/e1000e/netdev.c |    8 ++++++--
 1 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 6025d5f..7cedfeb 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -1843,7 +1843,9 @@ static int e1000_request_msix(struct e1000_adapter *adapter)
 	int err = 0, vector = 0;
 
 	if (strlen(netdev->name) < (IFNAMSIZ - 5))
-		sprintf(adapter->rx_ring->name, "%s-rx-0", netdev->name);
+		snprintf(adapter->rx_ring->name,
+			 sizeof(adapter->rx_ring->name) - 1,
+			 "%s-rx-0", netdev->name);
 	else
 		memcpy(adapter->rx_ring->name, netdev->name, IFNAMSIZ);
 	err = request_irq(adapter->msix_entries[vector].vector,
@@ -1856,7 +1858,9 @@ static int e1000_request_msix(struct e1000_adapter *adapter)
 	vector++;
 
 	if (strlen(netdev->name) < (IFNAMSIZ - 5))
-		sprintf(adapter->tx_ring->name, "%s-tx-0", netdev->name);
+		snprintf(adapter->tx_ring->name,
+			 sizeof(adapter->tx_ring->name) - 1,
+			 "%s-tx-0", netdev->name);
 	else
 		memcpy(adapter->tx_ring->name, netdev->name, IFNAMSIZ);
 	err = request_irq(adapter->msix_entries[vector].vector,
-- 
1.7.4


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox