* [PATCH] net/unix: Allow Unix sockets to be treated like normal files. (round 2)
From: Jeff Hansen @ 2010-10-25 4:59 UTC (permalink / raw)
To: netdev; +Cc: x, Dave Miller
This allows Unix sockets to be opened, written, read, and closed, like normal
files. This can be especially handy from, for example, a shell script that
wants to send a short message to a Unix socket, but doesn't want to and/or
cannot create the socket itself.
This will try to open the Unix socket first in SOCK_DGRAM mode, then
SOCK_STREAM mode if that fails.
Signed-off-by: Jeff Hansen <x@jeffhansen.com>
---
net/unix/Kconfig | 10 +++++
net/unix/af_unix.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 114 insertions(+), 0 deletions(-)
diff --git a/net/unix/Kconfig b/net/unix/Kconfig
index 5a69733..68df4f1 100644
--- a/net/unix/Kconfig
+++ b/net/unix/Kconfig
@@ -19,3 +19,13 @@ config UNIX
Say Y unless you know what you are doing.
+config UNIX_FOPS
+ boolean "Allow Unix sockets to be treated like normal files"
+ depends on UNIX
+ ---help---
+ If you say Y here, Unix sockets may be opened, written, read, and
+ closed, like normal files. This is handy for sending short commands
+ to Unix sockets (i.e. from shell scripts), without having to create
+ a Unix socket.
+
+ Say Y unless you know what you are doing.
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 0ebc777..feb5877 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -798,6 +798,105 @@ fail:
return NULL;
}
+#ifdef CONFIG_UNIX_FOPS
+static int unix_open(struct inode *inode, struct file *filp)
+{
+ int err;
+ struct socket *sock = NULL;
+ struct dentry *dentry = filp->f_dentry;
+ struct sockaddr_un sunaddr = { 0 };
+ char *p;
+
+ if (!filp)
+ return -ENXIO;
+ dentry = filp->f_dentry;
+
+ if (!dentry || !dentry->d_parent)
+ return -ENXIO;
+
+ if (filp->private_data)
+ return -EBUSY;
+
+ sunaddr.sun_family = AF_UNIX;
+ p = d_path(&filp->f_path, sunaddr.sun_path, sizeof(sunaddr.sun_path));
+ if (IS_ERR(p))
+ return PTR_ERR(p);
+ memmove(sunaddr.sun_path, p, p[sizeof(sunaddr.sun_path) - 1] ?
+ sizeof(sunaddr.sun_path) : strlen(p));
+
+ err = sock_create(PF_UNIX, SOCK_DGRAM, 0, &sock);
+ if (err)
+ return err;
+
+ err = unix_dgram_connect(sock, (struct sockaddr *)&sunaddr,
+ sizeof(sunaddr), 0);
+ if (err) {
+ sock_release(sock);
+
+ err = sock_create(PF_UNIX, SOCK_STREAM, 0, &sock);
+ if (err)
+ return err;
+
+ err = unix_stream_connect(sock, (struct sockaddr *)&sunaddr,
+ sizeof(sunaddr), 0);
+
+ if (err)
+ return err;
+ }
+ filp->private_data = sock;
+
+ return err;
+}
+
+static int unix_frelease(struct inode *inode, struct file *filp)
+{
+ if (!filp->private_data)
+ return -ENXIO;
+
+ sock_release(filp->private_data);
+ filp->private_data = NULL;
+ return 0;
+}
+
+#define DECLARE_UNIX_FOP(name, buf_mod, fop) \
+static ssize_t name(struct file *filp, buf_mod char __user *buf, \
+ size_t _len, loff_t *ppos) \
+{ \
+ struct socket *sock = filp->private_data; \
+ int len = (int)_len, err; \
+ struct kvec iov = { \
+ .iov_base = (void *)buf, \
+ .iov_len = len, \
+ }; \
+ struct msghdr msg = { \
+ /* NB: struct iovec and kvec are equal */ \
+ .msg_iov = (struct iovec *)&iov, \
+ .msg_iovlen = 1, \
+ }; \
+\
+ if (!sock) \
+ return -ENXIO; \
+ if (_len > 0xffffffffLL) \
+ return -E2BIG; \
+\
+ err = fop; \
+ if (err > 0 && ppos) \
+ *ppos += err; \
+\
+ return err; \
+}
+
+DECLARE_UNIX_FOP(unix_write, const, sock_sendmsg(sock, &msg, len))
+DECLARE_UNIX_FOP(unix_read, , sock_recvmsg(sock, &msg, len, 0))
+
+const struct file_operations unix_sock_fops = {
+ .owner = THIS_MODULE,
+ .open = unix_open,
+ .release = unix_frelease,
+ .write = unix_write,
+ .read = unix_read,
+};
+#endif /* CONFIG_UNIX_FOPS */
static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
{
@@ -874,6 +973,11 @@ out_mknod_drop_write:
mnt_drop_write(nd.path.mnt);
if (err)
goto out_mknod_dput;
+
+#ifdef CONFIG_UNIX_FOPS
+ dentry->d_inode->i_fop = &unix_sock_fops;
+#endif
+
mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
dput(nd.path.dentry);
nd.path.dentry = dentry;
--
1.7.0.4
^ permalink raw reply related
* Re: linux-next: build failure after merge of the final tree (net-current tree related)
From: David Miller @ 2010-10-25 5:26 UTC (permalink / raw)
To: sfr; +Cc: netdev, linux-next, linux-kernel, shemminger, jchapman
In-Reply-To: <20101025141956.d8f0888f.sfr@canb.auug.org.au>
From: Stephen Rothwell <sfr@canb.auug.org.au>
Date: Mon, 25 Oct 2010 14:19:56 +1100
> I wish doing that caused a build failure on other architectures ...
Me too :-/
> Subject: [PATCH] l2tp: static functions should not be exported
I'll add this thanks Stephen.
^ permalink raw reply
* Re: [Security] TIPC security issues
From: David Miller @ 2010-10-25 5:28 UTC (permalink / raw)
To: torvalds; +Cc: drosenberg, jon.maloy, allan.stephens, netdev, security
In-Reply-To: <AANLkTinXmKrf+wovco0j_aBuB7=qSq42+bVCM-amfL7W@mail.gmail.com>
From: Linus Torvalds <torvalds@linux-foundation.org>
Date: Sun, 24 Oct 2010 20:42:39 -0700
> David - the issue is _security_. The way to fix security problems is
> not to say "most things handle this correctly". The way to avoid them
> is to have several layers of handling things correctly, so that even
> when one turns out to be broken, the others still protect it.
Fair enough.
^ permalink raw reply
* Re: [PATCH net-next-2.6 v1] can: Topcliff: Update PCH_CAN driver to 2.6.35
From: Marc Kleine-Budde @ 2010-10-25 6:37 UTC (permalink / raw)
To: socketcan-core-0fE9KPoRgkgATYTw5x5z8w
Cc: Andrew ", Samuel Ortiz, margie.foster-ral2JQCrhuEAvxtiuMwx3w,
Linux Netdev List, Wang Yong Y ", Masayuki Ohtak,
kok.howg.ewe-ral2JQCrhuEAvxtiuMwx3w, Tomoya MORINAGA,
joel.clark-ral2JQCrhuEAvxtiuMwx3w, Wang Qi "
In-Reply-To: <4CB8506C.3060600-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>
[-- Attachment #1.1: Type: text/plain, Size: 50691 bytes --]
Hello Masayuki,
here again, the review. I only replied to the socketcan mailinglist.
Here again to (hopefully) everyone who's interested.
On 10/15/2010 03:00 PM, Masayuki Ohtak wrote:
> Hi Wolfgang,
>
> We have modified for your indications.
> Please check below.
The driver looks better each time, some comments inline.
cheers, Marc
> ---
> CAN driver of Topcliff PCH
>
> Topcliff PCH is the platform controller hub that is going to be used in
> Intel's upcoming general embedded platform. All IO peripherals in
> Topcliff PCH are actually devices sitting on AMBA bus.
> Topcliff PCH has CAN I/F. This driver enables CAN function.
>
> Signed-off-by: Masayuki Ohtake <masa-korg-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>
> ---
> drivers/net/can/Kconfig | 8 +
> drivers/net/can/Makefile | 1 +
> drivers/net/can/pch_can.c | 1463 +++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 1472 insertions(+), 0 deletions(-)
> create mode 100644 drivers/net/can/pch_can.c
>
> diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
> index 2c5227c..5c98a20 100644
> --- a/drivers/net/can/Kconfig
> +++ b/drivers/net/can/Kconfig
> @@ -73,6 +73,14 @@ config CAN_JANZ_ICAN3
> This driver can also be built as a module. If so, the module will be
> called janz-ican3.ko.
>
> +config PCH_CAN
> + tristate "PCH CAN"
> + depends on CAN_DEV
> + ---help---
> + This driver is for PCH CAN of Topcliff which is an IOH for x86
> + embedded processor.
> + This driver can access CAN bus.
> +
> source "drivers/net/can/mscan/Kconfig"
>
> source "drivers/net/can/sja1000/Kconfig"
> diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
> index 9047cd0..3ddc6a7 100644
> --- a/drivers/net/can/Makefile
> +++ b/drivers/net/can/Makefile
> @@ -16,5 +16,6 @@ obj-$(CONFIG_CAN_TI_HECC) += ti_hecc.o
> obj-$(CONFIG_CAN_MCP251X) += mcp251x.o
> obj-$(CONFIG_CAN_BFIN) += bfin_can.o
> obj-$(CONFIG_CAN_JANZ_ICAN3) += janz-ican3.o
> +obj-$(CONFIG_PCH_CAN) += pch_can.o
>
> ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
> diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c
> new file mode 100644
> index 0000000..55ec324
> --- /dev/null
> +++ b/drivers/net/can/pch_can.c
> @@ -0,0 +1,1463 @@
> +/*
> + * Copyright (C) 1999 - 2010 Intel Corporation.
> + * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; version 2 of the License.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
> + */
> +
> +#include <linux/interrupt.h>
> +#include <linux/delay.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/sched.h>
> +#include <linux/pci.h>
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/types.h>
> +#include <linux/errno.h>
> +#include <linux/netdevice.h>
> +#include <linux/skbuff.h>
> +#include <linux/can.h>
> +#include <linux/can/dev.h>
> +#include <linux/can/error.h>
> +
> +#define MAX_MSG_OBJ 32
> +#define MSG_OBJ_RX 0 /* The receive message object flag. */
> +#define MSG_OBJ_TX 1 /* The transmit message object flag. */
> +
> +#define ENABLE 1 /* The enable flag */
> +#define DISABLE 0 /* The disable flag */
I prefer just plain 0 and 1, YMMV.
> +#define CAN_CTRL_INIT 0x0001 /* The INIT bit of CANCONT register. */
> +#define CAN_CTRL_IE 0x0002 /* The IE bit of CAN control register */
> +#define CAN_CTRL_IE_SIE_EIE 0x000e
> +#define CAN_CTRL_CCE 0x0040
> +#define CAN_CTRL_OPT 0x0080 /* The OPT bit of CANCONT register. */
> +#define CAN_OPT_SILENT 0x0008 /* The Silent bit of CANOPT reg. */
> +#define CAN_OPT_LBACK 0x0010 /* The LoopBack bit of CANOPT reg. */
> +#define CAN_CMASK_RX_TX_SET 0x00f3
> +#define CAN_CMASK_RX_TX_GET 0x0073
> +#define CAN_CMASK_ALL 0xff
> +#define CAN_CMASK_RDWR 0x80
> +#define CAN_CMASK_ARB 0x20
> +#define CAN_CMASK_CTRL 0x10
> +#define CAN_CMASK_MASK 0x40
> +#define CAN_CMASK_NEWDAT 0x04
> +#define CAN_CMASK_CLRINTPND 0x08
> +
> +#define CAN_IF_MCONT_NEWDAT 0x8000
> +#define CAN_IF_MCONT_INTPND 0x2000
> +#define CAN_IF_MCONT_UMASK 0x1000
> +#define CAN_IF_MCONT_TXIE 0x0800
> +#define CAN_IF_MCONT_RXIE 0x0400
> +#define CAN_IF_MCONT_RMTEN 0x0200
> +#define CAN_IF_MCONT_TXRQXT 0x0100
> +#define CAN_IF_MCONT_EOB 0x0080
> +#define CAN_IF_MCONT_DLC 0x000f
> +#define CAN_IF_MCONT_MSGLOST 0x4000
> +#define CAN_MASK2_MDIR_MXTD 0xc000
> +#define CAN_ID2_DIR 0x2000
> +#define CAN_ID_MSGVAL 0x8000
> +
> +#define CAN_STATUS_INT 0x8000
> +#define CAN_IF_CREQ_BUSY 0x8000
> +#define CAN_ID2_XTD 0x4000
> +
> +#define CAN_REC 0x00007f00
> +#define CAN_TEC 0x000000ff
> +
> +#define PCH_RX_OK 0x00000010
> +#define PCH_TX_OK 0x00000008
> +#define PCH_BUS_OFF 0x00000080
> +#define PCH_EWARN 0x00000040
> +#define PCH_EPASSIV 0x00000020
> +#define PCH_LEC0 0x00000001
> +#define PCH_LEC1 0x00000002
> +#define PCH_LEC2 0x00000004
> +#define PCH_LEC_ALL (PCH_LEC0 | PCH_LEC1 | PCH_LEC2)
> +#define PCH_STUF_ERR PCH_LEC0
> +#define PCH_FORM_ERR PCH_LEC1
> +#define PCH_ACK_ERR (PCH_LEC0 | PCH_LEC1)
> +#define PCH_BIT1_ERR PCH_LEC2
> +#define PCH_BIT0_ERR (PCH_LEC0 | PCH_LEC2)
> +#define PCH_CRC_ERR (PCH_LEC1 | PCH_LEC2)
> +
> +/* bit position of certain controller bits. */
> +#define BIT_BITT_BRP 0
> +#define BIT_BITT_SJW 6
> +#define BIT_BITT_TSEG1 8
> +#define BIT_BITT_TSEG2 12
> +#define BIT_IF1_MCONT_RXIE 10
> +#define BIT_IF2_MCONT_TXIE 11
> +#define BIT_BRPE_BRPE 6
> +#define BIT_ES_TXERRCNT 0
> +#define BIT_ES_RXERRCNT 8
> +#define MSK_BITT_BRP 0x3f
> +#define MSK_BITT_SJW 0xc0
> +#define MSK_BITT_TSEG1 0xf00
> +#define MSK_BITT_TSEG2 0x7000
> +#define MSK_BRPE_BRPE 0x3c0
> +#define MSK_BRPE_GET 0x0f
> +#define MSK_CTRL_IE_SIE_EIE 0x07
> +#define MSK_MCONT_TXIE 0x08
> +#define MSK_MCONT_RXIE 0x10
> +#define PCH_CAN_NO_TX_BUFF 1
> +#define COUNTER_LIMIT 10
> +
> +#define PCH_CAN_CLK 50000000 /* 50MHz */
> +
> +/* Define the number of message object.
> + * PCH CAN communications are done via Message RAM.
> + * The Message RAM consists of 32 message objects. */
/*
* this is the preferred multi line comment style,
* please change
*/
> +#define PCH_RX_OBJ_NUM 26 /* 1~ PCH_RX_OBJ_NUM is Rx*/
> +#define PCH_TX_OBJ_NUM 6 /* PCH_RX_OBJ_NUM is RX ~ Tx*/
> +#define PCH_OBJ_NUM (PCH_TX_OBJ_NUM + PCH_RX_OBJ_NUM)
> +
> +#define PCH_FIFO_THRESH 16
> +
> +enum pch_can_mode {
> + PCH_CAN_ENABLE,
> + PCH_CAN_DISABLE,
> + PCH_CAN_ALL,
> + PCH_CAN_NONE,
> + PCH_CAN_STOP,
> + PCH_CAN_RUN
please add a "," at the end
> +};
> +
> +struct pch_can_regs {
> + u32 cont;
> + u32 stat;
> + u32 errc;
> + u32 bitt;
> + u32 intr;
> + u32 opt;
> + u32 brpe;
> + u32 reserve1;
> + u32 if1_creq;
> + u32 if1_cmask;
> + u32 if1_mask1;
> + u32 if1_mask2;
> + u32 if1_id1;
> + u32 if1_id2;
> + u32 if1_mcont;
> + u32 if1_dataa1;
> + u32 if1_dataa2;
> + u32 if1_datab1;
> + u32 if1_datab2;
> + u32 reserve2;
> + u32 reserve3[12];
> + u32 if2_creq;
> + u32 if2_cmask;
> + u32 if2_mask1;
> + u32 if2_mask2;
> + u32 if2_id1;
> + u32 if2_id2;
> + u32 if2_mcont;
> + u32 if2_dataa1;
> + u32 if2_dataa2;
> + u32 if2_datab1;
> + u32 if2_datab2;
> + u32 reserve4;
> + u32 reserve5[20];
> + u32 treq1;
> + u32 treq2;
> + u32 reserve6[2];
> + u32 reserve7[56];
> + u32 reserve8[3];
> + u32 srst;
> +};
> +
> +struct pch_can_priv {
> + struct can_priv can;
> + unsigned int can_num;
seems unused, pelase remove
> + struct pci_dev *dev;
> + unsigned int tx_enable[MAX_MSG_OBJ];
> + unsigned int rx_enable[MAX_MSG_OBJ];
> + unsigned int rx_link[MAX_MSG_OBJ];
> + unsigned int int_enables;
> + unsigned int int_stat;
> + struct net_device *ndev;
> + spinlock_t msgif_reg_lock; /* Message Interface Registers Access Lock*/
> + unsigned int msg_obj[MAX_MSG_OBJ];
> + struct pch_can_regs __iomem *regs;
> + struct napi_struct napi;
> + unsigned int tx_obj; /* Point next Tx Obj index */
> + unsigned int use_msi;
> +};
> +
> +static struct can_bittiming_const pch_can_bittiming_const = {
> + .name = KBUILD_MODNAME,
> + .tseg1_min = 1,
> + .tseg1_max = 16,
> + .tseg2_min = 1,
> + .tseg2_max = 8,
> + .sjw_max = 4,
> + .brp_min = 1,
> + .brp_max = 1024, /* 6bit + extended 4bit */
> + .brp_inc = 1,
> +};
> +
> +static DEFINE_PCI_DEVICE_TABLE(pch_pci_tbl) = {
> + {PCI_VENDOR_ID_INTEL, 0x8818, PCI_ANY_ID, PCI_ANY_ID,},
> + {0,}
> +};
> +MODULE_DEVICE_TABLE(pci, pch_pci_tbl);
> +
> +static inline void pch_can_bit_set(u32 *addr, u32 mask)
> +{
> + iowrite32(ioread32(addr) | mask, addr);
> +}
> +
> +static inline void pch_can_bit_clear(u32 *addr, u32 mask)
> +{
> + iowrite32(ioread32(addr) & ~mask, addr);
> +}
> +
> +static void pch_can_set_run_mode(struct pch_can_priv *priv,
> + enum pch_can_mode mode)
> +{
> + switch (mode) {
> + case PCH_CAN_RUN:
> + pch_can_bit_clear(&priv->regs->cont, CAN_CTRL_INIT);
> + break;
> +
> + case PCH_CAN_STOP:
> + pch_can_bit_set(&priv->regs->cont, CAN_CTRL_INIT);
> + break;
> +
> + default:
> + dev_err(&priv->ndev->dev, "%s -> Invalid Mode.\n", __func__);
> + break;
> + }
> +}
> +
> +static void pch_can_set_optmode(struct pch_can_priv *priv)
> +{
> + u32 reg_val = ioread32(&priv->regs->opt);
> +
> + if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
> + reg_val |= CAN_OPT_SILENT;
> +
> + if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)
> + reg_val |= CAN_OPT_LBACK;
> +
> + pch_can_bit_set(&priv->regs->cont, CAN_CTRL_OPT);
> + iowrite32(reg_val, &priv->regs->opt);
> +}
> +
> +static void pch_can_set_int_custom(struct pch_can_priv *priv)
> +{
> + /* Clearing the IE, SIE and EIE bits of Can control register. */
> + pch_can_bit_clear(&priv->regs->cont, CAN_CTRL_IE_SIE_EIE);
> +
> + /* Appropriately setting them. */
> + pch_can_bit_set(&priv->regs->cont,
> + ((priv->int_enables & MSK_CTRL_IE_SIE_EIE) << 1));
> +}
> +
> +/* This function retrieves interrupt enabled for the CAN device. */
> +static void pch_can_get_int_enables(struct pch_can_priv *priv, u32 *enables)
> +{
> + /* Obtaining the status of IE, SIE and EIE interrupt bits. */
> + *enables = ((ioread32(&priv->regs->cont) & CAN_CTRL_IE_SIE_EIE) >> 1);
> +}
I suggest to change these functions to simply return the value, not
using a pointer.
> +
> +static void pch_can_set_int_enables(struct pch_can_priv *priv,
> + enum pch_can_mode interrupt_no)
> +{
> + switch (interrupt_no) {
> + case PCH_CAN_ENABLE:
> + pch_can_bit_set(&priv->regs->cont, CAN_CTRL_IE);
> + break;
> +
> + case PCH_CAN_DISABLE:
> + pch_can_bit_clear(&priv->regs->cont, CAN_CTRL_IE);
> + break;
> +
> + case PCH_CAN_ALL:
> + pch_can_bit_set(&priv->regs->cont, CAN_CTRL_IE_SIE_EIE);
> + break;
> +
> + case PCH_CAN_NONE:
> + pch_can_bit_clear(&priv->regs->cont, CAN_CTRL_IE_SIE_EIE);
> + break;
> +
> + default:
> + dev_err(&priv->ndev->dev, "Invalid interrupt number.\n");
> + break;
> + }
> +}
> +
> +static void pch_can_check_if_busy(u32 __iomem *creq_addr, u32 num)
> +{
> + u32 counter = COUNTER_LIMIT;
> + u32 ifx_creq;
> +
> + iowrite32(num, creq_addr);
> + while (counter) {
> + ifx_creq = ioread32(creq_addr) & CAN_IF_CREQ_BUSY;
> + if (!ifx_creq)
> + break;
> + counter--;
> + udelay(1);
> + }
> + if (!counter)
> + pr_err("%s:IF1 BUSY Flag is set forever.\n", __func__);
> +}
> +
> +static void pch_can_set_rx_enable(struct pch_can_priv *priv, u32 buff_num,
> + u32 set)
a u32 is a bit uncommen here, as it is not a HW register, just use an
"int" (or a bool).
> +{
> + unsigned long flags;
> +
> + spin_lock_irqsave(&priv->msgif_reg_lock, flags);
> + /* Reading the receive buffer data from RAM to Interface1 registers */
> + iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if1_cmask);
> + pch_can_check_if_busy(&priv->regs->if1_creq, buff_num);
> +
> + /* Setting the IF1MASK1 register to access MsgVal and RxIE bits */
> + iowrite32(CAN_CMASK_RDWR | CAN_CMASK_ARB | CAN_CMASK_CTRL,
> + &priv->regs->if1_cmask);
> +
> + if (set == ENABLE) {
> + /* Setting the MsgVal and RxIE bits */
> + pch_can_bit_set(&priv->regs->if1_mcont, CAN_IF_MCONT_RXIE);
> + pch_can_bit_set(&priv->regs->if1_id2, CAN_ID_MSGVAL);
> +
> + } else if (set == DISABLE) {
> + /* Resetting the MsgVal and RxIE bits */
> + pch_can_bit_clear(&priv->regs->if1_mcont, CAN_IF_MCONT_RXIE);
> + pch_can_bit_clear(&priv->regs->if1_id2, CAN_ID_MSGVAL);
> + }
> +
> + pch_can_check_if_busy(&priv->regs->if1_creq, buff_num);
> + spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
> +}
> +
> +static void pch_can_rx_enable_all(struct pch_can_priv *priv)
> +{
> + int i;
> +
> + /* Traversing to obtain the object configured as receivers. */
> + for (i = 0; i < PCH_OBJ_NUM; i++) {
> + if (priv->msg_obj[i] == MSG_OBJ_RX)
> + pch_can_set_rx_enable(priv, i + 1, ENABLE);
> + }
> +}
> +
> +static void pch_can_rx_disable_all(struct pch_can_priv *priv)
> +{
> + int i;
> +
> + /* Traversing to obtain the object configured as receivers. */
> + for (i = 0; i < PCH_OBJ_NUM; i++) {
> + if (priv->msg_obj[i] == MSG_OBJ_RX)
> + pch_can_set_rx_enable(priv, i + 1, DISABLE);
> + }
> +}
> +
> +static void pch_can_set_tx_enable(struct pch_can_priv *priv, u32 buff_num,
> + u32 set)
> +{
> + unsigned long flags;
> +
> + spin_lock_irqsave(&priv->msgif_reg_lock, flags);
> + /* Reading the Msg buffer from Message RAM to Interface2 registers. */
> + iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if2_cmask);
> + pch_can_check_if_busy(&priv->regs->if2_creq, buff_num);
> +
> + /* Setting the IF2CMASK register for accessing the
> + MsgVal and TxIE bits */
> + iowrite32(CAN_CMASK_RDWR | CAN_CMASK_ARB | CAN_CMASK_CTRL,
> + &priv->regs->if2_cmask);
> +
> + if (set == ENABLE) {
> + /* Setting the MsgVal and TxIE bits */
> + pch_can_bit_set(&priv->regs->if2_mcont, CAN_IF_MCONT_TXIE);
> + pch_can_bit_set(&priv->regs->if2_id2, CAN_ID_MSGVAL);
> + } else if (set == DISABLE) {
> + /* Resetting the MsgVal and TxIE bits. */
> + pch_can_bit_clear(&priv->regs->if2_mcont, CAN_IF_MCONT_TXIE);
> + pch_can_bit_clear(&priv->regs->if2_id2, CAN_ID_MSGVAL);
> + }
> +
> + pch_can_check_if_busy(&priv->regs->if2_creq, buff_num);
> + spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
> +}
> +
> +static void pch_can_tx_enable_all(struct pch_can_priv *priv)
> +{
> + int i;
> +
> + /* Traversing to obtain the object configured as transmit object. */
> + for (i = 0; i < PCH_OBJ_NUM; i++) {
> + if (priv->msg_obj[i] == MSG_OBJ_TX)
> + pch_can_set_tx_enable(priv, i + 1, ENABLE);
> + }
> +}
> +
> +static void pch_can_tx_disable_all(struct pch_can_priv *priv)
> +{
> + int i;
> +
> + /* Traversing to obtain the object configured as transmit object. */
> + for (i = 0; i < PCH_OBJ_NUM; i++) {
> + if (priv->msg_obj[i] == MSG_OBJ_TX)
> + pch_can_set_tx_enable(priv, i + 1, DISABLE);
> + }
> +}
> +
> +static void pch_can_get_rx_enable(struct pch_can_priv *priv, u32 buff_num,
> + u32 *enable)
> +{
> + unsigned long flags;
> +
> + spin_lock_irqsave(&priv->msgif_reg_lock, flags);
> + iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if1_cmask);
> + pch_can_check_if_busy(&priv->regs->if1_creq, buff_num);
> +
> + if (((ioread32(&priv->regs->if1_id2)) & CAN_ID_MSGVAL) &&
> + ((ioread32(&priv->regs->if1_mcont)) &
> + CAN_IF_MCONT_RXIE))
> + *enable = ENABLE;
> + else
> + *enable = DISABLE;
> + spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
> +}
> +
> +static void pch_can_get_tx_enable(struct pch_can_priv *priv, u32 buff_num,
> + u32 *enable)
> +{
> + unsigned long flags;
> +
> + spin_lock_irqsave(&priv->msgif_reg_lock, flags);
> + iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if2_cmask);
> + pch_can_check_if_busy(&priv->regs->if2_creq, buff_num);
> +
> + if (((ioread32(&priv->regs->if2_id2)) & CAN_ID_MSGVAL) &&
> + ((ioread32(&priv->regs->if2_mcont)) &
> + CAN_IF_MCONT_TXIE)) {
> + *enable = ENABLE;
> + } else {
> + *enable = DISABLE;
> + }
> + spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
> +}
> +
> +static int pch_can_int_pending(struct pch_can_priv *priv)
> +{
> + return ioread32(&priv->regs->intr) & 0xffff;
> +}
> +
> +static void pch_can_set_rx_buffer_link(struct pch_can_priv *priv,
> + u32 buffer_num, u32 set)
> +{
> + unsigned long flags;
> +
> + spin_lock_irqsave(&priv->msgif_reg_lock, flags);
> + iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if1_cmask);
> + pch_can_check_if_busy(&priv->regs->if1_creq, buffer_num);
> + iowrite32(CAN_CMASK_RDWR | CAN_CMASK_CTRL, &priv->regs->if1_cmask);
> + if (set == ENABLE)
> + pch_can_bit_clear(&priv->regs->if1_mcont, CAN_IF_MCONT_EOB);
> + else
> + pch_can_bit_set(&priv->regs->if1_mcont, CAN_IF_MCONT_EOB);
> +
> + pch_can_check_if_busy(&priv->regs->if1_creq, buffer_num);
> + spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
> +}
> +
> +static void pch_can_get_rx_buffer_link(struct pch_can_priv *priv,
> + u32 buffer_num, u32 *link)
> +{
> + unsigned long flags;
> +
> + spin_lock_irqsave(&priv->msgif_reg_lock, flags);
> + iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if1_cmask);
> + pch_can_check_if_busy(&priv->regs->if1_creq, buffer_num);
> +
> + if (ioread32(&priv->regs->if1_mcont) & CAN_IF_MCONT_EOB)
> + *link = DISABLE;
> + else
> + *link = ENABLE;
> + spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
> +}
> +
> +static void pch_can_clear_buffers(struct pch_can_priv *priv)
> +{
> + int i;
> +
> + for (i = 0; i < PCH_RX_OBJ_NUM; i++) {
> + iowrite32(CAN_CMASK_RX_TX_SET, &priv->regs->if1_cmask);
> + iowrite32(0xffff, &priv->regs->if1_mask1);
> + iowrite32(0xffff, &priv->regs->if1_mask2);
> + iowrite32(0x0, &priv->regs->if1_id1);
> + iowrite32(0x0, &priv->regs->if1_id2);
> + iowrite32(0x0, &priv->regs->if1_mcont);
> + iowrite32(0x0, &priv->regs->if1_dataa1);
> + iowrite32(0x0, &priv->regs->if1_dataa2);
> + iowrite32(0x0, &priv->regs->if1_datab1);
> + iowrite32(0x0, &priv->regs->if1_datab2);
> + iowrite32(CAN_CMASK_RDWR | CAN_CMASK_MASK |
> + CAN_CMASK_ARB | CAN_CMASK_CTRL,
> + &priv->regs->if1_cmask);
> + pch_can_check_if_busy(&priv->regs->if1_creq, i+1);
^^^
Is it correct that the loop variable "i" is only used here?
> + }
> +
> + for (i = i; i < PCH_OBJ_NUM; i++) {
^^^^^
this _looks_ strange, make it more clean, i.e. by removing it, adding a
comment, defining a macro for the staring value...
> + iowrite32(CAN_CMASK_RX_TX_SET, &priv->regs->if2_cmask);
> + iowrite32(0xffff, &priv->regs->if2_mask1);
> + iowrite32(0xffff, &priv->regs->if2_mask2);
> + iowrite32(0x0, &priv->regs->if2_id1);
> + iowrite32(0x0, &priv->regs->if2_id2);
> + iowrite32(0x0, &priv->regs->if2_mcont);
> + iowrite32(0x0, &priv->regs->if2_dataa1);
> + iowrite32(0x0, &priv->regs->if2_dataa2);
> + iowrite32(0x0, &priv->regs->if2_datab1);
> + iowrite32(0x0, &priv->regs->if2_datab2);
> + iowrite32(CAN_CMASK_RDWR | CAN_CMASK_MASK |
> + CAN_CMASK_ARB | CAN_CMASK_CTRL,
> + &priv->regs->if2_cmask);
> + pch_can_check_if_busy(&priv->regs->if2_creq, i+1);
dito
> + }
> +}
> +
> +static void pch_can_config_rx_tx_buffers(struct pch_can_priv *priv)
> +{
> + int i;
> + unsigned long flags;
> +
> + spin_lock_irqsave(&priv->msgif_reg_lock, flags);
> +
> + for (i = 0; i < PCH_OBJ_NUM; i++) {
> + if (priv->msg_obj[i] == MSG_OBJ_RX) {
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> + iowrite32(CAN_CMASK_RX_TX_GET,
> + &priv->regs->if1_cmask);
> + pch_can_check_if_busy(&priv->regs->if1_creq, i+1);
> +
> + iowrite32(0x0, &priv->regs->if1_id1);
> + iowrite32(0x0, &priv->regs->if1_id2);
> +
> + pch_can_bit_set(&priv->regs->if1_mcont,
> + CAN_IF_MCONT_UMASK);
> +
> + /* Set FIFO mode set to 0 except last Rx Obj*/
> + pch_can_bit_clear(&priv->regs->if1_mcont,
> + CAN_IF_MCONT_EOB);
> + /* In case FIFO mode, Last EoB of Rx Obj must be 1 */
> + if (i == (PCH_RX_OBJ_NUM - 1))
> + pch_can_bit_set(&priv->regs->if1_mcont,
> + CAN_IF_MCONT_EOB);
> +
> + iowrite32(0, &priv->regs->if1_mask1);
> + pch_can_bit_clear(&priv->regs->if1_mask2,
> + 0x1fff | CAN_MASK2_MDIR_MXTD);
> +
> + /* Setting CMASK for writing */
> + iowrite32(CAN_CMASK_RDWR | CAN_CMASK_MASK |
> + CAN_CMASK_ARB | CAN_CMASK_CTRL,
> + &priv->regs->if1_cmask);
> +
> + pch_can_check_if_busy(&priv->regs->if1_creq, i+1);
> + } else if (priv->msg_obj[i] == MSG_OBJ_TX) {
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Do I understand your code correctly? You have a big loop, but only do
two different things at certain values of the loop? Smells fishy.
> + iowrite32(CAN_CMASK_RX_TX_GET,
> + &priv->regs->if2_cmask);
> + pch_can_check_if_busy(&priv->regs->if2_creq, i+1);
> +
> + /* Resetting DIR bit for reception */
> + iowrite32(0x0, &priv->regs->if2_id1);
> + iowrite32(0x0, &priv->regs->if2_id2);
> + pch_can_bit_set(&priv->regs->if2_id2, CAN_ID2_DIR);
> +
> + /* Setting EOB bit for transmitter */
> + iowrite32(CAN_IF_MCONT_EOB, &priv->regs->if2_mcont);
> +
> + pch_can_bit_set(&priv->regs->if2_mcont,
> + CAN_IF_MCONT_UMASK);
> +
> + iowrite32(0, &priv->regs->if2_mask1);
> + pch_can_bit_clear(&priv->regs->if2_mask2, 0x1fff);
> +
> + /* Setting CMASK for writing */
> + iowrite32(CAN_CMASK_RDWR | CAN_CMASK_MASK |
> + CAN_CMASK_ARB | CAN_CMASK_CTRL,
> + &priv->regs->if2_cmask);
> +
> + pch_can_check_if_busy(&priv->regs->if2_creq, i+1);
> + }
> + }
> + spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
> +}
> +
> +static void pch_can_init(struct pch_can_priv *priv)
> +{
> + /* Stopping the Can device. */
> + pch_can_set_run_mode(priv, PCH_CAN_STOP);
> +
> + /* Clearing all the message object buffers. */
> + pch_can_clear_buffers(priv);
> +
> + /* Configuring the respective message object as either rx/tx object. */
> + pch_can_config_rx_tx_buffers(priv);
> +
> + /* Enabling the interrupts. */
> + pch_can_set_int_enables(priv, PCH_CAN_ALL);
> +}
> +
> +static void pch_can_release(struct pch_can_priv *priv)
> +{
> + /* Stooping the CAN device. */
> + pch_can_set_run_mode(priv, PCH_CAN_STOP);
> +
> + /* Disabling the interrupts. */
> + pch_can_set_int_enables(priv, PCH_CAN_NONE);
> +
> + /* Disabling all the receive object. */
> + pch_can_rx_disable_all(priv);
> +
> + /* Disabling all the transmit object. */
> + pch_can_tx_disable_all(priv);
> +}
> +
> +/* This function clears interrupt(s) from the CAN device. */
> +static void pch_can_int_clr(struct pch_can_priv *priv, u32 mask)
> +{
> + if (mask == CAN_STATUS_INT) {
> + ioread32(&priv->regs->stat);
> + return;
> + }
> +
> + /* Clear interrupt for transmit object */
> + if (priv->msg_obj[mask - 1] == MSG_OBJ_TX) {
> + /* Setting CMASK for clearing interrupts for
> + frame transmission. */
> + iowrite32(CAN_CMASK_RDWR | CAN_CMASK_CTRL | CAN_CMASK_ARB,
> + &priv->regs->if2_cmask);
> +
> + /* Resetting the ID registers. */
> + pch_can_bit_set(&priv->regs->if2_id2,
> + CAN_ID2_DIR | (0x7ff << 2));
> + iowrite32(0x0, &priv->regs->if2_id1);
> +
> + /* Claring NewDat, TxRqst & IntPnd */
> + pch_can_bit_clear(&priv->regs->if2_mcont,
> + CAN_IF_MCONT_NEWDAT | CAN_IF_MCONT_INTPND |
> + CAN_IF_MCONT_TXRQXT);
> + pch_can_check_if_busy(&priv->regs->if2_creq, mask);
> + } else if (priv->msg_obj[mask - 1] == MSG_OBJ_RX) {
> + /* Setting CMASK for clearing the reception interrupts. */
> + iowrite32(CAN_CMASK_RDWR | CAN_CMASK_CTRL | CAN_CMASK_ARB,
> + &priv->regs->if1_cmask);
> +
> + /* Clearing the Dir bit. */
> + pch_can_bit_clear(&priv->regs->if1_id2, CAN_ID2_DIR);
> +
> + /* Clearing NewDat & IntPnd */
> + pch_can_bit_clear(&priv->regs->if1_mcont,
> + CAN_IF_MCONT_NEWDAT | CAN_IF_MCONT_INTPND);
> +
> + pch_can_check_if_busy(&priv->regs->if1_creq, mask);
> + }
> +}
> +
> +static int pch_can_get_buffer_status(struct pch_can_priv *priv)
^^^
I'd use a u32, as it's a register value....
> +{
> + return (ioread32(&priv->regs->treq1) & 0xffff) |
> + ((ioread32(&priv->regs->treq2) & 0xffff) << 16);
> +}
> +
> +static void pch_can_reset(struct pch_can_priv *priv)
> +{
> + /* write to sw reset register */
> + iowrite32(1, &priv->regs->srst);
> + iowrite32(0, &priv->regs->srst);
> +}
> +
> +static void pch_can_error(struct net_device *ndev, u32 status)
> +{
> + struct sk_buff *skb;
> + struct pch_can_priv *priv = netdev_priv(ndev);
> + struct can_frame *cf;
> + u32 errc;
> + struct net_device_stats *stats = &(priv->ndev->stats);
> + enum can_state state = priv->can.state;
> +
> + skb = alloc_can_err_skb(ndev, &cf);
> + if (!skb)
> + return;
> +
> + if (status & PCH_BUS_OFF) {
> + pch_can_tx_disable_all(priv);
> + pch_can_rx_disable_all(priv);
> + state = CAN_STATE_BUS_OFF;
> + cf->can_id |= CAN_ERR_BUSOFF;
> + can_bus_off(ndev);
> + pch_can_set_run_mode(priv, PCH_CAN_RUN);
> + dev_err(&ndev->dev, "%s -> Bus Off occurres.\n", __func__);
> + }
> +
> + /* Warning interrupt. */
> + if (status & PCH_EWARN) {
> + state = CAN_STATE_ERROR_WARNING;
> + priv->can.can_stats.error_warning++;
> + cf->can_id |= CAN_ERR_CRTL;
> + errc = ioread32(&priv->regs->errc);
> + if (((errc & CAN_REC) >> 8) > 96)
> + cf->data[1] |= CAN_ERR_CRTL_RX_WARNING;
> + if ((errc & CAN_TEC) > 96)
> + cf->data[1] |= CAN_ERR_CRTL_TX_WARNING;
> + dev_warn(&ndev->dev,
> + "%s -> Error Counter is more than 96.\n", __func__);
> + }
> + /* Error passive interrupt. */
> + if (status & PCH_EPASSIV) {
> + priv->can.can_stats.error_passive++;
> + state = CAN_STATE_ERROR_PASSIVE;
> + cf->can_id |= CAN_ERR_CRTL;
> + errc = ioread32(&priv->regs->errc);
> + if (((errc & CAN_REC) >> 8) > 127)
> + cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE;
> + if ((errc & CAN_TEC) > 127)
> + cf->data[1] |= CAN_ERR_CRTL_TX_PASSIVE;
> + dev_err(&ndev->dev,
> + "%s -> CAN controller is ERROR PASSIVE .\n", __func__);
> + }
> +
> + if (status & PCH_LEC_ALL) {
> + priv->can.can_stats.bus_error++;
> + stats->rx_errors++;
> + switch (status & PCH_LEC_ALL) {
> + case PCH_STUF_ERR:
> + cf->data[2] |= CAN_ERR_PROT_STUFF;
> + break;
> + case PCH_FORM_ERR:
> + cf->data[2] |= CAN_ERR_PROT_FORM;
> + break;
> + case PCH_ACK_ERR:
> + cf->data[2] |= CAN_ERR_PROT_LOC_ACK |
> + CAN_ERR_PROT_LOC_ACK_DEL;
> + break;
> + case PCH_BIT1_ERR:
> + case PCH_BIT0_ERR:
> + cf->data[2] |= CAN_ERR_PROT_BIT;
> + break;
> + case PCH_CRC_ERR:
> + cf->data[2] |= CAN_ERR_PROT_LOC_CRC_SEQ |
> + CAN_ERR_PROT_LOC_CRC_DEL;
> + break;
> + default:
> + iowrite32(status | PCH_LEC_ALL, &priv->regs->stat);
> + break;
> + }
> +
> + }
> +
> + priv->can.state = state;
> + netif_rx(skb);
> +
> + stats->rx_packets++;
> + stats->rx_bytes += cf->can_dlc;
> +}
> +
> +static irqreturn_t pch_can_interrupt(int irq, void *dev_id)
> +{
> + struct net_device *ndev = (struct net_device *)dev_id;
> + struct pch_can_priv *priv = netdev_priv(ndev);
> +
> + pch_can_set_int_enables(priv, PCH_CAN_NONE);
> +
> + napi_schedule(&priv->napi);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static int pch_can_rx_normal(struct net_device *ndev, u32 int_stat)
> +{
> + u32 reg;
> + canid_t id;
> + u32 ide;
> + u32 rtr;
> + int i, j, k;
> + int rcv_pkts = 0;
> + struct sk_buff *skb;
> + struct can_frame *cf;
> + struct pch_can_priv *priv = netdev_priv(ndev);
> + struct net_device_stats *stats = &(priv->ndev->stats);
> +
> + /* Reading the messsage object from the Message RAM */
> + iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if1_cmask);
> + pch_can_check_if_busy(&priv->regs->if1_creq, int_stat);
> +
> + /* Reading the MCONT register. */
> + reg = ioread32(&priv->regs->if1_mcont);
> + reg &= 0xffff;
> +
> + for (k = int_stat; !(reg & CAN_IF_MCONT_EOB); k++) {
IMHO the loop is too long, please put make two or three functions from
this. (MsgLost bit handling, normal RX and threshold stuff)
> + /* If MsgLost bit set. */
> + if (reg & CAN_IF_MCONT_MSGLOST) {
> + dev_err(&priv->ndev->dev, "Msg Obj is overwritten.\n");
> + pch_can_bit_clear(&priv->regs->if1_mcont,
> + CAN_IF_MCONT_MSGLOST);
> + iowrite32(CAN_CMASK_RDWR | CAN_CMASK_CTRL,
> + &priv->regs->if1_cmask);
> + pch_can_check_if_busy(&priv->regs->if1_creq, k);
> +
> + skb = alloc_can_err_skb(ndev, &cf);
> + if (!skb)
> + return -ENOMEM;
> +
> + priv->can.can_stats.error_passive++;
> + priv->can.state = CAN_STATE_ERROR_PASSIVE;
> + cf->can_id |= CAN_ERR_CRTL;
> + cf->data[1] |= CAN_ERR_CRTL_RX_OVERFLOW;
> + cf->data[2] |= CAN_ERR_PROT_OVERLOAD;
> + stats->rx_packets++;
> + stats->rx_bytes += cf->can_dlc;
> +
> + netif_receive_skb(skb);
> + rcv_pkts++;
> + goto RX_NEXT;
> + }
> + if (!(reg & CAN_IF_MCONT_NEWDAT))
> + goto RX_NEXT;
> +
> + skb = alloc_can_skb(priv->ndev, &cf);
> + if (!skb)
> + return -ENOMEM;
> +
> + /* Get Received data */
> + ide = ((ioread32(&priv->regs->if1_id2)) & CAN_ID2_XTD) >> 14;
the shift is not needed
> + if (ide) {
> + id = (ioread32(&priv->regs->if1_id1) & 0xffff);
> + id |= (((ioread32(&priv->regs->if1_id2)) &
> + 0x1fff) << 16);
> + cf->can_id = (id & CAN_EFF_MASK) | CAN_EFF_FLAG;
> + } else {
> + id = (((ioread32(&priv->regs->if1_id2)) &
> + (CAN_SFF_MASK << 2)) >> 2);
> + cf->can_id = (id & CAN_SFF_MASK);
> + }
> +
> + rtr = (ioread32(&priv->regs->if1_id2) & CAN_ID2_DIR);
please remove the braces
> + if (rtr) {
> + cf->can_dlc = 0;
^
use the supplied dlc value
> + cf->can_id |= CAN_RTR_FLAG;
> + } else {
> + cf->can_dlc = ((ioread32(&priv->regs->if1_mcont)) &
> + 0x0f);
use get_can_dlc()
> + }
> +
> + for (i = 0, j = 0; i < cf->can_dlc; j++) {
> + reg = ioread32(&priv->regs->if1_dataa1 + j*4);
> + cf->data[i++] = cpu_to_le32(reg & 0xff);
> + if (i == cf->can_dlc)
> + break;
> + cf->data[i++] = cpu_to_le32((reg >> 8) & 0xff);
the idea behind the cpu_to_le32 and friends is that they do the needed
endianess conversion for you. This way you get rid of the second
variable in this loop (j).
> + }
> +
> + netif_receive_skb(skb);
> + rcv_pkts++;
> + stats->rx_packets++;
> + stats->rx_bytes += cf->can_dlc;
> +
> + if (k < PCH_FIFO_THRESH) {
> + iowrite32(CAN_CMASK_RDWR | CAN_CMASK_CTRL |
> + CAN_CMASK_ARB, &priv->regs->if1_cmask);
> +
> + /* Clearing the Dir bit. */
> + pch_can_bit_clear(&priv->regs->if1_id2, CAN_ID2_DIR);
> +
> + /* Clearing NewDat & IntPnd */
> + pch_can_bit_clear(&priv->regs->if1_mcont,
> + CAN_IF_MCONT_INTPND);
> + pch_can_check_if_busy(&priv->regs->if1_creq, k);
> + } else if (k > PCH_FIFO_THRESH) {
> + pch_can_int_clr(priv, k);
> + } else if (k == PCH_FIFO_THRESH) {
> + int cnt;
> + for (cnt = 0; cnt < PCH_FIFO_THRESH; cnt++)
> + pch_can_int_clr(priv, cnt+1);
> + }
> +RX_NEXT:
please use low case names for the labes
> + /* Reading the messsage object from the Message RAM */
> + iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if1_cmask);
> + pch_can_check_if_busy(&priv->regs->if1_creq, k + 1);
> + reg = ioread32(&priv->regs->if1_mcont);
> + }
> +
> + return rcv_pkts;
> +}
> +static int pch_can_rx_poll(struct napi_struct *napi, int quota)
^^^^^^^^^^
You should take care about the quota.
> +{
> + struct net_device *ndev = napi->dev;
> + struct pch_can_priv *priv = netdev_priv(ndev);
> + struct net_device_stats *stats = &(priv->ndev->stats);
> + u32 dlc;
> + u32 int_stat;
> + int rcv_pkts = 0;
> + u32 reg_stat;
> + unsigned long flags;
> +
> + int_stat = pch_can_int_pending(priv);
> + if (!int_stat)
> + return 0;
> +
> +INT_STAT:
> + if (int_stat == CAN_STATUS_INT) {
> + reg_stat = ioread32(&priv->regs->stat);
> + if (reg_stat & (PCH_BUS_OFF | PCH_LEC_ALL)) {
> + if ((reg_stat & PCH_LEC_ALL) != PCH_LEC_ALL)
> + pch_can_error(ndev, reg_stat);
> + }
> +
> + if (reg_stat & PCH_TX_OK) {
> + spin_lock_irqsave(&priv->msgif_reg_lock, flags);
> + iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if2_cmask);
> + pch_can_check_if_busy(&priv->regs->if2_creq,
> + ioread32(&priv->regs->intr));
> + spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
> + pch_can_bit_clear(&priv->regs->stat, PCH_TX_OK);
> + }
> +
> + if (reg_stat & PCH_RX_OK)
> + pch_can_bit_clear(&priv->regs->stat, PCH_RX_OK);
> +
> + int_stat = pch_can_int_pending(priv);
> + if (int_stat == CAN_STATUS_INT)
> + goto INT_STAT;
> + }
> +
> +MSG_OBJ:
> + if ((int_stat >= 1) && (int_stat <= PCH_RX_OBJ_NUM)) {
> + spin_lock_irqsave(&priv->msgif_reg_lock, flags);
> + rcv_pkts = pch_can_rx_normal(ndev, int_stat);
> + spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
> + if (rcv_pkts < 0)
> + return 0;
> + } else if ((int_stat > PCH_RX_OBJ_NUM) && (int_stat <= PCH_OBJ_NUM)) {
> + if (priv->msg_obj[int_stat - 1] == MSG_OBJ_TX) {
> + /* Handle transmission interrupt */
IMHO, make this a function, too
> + can_get_echo_skb(ndev, int_stat - PCH_RX_OBJ_NUM - 1);
> + spin_lock_irqsave(&priv->msgif_reg_lock, flags);
> + iowrite32(CAN_CMASK_RX_TX_GET | CAN_CMASK_CLRINTPND,
> + &priv->regs->if2_cmask);
> + dlc = ioread32(&priv->regs->if2_mcont) &
> + CAN_IF_MCONT_DLC;
> + pch_can_check_if_busy(&priv->regs->if2_creq, int_stat);
> + spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
> + if (dlc > 8)
> + dlc = 8;
> + stats->tx_bytes += dlc;
> + stats->tx_packets++;
> + }
> + }
> +
> + int_stat = pch_can_int_pending(priv);
> + if (int_stat == CAN_STATUS_INT)
> + goto INT_STAT;
> + else if (int_stat >= 1 && int_stat <= 32)
> + goto MSG_OBJ;
> +
> + napi_complete(napi);
> + pch_can_set_int_enables(priv, PCH_CAN_ALL);
> +
> + return rcv_pkts;
> +}
> +
> +static int pch_set_bittiming(struct net_device *ndev)
> +{
> + struct pch_can_priv *priv = netdev_priv(ndev);
> + const struct can_bittiming *bt = &priv->can.bittiming;
> + u32 canbit;
> + u32 bepe;
> + u32 brp;
> +
> + /* Setting the CCE bit for accessing the Can Timing register. */
> + pch_can_bit_set(&priv->regs->cont, CAN_CTRL_CCE);
> +
> + brp = (bt->tq) / (1000000000/PCH_CAN_CLK) - 1;
You already set "priv->can.clock.freq = PCH_CAN_CLK;" why do you need to
calculate the brp by yourself?
> + canbit = brp & MSK_BITT_BRP;
> + canbit |= (bt->sjw - 1) << BIT_BITT_SJW;
> + canbit |= (bt->phase_seg1 + bt->prop_seg - 1) << BIT_BITT_TSEG1;
> + canbit |= (bt->phase_seg2 - 1) << BIT_BITT_TSEG2;
> + bepe = (brp & MSK_BRPE_BRPE) >> BIT_BRPE_BRPE;
> + iowrite32(canbit, &priv->regs->bitt);
> + iowrite32(bepe, &priv->regs->brpe);
> + pch_can_bit_clear(&priv->regs->cont, CAN_CTRL_CCE);
> +
> + return 0;
> +}
> +
> +static void pch_can_start(struct net_device *ndev)
> +{
> + struct pch_can_priv *priv = netdev_priv(ndev);
> +
> + if (priv->can.state != CAN_STATE_STOPPED)
> + pch_can_reset(priv);
> +
> + pch_set_bittiming(ndev);
> + pch_can_set_optmode(priv);
> +
> + pch_can_tx_enable_all(priv);
> + pch_can_rx_enable_all(priv);
> +
> + /* Setting the CAN to run mode. */
> + pch_can_set_run_mode(priv, PCH_CAN_RUN);
> +
> + priv->can.state = CAN_STATE_ERROR_ACTIVE;
> +
> + return;
> +}
> +
> +static int pch_can_do_set_mode(struct net_device *ndev, enum can_mode mode)
> +{
> + int ret = 0;
> +
> + switch (mode) {
> + case CAN_MODE_START:
> + pch_can_start(ndev);
> + netif_wake_queue(ndev);
> + break;
> + default:
> + ret = -EOPNOTSUPP;
> + break;
> + }
> +
> + return ret;
> +}
> +
> +static int pch_can_open(struct net_device *ndev)
> +{
> + struct pch_can_priv *priv = netdev_priv(ndev);
> + int retval;
> +
> + retval = pci_enable_msi(priv->dev);
> + if (retval) {
> + dev_info(&ndev->dev, "PCH CAN opened without MSI\n");
> + priv->use_msi = 0;
> + } else {
> + dev_info(&ndev->dev, "PCH CAN opened with MSI\n");
> + priv->use_msi = 1;
> + }
> +
> + /* Regsitering the interrupt. */
> + retval = request_irq(priv->dev->irq, pch_can_interrupt, IRQF_SHARED,
> + ndev->name, ndev);
> + if (retval) {
> + dev_err(&ndev->dev, "request_irq failed.\n");
> + goto req_irq_err;
> + }
> +
> + /* Open common can device */
> + retval = open_candev(ndev);
> + if (retval) {
> + dev_err(ndev->dev.parent, "open_candev() failed %d\n", retval);
> + goto err_open_candev;
> + }
> +
> + pch_can_init(priv);
> + pch_can_start(ndev);
> + napi_enable(&priv->napi);
> + netif_start_queue(ndev);
> +
> + return 0;
> +
> +err_open_candev:
> + free_irq(priv->dev->irq, ndev);
> +req_irq_err:
> + if (priv->use_msi)
> + pci_disable_msi(priv->dev);
> +
> + pch_can_release(priv);
> +
> + return retval;
> +}
> +
> +static int pch_close(struct net_device *ndev)
> +{
> + struct pch_can_priv *priv = netdev_priv(ndev);
> +
> + netif_stop_queue(ndev);
> + napi_disable(&priv->napi);
> + pch_can_release(priv);
> + free_irq(priv->dev->irq, ndev);
> + if (priv->use_msi)
> + pci_disable_msi(priv->dev);
> + close_candev(ndev);
> + priv->can.state = CAN_STATE_STOPPED;
> + return 0;
> +}
> +
> +static int pch_get_msg_obj_sts(struct net_device *ndev, u32 obj_id)
> +{
> + u32 buffer_status = 0;
> + struct pch_can_priv *priv = netdev_priv(ndev);
> +
> + /* Getting the message object status. */
> + buffer_status = (u32) pch_can_get_buffer_status(priv);
> +
> + return buffer_status & obj_id;
> +}
> +
> +
> +static netdev_tx_t pch_xmit(struct sk_buff *skb, struct net_device *ndev)
> +{
> + int i, j;
> + unsigned long flags;
> + struct pch_can_priv *priv = netdev_priv(ndev);
> + struct can_frame *cf = (struct can_frame *)skb->data;
> + int tx_buffer_avail = 0;
> +
> + if (can_dropped_invalid_skb(ndev, skb))
> + return NETDEV_TX_OK;
> +
> + if (priv->tx_obj == (PCH_OBJ_NUM + 1)) { /* Point tail Obj */
what does this loop do? why is it nessecarry? I don't like delay loops
in the hot path of a driver.
> + while (pch_get_msg_obj_sts(ndev, (((1 << PCH_TX_OBJ_NUM)-1) <<
> + PCH_RX_OBJ_NUM)))
> + udelay(500);
> +
> + priv->tx_obj = PCH_RX_OBJ_NUM + 1; /* Point head of Tx Obj ID */
> + tx_buffer_avail = priv->tx_obj; /* Point Tail of Tx Obj */
> + } else {
> + tx_buffer_avail = priv->tx_obj;
> + }
> + priv->tx_obj++;
> +
> + /* Attaining the lock. */
> + spin_lock_irqsave(&priv->msgif_reg_lock, flags);
> +
> + /* Reading the Msg Obj from the Msg RAM to the Interface register. */
You mean write? We're sending can frames here :)
> + iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if2_cmask);
> + pch_can_check_if_busy(&priv->regs->if2_creq, tx_buffer_avail);
> +
> + /* Setting the CMASK register. */
> + pch_can_bit_set(&priv->regs->if2_cmask, CAN_CMASK_ALL);
> +
> + /* If ID extended is set. */
> + pch_can_bit_clear(&priv->regs->if2_id1, 0xffff);
> + pch_can_bit_clear(&priv->regs->if2_id2, 0x1fff | CAN_ID2_XTD);
> + if (cf->can_id & CAN_EFF_FLAG) {
> + pch_can_bit_set(&priv->regs->if2_id1, cf->can_id & 0xffff);
> + pch_can_bit_set(&priv->regs->if2_id2,
> + ((cf->can_id >> 16) & 0x1fff) | CAN_ID2_XTD);
> + } else {
> + pch_can_bit_set(&priv->regs->if2_id1, 0);
> + pch_can_bit_set(&priv->regs->if2_id2,
> + (cf->can_id & CAN_SFF_MASK) << 2);
> + }
Taking about speed, you do 2 read-modify-write cycles on if2_id{1,2}.
Yhe usual way is to prepare the values that should go into the hardware,
then writen them.
> +
> + /* If remote frame has to be transmitted.. */
> + if (cf->can_id & CAN_RTR_FLAG)
> + pch_can_bit_clear(&priv->regs->if2_id2, CAN_ID2_DIR);
dito
> +
> + for (i = 0, j = 0; i < cf->can_dlc; j++) {
> + iowrite32(le32_to_cpu(cf->data[i++]),
> + (&priv->regs->if2_dataa1) + j*4);
> + if (i == cf->can_dlc)
> + break;
> + iowrite32(le32_to_cpu(cf->data[i++] << 8),
> + (&priv->regs->if2_dataa1) + j*4);
If you figured out how to use the endianess conversion functions from
the cpu_to_{le,be}-{le,to}_to_cpup family use them here, too.
> + }
> +
> + can_put_echo_skb(skb, ndev, tx_buffer_avail - PCH_RX_OBJ_NUM - 1);
> +
> + /* Updating the size of the data. */
> + pch_can_bit_clear(&priv->regs->if2_mcont, 0x0f);
> + pch_can_bit_set(&priv->regs->if2_mcont, cf->can_dlc);
the comment about read-modify-write applies here, too
> +
> + /* Clearing IntPend, NewDat & TxRqst */
> + pch_can_bit_clear(&priv->regs->if2_mcont,
> + CAN_IF_MCONT_NEWDAT | CAN_IF_MCONT_INTPND |
> + CAN_IF_MCONT_TXRQXT);
dito
> +
> + /* Setting NewDat, TxRqst bits */
> + pch_can_bit_set(&priv->regs->if2_mcont,
> + CAN_IF_MCONT_NEWDAT | CAN_IF_MCONT_TXRQXT);
dito
> +
> + pch_can_check_if_busy(&priv->regs->if2_creq, tx_buffer_avail);
All these check if busy in the code make me a bit nervous, can you
please explain why they are needed. A pointer to the manual is okay, too.
> +
> + spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
> +
> + return NETDEV_TX_OK;
> +}
> +
> +static const struct net_device_ops pch_can_netdev_ops = {
> + .ndo_open = pch_can_open,
> + .ndo_stop = pch_close,
> + .ndo_start_xmit = pch_xmit,
> +};
> +
> +static void __devexit pch_can_remove(struct pci_dev *pdev)
> +{
> + struct net_device *ndev = pci_get_drvdata(pdev);
> + struct pch_can_priv *priv = netdev_priv(ndev);
> +
> + unregister_candev(priv->ndev);
> + free_candev(priv->ndev);
Is priv still valid after this? It's in several other drivers, too...but
this smells like a bug.
Any has a "spatch" handy?
> + pci_iounmap(pdev, priv->regs);
> + pci_release_regions(pdev);
> + pci_disable_device(pdev);
> + pci_set_drvdata(pdev, NULL);
> + pch_can_reset(priv);
> +}
> +
> +#ifdef CONFIG_PM
> +static int pch_can_suspend(struct pci_dev *pdev, pm_message_t state)
> +{
> + int i; /* Counter variable. */
> + int retval; /* Return value. */
> + u32 buf_stat; /* Variable for reading the transmit buffer status. */
> + u32 counter = 0xFFFFFF;
> +
> + struct net_device *dev = pci_get_drvdata(pdev);
> + struct pch_can_priv *priv = netdev_priv(dev);
> +
> + /* Stop the CAN controller */
> + pch_can_set_run_mode(priv, PCH_CAN_STOP);
> +
> + /* Indicate that we are aboutto/in suspend */
> + priv->can.state = CAN_STATE_SLEEPING;
> +
> + /* Waiting for all transmission to complete. */
> + while (counter) {
> + buf_stat = pch_can_get_buffer_status(priv);
> + if (!buf_stat)
> + break;
> + counter--;
> + udelay(1);
> + }
> + if (!counter)
> + dev_err(&pdev->dev, "%s -> Transmission time out.\n", __func__);
> +
> + /* Save interrupt configuration and then disable them */
> + pch_can_get_int_enables(priv, &(priv->int_enables));
> + pch_can_set_int_enables(priv, PCH_CAN_DISABLE);
> +
> + /* Save Tx buffer enable state */
> + for (i = 0; i < PCH_OBJ_NUM; i++) {
> + if (priv->msg_obj[i] == MSG_OBJ_TX)
> + pch_can_get_tx_enable(priv, i + 1,
> + &(priv->tx_enable[i]));
> + }
> +
> + /* Disable all Transmit buffers */
> + pch_can_tx_disable_all(priv);
> +
> + /* Save Rx buffer enable state */
> + for (i = 0; i < PCH_OBJ_NUM; i++) {
> + if (priv->msg_obj[i] == MSG_OBJ_RX) {
> + pch_can_get_rx_enable(priv, i + 1,
> + &(priv->rx_enable[i]));
> + pch_can_get_rx_buffer_link(priv, i + 1,
> + &(priv->rx_link[i]));
> + }
> + }
> +
> + /* Disable all Receive buffers */
> + pch_can_rx_disable_all(priv);
> + retval = pci_save_state(pdev);
> + if (retval) {
> + dev_err(&pdev->dev, "pci_save_state failed.\n");
> + } else {
> + pci_enable_wake(pdev, PCI_D3hot, 0);
> + pci_disable_device(pdev);
> + pci_set_power_state(pdev, pci_choose_state(pdev, state));
> + }
> +
> + return retval;
> +}
> +
> +static int pch_can_resume(struct pci_dev *pdev)
> +{
> + int i; /* Counter variable. */
> + int retval; /* Return variable. */
> + struct net_device *dev = pci_get_drvdata(pdev);
> + struct pch_can_priv *priv = netdev_priv(dev);
> +
> + pci_set_power_state(pdev, PCI_D0);
> + pci_restore_state(pdev);
> + retval = pci_enable_device(pdev);
> + if (retval) {
> + dev_err(&pdev->dev, "pci_enable_device failed.\n");
> + return retval;
> + }
> +
> + pci_enable_wake(pdev, PCI_D3hot, 0);
> +
> + priv->can.state = CAN_STATE_ERROR_ACTIVE;
> +
> + /* Disabling all interrupts. */
> + pch_can_set_int_enables(priv, PCH_CAN_DISABLE);
> +
> + /* Setting the CAN device in Stop Mode. */
> + pch_can_set_run_mode(priv, PCH_CAN_STOP);
> +
> + /* Configuring the transmit and receive buffers. */
> + pch_can_config_rx_tx_buffers(priv);
> +
> + /* Restore the CAN state */
> + pch_set_bittiming(dev);
> +
> + /* Listen/Active */
> + pch_can_set_optmode(priv);
> +
> + /* Enabling the transmit buffer. */
> + for (i = 0; i < PCH_OBJ_NUM; i++) {
> + if (priv->msg_obj[i] == MSG_OBJ_TX) {
> + pch_can_set_tx_enable(priv, i + 1,
> + priv->tx_enable[i]);
> + }
> + }
> +
> + /* Configuring the receive buffer and enabling them. */
> + for (i = 0; i < PCH_OBJ_NUM; i++) {
> + if (priv->msg_obj[i] == MSG_OBJ_RX) {
> + /* Restore buffer link */
> + pch_can_set_rx_buffer_link(priv, i + 1,
> + priv->rx_link[i]);
> +
> + /* Restore buffer enables */
> + pch_can_set_rx_enable(priv, i + 1, priv->rx_enable[i]);
> + }
> + }
> +
> + /* Enable CAN Interrupts */
> + pch_can_set_int_custom(priv);
> +
> + /* Restore Run Mode */
> + pch_can_set_run_mode(priv, PCH_CAN_RUN);
> +
> + return retval;
> +}
> +#else
> +#define pch_can_suspend NULL
> +#define pch_can_resume NULL
> +#endif
> +
> +static int pch_can_get_berr_counter(const struct net_device *dev,
> + struct can_berr_counter *bec)
> +{
> + struct pch_can_priv *priv = netdev_priv(dev);
> +
> + bec->txerr = ioread32(&priv->regs->errc) & CAN_TEC;
> + bec->rxerr = (ioread32(&priv->regs->errc) & CAN_REC) >> 8;
> +
> + return 0;
> +}
> +
> +static int __devinit pch_can_probe(struct pci_dev *pdev,
> + const struct pci_device_id *id)
> +{
> + struct net_device *ndev;
> + struct pch_can_priv *priv;
> + int rc;
> + int index;
> + void __iomem *addr;
> +
> + rc = pci_enable_device(pdev);
> + if (rc) {
> + dev_err(&pdev->dev, "Failed pci_enable_device %d\n", rc);
> + goto probe_exit_endev;
> + }
> +
> + rc = pci_request_regions(pdev, KBUILD_MODNAME);
is there some pdev->name instead of KBUILD_MODNAME that can be used?
> + if (rc) {
> + dev_err(&pdev->dev, "Failed pci_request_regions %d\n", rc);
> + goto probe_exit_pcireq;
> + }
> +
> + addr = pci_iomap(pdev, 1, 0);
> + if (!addr) {
> + rc = -EIO;
> + dev_err(&pdev->dev, "Failed pci_iomap\n");
> + goto probe_exit_ipmap;
> + }
> +
> + ndev = alloc_candev(sizeof(struct pch_can_priv), PCH_TX_OBJ_NUM);
> + if (!ndev) {
> + rc = -ENOMEM;
> + dev_err(&pdev->dev, "Failed alloc_candev\n");
> + goto probe_exit_alloc_candev;
> + }
> +
> + priv = netdev_priv(ndev);
> + priv->ndev = ndev;
> + priv->regs = addr;
> + priv->dev = pdev;
> + priv->can.bittiming_const = &pch_can_bittiming_const;
> + priv->can.do_set_mode = pch_can_do_set_mode;
> + priv->can.do_get_berr_counter = pch_can_get_berr_counter;
> + priv->can.ctrlmode_supported = CAN_CTRLMODE_LISTENONLY |
> + CAN_CTRLMODE_LOOPBACK;
> + priv->tx_obj = PCH_RX_OBJ_NUM + 1; /* Point head of Tx Obj */
> +
> + ndev->irq = pdev->irq;
> + ndev->flags |= IFF_ECHO;
> +
> + pci_set_drvdata(pdev, ndev);
> + SET_NETDEV_DEV(ndev, &pdev->dev);
> + ndev->netdev_ops = &pch_can_netdev_ops;
> +
> + priv->can.clock.freq = PCH_CAN_CLK; /* Hz */
> + for (index = 0; index < PCH_RX_OBJ_NUM;)
> + priv->msg_obj[index++] = MSG_OBJ_RX;
> +
> + for (index = index; index < PCH_OBJ_NUM;)
> + priv->msg_obj[index++] = MSG_OBJ_TX;
> +
> + netif_napi_add(ndev, &priv->napi, pch_can_rx_poll, PCH_RX_OBJ_NUM);
> +
> + rc = register_candev(ndev);
> + if (rc) {
> + dev_err(&pdev->dev, "Failed register_candev %d\n", rc);
> + goto probe_exit_reg_candev;
> + }
> +
> + return 0;
> +
> +probe_exit_reg_candev:
> + free_candev(ndev);
> +probe_exit_alloc_candev:
> + pci_iounmap(pdev, addr);
> +probe_exit_ipmap:
> + pci_release_regions(pdev);
> +probe_exit_pcireq:
> + pci_disable_device(pdev);
> +probe_exit_endev:
> + return rc;
> +}
> +
> +static struct pci_driver pch_can_pcidev = {
> + .name = "pch_can",
> + .id_table = pch_pci_tbl,
> + .probe = pch_can_probe,
> + .remove = __devexit_p(pch_can_remove),
> + .suspend = pch_can_suspend,
> + .resume = pch_can_resume,
> +};
> +
> +static int __init pch_can_pci_init(void)
> +{
> + return pci_register_driver(&pch_can_pcidev);
> +}
> +module_init(pch_can_pci_init);
> +
> +static void __exit pch_can_pci_exit(void)
> +{
> + pci_unregister_driver(&pch_can_pcidev);
> +}
> +module_exit(pch_can_pci_exit);
> +
> +MODULE_DESCRIPTION("Controller Area Network Driver");
the driver name should apper here
> +MODULE_LICENSE("GPL v2");
> +MODULE_VERSION("0.94");
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 262 bytes --]
[-- Attachment #2: Type: text/plain, Size: 188 bytes --]
_______________________________________________
Socketcan-core mailing list
Socketcan-core-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org
https://lists.berlios.de/mailman/listinfo/socketcan-core
^ permalink raw reply
* Re: [PATCH net-next-2.6 v1] can: Topcliff: Update PCH_CAN driver to 2.6.35
From: Wolfgang Grandegger @ 2010-10-25 7:06 UTC (permalink / raw)
To: Marc Kleine-Budde
Cc: andrew.chih.howe.khor-ral2JQCrhuEAvxtiuMwx3w,
masa-korg-ECg8zkTtlr0C6LszWs/t0g, sameo-VuQAYsv1563Yd54FQh9/CA,
margie.foster-ral2JQCrhuEAvxtiuMwx3w,
netdev-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
yong.y.wang-ral2JQCrhuEAvxtiuMwx3w,
socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
kok.howg.ewe-ral2JQCrhuEAvxtiuMwx3w,
joel.clark-ral2JQCrhuEAvxtiuMwx3w,
morinaga526-ECg8zkTtlr0C6LszWs/t0g, David Miller,
chripell-VaTbYqLCNhc, qi.wang-ral2JQCrhuEAvxtiuMwx3w
In-Reply-To: <4CC4AFF9.90009-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
On 10/25/2010 12:15 AM, Marc Kleine-Budde wrote:
> On 10/25/2010 12:09 AM, David Miller wrote:
>> From: Marc Kleine-Budde <mkl-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
>> Date: Mon, 25 Oct 2010 00:05:25 +0200
>>
>>> On 10/24/2010 11:43 PM, David Miller wrote:
>>>> From: Masayuki Ohtak <masa-korg-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>
>>>> Date: Fri, 15 Oct 2010 22:00:28 +0900
>>>>
>>>>> CAN driver of Topcliff PCH
>>>>>
>>>>> Topcliff PCH is the platform controller hub that is going to be used in
>>>>> Intel's upcoming general embedded platform. All IO peripherals in
>>>>> Topcliff PCH are actually devices sitting on AMBA bus.
>>>>> Topcliff PCH has CAN I/F. This driver enables CAN function.
>>>>>
>>>>> Signed-off-by: Masayuki Ohtake <masa-korg-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>
>>>>
>>>> Applied, thanks.
>>>
>>> IMHO this driver needs some improvements. There are some open points
>>> from Wolfgangs and my review. On the other side, it's a new driver and
>>> there's some time left before it hits mainline.
>>
>> When people have more than a week to review and provide feedback,
>> and don't, I have zero sympathy especially this early in the
>> release cycle.
>
> Let me see....Crap, it's my fault, I just replied to the socketcan
> mailinglist ;( [1]
>
>> So if adding it to the tree is what I have to do to get you guys to
>> post your comments and suggest fixes, then that's what I am going to
>> (continue) to do. :-)
>
> ...or to learn how to reply properly :)
Ah, oh, and I added my review to yours :-(. Sorry, for the inconvenience
it caused:
https://lists.berlios.de/pipermail/socketcan-core/2010-October/004787.html
Anyway, Ohtake should have received the review. The driver is *not* yet
ready for inclusion. Therefore, please fix the remaining issues asap.
Thanks,
Wolfgang.
^ permalink raw reply
* [PATCH 1/4] vlan: rcu annotations
From: Eric Dumazet @ 2010-10-25 7:31 UTC (permalink / raw)
To: David Miller; +Cc: netdev
(struct net_device)->vlgrp is rcu protected :
add __rcu annotation and proper rcu primitives.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
include/linux/netdevice.h | 2 +-
net/8021q/vlan.c | 6 +++---
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index fcd3dda..ceefb441 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -944,7 +944,7 @@ struct net_device {
/* Protocol specific pointers */
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
- struct vlan_group *vlgrp; /* VLAN group */
+ struct vlan_group __rcu *vlgrp; /* VLAN group */
#endif
#ifdef CONFIG_NET_DSA
void *dsa_ptr; /* dsa specific data */
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 05b867e..52077ca 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -112,7 +112,7 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head)
ASSERT_RTNL();
- grp = real_dev->vlgrp;
+ grp = rtnl_dereference(real_dev->vlgrp);
BUG_ON(!grp);
/* Take it out of our own structures, but be sure to interlock with
@@ -177,7 +177,7 @@ int register_vlan_dev(struct net_device *dev)
struct vlan_group *grp, *ngrp = NULL;
int err;
- grp = real_dev->vlgrp;
+ grp = rtnl_dereference(real_dev->vlgrp);
if (!grp) {
ngrp = grp = vlan_group_alloc(real_dev);
if (!grp)
@@ -385,7 +385,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
dev->netdev_ops->ndo_vlan_rx_add_vid(dev, 0);
}
- grp = dev->vlgrp;
+ grp = rtnl_dereference(dev->vlgrp);
if (!grp)
goto out;
^ permalink raw reply related
* [PATCH 2/4] ipv6: ip6_ptr rcu annotations
From: Eric Dumazet @ 2010-10-25 7:32 UTC (permalink / raw)
To: David Miller; +Cc: netdev
(struct net_device)->ip6_ptr is rcu protected :
add __rcu annotation and proper rcu primitives.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
include/linux/netdevice.h | 2 +-
net/core/dev.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index ceefb441..4722d4a 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -952,7 +952,7 @@ struct net_device {
void *atalk_ptr; /* AppleTalk link */
struct in_device __rcu *ip_ptr; /* IPv4 specific data */
void *dn_ptr; /* DECnet specific data */
- void *ip6_ptr; /* IPv6 specific data */
+ struct inet6_dev __rcu *ip6_ptr; /* IPv6 specific data */
void *ec_ptr; /* Econet specific data */
void *ax25_ptr; /* AX.25 specific data */
struct wireless_dev *ieee80211_ptr; /* IEEE 802.11 specific data,
diff --git a/net/core/dev.c b/net/core/dev.c
index 78b5a89..63fd9d9 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -5416,7 +5416,7 @@ void netdev_run_todo(void)
/* paranoia */
BUG_ON(netdev_refcnt_read(dev));
WARN_ON(rcu_dereference_raw(dev->ip_ptr));
- WARN_ON(dev->ip6_ptr);
+ WARN_ON(rcu_dereference_raw(dev->ip6_ptr));
WARN_ON(dev->dn_ptr);
if (dev->destructor)
^ permalink raw reply related
* [PATCH 3/4] net/802: add __rcu annotations
From: Eric Dumazet @ 2010-10-25 7:32 UTC (permalink / raw)
To: David Miller; +Cc: netdev
(struct net_device)->garp_port is rcu protected :
(struct garp_port)->applicants is rcu protected :
add __rcu annotation and proper rcu primitives.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
include/linux/netdevice.h | 2 +-
include/net/garp.h | 2 +-
net/802/garp.c | 18 +++++++++---------
net/802/stp.c | 4 ++--
4 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 4722d4a..b72d5a4 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1072,7 +1072,7 @@ struct net_device {
struct pcpu_dstats __percpu *dstats; /* dummy stats */
};
/* GARP */
- struct garp_port *garp_port;
+ struct garp_port __rcu *garp_port;
/* class/net/name entry */
struct device dev;
diff --git a/include/net/garp.h b/include/net/garp.h
index 825f172..f4c2959 100644
--- a/include/net/garp.h
+++ b/include/net/garp.h
@@ -107,7 +107,7 @@ struct garp_applicant {
};
struct garp_port {
- struct garp_applicant *applicants[GARP_APPLICATION_MAX + 1];
+ struct garp_applicant __rcu *applicants[GARP_APPLICATION_MAX + 1];
};
extern int garp_register_application(struct garp_application *app);
diff --git a/net/802/garp.c b/net/802/garp.c
index 941f2a3..c1df2da 100644
--- a/net/802/garp.c
+++ b/net/802/garp.c
@@ -346,8 +346,8 @@ int garp_request_join(const struct net_device *dev,
const struct garp_application *appl,
const void *data, u8 len, u8 type)
{
- struct garp_port *port = dev->garp_port;
- struct garp_applicant *app = port->applicants[appl->type];
+ struct garp_port *port = rtnl_dereference(dev->garp_port);
+ struct garp_applicant *app = rtnl_dereference(port->applicants[appl->type]);
struct garp_attr *attr;
spin_lock_bh(&app->lock);
@@ -366,8 +366,8 @@ void garp_request_leave(const struct net_device *dev,
const struct garp_application *appl,
const void *data, u8 len, u8 type)
{
- struct garp_port *port = dev->garp_port;
- struct garp_applicant *app = port->applicants[appl->type];
+ struct garp_port *port = rtnl_dereference(dev->garp_port);
+ struct garp_applicant *app = rtnl_dereference(port->applicants[appl->type]);
struct garp_attr *attr;
spin_lock_bh(&app->lock);
@@ -546,11 +546,11 @@ static int garp_init_port(struct net_device *dev)
static void garp_release_port(struct net_device *dev)
{
- struct garp_port *port = dev->garp_port;
+ struct garp_port *port = rtnl_dereference(dev->garp_port);
unsigned int i;
for (i = 0; i <= GARP_APPLICATION_MAX; i++) {
- if (port->applicants[i])
+ if (rtnl_dereference(port->applicants[i]))
return;
}
rcu_assign_pointer(dev->garp_port, NULL);
@@ -565,7 +565,7 @@ int garp_init_applicant(struct net_device *dev, struct garp_application *appl)
ASSERT_RTNL();
- if (!dev->garp_port) {
+ if (!rtnl_dereference(dev->garp_port)) {
err = garp_init_port(dev);
if (err < 0)
goto err1;
@@ -601,8 +601,8 @@ EXPORT_SYMBOL_GPL(garp_init_applicant);
void garp_uninit_applicant(struct net_device *dev, struct garp_application *appl)
{
- struct garp_port *port = dev->garp_port;
- struct garp_applicant *app = port->applicants[appl->type];
+ struct garp_port *port = rtnl_dereference(dev->garp_port);
+ struct garp_applicant *app = rtnl_dereference(port->applicants[appl->type]);
ASSERT_RTNL();
diff --git a/net/802/stp.c b/net/802/stp.c
index 53c8f77..978c30b 100644
--- a/net/802/stp.c
+++ b/net/802/stp.c
@@ -21,8 +21,8 @@
#define GARP_ADDR_MAX 0x2F
#define GARP_ADDR_RANGE (GARP_ADDR_MAX - GARP_ADDR_MIN)
-static const struct stp_proto *garp_protos[GARP_ADDR_RANGE + 1] __read_mostly;
-static const struct stp_proto *stp_proto __read_mostly;
+static const struct stp_proto __rcu *garp_protos[GARP_ADDR_RANGE + 1] __read_mostly;
+static const struct stp_proto __rcu *stp_proto __read_mostly;
static struct llc_sap *sap __read_mostly;
static unsigned int sap_registered;
^ permalink raw reply related
* [PATCH 4/4] tunnels: add _rcu annotations
From: Eric Dumazet @ 2010-10-25 7:33 UTC (permalink / raw)
To: David Miller; +Cc: netdev
(struct ip6_tnl)->next is rcu protected :
(struct ip_tunnel)->next is rcu protected :
(struct xfrm6_tunnel)->next is rcu protected :
add __rcu annotation and proper rcu primitives.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
include/net/ip6_tunnel.h | 2 +-
include/net/ipip.h | 2 +-
include/net/xfrm.h | 2 +-
net/ipv4/gre.c | 5 +++--
net/ipv6/tunnel6.c | 24 +++++++++++++++---------
5 files changed, 21 insertions(+), 14 deletions(-)
diff --git a/include/net/ip6_tunnel.h b/include/net/ip6_tunnel.h
index fc94ec5..fc73e66 100644
--- a/include/net/ip6_tunnel.h
+++ b/include/net/ip6_tunnel.h
@@ -13,7 +13,7 @@
/* IPv6 tunnel */
struct ip6_tnl {
- struct ip6_tnl *next; /* next tunnel in list */
+ struct ip6_tnl __rcu *next; /* next tunnel in list */
struct net_device *dev; /* virtual device associated with tunnel */
struct ip6_tnl_parm parms; /* tunnel configuration parameters */
struct flowi fl; /* flowi template for xmit */
diff --git a/include/net/ipip.h b/include/net/ipip.h
index 58abbf9..0403fe4 100644
--- a/include/net/ipip.h
+++ b/include/net/ipip.h
@@ -16,7 +16,7 @@ struct ip_tunnel_6rd_parm {
};
struct ip_tunnel {
- struct ip_tunnel *next;
+ struct ip_tunnel __rcu *next;
struct net_device *dev;
int err_count; /* Number of arrived ICMP errors */
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index f28d7c9..ffcd478 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1272,7 +1272,7 @@ struct xfrm6_tunnel {
int (*handler)(struct sk_buff *skb);
int (*err_handler)(struct sk_buff *skb, struct inet6_skb_parm *opt,
u8 type, u8 code, int offset, __be32 info);
- struct xfrm6_tunnel *next;
+ struct xfrm6_tunnel __rcu *next;
int priority;
};
diff --git a/net/ipv4/gre.c b/net/ipv4/gre.c
index caea688..c6933f2 100644
--- a/net/ipv4/gre.c
+++ b/net/ipv4/gre.c
@@ -22,7 +22,7 @@
#include <net/gre.h>
-static const struct gre_protocol *gre_proto[GREPROTO_MAX] __read_mostly;
+static const struct gre_protocol __rcu *gre_proto[GREPROTO_MAX] __read_mostly;
static DEFINE_SPINLOCK(gre_proto_lock);
int gre_add_protocol(const struct gre_protocol *proto, u8 version)
@@ -51,7 +51,8 @@ int gre_del_protocol(const struct gre_protocol *proto, u8 version)
goto err_out;
spin_lock(&gre_proto_lock);
- if (gre_proto[version] != proto)
+ if (rcu_dereference_protected(gre_proto[version],
+ lockdep_is_held(&gre_proto_lock)) != proto)
goto err_out_unlock;
rcu_assign_pointer(gre_proto[version], NULL);
spin_unlock(&gre_proto_lock);
diff --git a/net/ipv6/tunnel6.c b/net/ipv6/tunnel6.c
index d986472..4f3cec1 100644
--- a/net/ipv6/tunnel6.c
+++ b/net/ipv6/tunnel6.c
@@ -30,23 +30,26 @@
#include <net/protocol.h>
#include <net/xfrm.h>
-static struct xfrm6_tunnel *tunnel6_handlers __read_mostly;
-static struct xfrm6_tunnel *tunnel46_handlers __read_mostly;
+static struct xfrm6_tunnel __rcu *tunnel6_handlers __read_mostly;
+static struct xfrm6_tunnel __rcu *tunnel46_handlers __read_mostly;
static DEFINE_MUTEX(tunnel6_mutex);
int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family)
{
- struct xfrm6_tunnel **pprev;
+ struct xfrm6_tunnel __rcu **pprev;
+ struct xfrm6_tunnel *t;
int ret = -EEXIST;
int priority = handler->priority;
mutex_lock(&tunnel6_mutex);
for (pprev = (family == AF_INET6) ? &tunnel6_handlers : &tunnel46_handlers;
- *pprev; pprev = &(*pprev)->next) {
- if ((*pprev)->priority > priority)
+ (t = rcu_dereference_protected(*pprev,
+ lockdep_is_held(&tunnel6_mutex))) != NULL;
+ pprev = &t->next) {
+ if (t->priority > priority)
break;
- if ((*pprev)->priority == priority)
+ if (t->priority == priority)
goto err;
}
@@ -65,14 +68,17 @@ EXPORT_SYMBOL(xfrm6_tunnel_register);
int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family)
{
- struct xfrm6_tunnel **pprev;
+ struct xfrm6_tunnel __rcu **pprev;
+ struct xfrm6_tunnel *t;
int ret = -ENOENT;
mutex_lock(&tunnel6_mutex);
for (pprev = (family == AF_INET6) ? &tunnel6_handlers : &tunnel46_handlers;
- *pprev; pprev = &(*pprev)->next) {
- if (*pprev == handler) {
+ (t = rcu_dereference_protected(*pprev,
+ lockdep_is_held(&tunnel6_mutex))) != NULL;
+ pprev = &t->next) {
+ if (t == handler) {
*pprev = handler->next;
ret = 0;
break;
^ permalink raw reply related
* [patch 0/1] ipv6 POSTDAD fix
From: Ursula Braun @ 2010-10-25 9:06 UTC (permalink / raw)
To: netdev, linux-s390; +Cc: vosburgh
Dave,
running into a refcnt problem with a bond device,
I propose this patch to solve it.
Regards, Ursula
^ permalink raw reply
* [patch 1/1] [PATCH BUG_FIX] ipv6: fix refcnt problem related to POSTDAD state
From: Ursula Braun @ 2010-10-25 9:06 UTC (permalink / raw)
To: netdev, linux-s390; +Cc: vosburgh, Ursula Braun, David S. Miller, Herbert Xu
In-Reply-To: <20101025090642.958260964@linux.vnet.ibm.com>
[-- Attachment #1: addrconf.patch --]
[-- Type: text/plain, Size: 1281 bytes --]
Subject: [patch 1/1] [PATCH BUG_FIX] ipv6: fix refcnt problem related to POSTDAD state
From: Ursula Braun <ursula.braun@de.ibm.com>
After running this bonding setup script
modprobe bonding miimon=100 mode=0 max_bonds=1
ifconfig bond0 10.1.1.1/16
ifenslave bond0 eth1
ifenslave bond0 eth3
on s390 with qeth-driven slaves, modprobe -r fails with this message
unregister_netdevice: waiting for bond0 to become free. Usage count = 1
due to twice detection of duplicate address.
Problem is caused by a missing decrease of ifp->refcnt in addrconf_dad_failure.
An extra call of in6_ifa_put(ifp) solves it.
Problem has been introduced with commit f2344a131bccdbfc5338e17fa71a807dee7944fa.
Signed-off-by: Ursula Braun <ursula.braun@de.ibm.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
---
net/ipv6/addrconf.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1426,8 +1426,10 @@ void addrconf_dad_failure(struct inet6_i
{
struct inet6_dev *idev = ifp->idev;
- if (addrconf_dad_end(ifp))
+ if (addrconf_dad_end(ifp)) {
+ in6_ifa_put(ifp);
return;
+ }
if (net_ratelimit())
printk(KERN_INFO "%s: IPv6 duplicate address %pI6c detected!\n",
^ permalink raw reply
* 2.6.35->2.6.36 regression, vanilla kernel panic, ppp or hrtimers crashing
From: Denys Fedoryshchenko @ 2010-10-25 9:22 UTC (permalink / raw)
To: Thomas Gleixner, Paul Mackerras, linux-kernel, netdev
Hi
Here is what i got from netconsole
[ 259.238755] BUG: unable to handle kernel
paging request
at f8ba001c
[ 259.238953] IP:
[<c0199ebe>] do_select+0x2cc/0x502
[ 259.239008] *pdpt = 0000000000a55001
*pde = 0000000036dd6067
*pte = 0000000000000000
[ 259.239008] Oops: 0000 [#1]
SMP
[ 259.239008] last sysfs file: /sys/devices/pnp0/00:02/rtc/rtc0/dev
[ 259.239008] Modules linked in:
rtc_cmos
rtc_core
rtc_lib
act_skbedit
sch_ingress
sch_prio
configfs
cls_flow
cls_u32
em_meta
cls_basic
xt_dscp
ipt_REJECT
ts_bm
xt_string
xt_hl
ifb
cls_fw
sch_tbf
sch_htb
act_ipt
act_mirred
pppoe
pppox
ppp_generic
slhc
ipt_REDIRECT
ipt_MASQUERADE
xt_TCPMSS
xt_DSCP
xt_mark
xt_tcpudp
iptable_mangle
iptable_nat
nf_nat
nf_conntrack_ipv4
nf_conntrack
nf_defrag_ipv4
iptable_filter
ip_tables
x_tables
8021q
garp
stp
llc
loop
usb_storage
iTCO_wdt
iTCO_vendor_support
ata_generic
pata_acpi
ata_piix
libata
8139cp
sr_mod
cdrom
tulip
r8169
sky2
via_velocity
via_rhine
sis900
ne2k_pci
8390
skge
tg3
libphy
8139too
e1000
e100
usbhid
ohci_hcd
uhci_hcd
ehci_hcd
usbcore
nls_base
[ 259.239008]
[ 259.239008] Pid: 3307, comm: pppd Not tainted 2.6.36-build-0053 #14
D915GAV /
[ 259.239008] EIP: 0060:[<c0199ebe>] EFLAGS: 00010286 CPU: 0
[ 259.239008] EIP is at do_select+0x2cc/0x502
[ 259.239008] EAX: f610a600 EBX: 00000080 ECX: f8ba0000 EDX: f60f1808
[ 259.239008] ESI: 00000000 EDI: f610a600 EBP: f60eae4c ESP: f60eab64
[ 259.239008] DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068
[ 259.239008] Process pppd (pid: 3307, ti=f60ea000 task=f66a0000
task.ti=f60ea000)
[ 259.239008] Stack:
[ 259.239008] 0e95bb42
0000003d
000000d0
00000000
f60eaf60
f66a0000
f60eae6c
f60eae70
[ 259.239008] <0>
f60eae74
f60eae60
f60eae64
f60eae68
00000180
00000020
010eabdc
002dc698
[ 259.239008] <0>
f60eae34
00000180
00000000
00000180
00000000
00000000
00000000
00000000
[ 259.239008] Call Trace:
[ 259.239008] [<c019a484>] ? __pollwait+0x0/0xa5
[ 259.239008] [<c019a529>] ? pollwake+0x0/0x63
[ 259.239008] [<c019a529>] ? pollwake+0x0/0x63
[ 259.239008] [<c0143f37>] ? sched_clock_local+0x17/0x13d
[ 259.239008] [<c0122ac4>] ? update_curr+0x84/0x15c
[ 259.239008] [<c011f5a3>] ? kmap_atomic_prot+0xe1/0xe3
[ 259.239008] [<c0143f37>] ? sched_clock_local+0x17/0x13d
[ 259.239008] [<c02044ee>] ? put_dec+0x2a/0x74
[ 259.239008] [<c0204689>] ? number+0x151/0x223
[ 259.239008] [<c012461f>] ? dequeue_task_fair+0x283/0x28b
[ 259.239008] [<c0123845>] ? __dequeue_entity+0x23/0x27
[ 259.239008] [<c01238d6>] ? set_next_entity+0x8d/0xf7
[ 259.239008] [<c012889c>] ? finish_task_switch+0x33/0x7a
[ 259.239008] [<c02f931c>] ? schedule+0x5c0/0x5ff
[ 259.239008] [<c019a208>] ? core_sys_select+0x114/0x190
[ 259.239008] [<c015ce1c>] ? call_rcu_sched+0xd/0xf
[ 259.239008] [<c015ce26>] ? call_rcu+0x8/0xa
[ 259.239008] [<c012f80b>] ? release_task+0x28d/0x29d
[ 259.239008] [<c012fc80>] ? wait_consider_task+0x465/0x7b7
[ 259.239008] [<c013fa7f>] ? spin_unlock_irqrestore+0x8/0xa
[ 259.239008] [<c013fc10>] ? remove_wait_queue+0x31/0x36
[ 259.239008] [<f8bacff1>] ? ppp_read+0x101/0x145 [ppp_generic]
[ 259.239008] [<c0145ceb>] ? timekeeping_get_ns+0x11/0x4f
[ 259.239008] [<c014688a>] ? ktime_get_ts+0x89/0x93
[ 259.239008] [<c019a42e>] ? sys_select+0x68/0x84
[ 259.239008] [<c02fa625>] ? syscall_call+0x7/0xb
[ 259.239008] Code:
85
9d
48
fd
ff
ff
0f
84
cb
00
00
00
8b
85
7c
fd
ff
ff
8d
55
f0
e8
c1
55
ff
ff
85
c0
89
c7
0f
84
b3
00
00
00
8b
48
10
85
c9
74
3a
79
1c
00
74
34
85
f6
74
25
c7
46
04
02
00
00
00
85
9d
5c
fd
[ 259.239008] EIP: [<c0199ebe>]
do_select+0x2cc/0x502
SS:ESP 0068:f60eab64
[ 259.239008] CR2: 00000000f8ba001c
[ 259.239008] ---[ end trace a6117b9e067aeb87 ]---
[ 259.239008] Kernel panic - not syncing: Fatal exception
[ 259.239008] Pid: 3307, comm: pppd Tainted: G D 2.6.36-build-0053
#14
[ 259.239008] Call Trace:
[ 259.239008] [<c02f8ace>] ? printk+0xf/0x11
[ 259.239008] [<c02f89cb>] panic+0x50/0x144
[ 259.239008] [<c0105061>] oops_end+0x8b/0x9a
[ 259.239008] [<c011af70>] no_context+0x13e/0x148
[ 259.239008] [<c0142b8c>] ? hrtimer_try_to_cancel+0x60/0x69
[ 259.239008] [<c011b05f>] __bad_area_nosemaphore+0xe5/0xed
[ 259.239008] [<c011b074>] bad_area_nosemaphore+0xd/0x10
[ 259.239008] [<c011b2d6>] do_page_fault+0xf6/0x230
[ 259.239008] [<c011b1e0>] ? do_page_fault+0x0/0x230
[ 259.239008] [<c02fac22>] error_code+0x5a/0x60
[ 259.239008] [<c019007b>] ? grab_super+0x30/0x56
[ 259.239008] [<c011b1e0>] ? do_page_fault+0x0/0x230
[ 259.239008] [<c0199ebe>] ? do_select+0x2cc/0x502
[ 259.239008] [<c019a484>] ? __pollwait+0x0/0xa5
[ 259.239008] [<c019a529>] ? pollwake+0x0/0x63
[ 259.239008] [<c019a529>] ? pollwake+0x0/0x63
[ 259.239008] [<c0143f37>] ? sched_clock_local+0x17/0x13d
[ 259.239008] [<c0122ac4>] ? update_curr+0x84/0x15c
[ 259.239008] [<c011f5a3>] ? kmap_atomic_prot+0xe1/0xe3
[ 259.239008] [<c0143f37>] ? sched_clock_local+0x17/0x13d
[ 259.239008] [<c02044ee>] ? put_dec+0x2a/0x74
[ 259.239008] [<c0204689>] ? number+0x151/0x223
[ 259.239008] [<c012461f>] ? dequeue_task_fair+0x283/0x28b
[ 259.239008] [<c0123845>] ? __dequeue_entity+0x23/0x27
[ 259.239008] [<c01238d6>] ? set_next_entity+0x8d/0xf7
[ 259.239008] [<c012889c>] ? finish_task_switch+0x33/0x7a
[ 259.239008] [<c02f931c>] ? schedule+0x5c0/0x5ff
[ 259.239008] [<c019a208>] core_sys_select+0x114/0x190
[ 259.239008] [<c015ce1c>] ? call_rcu_sched+0xd/0xf
[ 259.239008] [<c015ce26>] ? call_rcu+0x8/0xa
[ 259.239008] [<c012f80b>] ? release_task+0x28d/0x29d
[ 259.239008] [<c012fc80>] ? wait_consider_task+0x465/0x7b7
[ 259.239008] [<c013fa7f>] ? spin_unlock_irqrestore+0x8/0xa
[ 259.239008] [<c013fc10>] ? remove_wait_queue+0x31/0x36
[ 259.239008] [<f8bacff1>] ? ppp_read+0x101/0x145 [ppp_generic]
[ 259.239008] [<c0145ceb>] ? timekeeping_get_ns+0x11/0x4f
[ 259.239008] [<c014688a>] ? ktime_get_ts+0x89/0x93
[ 259.239008] [<c019a42e>] sys_select+0x68/0x84
[ 259.239008] [<c02fa625>] syscall_call+0x7/0xb
[ 259.239008] Rebooting in 5 seconds..
It is not easy to do full git bisect(it is semi-embedded distro), but i can
try reversing particular commits, if someone can give idea which one, and can
try debug patches.
^ permalink raw reply
* Re: [PATCH v2 1/9] tproxy: split off ipv6 defragmentation to a separate module
From: KOVACS Krisztian @ 2010-10-25 9:38 UTC (permalink / raw)
To: Eric Dumazet
Cc: Patrick McHardy, netdev, netfilter-devel, Balazs Scheidler,
David Miller
In-Reply-To: <1287699558.2607.5.camel@edumazet-laptop>
Hi,
On Fri, 2010-10-22 at 00:19 +0200, Eric Dumazet wrote:
> Le jeudi 21 octobre 2010 à 16:04 +0200, Patrick McHardy a écrit :
> > Am 21.10.2010 13:43, schrieb KOVACS Krisztian:
> > > tproxy: split off ipv6 defragmentation to a separate module
> > >
> > > Like with IPv4, TProxy needs IPv6 defragmentation but does not
> > > require connection tracking. Since defragmentation was coupled
> > > with conntrack, I split off the two, creating an nf_defrag_ipv6 module,
> > > similar to the already existing nf_defrag_ipv4.
> >
> > Applied, thanks.
>
> Hmm...
>
> CONFIG_IPV6=m
> CONFIG_NETFILTER_TPROXY=m
>
>
> MODPOST 201 modules
> ERROR: "nf_defrag_ipv6_enable" [net/netfilter/xt_TPROXY.ko] undefined!
> ERROR: "ipv6_find_hdr" [net/netfilter/xt_TPROXY.ko] undefined!
>
> Sorry, it's late here, I wont fix this ;)
Oops, I guess this is because you do have IPv6 support but don't have
ip6tables enabled in your config. Does the patch below fix the issue for
you? (For me it now compiles with and without IPv6 conntrack, ip6tables
and IPv6 support, too.)
netfilter: fix module dependency issues with IPv6 defragmentation, ip6tables and xt_TPROXY
One of the previous tproxy related patches split IPv6 defragmentation and
connection tracking, but did not correctly add Kconfig stanzas to handle the
new dependencies correctly. This patch fixes that by making the config options
mirror the setup we have for IPv4: a distinct config option for defragmentation
that is automatically selected by both connection tracking and
xt_TPROXY/xt_socket.
The patch also changes the #ifdefs enclosing IPv6 specific code in xt_socket
and xt_TPROXY: we only compile these in case we have ip6tables support enabled.
Signed-off-by: KOVACS Krisztian <hidden@balabit.hu>
---
net/ipv6/netfilter/Kconfig | 5 +++++
net/ipv6/netfilter/Makefile | 5 ++++-
net/netfilter/Kconfig | 2 ++
net/netfilter/xt_TPROXY.c | 10 ++++++----
net/netfilter/xt_socket.c | 12 ++++++++----
5 files changed, 25 insertions(+), 9 deletions(-)
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index 29d643b..e5f6edc 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -5,10 +5,15 @@
menu "IPv6: Netfilter Configuration"
depends on INET && IPV6 && NETFILTER
+config NF_DEFRAG_IPV6
+ tristate
+ default n
+
config NF_CONNTRACK_IPV6
tristate "IPv6 connection tracking support"
depends on INET && IPV6 && NF_CONNTRACK
default m if NETFILTER_ADVANCED=n
+ select NF_DEFRAG_IPV6
---help---
Connection tracking keeps a record of what packets have passed
through your machine, in order to figure out how they are related
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
index 3f8e4a3..0a432c9 100644
--- a/net/ipv6/netfilter/Makefile
+++ b/net/ipv6/netfilter/Makefile
@@ -12,11 +12,14 @@ obj-$(CONFIG_IP6_NF_SECURITY) += ip6table_security.o
# objects for l3 independent conntrack
nf_conntrack_ipv6-objs := nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o
-nf_defrag_ipv6-objs := nf_defrag_ipv6_hooks.o nf_conntrack_reasm.o
# l3 independent conntrack
obj-$(CONFIG_NF_CONNTRACK_IPV6) += nf_conntrack_ipv6.o nf_defrag_ipv6.o
+# defrag
+nf_defrag_ipv6-objs := nf_defrag_ipv6_hooks.o nf_conntrack_reasm.o
+obj-$(CONFIG_NF_DEFRAG_IPV6) += nf_defrag_ipv6.o
+
# matches
obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o
obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 4328825..1534f2b 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -525,6 +525,7 @@ config NETFILTER_XT_TARGET_TPROXY
depends on NETFILTER_XTABLES
depends on NETFILTER_ADVANCED
select NF_DEFRAG_IPV4
+ select NF_DEFRAG_IPV6 if IP6_NF_IPTABLES
help
This option adds a `TPROXY' target, which is somewhat similar to
REDIRECT. It can only be used in the mangle table and is useful
@@ -927,6 +928,7 @@ config NETFILTER_XT_MATCH_SOCKET
depends on NETFILTER_ADVANCED
depends on !NF_CONNTRACK || NF_CONNTRACK
select NF_DEFRAG_IPV4
+ select NF_DEFRAG_IPV6 if IP6_NF_IPTABLES
help
This option adds a `socket' match, which can be used to match
packets for which a TCP or UDP socket lookup finds a valid socket.
diff --git a/net/netfilter/xt_TPROXY.c b/net/netfilter/xt_TPROXY.c
index 19c482c..640678f 100644
--- a/net/netfilter/xt_TPROXY.c
+++ b/net/netfilter/xt_TPROXY.c
@@ -21,7 +21,9 @@
#include <linux/netfilter_ipv4/ip_tables.h>
#include <net/netfilter/ipv4/nf_defrag_ipv4.h>
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+
+#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
+#define XT_TPROXY_HAVE_IPV6 1
#include <net/if_inet6.h>
#include <net/addrconf.h>
#include <linux/netfilter_ipv6/ip6_tables.h>
@@ -172,7 +174,7 @@ tproxy_tg4_v1(struct sk_buff *skb, const struct xt_action_param *par)
return tproxy_tg4(skb, tgi->laddr.ip, tgi->lport, tgi->mark_mask, tgi->mark_value);
}
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#ifdef XT_TPROXY_HAVE_IPV6
static inline const struct in6_addr *
tproxy_laddr6(struct sk_buff *skb, const struct in6_addr *user_laddr,
@@ -372,7 +374,7 @@ static struct xt_target tproxy_tg_reg[] __read_mostly = {
.hooks = 1 << NF_INET_PRE_ROUTING,
.me = THIS_MODULE,
},
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#ifdef XT_TPROXY_HAVE_IPV6
{
.name = "TPROXY",
.family = NFPROTO_IPV6,
@@ -391,7 +393,7 @@ static struct xt_target tproxy_tg_reg[] __read_mostly = {
static int __init tproxy_tg_init(void)
{
nf_defrag_ipv4_enable();
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#ifdef XT_TPROXY_HAVE_IPV6
nf_defrag_ipv6_enable();
#endif
diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c
index 2dbd4c8..d94a858 100644
--- a/net/netfilter/xt_socket.c
+++ b/net/netfilter/xt_socket.c
@@ -14,7 +14,6 @@
#include <linux/skbuff.h>
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv6/ip6_tables.h>
#include <net/tcp.h>
#include <net/udp.h>
#include <net/icmp.h>
@@ -22,7 +21,12 @@
#include <net/inet_sock.h>
#include <net/netfilter/nf_tproxy_core.h>
#include <net/netfilter/ipv4/nf_defrag_ipv4.h>
+
+#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
+#define XT_SOCKET_HAVE_IPV6 1
+#include <linux/netfilter_ipv6/ip6_tables.h>
#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
+#endif
#include <linux/netfilter/xt_socket.h>
@@ -186,7 +190,7 @@ socket_mt4_v1(const struct sk_buff *skb, struct xt_action_param *par)
return socket_match(skb, par, par->matchinfo);
}
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#ifdef XT_SOCKET_HAVE_IPV6
static int
extract_icmp6_fields(const struct sk_buff *skb,
@@ -331,7 +335,7 @@ static struct xt_match socket_mt_reg[] __read_mostly = {
(1 << NF_INET_LOCAL_IN),
.me = THIS_MODULE,
},
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#ifdef XT_SOCKET_HAVE_IPV6
{
.name = "socket",
.revision = 1,
@@ -348,7 +352,7 @@ static struct xt_match socket_mt_reg[] __read_mostly = {
static int __init socket_mt_init(void)
{
nf_defrag_ipv4_enable();
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#ifdef XT_SOCKET_HAVE_IPV6
nf_defrag_ipv6_enable();
#endif
^ permalink raw reply related
* Re: [PATCH v2 1/9] tproxy: split off ipv6 defragmentation to a separate module
From: Eric Dumazet @ 2010-10-25 10:14 UTC (permalink / raw)
To: KOVACS Krisztian
Cc: Patrick McHardy, netdev, netfilter-devel, Balazs Scheidler,
David Miller
In-Reply-To: <1287999512.2160.25.camel@este.odu>
Le lundi 25 octobre 2010 à 11:38 +0200, KOVACS Krisztian a écrit :
> Hi,
>
> On Fri, 2010-10-22 at 00:19 +0200, Eric Dumazet wrote:
> > Le jeudi 21 octobre 2010 à 16:04 +0200, Patrick McHardy a écrit :
> > > Am 21.10.2010 13:43, schrieb KOVACS Krisztian:
> > > > tproxy: split off ipv6 defragmentation to a separate module
> > > >
> > > > Like with IPv4, TProxy needs IPv6 defragmentation but does not
> > > > require connection tracking. Since defragmentation was coupled
> > > > with conntrack, I split off the two, creating an nf_defrag_ipv6 module,
> > > > similar to the already existing nf_defrag_ipv4.
> > >
> > > Applied, thanks.
> >
> > Hmm...
> >
> > CONFIG_IPV6=m
> > CONFIG_NETFILTER_TPROXY=m
> >
> >
> > MODPOST 201 modules
> > ERROR: "nf_defrag_ipv6_enable" [net/netfilter/xt_TPROXY.ko] undefined!
> > ERROR: "ipv6_find_hdr" [net/netfilter/xt_TPROXY.ko] undefined!
> >
> > Sorry, it's late here, I wont fix this ;)
>
> Oops, I guess this is because you do have IPv6 support but don't have
> ip6tables enabled in your config. Does the patch below fix the issue for
> you? (For me it now compiles with and without IPv6 conntrack, ip6tables
> and IPv6 support, too.)
>
>
I had ip6tables enabled, but not CONFIG_NF_CONNTRACK_IPV6 ;)
>
> netfilter: fix module dependency issues with IPv6 defragmentation, ip6tables and xt_TPROXY
>
> One of the previous tproxy related patches split IPv6 defragmentation and
> connection tracking, but did not correctly add Kconfig stanzas to handle the
> new dependencies correctly. This patch fixes that by making the config options
> mirror the setup we have for IPv4: a distinct config option for defragmentation
> that is automatically selected by both connection tracking and
> xt_TPROXY/xt_socket.
>
> The patch also changes the #ifdefs enclosing IPv6 specific code in xt_socket
> and xt_TPROXY: we only compile these in case we have ip6tables support enabled.
>
> Signed-off-by: KOVACS Krisztian <hidden@balabit.hu>
Reported-and-tested-by: Eric Dumazet <eric.dumazet@gmail.com>
Thanks !
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* ***IMPORTANT NOTICE***
From: Mr Jerry Ntai @ 2010-10-25 10:56 UTC (permalink / raw)
MR.JERRY NTAI.
MEVAS BANK
QUEEN`S ROAD
CENTRAL BRANCH,
HONG KONG.
Good Day,
Please kindly accept my apology for sending you this email without your consent. I believe you are a highly respected personality, considering the fact that I sourced your email from the peoples search database on the web during my descret search for a foreign partner whom can assist me in taking this business to it success. Though, I do not know to what extent you are familiar with events. I have a proposal for you.This however is not mandatory nor will I in any manner compel you to honor against your will, but I hope you will read on and consider the value I offer.
My name is Mr. Jerry Ntai, I am the Head of Operations in Mevas Bank, Hong Kong. I have a business proposal in the tune of US$25.2m to be transferred to an offshore account with your assistance if willing.
After the successful transfer, we shall share in ratio of 30% for you and 70% for me. Should you be interested, please
respond to my letter immediately, so we can commence all arrangements and I will give you more information on the project and
how we would handle it.
You can contact me on my private email:(mrjerryntai72@yahoo.com.hk) and send me the following information for documentation
purpose:
(1)Full name:
(2)private phone number:
(3)current residential address:
(4)Occupation:
(5)Age and Sex:
I look forward to hearing from you.
Kind Regards,
Mr.Jerry Ntai.
^ permalink raw reply
* [PATCH 1/2] be2net: Call netif_carier_off() after register_netdev()
From: Somnath Kotur @ 2010-10-25 11:11 UTC (permalink / raw)
To: netdev
Calling netif_carrier_off before register_netdev was causing the network interface
to miss a linkwatch pending event leading to an inconsistent state if the link
is not up when interface is initialized.This is now invoked after register_netdev.
Signed-off-by: Somnath Kotur <somnath.kotur@emulex.com>
---
drivers/net/benet/be_main.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c
index 1248626..8767355 100644
--- a/drivers/net/benet/be_main.c
+++ b/drivers/net/benet/be_main.c
@@ -2556,7 +2556,6 @@ static void be_netdev_init(struct net_device *netdev)
netif_napi_add(netdev, &adapter->tx_eq.napi, be_poll_tx_mcc,
BE_NAPI_WEIGHT);
- netif_carrier_off(netdev);
netif_stop_queue(netdev);
}
@@ -2865,6 +2864,7 @@ static int __devinit be_probe(struct pci_dev *pdev,
status = register_netdev(netdev);
if (status != 0)
goto unsetup;
+ netif_carrier_off(netdev);
dev_info(&pdev->dev, "%s port %d\n", nic_name(pdev), adapter->port_num);
return 0;
--
1.5.6.1
^ permalink raw reply related
* [PATCH 2/2] be2net: Fix CSO for UDP packets
From: Somnath Kotur @ 2010-10-25 11:11 UTC (permalink / raw)
To: netdev
We're setting skb->ip_summed to CHECKSUM_NONE for all non-TCP pkts, making the stack
recompute checksum.This is a bug for UDP pkts for which cso must be used.
Signed-off-by: Somnath Kotur <somnath.kotur@emulex.com>
---
drivers/net/benet/be_main.c | 20 ++++++++------------
1 files changed, 8 insertions(+), 12 deletions(-)
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c
index 8767355..6b80a06 100644
--- a/drivers/net/benet/be_main.c
+++ b/drivers/net/benet/be_main.c
@@ -849,20 +849,16 @@ static void be_rx_stats_update(struct be_rx_obj *rxo,
stats->rx_mcast_pkts++;
}
-static inline bool do_pkt_csum(struct be_eth_rx_compl *rxcp, bool cso)
+static inline bool csum_passed(struct be_eth_rx_compl *rxcp)
{
- u8 l4_cksm, ip_version, ipcksm, tcpf = 0, udpf = 0, ipv6_chk;
+ u8 l4_cksm, ipv6, ipcksm;
l4_cksm = AMAP_GET_BITS(struct amap_eth_rx_compl, l4_cksm, rxcp);
ipcksm = AMAP_GET_BITS(struct amap_eth_rx_compl, ipcksm, rxcp);
- ip_version = AMAP_GET_BITS(struct amap_eth_rx_compl, ip_version, rxcp);
- if (ip_version) {
- tcpf = AMAP_GET_BITS(struct amap_eth_rx_compl, tcpf, rxcp);
- udpf = AMAP_GET_BITS(struct amap_eth_rx_compl, udpf, rxcp);
- }
- ipv6_chk = (ip_version && (tcpf || udpf));
+ ipv6 = AMAP_GET_BITS(struct amap_eth_rx_compl, ip_version, rxcp);
- return ((l4_cksm && ipv6_chk && ipcksm) && cso) ? false : true;
+ /* Ignore ipcksm for ipv6 pkts */
+ return l4_cksm && (ipcksm || ipv6);
}
static struct be_rx_page_info *
@@ -1017,10 +1013,10 @@ static void be_rx_compl_process(struct be_adapter *adapter,
skb_fill_rx_data(adapter, rxo, skb, rxcp, num_rcvd);
- if (do_pkt_csum(rxcp, adapter->rx_csum))
- skb_checksum_none_assert(skb);
- else
+ if (likely(adapter->rx_csum && csum_passed(rxcp)))
skb->ip_summed = CHECKSUM_UNNECESSARY;
+ else
+ skb_checksum_none_assert(skb);
skb->truesize = skb->len + sizeof(struct sk_buff);
skb->protocol = eth_type_trans(skb, adapter->netdev);
--
1.5.6.1
^ permalink raw reply related
* [PATCH net-next-2.6 1/2] be2net: Adding an option to use INTx instead of MSI-X
From: Somnath Kotur @ 2010-10-25 11:12 UTC (permalink / raw)
To: netdev
By default, be2net uses MSIx wherever possible.
Adding a module parameter to use INTx for users who do not want to use MSIx.
Signed-off-by: Somnath Kotur <somnath.kotur@emulex.com>
---
drivers/net/benet/be_main.c | 12 +++++++++++-
1 files changed, 11 insertions(+), 1 deletions(-)
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c
index 45b1f66..1262292 100644
--- a/drivers/net/benet/be_main.c
+++ b/drivers/net/benet/be_main.c
@@ -27,10 +27,13 @@ MODULE_LICENSE("GPL");
static unsigned int rx_frag_size = 2048;
static unsigned int num_vfs;
+static unsigned int msix = 1;
module_param(rx_frag_size, uint, S_IRUGO);
module_param(num_vfs, uint, S_IRUGO);
+module_param(msix, uint, S_IRUGO);
MODULE_PARM_DESC(rx_frag_size, "Size of a fragment that holds rcvd data.");
MODULE_PARM_DESC(num_vfs, "Number of PCI VFs to initialize");
+MODULE_PARM_DESC(msix, "Enable/Disable the MSIx (MSIx enabled by default)");
static bool multi_rxq = true;
module_param(multi_rxq, bool, S_IRUGO | S_IWUSR);
@@ -2856,7 +2859,8 @@ static int __devinit be_probe(struct pci_dev *pdev,
if (status)
goto stats_clean;
- be_msix_enable(adapter);
+ if (msix)
+ be_msix_enable(adapter);
INIT_DELAYED_WORK(&adapter->work, be_worker);
@@ -3082,6 +3086,12 @@ static int __init be_init_module(void)
num_vfs = 32;
}
+ if (!msix && num_vfs > 0) {
+ printk(KERN_WARNING DRV_NAME
+ " : MSIx required for num_vfs > 0. Ignoring msix=0\n");
+ msix = 1;
+ }
+
return pci_register_driver(&be_driver);
}
module_init(be_init_module);
--
1.5.6.1
^ permalink raw reply related
* [PATCH net-next-2.6 2/2] be2net: Schedule/Destroy worker thread in probe()/remove() rather than open()/close()
From: Somnath Kotur @ 2010-10-25 11:13 UTC (permalink / raw)
To: netdev
When async mcc compls are rcvd on an i/f that is down (and so interrupts are disabled)
they just lie unprocessed in the compl queue.The compl queue can eventually get filled
up and cause the BE to lock up.The fix is to use be_worker to reap mcc compls when the
i/f is down.be_worker is now launched in be_probe() and canceled in be_remove().
Signed-off-by: Somnath Kotur <somnath.kotur@emulex.com>
---
drivers/net/benet/be_main.c | 22 ++++++++++++++++++----
1 files changed, 18 insertions(+), 4 deletions(-)
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c
index 1262292..2546273 100644
--- a/drivers/net/benet/be_main.c
+++ b/drivers/net/benet/be_main.c
@@ -1809,6 +1809,20 @@ static void be_worker(struct work_struct *work)
struct be_rx_obj *rxo;
int i;
+ /* when interrupts are not yet enabled, just reap any pending
+ * mcc completions */
+ if (!netif_running(adapter->netdev)) {
+ int mcc_compl, status = 0;
+
+ mcc_compl = be_process_mcc(adapter, &status);
+
+ if (mcc_compl) {
+ struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
+ be_cq_notify(adapter, mcc_obj->cq.id, false, mcc_compl);
+ }
+ goto reschedule;
+ }
+
if (!adapter->stats_ioctl_sent)
be_cmd_get_stats(adapter, &adapter->stats_cmd);
@@ -1827,6 +1841,7 @@ static void be_worker(struct work_struct *work)
if (!adapter->ue_detected)
be_detect_dump_ue(adapter);
+reschedule:
schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000));
}
@@ -2022,8 +2037,6 @@ static int be_close(struct net_device *netdev)
struct be_eq_obj *tx_eq = &adapter->tx_eq;
int vec, i;
- cancel_delayed_work_sync(&adapter->work);
-
be_async_mcc_disable(adapter);
netif_stop_queue(netdev);
@@ -2088,8 +2101,6 @@ static int be_open(struct net_device *netdev)
/* Now that interrupts are on we can process async mcc */
be_async_mcc_enable(adapter);
- schedule_delayed_work(&adapter->work, msecs_to_jiffies(100));
-
status = be_cmd_link_status_query(adapter, &link_up, &mac_speed,
&link_speed);
if (status)
@@ -2718,6 +2729,8 @@ static void __devexit be_remove(struct pci_dev *pdev)
if (!adapter)
return;
+ cancel_delayed_work_sync(&adapter->work);
+
unregister_netdev(adapter->netdev);
be_clear(adapter);
@@ -2874,6 +2887,7 @@ static int __devinit be_probe(struct pci_dev *pdev,
goto unsetup;
dev_info(&pdev->dev, "%s port %d\n", nic_name(pdev), adapter->port_num);
+ schedule_delayed_work(&adapter->work, msecs_to_jiffies(100));
return 0;
unsetup:
--
1.5.6.1
^ permalink raw reply related
* RE: [PATCH] macb: Don't re-enable interrupts while in polling mode
From: Joshua Hoke @ 2010-10-25 11:44 UTC (permalink / raw)
To: David Miller
Cc: nicolas.ferre, jpirko, peter.korsgaard, eric.dumazet,
haavard.skinnemoen, netdev, linux-kernel, akpm
In-Reply-To: <20101024.152306.48512783.davem@davemloft.net>
> Your email client is breaking up long lines which corrupts the
> patch.
>
> Please fix this up in your email client and resubmit.
Thanks for pointing this out. It looks fine in my sent folder but here's
a second try. In case this doesn't work, I've attached the contents to the bug as: https://bugzilla.kernel.org/attachment.cgi?id=34972
Contents of first e-mail follow, maybe not mangled this time.
From: Joshua Hoke <joshua.hoke@sixnet.com>
[PATCH] macb: Don't re-enable interrupts while in polling mode
On a busy network, the macb driver could get stuck in the interrupt
handler, quickly triggering the watchdog, due to a confluence of
factors:
1. macb_poll re-enables interrupts unconditionally, even when it will
be called again because it exhausted its rx budget
2. macb_interrupt only disables interrupts after scheduling
macb_poll, but scheduling fails when macb_poll is already scheduled
because it didn't call napi_complete
3. macb_interrupt loops until the interrupt status register is clear,
which will never happen in this case if the driver doesn't disable
the RX interrupt
Since macb_interrupt runs in interrupt context, this effectively locks
up the machine, triggering the hardware watchdog.
This issue was readily reproducible on a flooded network with a
modified 2.6.27.48 kernel. The same problem appears to still be in the
2.6.36-rc8 driver code, so I am submitting this patch against that
version. I have not tested this version of the patch except to make
sure the kernel compiles.
Signed-off-by: Joshua Hoke <joshua.hoke@sixnet.com>
---
I'm submitting this at the request of Andrew Morton in this bug:
https://bugzilla.kernel.org/show_bug.cgi?id=20732
This version of the patch applies to 2.6.36-rc8 but has not been
tested. In particular I am assuming that napi_schedule_prep() behaves
the same as netif_rx_schedule_prep() did by failing when the macb_poll
callback is already scheduled.
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index ff2f158..36cf594 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -515,14 +515,15 @@ static int macb_poll(struct napi_struct *napi, int budget)
(unsigned long)status, budget);
work_done = macb_rx(bp, budget);
- if (work_done < budget)
+ if (work_done < budget) {
napi_complete(napi);
- /*
- * We've done what we can to clean the buffers. Make sure we
- * get notified when new packets arrive.
- */
- macb_writel(bp, IER, MACB_RX_INT_FLAGS);
+ /*
+ * We've done what we can to clean the buffers. Make sure we
+ * get notified when new packets arrive.
+ */
+ macb_writel(bp, IER, MACB_RX_INT_FLAGS);
+ }
/* TODO: Handle errors */
@@ -550,12 +551,16 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
}
if (status & MACB_RX_INT_FLAGS) {
+ /*
+ * There's no point taking any more interrupts
+ * until we have processed the buffers. The
+ * scheduling call may fail if the poll routine
+ * is already scheduled, so disable interrupts
+ * now.
+ */
+ macb_writel(bp, IDR, MACB_RX_INT_FLAGS);
+
if (napi_schedule_prep(&bp->napi)) {
- /*
- * There's no point taking any more interrupts
- * until we have processed the buffers
- */
- macb_writel(bp, IDR, MACB_RX_INT_FLAGS);
dev_dbg(&bp->pdev->dev,
"scheduling RX softirq\n");
__napi_schedule(&bp->napi);
^ permalink raw reply related
* [PATCH] mlx4_en: Fix out of bounds array access
From: Eli Cohen @ 2010-10-25 12:56 UTC (permalink / raw)
To: davem, yevgenyp; +Cc: Roland Dreier, RDMA list, netdev
When searching for a free entry in either mlx4_register_vlan() or
mlx4_register_mac(), and there is no free entry, the loop terminates without
updating the local variable free thus causing out of array bounds access. Fix
this by adding a proper check outside the loop.
Signed-off-by: Eli Cohen <eli@mellanox.co.il>
---
drivers/net/mlx4/port.c | 11 +++++++++++
1 files changed, 11 insertions(+), 0 deletions(-)
diff --git a/drivers/net/mlx4/port.c b/drivers/net/mlx4/port.c
index 56371ef..4513395 100644
--- a/drivers/net/mlx4/port.c
+++ b/drivers/net/mlx4/port.c
@@ -111,6 +111,12 @@ int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *index)
goto out;
}
}
+
+ if (free < 0) {
+ err = -ENOMEM;
+ goto out;
+ }
+
mlx4_dbg(dev, "Free MAC index is %d\n", free);
if (table->total == table->max) {
@@ -224,6 +230,11 @@ int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index)
}
}
+ if (free < 0) {
+ err = -ENOMEM;
+ goto out;
+ }
+
if (table->total == table->max) {
/* No free vlan entries */
err = -ENOSPC;
--
1.7.3.1
^ permalink raw reply related
* [PATCH] rps: add __rcu annotations
From: Eric Dumazet @ 2010-10-25 13:02 UTC (permalink / raw)
To: David Miller; +Cc: netdev
Add __rcu annotations to :
(struct netdev_rx_queue)->rps_map
(struct netdev_rx_queue)->rps_flow_table
struct rps_sock_flow_table *rps_sock_flow_table;
And use appropriate rcu primitives.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
include/linux/netdevice.h | 12 ++++++------
net/core/dev.c | 12 ++++++------
net/core/net-sysfs.c | 20 +++++++++++++-------
net/core/sysctl_net_core.c | 3 ++-
4 files changed, 27 insertions(+), 20 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index fcd3dda..2475206 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -585,15 +585,15 @@ static inline void rps_reset_sock_flow(struct rps_sock_flow_table *table,
table->ents[hash & table->mask] = RPS_NO_CPU;
}
-extern struct rps_sock_flow_table *rps_sock_flow_table;
+extern struct rps_sock_flow_table __rcu *rps_sock_flow_table;
/* This structure contains an instance of an RX queue. */
struct netdev_rx_queue {
- struct rps_map *rps_map;
- struct rps_dev_flow_table *rps_flow_table;
- struct kobject kobj;
- struct netdev_rx_queue *first;
- atomic_t count;
+ struct rps_map __rcu *rps_map;
+ struct rps_dev_flow_table __rcu *rps_flow_table;
+ struct kobject kobj;
+ struct netdev_rx_queue *first;
+ atomic_t count;
} ____cacheline_aligned_in_smp;
#endif /* CONFIG_RPS */
diff --git a/net/core/dev.c b/net/core/dev.c
index 78b5a89..625fde2 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2413,7 +2413,7 @@ EXPORT_SYMBOL(__skb_get_rxhash);
#ifdef CONFIG_RPS
/* One global table that all flow-based protocols share. */
-struct rps_sock_flow_table *rps_sock_flow_table __read_mostly;
+struct rps_sock_flow_table __rcu *rps_sock_flow_table __read_mostly;
EXPORT_SYMBOL(rps_sock_flow_table);
/*
@@ -2425,7 +2425,7 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb,
struct rps_dev_flow **rflowp)
{
struct netdev_rx_queue *rxqueue;
- struct rps_map *map = NULL;
+ struct rps_map *map;
struct rps_dev_flow_table *flow_table;
struct rps_sock_flow_table *sock_flow_table;
int cpu = -1;
@@ -2444,15 +2444,15 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb,
} else
rxqueue = dev->_rx;
- if (rxqueue->rps_map) {
- map = rcu_dereference(rxqueue->rps_map);
- if (map && map->len == 1) {
+ map = rcu_dereference(rxqueue->rps_map);
+ if (map) {
+ if (map->len == 1) {
tcpu = map->cpus[0];
if (cpu_online(tcpu))
cpu = tcpu;
goto done;
}
- } else if (!rxqueue->rps_flow_table) {
+ } else if (!rcu_dereference_raw(rxqueue->rps_flow_table)) {
goto done;
}
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index b143173..a5ff5a8 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -598,7 +598,8 @@ static ssize_t store_rps_map(struct netdev_rx_queue *queue,
}
spin_lock(&rps_map_lock);
- old_map = queue->rps_map;
+ old_map = rcu_dereference_protected(queue->rps_map,
+ lockdep_is_held(&rps_map_lock));
rcu_assign_pointer(queue->rps_map, map);
spin_unlock(&rps_map_lock);
@@ -677,7 +678,8 @@ static ssize_t store_rps_dev_flow_table_cnt(struct netdev_rx_queue *queue,
table = NULL;
spin_lock(&rps_dev_flow_lock);
- old_table = queue->rps_flow_table;
+ old_table = rcu_dereference_protected(queue->rps_flow_table,
+ lockdep_is_held(&rps_dev_flow_lock));
rcu_assign_pointer(queue->rps_flow_table, table);
spin_unlock(&rps_dev_flow_lock);
@@ -705,13 +707,17 @@ static void rx_queue_release(struct kobject *kobj)
{
struct netdev_rx_queue *queue = to_rx_queue(kobj);
struct netdev_rx_queue *first = queue->first;
+ struct rps_map *map;
+ struct rps_dev_flow_table *flow_table;
- if (queue->rps_map)
- call_rcu(&queue->rps_map->rcu, rps_map_release);
- if (queue->rps_flow_table)
- call_rcu(&queue->rps_flow_table->rcu,
- rps_dev_flow_table_release);
+ map = rcu_dereference_raw(queue->rps_map);
+ if (map)
+ call_rcu(&map->rcu, rps_map_release);
+
+ flow_table = rcu_dereference_raw(queue->rps_flow_table);
+ if (flow_table)
+ call_rcu(&flow_table->rcu, rps_dev_flow_table_release);
if (atomic_dec_and_test(&first->count))
kfree(first);
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c
index 01eee5d..385b609 100644
--- a/net/core/sysctl_net_core.c
+++ b/net/core/sysctl_net_core.c
@@ -34,7 +34,8 @@ static int rps_sock_flow_sysctl(ctl_table *table, int write,
mutex_lock(&sock_flow_mutex);
- orig_sock_table = rps_sock_flow_table;
+ orig_sock_table = rcu_dereference_protected(rps_sock_flow_table,
+ lockdep_is_held(&sock_flow_mutex));
size = orig_size = orig_sock_table ? orig_sock_table->mask + 1 : 0;
ret = proc_dointvec(&tmp, write, buffer, lenp, ppos);
^ permalink raw reply related
* [PATCH] net_ns: add __rcu annotations
From: Eric Dumazet @ 2010-10-25 13:20 UTC (permalink / raw)
To: David Miller; +Cc: netdev
add __rcu annotation to (struct net)->gen, and use
rcu_dereference_protected() in net_assign_generic()
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
include/net/net_namespace.h | 2 +-
net/core/net_namespace.c | 4 +++-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 65af9a0..1bf812b 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -88,7 +88,7 @@ struct net {
#ifdef CONFIG_WEXT_CORE
struct sk_buff_head wext_nlevents;
#endif
- struct net_generic *gen;
+ struct net_generic __rcu *gen;
/* Note : following structs are cache line aligned */
#ifdef CONFIG_XFRM
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index c988e68..3f86026 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -42,7 +42,9 @@ static int net_assign_generic(struct net *net, int id, void *data)
BUG_ON(!mutex_is_locked(&net_mutex));
BUG_ON(id == 0);
- ng = old_ng = net->gen;
+ old_ng = rcu_dereference_protected(net->gen,
+ lockdep_is_held(&net_mutex));
+ ng = old_ng;
if (old_ng->len >= id)
goto assign;
^ permalink raw reply related
* Re: [PATCH] drivers: rtl818x: request DMA-able memory
From: Larry Finger @ 2010-10-25 13:24 UTC (permalink / raw)
To: Serafeim Zanikolas
Cc: herton, htl10, linville, joe, davem, linux-wireless, netdev,
linux-kernel
In-Reply-To: <1287952327-9924-1-git-send-email-sez@debian.org>
On 10/24/2010 03:32 PM, Serafeim Zanikolas wrote:
> Despite the indicated intention in comment, the kmalloc() call was not
> explicitly requesting memory from ZONE_DMA.
>
> Signed-off-by: Serafeim Zanikolas <sez@debian.org>
> ---
> drivers/net/wireless/rtl818x/rtl8187_dev.c | 3 ++-
> 1 files changed, 2 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c
> index 38fa824..771794d 100644
> --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c
> +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c
> @@ -1343,7 +1343,8 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
> priv->is_rtl8187b = (id->driver_info == DEVICE_RTL8187B);
>
> /* allocate "DMA aware" buffer for register accesses */
> - priv->io_dmabuf = kmalloc(sizeof(*priv->io_dmabuf), GFP_KERNEL);
> + priv->io_dmabuf = kmalloc(sizeof(*priv->io_dmabuf),
> + GFP_DMA | GFP_KERNEL);
> if (!priv->io_dmabuf) {
> err = -ENOMEM;
> goto err_free_dev;
ACK.
Larry
^ permalink raw reply
* [PATCH] ipv4: add __rcu annotations to ip_ra_chain
From: Eric Dumazet @ 2010-10-25 13:32 UTC (permalink / raw)
To: David Miller; +Cc: netdev
Add __rcu annotations to :
(struct ip_ra_chain)->next
struct ip_ra_chain *ip_ra_chain;
And use appropriate rcu primitives.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
include/net/ip.h | 4 ++--
net/ipv4/ip_sockglue.c | 10 +++++++---
2 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/include/net/ip.h b/include/net/ip.h
index dbee3fe..86e2b18 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -59,7 +59,7 @@ struct ipcm_cookie {
#define IPCB(skb) ((struct inet_skb_parm*)((skb)->cb))
struct ip_ra_chain {
- struct ip_ra_chain *next;
+ struct ip_ra_chain __rcu *next;
struct sock *sk;
union {
void (*destructor)(struct sock *);
@@ -68,7 +68,7 @@ struct ip_ra_chain {
struct rcu_head rcu;
};
-extern struct ip_ra_chain *ip_ra_chain;
+extern struct ip_ra_chain __rcu *ip_ra_chain;
/* IP flags. */
#define IP_CE 0x8000 /* Flag: "Congestion" */
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 64b70ad..3948c86 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -238,7 +238,7 @@ int ip_cmsg_send(struct net *net, struct msghdr *msg, struct ipcm_cookie *ipc)
but receiver should be enough clever f.e. to forward mtrace requests,
sent to multicast group to reach destination designated router.
*/
-struct ip_ra_chain *ip_ra_chain;
+struct ip_ra_chain __rcu *ip_ra_chain;
static DEFINE_SPINLOCK(ip_ra_lock);
@@ -253,7 +253,8 @@ static void ip_ra_destroy_rcu(struct rcu_head *head)
int ip_ra_control(struct sock *sk, unsigned char on,
void (*destructor)(struct sock *))
{
- struct ip_ra_chain *ra, *new_ra, **rap;
+ struct ip_ra_chain *ra, *new_ra;
+ struct ip_ra_chain __rcu **rap;
if (sk->sk_type != SOCK_RAW || inet_sk(sk)->inet_num == IPPROTO_RAW)
return -EINVAL;
@@ -261,7 +262,10 @@ int ip_ra_control(struct sock *sk, unsigned char on,
new_ra = on ? kmalloc(sizeof(*new_ra), GFP_KERNEL) : NULL;
spin_lock_bh(&ip_ra_lock);
- for (rap = &ip_ra_chain; (ra = *rap) != NULL; rap = &ra->next) {
+ for (rap = &ip_ra_chain;
+ (ra = rcu_dereference_protected(*rap,
+ lockdep_is_held(&ip_ra_lock))) != NULL;
+ rap = &ra->next) {
if (ra->sk == sk) {
if (on) {
spin_unlock_bh(&ip_ra_lock);
^ permalink raw reply related
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