Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH net-next-2.6 v2] can: Topcliff: PCH_CAN driver: Fix build warnings
From: Marc Kleine-Budde @ 2010-10-29 17:58 UTC (permalink / raw)
  To: Oliver Hartkopp
  Cc: andrew.chih.howe.khor-ral2JQCrhuEAvxtiuMwx3w, Masayuki Ohtake,
	Samuel Ortiz, margie.foster-ral2JQCrhuEAvxtiuMwx3w,
	netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	yong.y.wang-ral2JQCrhuEAvxtiuMwx3w,
	kok.howg.ewe-ral2JQCrhuEAvxtiuMwx3w, Wolfgang Grandegger,
	joel.clark-ral2JQCrhuEAvxtiuMwx3w, David S. Miller,
	Christian Pellegrin, qi.wang-ral2JQCrhuEAvxtiuMwx3w
In-Reply-To: <4CCAFA68.2030903-fJ+pQTUTwRTk1uMJSBkQmQ@public.gmane.org>


[-- Attachment #1.1: Type: text/plain, Size: 2851 bytes --]

On 10/29/2010 06:46 PM, Oliver Hartkopp wrote:
> Indeed the access to the data registers does not seem to be endian aware.
> 
> See in pch_can_rx_normal():
> 
> +			cf->can_dlc = get_can_dlc((ioread32(&priv->regs->
> +						   if1_mcont)) & 0xF);
> +			*(u16 *)(cf->data + 0) = ioread16(&priv->regs->
> +							  if1_dataa1);
> +			*(u16 *)(cf->data + 2) = ioread16(&priv->regs->
> +							  if1_dataa2);
> +			*(u16 *)(cf->data + 4) = ioread16(&priv->regs->
> +							  if1_datab1);
> +			*(u16 *)(cf->data + 6) = ioread16(&priv->regs->
> +							  if1_datab2);
> 
> See in pch_xmit():
> 
> +	/* Copy data to register */
> +	if (cf->can_dlc > 0) {
> +		u32 data1 = *((u16 *)&cf->data[0]);
> +		iowrite32(data1, &priv->regs->if2_dataa1);
> +	}
> +	if (cf->can_dlc > 2) {
> +		u32 data1 = *((u16 *)&cf->data[2]);
> +		iowrite32(data1, &priv->regs->if2_dataa2);
> +	}
> +	if (cf->can_dlc > 4) {
> +		u32 data1 = *((u16 *)&cf->data[4]);
> +		iowrite32(data1, &priv->regs->if2_datab1);
> +	}
> +	if (cf->can_dlc > 6) {
> +		u32 data1 = *((u16 *)&cf->data[6]);
> +		iowrite32(data1, &priv->regs->if2_datab2);
> +	}
> +
> 
> It's just a question if the driver for an Intel Chipset should/could ignore
> the endian problematic.
> 
> If this is intended the driver should only appear in Kconfig depending on X86
> or little endian systems.
> 
> Besides this remark, the struct pch_can_regs could also be defined in a way
> that every single CAN payload data byte could be accessed directly to allow

That _should_ work on x86. On the contrary on ARM some registers in SOCs
allow only full 32 bit access.

> e.g. this code in pch_can_rx_normal():
> 
> cf->data[0] = ioread8(&priv->regs->if1_data0);
> cf->data[1] = ioread8(&priv->regs->if1_data1);
> cf->data[2] = ioread8(&priv->regs->if1_data2);
> (..)
> cf->data[6] = ioread8(&priv->regs->if1_data6);
> cf->data[7] = ioread8(&priv->regs->if1_data7);

> This is easy to understand and additionally endian aware.

or use this, (as proposed in a earlier mail)

	for (i = 0; i < cf->can_dlc; i += 2) {
		reg = ioread32(&priv->regs->if1_data[i >> 1]);
		*(__be16 *)cf->data[i] = cpu_to_be16(reg);
	}

> In opposite to this:
> 
> +	if (cf->can_dlc > 2) {
> +		u32 data1 = *((u16 *)&cf->data[2]);
> +		iowrite32(data1, &priv->regs->if2_dataa2);
> +	}
> 
> Which puts a little? endian u16 into the big endian register layout.
> Sorry i'm just getting curious on this register access implementation.

According to the datasheet the layout is LE.

cheers, Marc

-- 
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

* [PATCH] netfilter: fix nf_conntrack_l4proto_register()
From: Eric Dumazet @ 2010-10-29 17:57 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: David Miller, netdev, Netfilter Development Mailinglist

While doing __rcu annotations work on net/netfilter I found following
bug. On some arches, it is possible we publish a table while its content
is not yet committed to memory, and lockless reader can dereference wild
pointer.

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
 net/netfilter/nf_conntrack_proto.c |    6 ++++++
 1 files changed, 6 insertions(+)

diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c
index ed6d929..dc7bb74 100644
--- a/net/netfilter/nf_conntrack_proto.c
+++ b/net/netfilter/nf_conntrack_proto.c
@@ -292,6 +292,12 @@ int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *l4proto)
 
 		for (i = 0; i < MAX_NF_CT_PROTO; i++)
 			proto_array[i] = &nf_conntrack_l4proto_generic;
+
+		/* Before making proto_array visible to lockless readers,
+		 * we must make sure its content is committed to memory.
+		 */
+		smp_wmb();
+
 		nf_ct_protos[l4proto->l3proto] = proto_array;
 	} else if (nf_ct_protos[l4proto->l3proto][l4proto->l4proto] !=
 					&nf_conntrack_l4proto_generic) {



^ permalink raw reply related

* Re: [ANNOUNCE]: Release of iptables-1.4.10
From: Jan Engelhardt @ 2010-10-29 17:54 UTC (permalink / raw)
  To: Patrick McHardy
  Cc: Netfilter Development Mailinglist, NetDev, netfilter-announce,
	'netfilter@vger.kernel.org'
In-Reply-To: <4CCAEB8A.5090504@trash.net>


On Friday 2010-10-29 17:43, Patrick McHardy wrote:

>The netfilter coreteam presents:
>
>    iptables version 1.4.10
>
>Version 1.4.10 can be obtained from:
>
>http://www.netfilter.org/projects/iptables/downloads.html
>ftp://ftp.netfilter.org/pub/iptables/
>git://git.netfilter.org/iptables.git

The v1.4.10 tag seems to not have made it onto the server. :^)

^ permalink raw reply

* Re: [PATCH] aoe: remove dev_base_lock use from aoecmd_cfg_pkts()
From: Ed Cashin @ 2010-10-29 17:18 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: David Miller, netdev
In-Reply-To: <1288350929.2560.16.camel@edumazet-laptop>

Eric Dumazet writes :

> dev_base_lock is the legacy way to lock the device list, and is planned
> to disappear. (writers hold RTNL, readers hold RCU lock)
> 
> Convert aoecmd_cfg_pkts() to RCU locking.


Thanks.

-- 
  Ed Cashin
  ecashin@coraid.com


^ permalink raw reply

* Re: [PATCH] net: Limit socket I/O iovec total length to INT_MAX.
From: Al Viro @ 2010-10-29 17:32 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: David Miller, netdev, jon.maloy, allan.stephens, Dan Rosenberg
In-Reply-To: <AANLkTi=zieMoDdHgB_aY4xN=A6ErrjUWpaME1WwWrvnL@mail.gmail.com>

On Fri, Oct 29, 2010 at 10:01:19AM -0700, Linus Torvalds wrote:
> On Fri, Oct 29, 2010 at 9:45 AM, Al Viro <viro@zeniv.linux.org.uk> wrote:
> >
> > I don't see anything obviously broken (and we obviously have allowed
> > iov_len == 0 cases all along, so if anything, breakage won't be new).
> > However, I wonder if things like sendmsg() for datagrams have warranties
> > against silent truncation. ?Davem?
> 
> You missed that discussion - my argument is that anybody who thinks
> that they can send a single packet that is 2GB+ in size are already
> screwed. And the packet protocol will have some inherent upper limit
> anyway (possibly introduced by just allocation issues, but quite
> likely inherent to the protocol itself)

Sure, but... do we want to send something truncated in that case or
should we just fail?  Note that with your change previously deliberately
b0rken iovecs (anything with sum of lengths equal to 1<<31 on 32bit)
will get a chance to be accepted *OR* (much more likely) get rejected with
unexpected error value.  It may well be OK, but I'd like to hear from
network folks...

^ permalink raw reply

* Reply Needed
From: Dr Carl Lee @ 2010-10-26  9:49 UTC (permalink / raw)
  To: netdev

Hello,
 
I have a proposition for you, this however is not mandatory nor will I
in any manner compel you to honor against your will.Let me start by
introducing myself. I am Dr.Carl Lee, Director of Operations
of the Hang Seng Bank Ltd,Sai Wan Ho Branch. I have a mutual beneficial
business suggestion for you.
 
1. Can you handle this project?
2. Can I give you this trust ?
 
Absolute confidentiality is required from you.Besides,I will use my connection
to get some documents to back up the fund so that the fund can not be
question by any authority.
 
More information await you in my next response to your email message.
 
 
Treat as very urgent.
 
Yours Faithfully,
 
Dr. Carl Lee.




^ permalink raw reply

* Re: [PATCH] net: Limit socket I/O iovec total length to INT_MAX.
From: Linus Torvalds @ 2010-10-29 17:01 UTC (permalink / raw)
  To: Al Viro; +Cc: David Miller, netdev, jon.maloy, allan.stephens, Dan Rosenberg
In-Reply-To: <20101029164532.GV19804@ZenIV.linux.org.uk>

On Fri, Oct 29, 2010 at 9:45 AM, Al Viro <viro@zeniv.linux.org.uk> wrote:
>
> I don't see anything obviously broken (and we obviously have allowed
> iov_len == 0 cases all along, so if anything, breakage won't be new).
> However, I wonder if things like sendmsg() for datagrams have warranties
> against silent truncation.  Davem?

You missed that discussion - my argument is that anybody who thinks
that they can send a single packet that is 2GB+ in size are already
screwed. And the packet protocol will have some inherent upper limit
anyway (possibly introduced by just allocation issues, but quite
likely inherent to the protocol itself)

And yes, the iov_len = 0 case has always been possible and accepted so
my patch doesn't really change anything. In fact, I think it even
happens (simple example: the easiest way for user space to resume a
partial writev() is to basically subtract out the return value from
the iovec and then re-submit it - so getting zero iovec entries at the
beginning in particular would not necessarily even be odd)

                            Linus

^ permalink raw reply

* Payment.
From: Western Union® @ 2010-10-29 16:39 UTC (permalink / raw)


You have earned 1,000,000.00 USD from Western Union. To receive your
cash,send your details: Full Names, Age, Country, Phone Number to:
office@westernu.co.uk


^ permalink raw reply

* Re: [PATCH net-next-2.6 v2] can: Topcliff: PCH_CAN driver: Fix build warnings
From: Oliver Hartkopp @ 2010-10-29 16:46 UTC (permalink / raw)
  To: Marc Kleine-Budde, Tomoya
  Cc: andrew.chih.howe.khor-ral2JQCrhuEAvxtiuMwx3w, Masayuki Ohtake,
	Samuel Ortiz, margie.foster-ral2JQCrhuEAvxtiuMwx3w,
	netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	yong.y.wang-ral2JQCrhuEAvxtiuMwx3w,
	kok.howg.ewe-ral2JQCrhuEAvxtiuMwx3w, Wolfgang Grandegger,
	joel.clark-ral2JQCrhuEAvxtiuMwx3w, David S. Miller,
	Christian Pellegrin, qi.wang-ral2JQCrhuEAvxtiuMwx3w
In-Reply-To: <4CCAC4CD.7000503-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>

On 29.10.2010 14:57, Marc Kleine-Budde wrote:
> Hello,
> 
> On 10/29/2010 12:37 PM, Tomoya wrote:

>>>> 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.
> 
>> Sorry, I misunderstood the spec of Topcliff CAN endianess.
>> I have understood endianess conversion is not necessary.
>> (CAN data is set as Big-Endian in Topcliff CAN register)
> 
>>> You have to change the definition of the regs struct a bit:
>>>> 	u32 if1_mcont;
>>>> 	u32 if1_data[4];
>>>> 	u32 reserve2;
>> Uh, I can't find this. Where is this ?
> 
> Here's a patch to illustrate what I meant:
> 
> diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c
> index 55ec324..5ee7589 100644
> --- a/drivers/net/can/pch_can.c
> +++ b/drivers/net/can/pch_can.c
> @@ -150,10 +150,7 @@ struct pch_can_regs {
>         u32 if1_id1;
>         u32 if1_id2;
>         u32 if1_mcont;
> -       u32 if1_dataa1;
> -       u32 if1_dataa2;
> -       u32 if1_datab1;
> -       u32 if1_datab2;
> +       u32 if1_data[4];
>         u32 reserve2;
>         u32 reserve3[12];
>         u32 if2_creq;
> 

Indeed the access to the data registers does not seem to be endian aware.

See in pch_can_rx_normal():

+			cf->can_dlc = get_can_dlc((ioread32(&priv->regs->
+						   if1_mcont)) & 0xF);
+			*(u16 *)(cf->data + 0) = ioread16(&priv->regs->
+							  if1_dataa1);
+			*(u16 *)(cf->data + 2) = ioread16(&priv->regs->
+							  if1_dataa2);
+			*(u16 *)(cf->data + 4) = ioread16(&priv->regs->
+							  if1_datab1);
+			*(u16 *)(cf->data + 6) = ioread16(&priv->regs->
+							  if1_datab2);

See in pch_xmit():

+	/* Copy data to register */
+	if (cf->can_dlc > 0) {
+		u32 data1 = *((u16 *)&cf->data[0]);
+		iowrite32(data1, &priv->regs->if2_dataa1);
+	}
+	if (cf->can_dlc > 2) {
+		u32 data1 = *((u16 *)&cf->data[2]);
+		iowrite32(data1, &priv->regs->if2_dataa2);
+	}
+	if (cf->can_dlc > 4) {
+		u32 data1 = *((u16 *)&cf->data[4]);
+		iowrite32(data1, &priv->regs->if2_datab1);
+	}
+	if (cf->can_dlc > 6) {
+		u32 data1 = *((u16 *)&cf->data[6]);
+		iowrite32(data1, &priv->regs->if2_datab2);
+	}
+

It's just a question if the driver for an Intel Chipset should/could ignore
the endian problematic.

If this is intended the driver should only appear in Kconfig depending on X86
or little endian systems.

Besides this remark, the struct pch_can_regs could also be defined in a way
that every single CAN payload data byte could be accessed directly to allow
e.g. this code in pch_can_rx_normal():

cf->data[0] = ioread8(&priv->regs->if1_data0);
cf->data[1] = ioread8(&priv->regs->if1_data1);
cf->data[2] = ioread8(&priv->regs->if1_data2);
(..)
cf->data[6] = ioread8(&priv->regs->if1_data6);
cf->data[7] = ioread8(&priv->regs->if1_data7);

This is easy to understand and additionally endian aware.

In opposite to this:

+	if (cf->can_dlc > 2) {
+		u32 data1 = *((u16 *)&cf->data[2]);
+		iowrite32(data1, &priv->regs->if2_dataa2);
+	}

Which puts a little? endian u16 into the big endian register layout.
Sorry i'm just getting curious on this register access implementation.

Regards,
Oliver

^ permalink raw reply

* Re: [PATCH] net: Limit socket I/O iovec total length to INT_MAX.
From: Al Viro @ 2010-10-29 16:45 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: David Miller, netdev, jon.maloy, allan.stephens, Dan Rosenberg
In-Reply-To: <AANLkTi=sUDRzGnkp57OCQUi9APHWLYLShhiTVHLyq1eV@mail.gmail.com>

On Fri, Oct 29, 2010 at 09:21:16AM -0700, Linus Torvalds wrote:
>  	ret = -EINVAL;
>  	for (seg = 0; seg < nr_segs; seg++) {
> -		compat_ssize_t tmp = tot_len;
>  		compat_uptr_t buf;
>  		compat_ssize_t len;
>  
> @@ -624,13 +624,13 @@ ssize_t compat_rw_copy_check_uvector(int type,
>  		}
>  		if (len < 0)	/* size_t not fitting in compat_ssize_t .. */
>  			goto out;
> -		tot_len += len;
> -		if (tot_len < tmp) /* maths overflow on the compat_ssize_t */
> -			goto out;
>  		if (!access_ok(vrfy_dir(type), compat_ptr(buf), len)) {
>  			ret = -EFAULT;
>  			goto out;
>  		}
> +		if (len > MAX_RW_COUNT - tot_len)
> +			len = MAX_RW_COUNT - tot_len;
> +		tot_len += len;
>  		iov->iov_base = compat_ptr(buf);
>  		iov->iov_len = (compat_size_t) len;
>  		uvector++;

Interesting...  Had anybody tested vectors with 0 iov_len in the end and/or
middle?  Looks like something rarely hit in practice...

I don't see anything obviously broken (and we obviously have allowed
iov_len == 0 cases all along, so if anything, breakage won't be new).
However, I wonder if things like sendmsg() for datagrams have warranties
against silent truncation.  Davem?

^ permalink raw reply

* Re: [PATCH net-next-2.6 v2] can: Topcliff: PCH_CAN driver: Fix build warnings
From: Marc Kleine-Budde @ 2010-10-29 16:23 UTC (permalink / raw)
  To: Tomoya
  Cc: andrew.chih.howe.khor-ral2JQCrhuEAvxtiuMwx3w, Masayuki Ohtake,
	Samuel Ortiz, margie.foster-ral2JQCrhuEAvxtiuMwx3w,
	netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	yong.y.wang-ral2JQCrhuEAvxtiuMwx3w,
	kok.howg.ewe-ral2JQCrhuEAvxtiuMwx3w, Wolfgang Grandegger,
	joel.clark-ral2JQCrhuEAvxtiuMwx3w, David S. Miller,
	Christian Pellegrin, qi.wang-ral2JQCrhuEAvxtiuMwx3w
In-Reply-To: <4CCAC4CD.7000503-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>


[-- Attachment #1.1: Type: text/plain, Size: 49724 bytes --]

Hello,

On 10/29/2010 02:57 PM, Marc Kleine-Budde wrote:
> The driver has already been merged. Please send incremental patches
> against david's net-2.6 branch.

Here a review, find comments inline. Lets talk about my remarks, please
answer inline and don't delete the code.

Can you please explain me your locking sheme? If I understand the
documenation correctly the two message interfaces can be used mutual.
And you use one for rx the other one for tx.

Please use netdev_<level> instead of dev_<level> for debug.

> --- /dev/null
> +++ b/drivers/net/can/pch_can.c
> @@ -0,0 +1,1436 @@
> +/*
> + * 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 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

A prefix for like PCH_ instead of CAN_ for all those define above would
be fine to avoid namespace clashes and/or confusion with the defines from the socketcan framework.

> +
> +#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

These are just single set bit, please use BIT()
Consider adding the name of the corresponding register to the define's
name.

> +#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

these are usually called SHIFT

> +#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

MSK or MASK is okay, however the last two are just single bits.

Please add a PCH_ prefix here, too.

> +#define PCH_CAN_NO_TX_BUFF	1
> +#define COUNTER_LIMIT		10

dito

> +
> +#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.
> + */
> +#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)

You define MAX_MSG_OBJ earlier, seems like two names for the same value.

> +
> +#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,
> +};
> +
> +struct pch_can_regs {
> +	u32 cont;
> +	u32 stat;
> +	u32 errc;
> +	u32 bitt;
> +	u32 intr;
> +	u32 opt;
> +	u32 brpe;
> +	u32 reserve1;

VVVV
> +	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;
^^^^

these registers and....

> +	u32 reserve2;
> +	u32 reserve3[12];

...and these

VVVV
> +	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;

^^^^

...are identical. I suggest to make a struct defining a complete
"Message Interface Register Set". If you include the correct number of
reserved bytes in the struct, you can have an array of two of these
structs in the struct pch_can_regs.

> +	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;
> +	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*/
                                                                            ^^^
please add a whitespace

> +	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 = "pch_can",
> +	.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)
                                      ^^^^^

that should be an void __iomem *, see mail I've send the other day.
Please use sparse to check for this kinds of errors.
(Compile the driver with C=2, i.e.: make drivers/net/can/pch_can.ko C=2)

> +{
> +	iowrite32(ioread32(addr) | mask, addr);
> +}
> +
> +static inline void pch_can_bit_clear(u32 *addr, u32 mask)
                                        ^^^^^

dito

> +{
> +	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);
> +}
> +

IMHO the function name is missleading, if I understand the code
correctly, this functions triggers the transmission of the message.
After this it checks for busy, but 

> +static void pch_can_check_if_busy(u32 __iomem *creq_addr, u32 num)
                                     ^^^^

that should probaby be a void

> +{
> +	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_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);

noone uses this case.

> +		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_set_rx_enable(struct pch_can_priv *priv, u32 buff_num,
> +				  int set)
> +{
> +	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 == 1) {
> +		/* 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 == 0) {
> +		/* 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 = 1; i <= PCH_RX_OBJ_NUM; i++)
> +		pch_can_set_rx_enable(priv, i, 1);
> +}
> +
> +static void pch_can_rx_disable_all(struct pch_can_priv *priv)
> +{
> +	int i;
> +
> +	/* Traversing to obtain the object configured as receivers. */
> +	for (i = 1; i <= PCH_RX_OBJ_NUM; i++)
> +		pch_can_set_rx_enable(priv, i, 0);
> +}
> +
> +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 == 1) {
> +		/* 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 == 0) {
> +		/* 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 = PCH_RX_OBJ_NUM + 1; i <= PCH_OBJ_NUM; i++)
> +		pch_can_set_tx_enable(priv, i, 1);
> +}
> +
> +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 = PCH_RX_OBJ_NUM + 1; i <= PCH_OBJ_NUM; i++)
> +		pch_can_set_tx_enable(priv, i, 0);
> +}
> +
> +static int pch_can_int_pending(struct pch_can_priv *priv)
          ^^^

make it u32 as it returns a register value, or a u16 as you only use
the 16 lower bits.

> +{
> +	return ioread32(&priv->regs->intr) & 0xffff;
> +}
> +
> +static void pch_can_clear_buffers(struct pch_can_priv *priv)
> +{
> +	int i; /* Msg Obj ID (1~32) */
> +
> +	for (i = 1; i <= PCH_RX_OBJ_NUM; i++) {

IMHO the readability would be improved if you define something like
PCH_RX_OBJ_START and PCH_RX_OBJ_END.

> +		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);
> +	}
> +
> +	for (i = PCH_RX_OBJ_NUM + 1; i <= PCH_OBJ_NUM; i++) {
                 ^^^^^^^^^^^^^^^^^^
dito for TX objects

> +		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);
> +	}
> +}
> +
> +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 = 1; i <= PCH_RX_OBJ_NUM; i++) {
> +		iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if1_cmask);
> +		pch_can_check_if_busy(&priv->regs->if1_creq, i);

If I understand the code correctly, the about function triggers a
transfer. Why do you first trigger a transfer, then set the message contents....
> +
> +		iowrite32(0x0, &priv->regs->if1_id1);
> +		iowrite32(0x0, &priv->regs->if1_id2);
> +
> +		pch_can_bit_set(&priv->regs->if1_mcont, CAN_IF_MCONT_UMASK);

    Why do you set the "Use acceptance mask" bit? We want to receive
    all can messages.

> +
> +		/* 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);

    Make it if () { } else { }, please.

> +
> +		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);

...and then trigger the transfer again?

> +	}
> +
> +	for (i = PCH_RX_OBJ_NUM + 1; i <= PCH_OBJ_NUM; i++) {
> +		iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if2_cmask);
> +		pch_can_check_if_busy(&priv->regs->if2_creq, i);

same question about triggering the transfer 2 times applied here, too
> +
> +		/* 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);

Can you combine the two accesses to >if2_id2 into one?

> +
> +		/* 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);

dito for if2_mcont

> +
> +		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);
> +	}
> +
> +	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) {

is this a valid case?

> +		ioread32(&priv->regs->stat);
> +		return;
> +	}
> +
> +	/* Clear interrupt for transmit object */
> +	if ((mask >= 1) && (mask <= PCH_RX_OBJ_NUM)) {
> +		/* 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);
> +	} else if ((mask > PCH_RX_OBJ_NUM) && (mask <= PCH_OBJ_NUM)) {
> +		/* Setting CMASK for clearing interrupts for
> +		   frame transmission. */

/*
 * this is the prefered style of multi line comments,
 * please adjust you comments
 */

> +		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);
> +	}
> +}
> +
> +static u32 pch_can_get_buffer_status(struct pch_can_priv *priv)
> +{
> +	return (ioread32(&priv->regs->treq1) & 0xffff) |
> +	       ((ioread32(&priv->regs->treq2) & 0xffff) << 16);

the second 0xffff is not needed, as the return value is u32 and you shift by 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);
> +	}
> +
> +	/* 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__);

Please use just "debug" level not warning here. Consider to use
netdev_dbg() instead. IMHO the __func__ can be dropped and the
"official" name for the error is "Error Warning".

> +	}
> +	/* 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__);

dito

> +	}
> +
> +	if (status & PCH_LEC_ALL) {
> +		priv->can.can_stats.bus_error++;
> +		stats->rx_errors++;
> +		switch (status & PCH_LEC_ALL) {

I suggest to convert to a if-bit-set because there might be more than
one bit set.

> +		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_receive_skb(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 void pch_fifo_thresh(struct pch_can_priv *priv, int obj_id)
> +{
> +	if (obj_id < 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, obj_id);
> +	} else if (obj_id > PCH_FIFO_THRESH) {
> +		pch_can_int_clr(priv, obj_id);
> +	} else if (obj_id == PCH_FIFO_THRESH) {
> +		int cnt;
> +		for (cnt = 0; cnt < PCH_FIFO_THRESH; cnt++)
> +			pch_can_int_clr(priv, cnt+1);
> +	}
> +}
> +
> +static int pch_can_rx_msg_lost(struct net_device *ndev, int obj_id)
> +{
> +	struct pch_can_priv *priv = netdev_priv(ndev);
> +	struct net_device_stats *stats = &(priv->ndev->stats);
> +	struct sk_buff *skb;
> +	struct can_frame *cf;
> +
> +	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, obj_id);
> +
> +	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;
> +	stats->rx_over_errors++;
> +	stats->rx_errors++;
> +
> +	netif_receive_skb(skb);
> +
> +	return 0;
> +}
> +
> +static int pch_can_rx_normal(struct net_device *ndev, u32 obj_num, int quota)
> +{
> +	u32 reg;
> +	canid_t id;
> +	u32 ide;
> +	u32 rtr;
> +	int rcv_pkts = 0;
> +	int rtn;
> +	int next_flag = 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, obj_num);
> +
> +	/* Reading the MCONT register. */
> +	reg = ioread32(&priv->regs->if1_mcont);
> +	reg &= 0xffff;
> +
> +	for (; (!(reg & CAN_IF_MCONT_EOB)) && (quota > 0);
> +						obj_num++, next_flag = 0) {
> +		/* If MsgLost bit set. */
> +		if (reg & CAN_IF_MCONT_MSGLOST) {
> +			rtn = pch_can_rx_msg_lost(ndev, obj_num);
> +			if (!rtn)
> +				return rtn;
> +			rcv_pkts++;
> +			quota--;
> +			next_flag = 1;
> +		} else if (!(reg & CAN_IF_MCONT_NEWDAT))
> +			next_flag = 1;
> +

after rearanging the code (see below..) you should be able to use a continue here.

> +		if (!next_flag) {
> +			skb = alloc_can_skb(priv->ndev, &cf);
> +			if (!skb)
> +				return -ENOMEM;
> +
> +			/* Get Received data */
> +			ide = ((ioread32(&priv->regs->if1_id2)) & CAN_ID2_XTD);
> +			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;
                                              ^^^^^^^^^^^^^^^^^

is the mask needed, you mask the if1_id{1,2} already

> +			} else {
> +				id = (((ioread32(&priv->regs->if1_id2)) &
> +						  (CAN_SFF_MASK << 2)) >> 2);
> +				cf->can_id = (id & CAN_SFF_MASK);

one mask can go away

> +			}
> +
> +			rtr = ioread32(&priv->regs->if1_id2) &  CAN_ID2_DIR;
                                                              ^^

remove one space

> +
> +			if (rtr)
> +				cf->can_id |= CAN_RTR_FLAG;
> +
> +			cf->can_dlc = get_can_dlc((ioread32(&priv->regs->
> +						   if1_mcont)) & 0xF);
> +			*(u16 *)(cf->data + 0) = ioread16(&priv->regs->
> +							  if1_dataa1);
> +			*(u16 *)(cf->data + 2) = ioread16(&priv->regs->
> +							  if1_dataa2);
> +			*(u16 *)(cf->data + 4) = ioread16(&priv->regs->
> +							  if1_datab1);
> +			*(u16 *)(cf->data + 6) = ioread16(&priv->regs->
> +							  if1_datab2);

are you sure, the bytes in the can package a in the correct order.
Please test your pch_can against a non pch_can system.

> +
> +			netif_receive_skb(skb);
> +			rcv_pkts++;
> +			stats->rx_packets++;
> +			quota--;
> +			stats->rx_bytes += cf->can_dlc;
> +
> +			pch_fifo_thresh(priv, obj_num);
> +		}
> +
> +		/* 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, obj_num + 1);
> +		reg = ioread32(&priv->regs->if1_mcont);

this is almost the same code as before the the loop, can you rearange
the code to avoid duplication?
 
> +	}
> +
> +	return rcv_pkts;
> +}
> +
> +static void pch_can_tx_complete(struct net_device *ndev, u32 int_stat)
> +{
> +	struct pch_can_priv *priv = netdev_priv(ndev);
> +	struct net_device_stats *stats = &(priv->ndev->stats);
> +	unsigned long flags;
> +	u32 dlc;
> +
> +	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;

use get_can_dlc

> +	stats->tx_bytes += dlc;
> +	stats->tx_packets++;
> +}
> +
> +static int pch_can_rx_poll(struct napi_struct *napi, int quota)
> +{
> +	struct net_device *ndev = napi->dev;
> +	struct pch_can_priv *priv = netdev_priv(ndev);
> +	u32 int_stat;
> +	int rcv_pkts = 0;
> +	u32 reg_stat;
> +	unsigned long flags;
> +
> +	int_stat = pch_can_int_pending(priv);
> +	if (!int_stat)
> +		goto END;
> +
> +	if ((int_stat == CAN_STATUS_INT) && (quota > 0)) {
> +		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);
> +				quota--;
> +			}
> +		}
> +
> +		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));
                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^

Isn't this "int_stat". Might it be possilbe that regs->intr changes
between the pch_can_int_pending and here?

What should this transfer do?

> +			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 (quota == 0)
> +		goto END;
> +
> +	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, quota);
> +		spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
> +		quota -= rcv_pkts;
> +		if (rcv_pkts < 0)

how can this happen?

> +			goto END;
> +	} else if ((int_stat > PCH_RX_OBJ_NUM) && (int_stat <= PCH_OBJ_NUM)) {
> +		/* Handle transmission interrupt */
> +		pch_can_tx_complete(ndev, int_stat);
> +	}
> +
> +END:
> +	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;
> +
> +	/* Setting the CCE bit for accessing the Can Timing register. */
> +	pch_can_bit_set(&priv->regs->cont, CAN_CTRL_CCE);
> +
> +	canbit = (bt->brp - 1) & 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 = ((bt->brp - 1) & 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;
> +
> +	/* 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:
> +	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);
> +	close_candev(ndev);
> +	priv->can.state = CAN_STATE_STOPPED;
> +	return 0;
> +}
> +
> +static netdev_tx_t pch_xmit(struct sk_buff *skb, struct net_device *ndev)
> +{
> +	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;

What I'm totally missing is the TX flow controll. Your driver has to
ensure that the package leave the controller in the order that come
into the xmit function. Further you have to stop your xmit queue if
you're out of tx objects and reenable if you have a object free.

Use netif_stop_queue() and netif_wake_queue() for this.

> +
> +	if (can_dropped_invalid_skb(ndev, skb))
> +		return NETDEV_TX_OK;
> +
> +	if (priv->tx_obj == (PCH_OBJ_NUM + 1)) { /* Point tail Obj + 1 */
> +		while (ioread32(&priv->regs->treq2) & 0xfc00)
> +			udelay(1);

please no (possible) infinite delays!

> +		priv->tx_obj = PCH_RX_OBJ_NUM + 1; /* Point head of Tx Obj ID */
> +	}

> +
> +	tx_buffer_avail = priv->tx_obj;

why has the "object" become a "buffer" now? :)

> +	priv->tx_obj++;
> +
> +	/* Attaining the lock. */
> +	spin_lock_irqsave(&priv->msgif_reg_lock, flags);
> +
> +	/* Setting the CMASK register to set value*/
                                                 ^^^

pleas add a whitespace

> +	iowrite32(CAN_CMASK_RX_TX_SET, &priv->regs->if2_cmask);
> +
> +	/* If ID extended is set. */
> +	if (cf->can_id & CAN_EFF_FLAG) {
> +		iowrite32(cf->can_id & 0xffff, &priv->regs->if2_id1);
> +		iowrite32(((cf->can_id >> 16) & 0x1fff) | CAN_ID2_XTD,
> +			    &priv->regs->if2_id2);
> +	} else {
> +		iowrite32(0, &priv->regs->if2_id1);
> +		iowrite32((cf->can_id & CAN_SFF_MASK) << 2,
> +			   &priv->regs->if2_id2);
> +	}
> +
> +	pch_can_bit_set(&priv->regs->if2_id2, CAN_ID_MSGVAL);

Do you need to do a read-modify-write of the hardware register? Please
prepare the values you want to write to hardware, then do it.

> +
> +	/* If remote frame has to be transmitted.. */
> +	if (!(cf->can_id & CAN_RTR_FLAG))
> +		pch_can_bit_set(&priv->regs->if2_id2, CAN_ID2_DIR);
dito
> +	/* 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
> +
> +	/* Copy data to register */
> +	if (cf->can_dlc > 0) {
> +		u32 data1 = *((u16 *)&cf->data[0]);
> +		iowrite32(data1, &priv->regs->if2_dataa1);

do you think you send the bytes in correct order?

> +	}
> +	if (cf->can_dlc > 2) {
> +		u32 data1 = *((u16 *)&cf->data[2]);
> +		iowrite32(data1, &priv->regs->if2_dataa2);
> +	}
> +	if (cf->can_dlc > 4) {
> +		u32 data1 = *((u16 *)&cf->data[4]);
> +		iowrite32(data1, &priv->regs->if2_datab1);
> +	}
> +	if (cf->can_dlc > 6) {
> +		u32 data1 = *((u16 *)&cf->data[6]);
> +		iowrite32(data1, &priv->regs->if2_datab2);
> +	}
> +
> +	can_put_echo_skb(skb, ndev, tx_buffer_avail - PCH_RX_OBJ_NUM - 1);
> +
> +	/* Set the size of the data. */
> +	iowrite32(cf->can_dlc, &priv->regs->if2_mcont);
> +
> +	/* Update if2_mcont */
> +	pch_can_bit_set(&priv->regs->if2_mcont,
> +			CAN_IF_MCONT_NEWDAT | CAN_IF_MCONT_TXRQXT |
> +			CAN_IF_MCONT_TXIE);

pleae first perpare your value, then write to hardware.

> +
> +	if (tx_buffer_avail == PCH_RX_OBJ_NUM) /* If points tail of FIFO  */
> +		pch_can_bit_set(&priv->regs->if2_mcont, CAN_IF_MCONT_EOB);

dito

Is EOB relevant for TX objects?

> +	pch_can_check_if_busy(&priv->regs->if2_creq, tx_buffer_avail);
> +	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);
> +	pci_iounmap(pdev, priv->regs);
> +	if (priv->use_msi)
> +		pci_disable_msi(priv->dev);
> +	pci_release_regions(pdev);
> +	pci_disable_device(pdev);
> +	pci_set_drvdata(pdev, NULL);
> +	free_candev(priv->ndev);
> +}
> +
> +#ifdef CONFIG_PM
> +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 u32 pch_can_get_int_enables(struct pch_can_priv *priv)
> +{
> +	/* Obtaining the status of IE, SIE and EIE interrupt bits. */
> +	return (ioread32(&priv->regs->cont) & CAN_CTRL_IE_SIE_EIE) >> 1;
> +}
> +
> +static u32 pch_can_get_rx_enable(struct pch_can_priv *priv, u32 buff_num)
> +{
> +	unsigned long flags;
> +	u32 enable;
> +
> +	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 = 1;
> +	else
> +		enable = 0;
> +	spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
> +	return enable;
> +}
> +
> +static u32 pch_can_get_tx_enable(struct pch_can_priv *priv, u32 buff_num)
> +{
> +	unsigned long flags;
> +	u32 enable;
> +
> +	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 = 1;
> +	} else {
> +		enable = 0;
> +	}
> +	spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
> +
> +	return enable;
> +}
> +
> +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 == 1)
> +		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 u32 pch_can_get_rx_buffer_link(struct pch_can_priv *priv, u32 buffer_num)
> +{
> +	unsigned long flags;
> +	u32 link;
> +
> +	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 = 0;
> +	else
> +		link = 1;
> +	spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
> +	return link;
> +}
> +
> +static int pch_can_suspend(struct pci_dev *pdev, pm_message_t state)
> +{
> +	int i;
> +	int retval;
> +	u32 buf_stat;	/* Variable for reading the transmit buffer status. */
> +	u32 counter = COUNTER_LIMIT;
> +
> +	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_STOPPED;
> +
> +	/* 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 */
> +	priv->int_enables = pch_can_get_int_enables(priv);
> +	pch_can_set_int_enables(priv, PCH_CAN_DISABLE);
> +
> +	/* Save Tx buffer enable state */
> +	for (i = PCH_RX_OBJ_NUM + 1; i <= PCH_OBJ_NUM; i++)
> +		priv->tx_enable[i] = pch_can_get_tx_enable(priv, i);
> +
> +	/* Disable all Transmit buffers */
> +	pch_can_tx_disable_all(priv);
> +
> +	/* Save Rx buffer enable state */
> +	for (i = 1; i <= PCH_RX_OBJ_NUM; i++) {
> +		priv->rx_enable[i] = pch_can_get_rx_enable(priv, i);
> +		priv->rx_link[i] = pch_can_get_rx_buffer_link(priv, 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;
> +	int retval;
> +	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 = 1; i <= PCH_RX_OBJ_NUM; i++)
> +		pch_can_set_tx_enable(priv, i, priv->tx_enable[i]);
> +
> +	/* Configuring the receive buffer and enabling them. */
> +	for (i = PCH_RX_OBJ_NUM + 1; i <= PCH_OBJ_NUM; i++) {
> +		/* Restore buffer link */
> +		pch_can_set_rx_buffer_link(priv, i, priv->rx_link[i]);
> +
> +		/* Restore buffer enables */
> +		pch_can_set_rx_enable(priv, i, 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;
> +	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);
> +	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 */
> +
> +	netif_napi_add(ndev, &priv->napi, pch_can_rx_poll, PCH_RX_OBJ_NUM);
> +
> +	rc = pci_enable_msi(priv->dev);
> +	if (rc) {
> +		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;
> +	}
> +
> +	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("Intel EG20T PCH CAN(Controller Area Network) Driver");
> +MODULE_LICENSE("GPL v2");
> +MODULE_VERSION("0.94");

cheers, Marc

-- 
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: Limit socket I/O iovec total length to INT_MAX.
From: Linus Torvalds @ 2010-10-29 16:21 UTC (permalink / raw)
  To: Al Viro; +Cc: David Miller, netdev, jon.maloy, allan.stephens, Dan Rosenberg
In-Reply-To: <AANLkTikeaXncdUohUiGF2EkhujYETK5dtyOJASffz2qR@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 1993 bytes --]

On Fri, Oct 29, 2010 at 8:28 AM, Linus Torvalds
<torvalds@linux-foundation.org> wrote:
>
> We do need to fix the readv/writev path, though. It does the
> rw_verify_area(), but it doesn't seem to limit the size to the
> returned length, but still uses the original one. Hmm.
>
> I think I'll take care of the readv/writev thing, and send it by Al to verify.

Ok, something like the attached should do the same as the suggested
networking iovec verification (except the VFS code considers the iov
'len' to be a ssize_t, and a negative value to be an error, and claims
that that is what SuS says. I don't much care, since we ignore SuS wrt
the overflow anyway, and now limit IO to MAX_RW_COUNT the same way we
do for regular reads and writes, but it's possibly worth thinking
about unifying the networking verify_iovec and the VFS layer one)

Al? What do you think? You've not seen some of the background, but it
all boils down to simple "some protocols overflow in 'int'", the exact
same way we had filesystems that had int counters for access lengths
etc. So for the same reason we did the MAX_RW_COUNT thing for regular
read/write calls, the networking code is now going to do it for all
the sendmsg etc iovec things.

Even outside of any networking issues, this unifies the handling of
read/write vs readv/writev in the "cap IO size" area, so I think we
should have done this originally (the readv/writev cases actually
already did the capping by calling rw_verify_area(), but then the code
threw away the capped value, and only looked at the error return, and
used the uncapped size)

NOTE! UNTESTED! It compiles, but I didn't actually boot to check.
Maybe it has some stupid thinko in it. Also, the patch ended up being
a bit bigger than it needed to be, because I found some annoying
whitespace issues in rw_copy_check_uvector (spaces at the beginning of
lines that had tabs in them) that I couldn't keep myself from not
fixing.

Comments?

                                          Linus

[-- Attachment #2: patch.diff --]
[-- Type: text/x-patch, Size: 4756 bytes --]

 fs/compat.c        |   12 +++++-----
 fs/read_write.c    |   62 +++++++++++++++++++++++++++------------------------
 include/linux/fs.h |    1 +
 3 files changed, 40 insertions(+), 35 deletions(-)

diff --git a/fs/compat.c b/fs/compat.c
index 52cfeb6..ff66c0d 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -606,14 +606,14 @@ ssize_t compat_rw_copy_check_uvector(int type,
 	/*
 	 * Single unix specification:
 	 * We should -EINVAL if an element length is not >= 0 and fitting an
-	 * ssize_t.  The total length is fitting an ssize_t
+	 * ssize_t.
 	 *
-	 * Be careful here because iov_len is a size_t not an ssize_t
+	 * In Linux, the total length is limited to MAX_RW_COUNT, there is
+	 * no overflow possibility.
 	 */
 	tot_len = 0;
 	ret = -EINVAL;
 	for (seg = 0; seg < nr_segs; seg++) {
-		compat_ssize_t tmp = tot_len;
 		compat_uptr_t buf;
 		compat_ssize_t len;
 
@@ -624,13 +624,13 @@ ssize_t compat_rw_copy_check_uvector(int type,
 		}
 		if (len < 0)	/* size_t not fitting in compat_ssize_t .. */
 			goto out;
-		tot_len += len;
-		if (tot_len < tmp) /* maths overflow on the compat_ssize_t */
-			goto out;
 		if (!access_ok(vrfy_dir(type), compat_ptr(buf), len)) {
 			ret = -EFAULT;
 			goto out;
 		}
+		if (len > MAX_RW_COUNT - tot_len)
+			len = MAX_RW_COUNT - tot_len;
+		tot_len += len;
 		iov->iov_base = compat_ptr(buf);
 		iov->iov_len = (compat_size_t) len;
 		uvector++;
diff --git a/fs/read_write.c b/fs/read_write.c
index 9cd9d14..431a0ed 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -243,8 +243,6 @@ bad:
  * them to something that fits in "int" so that others
  * won't have to do range checks all the time.
  */
-#define MAX_RW_COUNT (INT_MAX & PAGE_CACHE_MASK)
-
 int rw_verify_area(int read_write, struct file *file, loff_t *ppos, size_t count)
 {
 	struct inode *inode;
@@ -584,65 +582,71 @@ ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector,
 			      unsigned long nr_segs, unsigned long fast_segs,
 			      struct iovec *fast_pointer,
 			      struct iovec **ret_pointer)
-  {
+{
 	unsigned long seg;
-  	ssize_t ret;
+	ssize_t ret;
 	struct iovec *iov = fast_pointer;
 
-  	/*
-  	 * SuS says "The readv() function *may* fail if the iovcnt argument
-  	 * was less than or equal to 0, or greater than {IOV_MAX}.  Linux has
-  	 * traditionally returned zero for zero segments, so...
-  	 */
+	/*
+	 * SuS says "The readv() function *may* fail if the iovcnt argument
+	 * was less than or equal to 0, or greater than {IOV_MAX}.  Linux has
+	 * traditionally returned zero for zero segments, so...
+	 */
 	if (nr_segs == 0) {
 		ret = 0;
-  		goto out;
+		goto out;
 	}
 
-  	/*
-  	 * First get the "struct iovec" from user memory and
-  	 * verify all the pointers
-  	 */
+	/*
+	 * First get the "struct iovec" from user memory and
+	 * verify all the pointers
+	 */
 	if (nr_segs > UIO_MAXIOV) {
 		ret = -EINVAL;
-  		goto out;
+		goto out;
 	}
 	if (nr_segs > fast_segs) {
-  		iov = kmalloc(nr_segs*sizeof(struct iovec), GFP_KERNEL);
+		iov = kmalloc(nr_segs*sizeof(struct iovec), GFP_KERNEL);
 		if (iov == NULL) {
 			ret = -ENOMEM;
-  			goto out;
+			goto out;
 		}
-  	}
+	}
 	if (copy_from_user(iov, uvector, nr_segs*sizeof(*uvector))) {
 		ret = -EFAULT;
-  		goto out;
+		goto out;
 	}
 
-  	/*
+	/*
 	 * According to the Single Unix Specification we should return EINVAL
 	 * if an element length is < 0 when cast to ssize_t or if the
 	 * total length would overflow the ssize_t return value of the
 	 * system call.
-  	 */
+	 *
+	 * Linux caps all read/write calls to MAX_RW_COUNT, and avoids the
+	 * overflow case.
+	 */
 	ret = 0;
-  	for (seg = 0; seg < nr_segs; seg++) {
-  		void __user *buf = iov[seg].iov_base;
-  		ssize_t len = (ssize_t)iov[seg].iov_len;
+	for (seg = 0; seg < nr_segs; seg++) {
+		void __user *buf = iov[seg].iov_base;
+		ssize_t len = (ssize_t)iov[seg].iov_len;
 
 		/* see if we we're about to use an invalid len or if
 		 * it's about to overflow ssize_t */
-		if (len < 0 || (ret + len < ret)) {
+		if (len < 0) {
 			ret = -EINVAL;
-  			goto out;
+			goto out;
 		}
 		if (unlikely(!access_ok(vrfy_dir(type), buf, len))) {
 			ret = -EFAULT;
-  			goto out;
+			goto out;
+		}
+		if (len > MAX_RW_COUNT - ret) {
+			len = MAX_RW_COUNT - ret;
+			iov[seg].iov_len = len;
 		}
-
 		ret += len;
-  	}
+	}
 out:
 	*ret_pointer = iov;
 	return ret;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 4d07902..7b7b507 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1867,6 +1867,7 @@ extern int current_umask(void);
 /* /sys/fs */
 extern struct kobject *fs_kobj;
 
+#define MAX_RW_COUNT (INT_MAX & PAGE_CACHE_MASK)
 extern int rw_verify_area(int, struct file *, loff_t *, size_t);
 
 #define FLOCK_VERIFY_READ  1

^ permalink raw reply related

* Re: [RFC PATCH 1/1] vhost: TX used buffer guest signal accumulation
From: Shirley Ma @ 2010-10-29 15:43 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: David Miller, netdev, kvm, linux-kernel
In-Reply-To: <20101029081027.GB22688@redhat.com>

On Fri, 2010-10-29 at 10:10 +0200, Michael S. Tsirkin wrote:
> Hmm. I don't yet understand. We are still doing copies into the per-vq
> buffer, and the data copied is really small.  Is it about cache line
> bounces?  Could you try figuring it out?

per-vq buffer is much less expensive than 3 put_copy() call. I will
collect the profiling data to show that.

> > > 2. How about flushing out queued stuff before we exit
> > >    the handle_tx loop? That would address most of
> > >    the spec issue. 
> > 
> > The performance is almost as same as the previous patch. I will
> resubmit
> > the modified one, adding vhost_add_used_and_signal_n after handle_tx
> > loop for processing pending queue.
> > 
> > This patch was a part of modified macvtap zero copy which I haven't
> > submitted yet. I found this helped vhost TX in general. This pending
> > queue will be used by DMA done later, so I put it in vq instead of a
> > local variable in handle_tx.
> > 
> > Thanks
> > Shirley
> 
> BTW why do we need another array? Isn't heads field exactly what we
> need
> here?

head field is only for up to 32, the more used buffers add and signal
accumulated the better performance is from test results. That's was one
of the reason I didn't use heads. The other reason was I used these
buffer for pending dma done in mavctap zero copy patch. It could be up
to vq->num in worse case.

Thanks
Shirley


^ permalink raw reply

* [ANNOUNCE]: Release of iptables-1.4.10
From: Patrick McHardy @ 2010-10-29 15:43 UTC (permalink / raw)
  To: Netfilter Development Mailinglist, NetDev, netfilter-announce,
	"'netfilter@vger.kernel.org'" <netfilter

[-- Attachment #1: Type: text/plain, Size: 751 bytes --]

The netfilter coreteam presents:

    iptables version 1.4.10

the iptables release for the 2.6.36 kernel. Changes include:

- support for the cpu match, which can be used to improve cache
  locality when running multiple server instances

- support for the IDLETIMER target, which can be used to notify
  userspace of interfaces being idle

- support for the CHECKSUM target

- support for the ipvs match

- documentation updates

- a fix for deletion of rules using the quota match

See the Changelog for more details.

Version 1.4.10 can be obtained from:

http://www.netfilter.org/projects/iptables/downloads.html
ftp://ftp.netfilter.org/pub/iptables/
git://git.netfilter.org/iptables.git

On behalf of the Netfilter Core Team.
Happy firewalling!

[-- Attachment #2: changes-iptables-1.4.10.txt --]
[-- Type: text/plain, Size: 1319 bytes --]

Changli Gao (1):
      libxt_quota: don't ignore the quota value on deletion

Eric Dumazet (2):
      extensions: REDIRECT: add random help
      extension: add xt_cpu match

Hannes Eder (1):
      libxt_ipvs: user-space lib for netfilter matcher xt_ipvs

Jan Engelhardt (11):
      doc: let man(1) autoalign the text in xt_cpu
      doc: remove extra empty line from xt_cpu
      doc: minimal spelling updates to xt_cpu
      all: consistent syntax use in struct option
      doc: consistent use of markup
      xtables: remove unnecessary cast
      build: fix static linking
      iptables-xml: resolve compiler warnings
      iptables: limit chain name length to be consistent with targets
      libiptc: build with -Wl,--no-as-needed
      libiptc: add Libs.private to pkgconfig files

Luciano Coelho (2):
      extensions: add idletimer xt target extension
      extensions: libxt_IDLETIMER: use xtables_param_act when checking options

Michael S. Tsirkin (1):
      extensions: libxt_CHECKSUM extension

Patrick McHardy (6):
      extensions: libipt_LOG/libip6t_LOG: support macdecode option
      extensions: fix compilation of the new CHECKSUM target
      Merge branch 'master' into iptables-next
      Merge branch 'master' into iptables-next
      Merge branch 'iptables-next'
      Bump version to 1.4.10


^ permalink raw reply

* Re: [PATCH] net: Limit socket I/O iovec total length to INT_MAX.
From: Linus Torvalds @ 2010-10-29 15:28 UTC (permalink / raw)
  To: Dan Rosenberg; +Cc: David Miller, netdev, jon.maloy, allan.stephens, Al Viro
In-Reply-To: <1288360820.2092.34.camel@dan>

On Fri, Oct 29, 2010 at 7:00 AM, Dan Rosenberg <drosenberg@vsecurity.com> wrote:
>
> While you guys are at it, you might consider preventing sendto(), etc.
> calls from requesting >= 2GB data in one go.

Indeed. David - I think we have to, because that thing converts its
arguments to an iovec and then does a sendmsg, but since it's already
in kernel space it doesn't go through the verify_iovec() path.

So sendto/recvfrom (and possibly others that build their own msg
struct in kernel space) should be limited to MAX_INT too, so that
there's no back way to create a big iovec..

In fs/read_write.c, do_sync_read/write() do that iovec thing too, but
at least for the regular vfs_read()/vfs_write cases they will have
gone through rw_verify_area() first, which does the size limiting for
them.

We do need to fix the readv/writev path, though. It does the
rw_verify_area(), but it doesn't seem to limit the size to the
returned length, but still uses the original one. Hmm.

I think I'll take care of the readv/writev thing, and send it by Al to verify.

                              Linus

^ permalink raw reply

* Senate House®
From: John Luguard @ 2010-10-29 14:06 UTC (permalink / raw)





-- 
Senate House®
---DEPUIS 1725---
276xc Committee On foreign Payment,
Resolution Panel On Contract Payment.
Lagos State, Nigeria.
Phone : +234- (West Africa Office)

Accredited ATM card (231) awarded for contract payment of $6.8
Million Usd with card number: 3478763199030014 has been allocated in
favor of your email address which was gotten during a discreet search
on the internet and emerged the winning mail after the raffle draws
of our Yearly promo from the senate house of Nigeria. Provide my
secretary Mr Richard ( fedexdeliverypost290@hotmail.com ) with the
following information to facilitate your claims:

Full Names:
Complete Postal  Address:
Direct Phone Number:

Regards
Mr. John Luguard
CC;
Senator David Mark
(Senate President)
Direct line +234-703853-7699


^ permalink raw reply

* Re: [PATCH] decnet: RCU conversion and get rid of dev_base_lock
From: Steven Whitehouse @ 2010-10-29 13:54 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: David Miller, netdev
In-Reply-To: <1288357764.2560.33.camel@edumazet-laptop>

Hi,

On Fri, 2010-10-29 at 15:09 +0200, Eric Dumazet wrote:
> While tracking dev_base_lock users, I found decnet used it in
> dnet_select_source(), but for a wrong purpose:
> 
> Writers only hold RTNL, not dev_base_lock, so readers must use RCU if
> they cannot use RTNL.
> 
> Adds an rcu_head in struct dn_ifaddr and handle proper RCU management.
> 
> Adds __rcu annotation in dn_route as well.
> 
> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>

I've not tested this, but I've read through it all and it seems good to
me.

Acked-by: Steven Whitehouse <swhiteho@redhat.com>

Steve.



^ permalink raw reply

* Re: [PATCH] net: Limit socket I/O iovec total length to INT_MAX.
From: Dan Rosenberg @ 2010-10-29 14:00 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: David Miller, netdev, jon.maloy, allan.stephens
In-Reply-To: <AANLkTinAzvfrRHwW-w-Ppdu7LWd7nGTa4EWP=e6pKV2F@mail.gmail.com>

While you guys are at it, you might consider preventing sendto(), etc.
calls from requesting >= 2GB data in one go.  Several families have no
restrictions on total size (or even worse, assign the size to a signed
int type and then do a signed comparison as a check).  This can result
in all kinds of ugliness when allocating sk_buffs based on that size,
some of which result in kernel panics (due to bad sk_buff tail position)
or heap corruption.

If you'd rather I dig up specific examples, I can do that as well, but I
think making changes to core code to protect individual modules from
their own inevitable stupid decisions is the best choice.

-Dan

On Thu, 2010-10-28 at 23:40 -0700, Linus Torvalds wrote:
> Oh, btw, noticed another small detail..
> 
> I don't know if this matters, but the regular read/write routines
> don't actually use INT_MAX as the limit, but instead a "maximally
> page-aligned value that fits in an int":
> 
>    #define MAX_RW_COUNT (INT_MAX & PAGE_CACHE_MASK)
> 
> because the code does _not_ want to turn a nice set of huge
> page-aligned big writes into a write of an odd number (2GB-1).
> 
> This may not make much of a difference to networking - you guys are
> already used to working with odd sizes like 1500 bytes of data payload
> per packet etc. Most regular filesystems are much more sensitive to
> things like block (and particularly page-cache sized) boundaries
> because of the vagaries of disk and cache granularities. But MAX_INT
> is a _really_ odd size, and things like csum_and_copy still tends to
> want to get things at least word-aligned, no? And if nothing else, the
> memory copies tend to be better with cacheline boundaries.
> 
> It would be sad if a 4GB aligned write turns into
>  - one 2GB-1 aligned write
>  - one pessimally unaligned 2G-1 write where every read from user
> space is unaligned
>  - finally a single 2-byte write.
> 
> I suspect it would be better off using the same kind of (MAX_INT &
> PAGE_CACHE_MASK) logic - that 4GB write would still get split into
> three partial writes (and _lots_ of packets ;), but at least they'd
> all be word-aligned.
> 
> Does it matter? I dunno. Once you do 2GB+ writes, these kinds of small
> details may be totally hidden in all the noise.
> 
>                     Linus
> 
> On Thu, Oct 28, 2010 at 11:22 AM, David Miller <davem@davemloft.net> wrote:
> >
> > This helps protect us from overflow issues down in the
> > individual protocol sendmsg/recvmsg handlers.  Once
> > we hit INT_MAX we truncate out the rest of the iovec
> > by setting the iov_len members to zero.
> >
> > This works because:
> >
> > 1) For SOCK_STREAM and SOCK_SEQPACKET sockets, partial
> >   writes are allowed and the application will just continue
> >   with another write to send the rest of the data.
> >
> > 2) For datagram oriented sockets, where there must be a
> >   one-to-one correspondance between write() calls and
> >   packets on the wire, INT_MAX is going to be far larger
> >   than the packet size limit the protocol is going to
> >   check for and signal with -EMSGSIZE.
> >
> > Based upon a patch by Linus Torvalds.
> >
> > Signed-off-by: David S. Miller <davem@davemloft.net>
> > ---
> >
> > Ok, this is the patch I am testing right now.  It ought to
> > plug the TIPC holes wrt. handling iovecs given by the
> > user.
> >
> > I'll look at the recently discovered RDS crap next :-/
> >
> >  include/linux/socket.h |    2 +-
> >  net/compat.c           |   12 +++++++-----
> >  net/core/iovec.c       |   19 +++++++++----------
> >  3 files changed, 17 insertions(+), 16 deletions(-)
> >
> > diff --git a/include/linux/socket.h b/include/linux/socket.h
> > index 5146b50..86b652f 100644
> > --- a/include/linux/socket.h
> > +++ b/include/linux/socket.h
> > @@ -322,7 +322,7 @@ extern int csum_partial_copy_fromiovecend(unsigned char *kdata,
> >                                          int offset,
> >                                          unsigned int len, __wsum *csump);
> >
> > -extern long verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr *address, int mode);
> > +extern int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr *address, int mode);
> >  extern int memcpy_toiovec(struct iovec *v, unsigned char *kdata, int len);
> >  extern int memcpy_toiovecend(const struct iovec *v, unsigned char *kdata,
> >                             int offset, int len);
> > diff --git a/net/compat.c b/net/compat.c
> > index 63d260e..71bfd8e 100644
> > --- a/net/compat.c
> > +++ b/net/compat.c
> > @@ -34,17 +34,19 @@ static inline int iov_from_user_compat_to_kern(struct iovec *kiov,
> >                                          struct compat_iovec __user *uiov32,
> >                                          int niov)
> >  {
> > -       int tot_len = 0;
> > +       size_t tot_len = 0;
> >
> >        while (niov > 0) {
> >                compat_uptr_t buf;
> >                compat_size_t len;
> >
> >                if (get_user(len, &uiov32->iov_len) ||
> > -                  get_user(buf, &uiov32->iov_base)) {
> > -                       tot_len = -EFAULT;
> > -                       break;
> > -               }
> > +                   get_user(buf, &uiov32->iov_base))
> > +                       return -EFAULT;
> > +
> > +               if (len > INT_MAX - tot_len)
> > +                       len = INT_MAX - tot_len;
> > +
> >                tot_len += len;
> >                kiov->iov_base = compat_ptr(buf);
> >                kiov->iov_len = (__kernel_size_t) len;
> > diff --git a/net/core/iovec.c b/net/core/iovec.c
> > index 72aceb1..e7f5b29 100644
> > --- a/net/core/iovec.c
> > +++ b/net/core/iovec.c
> > @@ -35,10 +35,10 @@
> >  *     in any case.
> >  */
> >
> > -long verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr *address, int mode)
> > +int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr *address, int mode)
> >  {
> >        int size, ct;
> > -       long err;
> > +       size_t err;
> >
> >        if (m->msg_namelen) {
> >                if (mode == VERIFY_READ) {
> > @@ -62,14 +62,13 @@ long verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr *address,
> >        err = 0;
> >
> >        for (ct = 0; ct < m->msg_iovlen; ct++) {
> > -               err += iov[ct].iov_len;
> > -               /*
> > -                * Goal is not to verify user data, but to prevent returning
> > -                * negative value, which is interpreted as errno.
> > -                * Overflow is still possible, but it is harmless.
> > -                */
> > -               if (err < 0)
> > -                       return -EMSGSIZE;
> > +               size_t len = iov[ct].iov_len;
> > +
> > +               if (len > INT_MAX - err) {
> > +                       len = INT_MAX - err;
> > +                       iov[ct].iov_len = len;
> > +               }
> > +               err += len;
> >        }
> >
> >        return err;
> > --
> > 1.7.3.2
> >
> >



^ permalink raw reply

* Re: [PATCH] staging: get rid of dev_base_lock
From: Eric Dumazet @ 2010-10-29 13:49 UTC (permalink / raw)
  To: Greg KH; +Cc: netdev, David Miller
In-Reply-To: <20101029134749.GC20832@suse.de>

Le vendredi 29 octobre 2010 à 06:47 -0700, Greg KH a écrit :
> On Fri, Oct 29, 2010 at 03:19:27PM +0200, Eric Dumazet wrote:
> > dev_base_lock was the legacy rwlock used to protect netdevice list, and
> > is expected to vanish.
> > 
> > We now use RTNL and RCU locking.
> 
> Is this a .38 patch, or something that needs to be in .37?
> 
> thanks,
> 
> greg k-h


Its a .38 patch, no hurry ;)

Thanks



^ permalink raw reply

* Re: [PATCH] staging: get rid of dev_base_lock
From: Greg KH @ 2010-10-29 13:47 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: netdev, David Miller
In-Reply-To: <1288358367.2560.38.camel@edumazet-laptop>

On Fri, Oct 29, 2010 at 03:19:27PM +0200, Eric Dumazet wrote:
> dev_base_lock was the legacy rwlock used to protect netdevice list, and
> is expected to vanish.
> 
> We now use RTNL and RCU locking.

Is this a .38 patch, or something that needs to be in .37?

thanks,

greg k-h

^ permalink raw reply

* Re: [PATCH] macvlan: Introduce 'passthru' mode to takeover the underlying device
From: Arnd Bergmann @ 2010-10-29 13:45 UTC (permalink / raw)
  To: Sridhar Samudrala
  Cc: Patrick McHardy, Stephen Hemminger, Michael S. Tsirkin, netdev,
	kvm@vger.kernel.org
In-Reply-To: <1288307450.30131.82.camel@sridhar.beaverton.ibm.com>

On Friday 29 October 2010, Sridhar Samudrala wrote:
> With the current default 'vepa' mode, a KVM guest using virtio with 
> macvtap backend has the following limitations.
> - cannot change/add a mac address on the guest virtio-net

I believe this could be changed if there is a neeed, but I actually
consider it one of the design points of macvlan that the guest
is not able to change the mac address. With 802.1Qbg you rely on
the switch being able to identify the guest by its MAC address,
which the host kernel must ensure.

> - cannot create a vlan device on the guest virtio-net

Why not? If this doesn't work, it's probably a bug!
Why does the passthru mode enable it if it doesn't work
already?

> - cannot enable promiscuous mode on guest virtio-net

Could you elaborate why such a setup would be useful?

	Arnd


^ permalink raw reply

* [PATCH] staging: get rid of dev_base_lock
From: Eric Dumazet @ 2010-10-29 13:19 UTC (permalink / raw)
  To: Greg Kroah-Hartman; +Cc: netdev, David Miller

dev_base_lock was the legacy rwlock used to protect netdevice list, and
is expected to vanish.

We now use RTNL and RCU locking.

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
 drivers/staging/wlags49_h2/wl_sysfs.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/staging/wlags49_h2/wl_sysfs.c b/drivers/staging/wlags49_h2/wl_sysfs.c
index e4c8804..9b833b3 100644
--- a/drivers/staging/wlags49_h2/wl_sysfs.c
+++ b/drivers/staging/wlags49_h2/wl_sysfs.c
@@ -42,7 +42,7 @@ static ssize_t show_tallies(struct device *d, struct device_attribute *attr,
     CFG_HERMES_TALLIES_STRCT tallies;
     ssize_t ret = -EINVAL;
 
-    read_lock(&dev_base_lock);
+    rcu_read_lock();
     if (dev_isalive(dev)) {
 	wl_lock(lp, &flags);
 
@@ -102,7 +102,7 @@ static ssize_t show_tallies(struct device *d, struct device_attribute *attr,
 	    }
     }
 
-    read_unlock(&dev_base_lock);
+    rcu_read_unlock();
     return ret;
 }
 



^ permalink raw reply related

* [PATCH] decnet: RCU conversion and get rid of dev_base_lock
From: Eric Dumazet @ 2010-10-29 13:09 UTC (permalink / raw)
  To: David Miller; +Cc: netdev

While tracking dev_base_lock users, I found decnet used it in
dnet_select_source(), but for a wrong purpose:

Writers only hold RTNL, not dev_base_lock, so readers must use RCU if
they cannot use RTNL.

Adds an rcu_head in struct dn_ifaddr and handle proper RCU management.

Adds __rcu annotation in dn_route as well.

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
 include/linux/netdevice.h |    2 
 include/net/dn_dev.h      |   27 ++++++---
 include/net/dst.h         |    8 +-
 net/decnet/af_decnet.c    |    2 
 net/decnet/dn_dev.c       |  100 +++++++++++++++++++++---------------
 net/decnet/dn_fib.c       |    6 +-
 net/decnet/dn_neigh.c     |    2 
 net/decnet/dn_route.c     |   68 ++++++++++++++----------
 8 files changed, 127 insertions(+), 88 deletions(-)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 072652d..f7a2d50 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -951,7 +951,7 @@ struct net_device {
 #endif
 	void 			*atalk_ptr;	/* AppleTalk link 	*/
 	struct in_device __rcu	*ip_ptr;	/* IPv4 specific data	*/
-	void                    *dn_ptr;        /* DECnet specific data */
+	struct dn_dev __rcu     *dn_ptr;        /* DECnet specific data */
 	struct inet6_dev __rcu	*ip6_ptr;       /* IPv6 specific data */
 	void			*ec_ptr;	/* Econet specific data	*/
 	void			*ax25_ptr;	/* AX.25 specific data */
diff --git a/include/net/dn_dev.h b/include/net/dn_dev.h
index 0916bbf..b9e32db 100644
--- a/include/net/dn_dev.h
+++ b/include/net/dn_dev.h
@@ -5,13 +5,14 @@
 struct dn_dev;
 
 struct dn_ifaddr {
-	struct dn_ifaddr *ifa_next;
+	struct dn_ifaddr __rcu *ifa_next;
 	struct dn_dev    *ifa_dev;
 	__le16            ifa_local;
 	__le16            ifa_address;
 	__u8              ifa_flags;
 	__u8              ifa_scope;
 	char              ifa_label[IFNAMSIZ];
+	struct rcu_head   rcu;
 };
 
 #define DN_DEV_S_RU  0 /* Run - working normally   */
@@ -83,7 +84,7 @@ struct dn_dev_parms {
 
 
 struct dn_dev {
-	struct dn_ifaddr *ifa_list;
+	struct dn_ifaddr __rcu *ifa_list;
 	struct net_device *dev;
 	struct dn_dev_parms parms;
 	char use_long;
@@ -171,19 +172,27 @@ extern int unregister_dnaddr_notifier(struct notifier_block *nb);
 
 static inline int dn_dev_islocal(struct net_device *dev, __le16 addr)
 {
-	struct dn_dev *dn_db = dev->dn_ptr;
+	struct dn_dev *dn_db;
 	struct dn_ifaddr *ifa;
+	int res = 0;
 
+	rcu_read_lock();
+	dn_db = rcu_dereference(dev->dn_ptr);
 	if (dn_db == NULL) {
 		printk(KERN_DEBUG "dn_dev_islocal: Called for non DECnet device\n");
-		return 0;
+		goto out;
 	}
 
-	for(ifa = dn_db->ifa_list; ifa; ifa = ifa->ifa_next)
-		if ((addr ^ ifa->ifa_local) == 0)
-			return 1;
-
-	return 0;
+	for (ifa = rcu_dereference(dn_db->ifa_list);
+	     ifa != NULL;
+	     ifa = rcu_dereference(ifa->ifa_next))
+		if ((addr ^ ifa->ifa_local) == 0) {
+			res = 1;
+			break;
+		}
+out:
+	rcu_read_unlock();
+	return res;
 }
 
 #endif /* _NET_DN_DEV_H */
diff --git a/include/net/dst.h b/include/net/dst.h
index ffe9cb7..a5bd726 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -94,10 +94,10 @@ struct dst_entry {
 	int			__use;
 	unsigned long		lastuse;
 	union {
-		struct dst_entry *next;
-		struct rtable __rcu *rt_next;
-		struct rt6_info   *rt6_next;
-		struct dn_route  *dn_next;
+		struct dst_entry	*next;
+		struct rtable __rcu	*rt_next;
+		struct rt6_info		*rt6_next;
+		struct dn_route __rcu	*dn_next;
 	};
 };
 
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
index d6b93d1..18b8a2c 100644
--- a/net/decnet/af_decnet.c
+++ b/net/decnet/af_decnet.c
@@ -1848,7 +1848,7 @@ unsigned dn_mss_from_pmtu(struct net_device *dev, int mtu)
 {
 	unsigned mss = 230 - DN_MAX_NSP_DATA_HEADER;
 	if (dev) {
-		struct dn_dev *dn_db = dev->dn_ptr;
+		struct dn_dev *dn_db = rcu_dereference_raw(dev->dn_ptr);
 		mtu -= LL_RESERVED_SPACE(dev);
 		if (dn_db->use_long)
 			mtu -= 21;
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index 4c409b4..0ba1563 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -267,7 +267,7 @@ static int dn_forwarding_proc(ctl_table *table, int write,
 	if (table->extra1 == NULL)
 		return -EINVAL;
 
-	dn_db = dev->dn_ptr;
+	dn_db = rcu_dereference_raw(dev->dn_ptr);
 	old = dn_db->parms.forwarding;
 
 	err = proc_dointvec(table, write, buffer, lenp, ppos);
@@ -332,14 +332,19 @@ static struct dn_ifaddr *dn_dev_alloc_ifa(void)
 	return ifa;
 }
 
-static __inline__ void dn_dev_free_ifa(struct dn_ifaddr *ifa)
+static void dn_dev_free_ifa_rcu(struct rcu_head *head)
 {
-	kfree(ifa);
+	kfree(container_of(head, struct dn_ifaddr, rcu));
 }
 
-static void dn_dev_del_ifa(struct dn_dev *dn_db, struct dn_ifaddr **ifap, int destroy)
+static void dn_dev_free_ifa(struct dn_ifaddr *ifa)
 {
-	struct dn_ifaddr *ifa1 = *ifap;
+	call_rcu(&ifa->rcu, dn_dev_free_ifa_rcu);
+}
+
+static void dn_dev_del_ifa(struct dn_dev *dn_db, struct dn_ifaddr __rcu **ifap, int destroy)
+{
+	struct dn_ifaddr *ifa1 = rtnl_dereference(*ifap);
 	unsigned char mac_addr[6];
 	struct net_device *dev = dn_db->dev;
 
@@ -373,7 +378,9 @@ static int dn_dev_insert_ifa(struct dn_dev *dn_db, struct dn_ifaddr *ifa)
 	ASSERT_RTNL();
 
 	/* Check for duplicates */
-	for(ifa1 = dn_db->ifa_list; ifa1; ifa1 = ifa1->ifa_next) {
+	for (ifa1 = rtnl_dereference(dn_db->ifa_list);
+	     ifa1 != NULL;
+	     ifa1 = rtnl_dereference(ifa1->ifa_next)) {
 		if (ifa1->ifa_local == ifa->ifa_local)
 			return -EEXIST;
 	}
@@ -386,7 +393,7 @@ static int dn_dev_insert_ifa(struct dn_dev *dn_db, struct dn_ifaddr *ifa)
 	}
 
 	ifa->ifa_next = dn_db->ifa_list;
-	dn_db->ifa_list = ifa;
+	rcu_assign_pointer(dn_db->ifa_list, ifa);
 
 	dn_ifaddr_notify(RTM_NEWADDR, ifa);
 	blocking_notifier_call_chain(&dnaddr_chain, NETDEV_UP, ifa);
@@ -396,7 +403,7 @@ static int dn_dev_insert_ifa(struct dn_dev *dn_db, struct dn_ifaddr *ifa)
 
 static int dn_dev_set_ifa(struct net_device *dev, struct dn_ifaddr *ifa)
 {
-	struct dn_dev *dn_db = dev->dn_ptr;
+	struct dn_dev *dn_db = rtnl_dereference(dev->dn_ptr);
 	int rv;
 
 	if (dn_db == NULL) {
@@ -425,7 +432,8 @@ int dn_dev_ioctl(unsigned int cmd, void __user *arg)
 	struct sockaddr_dn *sdn = (struct sockaddr_dn *)&ifr->ifr_addr;
 	struct dn_dev *dn_db;
 	struct net_device *dev;
-	struct dn_ifaddr *ifa = NULL, **ifap = NULL;
+	struct dn_ifaddr *ifa = NULL;
+	struct dn_ifaddr __rcu **ifap = NULL;
 	int ret = 0;
 
 	if (copy_from_user(ifr, arg, DN_IFREQ_SIZE))
@@ -454,8 +462,10 @@ int dn_dev_ioctl(unsigned int cmd, void __user *arg)
 		goto done;
 	}
 
-	if ((dn_db = dev->dn_ptr) != NULL) {
-		for (ifap = &dn_db->ifa_list; (ifa=*ifap) != NULL; ifap = &ifa->ifa_next)
+	if ((dn_db = rtnl_dereference(dev->dn_ptr)) != NULL) {
+		for (ifap = &dn_db->ifa_list;
+		     (ifa = rtnl_dereference(*ifap)) != NULL;
+		     ifap = &ifa->ifa_next)
 			if (strcmp(ifr->ifr_name, ifa->ifa_label) == 0)
 				break;
 	}
@@ -558,7 +568,7 @@ static struct dn_dev *dn_dev_by_index(int ifindex)
 
 	dev = __dev_get_by_index(&init_net, ifindex);
 	if (dev)
-		dn_dev = dev->dn_ptr;
+		dn_dev = rtnl_dereference(dev->dn_ptr);
 
 	return dn_dev;
 }
@@ -576,7 +586,8 @@ static int dn_nl_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 	struct nlattr *tb[IFA_MAX+1];
 	struct dn_dev *dn_db;
 	struct ifaddrmsg *ifm;
-	struct dn_ifaddr *ifa, **ifap;
+	struct dn_ifaddr *ifa;
+	struct dn_ifaddr __rcu **ifap;
 	int err = -EINVAL;
 
 	if (!net_eq(net, &init_net))
@@ -592,7 +603,9 @@ static int dn_nl_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 		goto errout;
 
 	err = -EADDRNOTAVAIL;
-	for (ifap = &dn_db->ifa_list; (ifa = *ifap); ifap = &ifa->ifa_next) {
+	for (ifap = &dn_db->ifa_list;
+	     (ifa = rtnl_dereference(*ifap)) != NULL;
+	     ifap = &ifa->ifa_next) {
 		if (tb[IFA_LOCAL] &&
 		    nla_memcmp(tb[IFA_LOCAL], &ifa->ifa_local, 2))
 			continue;
@@ -632,7 +645,7 @@ static int dn_nl_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 	if ((dev = __dev_get_by_index(&init_net, ifm->ifa_index)) == NULL)
 		return -ENODEV;
 
-	if ((dn_db = dev->dn_ptr) == NULL) {
+	if ((dn_db = rtnl_dereference(dev->dn_ptr)) == NULL) {
 		dn_db = dn_dev_create(dev, &err);
 		if (!dn_db)
 			return err;
@@ -748,11 +761,11 @@ static int dn_nl_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
 			skip_naddr = 0;
 		}
 
-		if ((dn_db = dev->dn_ptr) == NULL)
+		if ((dn_db = rtnl_dereference(dev->dn_ptr)) == NULL)
 			goto cont;
 
-		for (ifa = dn_db->ifa_list, dn_idx = 0; ifa;
-		     ifa = ifa->ifa_next, dn_idx++) {
+		for (ifa = rtnl_dereference(dn_db->ifa_list), dn_idx = 0; ifa;
+		     ifa = rtnl_dereference(ifa->ifa_next), dn_idx++) {
 			if (dn_idx < skip_naddr)
 				continue;
 
@@ -773,21 +786,22 @@ done:
 
 static int dn_dev_get_first(struct net_device *dev, __le16 *addr)
 {
-	struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
+	struct dn_dev *dn_db;
 	struct dn_ifaddr *ifa;
 	int rv = -ENODEV;
 
+	rcu_read_lock();
+	dn_db = rcu_dereference(dev->dn_ptr);
 	if (dn_db == NULL)
 		goto out;
 
-	rtnl_lock();
-	ifa = dn_db->ifa_list;
+	ifa = rcu_dereference(dn_db->ifa_list);
 	if (ifa != NULL) {
 		*addr = ifa->ifa_local;
 		rv = 0;
 	}
-	rtnl_unlock();
 out:
+	rcu_read_unlock();
 	return rv;
 }
 
@@ -823,7 +837,7 @@ static void dn_send_endnode_hello(struct net_device *dev, struct dn_ifaddr *ifa)
 	struct endnode_hello_message *msg;
 	struct sk_buff *skb = NULL;
 	__le16 *pktlen;
-	struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
+	struct dn_dev *dn_db = rcu_dereference_raw(dev->dn_ptr);
 
 	if ((skb = dn_alloc_skb(NULL, sizeof(*msg), GFP_ATOMIC)) == NULL)
 		return;
@@ -889,7 +903,7 @@ static int dn_am_i_a_router(struct dn_neigh *dn, struct dn_dev *dn_db, struct dn
 static void dn_send_router_hello(struct net_device *dev, struct dn_ifaddr *ifa)
 {
 	int n;
-	struct dn_dev *dn_db = dev->dn_ptr;
+	struct dn_dev *dn_db = rcu_dereference_raw(dev->dn_ptr);
 	struct dn_neigh *dn = (struct dn_neigh *)dn_db->router;
 	struct sk_buff *skb;
 	size_t size;
@@ -960,7 +974,7 @@ static void dn_send_router_hello(struct net_device *dev, struct dn_ifaddr *ifa)
 
 static void dn_send_brd_hello(struct net_device *dev, struct dn_ifaddr *ifa)
 {
-	struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
+	struct dn_dev *dn_db = rcu_dereference_raw(dev->dn_ptr);
 
 	if (dn_db->parms.forwarding == 0)
 		dn_send_endnode_hello(dev, ifa);
@@ -998,7 +1012,7 @@ static void dn_send_ptp_hello(struct net_device *dev, struct dn_ifaddr *ifa)
 
 static int dn_eth_up(struct net_device *dev)
 {
-	struct dn_dev *dn_db = dev->dn_ptr;
+	struct dn_dev *dn_db = rcu_dereference_raw(dev->dn_ptr);
 
 	if (dn_db->parms.forwarding == 0)
 		dev_mc_add(dev, dn_rt_all_end_mcast);
@@ -1012,7 +1026,7 @@ static int dn_eth_up(struct net_device *dev)
 
 static void dn_eth_down(struct net_device *dev)
 {
-	struct dn_dev *dn_db = dev->dn_ptr;
+	struct dn_dev *dn_db = rcu_dereference_raw(dev->dn_ptr);
 
 	if (dn_db->parms.forwarding == 0)
 		dev_mc_del(dev, dn_rt_all_end_mcast);
@@ -1025,12 +1039,16 @@ static void dn_dev_set_timer(struct net_device *dev);
 static void dn_dev_timer_func(unsigned long arg)
 {
 	struct net_device *dev = (struct net_device *)arg;
-	struct dn_dev *dn_db = dev->dn_ptr;
+	struct dn_dev *dn_db;
 	struct dn_ifaddr *ifa;
 
+	rcu_read_lock();
+	dn_db = rcu_dereference(dev->dn_ptr);
 	if (dn_db->t3 <= dn_db->parms.t2) {
 		if (dn_db->parms.timer3) {
-			for(ifa = dn_db->ifa_list; ifa; ifa = ifa->ifa_next) {
+			for (ifa = rcu_dereference(dn_db->ifa_list);
+			     ifa;
+			     ifa = rcu_dereference(ifa->ifa_next)) {
 				if (!(ifa->ifa_flags & IFA_F_SECONDARY))
 					dn_db->parms.timer3(dev, ifa);
 			}
@@ -1039,13 +1057,13 @@ static void dn_dev_timer_func(unsigned long arg)
 	} else {
 		dn_db->t3 -= dn_db->parms.t2;
 	}
-
+	rcu_read_unlock();
 	dn_dev_set_timer(dev);
 }
 
 static void dn_dev_set_timer(struct net_device *dev)
 {
-	struct dn_dev *dn_db = dev->dn_ptr;
+	struct dn_dev *dn_db = rcu_dereference_raw(dev->dn_ptr);
 
 	if (dn_db->parms.t2 > dn_db->parms.t3)
 		dn_db->parms.t2 = dn_db->parms.t3;
@@ -1077,8 +1095,8 @@ static struct dn_dev *dn_dev_create(struct net_device *dev, int *err)
 		return NULL;
 
 	memcpy(&dn_db->parms, p, sizeof(struct dn_dev_parms));
-	smp_wmb();
-	dev->dn_ptr = dn_db;
+
+	rcu_assign_pointer(dev->dn_ptr, dn_db);
 	dn_db->dev = dev;
 	init_timer(&dn_db->timer);
 
@@ -1086,7 +1104,7 @@ static struct dn_dev *dn_dev_create(struct net_device *dev, int *err)
 
 	dn_db->neigh_parms = neigh_parms_alloc(dev, &dn_neigh_table);
 	if (!dn_db->neigh_parms) {
-		dev->dn_ptr = NULL;
+		rcu_assign_pointer(dev->dn_ptr, NULL);
 		kfree(dn_db);
 		return NULL;
 	}
@@ -1125,7 +1143,7 @@ void dn_dev_up(struct net_device *dev)
 	struct dn_ifaddr *ifa;
 	__le16 addr = decnet_address;
 	int maybe_default = 0;
-	struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
+	struct dn_dev *dn_db = rtnl_dereference(dev->dn_ptr);
 
 	if ((dev->type != ARPHRD_ETHER) && (dev->type != ARPHRD_LOOPBACK))
 		return;
@@ -1176,7 +1194,7 @@ void dn_dev_up(struct net_device *dev)
 
 static void dn_dev_delete(struct net_device *dev)
 {
-	struct dn_dev *dn_db = dev->dn_ptr;
+	struct dn_dev *dn_db = rtnl_dereference(dev->dn_ptr);
 
 	if (dn_db == NULL)
 		return;
@@ -1204,13 +1222,13 @@ static void dn_dev_delete(struct net_device *dev)
 
 void dn_dev_down(struct net_device *dev)
 {
-	struct dn_dev *dn_db = dev->dn_ptr;
+	struct dn_dev *dn_db = rtnl_dereference(dev->dn_ptr);
 	struct dn_ifaddr *ifa;
 
 	if (dn_db == NULL)
 		return;
 
-	while((ifa = dn_db->ifa_list) != NULL) {
+	while ((ifa = rtnl_dereference(dn_db->ifa_list)) != NULL) {
 		dn_dev_del_ifa(dn_db, &dn_db->ifa_list, 0);
 		dn_dev_free_ifa(ifa);
 	}
@@ -1270,7 +1288,7 @@ static inline int is_dn_dev(struct net_device *dev)
 }
 
 static void *dn_dev_seq_start(struct seq_file *seq, loff_t *pos)
-	__acquires(rcu)
+	__acquires(RCU)
 {
 	int i;
 	struct net_device *dev;
@@ -1313,7 +1331,7 @@ static void *dn_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 }
 
 static void dn_dev_seq_stop(struct seq_file *seq, void *v)
-	__releases(rcu)
+	__releases(RCU)
 {
 	rcu_read_unlock();
 }
@@ -1340,7 +1358,7 @@ static int dn_dev_seq_show(struct seq_file *seq, void *v)
 		struct net_device *dev = v;
 		char peer_buf[DN_ASCBUF_LEN];
 		char router_buf[DN_ASCBUF_LEN];
-		struct dn_dev *dn_db = dev->dn_ptr;
+		struct dn_dev *dn_db = rcu_dereference(dev->dn_ptr);
 
 		seq_printf(seq, "%-8s %1s     %04u %04u   %04lu %04lu"
 				"   %04hu    %03d %02x    %-10s %-7s %-7s\n",
diff --git a/net/decnet/dn_fib.c b/net/decnet/dn_fib.c
index 4ab96c1..0ef0a81 100644
--- a/net/decnet/dn_fib.c
+++ b/net/decnet/dn_fib.c
@@ -610,10 +610,12 @@ static void dn_fib_del_ifaddr(struct dn_ifaddr *ifa)
 	/* Scan device list */
 	rcu_read_lock();
 	for_each_netdev_rcu(&init_net, dev) {
-		dn_db = dev->dn_ptr;
+		dn_db = rcu_dereference(dev->dn_ptr);
 		if (dn_db == NULL)
 			continue;
-		for(ifa2 = dn_db->ifa_list; ifa2; ifa2 = ifa2->ifa_next) {
+		for (ifa2 = rcu_dereference(dn_db->ifa_list);
+		     ifa2 != NULL;
+		     ifa2 = rcu_dereference(ifa2->ifa_next)) {
 			if (ifa2->ifa_local == ifa->ifa_local) {
 				found_it = 1;
 				break;
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c
index a085dbc..602dade 100644
--- a/net/decnet/dn_neigh.c
+++ b/net/decnet/dn_neigh.c
@@ -391,7 +391,7 @@ int dn_neigh_router_hello(struct sk_buff *skb)
 		write_lock(&neigh->lock);
 
 		neigh->used = jiffies;
-		dn_db = (struct dn_dev *)neigh->dev->dn_ptr;
+		dn_db = rcu_dereference(neigh->dev->dn_ptr);
 
 		if (!(neigh->nud_state & NUD_PERMANENT)) {
 			neigh->updated = jiffies;
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index df0f3e5..94a9eb1 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -93,7 +93,7 @@
 
 struct dn_rt_hash_bucket
 {
-	struct dn_route *chain;
+	struct dn_route __rcu *chain;
 	spinlock_t lock;
 };
 
@@ -157,15 +157,17 @@ static inline void dnrt_drop(struct dn_route *rt)
 static void dn_dst_check_expire(unsigned long dummy)
 {
 	int i;
-	struct dn_route *rt, **rtp;
+	struct dn_route *rt;
+	struct dn_route __rcu **rtp;
 	unsigned long now = jiffies;
 	unsigned long expire = 120 * HZ;
 
-	for(i = 0; i <= dn_rt_hash_mask; i++) {
+	for (i = 0; i <= dn_rt_hash_mask; i++) {
 		rtp = &dn_rt_hash_table[i].chain;
 
 		spin_lock(&dn_rt_hash_table[i].lock);
-		while((rt=*rtp) != NULL) {
+		while ((rt = rcu_dereference_protected(*rtp,
+						lockdep_is_held(&dn_rt_hash_table[i].lock))) != NULL) {
 			if (atomic_read(&rt->dst.__refcnt) ||
 					(now - rt->dst.lastuse) < expire) {
 				rtp = &rt->dst.dn_next;
@@ -186,17 +188,19 @@ static void dn_dst_check_expire(unsigned long dummy)
 
 static int dn_dst_gc(struct dst_ops *ops)
 {
-	struct dn_route *rt, **rtp;
+	struct dn_route *rt;
+	struct dn_route __rcu **rtp;
 	int i;
 	unsigned long now = jiffies;
 	unsigned long expire = 10 * HZ;
 
-	for(i = 0; i <= dn_rt_hash_mask; i++) {
+	for (i = 0; i <= dn_rt_hash_mask; i++) {
 
 		spin_lock_bh(&dn_rt_hash_table[i].lock);
 		rtp = &dn_rt_hash_table[i].chain;
 
-		while((rt=*rtp) != NULL) {
+		while ((rt = rcu_dereference_protected(*rtp,
+						lockdep_is_held(&dn_rt_hash_table[i].lock))) != NULL) {
 			if (atomic_read(&rt->dst.__refcnt) ||
 					(now - rt->dst.lastuse) < expire) {
 				rtp = &rt->dst.dn_next;
@@ -227,7 +231,7 @@ static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu)
 {
 	u32 min_mtu = 230;
 	struct dn_dev *dn = dst->neighbour ?
-			    (struct dn_dev *)dst->neighbour->dev->dn_ptr : NULL;
+			    rcu_dereference_raw(dst->neighbour->dev->dn_ptr) : NULL;
 
 	if (dn && dn->use_long == 0)
 		min_mtu -= 6;
@@ -277,13 +281,15 @@ static inline int compare_keys(struct flowi *fl1, struct flowi *fl2)
 
 static int dn_insert_route(struct dn_route *rt, unsigned hash, struct dn_route **rp)
 {
-	struct dn_route *rth, **rthp;
+	struct dn_route *rth;
+	struct dn_route __rcu **rthp;
 	unsigned long now = jiffies;
 
 	rthp = &dn_rt_hash_table[hash].chain;
 
 	spin_lock_bh(&dn_rt_hash_table[hash].lock);
-	while((rth = *rthp) != NULL) {
+	while ((rth = rcu_dereference_protected(*rthp,
+						lockdep_is_held(&dn_rt_hash_table[hash].lock))) != NULL) {
 		if (compare_keys(&rth->fl, &rt->fl)) {
 			/* Put it first */
 			*rthp = rth->dst.dn_next;
@@ -315,15 +321,15 @@ static void dn_run_flush(unsigned long dummy)
 	int i;
 	struct dn_route *rt, *next;
 
-	for(i = 0; i < dn_rt_hash_mask; i++) {
+	for (i = 0; i < dn_rt_hash_mask; i++) {
 		spin_lock_bh(&dn_rt_hash_table[i].lock);
 
-		if ((rt = xchg(&dn_rt_hash_table[i].chain, NULL)) == NULL)
+		if ((rt = xchg((struct dn_route **)&dn_rt_hash_table[i].chain, NULL)) == NULL)
 			goto nothing_to_declare;
 
-		for(; rt; rt=next) {
-			next = rt->dst.dn_next;
-			rt->dst.dn_next = NULL;
+		for(; rt; rt = next) {
+			next = rcu_dereference_raw(rt->dst.dn_next);
+			RCU_INIT_POINTER(rt->dst.dn_next, NULL);
 			dst_free((struct dst_entry *)rt);
 		}
 
@@ -458,15 +464,16 @@ static int dn_return_long(struct sk_buff *skb)
  */
 static int dn_route_rx_packet(struct sk_buff *skb)
 {
-	struct dn_skb_cb *cb = DN_SKB_CB(skb);
+	struct dn_skb_cb *cb;
 	int err;
 
 	if ((err = dn_route_input(skb)) == 0)
 		return dst_input(skb);
 
+	cb = DN_SKB_CB(skb);
 	if (decnet_debug_level & 4) {
 		char *devname = skb->dev ? skb->dev->name : "???";
-		struct dn_skb_cb *cb = DN_SKB_CB(skb);
+
 		printk(KERN_DEBUG
 			"DECnet: dn_route_rx_packet: rt_flags=0x%02x dev=%s len=%d src=0x%04hx dst=0x%04hx err=%d type=%d\n",
 			(int)cb->rt_flags, devname, skb->len,
@@ -573,7 +580,7 @@ int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type
 	struct dn_skb_cb *cb;
 	unsigned char flags = 0;
 	__u16 len = le16_to_cpu(*(__le16 *)skb->data);
-	struct dn_dev *dn = (struct dn_dev *)dev->dn_ptr;
+	struct dn_dev *dn = rcu_dereference(dev->dn_ptr);
 	unsigned char padlen = 0;
 
 	if (!net_eq(dev_net(dev), &init_net))
@@ -728,7 +735,7 @@ static int dn_forward(struct sk_buff *skb)
 {
 	struct dn_skb_cb *cb = DN_SKB_CB(skb);
 	struct dst_entry *dst = skb_dst(skb);
-	struct dn_dev *dn_db = dst->dev->dn_ptr;
+	struct dn_dev *dn_db = rcu_dereference(dst->dev->dn_ptr);
 	struct dn_route *rt;
 	struct neighbour *neigh = dst->neighbour;
 	int header_len;
@@ -835,13 +842,16 @@ static inline int dn_match_addr(__le16 addr1, __le16 addr2)
 static __le16 dnet_select_source(const struct net_device *dev, __le16 daddr, int scope)
 {
 	__le16 saddr = 0;
-	struct dn_dev *dn_db = dev->dn_ptr;
+	struct dn_dev *dn_db;
 	struct dn_ifaddr *ifa;
 	int best_match = 0;
 	int ret;
 
-	read_lock(&dev_base_lock);
-	for(ifa = dn_db->ifa_list; ifa; ifa = ifa->ifa_next) {
+	rcu_read_lock();
+	dn_db = rcu_dereference(dev->dn_ptr);
+	for (ifa = rcu_dereference(dn_db->ifa_list);
+	     ifa != NULL;
+	     ifa = rcu_dereference(ifa->ifa_next)) {
 		if (ifa->ifa_scope > scope)
 			continue;
 		if (!daddr) {
@@ -854,7 +864,7 @@ static __le16 dnet_select_source(const struct net_device *dev, __le16 daddr, int
 		if (best_match == 0)
 			saddr = ifa->ifa_local;
 	}
-	read_unlock(&dev_base_lock);
+	rcu_read_unlock();
 
 	return saddr;
 }
@@ -1020,7 +1030,7 @@ source_ok:
 		err = -ENODEV;
 		if (dev_out == NULL)
 			goto out;
-		dn_db = dev_out->dn_ptr;
+		dn_db = rcu_dereference_raw(dev_out->dn_ptr);
 		/* Possible improvement - check all devices for local addr */
 		if (dn_dev_islocal(dev_out, fl.fld_dst)) {
 			dev_put(dev_out);
@@ -1233,7 +1243,7 @@ static int dn_route_input_slow(struct sk_buff *skb)
 
 	dev_hold(in_dev);
 
-	if ((dn_db = in_dev->dn_ptr) == NULL)
+	if ((dn_db = rcu_dereference(in_dev->dn_ptr)) == NULL)
 		goto out;
 
 	/* Zero source addresses are not allowed */
@@ -1677,15 +1687,15 @@ static struct dn_route *dn_rt_cache_get_next(struct seq_file *seq, struct dn_rou
 {
 	struct dn_rt_cache_iter_state *s = seq->private;
 
-	rt = rt->dst.dn_next;
-	while(!rt) {
+	rt = rcu_dereference_bh(rt->dst.dn_next);
+	while (!rt) {
 		rcu_read_unlock_bh();
 		if (--s->bucket < 0)
 			break;
 		rcu_read_lock_bh();
-		rt = dn_rt_hash_table[s->bucket].chain;
+		rt = rcu_dereference_bh(dn_rt_hash_table[s->bucket].chain);
 	}
-	return rcu_dereference_bh(rt);
+	return rt;
 }
 
 static void *dn_rt_cache_seq_start(struct seq_file *seq, loff_t *pos)



^ permalink raw reply related

* Re: [PATCH net-next-2.6 v2] can: Topcliff: PCH_CAN driver: Fix build warnings
From: Marc Kleine-Budde @ 2010-10-29 12:57 UTC (permalink / raw)
  To: Tomoya
  Cc: andrew.chih.howe.khor-ral2JQCrhuEAvxtiuMwx3w, Masayuki Ohtake,
	Samuel Ortiz, margie.foster-ral2JQCrhuEAvxtiuMwx3w,
	netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	yong.y.wang-ral2JQCrhuEAvxtiuMwx3w,
	kok.howg.ewe-ral2JQCrhuEAvxtiuMwx3w, Wolfgang Grandegger,
	joel.clark-ral2JQCrhuEAvxtiuMwx3w, David S. Miller,
	Christian Pellegrin, qi.wang-ral2JQCrhuEAvxtiuMwx3w
In-Reply-To: <4CCAA3D4.8070408-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>


[-- Attachment #1.1: Type: text/plain, Size: 4262 bytes --]

Hello,

On 10/29/2010 12:37 PM, Tomoya wrote:
>>>> what does this loop do? why is it nessecarry? I don't like delay loops
>>>>   in the hot path of a driver.
>>> This loop is for waiting for all tx Message Object completion.
>>> This is Topcliff CAN HW specification.
>> What do you mean with "tx Message Object completion"? Is TX done not
>> signaled via interrupt?
> Yes Tx done is signaled via interrupt.
> On the other hand, register "CANTREQx" also shows the status of Message Object.
> Reading the register, CAN driver can know the Message Object is empty or not.
> In case of this processing, using this register is better, I think.
> 
>> Please explain why you need to wait multiples of
>>> 500us here in the hot TX path.
> You are right. The value "500us" was too big.
> According to Topcliff document, it takes 3~6 cycles for transferring between
> register and Message Object RAM.
> Since 50MHz is, 1cycle=0.02usec, 6cycle=0.12. May be true.
> I will modify 500usec to 1usec.
> 
>>>>> 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.
>>>> Me too. I already ask in my previous mail how long that functions
>>>> usually blocks.
>>> When accessing read/write from/to Message RAM,
>>> Since it takes much time for transferring between Register and Message RAM,
>> Much time means how many mirco-seconds?
> ditto
> 
>>> SW must check busy flag of CAN register.
>>> This is a Topcliff HW specification.
>> Maybe the busy check could also be done *before* the Message RAM is
>> accessed to avoid (or minimize) waiting.
> Yes, *before* is right.
> If there is *after* processing, this is a bug.
> Can you see anyway ?

Sorry I don't understand what you mean.

>> Can you give us a pointer into intel's documentation?
> You have already had Intel's data sheet(Topcliff/Atom E6xx series), right ?
> What's document for ?

You probably know the datasheet, but I don't, although I've printed
chapter 13 from the Intel Controller Hub EG20T datasheet, but it's 50+
pages. If the hardware needs the busy waiting in the hot tx path a
pointer to the respective section in the manual is a good idea. Just
something like:

    According to the Datasheet $REFERENCE section $SECTION_NUMBER we
    need to wait until the $FOO operation finished.

>>> 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.

> Sorry, I misunderstood the spec of Topcliff CAN endianess.
> I have understood endianess conversion is not necessary.
> (CAN data is set as Big-Endian in Topcliff CAN register)

>> You have to change the definition of the regs struct a bit:
>>> 	u32 if1_mcont;
>>> 	u32 if1_data[4];
>>> 	u32 reserve2;
> Uh, I can't find this. Where is this ?

Here's a patch to illustrate what I meant:

diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c
index 55ec324..5ee7589 100644
--- a/drivers/net/can/pch_can.c
+++ b/drivers/net/can/pch_can.c
@@ -150,10 +150,7 @@ struct pch_can_regs {
        u32 if1_id1;
        u32 if1_id2;
        u32 if1_mcont;
-       u32 if1_dataa1;
-       u32 if1_dataa2;
-       u32 if1_datab1;
-       u32 if1_datab2;
+       u32 if1_data[4];
        u32 reserve2;
        u32 reserve3[12];
        u32 if2_creq;

>> BTW: Where can I get this Intel Hardware to improve and test the driver?
> We don't know, please contact to Intel,
> Topcliff is formally called "Atom E6xx series" http://edc.intel.com/Platforms/Atom-E6xx/

> I have completed modifying for your comments excepting above.
> Receiving many comments, your indication may be dropped. If you find, please indicate again?.
> For your confirming my modification, I show current whole of CAN driver.

The driver has already been merged. Please send incremental patches
against david's net-2.6 branch.

Cheers, Marc

-- 
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 related

* [PATCH] bonding: remove dev_base_lock use
From: Eric Dumazet @ 2010-10-29 11:52 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Jay Vosburgh

bond_info_seq_start() uses a read_lock(&dev_base_lock) to make sure
device doesn’t disappear. Same goal can be achieved using RCU.

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
 drivers/net/bonding/bond_main.c |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index bdb68a6..5188448 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -3209,7 +3209,7 @@ out:
 #ifdef CONFIG_PROC_FS
 
 static void *bond_info_seq_start(struct seq_file *seq, loff_t *pos)
-	__acquires(&dev_base_lock)
+	__acquires(RCU)
 	__acquires(&bond->lock)
 {
 	struct bonding *bond = seq->private;
@@ -3218,7 +3218,7 @@ static void *bond_info_seq_start(struct seq_file *seq, loff_t *pos)
 	int i;
 
 	/* make sure the bond won't be taken away */
-	read_lock(&dev_base_lock);
+	rcu_read_lock();
 	read_lock(&bond->lock);
 
 	if (*pos == 0)
@@ -3248,12 +3248,12 @@ static void *bond_info_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 
 static void bond_info_seq_stop(struct seq_file *seq, void *v)
 	__releases(&bond->lock)
-	__releases(&dev_base_lock)
+	__releases(RCU)
 {
 	struct bonding *bond = seq->private;
 
 	read_unlock(&bond->lock);
-	read_unlock(&dev_base_lock);
+	rcu_read_unlock();
 }
 
 static void bond_info_show_master(struct seq_file *seq)



^ permalink raw reply related


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