* Re: [Patch net-next]atl1e:fix 2.6.31-git4 -- ATL1E 0000:03:00.0: DMA-API: device driver frees DMA
From: Daniel Walker @ 2009-09-16 9:10 UTC (permalink / raw)
To: jie.yang; +Cc: davem, miles.lane, chris.snook, jcliburn, netdev, linux-kernel
In-Reply-To: <12530821133392-git-send-email-jie.yang@atheros.com>
On Wed, 2009-09-16 at 14:21 +0800, jie.yang@atheros.com wrote:
> - pci_unmap_page(pdev, tx_buffer->dma,
> + if (tx_buffer->flags & ATL1E_TX_PCIMAP_SINGLE)
> + pci_unmap_single(pdev, tx_buffer->dma,
> + tx_buffer->length, PCI_DMA_TODEVICE);
> + else if (tx_buffer->flags & ATL1E_TX_PCIMAP_PAGE)
> + pci_unmap_page(pdev, tx_buffer->dma,
Could you run this through checkpatch, and fix any errors if find? It
looks like you uses spaces for tabs in the code above, maybe in the
other block too..
Daniel
^ permalink raw reply
* Re: [E1000-devel] [BUG 2.6.30+] e100 sometimes causes oops during resume
From: Karol Lewandowski @ 2009-09-16 9:19 UTC (permalink / raw)
To: Karol Lewandowski
Cc: Graham, David, Rafael J. Wysocki, linux-kernel@vger.kernel.org,
e1000-devel@lists.sourceforge.net, netdev@vger.kernel.org
In-Reply-To: <20090916014448.GA1070@bizet.domek.prywatny>
On Wed, Sep 16, 2009 at 03:44:48AM +0200, Karol Lewandowski wrote:
> On Tue, Sep 15, 2009 at 03:54:20PM -0700, Graham, David wrote:
>
> > A v2.6.30..v2.6.31 diff shows that this is probably exposed by
> > Rafael Wysocki's commit 6905b1f1, which now allows systems with e100
> > to sleep. If I understand correctly, it looks like these systems
> > simply couldn't sleep before. Is that right Rafael?.
>
> Probably true, but that wasn't the case for my (I guess
> ACPI-controlled) system.
>
>
> > I don't think its likely that the commit is a direct cause of the
> > problem, but that the suspend/resume cycle now allows us to see
> > another issue.
>
> From my (very limited) understanding commit message is at least in
> conflict with patch body.
No, it isn't, I must just go to bed earlier than 4AM. :/
Sorry for noise.
^ permalink raw reply
* Re: [PATCH V2 2/2] ems_usb: Added support for EMS CPC-USB/ARM7 CAN/USB interface
From: Wolfgang Grandegger @ 2009-09-16 9:26 UTC (permalink / raw)
To: Sebastian Haas
Cc: eric.dumazet-Re5JQEeQqe8AvxtiuMwx3w,
netdev-u79uwXL29TY76Z2rM5mHXA, oliver-GvhC2dPhHPQdnm+yROfE0A,
socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
oliver-fJ+pQTUTwRTk1uMJSBkQmQ, greg-U8xfFu+wG4EAvxtiuMwx3w,
davem-fT/PcQaiUtIeIZ0/mPfg9Q
In-Reply-To: <20090916090418.12370.16510.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
Sebastian Haas wrote:
> This patch adds support for one channel CAN/USB interace CPC-USB/ARM7 from
> EMS Dr. Thomas Wuensche (http://www.ems-wuensche.com).
>
> Signed-off-by: Sebastian Haas <haas-zsNKPWJ8Pib6hrUXjxyGrA@public.gmane.org>
The cleanup in the probe function is still not OK :-(.
> ---
>
> drivers/net/can/Kconfig | 7
> drivers/net/can/Makefile | 2
> drivers/net/can/usb/Makefile | 5
> drivers/net/can/usb/ems_usb.c | 1151 +++++++++++++++++++++++++++++++++++++++++
> 4 files changed, 1165 insertions(+), 0 deletions(-)
> create mode 100644 drivers/net/can/usb/Makefile
> create mode 100644 drivers/net/can/usb/ems_usb.c
>
> diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
> index 0900743..6ac5aa5 100644
> --- a/drivers/net/can/Kconfig
> +++ b/drivers/net/can/Kconfig
> @@ -75,6 +75,13 @@ config CAN_EMS_PCI
> CPC-PCIe and CPC-104P cards from EMS Dr. Thomas Wuensche
> (http://www.ems-wuensche.de).
>
> +config CAN_EMS_USB
> + tristate "EMS CPC-USB/ARM7 CAN/USB interface"
> + depends on USB && CAN_DEV
> + ---help---
> + This driver is for the one channel CPC-USB/ARM7 CAN/USB interface
> + from from EMS Dr. Thomas Wuensche (http://www.ems-wuensche.de).
> +
> config CAN_KVASER_PCI
> tristate "Kvaser PCIcanx and Kvaser PCIcan PCI Cards"
> depends on PCI && CAN_SJA1000
> diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
> index 523a941..9b035ec 100644
> --- a/drivers/net/can/Makefile
> +++ b/drivers/net/can/Makefile
> @@ -7,6 +7,8 @@ obj-$(CONFIG_CAN_VCAN) += vcan.o
> obj-$(CONFIG_CAN_DEV) += can-dev.o
> can-dev-y := dev.o
>
> +obj-y += usb/
> +
> obj-$(CONFIG_CAN_SJA1000) += sja1000/
>
> ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
> diff --git a/drivers/net/can/usb/Makefile b/drivers/net/can/usb/Makefile
> new file mode 100644
> index 0000000..c3f75ba
> --- /dev/null
> +++ b/drivers/net/can/usb/Makefile
> @@ -0,0 +1,5 @@
> +#
> +# Makefile for the Linux Controller Area Network USB drivers.
> +#
> +
> +obj-$(CONFIG_CAN_EMS_USB) += ems_usb.o
> diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c
[snip]
> +/*
> + * probe function for new CPC-USB devices
> + */
> +static int ems_usb_probe(struct usb_interface *intf,
> + const struct usb_device_id *id)
> +{
> + struct net_device *netdev;
> + struct ems_usb *dev;
> + int i, err;
> + int retval = -ENOMEM;
Why do you need an extra variable here.
int err = -ENOMEM;
Should work fine!?
> +
> + netdev = alloc_candev(sizeof(struct ems_usb));
> + if (!netdev) {
> + dev_err(netdev->dev.parent, "Couldn't alloc candev\n");
> + return -ENOMEM;
> + }
> +
> + dev = netdev_priv(netdev);
> +
> + dev->udev = interface_to_usbdev(intf);
> + dev->netdev = netdev;
> +
> + dev->can.state = CAN_STATE_STOPPED;
> + dev->can.clock.freq = EMS_USB_ARM7_CLOCK;
> + dev->can.bittiming_const = &ems_usb_bittiming_const;
> + dev->can.do_set_bittiming = ems_usb_set_bittiming;
> + dev->can.do_set_mode = ems_usb_set_mode;
> +
> + netdev->flags |= IFF_ECHO; /* we support local echo */
> +
> + /*
> + * The device actually uses a 16MHz clock to generate the CAN clock
> + * but it expects SJA1000 bit settings based on 8MHz (is internally
> + * converted).
> + */
> +
> + netdev->netdev_ops = &ems_usb_netdev_ops;
> +
> + netdev->flags |= IFF_ECHO; /* we support local echo */
> +
> + init_usb_anchor(&dev->rx_submitted);
> +
> + init_usb_anchor(&dev->tx_submitted);
> + atomic_set(&dev->active_tx_urbs, 0);
> +
> + for (i = 0; i < MAX_TX_URBS; i++)
> + dev->tx_contexts[i].echo_index = MAX_TX_URBS;
> +
> + dev->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
> + if (!dev->intr_urb) {
> + dev_err(netdev->dev.parent, "Couldn't alloc intr URB\n");
> + goto cleanup_candev;
> + }
> +
> + dev->intr_in_buffer = kzalloc(INTR_IN_BUFFER_SIZE, GFP_KERNEL);
> + if (!dev->intr_in_buffer) {
> + dev_err(netdev->dev.parent, "Couldn't alloc Intr buffer\n");
> + goto cleanup_intr_urb;
> + }
> +
> + dev->tx_msg_buffer = kzalloc(CPC_HEADER_SIZE +
> + sizeof(struct ems_cpc_msg), GFP_KERNEL);
> + if (!dev->tx_msg_buffer) {
> + dev_err(netdev->dev.parent, "Couldn't alloc Tx buffer\n");
> + goto cleanup_intr_in_buffer;
> + }
> +
> + usb_set_intfdata(intf, dev);
> +
> + SET_NETDEV_DEV(netdev, &intf->dev);
> +
> + init_params_sja1000(&dev->active_params);
> +
> + err = ems_usb_command_msg(dev, &dev->active_params);
> + if (err) {
> + dev_err(netdev->dev.parent,
> + "couldn't initialize controller: %d\n", err);
> + retval = err;
Could be removed then.
> + goto cleanup_tx_msg_buffer;
> + }
> +
> + return register_candev(netdev);
Cleanup is missing if register_candev() fails!
> +
> +cleanup_tx_msg_buffer:
> + kfree(dev->tx_msg_buffer);
> +
> +cleanup_intr_in_buffer:
> + kfree(dev->intr_in_buffer);
> +
> +cleanup_intr_urb:
> + usb_free_urb(dev->intr_urb);
> +
> +cleanup_candev:
> + free_candev(netdev);
> +
> + return retval;
> +}
Wolfgang.
^ permalink raw reply
* [Patch net-next]atl1e:fix 2.6.31-git4 -- ATL1E 0000:03:00.0: DMA-API: device driver frees DMA
From: jie.yang @ 2009-09-16 9:28 UTC (permalink / raw)
To: davem; +Cc: miles.lane, chris.snook, jcliburn, netdev, linux-kernel, Jie Yang
use the wrong API when free dma. So when map dma use a flag to demostrate whether it is 'pci_map_single' or 'pci_map_page'. When free the dma, check the flags to select the right APIs('pci_unmap_single' or 'pci_unmap_page').
set the flags type to u16 instead of unsigned long on David's comments.
Signed-off-by: Jie Yang <jie.yang@atheros.com>
---
diff --git a/drivers/net/atl1e/atl1e.h b/drivers/net/atl1e/atl1e.h
index ba48220..490d3b3 100644
--- a/drivers/net/atl1e/atl1e.h
+++ b/drivers/net/atl1e/atl1e.h
@@ -377,10 +377,19 @@ struct atl1e_hw {
*/
struct atl1e_tx_buffer {
struct sk_buff *skb;
+ u16 flags;
+#define ATL1E_TX_PCIMAP_SINGLE 0x0001
+#define ATL1E_TX_PCIMAP_PAGE 0x0002
+#define ATL1E_TX_PCIMAP_TYPE_MASK 0x0003
u16 length;
dma_addr_t dma;
};
+#define ATL1E_SET_PCIMAP_TYPE(tx_buff, type) do { \
+ ((tx_buff)->flags) &= ~ATL1E_TX_PCIMAP_TYPE_MASK; \
+ ((tx_buff)->flags) |= (type); \
+ } while (0)
+
struct atl1e_rx_page {
dma_addr_t dma; /* receive rage DMA address */
u8 *addr; /* receive rage virtual address */
diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/atl1e/atl1e_main.c
index 69b830f..955da73 100644
--- a/drivers/net/atl1e/atl1e_main.c
+++ b/drivers/net/atl1e/atl1e_main.c
@@ -635,7 +635,11 @@ static void atl1e_clean_tx_ring(struct atl1e_adapter *adapter)
for (index = 0; index < ring_count; index++) {
tx_buffer = &tx_ring->tx_buffer[index];
if (tx_buffer->dma) {
- pci_unmap_page(pdev, tx_buffer->dma,
+ if (tx_buffer->flags & ATL1E_TX_PCIMAP_SINGLE)
+ pci_unmap_single(pdev, tx_buffer->dma,
+ tx_buffer->length, PCI_DMA_TODEVICE);
+ else if (tx_buffer->flags & ATL1E_TX_PCIMAP_PAGE)
+ pci_unmap_page(pdev, tx_buffer->dma,
tx_buffer->length, PCI_DMA_TODEVICE);
tx_buffer->dma = 0;
}
@@ -1220,7 +1224,11 @@ static bool atl1e_clean_tx_irq(struct atl1e_adapter *adapter)
while (next_to_clean != hw_next_to_clean) {
tx_buffer = &tx_ring->tx_buffer[next_to_clean];
if (tx_buffer->dma) {
- pci_unmap_page(adapter->pdev, tx_buffer->dma,
+ if (tx_buffer->flags & ATL1E_TX_PCIMAP_SINGLE)
+ pci_unmap_single(adapter->pdev, tx_buffer->dma,
+ tx_buffer->length, PCI_DMA_TODEVICE);
+ else if (tx_buffer->flags & ATL1E_TX_PCIMAP_PAGE)
+ pci_unmap_page(adapter->pdev, tx_buffer->dma,
tx_buffer->length, PCI_DMA_TODEVICE);
tx_buffer->dma = 0;
}
@@ -1741,6 +1749,7 @@ static void atl1e_tx_map(struct atl1e_adapter *adapter,
tx_buffer->length = map_len;
tx_buffer->dma = pci_map_single(adapter->pdev,
skb->data, hdr_len, PCI_DMA_TODEVICE);
+ ATL1E_SET_PCIMAP_TYPE(tx_buffer, ATL1E_TX_PCIMAP_SINGLE);
mapped_len += map_len;
use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma);
use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) |
@@ -1766,6 +1775,7 @@ static void atl1e_tx_map(struct atl1e_adapter *adapter,
tx_buffer->dma =
pci_map_single(adapter->pdev, skb->data + mapped_len,
map_len, PCI_DMA_TODEVICE);
+ ATL1E_SET_PCIMAP_TYPE(tx_buffer, ATL1E_TX_PCIMAP_SINGLE);
mapped_len += map_len;
use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma);
use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) |
@@ -1801,6 +1811,7 @@ static void atl1e_tx_map(struct atl1e_adapter *adapter,
(i * MAX_TX_BUF_LEN),
tx_buffer->length,
PCI_DMA_TODEVICE);
+ ATL1E_SET_PCIMAP_TYPE(tx_buffer, ATL1E_TX_PCIMAP_PAGE);
use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma);
use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) |
((cpu_to_le32(tx_buffer->length) &
^ permalink raw reply related
* RE: [Patch net-next]atl1e:fix 2.6.31-git4 -- ATL1E 0000:03:00.0: DMA-API: device driver frees DMA
From: Jie Yang @ 2009-09-16 9:31 UTC (permalink / raw)
To: Daniel Walker
Cc: davem@davemloft.net, miles.lane@gmail.com, chris.snook@gmail.com,
jcliburn@gmail.com, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <1253092251.11643.569.camel@desktop>
On Wednesday, September 16, 2009 5:11 PM
Daniel Walker <dwalker@fifo99.com> wrote:
> On Wed, 2009-09-16 at 14:21 +0800, jie.yang@atheros.com wrote:
> > - pci_unmap_page(pdev, tx_buffer->dma,
> > + if (tx_buffer->flags & ATL1E_TX_PCIMAP_SINGLE)
> > + pci_unmap_single(pdev, tx_buffer->dma,
> > + tx_buffer->length, PCI_DMA_TODEVICE);
> > + else if (tx_buffer->flags & ATL1E_TX_PCIMAP_PAGE)
> > + pci_unmap_page(pdev, tx_buffer->dma,
>
> Could you run this through checkpatch, and fix any errors if
> find? It looks like you uses spaces for tabs in the code
> above, maybe in the other block too..
>
> Daniel
>
>
ou, my mistake, just resend.
Best wishes
jie
^ permalink raw reply
* [PATCH 0/3] at91_can: add support for Atmel's CAN controller on AT91SAM9263
From: Marc Kleine-Budde @ 2009-09-16 9:46 UTC (permalink / raw)
To: netdev-u79uwXL29TY76Z2rM5mHXA
Cc: Socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
This patch series add support for Atmels's CAN controller as found
on the AT91SAM9263.
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 | 1177 ++++++++++++++++++++++++++++++
6 files changed, 1245 insertions(+), 0 deletions(-)
create mode 100644 drivers/net/can/at91_can.c
^ permalink raw reply
* [PATCH 2/3] at91sam9263ek: activate at91 CAN controller
From: Marc Kleine-Budde @ 2009-09-16 9:46 UTC (permalink / raw)
To: netdev-u79uwXL29TY76Z2rM5mHXA
Cc: Socketcan-core-0fE9KPoRgkgATYTw5x5z8w, Marc Kleine-Budde,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <1253094405-3216-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.3.3
^ permalink raw reply related
* [PATCH 1/3] at91sam9263: add at91_can device to generic device definition
From: Marc Kleine-Budde @ 2009-09-16 9:46 UTC (permalink / raw)
To: netdev; +Cc: linux-arm-kernel, Socketcan-core, Marc Kleine-Budde, Hans J. Koch
In-Reply-To: <1253094405-3216-1-git-send-email-mkl@pengutronix.de>
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);
--
1.6.3.3
^ permalink raw reply related
* [PATCH 3/3] at91_can: add driver for Atmel's CAN controller on AT91SAM9263
From: Marc Kleine-Budde @ 2009-09-16 9:46 UTC (permalink / raw)
To: netdev; +Cc: linux-arm-kernel, Socketcan-core, Marc Kleine-Budde
In-Reply-To: <1253094405-3216-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 | 1177 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 1184 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..b6d2af1 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 && 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..cd1e8cb
--- /dev/null
+++ b/drivers/net/can/at91_can.c
@@ -0,0 +1,1177 @@
+/*
+ * 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>
+ *
+ */
+
+#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 *)®_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.3.3
^ permalink raw reply related
* Re: [Patch net-next]atl1e:fix 2.6.31-git4 -- ATL1E 0000:03:00.0: DMA-API: device driver frees DMA
From: David Miller @ 2009-09-16 9:47 UTC (permalink / raw)
To: dwalker; +Cc: jie.yang, miles.lane, chris.snook, jcliburn, netdev, linux-kernel
In-Reply-To: <1253092251.11643.569.camel@desktop>
From: Daniel Walker <dwalker@fifo99.com>
Date: Wed, 16 Sep 2009 02:10:51 -0700
> On Wed, 2009-09-16 at 14:21 +0800, jie.yang@atheros.com wrote:
>> - pci_unmap_page(pdev, tx_buffer->dma,
>> + if (tx_buffer->flags & ATL1E_TX_PCIMAP_SINGLE)
>> + pci_unmap_single(pdev, tx_buffer->dma,
>> + tx_buffer->length, PCI_DMA_TODEVICE);
>> + else if (tx_buffer->flags & ATL1E_TX_PCIMAP_PAGE)
>> + pci_unmap_page(pdev, tx_buffer->dma,
>
> Could you run this through checkpatch, and fix any errors if find? It
> looks like you uses spaces for tabs in the code above, maybe in the
> other block too..
>
It's because of his email client, it corrupted the whole patch
like that.
^ permalink raw reply
* Re: fanotify as syscalls
From: Eric Paris @ 2009-09-16 9:48 UTC (permalink / raw)
To: Jamie Lokier
Cc: Linus Torvalds, Evgeniy Polyakov, David Miller, linux-kernel,
linux-fsdevel, netdev, viro, alan, hch
In-Reply-To: <20090916075219.GA22024@shareable.org>
On Wed, 2009-09-16 at 08:52 +0100, Jamie Lokier wrote:
> Eric Paris wrote:
> > On Tue, 2009-09-15 at 16:49 -0700, Linus Torvalds wrote:
> > > And btw, I still want to know what's so wonderful about fanotify that we
> > > would actually want yet-another-filesystem-notification-interface. So I'm
> > > not sayying that I'll take a system call interface.
> >
> > The real thing that fanotify provides is an open fd with the event
> > rather than some arbitrary 'watch descriptor' that userspace must
> > somehow magically map back to data on disk. This means that it could be
> > used to provide subtree notification, which inotify is completely
> > incapable of doing.
>
> That's a bit of a spurious claim.
My claim that a watch descriptor plus pathname segment sucks is
spurious? You've got to be kidding me. You think that a number which
represents the pathname of an object at some point in the past is a
reasonable piece of information? If a watch descriptor actually
provided any information about the object on which an event just
happened it would be useful. Sadly, it doesn't.
> - fanotify does not provide subtree notification in it's
> present form. When it is extended to do that, why wouldn't
> inotify be as well? That's an fsnotify feature, common to both.
Because I don't believe inotify can be reasonably extended in this way.
It's already clear that an arbitrary watch descriptor which userspace
has to somehow know how to correctly map back to an object (impossible
task) is difficult to use and I personally don't see how watch
descriptor + long path name component is somehow better or even
reasonable. Path names are such crap and passing a pathname to
userspace is really just telling userspace, something happened to
something that used to be at this location but is possibly long since
gone. I don't believe that's a good interface or one we should be
allowing to be {ab,}used.
> - fanotify does not provide notification at all for some events that
> you get with inotify. It is not a superset, so you can't use
> fanotify to provide a subtree-capable equivalent to inotify. What
> a mess when you need the combination of both features!
This is true, although where possible I plan to rectify this situation
on an ongoing basis. Absolutely nothing preventing that from happening.
> - fanotify requires you call readlink(/proc/fd/N) for every event to
> get the path.
And inotify requires magic. Which one sounds better?
> It's not a particularly efficient way to get it,
What is?
> especially when an apps wants to know if it's something in it's
> region of interest but doesn't care about the actual path.
> When an apps knows it needs the map back to to path, why make it
> slow to get it? That "extensible data format" is being
> underutilised...
You convince Al Viro that the vfs should give us a path name for an
arbitrary object that honestly might not have one and I'll consider
giving it to userspace in the event notification. Probably should read
some of the AppArmour arguments before you do though. You're asking for
something that's impossible and is at best incredibly race prone crap.
At worst is a total lie.
> - fanotify's descriptor may be race-prone as a way to get the subtree
> used for access, because any of the parent directories could have
> moved and even been deleted before the app calls
> readlink(/proc/fd/N). I don't know if a _reliable_ way to track
> changes in a subtree can be built on it. Maybe it can but it
> appears this hasn't been analysed. It depends on
> readlink(/proc/fd/N)'s behaviour when the dentry's have been
> changed, among other things.
Huh? Your saying that by the time userspace deals with an event it
might have moved? True. So what? Spurious and irrelevant. You got an
event that happened to this object. If subtree notification is added at
some later point you may get an event for an object that was in the
subtree and is now not in the subtree. That sounds fine to me....
> - Does the descriptor cause umount to fail when user does "do some
> stuff in baz; umount baz", or does it serialise nicely? That's one
> of inotify's nice features - it doesn't cause umounts to fail.
Ah yes, you didn't read the code. Seeing as how that's an fsnotify
property and fanotify notify is built on fsnotify....
> Seriously, what does system-wide fanotify do when run from a
> chroot/namespace/cgroup, and a file outside them is accessed?
At the moment an fanotify global listener is system wide. Truely system
wide. A gentleman from suse is looking rectify the problem so that if
run inside a namespace it stays inside the namespace. Note that this
particular little tidbit is not in the 8 patches I proposed. At the
moment those just include the UI and basic notification.
> If the event is delivered with file desciptor, that's a security hole.
> If it's not delivered, that sounds like working subtree support?
What?
> I'd expect anti-malware to want to be run inside VMs quite often...
What?
> Answer questions about use-cases that you're not interested in? Why
> block them? What about Evigny's request for an event without an open
> fd - because he needs the pid information (inotify doesn't provide)
> but not the fd?
It's not blocked, it's on the list of things to look at. It's a
relatively simple change to have the mark add code return a watch
descriptor and use that value instead of an fd. I believe I already
said that. It certainly doesn't seem like a merge blocker that some
other feature might come along one day. There's nothing preventing it
from coming out. "Here is a patch which implements TCP." "No, don't
merge that, it doesn't implement UDP as well." "WTF?"
> I'd like to be able to use it from some applications to accelerate
> userspace caching of things (faster Make, faster Samba) without
> penalising all other applications touching unrelated parts of the
> filesystem. The attitude "you can live with 10% slowdown" worries me.
> I'm sure that can be fixed with a bit of care.
I've said that using ANYTHING which allows userspace to arbitrate access
decisions for an entries system is going to eat performance. If you
can't handle that, don't build that damn userspace decision making
portion into your kernel! Don't buy anti-malware snake oil.
fanotify as a notification system isn't some performance monster here to
eat your babies. fanotify as an access control system is, and I can't
really do anything about that, it's the nature of that part of the
horrible beast. Lets not confuse things...
> If the intention is to maintain fanotify and inotify side-by-side for
> different uses (because fanotify returns open descriptors and blocks
> the accessing process until acked)
I know I've told you this before. fanotify provides TWO separate
things. Notification with a fd. A method to provide access control and
blocking. Lets not lead people to believe you can't you one without the
other. They are very distinct.
> , that's ok with me. It makes
> sense. But then it's messy that neither offers a superset of the
> other regarding which files and events are tracked.
inotify isn't going away any time soon....
> If it's right that inotify has no room for extensibility (I'm not sure
> about this), than it appears we already made a mess with dnotify and
> inotify, so it would be a shame to repeat the same mistakes again.
> Let's get the next one right, even it takes a bit longer, ok?
Calling inotify a "mess" or "completely inextensible" would probably be
too harsh. There are ways with inotify_init1() that we could provide a
better or more forward looking data format. But you are still left with
inotify's fatal flaw: userspace is required to map a random number to an
object in the filesystem. inotify starts with a reasonably impossible
premise and builds from there.
You show me anything about my proposal that limits any use case you have
in mind and I'll fix it. I'll fix it today. My proposal does what it
does very well and leaves the door open to build upon it for whatever
has been mentioned over the last 1.25 years I've been trying to get
comments. I'm certainly not going to wait until fanotify can leap out
of my computer and make a pot of coffee before I ask for it to be merged
(and no, it doesn't have that forward looking extensibility, I'll add a
syscall flag for it right now, O_COFFEE)
-Eric
^ permalink raw reply
* Re: [Patch net-next]atl1e:fix 2.6.31-git4 -- ATL1E 0000:03:00.0: DMA-API: device driver frees DMA
From: Cyrill Gorcunov @ 2009-09-16 9:51 UTC (permalink / raw)
To: David Miller
Cc: dwalker, jie.yang, miles.lane, chris.snook, jcliburn, netdev,
linux-kernel
In-Reply-To: <20090916.024759.51103835.davem@davemloft.net>
[David Miller - Wed, Sep 16, 2009 at 02:47:59AM -0700]
| From: Daniel Walker <dwalker@fifo99.com>
| Date: Wed, 16 Sep 2009 02:10:51 -0700
|
| > On Wed, 2009-09-16 at 14:21 +0800, jie.yang@atheros.com wrote:
| >> - pci_unmap_page(pdev, tx_buffer->dma,
| >> + if (tx_buffer->flags & ATL1E_TX_PCIMAP_SINGLE)
| >> + pci_unmap_single(pdev, tx_buffer->dma,
| >> + tx_buffer->length, PCI_DMA_TODEVICE);
| >> + else if (tx_buffer->flags & ATL1E_TX_PCIMAP_PAGE)
| >> + pci_unmap_page(pdev, tx_buffer->dma,
| >
| > Could you run this through checkpatch, and fix any errors if find? It
| > looks like you uses spaces for tabs in the code above, maybe in the
| > other block too..
| >
|
| It's because of his email client, it corrupted the whole patch
| like that.
well, client seems to be
| X-Mailer: git-send-email 1.5.2.2
more probably the text editor is the reason.
-- Cyrill
^ permalink raw reply
* RE: [Patch net-next]atl1e:fix 2.6.31-git4 -- ATL1E 0000:03:00.0: DMA-API: device driver frees DMA
From: Jie Yang @ 2009-09-16 9:54 UTC (permalink / raw)
To: Cyrill Gorcunov, David Miller
Cc: dwalker@fifo99.com, miles.lane@gmail.com, chris.snook@gmail.com,
jcliburn@gmail.com, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <20090916095138.GH5094@lenovo>
On Wednesday, September 16, 2009 5:52 PM
Cyrill Gorcunov <gorcunov@gmail.com> wrote:
> [David Miller - Wed, Sep 16, 2009 at 02:47:59AM -0700]
> | From: Daniel Walker <dwalker@fifo99.com>
> | Date: Wed, 16 Sep 2009 02:10:51 -0700
> |
> | > On Wed, 2009-09-16 at 14:21 +0800, jie.yang@atheros.com wrote:
> | >> - pci_unmap_page(pdev, tx_buffer->dma,
> | >> + if (tx_buffer->flags & ATL1E_TX_PCIMAP_SINGLE)
> | >> + pci_unmap_single(pdev, tx_buffer->dma,
> | >> + tx_buffer->length, PCI_DMA_TODEVICE);
> | >> + else if (tx_buffer->flags & ATL1E_TX_PCIMAP_PAGE)
> | >> + pci_unmap_page(pdev, tx_buffer->dma,
> | >
> | > Could you run this through checkpatch, and fix any errors
> if find?
> | > It looks like you uses spaces for tabs in the code above,
> maybe in
> | > the other block too..
> | >
> |
> | It's because of his email client, it corrupted the whole patch like
> | that.
>
> well, client seems to be
>
> | X-Mailer: git-send-email 1.5.2.2
>
> more probably the text editor is the reason.
>
> -- Cyrill
>
yes, the editor 'vi' have configed "set expandtab".
^ permalink raw reply
* Re: [PATCH 3/3] at91_can: add driver for Atmel's CAN controller on AT91SAM9263
From: Wolfgang Grandegger @ 2009-09-16 10:07 UTC (permalink / raw)
To: Marc Kleine-Budde
Cc: Socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
netdev-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <1253094405-3216-4-git-send-email-mkl-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
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-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
I already reviewed at91_can.c on the Socket-CAN ML and it's almost OK
from the Socket-CAN point of view. I just realized two minor issues:
> ---
> drivers/net/can/Kconfig | 6 +
> drivers/net/can/Makefile | 1 +
> drivers/net/can/at91_can.c | 1177 ++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 1184 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..b6d2af1 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 && ARCH_AT91SAM9263
It should depend on CAN_DEV because it used the CAN device driver interface.
> + ---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..cd1e8cb
> --- /dev/null
> +++ b/drivers/net/can/at91_can.c
> @@ -0,0 +1,1177 @@
> +/*
> + * at91_can.c - CAN network driver for AT91 SoC CAN controller
> + *
> + * (C) 2007 by Hans J. Koch <hjk-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
> + * (C) 2008, 2009 by Marc Kleine-Budde <kernel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> + *
> + * 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-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org>
This driver uses platform data. Could you please add some description on
how they should be used, e.g. like for the MCP251x:
* Your platform definition file should specify something like:
*
* static struct mcp251x_platform_data mcp251x_info = {
* .oscillator_frequency = 8000000,
* .board_specific_setup = &mcp251x_setup,
* .model = CAN_MCP251X_MCP2510,
* .power_enable = mcp251x_power_enable,
* .transceiver_enable = NULL,
* };
*
* static struct spi_board_info spi_board_info[] = {
* {
* .modalias = "mcp251x",
* .platform_data = &mcp251x_info,
* .irq = IRQ_EINT13,
* .max_speed_hz = 2*1000*1000,
* .chip_select = 2,
* },
* };
*
* Please see mcp251x.h for a description of the fields in
* struct mcp251x_platform_data.
I find that really useful.
Wolfgang.
^ permalink raw reply
* [PATCH] pkt_sched: Fix qstats.qlen updating in dump_stats
From: Jarek Poplawski @ 2009-09-16 10:38 UTC (permalink / raw)
To: David Miller; +Cc: Patrick McHardy, netdev
Some classful qdiscs miss qstats.qlen updating with q.qlen of their
child qdiscs in dump_stats methods.
Signed-off-by: Jarek Poplawski <jarkao2@gmail.com>
---
net/sched/sch_drr.c | 4 +++-
net/sched/sch_mq.c | 1 +
net/sched/sch_multiq.c | 1 +
net/sched/sch_prio.c | 1 +
4 files changed, 6 insertions(+), 1 deletions(-)
diff --git a/net/sched/sch_drr.c b/net/sched/sch_drr.c
index 12b2fb0..5a888af 100644
--- a/net/sched/sch_drr.c
+++ b/net/sched/sch_drr.c
@@ -274,8 +274,10 @@ static int drr_dump_class_stats(struct Qdisc *sch, unsigned long arg,
struct tc_drr_stats xstats;
memset(&xstats, 0, sizeof(xstats));
- if (cl->qdisc->q.qlen)
+ if (cl->qdisc->q.qlen) {
xstats.deficit = cl->deficit;
+ cl->qdisc->qstats.qlen = cl->qdisc->q.qlen;
+ }
if (gnet_stats_copy_basic(d, &cl->bstats) < 0 ||
gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 ||
diff --git a/net/sched/sch_mq.c b/net/sched/sch_mq.c
index dd5ee02..d44eddd 100644
--- a/net/sched/sch_mq.c
+++ b/net/sched/sch_mq.c
@@ -188,6 +188,7 @@ static int mq_dump_class_stats(struct Qdisc *sch, unsigned long cl,
struct netdev_queue *dev_queue = mq_queue_get(sch, cl);
sch = dev_queue->qdisc_sleeping;
+ sch->qstats.qlen = sch->q.qlen;
if (gnet_stats_copy_basic(d, &sch->bstats) < 0 ||
gnet_stats_copy_queue(d, &sch->qstats) < 0)
return -1;
diff --git a/net/sched/sch_multiq.c b/net/sched/sch_multiq.c
index 069f81c..7db2c88 100644
--- a/net/sched/sch_multiq.c
+++ b/net/sched/sch_multiq.c
@@ -359,6 +359,7 @@ static int multiq_dump_class_stats(struct Qdisc *sch, unsigned long cl,
struct Qdisc *cl_q;
cl_q = q->queues[cl - 1];
+ cl_q->qstats.qlen = cl_q->q.qlen;
if (gnet_stats_copy_basic(d, &cl_q->bstats) < 0 ||
gnet_stats_copy_queue(d, &cl_q->qstats) < 0)
return -1;
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c
index 0f73c41..93285ce 100644
--- a/net/sched/sch_prio.c
+++ b/net/sched/sch_prio.c
@@ -322,6 +322,7 @@ static int prio_dump_class_stats(struct Qdisc *sch, unsigned long cl,
struct Qdisc *cl_q;
cl_q = q->queues[cl - 1];
+ cl_q->qstats.qlen = cl_q->q.qlen;
if (gnet_stats_copy_basic(d, &cl_q->bstats) < 0 ||
gnet_stats_copy_queue(d, &cl_q->qstats) < 0)
return -1;
^ permalink raw reply related
* Re: fanotify as syscalls
From: Alan Cox @ 2009-09-16 10:41 UTC (permalink / raw)
To: Jamie Lokier
Cc: Eric Paris, Linus Torvalds, Evgeniy Polyakov, David Miller,
linux-kernel, linux-fsdevel, netdev, viro, hch
In-Reply-To: <20090916075219.GA22024@shareable.org>
> - fanotify does not provide subtree notification in it's
> present form. When it is extended to do that, why wouldn't
> inotify be as well? That's an fsnotify feature, common to both.
Because inotify gives you no reliable access to the object monitored as
the name passed back is not an object reference and is racy. Inotify is
fine for making pretty icons pop up on desktops and making file
selectors update, but it is somewhat inadequate for indexers and
completely useless for stuff like HSM.
> - fanotify requires you call readlink(/proc/fd/N) for every event to
> get the path. It's not a particularly efficient way to get it,
IFF you want the path, but the path isn't usually the most valuable bit.
Plus you'll find the readlink is extremely quick anyway.
> People who want to break out of chroot/namespace jails using the
> conveniently provided open file descriptor? :-)
chroot isn't a security model. You can already do this with AF_UNIX
sockets (and there are apps that intentionally use fchdir that way)
> I'd expect anti-malware to want to be run inside VMs quite often...
Inside of containers - unlikely. Inside of guests sure but thats not
going to relevant to fanotify()
> the accessing process until acked), that's ok with me. It makes
> sense. But then it's messy that neither offers a superset of the
> other regarding which files and events are tracked.
Agreed.
^ permalink raw reply
* Re: [PATCH 3/3] at91_can: add driver for Atmel's CAN controller on AT91SAM9263
From: Marc Kleine-Budde @ 2009-09-16 10:47 UTC (permalink / raw)
To: Wolfgang Grandegger; +Cc: netdev, Socketcan-core, linux-arm-kernel
In-Reply-To: <4AB0B8F4.50301@grandegger.com>
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Wolfgang Grandegger wrote:
> 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>
>
> I already reviewed at91_can.c on the Socket-CAN ML and it's almost OK
> from the Socket-CAN point of view. I just realized two minor issues:
>
>> ---
>> drivers/net/can/Kconfig | 6 +
>> drivers/net/can/Makefile | 1 +
>> drivers/net/can/at91_can.c | 1177 ++++++++++++++++++++++++++++++++++++++++++++
>> 3 files changed, 1184 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..b6d2af1 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 && ARCH_AT91SAM9263
>
> It should depend on CAN_DEV because it used the CAN device driver interface.
will fix
>
>> + ---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..cd1e8cb
>> --- /dev/null
>> +++ b/drivers/net/can/at91_can.c
>> @@ -0,0 +1,1177 @@
>> +/*
>> + * 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>
>
> This driver uses platform data. Could you please add some description on
> how they should be used, e.g. like for the MCP251x:
>
> * Your platform definition file should specify something like:
> *
> * static struct mcp251x_platform_data mcp251x_info = {
> * .oscillator_frequency = 8000000,
> * .board_specific_setup = &mcp251x_setup,
> * .model = CAN_MCP251X_MCP2510,
> * .power_enable = mcp251x_power_enable,
> * .transceiver_enable = NULL,
> * };
> *
> * static struct spi_board_info spi_board_info[] = {
> * {
> * .modalias = "mcp251x",
> * .platform_data = &mcp251x_info,
> * .irq = IRQ_EINT13,
> * .max_speed_hz = 2*1000*1000,
> * .chip_select = 2,
> * },
> * };
> *
> * Please see mcp251x.h for a description of the fields in
> * struct mcp251x_platform_data.
>
> I find that really useful.
good point, I'll add a help text
tnx for the review,
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
iEYEARECAAYFAkqwwecACgkQjTAFq1RaXHNb9wCfTQ18W790/Bqsk8gEVWYnxsL6
sTkAmgNF3KzD8ics9UwemxHEi/HE4jIM
=pyRS
-----END PGP SIGNATURE-----
^ permalink raw reply
* Re: [PATCH 3/3] at91_can: add driver for Atmel's CAN controller on AT91SAM9263
From: Marc Kleine-Budde @ 2009-09-16 10:45 UTC (permalink / raw)
To: Wolfgang Grandegger; +Cc: netdev, Socketcan-core, linux-arm-kernel
In-Reply-To: <4AB0B8F4.50301@grandegger.com>
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Wolfgang Grandegger wrote:
> 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>
>
> I already reviewed at91_can.c on the Socket-CAN ML and it's almost OK
> from the Socket-CAN point of view. I just realized two minor issues:
>
>> ---
>> drivers/net/can/Kconfig | 6 +
>> drivers/net/can/Makefile | 1 +
>> drivers/net/can/at91_can.c | 1177 ++++++++++++++++++++++++++++++++++++++++++++
>> 3 files changed, 1184 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..b6d2af1 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 && ARCH_AT91SAM9263
>
> It should depend on CAN_DEV because it used the CAN device driver interface.
will fix
>
>> + ---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..cd1e8cb
>> --- /dev/null
>> +++ b/drivers/net/can/at91_can.c
>> @@ -0,0 +1,1177 @@
>> +/*
>> + * 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>
>
> This driver uses platform data. Could you please add some description on
> how they should be used, e.g. like for the MCP251x:
>
> * Your platform definition file should specify something like:
> *
> * static struct mcp251x_platform_data mcp251x_info = {
> * .oscillator_frequency = 8000000,
> * .board_specific_setup = &mcp251x_setup,
> * .model = CAN_MCP251X_MCP2510,
> * .power_enable = mcp251x_power_enable,
> * .transceiver_enable = NULL,
> * };
> *
> * static struct spi_board_info spi_board_info[] = {
> * {
> * .modalias = "mcp251x",
> * .platform_data = &mcp251x_info,
> * .irq = IRQ_EINT13,
> * .max_speed_hz = 2*1000*1000,
> * .chip_select = 2,
> * },
> * };
> *
> * Please see mcp251x.h for a description of the fields in
> * struct mcp251x_platform_data.
>
> I find that really useful.
good point, I'll add a help text
tnx for the review,
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
iEYEARECAAYFAkqwwecACgkQjTAFq1RaXHNb9wCfTQ18W790/Bqsk8gEVWYnxsL6
sTkAmgNF3KzD8ics9UwemxHEi/HE4jIM
=pyRS
-----END PGP SIGNATURE-----
^ permalink raw reply
* Re: fanotify as syscalls
From: Arnd Bergmann @ 2009-09-16 11:30 UTC (permalink / raw)
To: Eric Paris
Cc: Evgeniy Polyakov, Jamie Lokier, David Miller, linux-kernel,
linux-fsdevel, netdev, viro, alan, hch, torvalds
In-Reply-To: <1253051699.5213.18.camel@dhcp231-106.rdu.redhat.com>
On Tuesday 15 September 2009, Eric Paris wrote:
> fanotify_modify_mark_at() --- like inotify_add_watch and rm_watch
> fanotify_modify_mark_fd() --- same but with an fd instead of a path
I think these two can be merged into one without adding complexity,
in the same way that sys_utimensat can take a file descriptor or
a path or both.
> fanotify_response() --- userspace tells the kernel what to do if requested/allowed
> (could probably be done using write() to the fanotify fd)
> fanotify_exclude() --- a horrid syscall which might be better as an ioctl since it isn't strongly typed....
Please don't use an ioctl here. While ioctl is fine for character devices
and sort of fine for sockets, I think it would be very bad style to use
it on file descriptors that you get back from specialized syscalls like
fanotify_init. Do one or the other, but do it consistently.
Why is it not strongly typed anyway? Something like
int fanotify_ignore_sb(int fanotify_fd, unsigned int flag,
long f_type, fsid_t f_fsid);
would be type safe, although I think it would be better to only handle
one of the two cases. Can you think of a case that you can't handle if
you have to decide between them and only do one interface (f_type or fsid)?
Arnd <><
^ permalink raw reply
* Re: fanotify as syscalls
From: Jamie Lokier @ 2009-09-16 11:41 UTC (permalink / raw)
To: Alan Cox
Cc: Eric Paris, Linus Torvalds, Evgeniy Polyakov, David Miller,
linux-kernel, linux-fsdevel, netdev, viro, hch
In-Reply-To: <20090916114111.2228f0fc@linux.intel.com>
Alan Cox wrote:
> > - fanotify does not provide subtree notification in it's
> > present form. When it is extended to do that, why wouldn't
> > inotify be as well? That's an fsnotify feature, common to both.
>
> Because inotify gives you no reliable access to the object monitored as
> the name passed back is not an object reference and is racy. Inotify is
> fine for making pretty icons pop up on desktops and making file
> selectors update, but it is somewhat inadequate for indexers and
> completely useless for stuff like HSM.
That was my point. (Why do people keep not getting it?)
You can't rely on the name being non-racy, but you _can_ reliably
invalidate application-level caches from the sequence of events
including file writes, creates, renames, links, unlinks, mounts. And
revalidate such caches by the absence of pending events.
(There is one obscure case which inotify is missing, though, which
means it cannot detect file changes in certain cases with hard links.
I intend to fix that one.)
For that, an inode isn't useful, a descriptor isn't useful, a
directory descriptor/inode and pathname isn't useful, and file write
events by themselves aren't useful. None of them quite do it by
themselves.
But with the correct combination of events, you can maintain very
efficient application-level caching of file data / directory listing
and lookups / stat results you have previously read from the
filesystem. That's because the information you have previously
depended upon, including path lookups, are all notified as one sort of
inotify event or another when changed.
Which doesn't sound all that special until you realise you can very
quickly revalidate application-caches of any data structure calculated
from reading things from the filesystem, no matter how many
prerequisites or how complex the data structures, in a single system
call. Amortised over many revalidations if you have them in parallel.
That can apply to things like git, make, ccache, samba, rsync, httpd
path walks, and virtually any "web templating" framework. Of course
it takes userspace support as well, but that's where I'm coming from
regarding "acceleration" and the essential kernel infrastructure.
Clearly, I'm going to have to explain with working code :-)
> but it is somewhat inadequate for indexers
For indexers, the real inadequacy is the need to attach inotify
watches to every directory at system startup, and to stat() everything
to check it hasn't changed since the indexer was last running. Both
are very slow on a large directory tree. The former can be dealt with
using subtree watches (yes, even with hard links - I have proposed an
algorithm for this but I think nobody understood it ;-). The latter
needs filesystem support for a persistent change attribute.
> > - fanotify requires you call readlink(/proc/fd/N) for every event to
> > get the path. It's not a particularly efficient way to get it,
>
> IFF you want the path, but the path isn't usually the most valuable bit.
> Plus you'll find the readlink is extremely quick anyway.
I agree, you don't usually want the whole path.
So what was the point about fanotify making subtree tracking possible
with it's file descriptor, if not by readlink(/proc/fd/N)?
Descriptors don't tell you which subtree a file is in any better than
inotify watches. I.e. they do, if you track them and their containing
directories all individually.
> > People who want to break out of chroot/namespace jails using the
> > conveniently provided open file descriptor? :-)
>
> chroot isn't a security model. You can already do this with AF_UNIX
> sockets (and there are apps that intentionally use fchdir that way)
Ah, no. AF_UNIX works with explicit sender cooperation.
fanotify gives you access to files without sender cooperation, as it
intercepts every open().
> > I'd expect anti-malware to want to be run inside VMs quite often...
>
> Inside of containers - unlikely.
Why not? Some people run entire distributions in containiners, and
present them as VMs to the world for other people to admin.
> > the accessing process until acked), that's ok with me. It makes
> > sense. But then it's messy that neither offers a superset of the
> > other regarding which files and events are tracked.
>
> Agreed.
In the end this is my main gripe.
-- Jamie
^ permalink raw reply
* Re: [PATCHv5 3/3] vhost_net: a kernel-level virtio server
From: Gregory Haskins @ 2009-09-16 11:44 UTC (permalink / raw)
To: Avi Kivity
Cc: 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: <4AB0A070.1050400@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 5873 bytes --]
Avi Kivity wrote:
> On 09/15/2009 11:08 PM, Gregory Haskins wrote:
>>
>>> There's virtio-console, virtio-blk etc. None of these have kernel-mode
>>> servers, but these could be implemented if/when needed.
>>>
>> IIUC, Ira already needs at least ethernet and console capability.
>>
>>
>
> He's welcome to pick up the necessary code from qemu.
The problem isn't where to find the models...the problem is how to
aggregate multiple models to the guest.
>
>>>> b) what do you suppose this protocol to aggregate the connections would
>>>> look like? (hint: this is what a vbus-connector does).
>>>>
>>>>
>>> You mean multilink? You expose the device as a multiqueue.
>>>
>> No, what I mean is how do you surface multiple ethernet and consoles to
>> the guests? For Ira's case, I think he needs at minimum at least one of
>> each, and he mentioned possibly having two unique ethernets at one point.
>>
>
> You instantiate multiple vhost-nets. Multiple ethernet NICs is a
> supported configuration for kvm.
But this is not KVM.
>
>> His slave boards surface themselves as PCI devices to the x86
>> host. So how do you use that to make multiple vhost-based devices (say
>> two virtio-nets, and a virtio-console) communicate across the transport?
>>
>
> I don't really see the difference between 1 and N here.
A KVM surfaces N virtio-devices as N pci-devices to the guest. What do
we do in Ira's case where the entire guest represents itself as a PCI
device to the host, and nothing the other way around?
>
>> There are multiple ways to do this, but what I am saying is that
>> whatever is conceived will start to look eerily like a vbus-connector,
>> since this is one of its primary purposes ;)
>>
>
> I'm not sure if you're talking about the configuration interface or data
> path here.
I am talking about how we would tunnel the config space for N devices
across his transport.
As an aside, the vbus-kvm connector makes them one and the same, but
they do not have to be. Its all in the connector design.
>
>>>> c) how do you manage the configuration, especially on a per-board
>>>> basis?
>>>>
>>>>
>>> pci (for kvm/x86).
>>>
>> Ok, for kvm understood (and I would also add "qemu" to that mix). But
>> we are talking about vhost's application in a non-kvm environment here,
>> right?.
>>
>> So if the vhost-X devices are in the "guest",
>
> They aren't in the "guest". The best way to look at it is
>
> - a device side, with a dma engine: vhost-net
> - a driver side, only accessing its own memory: virtio-net
>
> Given that Ira's config has the dma engine in the ppc boards, that's
> where vhost-net would live (the ppc boards acting as NICs to the x86
> board, essentially).
That sounds convenient given his hardware, but it has its own set of
problems. For one, the configuration/inventory of these boards is now
driven by the wrong side and has to be addressed. Second, the role
reversal will likely not work for many models other than ethernet (e.g.
virtio-console or virtio-blk drivers running on the x86 board would be
naturally consuming services from the slave boards...virtio-net is an
exception because 802.x is generally symmetrical).
IIUC, vbus would support having the device models live properly on the
x86 side, solving both of these problems. It would be impossible to
reverse vhost given its current design.
>
>> and the x86 board is just
>> a slave...How do you tell each ppc board how many devices and what
>> config (e.g. MACs, etc) to instantiate? Do you assume that they should
>> all be symmetric and based on positional (e.g. slot) data? What if you
>> want asymmetric configurations (if not here, perhaps in a different
>> environment)?
>>
>
> I have no idea, that's for Ira to solve.
Bingo. Thus my statement that the vhost proposal is incomplete. You
have the virtio-net and vhost-net pieces covering the fast-path
end-points, but nothing in the middle (transport, aggregation,
config-space), and nothing on the management-side. vbus provides most
of the other pieces, and can even support the same virtio-net protocol
on top. The remaining part would be something like a udev script to
populate the vbus with devices on board-insert events.
> If he could fake the PCI
> config space as seen by the x86 board, he would just show the normal pci
> config and use virtio-pci (multiple channels would show up as a
> multifunction device). Given he can't, he needs to tunnel the virtio
> config space some other way.
Right, and note that vbus was designed to solve this. This tunneling
can, of course, be done without vbus using some other design. However,
whatever solution is created will look incredibly close to what I've
already done, so my point is "why reinvent it"?
>
>>> Yes. virtio is really virtualization oriented.
>>>
>> I would say that its vhost in particular that is virtualization
>> oriented. virtio, as a concept, generally should work in physical
>> systems, if perhaps with some minor modifications. The biggest "limit"
>> is having "virt" in its name ;)
>>
>
> Let me rephrase. The virtio developers are virtualization oriented. If
> it works for non-virt applications, that's good, but not a design goal.
>
Fair enough. Vbus was designed to support both HW and virt (as well as
other models, like containers), including tunneling virtio within those
environments. That is probably why IMO vbus is a better fit than vhost
here. (FWIW: I would love to see vhost use the vbus framework, then we
all win. You can do this and still retain virtio-pci compatiblity (at
least theoretically). I am still open to working with the team on this).
Kind Regards,
-Greg
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 267 bytes --]
^ permalink raw reply
* [PATCH] ipv6: Log the affected address when DAD failure occurs
From: Jens Rosenboom @ 2009-09-16 11:44 UTC (permalink / raw)
To: Linux Network Developers
From: Jens Rosenboom <me@jayr.de>
If an interface has multiple addresses, the current message for DAD
failure isn't really helpful, so this patch adds the address itself to
the printk.
Signed-off-by: Jens Rosenboom <me@jayr.de>
---
This is a resubmit of http://patchwork.ozlabs.org/patch/31196/ which
erroneously was marked as superseded, but using the new compact output format.
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index c9b3690..907a6f7 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1405,8 +1405,8 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp)
struct inet6_dev *idev = ifp->idev;
if (net_ratelimit())
- printk(KERN_INFO "%s: IPv6 duplicate address detected!\n",
- ifp->idev->dev->name);
+ printk(KERN_INFO "%s: IPv6 duplicate address %pI6c detected!\n",
+ ifp->idev->dev->name, &ifp->addr);
if (idev->cnf.accept_dad > 1 && !idev->cnf.disable_ipv6) {
struct in6_addr addr;
^ permalink raw reply related
* Re: Fwd: [RFC v3] net: Introduce recvmmsg socket syscall
From: Arnaldo Carvalho de Melo @ 2009-09-16 11:52 UTC (permalink / raw)
To: Simon Horman
Cc: Arnaldo Carvalho de Melo, Nir Tzachar,
Linux Networking Development Mailing List, Ziv Ayalon
In-Reply-To: <20090916045333.GA18325@verge.net.au>
Em Wed, Sep 16, 2009 at 02:53:44PM +1000, Simon Horman escreveu:
> On Tue, Sep 15, 2009 at 05:52:07PM -0300, Arnaldo Carvalho de Melo wrote:
> > Em Tue, Sep 15, 2009 at 09:20:13PM +0300, Nir Tzachar escreveu:
> > > >> Setup:
> > > >> linux 2.6.29.2 with the third version of the patch, running on an
> > > >> Intel Xeon X3220 2.4GHz quad core, with 4Gbyte of ram, running Ubuntu
> > > >> 9.04
> > > >
> > > > Which NIC? 10 Gbit/s?
> > >
> > > 1G. We do not care as much for throughput as we do about latency...
> >
> > OK, but anyway the 10 Gbit/s cards I've briefly played with all
> > exhibited lower latencies than all 1 gbit/s ones, in fact I've heard
> > about people moving to 10 Gbit/s not for the bw, but for the lower
> > latencies :-)
>
> Hi Arnaldo,
>
> Out of curiosity, is that using a 10Gbit card with
> a 10Gbit link or a 1Gbit link?
Its been a while, but most details should be publicly available here:
http://www.stacresearch.com/node/4211
- Arnaldo
^ permalink raw reply
* Re: fanotify as syscalls
From: Alan Cox @ 2009-09-16 12:01 UTC (permalink / raw)
To: Jamie Lokier
Cc: Alan Cox, Eric Paris, Linus Torvalds, Evgeniy Polyakov,
David Miller, linux-kernel, linux-fsdevel, netdev, viro, hch
In-Reply-To: <20090916114107.GB29359@shareable.org>
> You can't rely on the name being non-racy, but you _can_ reliably
> invalidate application-level caches from the sequence of events
> including file writes, creates, renames, links, unlinks, mounts. And
> revalidate such caches by the absence of pending events.
You can't however create the caches reliably because you've no idea if
you are referencing the right object in the first place - which is why
you want a handle in these cases. I see fanotify as a handle producing
addition to inotify, not as a replacement (plus some other bits around
open blocking for HSM etc)
> Clearly, I'm going to have to explain with working code :-)
Always a good demo
> > but it is somewhat inadequate for indexers
>
> For indexers, the real inadequacy is the need to attach inotify
> watches to every directory at system startup, and to stat() everything
> to check it hasn't changed since the indexer was last running. Both
stat doesn't help you - inode numbers are only guaranteed unqiue (and
constant) while a reference to the object is held.
> Descriptors don't tell you which subtree a file is in any better than
> inotify watches. I.e. they do, if you track them and their containing
> directories all individually.
Don't get me wrong - I don't think fanotify is sufficient on its own -
and this is one reason. Some things care about the namespace, some about
getting the exact content.
> > chroot isn't a security model. You can already do this with AF_UNIX
> > sockets (and there are apps that intentionally use fchdir that way)
>
> Ah, no. AF_UNIX works with explicit sender cooperation.
>
> fanotify gives you access to files without sender cooperation, as it
> intercepts every open().
and is currently not general user accessible for this reason.
> > Inside of containers - unlikely.
>
> Why not? Some people run entire distributions in containiners, and
> present them as VMs to the world for other people to admin.
In a word - performance. In two words performance and security. It isn't
a sensible setup because you want to scan the most efficient way possible
and you want to keep your malware scan as far away from attackers, so it
makes sense to keep it outside of the containers and do the job once
- one scan, one database of things to keep current.
Alan
^ permalink raw reply
* [PATCH V3 0/2 -next] ems_usb: Added support for EMS CPC-USB/ARM7 CAN interface
From: Sebastian Haas @ 2009-09-16 12:04 UTC (permalink / raw)
To: netdev-u79uwXL29TY76Z2rM5mHXA
Cc: socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
greg-U8xfFu+wG4EAvxtiuMwx3w, davem-fT/PcQaiUtIeIZ0/mPfg9Q,
wg-5Yr1BZd7O62+XT7JhA+gdA
The following series replaces the staging driver cpc-usb with the newly written
ems_usb CAN driver.
---
Sebastian Haas (2):
ems_usb: Added support for EMS CPC-USB/ARM7 CAN/USB interface
cpc-usb: Removed driver from staging tree
drivers/net/can/Kconfig | 7
drivers/net/can/Makefile | 2
drivers/net/can/usb/Makefile | 5
drivers/net/can/usb/ems_usb.c | 1151 ++++++++++++++++++++++++++++++++
drivers/staging/Kconfig | 2
drivers/staging/Makefile | 1
drivers/staging/cpc-usb/Kconfig | 4
drivers/staging/cpc-usb/Makefile | 3
drivers/staging/cpc-usb/TODO | 9
drivers/staging/cpc-usb/cpc-usb_drv.c | 1185 ---------------------------------
drivers/staging/cpc-usb/cpc.h | 440 ------------
drivers/staging/cpc-usb/cpc_int.h | 83 --
drivers/staging/cpc-usb/cpcusb.h | 86 --
drivers/staging/cpc-usb/sja2m16c.h | 41 -
drivers/staging/cpc-usb/sja2m16c_2.c | 452 -------------
15 files changed, 1165 insertions(+), 2306 deletions(-)
create mode 100644 drivers/net/can/usb/Makefile
create mode 100644 drivers/net/can/usb/ems_usb.c
delete mode 100644 drivers/staging/cpc-usb/Kconfig
delete mode 100644 drivers/staging/cpc-usb/Makefile
delete mode 100644 drivers/staging/cpc-usb/TODO
delete mode 100644 drivers/staging/cpc-usb/cpc-usb_drv.c
delete mode 100644 drivers/staging/cpc-usb/cpc.h
delete mode 100644 drivers/staging/cpc-usb/cpc_int.h
delete mode 100644 drivers/staging/cpc-usb/cpcusb.h
delete mode 100644 drivers/staging/cpc-usb/sja2m16c.h
delete mode 100644 drivers/staging/cpc-usb/sja2m16c_2.c
--
Cheers, Sebastian
--
EMS Dr. Thomas Wuensche e.K.
Sonnenhang 3
85304 Ilmmuenster
HRA Neuburg a.d. Donau, HR-Nr. 70.106
Phone: +49-8441-490260
Fax : +49-8441-81860
http://www.ems-wuensche.com
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox