Netdev List
 help / color / mirror / Atom feed
* [PATCH 1/3] at91sam9263: add at91_can device to generic device definition
From: Marc Kleine-Budde @ 2009-09-17  9:37 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA
  Cc: Socketcan-core-0fE9KPoRgkgATYTw5x5z8w, Marc Kleine-Budde,
	wg-5Yr1BZd7O62+XT7JhA+gdA, Andrew Victor,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <1253180254-11910-1-git-send-email-mkl-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>

This patch adds the device definition for the at91_can device to
the generic device definiton file for the at91sam9263.

Signed-off-by: Hans J. Koch <hjk-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
Signed-off-by: Marc Kleine-Budde <mkl-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
---
 arch/arm/mach-at91/at91sam9263_devices.c |   36 ++++++++++++++++++++++++++++++
 arch/arm/mach-at91/include/mach/board.h  |    6 +++++
 2 files changed, 42 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index b7f2332..6026c2e 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -757,6 +757,42 @@ void __init at91_add_device_ac97(struct atmel_ac97_data *data)
 void __init at91_add_device_ac97(struct atmel_ac97_data *data) {}
 #endif
 
+/* --------------------------------------------------------------------
+ *  CAN Controller
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_CAN_AT91) || defined(CONFIG_CAN_AT91_MODULE)
+static struct resource can_resources[] = {
+	[0] = {
+		.start	= AT91SAM9263_BASE_CAN,
+		.end	= AT91SAM9263_BASE_CAN + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9263_ID_CAN,
+		.end	= AT91SAM9263_ID_CAN,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91sam9263_can_device = {
+	.name		= "at91_can",
+	.id		= -1,
+	.resource	= can_resources,
+	.num_resources	= ARRAY_SIZE(can_resources),
+};
+
+void __init at91_add_device_can(struct at91_can_data *data)
+{
+	at91_set_A_periph(AT91_PIN_PA13, 0);	/* CANTX */
+	at91_set_A_periph(AT91_PIN_PA14, 0);	/* CANRX */
+	at91sam9263_can_device.dev.platform_data = data;
+
+	platform_device_register(&at91sam9263_can_device);
+}
+#else
+void __init at91_add_device_can(struct at91_can_data *data) {}
+#endif
 
 /* --------------------------------------------------------------------
  *  LCD Controller
diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h
index e6afff8..134731c 100644
--- a/arch/arm/mach-at91/include/mach/board.h
+++ b/arch/arm/mach-at91/include/mach/board.h
@@ -179,6 +179,12 @@ extern void __init at91_add_device_isi(void);
  /* Touchscreen Controller */
 extern void __init at91_add_device_tsadcc(void);
 
+/* CAN */
+struct at91_can_data {
+	void (*transceiver_switch)(int on);
+};
+extern void __init at91_add_device_can(struct at91_can_data *data);
+
  /* LEDs */
 extern void __init at91_init_leds(u8 cpu_led, u8 timer_led);
 extern void __init at91_gpio_leds(struct gpio_led *leds, int nr);
-- 
1.6.4.3

^ permalink raw reply related

* [PATCH 2/3] at91sam9263ek: activate at91 CAN controller
From: Marc Kleine-Budde @ 2009-09-17  9:37 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA
  Cc: Socketcan-core-0fE9KPoRgkgATYTw5x5z8w, Marc Kleine-Budde,
	wg-5Yr1BZd7O62+XT7JhA+gdA, Andrew Victor,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <1253180254-11910-2-git-send-email-mkl-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>

This patch activates the at91 CAN controller for the at91sam9263ek
development board.

Signed-off-by: Hans J. Koch <hjk-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
Signed-off-by: Marc Kleine-Budde <mkl-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
---
 arch/arm/mach-at91/board-sam9263ek.c |   19 +++++++++++++++++++
 1 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
index 57d5252..e6268b3 100644
--- a/arch/arm/mach-at91/board-sam9263ek.c
+++ b/arch/arm/mach-at91/board-sam9263ek.c
@@ -400,6 +400,23 @@ static struct gpio_led ek_pwm_led[] = {
 	}
 };
 
+/*
+ * CAN
+ */
+static void sam9263ek_transceiver_switch(int on)
+{
+	if (on) {
+		at91_set_gpio_output(AT91_PIN_PA18, 1); /* CANRXEN */
+		at91_set_gpio_output(AT91_PIN_PA19, 0); /* CANRS */
+	} else {
+		at91_set_gpio_output(AT91_PIN_PA18, 0); /* CANRXEN */
+		at91_set_gpio_output(AT91_PIN_PA19, 1); /* CANRS */
+	}
+}
+
+static struct at91_can_data ek_can_data = {
+	.transceiver_switch = sam9263ek_transceiver_switch,
+};
 
 static void __init ek_board_init(void)
 {
@@ -431,6 +448,8 @@ static void __init ek_board_init(void)
 	/* LEDs */
 	at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
 	at91_pwm_leds(ek_pwm_led, ARRAY_SIZE(ek_pwm_led));
+	/* CAN */
+	at91_add_device_can(&ek_can_data);
 }
 
 MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK")
-- 
1.6.4.3

^ permalink raw reply related

* (unknown), 
From: Marc Kleine-Budde @ 2009-09-17  9:37 UTC (permalink / raw)
  To: netdev; +Cc: linux-arm-kernel, Socketcan-core, Andrew Victor, wg

Hi,

This patch series adds support for the Atmel CAN controller as found
on the AT91SAM9263.

It adds the at91_can to the generic device definition, activates the CAN
controller on the at91sam9263ek and adds the driver itself.

Changes since V1:
- let Kconfig depend on CAN_DEV
- add example how driver is used in baord file

Please review and consider for inclusion.

cheers, Marc

Marc Kleine-Budde (3):
      at91sam9263: add at91_can device to generic device definition
      at91sam9263ek: activate at91 CAN controller
      at91_can: add driver for Atmel's CAN controller on AT91SAM9263

 arch/arm/mach-at91/at91sam9263_devices.c |   36 +
 arch/arm/mach-at91/board-sam9263ek.c     |   19 +
 arch/arm/mach-at91/include/mach/board.h  |    6 +
 drivers/net/can/Kconfig                  |    6 +
 drivers/net/can/Makefile                 |    1 +
 drivers/net/can/at91_can.c               | 1186 ++++++++++++++++++++++++++++++
 6 files changed, 1254 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/can/at91_can.c


^ permalink raw reply

* [PATCH 3/3] at91_can: add driver for Atmel's CAN controller on AT91SAM9263
From: Marc Kleine-Budde @ 2009-09-17  9:37 UTC (permalink / raw)
  To: netdev
  Cc: linux-arm-kernel, Socketcan-core, Andrew Victor, wg,
	Marc Kleine-Budde
In-Reply-To: <1253180254-11910-3-git-send-email-mkl@pengutronix.de>

This patch add the driver for the SoC CAN controller in Atmel's AT91SAM9263.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/Kconfig    |    6 +
 drivers/net/can/Makefile   |    1 +
 drivers/net/can/at91_can.c | 1186 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 1193 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/can/at91_can.c

diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index 0900743..719d43c 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -82,6 +82,12 @@ config CAN_KVASER_PCI
 	  This driver is for the the PCIcanx and PCIcan cards (1, 2 or
 	  4 channel) from Kvaser (http://www.kvaser.com).
 
+config CAN_AT91
+	tristate "Atmel AT91 onchip CAN controller"
+	depends on CAN && CAN_DEV && ARCH_AT91SAM9263
+	---help---
+	  This is a driver for the SoC CAN controller in Atmel's AT91SAM9263.
+
 config CAN_DEBUG_DEVICES
 	bool "CAN devices debugging messages"
 	depends on CAN
diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
index 523a941..3a54a12 100644
--- a/drivers/net/can/Makefile
+++ b/drivers/net/can/Makefile
@@ -8,5 +8,6 @@ obj-$(CONFIG_CAN_DEV)		+= can-dev.o
 can-dev-y			:= dev.o
 
 obj-$(CONFIG_CAN_SJA1000)	+= sja1000/
+obj-$(CONFIG_CAN_AT91)		+= at91_can.o
 
 ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c
new file mode 100644
index 0000000..f67ae28
--- /dev/null
+++ b/drivers/net/can/at91_can.c
@@ -0,0 +1,1186 @@
+/*
+ * at91_can.c - CAN network driver for AT91 SoC CAN controller
+ *
+ * (C) 2007 by Hans J. Koch <hjk@linutronix.de>
+ * (C) 2008, 2009 by Marc Kleine-Budde <kernel@pengutronix.de>
+ *
+ * This software may be distributed under the terms of the GNU General
+ * Public License ("GPL") version 2 as distributed in the 'COPYING'
+ * file from the main directory of the linux kernel source.
+ *
+ * Send feedback to <socketcan-users@lists.berlios.de>
+ *
+ *
+ * Your platform definition file should specify something like:
+ *
+ * static struct at91_can_data ek_can_data = {
+ *	transceiver_switch = sam9263ek_transceiver_switch,
+ * };
+ *
+ * at91_add_device_can(&ek_can_data);
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/errno.h>
+#include <linux/if_arp.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/platform_device.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+#include <linux/can.h>
+#include <linux/can/dev.h>
+#include <linux/can/error.h>
+
+#include <mach/board.h>
+
+#define DRV_NAME		"at91_can"
+#define AT91_NAPI_WEIGHT	12
+
+/*
+ * RX/TX Mailbox split
+ * don't dare to touch
+ */
+#define AT91_MB_RX_NUM		12
+#define AT91_MB_TX_SHIFT	2
+
+#define AT91_MB_RX_FIRST	0
+#define AT91_MB_RX_LAST		(AT91_MB_RX_FIRST + AT91_MB_RX_NUM - 1)
+
+#define AT91_MB_RX_MASK(i)	((1 << (i)) - 1)
+#define AT91_MB_RX_SPLIT	8
+#define AT91_MB_RX_LOW_LAST	(AT91_MB_RX_SPLIT - 1)
+#define AT91_MB_RX_LOW_MASK	(AT91_MB_RX_MASK(AT91_MB_RX_SPLIT))
+
+#define AT91_MB_TX_NUM		(1 << AT91_MB_TX_SHIFT)
+#define AT91_MB_TX_FIRST	(AT91_MB_RX_LAST + 1)
+#define AT91_MB_TX_LAST		(AT91_MB_TX_FIRST + AT91_MB_TX_NUM - 1)
+
+#define AT91_NEXT_PRIO_SHIFT	(AT91_MB_TX_SHIFT)
+#define AT91_NEXT_PRIO_MASK	(0xf << AT91_MB_TX_SHIFT)
+#define AT91_NEXT_MB_MASK	(AT91_MB_TX_NUM - 1)
+#define AT91_NEXT_MASK		((AT91_MB_TX_NUM - 1) | AT91_NEXT_PRIO_MASK)
+
+/* Common registers */
+enum at91_reg {
+	AT91_MR		= 0x000,
+	AT91_IER	= 0x004,
+	AT91_IDR	= 0x008,
+	AT91_IMR	= 0x00C,
+	AT91_SR		= 0x010,
+	AT91_BR		= 0x014,
+	AT91_TIM	= 0x018,
+	AT91_TIMESTP	= 0x01C,
+	AT91_ECR	= 0x020,
+	AT91_TCR	= 0x024,
+	AT91_ACR	= 0x028,
+};
+
+/* Mailbox registers (0 <= i <= 15) */
+#define AT91_MMR(i)		(enum at91_reg)(0x200 + ((i) * 0x20))
+#define AT91_MAM(i)		(enum at91_reg)(0x204 + ((i) * 0x20))
+#define AT91_MID(i)		(enum at91_reg)(0x208 + ((i) * 0x20))
+#define AT91_MFID(i)		(enum at91_reg)(0x20C + ((i) * 0x20))
+#define AT91_MSR(i)		(enum at91_reg)(0x210 + ((i) * 0x20))
+#define AT91_MDL(i)		(enum at91_reg)(0x214 + ((i) * 0x20))
+#define AT91_MDH(i)		(enum at91_reg)(0x218 + ((i) * 0x20))
+#define AT91_MCR(i)		(enum at91_reg)(0x21C + ((i) * 0x20))
+
+/* Register bits */
+#define AT91_MR_CANEN		BIT(0)
+#define AT91_MR_LPM		BIT(1)
+#define AT91_MR_ABM		BIT(2)
+#define AT91_MR_OVL		BIT(3)
+#define AT91_MR_TEOF		BIT(4)
+#define AT91_MR_TTM		BIT(5)
+#define AT91_MR_TIMFRZ		BIT(6)
+#define AT91_MR_DRPT		BIT(7)
+
+#define AT91_SR_RBSY		BIT(29)
+
+#define AT91_MMR_PRIO_SHIFT	(16)
+
+#define AT91_MID_MIDE		BIT(29)
+
+#define AT91_MSR_MRTR		BIT(20)
+#define AT91_MSR_MABT		BIT(22)
+#define AT91_MSR_MRDY		BIT(23)
+#define AT91_MSR_MMI		BIT(24)
+
+#define AT91_MCR_MRTR		BIT(20)
+#define AT91_MCR_MTCR		BIT(23)
+
+/* Mailbox Modes */
+enum at91_mb_mode {
+	AT91_MB_MODE_DISABLED	= 0,
+	AT91_MB_MODE_RX		= 1,
+	AT91_MB_MODE_RX_OVRWR	= 2,
+	AT91_MB_MODE_TX		= 3,
+	AT91_MB_MODE_CONSUMER	= 4,
+	AT91_MB_MODE_PRODUCER	= 5,
+};
+
+/* Interrupt mask bits */
+#define AT91_IRQ_MB_RX		((1 << (AT91_MB_RX_LAST + 1)) \
+				 - (1 << AT91_MB_RX_FIRST))
+#define AT91_IRQ_MB_TX		((1 << (AT91_MB_TX_LAST + 1)) \
+				 - (1 << AT91_MB_TX_FIRST))
+#define AT91_IRQ_MB_ALL		(AT91_IRQ_MB_RX | AT91_IRQ_MB_TX)
+
+#define AT91_IRQ_ERRA		(1 << 16)
+#define AT91_IRQ_WARN		(1 << 17)
+#define AT91_IRQ_ERRP		(1 << 18)
+#define AT91_IRQ_BOFF		(1 << 19)
+#define AT91_IRQ_SLEEP		(1 << 20)
+#define AT91_IRQ_WAKEUP		(1 << 21)
+#define AT91_IRQ_TOVF		(1 << 22)
+#define AT91_IRQ_TSTP		(1 << 23)
+#define AT91_IRQ_CERR		(1 << 24)
+#define AT91_IRQ_SERR		(1 << 25)
+#define AT91_IRQ_AERR		(1 << 26)
+#define AT91_IRQ_FERR		(1 << 27)
+#define AT91_IRQ_BERR		(1 << 28)
+
+#define AT91_IRQ_ERR_ALL	(0x1fff0000)
+#define AT91_IRQ_ERR_FRAME	(AT91_IRQ_CERR | AT91_IRQ_SERR | \
+				 AT91_IRQ_AERR | AT91_IRQ_FERR | AT91_IRQ_BERR)
+#define AT91_IRQ_ERR_LINE	(AT91_IRQ_ERRA | AT91_IRQ_WARN | \
+				 AT91_IRQ_ERRP | AT91_IRQ_BOFF)
+
+#define AT91_IRQ_ALL		(0x1fffffff)
+
+struct at91_priv {
+	struct can_priv		can;	   /* must be the first member! */
+	struct net_device	*dev;
+	struct napi_struct	napi;
+
+	void __iomem		*reg_base;
+
+	u32			reg_sr;
+	unsigned int		tx_next;
+	unsigned int		tx_echo;
+	unsigned int		rx_next;
+
+	struct clk		*clk;
+	struct at91_can_data	*pdata;
+};
+
+static struct can_bittiming_const at91_bittiming_const = {
+	.tseg1_min	= 4,
+	.tseg1_max	= 16,
+	.tseg2_min	= 2,
+	.tseg2_max	= 8,
+	.sjw_max	= 4,
+	.brp_min 	= 2,
+	.brp_max	= 128,
+	.brp_inc	= 1,
+};
+
+static inline int get_tx_next_mb(const struct at91_priv *priv)
+{
+	return (priv->tx_next & AT91_NEXT_MB_MASK) + AT91_MB_TX_FIRST;
+}
+
+static inline int get_tx_next_prio(const struct at91_priv *priv)
+{
+	return (priv->tx_next >> AT91_NEXT_PRIO_SHIFT) & 0xf;
+}
+
+static inline int get_tx_echo_mb(const struct at91_priv *priv)
+{
+	return (priv->tx_echo & AT91_NEXT_MB_MASK) + AT91_MB_TX_FIRST;
+}
+
+static inline u32 at91_read(const struct at91_priv *priv, enum at91_reg reg)
+{
+	return readl(priv->reg_base + reg);
+}
+
+static inline void at91_write(const struct at91_priv *priv, enum at91_reg reg,
+		u32 value)
+{
+	writel(value, priv->reg_base + reg);
+}
+
+static inline void set_mb_mode_prio(const struct at91_priv *priv,
+		unsigned int mb, enum at91_mb_mode mode, int prio)
+{
+	at91_write(priv, AT91_MMR(mb), (mode << 24) | (prio << 16));
+}
+
+static inline void set_mb_mode(const struct at91_priv *priv, unsigned int mb,
+		enum at91_mb_mode mode)
+{
+	set_mb_mode_prio(priv, mb, mode, 0);
+}
+
+static struct sk_buff *alloc_can_skb(struct net_device *dev,
+		struct can_frame **cf)
+{
+	struct sk_buff *skb;
+
+	skb = netdev_alloc_skb(dev, sizeof(struct can_frame));
+	if (unlikely(!skb))
+		return NULL;
+
+	skb->protocol = htons(ETH_P_CAN);
+	skb->ip_summed = CHECKSUM_UNNECESSARY;
+	*cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
+
+	return skb;
+}
+
+static struct sk_buff *alloc_can_err_skb(struct net_device *dev,
+		struct can_frame **cf)
+{
+	struct sk_buff *skb;
+
+	skb = alloc_can_skb(dev, cf);
+	if (unlikely(!skb))
+		return NULL;
+
+	memset(*cf, 0, sizeof(struct can_frame));
+	(*cf)->can_id = CAN_ERR_FLAG;
+	(*cf)->can_dlc = CAN_ERR_DLC;
+
+	return skb;
+}
+
+/*
+ * Swtich transceiver on or off
+ */
+static void at91_transceiver_switch(const struct at91_priv *priv, int on)
+{
+	if (priv->pdata && priv->pdata->transceiver_switch)
+		priv->pdata->transceiver_switch(on);
+}
+
+static void at91_setup_mailboxes(struct net_device *dev)
+{
+	struct at91_priv *priv = netdev_priv(dev);
+	unsigned int i;
+
+	/*
+	 * The first 12 mailboxes are used as a reception FIFO. The
+	 * last mailbox is configured with overwrite option. The
+	 * overwrite flag indicates a FIFO overflow.
+	 */
+	for (i = AT91_MB_RX_FIRST; i < AT91_MB_RX_LAST; i++)
+		set_mb_mode(priv, i, AT91_MB_MODE_RX);
+	set_mb_mode(priv, AT91_MB_RX_LAST, AT91_MB_MODE_RX_OVRWR);
+
+	/* The last 4 mailboxes are used for transmitting. */
+	for (i = AT91_MB_TX_FIRST; i <= AT91_MB_TX_LAST; i++)
+		set_mb_mode_prio(priv, i, AT91_MB_MODE_TX, 0);
+
+	/* Reset tx and rx helper pointers */
+	priv->tx_next = priv->tx_echo = priv->rx_next = 0;
+}
+
+static int at91_set_bittiming(struct net_device *dev)
+{
+	const struct at91_priv *priv = netdev_priv(dev);
+	const struct can_bittiming *bt = &priv->can.bittiming;
+	u32 reg_br;
+
+	reg_br = ((priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) << 24) |
+		((bt->brp - 1) << 16) |	((bt->sjw - 1) << 12) |
+		((bt->prop_seg - 1) << 8) | ((bt->phase_seg1 - 1) << 4) |
+		((bt->phase_seg2 - 1) << 0);
+
+	dev_info(dev->dev.parent, "writing AT91_BR: 0x%08x\n", reg_br);
+
+	at91_write(priv, AT91_BR, reg_br);
+
+	return 0;
+}
+
+static void at91_chip_start(struct net_device *dev)
+{
+	struct at91_priv *priv = netdev_priv(dev);
+	u32 reg_mr, reg_ier;
+
+	/* disable interrupts */
+	at91_write(priv, AT91_IDR, AT91_IRQ_ALL);
+
+	/* disable chip */
+	reg_mr = at91_read(priv, AT91_MR);
+	at91_write(priv, AT91_MR, reg_mr & ~AT91_MR_CANEN);
+
+	at91_setup_mailboxes(dev);
+	at91_transceiver_switch(priv, 1);
+
+	/* enable chip */
+	at91_write(priv, AT91_MR, AT91_MR_CANEN);
+
+	priv->can.state = CAN_STATE_ERROR_ACTIVE;
+
+	/* Enable interrupts */
+	reg_ier = AT91_IRQ_MB_RX | AT91_IRQ_ERRP | AT91_IRQ_ERR_FRAME;
+	at91_write(priv, AT91_IDR, AT91_IRQ_ALL);
+	at91_write(priv, AT91_IER, reg_ier);
+}
+
+static void at91_chip_stop(struct net_device *dev, enum can_state state)
+{
+	struct at91_priv *priv = netdev_priv(dev);
+	u32 reg_mr;
+
+	/* disable interrupts */
+	at91_write(priv, AT91_IDR, AT91_IRQ_ALL);
+
+	reg_mr = at91_read(priv, AT91_MR);
+	at91_write(priv, AT91_MR, reg_mr & ~AT91_MR_CANEN);
+
+	at91_transceiver_switch(priv, 0);
+	priv->can.state = state;
+}
+
+/*
+ * theory of operation:
+ *
+ * According to the datasheet priority 0 is the highest priority, 15
+ * is the lowest. If two mailboxes have the same priority level the
+ * message of the mailbox with the lowest number is sent first.
+ *
+ * We use the first TX mailbox (AT91_MB_TX_FIRST) with prio 0, then
+ * the next mailbox with prio 0, and so on, until all mailboxes are
+ * used. Then we start from the beginning with mailbox
+ * AT91_MB_TX_FIRST, but with prio 1, mailbox AT91_MB_TX_FIRST + 1
+ * prio 1. When we reach the last mailbox with prio 15, we have to
+ * stop sending, waiting for all messages to be delivered, then start
+ * again with mailbox AT91_MB_TX_FIRST prio 0.
+ *
+ * We use the priv->tx_next as counter for the next transmission
+ * mailbox, but without the offset AT91_MB_TX_FIRST. The lower bits
+ * encode the mailbox number, the upper 4 bits the mailbox priority:
+ *
+ * priv->tx_next = (prio << AT91_NEXT_PRIO_SHIFT) ||
+ *                 (mb - AT91_MB_TX_FIRST);
+ *
+ */
+static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct at91_priv *priv = netdev_priv(dev);
+	struct net_device_stats *stats = &dev->stats;
+	struct can_frame *cf = (struct can_frame *)skb->data;
+	unsigned int mb, prio;
+	u32 reg_mid, reg_mcr;
+
+	mb = get_tx_next_mb(priv);
+	prio = get_tx_next_prio(priv);
+
+	if (unlikely(!(at91_read(priv, AT91_MSR(mb)) & AT91_MSR_MRDY))) {
+		netif_stop_queue(dev);
+
+		dev_err(dev->dev.parent,
+			"BUG! TX buffer full when queue awake!\n");
+		return NETDEV_TX_BUSY;
+	}
+
+	if (cf->can_id & CAN_EFF_FLAG)
+		reg_mid = (cf->can_id & CAN_EFF_MASK) | AT91_MID_MIDE;
+	else
+		reg_mid = (cf->can_id & CAN_SFF_MASK) << 18;
+
+	reg_mcr = ((cf->can_id & CAN_RTR_FLAG) ? AT91_MCR_MRTR : 0) |
+		(cf->can_dlc << 16) | AT91_MCR_MTCR;
+
+	/* disable MB while writing ID (see datasheet) */
+	set_mb_mode(priv, mb, AT91_MB_MODE_DISABLED);
+	at91_write(priv, AT91_MID(mb), reg_mid);
+	set_mb_mode_prio(priv, mb, AT91_MB_MODE_TX, prio);
+
+	at91_write(priv, AT91_MDL(mb), *(u32 *)(cf->data + 0));
+	at91_write(priv, AT91_MDH(mb), *(u32 *)(cf->data + 4));
+
+	/* This triggers transmission */
+	at91_write(priv, AT91_MCR(mb), reg_mcr);
+
+	stats->tx_bytes += cf->can_dlc;
+	dev->trans_start = jiffies;
+
+	/* _NOTE_: substract AT91_MB_TX_FIRST offset from mb! */
+	can_put_echo_skb(skb, dev, mb - AT91_MB_TX_FIRST);
+
+	/*
+	 * we have to stop the queue and deliver all messages in case
+	 * of a prio+mb counter wrap around. This is the case if
+	 * tx_next buffer prio and mailbox equals 0.
+	 *
+	 * also stop the queue if next buffer is still in use
+	 * (== not ready)
+	 */
+	priv->tx_next++;
+	if (!(at91_read(priv, AT91_MSR(get_tx_next_mb(priv))) &
+	      AT91_MSR_MRDY) ||
+	    (priv->tx_next & AT91_NEXT_MASK) == 0)
+		netif_stop_queue(dev);
+
+	/* Enable interrupt for this mailbox */
+	at91_write(priv, AT91_IER, 1 << mb);
+
+	return NETDEV_TX_OK;
+}
+
+/**
+ * at91_activate_rx_low - activate lower rx mailboxes
+ * @priv: a91 context
+ *
+ * Reenables the lower mailboxes for reception of new CAN messages
+ */
+static inline void at91_activate_rx_low(const struct at91_priv *priv)
+{
+	u32 mask = AT91_MB_RX_LOW_MASK;
+	at91_write(priv, AT91_TCR, mask);
+}
+
+/**
+ * at91_activate_rx_mb - reactive single rx mailbox
+ * @priv: a91 context
+ * @mb: mailbox to reactivate
+ *
+ * Reenables given mailbox for reception of new CAN messages
+ */
+static inline void at91_activate_rx_mb(const struct at91_priv *priv,
+		unsigned int mb)
+{
+	u32 mask = 1 << mb;
+	at91_write(priv, AT91_TCR, mask);
+}
+
+/**
+ * at91_rx_overflow_err - send error frame due to rx overflow
+ * @dev: net device
+ */
+static void at91_rx_overflow_err(struct net_device *dev)
+{
+	struct net_device_stats *stats = &dev->stats;
+	struct sk_buff *skb;
+	struct can_frame *cf;
+
+	dev_dbg(dev->dev.parent, "RX buffer overflow\n");
+	stats->rx_over_errors++;
+	stats->rx_errors++;
+
+	skb = alloc_can_err_skb(dev, &cf);
+	if (unlikely(!skb))
+		return;
+
+	cf->can_id |= CAN_ERR_CRTL;
+	cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
+	netif_receive_skb(skb);
+
+	stats->rx_packets++;
+	stats->rx_bytes += cf->can_dlc;
+}
+
+/**
+ * at91_read_mb - read CAN msg from mailbox (lowlevel impl)
+ * @dev: net device
+ * @mb: mailbox number to read from
+ * @cf: can frame where to store message
+ *
+ * Reads a CAN message from the given mailbox and stores data into
+ * given can frame. "mb" and "cf" must be valid.
+ */
+static void at91_read_mb(struct net_device *dev, unsigned int mb,
+		struct can_frame *cf)
+{
+	const struct at91_priv *priv = netdev_priv(dev);
+	u32 reg_msr, reg_mid;
+
+	reg_mid = at91_read(priv, AT91_MID(mb));
+	if (reg_mid & AT91_MID_MIDE)
+		cf->can_id = ((reg_mid >> 0) & CAN_EFF_MASK) | CAN_EFF_FLAG;
+	else
+		cf->can_id = (reg_mid >> 18) & CAN_SFF_MASK;
+
+	reg_msr = at91_read(priv, AT91_MSR(mb));
+	if (reg_msr & AT91_MSR_MRTR)
+		cf->can_id |= CAN_RTR_FLAG;
+	cf->can_dlc = min_t(__u8, (reg_msr >> 16) & 0xf, 8);
+
+	*(u32 *)(cf->data + 0) = at91_read(priv, AT91_MDL(mb));
+	*(u32 *)(cf->data + 4) = at91_read(priv, AT91_MDH(mb));
+
+	if (unlikely(mb == AT91_MB_RX_LAST && reg_msr & AT91_MSR_MMI))
+		at91_rx_overflow_err(dev);
+}
+
+/**
+ * at91_read_msg - read CAN message from mailbox
+ * @dev: net device
+ * @mb: mail box to read from
+ *
+ * Reads a CAN message from given mailbox, and put into linux network
+ * RX queue, does all housekeeping chores (stats, ...)
+ */
+static void at91_read_msg(struct net_device *dev, unsigned int mb)
+{
+	struct net_device_stats *stats = &dev->stats;
+	struct can_frame *cf;
+	struct sk_buff *skb;
+
+	skb = alloc_can_skb(dev, &cf);
+	if (unlikely(!skb)) {
+		stats->rx_dropped++;
+		return;
+	}
+
+	at91_read_mb(dev, mb, cf);
+	netif_receive_skb(skb);
+
+	stats->rx_packets++;
+	stats->rx_bytes += cf->can_dlc;
+}
+
+/**
+ * at91_poll_rx - read multiple CAN messages from mailboxes
+ * @dev: net device
+ * @quota: max number of pkgs we're allowed to receive
+ *
+ * Theory of Operation:
+ *
+ * 12 of the 16 mailboxes on the chip are reserved for RX. we split
+ * them into 2 groups. The lower group holds 8 and upper 4 mailboxes.
+ *
+ * Like it or not, but the chip always saves a received CAN message
+ * into the first free mailbox it finds (starting with the
+ * lowest). This makes it very difficult to read the messages in the
+ * right order from the chip. This is how we work around that problem:
+ *
+ * The first message goes into mb nr. 0 and issues an interrupt. All
+ * rx ints are disabled in the interrupt handler and a napi poll is
+ * scheduled. We read the mailbox, but do _not_ reenable the mb (to
+ * receive another message).
+ *
+ *    lower mbxs      upper
+ *   ______^______    __^__
+ *  /             \  /     \
+ * +-+-+-+-+-+-+-+-++-+-+-+-+
+ * |x|x|x|x|x|x|x|x|| | | | |
+ * +-+-+-+-+-+-+-+-++-+-+-+-+
+ *  0 0 0 0 0 0  0 0 0 0 1 1  \ mail
+ *  0 1 2 3 4 5  6 7 8 9 0 1  / box
+ *
+ * The variable priv->rx_next points to the next mailbox to read a
+ * message from. As long we're in the lower mailboxes we just read the
+ * mailbox but not reenable it.
+ *
+ * With completion of the last of the lower mailboxes, we reenable the
+ * whole first group, but continue to look for filled mailboxes in the
+ * upper mailboxes. Imagine the second group like overflow mailboxes,
+ * which takes CAN messages if the lower goup is full. While in the
+ * upper group we reenable the mailbox right after reading it. Giving
+ * the chip more room to store messages.
+ *
+ * After finishing we look again in the lower group if we've still
+ * quota.
+ *
+ */
+static int at91_poll_rx(struct net_device *dev, int quota)
+{
+	struct at91_priv *priv = netdev_priv(dev);
+	u32 reg_sr = at91_read(priv, AT91_SR);
+	const unsigned long *addr = (unsigned long *)&reg_sr;
+	unsigned int mb;
+	int received = 0;
+
+	if (priv->rx_next > AT91_MB_RX_LOW_LAST &&
+	    reg_sr & AT91_MB_RX_LOW_MASK)
+		dev_info(dev->dev.parent,
+			 "order of incoming frames cannot be guaranteed\n");
+
+ again:
+	for (mb = find_next_bit(addr, AT91_MB_RX_NUM, priv->rx_next);
+	     mb < AT91_MB_RX_NUM && quota > 0;
+	     reg_sr = at91_read(priv, AT91_SR),
+	     mb = find_next_bit(addr, AT91_MB_RX_NUM, ++priv->rx_next)) {
+		at91_read_msg(dev, mb);
+
+		/* reactivate mailboxes */
+		if (mb == AT91_MB_RX_LOW_LAST)
+			/* all lower mailboxed, if just finished it */
+			at91_activate_rx_low(priv);
+		else if (mb > AT91_MB_RX_LOW_LAST)
+			/* only the mailbox we read */
+			at91_activate_rx_mb(priv, mb);
+
+		received++;
+		quota--;
+	}
+
+	/* upper group completed, look again in lower */
+	if (priv->rx_next > AT91_MB_RX_LOW_LAST &&
+	    quota > 0 && mb >= AT91_MB_RX_NUM) {
+		priv->rx_next = 0;
+		goto again;
+	}
+
+	return received;
+}
+
+static void at91_poll_err_frame(struct net_device *dev,
+		struct can_frame *cf, u32 reg_sr)
+{
+	struct at91_priv *priv = netdev_priv(dev);
+
+	/* CRC error */
+	if (reg_sr & AT91_IRQ_CERR) {
+		dev_dbg(dev->dev.parent, "CERR irq\n");
+		dev->stats.rx_errors++;
+		priv->can.can_stats.bus_error++;
+		cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+	}
+
+	/* Stuffing Error */
+	if (reg_sr & AT91_IRQ_SERR) {
+		dev_dbg(dev->dev.parent, "SERR irq\n");
+		dev->stats.rx_errors++;
+		priv->can.can_stats.bus_error++;
+		cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+		cf->data[2] |= CAN_ERR_PROT_STUFF;
+	}
+
+	/* Acknowledgement Error */
+	if (reg_sr & AT91_IRQ_AERR) {
+		dev_dbg(dev->dev.parent, "AERR irq\n");
+		dev->stats.tx_errors++;
+		cf->can_id |= CAN_ERR_ACK;
+	}
+
+	/* Form error */
+	if (reg_sr & AT91_IRQ_FERR) {
+		dev_dbg(dev->dev.parent, "FERR irq\n");
+		dev->stats.rx_errors++;
+		priv->can.can_stats.bus_error++;
+		cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+		cf->data[2] |= CAN_ERR_PROT_FORM;
+	}
+
+	/* Bit Error */
+	if (reg_sr & AT91_IRQ_BERR) {
+		dev_dbg(dev->dev.parent, "BERR irq\n");
+		dev->stats.tx_errors++;
+		priv->can.can_stats.bus_error++;
+		cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+		cf->data[2] |= CAN_ERR_PROT_BIT;
+	}
+}
+
+static int at91_poll_err(struct net_device *dev, int quota, u32 reg_sr)
+{
+	struct sk_buff *skb;
+	struct can_frame *cf;
+
+	if (quota == 0)
+		return 0;
+
+	skb = alloc_can_err_skb(dev, &cf);
+	if (unlikely(!skb))
+		return 0;
+
+	at91_poll_err_frame(dev, cf, reg_sr);
+	netif_receive_skb(skb);
+
+	dev->last_rx = jiffies;
+	dev->stats.rx_packets++;
+	dev->stats.rx_bytes += cf->can_dlc;
+
+	return 1;
+}
+
+static int at91_poll(struct napi_struct *napi, int quota)
+{
+	struct net_device *dev = napi->dev;
+	const struct at91_priv *priv = netdev_priv(dev);
+	u32 reg_sr = at91_read(priv, AT91_SR);
+	int work_done = 0;
+
+	if (reg_sr & AT91_IRQ_MB_RX)
+		work_done += at91_poll_rx(dev, quota - work_done);
+
+	/*
+	 * The error bits are clear on read,
+	 * so use saved value from irq handler.
+	 */
+	reg_sr |= priv->reg_sr;
+	if (reg_sr & AT91_IRQ_ERR_FRAME)
+		work_done += at91_poll_err(dev, quota - work_done, reg_sr);
+
+	if (work_done < quota) {
+		/* enable IRQs for frame errors and all mailboxes >= rx_next */
+		u32 reg_ier = AT91_IRQ_ERR_FRAME;
+		reg_ier |= AT91_IRQ_MB_RX & ~AT91_MB_RX_MASK(priv->rx_next);
+
+		napi_complete(napi);
+		at91_write(priv, AT91_IER, reg_ier);
+	}
+
+	return work_done;
+}
+
+/*
+ * theory of operation:
+ *
+ * priv->tx_echo holds the number of the oldest can_frame put for
+ * transmission into the hardware, but not yet ACKed by the CAN tx
+ * complete IRQ.
+ *
+ * We iterate from priv->tx_echo to priv->tx_next and check if the
+ * packet has been transmitted, echo it back to the CAN framework. If
+ * we discover a not yet transmitted package, stop looking for more.
+ *
+ */
+static void at91_irq_tx(struct net_device *dev, u32 reg_sr)
+{
+	struct at91_priv *priv = netdev_priv(dev);
+	u32 reg_msr;
+	unsigned int mb;
+
+	/* masking of reg_sr not needed, already done by at91_irq */
+
+	for (/* nix */; (priv->tx_next - priv->tx_echo) > 0; priv->tx_echo++) {
+		mb = get_tx_echo_mb(priv);
+
+		/* no event in mailbox? */
+		if (!(reg_sr & (1 << mb)))
+			break;
+
+		/* Disable irq for this TX mailbox */
+		at91_write(priv, AT91_IDR, 1 << mb);
+
+		/*
+		 * only echo if mailbox signals us a transfer
+		 * complete (MSR_MRDY). Otherwise it's a tansfer
+		 * abort. "can_bus_off()" takes care about the skbs
+		 * parked in the echo queue.
+		 */
+		reg_msr = at91_read(priv, AT91_MSR(mb));
+		if (likely(reg_msr & AT91_MSR_MRDY &&
+			   ~reg_msr & AT91_MSR_MABT)) {
+			/* _NOTE_: substract AT91_MB_TX_FIRST offset from mb! */
+			can_get_echo_skb(dev, mb - AT91_MB_TX_FIRST);
+			dev->stats.tx_packets++;
+		}
+	}
+
+	/*
+	 * restart queue if we don't have a wrap around but restart if
+	 * we get a TX int for the last can frame directly before a
+	 * wrap around.
+	 */
+	if ((priv->tx_next & AT91_NEXT_MASK) != 0 ||
+	    (priv->tx_echo & AT91_NEXT_MASK) == 0)
+		netif_wake_queue(dev);
+}
+
+static void at91_irq_err_state(struct net_device *dev,
+		struct can_frame *cf, enum can_state new_state)
+{
+	struct at91_priv *priv = netdev_priv(dev);
+	u32 reg_idr, reg_ier, reg_ecr;
+	u8 tec, rec;
+
+	reg_ecr = at91_read(priv, AT91_ECR);
+	rec = reg_ecr & 0xff;
+	tec = reg_ecr >> 16;
+
+	switch (priv->can.state) {
+	case CAN_STATE_ERROR_ACTIVE:
+		/*
+		 * from: ERROR_ACTIVE
+		 * to  : ERROR_WARNING, ERROR_PASSIVE, BUS_OFF
+		 * =>  : there was a warning int
+		 */
+		if (new_state >= CAN_STATE_ERROR_WARNING &&
+		    new_state <= CAN_STATE_BUS_OFF) {
+			dev_dbg(dev->dev.parent, "Error Warning IRQ\n");
+			priv->can.can_stats.error_warning++;
+
+			cf->can_id |= CAN_ERR_CRTL;
+			cf->data[1] = (tec > rec) ?
+				CAN_ERR_CRTL_TX_WARNING :
+				CAN_ERR_CRTL_RX_WARNING;
+		}
+	case CAN_STATE_ERROR_WARNING:	/* fallthrough */
+		/*
+		 * from: ERROR_ACTIVE, ERROR_WARNING
+		 * to  : ERROR_PASSIVE, BUS_OFF
+		 * =>  : error passive int
+		 */
+		if (new_state >= CAN_STATE_ERROR_PASSIVE &&
+		    new_state <= CAN_STATE_BUS_OFF) {
+			dev_dbg(dev->dev.parent, "Error Passive IRQ\n");
+			priv->can.can_stats.error_passive++;
+
+			cf->can_id |= CAN_ERR_CRTL;
+			cf->data[1] = (tec > rec) ?
+				CAN_ERR_CRTL_TX_PASSIVE :
+				CAN_ERR_CRTL_RX_PASSIVE;
+		}
+		break;
+	case CAN_STATE_BUS_OFF:
+		/*
+		 * from: BUS_OFF
+		 * to  : ERROR_ACTIVE, ERROR_WARNING, ERROR_PASSIVE
+		 */
+		if (new_state <= CAN_STATE_ERROR_PASSIVE) {
+			cf->can_id |= CAN_ERR_RESTARTED;
+
+			dev_dbg(dev->dev.parent, "restarted\n");
+			priv->can.can_stats.restarts++;
+
+			netif_carrier_on(dev);
+			netif_wake_queue(dev);
+		}
+		break;
+	default:
+		break;
+	}
+
+
+	/* process state changes depending on the new state */
+	switch (new_state) {
+	case CAN_STATE_ERROR_ACTIVE:
+		/*
+		 * actually we want to enable AT91_IRQ_WARN here, but
+		 * it screws up the system under certain
+		 * circumstances. so just enable AT91_IRQ_ERRP, thus
+		 * the "fallthrough"
+		 */
+		dev_dbg(dev->dev.parent, "Error Active\n");
+		cf->can_id |= CAN_ERR_PROT;
+		cf->data[2] = CAN_ERR_PROT_ACTIVE;
+	case CAN_STATE_ERROR_WARNING:	/* fallthrough */
+		reg_idr = AT91_IRQ_ERRA | AT91_IRQ_WARN | AT91_IRQ_BOFF;
+		reg_ier = AT91_IRQ_ERRP;
+		break;
+	case CAN_STATE_ERROR_PASSIVE:
+		reg_idr = AT91_IRQ_ERRA | AT91_IRQ_WARN | AT91_IRQ_ERRP;
+		reg_ier = AT91_IRQ_BOFF;
+		break;
+	case CAN_STATE_BUS_OFF:
+		reg_idr = AT91_IRQ_ERRA | AT91_IRQ_ERRP |
+			AT91_IRQ_WARN | AT91_IRQ_BOFF;
+		reg_ier = 0;
+
+		cf->can_id |= CAN_ERR_BUSOFF;
+
+		dev_dbg(dev->dev.parent, "bus-off\n");
+		netif_carrier_off(dev);
+		priv->can.can_stats.bus_off++;
+
+		/* turn off chip, if restart is disabled */
+		if (!priv->can.restart_ms) {
+			at91_chip_stop(dev, CAN_STATE_BUS_OFF);
+			return;
+		}
+		break;
+	default:
+		break;
+	}
+
+	at91_write(priv, AT91_IDR, reg_idr);
+	at91_write(priv, AT91_IER, reg_ier);
+}
+
+static void at91_irq_err(struct net_device *dev)
+{
+	struct at91_priv *priv = netdev_priv(dev);
+	struct sk_buff *skb;
+	struct can_frame *cf;
+	enum can_state new_state;
+	u32 reg_sr;
+
+	reg_sr = at91_read(priv, AT91_SR);
+
+	/* we need to look at the unmasked reg_sr */
+	if (unlikely(reg_sr & AT91_IRQ_BOFF))
+		new_state = CAN_STATE_BUS_OFF;
+	else if (unlikely(reg_sr & AT91_IRQ_ERRP))
+		new_state = CAN_STATE_ERROR_PASSIVE;
+	else if (unlikely(reg_sr & AT91_IRQ_WARN))
+		new_state = CAN_STATE_ERROR_WARNING;
+	else if (likely(reg_sr & AT91_IRQ_ERRA))
+		new_state = CAN_STATE_ERROR_ACTIVE;
+	else {
+		dev_err(dev->dev.parent, "BUG! hardware in undefined state\n");
+		return;
+	}
+
+	/* state hasn't changed */
+	if (likely(new_state == priv->can.state))
+		return;
+
+	skb = alloc_can_err_skb(dev, &cf);
+	if (unlikely(!skb))
+		return;
+
+	at91_irq_err_state(dev, cf, new_state);
+	netif_rx(skb);
+
+	dev->last_rx = jiffies;
+	dev->stats.rx_packets++;
+	dev->stats.rx_bytes += cf->can_dlc;
+
+	priv->can.state = new_state;
+}
+
+/*
+ * interrupt handler
+ */
+static irqreturn_t at91_irq(int irq, void *dev_id)
+{
+	struct net_device *dev = dev_id;
+	struct at91_priv *priv = netdev_priv(dev);
+	irqreturn_t handled = IRQ_NONE;
+	u32 reg_sr, reg_imr;
+
+	reg_sr = at91_read(priv, AT91_SR);
+	reg_imr = at91_read(priv, AT91_IMR);
+
+	/* Ignore masked interrupts */
+	reg_sr &= reg_imr;
+	if (!reg_sr)
+		goto exit;
+
+	handled = IRQ_HANDLED;
+
+	/* Receive or error interrupt? -> napi */
+	if (reg_sr & (AT91_IRQ_MB_RX | AT91_IRQ_ERR_FRAME)) {
+		/*
+		 * The error bits are clear on read,
+		 * save for later use.
+		 */
+		priv->reg_sr = reg_sr;
+		at91_write(priv, AT91_IDR,
+			   AT91_IRQ_MB_RX | AT91_IRQ_ERR_FRAME);
+		napi_schedule(&priv->napi);
+	}
+
+	/* Transmission complete interrupt */
+	if (reg_sr & AT91_IRQ_MB_TX)
+		at91_irq_tx(dev, reg_sr);
+
+	at91_irq_err(dev);
+
+ exit:
+	return handled;
+}
+
+static int at91_open(struct net_device *dev)
+{
+	struct at91_priv *priv = netdev_priv(dev);
+	int err;
+
+	clk_enable(priv->clk);
+
+	/* check or determine and set bittime */
+	err = open_candev(dev);
+	if (err)
+		goto out;
+
+	/* register interrupt handler */
+	if (request_irq(dev->irq, at91_irq, IRQF_SHARED,
+			dev->name, dev)) {
+		err = -EAGAIN;
+		goto out_close;
+	}
+
+	/* start chip and queuing */
+	at91_chip_start(dev);
+	napi_enable(&priv->napi);
+	netif_start_queue(dev);
+
+	return 0;
+
+ out_close:
+	close_candev(dev);
+ out:
+	clk_disable(priv->clk);
+
+	return err;
+}
+
+/*
+ * stop CAN bus activity
+ */
+static int at91_close(struct net_device *dev)
+{
+	struct at91_priv *priv = netdev_priv(dev);
+
+	netif_stop_queue(dev);
+	napi_disable(&priv->napi);
+	at91_chip_stop(dev, CAN_STATE_STOPPED);
+
+	free_irq(dev->irq, dev);
+	clk_disable(priv->clk);
+
+	close_candev(dev);
+
+	return 0;
+}
+
+static int at91_set_mode(struct net_device *dev, enum can_mode mode)
+{
+	switch (mode) {
+	case CAN_MODE_START:
+		at91_chip_start(dev);
+		netif_wake_queue(dev);
+		break;
+
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+static const struct net_device_ops at91_netdev_ops = {
+	.ndo_open	= at91_open,
+	.ndo_stop	= at91_close,
+	.ndo_start_xmit	= at91_start_xmit,
+};
+
+static int __init at91_can_probe(struct platform_device *pdev)
+{
+	struct net_device *dev;
+	struct at91_priv *priv;
+	struct resource *res;
+	struct clk *clk;
+	void __iomem *addr;
+	int err, irq;
+
+	clk = clk_get(&pdev->dev, "can_clk");
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "no clock defined\n");
+		err = -ENODEV;
+		goto exit;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	irq = platform_get_irq(pdev, 0);
+	if (!res || !irq) {
+		err = -ENODEV;
+		goto exit_put;
+	}
+
+	if (!request_mem_region(res->start,
+				resource_size(res),
+				pdev->name)) {
+		err = -EBUSY;
+		goto exit_put;
+	}
+
+	addr = ioremap_nocache(res->start, resource_size(res));
+	if (!addr) {
+		err = -ENOMEM;
+		goto exit_release;
+	}
+
+	dev = alloc_candev(sizeof(struct at91_priv));
+	if (!dev) {
+		err = -ENOMEM;
+		goto exit_iounmap;
+	}
+
+	dev->netdev_ops	= &at91_netdev_ops;
+	dev->irq = irq;
+	dev->flags |= IFF_ECHO;
+
+	priv = netdev_priv(dev);
+	priv->can.clock.freq = clk_get_rate(clk);
+	priv->can.bittiming_const = &at91_bittiming_const;
+	priv->can.do_set_bittiming = at91_set_bittiming;
+	priv->can.do_set_mode = at91_set_mode;
+	priv->reg_base = addr;
+	priv->dev = dev;
+	priv->clk = clk;
+	priv->pdata = pdev->dev.platform_data;
+
+	netif_napi_add(dev, &priv->napi, at91_poll, AT91_NAPI_WEIGHT);
+
+	dev_set_drvdata(&pdev->dev, dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
+
+	err = register_candev(dev);
+	if (err) {
+		dev_err(&pdev->dev, "registering netdev failed\n");
+		goto exit_free;
+	}
+
+	dev_info(&pdev->dev, "device registered (reg_base=%p, irq=%d)\n",
+		 priv->reg_base, dev->irq);
+
+	return 0;
+
+ exit_free:
+	free_netdev(dev);
+ exit_iounmap:
+	iounmap(addr);
+ exit_release:
+	release_mem_region(res->start, resource_size(res));
+ exit_put:
+	clk_put(clk);
+ exit:
+	return err;
+}
+
+static int __devexit at91_can_remove(struct platform_device *pdev)
+{
+	struct net_device *dev = platform_get_drvdata(pdev);
+	struct at91_priv *priv = netdev_priv(dev);
+	struct resource *res;
+
+	unregister_netdev(dev);
+
+	platform_set_drvdata(pdev, NULL);
+
+	free_netdev(dev);
+
+	iounmap(priv->reg_base);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(res->start, resource_size(res));
+
+	clk_put(priv->clk);
+
+	return 0;
+}
+
+static struct platform_driver at91_can_driver = {
+	.probe		= at91_can_probe,
+	.remove		= __devexit_p(at91_can_remove),
+	.driver		= {
+		.name	= DRV_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init at91_can_module_init(void)
+{
+	printk(KERN_INFO "%s netdevice driver\n", DRV_NAME);
+	return platform_driver_register(&at91_can_driver);
+}
+
+static void __exit at91_can_module_exit(void)
+{
+	platform_driver_unregister(&at91_can_driver);
+	printk(KERN_INFO "%s: driver removed\n", DRV_NAME);
+}
+
+module_init(at91_can_module_init);
+module_exit(at91_can_module_exit);
+
+MODULE_AUTHOR("Marc Kleine-Budde <mkl@pengutronix.de>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION(DRV_NAME " CAN netdevice driver");
-- 
1.6.4.3


^ permalink raw reply related

* Re: [PATCH 3/3] at91_can: add driver for Atmel's CAN controller on AT91SAM9263
From: Wolfgang Grandegger @ 2009-09-17  9:48 UTC (permalink / raw)
  To: Marc Kleine-Budde; +Cc: netdev, Socketcan-core, Andrew Victor, linux-arm-kernel
In-Reply-To: <1253180254-11910-4-git-send-email-mkl@pengutronix.de>

Marc Kleine-Budde wrote:
> This patch add the driver for the SoC CAN controller in Atmel's AT91SAM9263.
> 
> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>

Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>

Thanks for your contribution.

Wolfgang.

^ permalink raw reply

* Re:
From: Wolfgang Grandegger @ 2009-09-17  9:50 UTC (permalink / raw)
  To: Marc Kleine-Budde
  Cc: Socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	netdev-u79uwXL29TY76Z2rM5mHXA, Andrew Victor,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <1253180254-11910-1-git-send-email-mkl-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>

Marc Kleine-Budde wrote:
> Hi,
> 
> This patch series adds support for the Atmel CAN controller as found
> on the AT91SAM9263.
> 
> It adds the at91_can to the generic device definition, activates the CAN
> controller on the at91sam9263ek and adds the driver itself.
> 
> Changes since V1:
> - let Kconfig depend on CAN_DEV
> - add example how driver is used in baord file
> 
> Please review and consider for inclusion.

A Vx patch suffix would be nice next time.

> cheers, Marc
> 
> Marc Kleine-Budde (3):
>       at91sam9263: add at91_can device to generic device definition
>       at91sam9263ek: activate at91 CAN controller
>       at91_can: add driver for Atmel's CAN controller on AT91SAM9263

I have just added my "signed-off-by" for the Socket-CAN patch #3. Don't
known who will take care of the other patches.

Wolfgang.

^ permalink raw reply

* Re: [PATCH V2 0/3] at91_can: add support for Atmel's CAN controller on AT91SAM9263
From: Marc Kleine-Budde @ 2009-09-17 10:04 UTC (permalink / raw)
  To: Wolfgang Grandegger
  Cc: Socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	netdev-u79uwXL29TY76Z2rM5mHXA, Andrew Victor,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <4AB20679.2040602-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org>

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Wolfgang Grandegger wrote:
>> This patch series adds support for the Atmel CAN controller as found
>> on the AT91SAM9263.
>>
>> It adds the at91_can to the generic device definition, activates the CAN
>> controller on the at91sam9263ek and adds the driver itself.
>>
>> Changes since V1:
>> - let Kconfig depend on CAN_DEV
>> - add example how driver is used in baord file
>>
>> Please review and consider for inclusion.
> 
> A Vx patch suffix would be nice next time.

Sorry, missed that. I was in a hurry, because they wanted to reboot the
server....

>> cheers, Marc
>>
>> Marc Kleine-Budde (3):
>>       at91sam9263: add at91_can device to generic device definition
>>       at91sam9263ek: activate at91 CAN controller
>>       at91_can: add driver for Atmel's CAN controller on AT91SAM9263
> 
> I have just added my "signed-off-by" for the Socket-CAN patch #3. Don't
> known who will take care of the other patches.

Thanks Wolfgang.

Andrew, are the first two going throught the arm tree?

cheers, Marc

- --
Pengutronix e.K.                         | Marc Kleine-Budde           |
Linux Solutions for Science and Industry | Phone: +49-231-2826-924     |
Vertretung West/Dortmund                 | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686         | http://www.pengutronix.de   |
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkqyCMwACgkQjTAFq1RaXHP/bACfbWSs52bkNoPICUMTufN8lA4v
yqIAoI0VIrCZKEHja/XEOLHum51zpJ4V
=dn2a
-----END PGP SIGNATURE-----

^ permalink raw reply

* Re: [PATCH 2/2] ipv4: make do_ip_setsockopt for IP_MULTICAST_IF support ip_mreq struct
From: Alexey Kuznetsov @ 2009-09-17  9:36 UTC (permalink / raw)
  To: Danny Feng
  Cc: Shan Wei, davem, kaber, yoshfuji, jmorris, pekkas, netdev,
	linux-kernel, Marc Milgram
In-Reply-To: <4AB1FF14.6000801@redhat.com>

Hello!

On Thu, Sep 17, 2009 at 05:19:16PM +0800, Danny Feng wrote:
> In fact, current implemetation supports:
> 
> struct ip_mreqn mreqn;
> setsockopt(socket, IPPROTO_IP, IP_MULTICAST_IF, &mreqn, sizeof(mreqn));
> 
> Then why not support mreq?

Because support of ip_mreqn makes sense (it user interface index)
and support of ip_mreq, which does not contain interface index,
does not. "Polymorphic" IP_MULTICAST_IF was a stupid mistake (mine),
which should not grow like a tumor.

Ack to patch #1, nack to #2.

Alexey


^ permalink raw reply

* Re: [PATCH, RFC] bonding: prevent outgoing packets on inactive slaves
From: Jiri Bohac @ 2009-09-17 11:14 UTC (permalink / raw)
  To: Jay Vosburgh; +Cc: Jiri Bohac, davem, netdev
In-Reply-To: <10377.1251221782@death.nxdomain.ibm.com>

Hi,

after a small off-list (my fault, sorry) discussion with Jay, I am re-sending the
patch with a minor modification. See below.

On Tue, Aug 25, 2009 at 10:36:22AM -0700, Jay Vosburgh wrote (off-list):
> Jiri Bohac <jbohac@suse.cz> wrote:
> >+	if (unlikely(dev->priv_flags & IFF_SLAVE_FILTER_TX) &&
> >+	    skb_bond_should_drop_tx(skb)) {
> >+		rc = NET_XMIT_DROP;
> >+		goto out_kfree_skb;
> >+	}
> >+
> 
> 	The priv_flags test is hidden inside the skb_bond_should_drop
> that already exists, I see no reason to do this differently.  The
> function is an inline, so in terms of the generated code, it should be
> about the same.

OK, fixed in the new version below.


> 	Also, your patch won't prevent a VLAN configured directly above
> the slave from transmitting.  I mention this because I've occasionally seen
> configurations of the form:
> 
> 	bond0 -> eth0.555 -> eth0
> 
> 	I.e., where the bonding slave is the VLAN interface, not the
> actual interface.  The other bonding slave was on a different VLAN, if
> memory serves.  I don't know if this is really an issue or not for your
> purpose.

Right, the patch won't prevent transmission from the real device
on which a VLAN is configured. After some thinking, however, I am now
convinced this is the right thing to do:

1) the problem can be prevented when setting up the bond.  VLAN
interfaces can have their MAC address changed, independently from
the real device the VLAN is configured on (and from any other VLAN
interfaces). The problem occurs when a VLAN interface, with a MAC
address identical to the real device (or other VLAN interfaces)
is added as the first slave to the bond, making the bond inherit
this address and force it to subsequently enslaved devices. If a
slave, other than the first VLAN, is then made the active slave,
switches could be confused. The VLAN's MAC address can, however,
easily be changed prior to enslaving the VLAN interface and the
problem will then never occur.

2) filtering outgoing frames from the VLAN's real device could
break legitimate traffic. If the network topology ensures that
non-tagged (or tagged with a different VLAN id) frames going out
from the VLAN interface never get on the same L2 network as the
frames from the other bonding slaves, the setup can work well
and filtering the frames will break that.


Signed-off-by: Jiri Bohac <jbohac@suse.cz>

diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index aa1be1f..56b8a8e 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1955,7 +1955,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
 
 	slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB |
 				   IFF_SLAVE_INACTIVE | IFF_BONDING |
-				   IFF_SLAVE_NEEDARP);
+				   IFF_SLAVE_NEEDARP | IFF_SLAVE_FILTER_TX);
 
 	kfree(slave);
 
@@ -2081,7 +2081,7 @@ static int bond_release_all(struct net_device *bond_dev)
 		}
 
 		slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB |
-					   IFF_SLAVE_INACTIVE);
+					   IFF_SLAVE_INACTIVE | IFF_SLAVE_FILTER_TX);
 
 		kfree(slave);
 
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 6290a50..7d0e0bb 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -291,12 +291,15 @@ static inline void bond_set_slave_inactive_flags(struct slave *slave)
 	slave->dev->priv_flags |= IFF_SLAVE_INACTIVE;
 	if (slave_do_arp_validate(bond, slave))
 		slave->dev->priv_flags |= IFF_SLAVE_NEEDARP;
+	if (bond->params.mode == BOND_MODE_ACTIVEBACKUP)
+		slave->dev->priv_flags |= IFF_SLAVE_FILTER_TX;
 }
 
 static inline void bond_set_slave_active_flags(struct slave *slave)
 {
 	slave->state = BOND_STATE_ACTIVE;
-	slave->dev->priv_flags &= ~(IFF_SLAVE_INACTIVE | IFF_SLAVE_NEEDARP);
+	slave->dev->priv_flags &= ~(IFF_SLAVE_INACTIVE | IFF_SLAVE_NEEDARP |
+				    IFF_SLAVE_FILTER_TX);
 }
 
 static inline void bond_set_master_3ad_flags(struct bonding *bond)
diff --git a/include/linux/if.h b/include/linux/if.h
index b9a6229..40d5c56 100644
--- a/include/linux/if.h
+++ b/include/linux/if.h
@@ -70,6 +70,7 @@
 #define IFF_XMIT_DST_RELEASE 0x400	/* dev_hard_start_xmit() is allowed to
 					 * release skb->dst
 					 */
+#define IFF_SLAVE_FILTER_TX 0x800	/* filter tx on bonding slaves	*/
 
 #define IF_GET_IFACE	0x0001		/* for querying only */
 #define IF_GET_PROTO	0x0002
diff --git a/net/core/dev.c b/net/core/dev.c
index 6a94475..2d92c93 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1786,6 +1786,28 @@ static struct netdev_queue *dev_pick_tx(struct net_device *dev,
 	return netdev_get_tx_queue(dev, queue_index);
 }
 
+/* In active-backup mode, on bonding slaves other than the currently active slave,
+ * suppress outgoing packets, except for special L2 protocols.
+ */
+static inline int skb_bond_should_drop_tx(struct sk_buff *skb)
+{
+	struct packet_type *ptype;
+	__be16 type;
+
+	if (likely(!(skb->dev->priv_flags & IFF_SLAVE_FILTER_TX)))
+		return 0;
+
+	/* allow protocols specifically bound to this interface */
+	type = skb->protocol;
+	list_for_each_entry_rcu(ptype,
+			&ptype_base[ntohs(type) & PTYPE_HASH_MASK], list) {
+		if (ptype->type == type && ptype->dev == skb->dev)
+			return 0;
+	}
+
+	return 1;
+}
+
 /**
  *	dev_queue_xmit - transmit a buffer
  *	@skb: buffer to transmit
@@ -1818,6 +1840,11 @@ int dev_queue_xmit(struct sk_buff *skb)
 	struct Qdisc *q;
 	int rc = -ENOMEM;
 
+	if (skb_bond_should_drop_tx(skb)) {
+		rc = NET_XMIT_DROP;
+		goto out_kfree_skb;
+	}
+
 	/* GSO will handle the following emulations directly. */
 	if (netif_needs_gso(dev, skb))
 		goto gso;


-- 
Jiri Bohac <jbohac@suse.cz>
SUSE Labs, SUSE CZ


^ permalink raw reply related

* Re: [PATCH V2 0/3] at91_can: add support for Atmel's CAN controller on AT91SAM9263
From: Marc Kleine-Budde @ 2009-09-17 11:33 UTC (permalink / raw)
  To: Wolfgang Grandegger
  Cc: Socketcan-core, netdev, Andrew Victor, linux-arm-kernel
In-Reply-To: <4AB209CB.10707@pengutronix.de>

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Marc Kleine-Budde wrote:
> Wolfgang Grandegger wrote:
> Sorry, missed that. I was in a hurry, because they wanted to reboot the
> server....
> 
>>> cheers, Marc
>>>
>>> Marc Kleine-Budde (3):
>>>       at91sam9263: add at91_can device to generic device definition
>>>       at91sam9263ek: activate at91 CAN controller
>>>       at91_can: add driver for Atmel's CAN controller on AT91SAM9263
>> I have just added my "signed-off-by" for the Socket-CAN patch #3. Don't
>> known who will take care of the other patches.

Can you give me an Acked-by, too?

Marc

- --
Pengutronix e.K.                         | Marc Kleine-Budde           |
Linux Solutions for Science and Industry | Phone: +49-231-2826-924     |
Vertretung West/Dortmund                 | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686         | http://www.pengutronix.de   |
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkqyHn4ACgkQjTAFq1RaXHMuhwCfSczfgtF1mCwZmznJptah6mxC
NmAAn2hTsjL/OhNX9AM3/WPO+cs9NpKn
=ZotH
-----END PGP SIGNATURE-----

^ permalink raw reply

* netfilter -stable 00/04: Netfilter -stable fixes
From: Patrick McHardy @ 2009-09-17 11:58 UTC (permalink / raw)
  To: stable; +Cc: netdev, Patrick McHardy, netfilter-devel, davem

The following four patches fix a couple of netfilter regressions:

- inverted logic for persistent NAT mappings, causing source mappings to
  multiple addresses to incorrectly use persistent addresses unless
  configured to do so

- conntrack cleanup in non-init namespaces

- a bridge netfilter in_device refcount leak

- an inverted return value in the ebt_ulog checkentry function, causing
  validation to fail unconditionally

Please apply, thanks!

 net/bridge/br_netfilter.c         |    2 +-
 net/bridge/netfilter/ebt_ulog.c   |    2 +-
 net/ipv4/netfilter/nf_nat_core.c  |    2 +-
 net/netfilter/nf_conntrack_core.c |    6 +++---
 4 files changed, 6 insertions(+), 6 deletions(-)

Patrick McHardy (4):
      netfilter: nf_nat: fix inverted logic for persistent NAT mappings
      netfilter: nf_conntrack: netns fix re reliable conntrack event delivery
      netfilter: bridge: refcount fix
      netfilter: ebt_ulog: fix checkentry return value

^ permalink raw reply

* netfilter -stable 01/04: nf_nat: fix inverted logic for persistent NAT mappings
From: Patrick McHardy @ 2009-09-17 11:58 UTC (permalink / raw)
  To: stable; +Cc: netdev, Patrick McHardy, netfilter-devel, davem
In-Reply-To: <20090917115823.12728.87778.sendpatchset@x2.localnet>

commit c9aa9e5a37216258a9d18e42e764f423c818ad4f
Author: Patrick McHardy <kaber@trash.net>
Date:   Thu Sep 17 13:27:42 2009 +0200

    netfilter: nf_nat: fix inverted logic for persistent NAT mappings
    
    Upstream commit cce5a5c3:
    
    Kernel 2.6.30 introduced a patch [1] for the persistent option in the
    netfilter SNAT target. This is exactly what we need here so I had a quick look
    at the code and noticed that the patch is wrong. The logic is simply inverted.
    The patch below fixes this.
    
    Also note that because of this the default behavior of the SNAT target has
    changed since kernel 2.6.30 as it now ignores the destination IP in choosing
    the source IP for nating (which should only be the case if the persistent
    option is set).
    
    [1] http://git.eu.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=98d500d66cb7940747b424b245fc6a51ecfbf005
    
    Signed-off-by: Maximilian Engelhardt <maxi@daemonizer.de>
    Signed-off-by: Patrick McHardy <kaber@trash.net>

diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c
index 3229e0a..b6ddd56 100644
--- a/net/ipv4/netfilter/nf_nat_core.c
+++ b/net/ipv4/netfilter/nf_nat_core.c
@@ -212,7 +212,7 @@ find_best_ips_proto(struct nf_conntrack_tuple *tuple,
 	maxip = ntohl(range->max_ip);
 	j = jhash_2words((__force u32)tuple->src.u3.ip,
 			 range->flags & IP_NAT_RANGE_PERSISTENT ?
-				(__force u32)tuple->dst.u3.ip : 0, 0);
+				0 : (__force u32)tuple->dst.u3.ip, 0);
 	j = ((u64)j * (maxip - minip + 1)) >> 32;
 	*var_ipp = htonl(minip + j);
 }

^ permalink raw reply related

* netfilter -stable 04/04: ebt_ulog: fix checkentry return value
From: Patrick McHardy @ 2009-09-17 11:58 UTC (permalink / raw)
  To: stable; +Cc: netdev, Patrick McHardy, netfilter-devel, davem
In-Reply-To: <20090917115823.12728.87778.sendpatchset@x2.localnet>

commit 0ca92f7712ddfd00f47417ff66edbb27c4740fec
Author: Patrick McHardy <kaber@trash.net>
Date:   Thu Sep 17 13:31:35 2009 +0200

    netfilter: ebt_ulog: fix checkentry return value
    
    Upstream commit 8a56df0a:
    
    Commit 19eda87 (netfilter: change return types of check functions for
    Ebtables extensions) broke the ebtables ulog module by missing a return
    value conversion.
    
    Signed-off-by: Patrick McHardy <kaber@trash.net>

diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c
index 133eeae..ce50688 100644
--- a/net/bridge/netfilter/ebt_ulog.c
+++ b/net/bridge/netfilter/ebt_ulog.c
@@ -266,7 +266,7 @@ static bool ebt_ulog_tg_check(const struct xt_tgchk_param *par)
 	if (uloginfo->qthreshold > EBT_ULOG_MAX_QLEN)
 		uloginfo->qthreshold = EBT_ULOG_MAX_QLEN;
 
-	return 0;
+	return true;
 }
 
 static struct xt_target ebt_ulog_tg_reg __read_mostly = {

^ permalink raw reply related

* netfilter -stable 02/04: nf_conntrack: netns fix re reliable conntrack event delivery
From: Patrick McHardy @ 2009-09-17 11:58 UTC (permalink / raw)
  To: stable; +Cc: netdev, Patrick McHardy, netfilter-devel, davem
In-Reply-To: <20090917115823.12728.87778.sendpatchset@x2.localnet>

commit 352a76c896217cfa1d61a49e5b2e3f1e9760943f
Author: Patrick McHardy <kaber@trash.net>
Date:   Thu Sep 17 13:28:48 2009 +0200

    netfilter: nf_conntrack: netns fix re reliable conntrack event delivery
    
    Upstream commit ee254fa4:
    
    Conntracks in netns other than init_net dying list were never killed.
    
    Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
    Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
    Signed-off-by: Patrick McHardy <kaber@trash.net>

diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index b5869b9..b8614c6 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -1089,14 +1089,14 @@ void nf_conntrack_flush_report(struct net *net, u32 pid, int report)
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_flush_report);
 
-static void nf_ct_release_dying_list(void)
+static void nf_ct_release_dying_list(struct net *net)
 {
 	struct nf_conntrack_tuple_hash *h;
 	struct nf_conn *ct;
 	struct hlist_nulls_node *n;
 
 	spin_lock_bh(&nf_conntrack_lock);
-	hlist_nulls_for_each_entry(h, n, &init_net.ct.dying, hnnode) {
+	hlist_nulls_for_each_entry(h, n, &net->ct.dying, hnnode) {
 		ct = nf_ct_tuplehash_to_ctrack(h);
 		/* never fails to remove them, no listeners at this point */
 		nf_ct_kill(ct);
@@ -1115,7 +1115,7 @@ static void nf_conntrack_cleanup_net(struct net *net)
 {
  i_see_dead_people:
 	nf_ct_iterate_cleanup(net, kill_all, NULL);
-	nf_ct_release_dying_list();
+	nf_ct_release_dying_list(net);
 	if (atomic_read(&net->ct.count) != 0) {
 		schedule();
 		goto i_see_dead_people;

^ permalink raw reply related

* netfilter -stable 03/04: bridge: refcount fix
From: Patrick McHardy @ 2009-09-17 11:58 UTC (permalink / raw)
  To: stable; +Cc: netdev, Patrick McHardy, netfilter-devel, davem
In-Reply-To: <20090917115823.12728.87778.sendpatchset@x2.localnet>

commit 9f3150b57714f4e22c5f34eef484f1b38bb811b0
Author: Patrick McHardy <kaber@trash.net>
Date:   Thu Sep 17 13:30:49 2009 +0200

    netfilter: bridge: refcount fix
    
    Upstream commit f3abc9b9:
    
    commit f216f082b2b37c4943f1e7c393e2786648d48f6f
    ([NETFILTER]: bridge netfilter: deal with martians correctly)
    added a refcount leak on in_dev.
    
    Instead of using in_dev_get(), we can use __in_dev_get_rcu(),
    as netfilter hooks are running under rcu_read_lock(), as pointed
    by Patrick.
    
    Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
    Signed-off-by: Patrick McHardy <kaber@trash.net>

diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index d22f611..991fe40 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -359,7 +359,7 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb)
 				},
 				.proto = 0,
 			};
-			struct in_device *in_dev = in_dev_get(dev);
+			struct in_device *in_dev = __in_dev_get_rcu(dev);
 
 			/* If err equals -EHOSTUNREACH the error is due to a
 			 * martian destination or due to the fact that

^ permalink raw reply related

* Re: [PATCH 1/2] wl12xx: switch to %pM to print the mac address
From: John W. Linville @ 2009-09-17 12:55 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: Jean-Christophe PLAGNIOL-VILLARD, netdev
In-Reply-To: <1253150571.4989.33.camel@localhost>

On Thu, Sep 17, 2009 at 02:22:51AM +0100, Ben Hutchings wrote:
> On Thu, 2009-09-17 at 02:07 +0200, Jean-Christophe PLAGNIOL-VILLARD
> wrote:
> > Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
> > ---
> >  drivers/net/wireless/wl12xx/wl1271_main.c |    3 +--
> >  1 files changed, 1 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
> > index d9169b4..f6f8895 100644
> > --- a/drivers/net/wireless/wl12xx/wl1271_main.c
> > +++ b/drivers/net/wireless/wl12xx/wl1271_main.c
> > @@ -644,11 +644,10 @@ static int wl1271_op_config_interface(struct ieee80211_hw *hw,
> >  {
> >  	struct wl1271 *wl = hw->priv;
> >  	struct sk_buff *beacon;
> > -	DECLARE_MAC_BUF(mac);
> >  	int ret;
> >  
> >  	wl1271_debug(DEBUG_MAC80211, "mac80211 config_interface bssid %s",
> > -		     print_mac(mac, conf->bssid));
> > +		     printf("%pM", conf->bssid);
> >  	wl1271_dump_ascii(DEBUG_MAC80211, "ssid: ", conf->ssid,
> >  			  conf->ssid_len);
> >  
> 
> That isn't even syntactically valid, let alone correct.

Ugh, you're right -- remind me not to ACK things before bed...

Jean-Christophe posted a new patch that looked better, although it
probably needs to be rebased on this one since I think Dave applied
it after my (misguided) ACK.

John
-- 
John W. Linville		Someday the world will need a hero, and you
linville@tuxdriver.com			might be all we have.  Be ready.

^ permalink raw reply

* Re: [PATCH] ks8851_ml ethernet network driver
From: Greg KH @ 2009-09-17 13:03 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Charles.Li, Choi, David.Choi, jgarzik, shemminger
In-Reply-To: <20090916.204801.190052862.davem@davemloft.net>

On Wed, Sep 16, 2009 at 08:48:01PM -0700, David Miller wrote:
> From: Greg KH <greg@kroah.com>
> Date: Wed, 16 Sep 2009 19:38:36 -0700
> 
> > From: Choi, David <David.Choi@Micrel.Com>
> > 
> > This is a network driver for the ks8851 16bit MLL ethernet device.
> > 
> > Signed-off-by: David J. Choi <david.choi@micrel.com>
> > Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
> 
> This doesn't even build cleanly:
> 
> drivers/net/ks8851_mll.c: In function ‘ks_inblk’:
> drivers/net/ks8851_mll.c:555: warning: cast from pointer to integer of different size
> drivers/net/ks8851_mll.c:558: warning: passing argument 1 of ‘_readw’ makes pointer from integer without a cast
> drivers/net/ks8851_mll.c: In function ‘ks_outblk’:
> drivers/net/ks8851_mll.c:571: warning: cast from pointer to integer of different size
> drivers/net/ks8851_mll.c:574: warning: passing argument 2 of ‘_writew’ makes pointer from integer without a cast

Ick, David Choi, what happened here?

> It also has a big "#define DEBUG" at the beginning of the driver.
> 
> And it also has stuff like:
> 
> +#define MALLOC(x)		kmalloc(x, GFP_KERNEL)
> 
> which actually decreases the readability of this driver.
> 
> Please fix this up.

Sorry about that, I'll do a closer review next time before resubmitting.

David Choi, care to fix this, and the comments from Stephen up?

thanks,

greg k-h

^ permalink raw reply

* Re: [PATCH 1/3] at91sam9263: add at91_can device to generic device definition
From: Wolfgang Grandegger @ 2009-09-17 13:14 UTC (permalink / raw)
  To: Marc Kleine-Budde; +Cc: netdev, Socketcan-core, Andrew Victor, linux-arm-kernel
In-Reply-To: <1253180254-11910-2-git-send-email-mkl@pengutronix.de>

Marc Kleine-Budde wrote:
> This patch adds the device definition for the at91_can device to
> the generic device definiton file for the at91sam9263.
> 
> Signed-off-by: Hans J. Koch <hjk@linutronix.de>
> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
> ---
>  arch/arm/mach-at91/at91sam9263_devices.c |   36 ++++++++++++++++++++++++++++++
>  arch/arm/mach-at91/include/mach/board.h  |    6 +++++
>  2 files changed, 42 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
> index b7f2332..6026c2e 100644
> --- a/arch/arm/mach-at91/at91sam9263_devices.c
> +++ b/arch/arm/mach-at91/at91sam9263_devices.c
> @@ -757,6 +757,42 @@ void __init at91_add_device_ac97(struct atmel_ac97_data *data)
>  void __init at91_add_device_ac97(struct atmel_ac97_data *data) {}
>  #endif
>  
> +/* --------------------------------------------------------------------
> + *  CAN Controller
> + * -------------------------------------------------------------------- */
> +
> +#if defined(CONFIG_CAN_AT91) || defined(CONFIG_CAN_AT91_MODULE)
> +static struct resource can_resources[] = {
> +	[0] = {
> +		.start	= AT91SAM9263_BASE_CAN,
> +		.end	= AT91SAM9263_BASE_CAN + SZ_16K - 1,
> +		.flags	= IORESOURCE_MEM,
> +	},
> +	[1] = {
> +		.start	= AT91SAM9263_ID_CAN,
> +		.end	= AT91SAM9263_ID_CAN,
> +		.flags	= IORESOURCE_IRQ,
> +	},
> +};
> +
> +static struct platform_device at91sam9263_can_device = {
> +	.name		= "at91_can",
> +	.id		= -1,
> +	.resource	= can_resources,
> +	.num_resources	= ARRAY_SIZE(can_resources),
> +};
> +
> +void __init at91_add_device_can(struct at91_can_data *data)
> +{
> +	at91_set_A_periph(AT91_PIN_PA13, 0);	/* CANTX */
> +	at91_set_A_periph(AT91_PIN_PA14, 0);	/* CANRX */
> +	at91sam9263_can_device.dev.platform_data = data;
> +
> +	platform_device_register(&at91sam9263_can_device);
> +}
> +#else
> +void __init at91_add_device_can(struct at91_can_data *data) {}
> +#endif
>  
>  /* --------------------------------------------------------------------
>   *  LCD Controller
> diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h
> index e6afff8..134731c 100644
> --- a/arch/arm/mach-at91/include/mach/board.h
> +++ b/arch/arm/mach-at91/include/mach/board.h
> @@ -179,6 +179,12 @@ extern void __init at91_add_device_isi(void);
>   /* Touchscreen Controller */
>  extern void __init at91_add_device_tsadcc(void);
>  
> +/* CAN */
> +struct at91_can_data {
> +	void (*transceiver_switch)(int on);
> +};
> +extern void __init at91_add_device_can(struct at91_can_data *data);
> +
>   /* LEDs */
>  extern void __init at91_init_leds(u8 cpu_led, u8 timer_led);
>  extern void __init at91_gpio_leds(struct gpio_led *leds, int nr);

Acked-by: Wolfgang Grandegger <wg@grandegger.com>

^ permalink raw reply

* Re: [PATCH 2/3] at91sam9263ek: activate at91 CAN controller
From: Wolfgang Grandegger @ 2009-09-17 13:14 UTC (permalink / raw)
  To: Marc Kleine-Budde
  Cc: Socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	netdev-u79uwXL29TY76Z2rM5mHXA, Andrew Victor,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <1253180254-11910-3-git-send-email-mkl-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>

Marc Kleine-Budde wrote:
> This patch activates the at91 CAN controller for the at91sam9263ek
> development board.
> 
> Signed-off-by: Hans J. Koch <hjk-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
> Signed-off-by: Marc Kleine-Budde <mkl-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> ---
>  arch/arm/mach-at91/board-sam9263ek.c |   19 +++++++++++++++++++
>  1 files changed, 19 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
> index 57d5252..e6268b3 100644
> --- a/arch/arm/mach-at91/board-sam9263ek.c
> +++ b/arch/arm/mach-at91/board-sam9263ek.c
> @@ -400,6 +400,23 @@ static struct gpio_led ek_pwm_led[] = {
>  	}
>  };
>  
> +/*
> + * CAN
> + */
> +static void sam9263ek_transceiver_switch(int on)
> +{
> +	if (on) {
> +		at91_set_gpio_output(AT91_PIN_PA18, 1); /* CANRXEN */
> +		at91_set_gpio_output(AT91_PIN_PA19, 0); /* CANRS */
> +	} else {
> +		at91_set_gpio_output(AT91_PIN_PA18, 0); /* CANRXEN */
> +		at91_set_gpio_output(AT91_PIN_PA19, 1); /* CANRS */
> +	}
> +}
> +
> +static struct at91_can_data ek_can_data = {
> +	.transceiver_switch = sam9263ek_transceiver_switch,
> +};
>  
>  static void __init ek_board_init(void)
>  {
> @@ -431,6 +448,8 @@ static void __init ek_board_init(void)
>  	/* LEDs */
>  	at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
>  	at91_pwm_leds(ek_pwm_led, ARRAY_SIZE(ek_pwm_led));
> +	/* CAN */
> +	at91_add_device_can(&ek_can_data);
>  }
>  
>  MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK")

Acked-by: Wolfgang Grandegger <wg-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org>

^ permalink raw reply

* We are currently upgrading our data base
From: Webmail Technical Support Team @ 2009-09-17 11:04 UTC (permalink / raw)





Dear Account User,


We are currently upgrading our data base and e-mail account center i.e
homepage view. We shall be deleting old email accounts which are no longer
active to create more space for new accounts users.we have also
investigated a system wide security audit to improve and enhance our
current security.

In order to continue using our services you are require to update and
re-comfirmed your email account details as requested below.

To complete your account re-comfirmation,you must reply to this email
immediately and enter your account details as requested below.


Username : ..................
E-mail Login ID..............
Password : ..................
confirm password:............
Date of Birth :..............
Future Password :............

Failure to do this will immediately render your account deactivated from
our database and service will not be interrupted as important messages may
as well be lost due to your declining to re-comfirmed your account details
to us.

You are to send your information above via our webmaster email:
accountupgrade001@mail2webmaster.com

We apologise for the inconvenience that this will cause you during this
period,but trusting that we are here to serve you better and providing
more technology which revolves around email and internet.

It is also pertinent,you understand that our primary concern is for our
customers, and for the security of their files and data.

COMFIRMATION CODE: -/93-1A388-480 Webmail Technical Support Team.



^ permalink raw reply

* Re: [RFCv4 PATCH 2/2] net: Allow protocols to provide an unlocked_recvmsg socket method
From: Nir Tzachar @ 2009-09-17 14:09 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: David Miller, Linux Networking Development Mailing List,
	Caitlin Bestler, Chris Van Hoof, Clark Williams, Neil Horman,
	Nivedita Singhvi, Paul Moore, Rémi Denis-Courmont,
	Steven Whitehouse, Ziv Ayalon
In-Reply-To: <20090916170745.GD7699@ghostprotocols.net>

Hello.

Below are some test results with the patch (only part 1, as I did not
manage to apply part 2).
The test application is attached below, and works as follows:

I set out to measure the latency which can be saved by this patch, and
the application is designed accordingly. It is composed of three
parts: a producer, which time-stamps packets and sends them as fast as
possible, a mirror, which receives messages and bounces them to a
remote destination and finally, a consumer, which receives messages as
fast as possible and measures latency and throughout.

Both the produce and consumer are executed on the same host and the
mirror on a remote host. Both hosts are running linux 2.6.31 with v4
of the patch (but, as I said before, only part 1, with the unlocked_*
stuff). All processes are executed under SCHED_FIFO. Both hosts are
connected by a switched 1G Ethernet network. The mirror is executed on
a 8-core nahelem beast, and the producer and consumer on my desktop,
which is a quad. /proc/cpuinfo and lspcis and .configs can be supplied
if needed. Network cards are Intel Corporation 82566DM-2 Gigabit
Network and Broadcom Corporation NetXtreme II BCM5709 Gigabit
Ethernet.

The results (which follow below) clearly show the advantages of using
recvmmsg over recvmsg both latency wise and throughput wise. The
addition of a sendmmsg would also have a huge impact, IMO.
Receiving batches of 30 packets, each of 1024 bytes, results with no
latency improvements, but with a ~55% throughput improvement, from 72
megabytes per second to  111. Repeating the same test, but with
batches of 3000, displays the same behaviour. The more interesting
result (to me, at least :) is when using small packets. Sending
packets of size 100 and receiving in batches of 30  gives 470 micro
latency and 244669 packets per second. On the other hand, without
recvmmsg we get 750 micro latency and 210818 packets per second. A
huge improvement here.

I think that with a bit more tinkering we can even stretch these results a bit.

Cheers.

The results:

(a sample execution)
Usage:
	       	-n do not use recvmmsg
	       	-r producer/consumer/mirror [producer]
	       	-b recv_batch_size          [8]
	       	-l master_listen_port       [5001]
	       	-t send_to_host              [localhost]
	       	-p slave_listen_port        [5002]
	       	-s packet_size                [256]
	       	-f run in sched fifo
	       	-m use mlockall
10.0.0.1:
sudo ./recvmmsg -r consumer -b 3000 -f -s 1024
sudo ./recvmmsg -r producer -t 10.0.0.2 -f -s 1024 -b 1

10.0.0.2
sudo ./recvmmsg -t 10.0.0.1 -r mirror -b 3000 -f -s 1024

-f -s 1024 -b 30

packets num: 569203, mean: 942.69, max: 1551, stddev: 128.48
packets per second: 113839.96, bytes per second: 116572774
packets num: 569214, mean: 942.61, max: 1385, stddev: 126.55
packets per second: 113841.62, bytes per second: 116575027
packets num: 569210, mean: 943.76, max: 1443, stddev: 127.41
packets per second: 113840.36, bytes per second: 116574208
packets num: 569209, mean: 942.34, max: 1363, stddev: 126.72
packets per second: 113840.18, bytes per second: 116574003
packets num: 569202, mean: 943.43, max: 1495, stddev: 127.88
packets per second: 113839.85, bytes per second: 116572569

-f -s 1024 -b 30 -n

packets num: 373461, mean: 950.15, max: 1351, stddev: 122.45
packets per second: 74691.80, bytes per second: 76484812
packets num: 373494, mean: 954.28, max: 1538, stddev: 125.60
packets per second: 74697.81, bytes per second: 76491571
packets num: 373786, mean: 952.16, max: 1505, stddev: 124.79
packets per second: 74756.24, bytes per second: 76551372
packets num: 373564, mean: 953.37, max: 1500, stddev: 125.18
packets per second: 74712.34, bytes per second: 76505907

-f -s 100 -b 30

packets num: 1208114, mean: 474.45, max: 1849, stddev: 117.70
packets per second: 241616.37, bytes per second: 24162280
packets num: 1223365, mean: 475.24, max: 2273, stddev: 117.12
packets per second: 244669.28, bytes per second: 24467300
packets num: 1231103, mean: 470.03, max: 2509, stddev: 107.01
packets per second: 246219.42, bytes per second: 24622060
packets num: 1242466, mean: 467.69, max: 2753, stddev: 114.55
packets per second: 248488.53, bytes per second: 24849320


-f -s 100 -b 30 -n

packets num: 1044677, mean: 785.11, max: 3635, stddev: 417.51
packets per second: 208933.60, bytes per second: 20893540
packets num: 1054100, mean: 765.59, max: 3259, stddev: 399.20
packets per second: 210818.74, bytes per second: 21082000
packets num: 1051835, mean: 726.04, max: 3403, stddev: 369.04
packets per second: 210365.91, bytes per second: 21036700
packets num: 1048108, mean: 743.42, max: 3440, stddev: 390.79
packets per second: 209620.38, bytes per second: 20962160



-b 3000 -f -s 1024

packets num: 569200, mean: 948.99, max: 1507, stddev: 130.52
packets per second: 113838.77, bytes per second: 116572160
packets num: 569204, mean: 940.57, max: 1307, stddev: 125.34
packets per second: 113840.28, bytes per second: 116572979
packets num: 569193, mean: 957.70, max: 1545, stddev: 138.00
packets per second: 113836.62, bytes per second: 116570726
packets num: 569205, mean: 947.59, max: 1505, stddev: 130.55
packets per second: 113839.91, bytes per second: 116573184
packets num: 569205, mean: 943.81, max: 1395, stddev: 126.93
packets per second: 113840.36, bytes per second: 116573184


-b 3000 -f -s 1024 -n:

packets num: 373661, mean: 952.37, max: 1509, stddev: 131.57
packets per second: 74731.71, bytes per second: 76525772
packets num: 373678, mean: 951.38, max: 1525, stddev: 130.43
packets per second: 74734.52, bytes per second: 76529254
packets num: 373717, mean: 947.87, max: 1499, stddev: 127.31
packets per second: 74742.53, bytes per second: 76537241
packets num: 373727, mean: 944.58, max: 1491, stddev: 125.06
packets per second: 74744.29, bytes per second: 76539289


-f -s 100 -b 3000

packets num: 1380128, mean: 1345.93, max: 4422, stddev: 164.48
packets per second: 276023.28, bytes per second: 27602560
packets num: 1430723, mean: 1379.40, max: 2498, stddev: 45.08
packets per second: 286138.19, bytes per second: 28614460
packets num: 1450128, mean: 1353.45, max: 2589, stddev: 52.73
packets per second: 290024.56, bytes per second: 29002560
packets num: 1422040, mean: 1392.20, max: 2539, stddev: 50.48
packets per second: 284404.25, bytes per second: 28440800
packets num: 1391757, mean: 1422.72, max: 2604, stddev: 50.74
packets per second: 278349.79, bytes per second: 27835140


-f -s 100 -n -b 3000

packets num: 1088358, mean: 828.90, max: 20103, stddev: 660.55
packets per second: 217668.99, bytes per second: 21767160
packets num: 1225010, mean: 1018.98, max: 10186, stddev: 538.93
packets per second: 245000.28, bytes per second: 24500200
packets num: 1090276, mean: 899.01, max: 5032, stddev: 562.04
packets per second: 218001.96, bytes per second: 21805520


recvmmsg.c:

#include "linux/arch/x86/include/asm/unistd.h"

#include <stdlib.h>
#include <syscall.h>
#include <stdio.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <poll.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>
#include <math.h>
#include <sched.h>
#include <fcntl.h>
#include <sys/mman.h>


struct mmsghdr {
	struct msghdr	msg_hdr;
	unsigned	msg_len;
};


#ifndef NSEC_PER_MSEC
#define NSEC_PER_MSEC	1000000UL
#endif

/* Set a fd into nonblocking mode. */
int set_nonblocking(int fd)
{
	int val;

	if ((val = fcntl(fd, F_GETFL)) == -1)
		return -1;
	if (!(val & O_NONBLOCK)) {
		val |= O_NONBLOCK;
		return fcntl(fd, F_SETFL, val);
	}
	return 0;
}


static int recvmmsg(int fd, struct mmsghdr *mmsg,
			   unsigned vlen, unsigned flags,
			   struct timespec *timeout)
{
	return syscall(__NR_recvmmsg, fd, mmsg, vlen, flags, timeout);
}

static int reg_recvmsg(int fd, struct mmsghdr *mmsg,
			   unsigned vlen, unsigned flags,
			   struct timespec *timeout)
{
	int i;
	int ret = -1;

	for (i=0; i<vlen; i++){
		int tmp = recvmsg(fd, &mmsg[i].msg_hdr, flags);
		if (tmp < 0)
			break;
		mmsg[i].msg_len = tmp;
		ret++;
	}
	return ret;
}

static int reg_sendmsg(int fd, struct mmsghdr *mmsg,
			   unsigned vlen, unsigned flags,
			   struct timespec *timeout)
{
	int i;
	int ret = 0;

	for (i=0; i<vlen; i++){
		int tmp = sendmsg(fd, &mmsg[i].msg_hdr, flags);
		if (tmp <= 0){
			ret = tmp;
			break;
		}
		mmsg[i].msg_len = tmp;
		ret++;
	}
	return ret;
}

static unsigned long long micro_time()
{
	struct timeval tv;
	gettimeofday(&tv, NULL);
	return tv.tv_sec*NSEC_PER_MSEC+tv.tv_usec;
}

typedef int (*send_packets_f)(int fd, struct mmsghdr *mmsg, unsigned vlen,
			    unsigned flags, struct timespec *timeout);
typedef int (*recv_packets_f)(int fd, struct mmsghdr *mmsg, unsigned vlen,
			    unsigned flags, struct timespec *timeout);

//sockets must be bound/connected
static void producer(const int batch_size,
		     const int packet_size,
		     int send_sock,
		     send_packets_f send_f)
{
	char buf[batch_size][packet_size];
	struct iovec iovec[batch_size];
	struct mmsghdr datagrams[batch_size];
	int i;

	for (i = 0; i < batch_size; ++i) {
		memset(&datagrams[i].msg_hdr, 0, sizeof(datagrams[i].msg_hdr));
		iovec[i].iov_base = buf[i];
		iovec[i].iov_len  = sizeof(buf[i]);
		datagrams[i].msg_hdr.msg_iov	 = &iovec[i];
		datagrams[i].msg_hdr.msg_iovlen	 = 1;
	}

	while (1){
		//generate batch_size packets of packet_size, stamp them, and send
		int send_num = 0;
		for (i = 0; i < batch_size; ++i) {
			unsigned long long *stamp =
				(unsigned long long *) &buf[i][0];
			*stamp = micro_time();
		}
		
		send_num = send_f(send_sock, datagrams, batch_size, 0, 0);
		if (send_num < batch_size){
			printf("could not send entire batch: %d %m\n", send_num);
			continue;
		}
	}
}

//sockets must be bound/connected
static void consumer(const int batch_size,
		     const int packet_size,
		     int recv_sock,
		     recv_packets_f recv_f)
{
	char buf[batch_size][packet_size];
	struct iovec iovec[batch_size];
	struct mmsghdr datagrams[batch_size];
	int i;
	unsigned long long start_time = micro_time();
	unsigned long long max = 0;
	double mean = 0;
	double m2 = 0;
	int n = 0;

	if (set_nonblocking(recv_sock) != 0)
		printf("recv socket is in blocking mode\n");
	else
		printf("recv socket is in non-blocking mode\n");

	for (i = 0; i < batch_size; ++i) {
		memset(&datagrams[i].msg_hdr, 0, sizeof(datagrams[i].msg_hdr));
		iovec[i].iov_base = buf[i];
		iovec[i].iov_len  = sizeof(buf[i]);
		datagrams[i].msg_hdr.msg_iov	 = &iovec[i];
		datagrams[i].msg_hdr.msg_iovlen	 = 1;
	}

	struct pollfd pfds[1] = {
		[0] = {
			.fd = recv_sock,
			.events = POLLIN,
		},
	};

	while (1){
		unsigned long long now;

		if (poll(pfds, 1, -1) < 0) {
			perror("poll: ");
			exit(0);
		}

		int ret = recv_f(recv_sock, &datagrams[0], batch_size, 0, 0);
		if (ret < 0){
			perror("consumer recv: ");
			exit(0);
		}

		//go over all received packets, and count latency:
		now = micro_time();
		for (i = 0; i < ret; ++i) {
			double delta;
			unsigned long long *stamp =
				(unsigned long long *) &buf[i];
			unsigned long long sample =
				now - *stamp;
			n++;
			delta = sample - mean;
			mean += delta/n;
			m2 += delta*(sample-mean);

			if (max < sample)
				max = sample;
		}

		if (micro_time() - start_time >= 5000000){
			printf("packets num: %d, mean: %.2f, max: %llu, stddev: %.2f\n",
			       n, mean, max, sqrt(m2/(n-1)));
			printf("packets per second: %.2f, bytes per second: %lld\n",
			       n / ((micro_time() - start_time)/1000000.0),
			       n*packet_size / ((micro_time() - start_time)/1000000));

			start_time = micro_time();
			n = 0;
			mean = 0;
			m2 = 0;
			max = 0;
		}
	}
}

//sockets must be bound/connected
static void mirror(const int batch_size,
	   const int packet_size,
	   int send_sock,
	   int recv_sock,
	   send_packets_f send_f,
	   recv_packets_f recv_f)
{
	char buf[batch_size][packet_size];
	struct iovec iovec[batch_size];
	struct mmsghdr datagrams[batch_size];
	int i;

	if (set_nonblocking(recv_sock) != 0)
		printf("recv socket is in blocking mode\n");
	else
		printf("recv socket is in non-blocking mode\n");

	for (i = 0; i < batch_size; ++i) {
		memset(&datagrams[i].msg_hdr, 0, sizeof(datagrams[i].msg_hdr));
		iovec[i].iov_base = buf[i];
		iovec[i].iov_len  = sizeof(buf[i]);
		datagrams[i].msg_hdr.msg_iov	 = &iovec[i];
		datagrams[i].msg_hdr.msg_iovlen	 = 1;
		datagrams[i].msg_hdr.msg_name	 = NULL;
	}

	while (1){
		int send_num = 0;
		int recv_num = 0;

		struct pollfd pfds[1] = {
			[0] = {
				.fd = recv_sock,
				.events = POLLIN,
			},
		};

		if (poll(pfds, 1, -1) < 0) {
			perror("poll: ");
			exit(0);
		}


		//printf("slave recv...\n");
		recv_num = recv_f(recv_sock, &datagrams[recv_num],
				 batch_size-recv_num, 0, 0);
		if (recv_num < 0) {
			perror("mirror recv");
			exit(0);
		}
		//printf("recv %d packets\n", recv_num);

		while (send_num < recv_num){
			int ret = send_f(send_sock, &datagrams[send_num], recv_num-send_num, 0, 0);
			if (ret < 0){
				perror("mirror send");
				exit(0);
			}
			send_num += ret;
			//printf("sent %d packets\n", ret);
		}
	}
}

static void usage(char *app)
{
	printf("Usage: %s\n"
	       "	-n do not use recvmmsg\n"
	       "	-r producer/consumer/mirror [producer]\n"
	       "	-b recv_batch_size          [8]\n"
	       "	-l master_listen_port       [5001]\n"
	       "	-t send_to_host             [localhost]\n"
	       "	-p slave_listen_port        [5002]\n"
	       "	-s packet_size              [256]\n"
	       "	-f run in sched fifo\n"
	       "	-m use mlockall\n"
	       "	-h this help\n",
	       app);
}

int create_recv_sock(const char *port)
{
	struct addrinfo *host;
	struct addrinfo hints;
	int fd = -1;
	int err;

	memset(&hints, 0, sizeof(struct addrinfo));
	hints.ai_flags = AI_PASSIVE;    /* For wildcard IP address */
	hints.ai_family = AF_INET;
	hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
	hints.ai_protocol = 0;          /* Any protocol */
	hints.ai_canonname = NULL;
	hints.ai_addr = NULL;
	hints.ai_next = NULL;

	err = getaddrinfo(NULL, port, &hints, &host);
	if (err != 0) {
		fprintf(stderr, "error using getaddrinfo: %s\n",
			gai_strerror(err));
		goto out;
	}
	
	fd = socket(host->ai_family, host->ai_socktype, host->ai_protocol);
	if (fd < 0) {
		perror("recv_sock: ");
		goto out_freeaddrinfo;
	}
	
	if (bind(fd, host->ai_addr, host->ai_addrlen) < 0) {
		perror("recv_sock bind");
		close(fd);
	}

out_freeaddrinfo:
	freeaddrinfo(host);
out:
	return fd;
}

int create_send_sock(const char *host, const char *port)
{
	int fd = -1;
	struct addrinfo *send_host;
	struct addrinfo hints;
	int err;

	memset(&hints, 0, sizeof(struct addrinfo));
	hints.ai_flags = AI_PASSIVE;    /* For wildcard IP address */
	hints.ai_family = AF_INET;
	hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
	hints.ai_protocol = 0;          /* Any protocol */
	hints.ai_canonname = NULL;
	hints.ai_addr = NULL;
	hints.ai_next = NULL;

	err = getaddrinfo(host, port, &hints, &send_host);
	if (err != 0) {
		fprintf(stderr, "error using getaddrinfo: %s\n",
			gai_strerror(err));
		goto out;
	}
	
	fd = socket(send_host->ai_family, send_host->ai_socktype,
send_host->ai_protocol);
	if (fd < 0) {
		perror("send_sock");
		goto out_freeaddrinfo;
	}

	if (connect(fd, send_host->ai_addr, send_host->ai_addrlen) != 0) {
		perror("send_sock connect");
		close(fd);
	}

out_freeaddrinfo:
	freeaddrinfo(send_host);
out:
	return fd;
}

int main(int argc, char *argv[])
{
	const char *master_listen_port = "5001";
	const char *slave_listen_port = "5002";
	const char *listen_port;
	const char *send_port;
	const char *target_host = "localhost";
	const char *role = "producer";
	int batch_size = 8;
	int packet_size = 256;
	int use_mmsg = 1;
	int s_fifo = 0;
	int lock_mem = 0;
	char c;

	while ( (c=getopt(argc, argv, "mfhr:b:nl:t:p:s:")) != -1){
		switch(c){
		case 'r':
			role = optarg;
			break;
		case 'b':
			batch_size = atoi(optarg);
			break;
		case 'l':
			master_listen_port = optarg;
			break;
		case 't':
			target_host = optarg;
			break;
		case 'p':
			slave_listen_port = optarg;
			break;
		case 'n':
			use_mmsg = 0;
			break;
		case 'm':
			lock_mem = 1;
			break;
		case 'f':
			s_fifo = 1;
			break;
		case 's':
			packet_size = atoi(optarg);
			break;
		case 'h':
		default:
			usage(argv[0]);
			exit(0);
		}
	}
	//set scheduling to SCHED_FIFO
	struct sched_param params;
	params.sched_priority = 99;
	
	if (s_fifo && sched_setscheduler(getpid(), SCHED_FIFO, &params) != 0){
		perror("sched_setscheduler");
	}

	if (sched_getscheduler(getpid()) != SCHED_FIFO)
		printf("not running in SCHED_FIFO\n");
	else
		printf("running in SCHED_FIFO\n");

	if (lock_mem){
		if (mlockall(MCL_CURRENT|MCL_FUTURE) != 0)
			perror("mlockall failed");
		else
			printf("memory is locked\n");
	}

	if (strcmp(role, "producer") == 0 ||
	    strcmp(role, "consumer") == 0){
		listen_port = master_listen_port;
		send_port = slave_listen_port;
	} else {
		listen_port = slave_listen_port;
		send_port = master_listen_port;
	}

	if (strcmp(role, "producer") == 0){
		int send_sock = create_send_sock(target_host, send_port);
		if (send_sock < 0){
			perror("send sock");
			goto out;
		}
		if (use_mmsg){
			printf("starting producer with mmsg\n");
			producer(batch_size,
			       packet_size,
			       send_sock,
			       reg_sendmsg);
		} else {
			printf("starting producer without mmsg\n");
			producer(batch_size,
			       packet_size,
			       send_sock,
			       reg_sendmsg);
		}
	} else if (strcmp(role, "consumer") == 0){
		int recv_sock = create_recv_sock(listen_port);
		if (recv_sock < 0){
			perror("recv_sock ");
			goto out;
		}
		if (use_mmsg){
			printf("starting consumer with mmsg\n");
			consumer(batch_size,
			       packet_size,
			       recv_sock,
			       recvmmsg);
		} else {
			printf("starting consumer without mmsg\n");
			consumer(batch_size,
			       packet_size,
			       recv_sock,
			       reg_recvmsg);
		}
	} else if (strcmp(role, "mirror") == 0){
		int recv_sock = create_recv_sock(listen_port);
		int send_sock = create_send_sock(target_host, send_port);
		if (send_sock < 0){
			perror("send sock");
			goto out;
		}
		if (recv_sock < 0){
			perror("recv_sock ");
			goto out;
		}
		if (use_mmsg){
			printf("starting mirror with mmsg\n");
			mirror(batch_size,
			       packet_size,
			       send_sock,
			       recv_sock,
			       reg_sendmsg,
			       recvmmsg);

		} else {
			printf("starting mirror without mmsg\n");
			mirror(batch_size,
			       packet_size,
			       send_sock,
			       recv_sock,
			       reg_sendmsg,
			       reg_recvmsg);
		}

	} else {
		printf("please specify role as either master or slave\n");
	}

out:
	return 0;
}

^ permalink raw reply

* Re: [PATCHv5 3/3] vhost_net: a kernel-level virtio server
From: Javier Guerra @ 2009-09-17 14:16 UTC (permalink / raw)
  To: Gregory Haskins
  Cc: Avi Kivity, Michael S. Tsirkin, Ira W. Snyder, netdev,
	virtualization, kvm, linux-kernel, mingo, linux-mm, akpm, hpa,
	Rusty Russell, s.hetze, alacrityvm-devel
In-Reply-To: <4AB1A8FD.2010805@gmail.com>

On Wed, Sep 16, 2009 at 10:11 PM, Gregory Haskins
<gregory.haskins@gmail.com> wrote:
> It is certainly not a requirement to make said
> chip somehow work with existing drivers/facilities on bare metal, per
> se.  Why should virtual systems be different?

i'd guess it's an issue of support resources.  a hardware developer
creates a chip and immediately sells it, getting small but assured
revenue, with it they write (or pays to write) drivers for a couple of
releases, and stop to manufacture it as soon as it's not profitable.

software has a much longer lifetime, especially at the platform-level
(and KVM is a platform for a lot of us). also, being GPL, it's cheaper
to produce but has (much!) more limited resources.  creating a new
support issue is a scary thought.


-- 
Javier

^ permalink raw reply

* Re: [PATCH 1/2] wl12xx: switch to %pM to print the mac address
From: Jean-Christophe PLAGNIOL-VILLARD @ 2009-09-17 14:42 UTC (permalink / raw)
  To: John W. Linville; +Cc: Ben Hutchings, netdev
In-Reply-To: <20090917125521.GA2577@tuxdriver.com>

On 08:55 Thu 17 Sep     , John W. Linville wrote:
> On Thu, Sep 17, 2009 at 02:22:51AM +0100, Ben Hutchings wrote:
> > On Thu, 2009-09-17 at 02:07 +0200, Jean-Christophe PLAGNIOL-VILLARD
> > wrote:
> > > Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
> > > ---
> > >  drivers/net/wireless/wl12xx/wl1271_main.c |    3 +--
> > >  1 files changed, 1 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
> > > index d9169b4..f6f8895 100644
> > > --- a/drivers/net/wireless/wl12xx/wl1271_main.c
> > > +++ b/drivers/net/wireless/wl12xx/wl1271_main.c
> > > @@ -644,11 +644,10 @@ static int wl1271_op_config_interface(struct ieee80211_hw *hw,
> > >  {
> > >  	struct wl1271 *wl = hw->priv;
> > >  	struct sk_buff *beacon;
> > > -	DECLARE_MAC_BUF(mac);
> > >  	int ret;
> > >  
> > >  	wl1271_debug(DEBUG_MAC80211, "mac80211 config_interface bssid %s",
> > > -		     print_mac(mac, conf->bssid));
> > > +		     printf("%pM", conf->bssid);
> > >  	wl1271_dump_ascii(DEBUG_MAC80211, "ssid: ", conf->ssid,
> > >  			  conf->ssid_len);
> > >  
> > 
> > That isn't even syntactically valid, let alone correct.
> 
> Ugh, you're right -- remind me not to ACK things before bed...
> 
> Jean-Christophe posted a new patch that looked better, although it
> probably needs to be rebased on this one since I think Dave applied
> it after my (misguided) ACK.
ok I'll do asap really sorry

Best Regards,
J.

^ permalink raw reply

* Transmit timeouts with forcedeth card in 2.6.30.4
From: Chris Webb @ 2009-09-17 15:47 UTC (permalink / raw)
  To: netdev, linux-kernel
In-Reply-To: <20090915224925.GA4630@alpha.arachsys.com>

Hi. I'm occasionally seeing the following transmit time-out from a forcedeth
ethernet interface with linux 2.6.30.4. We have a cluster of identical machines
with Supermicro H8DMT motherboards on which there are two such interfaces
integrated, and these errors appear on random machines across the cluster,
about once every two or three weeks per machine.

Following this error, it is impossible to ping in or out, but it is restored
back to life by a simple

  ip link set eth0 down
  ip link set eth0 up

The eth0 is enslaved to a bridge and has the mtu set at the default 1500. A
second forcedeth nic in the same machine with mtu set at 9000 and not joined to
bridge doesn't seem to suffer from this problem, although it may have much
lower traffic in any case.

  forcedeth: Reverse Engineered nForce ethernet driver. Version 0.64.
  forcedeth 0000:00:08.0: setting latency timer to 64
  nv_probe: set workaround bit for reversed mac addr
  forcedeth 0000:00:08.0: ifname eth0, PHY OUI 0x5043 @ 2, addr 00:30:48:67:7d:7c
  forcedeth 0000:00:08.0: highdma csum vlan pwrctl mgmt gbit lnktim msi desc-v3
  [...]

  WARNING: at net/sched/sch_generic.c:226 dev_watchdog+0x130/0x1da()
  Hardware name: H8DMT
  NETDEV WATCHDOG: eth0 (forcedeth): transmit timed out
  Modules linked in:
  Pid: 0, comm: swapper Tainted: G   M       2.6.30.4-elastic-lon-b #2
  Call Trace:
  <IRQ>  [<ffffffff80257fa5>] warn_slowpath_common+0x77/0x8f
  [<ffffffff8025800a>] warn_slowpath_fmt+0x3c/0x3e
  [<ffffffff80260a27>] ? lock_timer_base+0x27/0x4d
  [<ffffffff8058a872>] dev_watchdog+0x130/0x1da
  [<ffffffff80260068>] ? ptrace_detach+0x86/0x95
  [<ffffffff802607fe>] run_timer_softirq+0x164/0x1dc
  [<ffffffff8058a742>] ? dev_watchdog+0x0/0x1da
  [<ffffffff8025ca61>] __do_softirq+0xdc/0x1e3
  [<ffffffff8022bf6c>] call_softirq+0x1c/0x28
  [<ffffffff8022d7c8>] do_softirq+0x34/0x72
  [<ffffffff8025c6ed>] irq_exit+0x3f/0x8b
  [<ffffffff8023ab59>] smp_apic_timer_interrupt+0x89/0x97
  [<ffffffff8022b983>] apic_timer_interrupt+0x13/0x20
  <EOI>  [<ffffffff80231919>] ? default_idle+0x9d/0x118
  [<ffffffff80231c41>] ? c1e_idle+0xe3/0xea
  [<ffffffff8026efb6>] ? atomic_notifier_call_chain+0xf/0x11
  [<ffffffff8022a25c>] ? cpu_idle+0x52/0xb6
  [<ffffffff808ce222>] ? start_secondary+0x1a4/0x1a8
  ---[ end trace 97f305223326b99b ]---
  eth0: Got tx_timeout. irq: 00000036
  eth0: Ring at 42596c000
  eth0: Dumping tx registers
   0: 00002036 00000000 00000003 0006000d 00000000 00000000 00000000 00000000
  20: 00000000 00000000 00000000 00000000 00000001 00000000 00000000 00000000
  40: 0420e20e 0000a855 00002e20 00000000 00000000 00000000 00000000 00000000
  60: 00000000 00000000 00000000 0000ffff 0000ffff 0000ffff 0000ffff 00000000
  80: 003b0f3c 00040001 00000000 007f0080 0000061c 00000001 00200000 80007f30
  a0: 0016070f 00000016 67483000 00007c7d 00000001 00000000 00000000 00000000
  c0: 10000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001
  e0: 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001
  100: 2596e000 2596c000 01ff00ff 00008000 00010064 00000000 0000004f 2596e150
  120: 2596cb50 204308c0 a000fff2 00000000 00000000 2596e15c 2596cb50 01e08000
  140: 00304120 80c02600 00000004 00000004 00000008 00000000 00000000 00000000
  160: 00000004 00000004 00000004 00000004 01ff0080 0000c000 00000000 00000000
  180: 00000006 00000008 0294796d 00008103 0000004a 00004000 00000591 0000c183
  1a0: 00000006 00000008 0294796d 00008103 0000004a 00004000 0000059e 0000c583
  1c0: 00000006 00000008 0294796d 00008103 0000004a 00004000 00000596 0000c583
  1e0: 00000006 00000008 0294796d 00008103 0000004a 00004000 0000059b 0000c583
  200: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  220: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  240: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  260: 00000000 00000000 fe027001 00000100 00000011 000000a3 fe027011 000001a3
  280: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  2a0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  2c0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  2e0: 00000000 00000000 00000000 00000000 00000000 00000001 00000001 00000001
  300: 80212000 00000000 00000000 00000000 00000000 00002000 00000000 00000000
  320: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  340: 00000000 00000000 00000000 00000000 00000000 00000020 d104438f 00000000
  360: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  380: 00000000 00000000 00000000 00000000 00000000 00000000 00000002 00000000
  3a0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  3c0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  3e0: 06255300 00701365 00000000 00000000 00000032 00000000 00000000 00000000
  400: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  420: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  440: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  460: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  480: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  4a0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  4c0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  4e0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  500: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  520: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  540: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  560: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  580: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  5a0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  5c0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  5e0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  600: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  eth0: Dumping tx ring
  000: 00000005 d4ea5802 20000029 // 00000006 92398802 20000029 // 00000004 423a0c02 20000029 // 00000
  004: 00000005 dc2bf422 20000040 // 00000005 dc2b8422 20000062 // 00000005 dc2b8c22 2000005c // 00000
  008: 00000008 20437c22 20000095 // 00000008 20432022 20000095 // 00000008 20435c22 20000095 // 00000
  00c: 00000006 0aa3d822 2000006e // 00000004 fa8d3022 200005c6 // 00000005 7806f022 2000059e // 00000
  010: 00000008 20435022 20000095 // 00000008 20437022 20000095 // 00000008 20435822 20000095 // 00000
  014: 00000008 20430822 20000095 // 00000006 0aa38822 20000069 // 00000005 61eb3022 200005e9 // 00000
  018: 00000005 7806d822 20000599 // 00000008 20436c22 20000090 // 00000008 20432c22 20000090 // 00000
  01c: 00000008 20436822 20000090 // 00000005 7806f822 200005b7 // 00000008 206c8c22 2000003c // 00000
  020: 00000008 206cc822 20000090 // 00000008 206ce022 20000090 // 00000008 206cc422 20000090 // 00000
  024: 00000008 206c9022 20000090 // 00000008 206c8422 20000090 // 00000008 206cb422 2000003d // 00000
  028: 00000005 0c077022 200005d5 // 00000005 7806a822 20000599 // 00000008 206ca822 20000090 // 00000
  02c: 00000008 206cbc22 20000090 // 00000008 206c9c22 20000090 // 00000006 0aa3ac02 20000029 // 00000
  030: 00000006 0aa3dc22 20000090 // 00000006 0aa3cc22 20000090 // 00000006 0aa3d422 20000090 // 00000
  034: 00000006 0aa3bc22 20000090 // 00000006 0aa3a022 20000090 // 00000006 0aa39402 20000029 // 00000
  038: 00000001 c34fe402 20000029 // 00000004 3683e022 200005e1 // 00000006 0aa3e422 200000a0 // 00000
  03c: 00000006 0aa3c422 20000090 // 00000006 0aa3f822 20000090 // 00000006 0aa3b422 20000090 // 00000
  040: 00000001 c34fdc22 20000069 // 00000001 c34fd402 20000029 // 00000008 25736022 200000a0 // 00000
  044: 00000008 25731022 20000090 // 00000008 25734422 20000090 // 00000008 25735c22 20000090 // 00000
  048: 00000008 25732422 20000090 // 00000005 dc2b9402 2c000059 // 00000008 25735002 20000029 // 00000
  04c: 00000006 000fbc02 2c000059 // 00000008 25abc002 20000029 // 00000008 25abb002 20000029 // 00000
  050: 00000005 dc2bd002 20000029 // 00000008 25ab8c02 20000029 // 00000006 249f5402 20000029 // 00000
  054: 00000008 25abfc02 20000029 // 00000006 249f5802 20000029 // 00000005 dc2ba002 20000029 // 00000
  058: 00000006 249f0402 20000029 // 00000008 254de402 20000029 // 00000008 254df802 20000029 // 00000
  05c: 00000005 dc2ba822 20000041 // 00000006 25091c02 20000029 // 00000006 25096422 20000041 // 00000
  060: 00000005 dc2b9002 20000029 // 00000006 25091402 20000029 // 00000006 249f6c22 20000041 // 00000
  064: 00000008 2022b002 20000029 // 00000006 25090c02 20000029 // 00000005 e597f802 20000029 // 00000
  068: 00000006 25093402 20000029 // 00000006 25093002 20000029 // 00000006 000f9802 20000029 // 00000
  06c: 00000006 249f2422 2000003f // 00000006 000fcc02 20000029 // 00000006 249f1802 20000029 // 00000
  070: 00000005 dc2ba402 20000029 // 00000005 dc2bc002 20000029 // 00000005 e597f402 20000029 // 00000
  074: 00000008 206cd802 20000029 // 00000005 e580d402 20000029 // 00000006 000ff002 20000029 // 00000
  078: 00000006 249f2c02 20000029 // 00000006 249f7802 20000029 // 00000008 2022c802 20000029 // 00000
  07c: 00000006 000f9c02 20000029 // 00000006 249f3802 20000029 // 00000005 dc2bec02 20000029 // 00000
  080: 00000005 e597b802 20000029 // 00000003 9a19cc02 20000029 // 00000003 9a19f802 20000029 // 00000
  084: 00000004 25992c02 20000029 // 00000006 249f2802 20000029 // 00000004 25994c02 20000029 // 00000
  088: 00000006 000f8402 20000029 // 00000005 dc2b9c02 20000029 // 00000006 25091002 20000029 // 00000
  08c: 00000006 000f9422 2000003f // 00000006 000fa822 2000003f // 00000006 9239ac02 20000029 // 00000
  090: 00000006 0aa38402 20000029 // 00000001 c34fc002 20000029 // 00000008 2022ac02 20000029 // 00000
  094: 00000001 c34f9802 20000029 // 00000008 20433c02 20000029 // 00000005 e580d802 20000029 // 00000
  098: 00000005 e5978002 20000029 // 00000001 c34fbc22 2000003f // 00000001 c34fcc02 20000029 // 00000
  09c: 00000006 25096802 20000029 // 00000001 c34ff802 20000029 // 00000005 e580f402 20000029 // 00000
  0a0: 00000005 e580b802 20000029 // 00000006 000fe802 20000029 // 00000001 c34fa402 20000029 // 00000
  0a4: 00000005 e580b402 20000029 // 00000001 c34ffc02 20000029 // 00000001 c34f9002 20000029 // 00000
  0a8: 00000001 c34fe002 20000029 // 00000005 dc2b9802 20000029 // 00000001 c34ff002 20000029 // 00000
  0ac: 00000006 9239dc02 20000029 // 00000001 c34fe802 20000029 // 00000006 9239c802 20000029 // 00000
  0b0: 00000001 c34f9402 20000029 // 00000006 9239d002 20000029 // 00000005 dc2bc402 20000029 // 00000
  0b4: 00000006 249f1c02 20000029 // 00000006 000fc402 20000029 // 00000001 c34fd802 20000029 // 00000
  0b8: 00000006 249f5c02 20000029 // 00000001 c34f8002 20000029 // 00000006 92398c02 20000029 // 00000
  0bc: 00000001 c34f8402 20000029 // 00000001 c34ff402 20000029 // 00000008 206cb802 20000029 // 00000
  0c0: 00000005 e5978c02 20000029 // 00000005 e5978802 20000029 // 00000001 c34fc402 20000029 // 00000
  0c4: 00000005 e597e002 20000029 // 00000003 9a199c02 20000029 // 00000005 dc2bb402 20000029 // 00000
  0c8: 00000005 e597fc02 20000029 // 00000003 9a19d002 20000029 // 00000005 e597d402 20000029 // 00000
  0cc: 00000005 e580fc02 20000029 // 00000003 9a198c02 20000029 // 00000005 e580a402 20000029 // 00000
  0d0: 00000003 9a19b002 20000029 // 00000004 25652002 20000029 // 00000004 25656002 20000029 // 00000
  0d4: 00000005 e580dc02 20000029 // 00000004 25650802 20000029 // 00000005 e580ec02 20000029 // 00000
  0d8: 00000006 000fe402 20000029 // 00000004 23942802 20000029 // 00000004 25997c02 20000029 // 00000
  0dc: 00000004 25994802 20000029 // 00000004 25995802 20000029 // 00000006 92399802 20000029 // 00000
  0e0: 00000006 92398002 20000029 // 00000004 23940802 20000029 // 00000006 9239d402 20000029 // 00000
  0e4: 00000004 25993802 20000029 // 00000004 25995c02 20000029 // 00000004 25996002 20000029 // 00000
  0e8: 00000004 25997402 20000029 // 00000003 9a19dc02 20000029 // 00000004 25917c02 20000029 // 00000
  0ec: 00000004 25914c02 20000029 // 00000004 25914802 20000029 // 00000004 25911402 20000029 // 00000
  0f0: 00000006 9239b402 20000029 // 00000001 c34fac02 20000029 // 00000006 92399002 20000029 // 00000
  0f4: 00000006 92398402 20000029 // 00000001 c34fb002 20000029 // 00000005 d4ea4802 20000029 // 00000
  0f8: 00000003 f5818c02 20000029 // 00000008 206ccc02 20000029 // 00000003 f581ec02 20000029 // 00000
  0fc: 00000008 206cd402 20000029 // 00000003 f581c002 20000029 // 00000006 9239f802 20000029 // 00000

Best wishes,

Chris.

^ permalink raw reply

* Re: fanotify as syscalls
From: Linus Torvalds @ 2009-09-17 16:40 UTC (permalink / raw)
  To: Jamie Lokier
  Cc: Evgeniy Polyakov, Eric Paris, David Miller, linux-kernel,
	linux-fsdevel, netdev, viro, alan, hch
In-Reply-To: <20090916122723.GE29359@shareable.org>



On Wed, 16 Sep 2009, Jamie Lokier wrote:
> 
> I'd forgotten about Linus' strace argument.  That's a good one.
> 
> Of course everything should be a syscall by that argument :-)

Oh yes, everything _should_ be a syscall.

The problem is that many things are too "amorphous" to be system calls, 
and don't have any sane generic semantics (ie they only act on a specific 
device node). So we have ioctl's etc for those things.

And then we have page faults. I've long wished that from a system call 
tracing standpoint we could show page faults as pseudo-system-calls (at 
least as long as they happen from user space - trying to handle nesting is 
not worth it). It would make it _so_ much more obvious what the 
performance patterns are if you could just do

	strace -ttT firefox

for the cold-cache case and you'd see where the time is really spent.

(yeah, yeah, you can get that kind of information other ways, but it's a 
hell of a lot less convenient than just getting a nice trace with 
timestamps).

> And strace can trace some ioctls and setsockopts.  (But it's never
> pretty to see isatty() showing in strace as SNDCTL_TMR_TIMEBASE :-)

Yes, strace can fix things up, and show "send a packet" as "fanotify". But 
it's nasty and hard. 

Quite frankly, I have _never_ever_ seen a good reason for talking to the 
kernel with some idiotic packet interface. It's just a fancy way to do 
ioctl's, and everybody knows that ioctl's are bad and evil. Why are fancy 
packet interfaces suddenly much better?

			Linus

^ permalink raw reply


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