Netdev List
 help / color / mirror / Atom feed
* Re: [Security] TIPC security issues
From: Linus Torvalds @ 2010-10-25  3:42 UTC (permalink / raw)
  To: David Miller; +Cc: drosenberg, jon.maloy, allan.stephens, netdev, security
In-Reply-To: <20101024.191415.226787411.davem@davemloft.net>

On Sun, Oct 24, 2010 at 7:14 PM, David Miller <davem@davemloft.net> wrote:
>
> Maybe the filesystem paths are this way, but the bulk of the socket
> paths properly use size_t when touching anything even related
> to an I/O length.

Umm. "Bulk" is not "all".

Which is the whole point. Most filesystems have no trouble either. But
when a mistake is a security issue, that's not enough.

> I know that TCP can do a >= 4GB write just fine right now.

Again - totally irrelevant. Plus anybody who relies on doing 4GB
writes in one go would be broken _anyway_.

In other words, what you argue for has zero upsides, and it has
downsides. As shown by the fact that TIPC was buggy.

> In fact if you look I recently removed the last obstacle to this based
> upon a bug report from a user trying to do a 4GB write (which ended up
> getting truncated to zero):

.. and if you looked at my suggested patch, you would have seen that
it would have avoided that, and still worked fine (exactly because it
doesn't truncate anything).

David - the issue is _security_. The way to fix security problems is
not to say "most things handle this correctly". The way to avoid them
is to have several layers of handling things correctly, so that even
when one turns out to be broken, the others still protect it.

                        Linus

^ permalink raw reply

* linux-next: build failure after merge of the final tree (net-current tree related)
From: Stephen Rothwell @ 2010-10-25  3:19 UTC (permalink / raw)
  To: David Miller, netdev
  Cc: linux-next, linux-kernel, stephen hemminger, James Chapman

Hi all,

After merging the final tree, today's linux-next build (powerpc
allyesconfig) failed like this:

net/l2tp/l2tp_core.c:1228: error: __ksymtab_l2tp_tunnel_closeall causes a section type conflict
net/l2tp/l2tp_core.c:1228: error: __ksymtab_l2tp_tunnel_closeall causes a section type conflict
net/l2tp/l2tp_core.c:1006: error: __ksymtab_l2tp_xmit_core causes a section type conflict
net/l2tp/l2tp_core.c:1006: error: __ksymtab_l2tp_xmit_core causes a section type conflict
net/l2tp/l2tp_core.c:847: error: __ksymtab_l2tp_udp_recv_core causes a section type conflict
net/l2tp/l2tp_core.c:847: error: __ksymtab_l2tp_udp_recv_core causes a section type conflict

Caused by commit fc130840d75d42c5a360fd1d8b72489eec09cad3 ("l2tp: make
local function static") since these functions are now static (and should
not be exported).  I wish doing that caused a build failure on other
architectures ...

I applied the following patch:

From: Stephen Rothwell <sfr@canb.auug.org.au>
Date: Mon, 25 Oct 2010 14:16:53 +1100
Subject: [PATCH] l2tp: static functions should not be exported

Causes these build failures on PowerPC:

net/l2tp/l2tp_core.c:1228: error: __ksymtab_l2tp_tunnel_closeall causes a section type conflict
net/l2tp/l2tp_core.c:1228: error: __ksymtab_l2tp_tunnel_closeall causes a section type conflict
net/l2tp/l2tp_core.c:1006: error: __ksymtab_l2tp_xmit_core causes a section type conflict
net/l2tp/l2tp_core.c:1006: error: __ksymtab_l2tp_xmit_core causes a section type conflict
net/l2tp/l2tp_core.c:847: error: __ksymtab_l2tp_udp_recv_core causes a section type conflict
net/l2tp/l2tp_core.c:847: error: __ksymtab_l2tp_udp_recv_core causes a section type conflict

Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
 net/l2tp/l2tp_core.c |    3 ---
 1 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index 5fb4803..c64ce0a 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -844,7 +844,6 @@ error:
 
 	return 1;
 }
-EXPORT_SYMBOL_GPL(l2tp_udp_recv_core);
 
 /* UDP encapsulation receive handler. See net/ipv4/udp.c.
  * Return codes:
@@ -1003,7 +1002,6 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb,
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(l2tp_xmit_core);
 
 /* Automatically called when the skb is freed.
  */
@@ -1225,7 +1223,6 @@ again:
 	}
 	write_unlock_bh(&tunnel->hlist_lock);
 }
-EXPORT_SYMBOL_GPL(l2tp_tunnel_closeall);
 
 /* Really kill the tunnel.
  * Come here only when all sessions have been cleared from the tunnel.
-- 
1.7.2.3

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/

^ permalink raw reply related

* [PATCH net-next-2.6 v2] can: Topcliff: PCH_CAN driver: Fix build warnings
From: Tomoya @ 2010-10-25  2:32 UTC (permalink / raw)
  To: Wolfgang Grandegger, David S. Miller, Wolfram Sang,
	Christian Pellegrin, Barry Song
  Cc: qi.wang, yong.y.wang, andrew.chih.howe.khor, joel.clark,
	kok.howg.ewe, morinaga526, Masayuki Ohtake, margie.foster

Hi David,

From: Tomoya MORINAGA <tomoya-linux@dsn.okisemi.com>
 - Fix build warnings when PM_CONFIG is disabled.
 - Modify Copyright "Co" to "CO".

Reported-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Tomoya MORINAGA <tomoya-linux@dsn.okisemi.com>
---
 drivers/net/can/pch_can.c |  208
++++++++++++++++++++++----------------------
 1 files changed, 104 insertions(+), 104 deletions(-)

diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c
index 55ec324..2889e11 100755
--- a/drivers/net/can/pch_can.c
+++ b/drivers/net/can/pch_can.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 1999 - 2010 Intel Corporation.
- * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ * 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
@@ -255,21 +255,21 @@ static void pch_can_set_optmode(struct
pch_can_priv *priv)
 	iowrite32(reg_val, &priv->regs->opt);
 }

-static void pch_can_set_int_custom(struct pch_can_priv *priv)
+static void pch_can_check_if_busy(u32 __iomem *creq_addr, u32 num)
 {
-	/* 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));
-}
+	u32 counter = COUNTER_LIMIT;
+	u32 ifx_creq;

-/* This function retrieves interrupt enabled for the CAN device. */
-static void pch_can_get_int_enables(struct pch_can_priv *priv, u32
*enables)
-{
-	/* Obtaining the status of IE, SIE and EIE interrupt bits. */
-	*enables = ((ioread32(&priv->regs->cont) & CAN_CTRL_IE_SIE_EIE) >> 1);
+	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,
@@ -298,23 +298,6 @@ static void pch_can_set_int_enables(struct
pch_can_priv *priv,
 	}
 }

-static void pch_can_check_if_busy(u32 __iomem *creq_addr, u32 num)
-{
-	u32 counter = COUNTER_LIMIT;
-	u32 ifx_creq;
-
-	iowrite32(num, creq_addr);
-	while (counter) {
-		ifx_creq = ioread32(creq_addr) & CAN_IF_CREQ_BUSY;
-		if (!ifx_creq)
-			break;
-		counter--;
-		udelay(1);
-	}
-	if (!counter)
-		pr_err("%s:IF1 BUSY Flag is set forever.\n", __func__);
-}
-
 static void pch_can_set_rx_enable(struct pch_can_priv *priv, u32 buff_num,
 				  u32 set)
 {
@@ -417,82 +400,11 @@ static void pch_can_tx_disable_all(struct
pch_can_priv *priv)
 	}
 }

-static void pch_can_get_rx_enable(struct pch_can_priv *priv, u32 buff_num,
-				 u32 *enable)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->msgif_reg_lock, flags);
-	iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if1_cmask);
-	pch_can_check_if_busy(&priv->regs->if1_creq, buff_num);
-
-	if (((ioread32(&priv->regs->if1_id2)) & CAN_ID_MSGVAL) &&
-			((ioread32(&priv->regs->if1_mcont)) &
-			CAN_IF_MCONT_RXIE))
-		*enable = ENABLE;
-	else
-		*enable = DISABLE;
-	spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
-}
-
-static void pch_can_get_tx_enable(struct pch_can_priv *priv, u32 buff_num,
-				 u32 *enable)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->msgif_reg_lock, flags);
-	iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if2_cmask);
-	pch_can_check_if_busy(&priv->regs->if2_creq, buff_num);
-
-	if (((ioread32(&priv->regs->if2_id2)) & CAN_ID_MSGVAL) &&
-			((ioread32(&priv->regs->if2_mcont)) &
-			CAN_IF_MCONT_TXIE)) {
-		*enable = ENABLE;
-	} else {
-		*enable = DISABLE;
-	}
-	spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
-}
-
 static int pch_can_int_pending(struct pch_can_priv *priv)
 {
 	return ioread32(&priv->regs->intr) & 0xffff;
 }

-static void pch_can_set_rx_buffer_link(struct pch_can_priv *priv,
-				       u32 buffer_num, u32 set)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->msgif_reg_lock, flags);
-	iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if1_cmask);
-	pch_can_check_if_busy(&priv->regs->if1_creq, buffer_num);
-	iowrite32(CAN_CMASK_RDWR | CAN_CMASK_CTRL, &priv->regs->if1_cmask);
-	if (set == ENABLE)
-		pch_can_bit_clear(&priv->regs->if1_mcont, CAN_IF_MCONT_EOB);
-	else
-		pch_can_bit_set(&priv->regs->if1_mcont, CAN_IF_MCONT_EOB);
-
-	pch_can_check_if_busy(&priv->regs->if1_creq, buffer_num);
-	spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
-}
-
-static void pch_can_get_rx_buffer_link(struct pch_can_priv *priv,
-				       u32 buffer_num, u32 *link)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->msgif_reg_lock, flags);
-	iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if1_cmask);
-	pch_can_check_if_busy(&priv->regs->if1_creq, buffer_num);
-
-	if (ioread32(&priv->regs->if1_mcont) & CAN_IF_MCONT_EOB)
-		*link = DISABLE;
-	else
-		*link = ENABLE;
-	spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
-}
-
 static void pch_can_clear_buffers(struct pch_can_priv *priv)
 {
 	int i;
@@ -1121,13 +1033,13 @@ static netdev_tx_t pch_xmit(struct sk_buff *skb,
struct net_device *ndev)
 	if (can_dropped_invalid_skb(ndev, skb))
 		return NETDEV_TX_OK;

-	if (priv->tx_obj == (PCH_OBJ_NUM + 1)) { /* Point tail Obj */
+	if (priv->tx_obj == (PCH_OBJ_NUM + 1)) { /* Point tail Obj + 1 */
 		while (pch_get_msg_obj_sts(ndev, (((1 << PCH_TX_OBJ_NUM)-1) <<
 					   PCH_RX_OBJ_NUM)))
 			udelay(500);

 		priv->tx_obj = PCH_RX_OBJ_NUM + 1; /* Point head of Tx Obj ID */
-		tx_buffer_avail = priv->tx_obj; /* Point Tail of Tx Obj */
+		tx_buffer_avail = priv->tx_obj;
 	} else {
 		tx_buffer_avail = priv->tx_obj;
 	}
@@ -1212,6 +1124,94 @@ static void __devexit pch_can_remove(struct
pci_dev *pdev)
 }

 #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 void pch_can_get_int_enables(struct pch_can_priv *priv, u32
*enables)
+{
+	/* Obtaining the status of IE, SIE and EIE interrupt bits. */
+	*enables = ((ioread32(&priv->regs->cont) & CAN_CTRL_IE_SIE_EIE) >> 1);
+}
+
+static void pch_can_get_rx_enable(struct pch_can_priv *priv, u32 buff_num,
+				 u32 *enable)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->msgif_reg_lock, flags);
+	iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if1_cmask);
+	pch_can_check_if_busy(&priv->regs->if1_creq, buff_num);
+
+	if (((ioread32(&priv->regs->if1_id2)) & CAN_ID_MSGVAL) &&
+			((ioread32(&priv->regs->if1_mcont)) &
+			CAN_IF_MCONT_RXIE))
+		*enable = ENABLE;
+	else
+		*enable = DISABLE;
+	spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
+}
+
+static void pch_can_get_tx_enable(struct pch_can_priv *priv, u32 buff_num,
+				 u32 *enable)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->msgif_reg_lock, flags);
+	iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if2_cmask);
+	pch_can_check_if_busy(&priv->regs->if2_creq, buff_num);
+
+	if (((ioread32(&priv->regs->if2_id2)) & CAN_ID_MSGVAL) &&
+			((ioread32(&priv->regs->if2_mcont)) &
+			CAN_IF_MCONT_TXIE)) {
+		*enable = ENABLE;
+	} else {
+		*enable = DISABLE;
+	}
+	spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
+}
+
+static void pch_can_set_rx_buffer_link(struct pch_can_priv *priv,
+				       u32 buffer_num, u32 set)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->msgif_reg_lock, flags);
+	iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if1_cmask);
+	pch_can_check_if_busy(&priv->regs->if1_creq, buffer_num);
+	iowrite32(CAN_CMASK_RDWR | CAN_CMASK_CTRL, &priv->regs->if1_cmask);
+	if (set == ENABLE)
+		pch_can_bit_clear(&priv->regs->if1_mcont, CAN_IF_MCONT_EOB);
+	else
+		pch_can_bit_set(&priv->regs->if1_mcont, CAN_IF_MCONT_EOB);
+
+	pch_can_check_if_busy(&priv->regs->if1_creq, buffer_num);
+	spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
+}
+
+static void pch_can_get_rx_buffer_link(struct pch_can_priv *priv,
+				       u32 buffer_num, u32 *link)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->msgif_reg_lock, flags);
+	iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if1_cmask);
+	pch_can_check_if_busy(&priv->regs->if1_creq, buffer_num);
+
+	if (ioread32(&priv->regs->if1_mcont) & CAN_IF_MCONT_EOB)
+		*link = DISABLE;
+	else
+		*link = ENABLE;
+	spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
+}
+
 static int pch_can_suspend(struct pci_dev *pdev, pm_message_t state)
 {
 	int i;			/* Counter variable. */
-- 
1.6.0.6


^ permalink raw reply related

* Re: [Security] TIPC security issues
From: David Miller @ 2010-10-25  2:14 UTC (permalink / raw)
  To: torvalds; +Cc: drosenberg, jon.maloy, allan.stephens, netdev, security
In-Reply-To: <AANLkTi=V93A660+YS8C2TvC13kGUcJpFgjPHUvONd_WW@mail.gmail.com>

From: Linus Torvalds <torvalds@linux-foundation.org>
Date: Thu, 21 Oct 2010 17:31:12 -0700

> We already (long ago) decided that POSIX.1 compatibility be damned,
> and that reading and writing more than 2GB in a single system call is
> bogus: so normal write calls will actually limit size_t arguments to
> MAX_INT, exactly so that various filesystems don't have to worry about
> overflow and can keep length arguments in an "int".

Maybe the filesystem paths are this way, but the bulk of the socket
paths properly use size_t when touching anything even related
to an I/O length.

I know that TCP can do a >= 4GB write just fine right now.

In fact if you look I recently removed the last obstacle to this based
upon a bug report from a user trying to do a 4GB write (which ended up
getting truncated to zero):

commit 01db403cf99f739f86903314a489fb420e0e254f
Author: David S. Miller <davem@davemloft.net>
Date:   Mon Sep 27 20:24:54 2010 -0700

    tcp: Fix >4GB writes on 64-bit.
    
    Fixes kernel bugzilla #16603
    
    tcp_sendmsg() truncates iov_len to an 'int' which a 4GB write to write
    zero bytes, for example.
    
    There is also the problem higher up of how verify_iovec() works.  It
    wants to prevent the total length from looking like an error return
    value.
    
    However it does this using 'int', but syscalls return 'long' (and
    thus signed 64-bit on 64-bit machines).  So it could trigger
    false-positives on 64-bit as written.  So fix it to use 'long'.
    
    Reported-by: Olaf Bonorden <bono@onlinehome.de>
    Reported-by: Daniel Büse <dbuese@gmx.de>
    Reported-by: Andrew Morton <akpm@linux-foundation.org>
    Signed-off-by: David S. Miller <davem@davemloft.net>

Anyways, my point is that not only is the socket layer entirely ready
for this, it is also the case that while 2GB may seem big today in
most places, some day it might not be.  :-)

^ permalink raw reply

* Re: [PATCH net-next-2.6 v2] can: Topcliff: Update PCH_CAN driver to 2.6.36
From: David Miller @ 2010-10-25  2:08 UTC (permalink / raw)
  To: tomoya-linux-ECg8zkTtlr0C6LszWs/t0g
  Cc: andrew.chih.howe.khor-ral2JQCrhuEAvxtiuMwx3w,
	masa-korg-ECg8zkTtlr0C6LszWs/t0g, sameo-VuQAYsv1563Yd54FQh9/CA,
	margie.foster-ral2JQCrhuEAvxtiuMwx3w,
	netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	kok.howg.ewe-ral2JQCrhuEAvxtiuMwx3w, wg-5Yr1BZd7O62+XT7JhA+gdA,
	morinaga526-ECg8zkTtlr0C6LszWs/t0g,
	joel.clark-ral2JQCrhuEAvxtiuMwx3w,
	yong.y.wang-ral2JQCrhuEAvxtiuMwx3w, chripell-VaTbYqLCNhc,
	qi.wang-ral2JQCrhuEAvxtiuMwx3w
In-Reply-To: <4CC4E32F.5000608-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>

From: Tomoya <tomoya-linux-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>
Date: Mon, 25 Oct 2010 10:53:51 +0900

> Hi David,
> 
> I have modified for your indications.
>  - Warning issue when "CONFIG_PM" is disabled.

I said to send me a relative patch to your previous one.

I already added the driver to the tree, so sending me a complete
new patch adding the driver isn't going to work.

^ permalink raw reply

* [PATCH net-next-2.6 v2] can: Topcliff: Update PCH_CAN driver to 2.6.36
From: Tomoya @ 2010-10-25  1:53 UTC (permalink / raw)
  To: Wolfgang Grandegger, David S. Miller, Wolfram Sang,
	Christian Pellegrin, Barry Song
  Cc: qi.wang, yong.y.wang, andrew.chih.howe.khor, joel.clark,
	kok.howg.ewe, morinaga526, Masayuki Ohtake, margie.foster

Hi David,

I have modified for your indications.
 - Warning issue when "CONFIG_PM" is disabled.

Thanks, Tomoya(OKI SEMICONDUCTOR CO., LTD.)
---
CAN driver of Topcliff PCH

Topcliff PCH is the platform controller hub that is going to be used in
Intel's upcoming general embedded platform. All IO peripherals in
Topcliff PCH are actually devices sitting on AMBA bus. Topcliff PCH has
CAN I/F. This driver enables CAN function.

Signed-off-by: Tomoya MORINAGA <tomoya-linux@dsn.okisemi.com>
---
 drivers/net/can/Kconfig   |    8 +
 drivers/net/can/Makefile  |    1 +
 drivers/net/can/pch_can.c | 1463
+++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 1472 insertions(+), 0 deletions(-)
 create mode 100755 drivers/net/can/pch_can.c

diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index 9d9e453..1948980 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -82,6 +82,14 @@ config CAN_FLEXCAN
 	---help---
 	  Say Y here if you want to support for Freescale FlexCAN.

+config PCH_CAN
+        tristate "PCH CAN"
+        depends on  CAN_DEV
+        ---help---
+          This driver is for PCH CAN of Topcliff which is an IOH for x86
+          embedded processor.
+          This driver can access CAN bus.
+
 source "drivers/net/can/mscan/Kconfig"

 source "drivers/net/can/sja1000/Kconfig"
diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
index 0057537..71695ce 100644
--- a/drivers/net/can/Makefile
+++ b/drivers/net/can/Makefile
@@ -17,5 +17,6 @@ obj-$(CONFIG_CAN_MCP251X)	+= mcp251x.o
 obj-$(CONFIG_CAN_BFIN)		+= bfin_can.o
 obj-$(CONFIG_CAN_JANZ_ICAN3)	+= janz-ican3.o
 obj-$(CONFIG_CAN_FLEXCAN)	+= flexcan.o
+obj-$(CONFIG_PCH_CAN)           += pch_can.o

 ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c
new file mode 100755
index 0000000..2889e11
--- /dev/null
+++ b/drivers/net/can/pch_can.c
@@ -0,0 +1,1463 @@
+/*
+ * Copyright (C) 1999 - 2010 Intel Corporation.
+ * Copyright (C) 2010 OKI SEMICONDUCTOR CO., LTD.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307, USA.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/can.h>
+#include <linux/can/dev.h>
+#include <linux/can/error.h>
+
+#define MAX_MSG_OBJ		32
+#define MSG_OBJ_RX		0 /* The receive message object flag. */
+#define MSG_OBJ_TX		1 /* The transmit message object flag. */
+
+#define ENABLE			1 /* The enable flag */
+#define DISABLE			0 /* The disable flag */
+#define CAN_CTRL_INIT		0x0001 /* The INIT bit of CANCONT register. */
+#define CAN_CTRL_IE		0x0002 /* The IE bit of CAN control register */
+#define CAN_CTRL_IE_SIE_EIE	0x000e
+#define CAN_CTRL_CCE		0x0040
+#define CAN_CTRL_OPT		0x0080 /* The OPT bit of CANCONT register. */
+#define CAN_OPT_SILENT		0x0008 /* The Silent bit of CANOPT reg. */
+#define CAN_OPT_LBACK		0x0010 /* The LoopBack bit of CANOPT reg. */
+#define CAN_CMASK_RX_TX_SET	0x00f3
+#define CAN_CMASK_RX_TX_GET	0x0073
+#define CAN_CMASK_ALL		0xff
+#define CAN_CMASK_RDWR		0x80
+#define CAN_CMASK_ARB		0x20
+#define CAN_CMASK_CTRL		0x10
+#define CAN_CMASK_MASK		0x40
+#define CAN_CMASK_NEWDAT	0x04
+#define CAN_CMASK_CLRINTPND	0x08
+
+#define CAN_IF_MCONT_NEWDAT	0x8000
+#define CAN_IF_MCONT_INTPND	0x2000
+#define CAN_IF_MCONT_UMASK	0x1000
+#define CAN_IF_MCONT_TXIE	0x0800
+#define CAN_IF_MCONT_RXIE	0x0400
+#define CAN_IF_MCONT_RMTEN	0x0200
+#define CAN_IF_MCONT_TXRQXT	0x0100
+#define CAN_IF_MCONT_EOB	0x0080
+#define CAN_IF_MCONT_DLC	0x000f
+#define CAN_IF_MCONT_MSGLOST	0x4000
+#define CAN_MASK2_MDIR_MXTD	0xc000
+#define CAN_ID2_DIR		0x2000
+#define CAN_ID_MSGVAL		0x8000
+
+#define CAN_STATUS_INT		0x8000
+#define CAN_IF_CREQ_BUSY	0x8000
+#define CAN_ID2_XTD		0x4000
+
+#define CAN_REC			0x00007f00
+#define CAN_TEC			0x000000ff
+
+#define PCH_RX_OK		0x00000010
+#define PCH_TX_OK		0x00000008
+#define PCH_BUS_OFF		0x00000080
+#define PCH_EWARN		0x00000040
+#define PCH_EPASSIV		0x00000020
+#define PCH_LEC0		0x00000001
+#define PCH_LEC1		0x00000002
+#define PCH_LEC2		0x00000004
+#define PCH_LEC_ALL		(PCH_LEC0 | PCH_LEC1 | PCH_LEC2)
+#define PCH_STUF_ERR		PCH_LEC0
+#define PCH_FORM_ERR		PCH_LEC1
+#define PCH_ACK_ERR		(PCH_LEC0 | PCH_LEC1)
+#define PCH_BIT1_ERR		PCH_LEC2
+#define PCH_BIT0_ERR		(PCH_LEC0 | PCH_LEC2)
+#define PCH_CRC_ERR		(PCH_LEC1 | PCH_LEC2)
+
+/* bit position of certain controller bits. */
+#define BIT_BITT_BRP		0
+#define BIT_BITT_SJW		6
+#define BIT_BITT_TSEG1		8
+#define BIT_BITT_TSEG2		12
+#define BIT_IF1_MCONT_RXIE	10
+#define BIT_IF2_MCONT_TXIE	11
+#define BIT_BRPE_BRPE		6
+#define BIT_ES_TXERRCNT		0
+#define BIT_ES_RXERRCNT		8
+#define MSK_BITT_BRP		0x3f
+#define MSK_BITT_SJW		0xc0
+#define MSK_BITT_TSEG1		0xf00
+#define MSK_BITT_TSEG2		0x7000
+#define MSK_BRPE_BRPE		0x3c0
+#define MSK_BRPE_GET		0x0f
+#define MSK_CTRL_IE_SIE_EIE	0x07
+#define MSK_MCONT_TXIE		0x08
+#define MSK_MCONT_RXIE		0x10
+#define PCH_CAN_NO_TX_BUFF	1
+#define COUNTER_LIMIT		10
+
+#define PCH_CAN_CLK		50000000	/* 50MHz */
+
+/* Define the number of message object.
+ * PCH CAN communications are done via Message RAM.
+ * The Message RAM consists of 32 message objects. */
+#define PCH_RX_OBJ_NUM		26  /* 1~ PCH_RX_OBJ_NUM is Rx*/
+#define PCH_TX_OBJ_NUM		6  /* PCH_RX_OBJ_NUM is RX ~ Tx*/
+#define PCH_OBJ_NUM		(PCH_TX_OBJ_NUM + PCH_RX_OBJ_NUM)
+
+#define PCH_FIFO_THRESH		16
+
+enum pch_can_mode {
+	PCH_CAN_ENABLE,
+	PCH_CAN_DISABLE,
+	PCH_CAN_ALL,
+	PCH_CAN_NONE,
+	PCH_CAN_STOP,
+	PCH_CAN_RUN
+};
+
+struct pch_can_regs {
+	u32 cont;
+	u32 stat;
+	u32 errc;
+	u32 bitt;
+	u32 intr;
+	u32 opt;
+	u32 brpe;
+	u32 reserve1;
+	u32 if1_creq;
+	u32 if1_cmask;
+	u32 if1_mask1;
+	u32 if1_mask2;
+	u32 if1_id1;
+	u32 if1_id2;
+	u32 if1_mcont;
+	u32 if1_dataa1;
+	u32 if1_dataa2;
+	u32 if1_datab1;
+	u32 if1_datab2;
+	u32 reserve2;
+	u32 reserve3[12];
+	u32 if2_creq;
+	u32 if2_cmask;
+	u32 if2_mask1;
+	u32 if2_mask2;
+	u32 if2_id1;
+	u32 if2_id2;
+	u32 if2_mcont;
+	u32 if2_dataa1;
+	u32 if2_dataa2;
+	u32 if2_datab1;
+	u32 if2_datab2;
+	u32 reserve4;
+	u32 reserve5[20];
+	u32 treq1;
+	u32 treq2;
+	u32 reserve6[2];
+	u32 reserve7[56];
+	u32 reserve8[3];
+	u32 srst;
+};
+
+struct pch_can_priv {
+	struct can_priv can;
+	unsigned int can_num;
+	struct pci_dev *dev;
+	unsigned int tx_enable[MAX_MSG_OBJ];
+	unsigned int rx_enable[MAX_MSG_OBJ];
+	unsigned int rx_link[MAX_MSG_OBJ];
+	unsigned int int_enables;
+	unsigned int int_stat;
+	struct net_device *ndev;
+	spinlock_t msgif_reg_lock; /* Message Interface Registers Access Lock*/
+	unsigned int msg_obj[MAX_MSG_OBJ];
+	struct pch_can_regs __iomem *regs;
+	struct napi_struct napi;
+	unsigned int tx_obj;	/* Point next Tx Obj index */
+	unsigned int use_msi;
+};
+
+static struct can_bittiming_const pch_can_bittiming_const = {
+	.name = KBUILD_MODNAME,
+	.tseg1_min = 1,
+	.tseg1_max = 16,
+	.tseg2_min = 1,
+	.tseg2_max = 8,
+	.sjw_max = 4,
+	.brp_min = 1,
+	.brp_max = 1024, /* 6bit + extended 4bit */
+	.brp_inc = 1,
+};
+
+static DEFINE_PCI_DEVICE_TABLE(pch_pci_tbl) = {
+	{PCI_VENDOR_ID_INTEL, 0x8818, PCI_ANY_ID, PCI_ANY_ID,},
+	{0,}
+};
+MODULE_DEVICE_TABLE(pci, pch_pci_tbl);
+
+static inline void pch_can_bit_set(u32 *addr, u32 mask)
+{
+	iowrite32(ioread32(addr) | mask, addr);
+}
+
+static inline void pch_can_bit_clear(u32 *addr, u32 mask)
+{
+	iowrite32(ioread32(addr) & ~mask, addr);
+}
+
+static void pch_can_set_run_mode(struct pch_can_priv *priv,
+				 enum pch_can_mode mode)
+{
+	switch (mode) {
+	case PCH_CAN_RUN:
+		pch_can_bit_clear(&priv->regs->cont, CAN_CTRL_INIT);
+		break;
+
+	case PCH_CAN_STOP:
+		pch_can_bit_set(&priv->regs->cont, CAN_CTRL_INIT);
+		break;
+
+	default:
+		dev_err(&priv->ndev->dev, "%s -> Invalid Mode.\n", __func__);
+		break;
+	}
+}
+
+static void pch_can_set_optmode(struct pch_can_priv *priv)
+{
+	u32 reg_val = ioread32(&priv->regs->opt);
+
+	if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
+		reg_val |= CAN_OPT_SILENT;
+
+	if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)
+		reg_val |= CAN_OPT_LBACK;
+
+	pch_can_bit_set(&priv->regs->cont, CAN_CTRL_OPT);
+	iowrite32(reg_val, &priv->regs->opt);
+}
+
+static void pch_can_check_if_busy(u32 __iomem *creq_addr, u32 num)
+{
+	u32 counter = COUNTER_LIMIT;
+	u32 ifx_creq;
+
+	iowrite32(num, creq_addr);
+	while (counter) {
+		ifx_creq = ioread32(creq_addr) & CAN_IF_CREQ_BUSY;
+		if (!ifx_creq)
+			break;
+		counter--;
+		udelay(1);
+	}
+	if (!counter)
+		pr_err("%s:IF1 BUSY Flag is set forever.\n", __func__);
+}
+
+static void pch_can_set_int_enables(struct pch_can_priv *priv,
+				    enum pch_can_mode interrupt_no)
+{
+	switch (interrupt_no) {
+	case PCH_CAN_ENABLE:
+		pch_can_bit_set(&priv->regs->cont, CAN_CTRL_IE);
+		break;
+
+	case PCH_CAN_DISABLE:
+		pch_can_bit_clear(&priv->regs->cont, CAN_CTRL_IE);
+		break;
+
+	case PCH_CAN_ALL:
+		pch_can_bit_set(&priv->regs->cont, CAN_CTRL_IE_SIE_EIE);
+		break;
+
+	case PCH_CAN_NONE:
+		pch_can_bit_clear(&priv->regs->cont, CAN_CTRL_IE_SIE_EIE);
+		break;
+
+	default:
+		dev_err(&priv->ndev->dev, "Invalid interrupt number.\n");
+		break;
+	}
+}
+
+static void pch_can_set_rx_enable(struct pch_can_priv *priv, u32 buff_num,
+				  u32 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 == ENABLE) {
+		/* Setting the MsgVal and RxIE bits */
+		pch_can_bit_set(&priv->regs->if1_mcont, CAN_IF_MCONT_RXIE);
+		pch_can_bit_set(&priv->regs->if1_id2, CAN_ID_MSGVAL);
+
+	} else if (set == DISABLE) {
+		/* Resetting the MsgVal and RxIE bits */
+		pch_can_bit_clear(&priv->regs->if1_mcont, CAN_IF_MCONT_RXIE);
+		pch_can_bit_clear(&priv->regs->if1_id2, CAN_ID_MSGVAL);
+	}
+
+	pch_can_check_if_busy(&priv->regs->if1_creq, buff_num);
+	spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
+}
+
+static void pch_can_rx_enable_all(struct pch_can_priv *priv)
+{
+	int i;
+
+	/* Traversing to obtain the object configured as receivers. */
+	for (i = 0; i < PCH_OBJ_NUM; i++) {
+		if (priv->msg_obj[i] == MSG_OBJ_RX)
+			pch_can_set_rx_enable(priv, i + 1, ENABLE);
+	}
+}
+
+static void pch_can_rx_disable_all(struct pch_can_priv *priv)
+{
+	int i;
+
+	/* Traversing to obtain the object configured as receivers. */
+	for (i = 0; i < PCH_OBJ_NUM; i++) {
+		if (priv->msg_obj[i] == MSG_OBJ_RX)
+			pch_can_set_rx_enable(priv, i + 1, DISABLE);
+	}
+}
+
+static void pch_can_set_tx_enable(struct pch_can_priv *priv, u32 buff_num,
+				 u32 set)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->msgif_reg_lock, flags);
+	/* Reading the Msg buffer from Message RAM to Interface2 registers. */
+	iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if2_cmask);
+	pch_can_check_if_busy(&priv->regs->if2_creq, buff_num);
+
+	/* Setting the IF2CMASK register for accessing the
+		MsgVal and TxIE bits */
+	iowrite32(CAN_CMASK_RDWR | CAN_CMASK_ARB | CAN_CMASK_CTRL,
+		 &priv->regs->if2_cmask);
+
+	if (set == ENABLE) {
+		/* Setting the MsgVal and TxIE bits */
+		pch_can_bit_set(&priv->regs->if2_mcont, CAN_IF_MCONT_TXIE);
+		pch_can_bit_set(&priv->regs->if2_id2, CAN_ID_MSGVAL);
+	} else if (set == DISABLE) {
+		/* Resetting the MsgVal and TxIE bits. */
+		pch_can_bit_clear(&priv->regs->if2_mcont, CAN_IF_MCONT_TXIE);
+		pch_can_bit_clear(&priv->regs->if2_id2, CAN_ID_MSGVAL);
+	}
+
+	pch_can_check_if_busy(&priv->regs->if2_creq, buff_num);
+	spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
+}
+
+static void pch_can_tx_enable_all(struct pch_can_priv *priv)
+{
+	int i;
+
+	/* Traversing to obtain the object configured as transmit object. */
+	for (i = 0; i < PCH_OBJ_NUM; i++) {
+		if (priv->msg_obj[i] == MSG_OBJ_TX)
+			pch_can_set_tx_enable(priv, i + 1, ENABLE);
+	}
+}
+
+static void pch_can_tx_disable_all(struct pch_can_priv *priv)
+{
+	int i;
+
+	/* Traversing to obtain the object configured as transmit object. */
+	for (i = 0; i < PCH_OBJ_NUM; i++) {
+		if (priv->msg_obj[i] == MSG_OBJ_TX)
+			pch_can_set_tx_enable(priv, i + 1, DISABLE);
+	}
+}
+
+static int pch_can_int_pending(struct pch_can_priv *priv)
+{
+	return ioread32(&priv->regs->intr) & 0xffff;
+}
+
+static void pch_can_clear_buffers(struct pch_can_priv *priv)
+{
+	int i;
+
+	for (i = 0; i < PCH_RX_OBJ_NUM; i++) {
+		iowrite32(CAN_CMASK_RX_TX_SET, &priv->regs->if1_cmask);
+		iowrite32(0xffff, &priv->regs->if1_mask1);
+		iowrite32(0xffff, &priv->regs->if1_mask2);
+		iowrite32(0x0, &priv->regs->if1_id1);
+		iowrite32(0x0, &priv->regs->if1_id2);
+		iowrite32(0x0, &priv->regs->if1_mcont);
+		iowrite32(0x0, &priv->regs->if1_dataa1);
+		iowrite32(0x0, &priv->regs->if1_dataa2);
+		iowrite32(0x0, &priv->regs->if1_datab1);
+		iowrite32(0x0, &priv->regs->if1_datab2);
+		iowrite32(CAN_CMASK_RDWR | CAN_CMASK_MASK |
+			  CAN_CMASK_ARB | CAN_CMASK_CTRL,
+			  &priv->regs->if1_cmask);
+		pch_can_check_if_busy(&priv->regs->if1_creq, i+1);
+	}
+
+	for (i = i;  i < PCH_OBJ_NUM; i++) {
+		iowrite32(CAN_CMASK_RX_TX_SET, &priv->regs->if2_cmask);
+		iowrite32(0xffff, &priv->regs->if2_mask1);
+		iowrite32(0xffff, &priv->regs->if2_mask2);
+		iowrite32(0x0, &priv->regs->if2_id1);
+		iowrite32(0x0, &priv->regs->if2_id2);
+		iowrite32(0x0, &priv->regs->if2_mcont);
+		iowrite32(0x0, &priv->regs->if2_dataa1);
+		iowrite32(0x0, &priv->regs->if2_dataa2);
+		iowrite32(0x0, &priv->regs->if2_datab1);
+		iowrite32(0x0, &priv->regs->if2_datab2);
+		iowrite32(CAN_CMASK_RDWR | CAN_CMASK_MASK |
+			  CAN_CMASK_ARB | CAN_CMASK_CTRL,
+			  &priv->regs->if2_cmask);
+		pch_can_check_if_busy(&priv->regs->if2_creq, i+1);
+	}
+}
+
+static void pch_can_config_rx_tx_buffers(struct pch_can_priv *priv)
+{
+	int i;
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->msgif_reg_lock, flags);
+
+	for (i = 0; i < PCH_OBJ_NUM; i++) {
+		if (priv->msg_obj[i] == MSG_OBJ_RX) {
+			iowrite32(CAN_CMASK_RX_TX_GET,
+				&priv->regs->if1_cmask);
+			pch_can_check_if_busy(&priv->regs->if1_creq, i+1);
+
+			iowrite32(0x0, &priv->regs->if1_id1);
+			iowrite32(0x0, &priv->regs->if1_id2);
+
+			pch_can_bit_set(&priv->regs->if1_mcont,
+					CAN_IF_MCONT_UMASK);
+
+			/* Set FIFO mode set to 0 except last Rx Obj*/
+			pch_can_bit_clear(&priv->regs->if1_mcont,
+					  CAN_IF_MCONT_EOB);
+			/* In case FIFO mode, Last EoB of Rx Obj must be 1 */
+			if (i == (PCH_RX_OBJ_NUM - 1))
+				pch_can_bit_set(&priv->regs->if1_mcont,
+						  CAN_IF_MCONT_EOB);
+
+			iowrite32(0, &priv->regs->if1_mask1);
+			pch_can_bit_clear(&priv->regs->if1_mask2,
+					  0x1fff | CAN_MASK2_MDIR_MXTD);
+
+			/* Setting CMASK for writing */
+			iowrite32(CAN_CMASK_RDWR | CAN_CMASK_MASK |
+				  CAN_CMASK_ARB | CAN_CMASK_CTRL,
+				  &priv->regs->if1_cmask);
+
+			pch_can_check_if_busy(&priv->regs->if1_creq, i+1);
+		} else if (priv->msg_obj[i] == MSG_OBJ_TX) {
+			iowrite32(CAN_CMASK_RX_TX_GET,
+				&priv->regs->if2_cmask);
+			pch_can_check_if_busy(&priv->regs->if2_creq, i+1);
+
+			/* Resetting DIR bit for reception */
+			iowrite32(0x0, &priv->regs->if2_id1);
+			iowrite32(0x0, &priv->regs->if2_id2);
+			pch_can_bit_set(&priv->regs->if2_id2, CAN_ID2_DIR);
+
+			/* Setting EOB bit for transmitter */
+			iowrite32(CAN_IF_MCONT_EOB, &priv->regs->if2_mcont);
+
+			pch_can_bit_set(&priv->regs->if2_mcont,
+					CAN_IF_MCONT_UMASK);
+
+			iowrite32(0, &priv->regs->if2_mask1);
+			pch_can_bit_clear(&priv->regs->if2_mask2, 0x1fff);
+
+			/* Setting CMASK for writing */
+			iowrite32(CAN_CMASK_RDWR | CAN_CMASK_MASK |
+				  CAN_CMASK_ARB | CAN_CMASK_CTRL,
+				  &priv->regs->if2_cmask);
+
+			pch_can_check_if_busy(&priv->regs->if2_creq, i+1);
+		}
+	}
+	spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
+}
+
+static void pch_can_init(struct pch_can_priv *priv)
+{
+	/* Stopping the Can device. */
+	pch_can_set_run_mode(priv, PCH_CAN_STOP);
+
+	/* Clearing all the message object buffers. */
+	pch_can_clear_buffers(priv);
+
+	/* Configuring the respective message object as either rx/tx object. */
+	pch_can_config_rx_tx_buffers(priv);
+
+	/* Enabling the interrupts. */
+	pch_can_set_int_enables(priv, PCH_CAN_ALL);
+}
+
+static void pch_can_release(struct pch_can_priv *priv)
+{
+	/* Stooping the CAN device. */
+	pch_can_set_run_mode(priv, PCH_CAN_STOP);
+
+	/* Disabling the interrupts. */
+	pch_can_set_int_enables(priv, PCH_CAN_NONE);
+
+	/* Disabling all the receive object. */
+	pch_can_rx_disable_all(priv);
+
+	/* Disabling all the transmit object. */
+	pch_can_tx_disable_all(priv);
+}
+
+/* This function clears interrupt(s) from the CAN device. */
+static void pch_can_int_clr(struct pch_can_priv *priv, u32 mask)
+{
+	if (mask == CAN_STATUS_INT) {
+		ioread32(&priv->regs->stat);
+		return;
+	}
+
+	/* Clear interrupt for transmit object */
+	if (priv->msg_obj[mask - 1] == MSG_OBJ_TX) {
+		/* Setting CMASK for clearing interrupts for
+					 frame transmission. */
+		iowrite32(CAN_CMASK_RDWR | CAN_CMASK_CTRL | CAN_CMASK_ARB,
+			  &priv->regs->if2_cmask);
+
+		/* Resetting the ID registers. */
+		pch_can_bit_set(&priv->regs->if2_id2,
+			       CAN_ID2_DIR | (0x7ff << 2));
+		iowrite32(0x0, &priv->regs->if2_id1);
+
+		/* Claring NewDat, TxRqst & IntPnd */
+		pch_can_bit_clear(&priv->regs->if2_mcont,
+				  CAN_IF_MCONT_NEWDAT | CAN_IF_MCONT_INTPND |
+				  CAN_IF_MCONT_TXRQXT);
+		pch_can_check_if_busy(&priv->regs->if2_creq, mask);
+	} else if (priv->msg_obj[mask - 1] == MSG_OBJ_RX) {
+		/* Setting CMASK for clearing the reception interrupts. */
+		iowrite32(CAN_CMASK_RDWR | CAN_CMASK_CTRL | CAN_CMASK_ARB,
+			  &priv->regs->if1_cmask);
+
+		/* Clearing the Dir bit. */
+		pch_can_bit_clear(&priv->regs->if1_id2, CAN_ID2_DIR);
+
+		/* Clearing NewDat & IntPnd */
+		pch_can_bit_clear(&priv->regs->if1_mcont,
+				  CAN_IF_MCONT_NEWDAT | CAN_IF_MCONT_INTPND);
+
+		pch_can_check_if_busy(&priv->regs->if1_creq, mask);
+	}
+}
+
+static int pch_can_get_buffer_status(struct pch_can_priv *priv)
+{
+	return (ioread32(&priv->regs->treq1) & 0xffff) |
+	       ((ioread32(&priv->regs->treq2) & 0xffff) << 16);
+}
+
+static void pch_can_reset(struct pch_can_priv *priv)
+{
+	/* write to sw reset register */
+	iowrite32(1, &priv->regs->srst);
+	iowrite32(0, &priv->regs->srst);
+}
+
+static void pch_can_error(struct net_device *ndev, u32 status)
+{
+	struct sk_buff *skb;
+	struct pch_can_priv *priv = netdev_priv(ndev);
+	struct can_frame *cf;
+	u32 errc;
+	struct net_device_stats *stats = &(priv->ndev->stats);
+	enum can_state state = priv->can.state;
+
+	skb = alloc_can_err_skb(ndev, &cf);
+	if (!skb)
+		return;
+
+	if (status & PCH_BUS_OFF) {
+		pch_can_tx_disable_all(priv);
+		pch_can_rx_disable_all(priv);
+		state = CAN_STATE_BUS_OFF;
+		cf->can_id |= CAN_ERR_BUSOFF;
+		can_bus_off(ndev);
+		pch_can_set_run_mode(priv, PCH_CAN_RUN);
+		dev_err(&ndev->dev, "%s -> Bus Off occurres.\n", __func__);
+	}
+
+	/* Warning interrupt. */
+	if (status & PCH_EWARN) {
+		state = CAN_STATE_ERROR_WARNING;
+		priv->can.can_stats.error_warning++;
+		cf->can_id |= CAN_ERR_CRTL;
+		errc = ioread32(&priv->regs->errc);
+		if (((errc & CAN_REC) >> 8) > 96)
+			cf->data[1] |= CAN_ERR_CRTL_RX_WARNING;
+		if ((errc & CAN_TEC) > 96)
+			cf->data[1] |= CAN_ERR_CRTL_TX_WARNING;
+		dev_warn(&ndev->dev,
+			"%s -> Error Counter is more than 96.\n", __func__);
+	}
+	/* Error passive interrupt. */
+	if (status & PCH_EPASSIV) {
+		priv->can.can_stats.error_passive++;
+		state = CAN_STATE_ERROR_PASSIVE;
+		cf->can_id |= CAN_ERR_CRTL;
+		errc = ioread32(&priv->regs->errc);
+		if (((errc & CAN_REC) >> 8) > 127)
+			cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE;
+		if ((errc & CAN_TEC) > 127)
+			cf->data[1] |= CAN_ERR_CRTL_TX_PASSIVE;
+		dev_err(&ndev->dev,
+			"%s -> CAN controller is ERROR PASSIVE .\n", __func__);
+	}
+
+	if (status & PCH_LEC_ALL) {
+		priv->can.can_stats.bus_error++;
+		stats->rx_errors++;
+		switch (status & PCH_LEC_ALL) {
+		case PCH_STUF_ERR:
+			cf->data[2] |= CAN_ERR_PROT_STUFF;
+			break;
+		case PCH_FORM_ERR:
+			cf->data[2] |= CAN_ERR_PROT_FORM;
+			break;
+		case PCH_ACK_ERR:
+			cf->data[2] |= CAN_ERR_PROT_LOC_ACK |
+				       CAN_ERR_PROT_LOC_ACK_DEL;
+			break;
+		case PCH_BIT1_ERR:
+		case PCH_BIT0_ERR:
+			cf->data[2] |= CAN_ERR_PROT_BIT;
+			break;
+		case PCH_CRC_ERR:
+			cf->data[2] |= CAN_ERR_PROT_LOC_CRC_SEQ |
+				       CAN_ERR_PROT_LOC_CRC_DEL;
+			break;
+		default:
+			iowrite32(status | PCH_LEC_ALL, &priv->regs->stat);
+			break;
+		}
+
+	}
+
+	priv->can.state = state;
+	netif_rx(skb);
+
+	stats->rx_packets++;
+	stats->rx_bytes += cf->can_dlc;
+}
+
+static irqreturn_t pch_can_interrupt(int irq, void *dev_id)
+{
+	struct net_device *ndev = (struct net_device *)dev_id;
+	struct pch_can_priv *priv = netdev_priv(ndev);
+
+	pch_can_set_int_enables(priv, PCH_CAN_NONE);
+
+	napi_schedule(&priv->napi);
+
+	return IRQ_HANDLED;
+}
+
+static int pch_can_rx_normal(struct net_device *ndev, u32 int_stat)
+{
+	u32 reg;
+	canid_t id;
+	u32 ide;
+	u32 rtr;
+	int i, j, k;
+	int rcv_pkts = 0;
+	struct sk_buff *skb;
+	struct can_frame *cf;
+	struct pch_can_priv *priv = netdev_priv(ndev);
+	struct net_device_stats *stats = &(priv->ndev->stats);
+
+	/* Reading the messsage object from the Message RAM */
+	iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if1_cmask);
+	pch_can_check_if_busy(&priv->regs->if1_creq, int_stat);
+
+	/* Reading the MCONT register. */
+	reg = ioread32(&priv->regs->if1_mcont);
+	reg &= 0xffff;
+
+	for (k = int_stat; !(reg & CAN_IF_MCONT_EOB); k++) {
+		/* If MsgLost bit set. */
+		if (reg & CAN_IF_MCONT_MSGLOST) {
+			dev_err(&priv->ndev->dev, "Msg Obj is overwritten.\n");
+			pch_can_bit_clear(&priv->regs->if1_mcont,
+					  CAN_IF_MCONT_MSGLOST);
+			iowrite32(CAN_CMASK_RDWR | CAN_CMASK_CTRL,
+				  &priv->regs->if1_cmask);
+			pch_can_check_if_busy(&priv->regs->if1_creq, k);
+
+			skb = alloc_can_err_skb(ndev, &cf);
+			if (!skb)
+				return -ENOMEM;
+
+			priv->can.can_stats.error_passive++;
+			priv->can.state = CAN_STATE_ERROR_PASSIVE;
+			cf->can_id |= CAN_ERR_CRTL;
+			cf->data[1] |= CAN_ERR_CRTL_RX_OVERFLOW;
+			cf->data[2] |= CAN_ERR_PROT_OVERLOAD;
+			stats->rx_packets++;
+			stats->rx_bytes += cf->can_dlc;
+
+			netif_receive_skb(skb);
+			rcv_pkts++;
+			goto RX_NEXT;
+		}
+		if (!(reg & CAN_IF_MCONT_NEWDAT))
+			goto RX_NEXT;
+
+		skb = alloc_can_skb(priv->ndev, &cf);
+		if (!skb)
+			return -ENOMEM;
+
+		/* Get Received data */
+		ide = ((ioread32(&priv->regs->if1_id2)) & CAN_ID2_XTD) >> 14;
+		if (ide) {
+			id = (ioread32(&priv->regs->if1_id1) & 0xffff);
+			id |= (((ioread32(&priv->regs->if1_id2)) &
+					    0x1fff) << 16);
+			cf->can_id = (id & CAN_EFF_MASK) | CAN_EFF_FLAG;
+		} else {
+			id = (((ioread32(&priv->regs->if1_id2)) &
+					  (CAN_SFF_MASK << 2)) >> 2);
+			cf->can_id = (id & CAN_SFF_MASK);
+		}
+
+		rtr = (ioread32(&priv->regs->if1_id2) &  CAN_ID2_DIR);
+		if (rtr) {
+			cf->can_dlc = 0;
+			cf->can_id |= CAN_RTR_FLAG;
+		} else {
+			cf->can_dlc = ((ioread32(&priv->regs->if1_mcont)) &
+						   0x0f);
+		}
+
+		for (i = 0, j = 0; i < cf->can_dlc; j++) {
+			reg = ioread32(&priv->regs->if1_dataa1 + j*4);
+			cf->data[i++] = cpu_to_le32(reg & 0xff);
+			if (i == cf->can_dlc)
+				break;
+			cf->data[i++] = cpu_to_le32((reg >> 8) & 0xff);
+		}
+
+		netif_receive_skb(skb);
+		rcv_pkts++;
+		stats->rx_packets++;
+		stats->rx_bytes += cf->can_dlc;
+
+		if (k < PCH_FIFO_THRESH) {
+			iowrite32(CAN_CMASK_RDWR | CAN_CMASK_CTRL |
+				  CAN_CMASK_ARB, &priv->regs->if1_cmask);
+
+			/* Clearing the Dir bit. */
+			pch_can_bit_clear(&priv->regs->if1_id2, CAN_ID2_DIR);
+
+			/* Clearing NewDat & IntPnd */
+			pch_can_bit_clear(&priv->regs->if1_mcont,
+					  CAN_IF_MCONT_INTPND);
+			pch_can_check_if_busy(&priv->regs->if1_creq, k);
+		} else if (k > PCH_FIFO_THRESH) {
+			pch_can_int_clr(priv, k);
+		} else if (k == PCH_FIFO_THRESH) {
+			int cnt;
+			for (cnt = 0; cnt < PCH_FIFO_THRESH; cnt++)
+				pch_can_int_clr(priv, cnt+1);
+		}
+RX_NEXT:
+		/* Reading the messsage object from the Message RAM */
+		iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if1_cmask);
+		pch_can_check_if_busy(&priv->regs->if1_creq, k + 1);
+		reg = ioread32(&priv->regs->if1_mcont);
+	}
+
+	return rcv_pkts;
+}
+static int pch_can_rx_poll(struct napi_struct *napi, int quota)
+{
+	struct net_device *ndev = napi->dev;
+	struct pch_can_priv *priv = netdev_priv(ndev);
+	struct net_device_stats *stats = &(priv->ndev->stats);
+	u32 dlc;
+	u32 int_stat;
+	int rcv_pkts = 0;
+	u32 reg_stat;
+	unsigned long flags;
+
+	int_stat = pch_can_int_pending(priv);
+	if (!int_stat)
+		return 0;
+
+INT_STAT:
+	if (int_stat == CAN_STATUS_INT) {
+		reg_stat = ioread32(&priv->regs->stat);
+		if (reg_stat & (PCH_BUS_OFF | PCH_LEC_ALL)) {
+			if ((reg_stat & PCH_LEC_ALL) != PCH_LEC_ALL)
+				pch_can_error(ndev, reg_stat);
+		}
+
+		if (reg_stat & PCH_TX_OK) {
+			spin_lock_irqsave(&priv->msgif_reg_lock, flags);
+			iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if2_cmask);
+			pch_can_check_if_busy(&priv->regs->if2_creq,
+					       ioread32(&priv->regs->intr));
+			spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
+			pch_can_bit_clear(&priv->regs->stat, PCH_TX_OK);
+		}
+
+		if (reg_stat & PCH_RX_OK)
+			pch_can_bit_clear(&priv->regs->stat, PCH_RX_OK);
+
+		int_stat = pch_can_int_pending(priv);
+		if (int_stat == CAN_STATUS_INT)
+			goto INT_STAT;
+	}
+
+MSG_OBJ:
+	if ((int_stat >= 1) && (int_stat <= PCH_RX_OBJ_NUM)) {
+		spin_lock_irqsave(&priv->msgif_reg_lock, flags);
+		rcv_pkts = pch_can_rx_normal(ndev, int_stat);
+		spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
+		if (rcv_pkts < 0)
+			return 0;
+	} else if ((int_stat > PCH_RX_OBJ_NUM) && (int_stat <= PCH_OBJ_NUM)) {
+		if (priv->msg_obj[int_stat - 1] == MSG_OBJ_TX) {
+			/* Handle transmission interrupt */
+			can_get_echo_skb(ndev, int_stat - PCH_RX_OBJ_NUM - 1);
+			spin_lock_irqsave(&priv->msgif_reg_lock, flags);
+			iowrite32(CAN_CMASK_RX_TX_GET | CAN_CMASK_CLRINTPND,
+				  &priv->regs->if2_cmask);
+			dlc = ioread32(&priv->regs->if2_mcont) &
+				       CAN_IF_MCONT_DLC;
+			pch_can_check_if_busy(&priv->regs->if2_creq, int_stat);
+			spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
+			if (dlc > 8)
+				dlc = 8;
+			stats->tx_bytes += dlc;
+			stats->tx_packets++;
+		}
+	}
+
+	int_stat = pch_can_int_pending(priv);
+	if (int_stat == CAN_STATUS_INT)
+		goto INT_STAT;
+	else if (int_stat >= 1 && int_stat <= 32)
+		goto MSG_OBJ;
+
+	napi_complete(napi);
+	pch_can_set_int_enables(priv, PCH_CAN_ALL);
+
+	return rcv_pkts;
+}
+
+static int pch_set_bittiming(struct net_device *ndev)
+{
+	struct pch_can_priv *priv = netdev_priv(ndev);
+	const struct can_bittiming *bt = &priv->can.bittiming;
+	u32 canbit;
+	u32 bepe;
+	u32 brp;
+
+	/* Setting the CCE bit for accessing the Can Timing register. */
+	pch_can_bit_set(&priv->regs->cont, CAN_CTRL_CCE);
+
+	brp = (bt->tq) / (1000000000/PCH_CAN_CLK) - 1;
+	canbit = brp & MSK_BITT_BRP;
+	canbit |= (bt->sjw - 1) << BIT_BITT_SJW;
+	canbit |= (bt->phase_seg1 + bt->prop_seg - 1) << BIT_BITT_TSEG1;
+	canbit |= (bt->phase_seg2 - 1) << BIT_BITT_TSEG2;
+	bepe = (brp & MSK_BRPE_BRPE) >> BIT_BRPE_BRPE;
+	iowrite32(canbit, &priv->regs->bitt);
+	iowrite32(bepe, &priv->regs->brpe);
+	pch_can_bit_clear(&priv->regs->cont, CAN_CTRL_CCE);
+
+	return 0;
+}
+
+static void pch_can_start(struct net_device *ndev)
+{
+	struct pch_can_priv *priv = netdev_priv(ndev);
+
+	if (priv->can.state != CAN_STATE_STOPPED)
+		pch_can_reset(priv);
+
+	pch_set_bittiming(ndev);
+	pch_can_set_optmode(priv);
+
+	pch_can_tx_enable_all(priv);
+	pch_can_rx_enable_all(priv);
+
+	/* Setting the CAN to run mode. */
+	pch_can_set_run_mode(priv, PCH_CAN_RUN);
+
+	priv->can.state = CAN_STATE_ERROR_ACTIVE;
+
+	return;
+}
+
+static int pch_can_do_set_mode(struct net_device *ndev, enum can_mode mode)
+{
+	int ret = 0;
+
+	switch (mode) {
+	case CAN_MODE_START:
+		pch_can_start(ndev);
+		netif_wake_queue(ndev);
+		break;
+	default:
+		ret = -EOPNOTSUPP;
+		break;
+	}
+
+	return ret;
+}
+
+static int pch_can_open(struct net_device *ndev)
+{
+	struct pch_can_priv *priv = netdev_priv(ndev);
+	int retval;
+
+	retval = pci_enable_msi(priv->dev);
+	if (retval) {
+		dev_info(&ndev->dev, "PCH CAN opened without MSI\n");
+		priv->use_msi = 0;
+	} else {
+		dev_info(&ndev->dev, "PCH CAN opened with MSI\n");
+		priv->use_msi = 1;
+	}
+
+	/* Regsitering the interrupt. */
+	retval = request_irq(priv->dev->irq, pch_can_interrupt, IRQF_SHARED,
+			     ndev->name, ndev);
+	if (retval) {
+		dev_err(&ndev->dev, "request_irq failed.\n");
+		goto req_irq_err;
+	}
+
+	/* Open common can device */
+	retval = open_candev(ndev);
+	if (retval) {
+		dev_err(ndev->dev.parent, "open_candev() failed %d\n", retval);
+		goto err_open_candev;
+	}
+
+	pch_can_init(priv);
+	pch_can_start(ndev);
+	napi_enable(&priv->napi);
+	netif_start_queue(ndev);
+
+	return 0;
+
+err_open_candev:
+	free_irq(priv->dev->irq, ndev);
+req_irq_err:
+	if (priv->use_msi)
+		pci_disable_msi(priv->dev);
+
+	pch_can_release(priv);
+
+	return retval;
+}
+
+static int pch_close(struct net_device *ndev)
+{
+	struct pch_can_priv *priv = netdev_priv(ndev);
+
+	netif_stop_queue(ndev);
+	napi_disable(&priv->napi);
+	pch_can_release(priv);
+	free_irq(priv->dev->irq, ndev);
+	if (priv->use_msi)
+		pci_disable_msi(priv->dev);
+	close_candev(ndev);
+	priv->can.state = CAN_STATE_STOPPED;
+	return 0;
+}
+
+static int pch_get_msg_obj_sts(struct net_device *ndev, u32 obj_id)
+{
+	u32 buffer_status = 0;
+	struct pch_can_priv *priv = netdev_priv(ndev);
+
+	/* Getting the message object status. */
+	buffer_status = (u32) pch_can_get_buffer_status(priv);
+
+	return buffer_status & obj_id;
+}
+
+
+static netdev_tx_t pch_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+	int i, j;
+	unsigned long flags;
+	struct pch_can_priv *priv = netdev_priv(ndev);
+	struct can_frame *cf = (struct can_frame *)skb->data;
+	int tx_buffer_avail = 0;
+
+	if (can_dropped_invalid_skb(ndev, skb))
+		return NETDEV_TX_OK;
+
+	if (priv->tx_obj == (PCH_OBJ_NUM + 1)) { /* Point tail Obj + 1 */
+		while (pch_get_msg_obj_sts(ndev, (((1 << PCH_TX_OBJ_NUM)-1) <<
+					   PCH_RX_OBJ_NUM)))
+			udelay(500);
+
+		priv->tx_obj = PCH_RX_OBJ_NUM + 1; /* Point head of Tx Obj ID */
+		tx_buffer_avail = priv->tx_obj;
+	} else {
+		tx_buffer_avail = priv->tx_obj;
+	}
+	priv->tx_obj++;
+
+	/* Attaining the lock. */
+	spin_lock_irqsave(&priv->msgif_reg_lock, flags);
+
+	/* Reading the Msg Obj from the Msg RAM to the Interface register. */
+	iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if2_cmask);
+	pch_can_check_if_busy(&priv->regs->if2_creq, tx_buffer_avail);
+
+	/* Setting the CMASK register. */
+	pch_can_bit_set(&priv->regs->if2_cmask, CAN_CMASK_ALL);
+
+	/* If ID extended is set. */
+	pch_can_bit_clear(&priv->regs->if2_id1, 0xffff);
+	pch_can_bit_clear(&priv->regs->if2_id2, 0x1fff | CAN_ID2_XTD);
+	if (cf->can_id & CAN_EFF_FLAG) {
+		pch_can_bit_set(&priv->regs->if2_id1, cf->can_id & 0xffff);
+		pch_can_bit_set(&priv->regs->if2_id2,
+				((cf->can_id >> 16) & 0x1fff) | CAN_ID2_XTD);
+	} else {
+		pch_can_bit_set(&priv->regs->if2_id1, 0);
+		pch_can_bit_set(&priv->regs->if2_id2,
+				(cf->can_id & CAN_SFF_MASK) << 2);
+	}
+
+	/* 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);
+
+	for (i = 0, j = 0; i < cf->can_dlc; j++) {
+		iowrite32(le32_to_cpu(cf->data[i++]),
+			 (&priv->regs->if2_dataa1) + j*4);
+		if (i == cf->can_dlc)
+			break;
+		iowrite32(le32_to_cpu(cf->data[i++] << 8),
+			 (&priv->regs->if2_dataa1) + j*4);
+	}
+
+	can_put_echo_skb(skb, ndev, tx_buffer_avail - PCH_RX_OBJ_NUM - 1);
+
+	/* Updating the size of the data. */
+	pch_can_bit_clear(&priv->regs->if2_mcont, 0x0f);
+	pch_can_bit_set(&priv->regs->if2_mcont, cf->can_dlc);
+
+	/* Clearing IntPend, NewDat & TxRqst */
+	pch_can_bit_clear(&priv->regs->if2_mcont,
+			  CAN_IF_MCONT_NEWDAT | CAN_IF_MCONT_INTPND |
+			  CAN_IF_MCONT_TXRQXT);
+
+	/* Setting NewDat, TxRqst bits */
+	pch_can_bit_set(&priv->regs->if2_mcont,
+			CAN_IF_MCONT_NEWDAT | CAN_IF_MCONT_TXRQXT);
+
+	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);
+	free_candev(priv->ndev);
+	pci_iounmap(pdev, priv->regs);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+	pci_set_drvdata(pdev, NULL);
+	pch_can_reset(priv);
+}
+
+#ifdef CONFIG_PM
+static void pch_can_set_int_custom(struct pch_can_priv *priv)
+{
+	/* Clearing the IE, SIE and EIE bits of Can control register. */
+	pch_can_bit_clear(&priv->regs->cont, CAN_CTRL_IE_SIE_EIE);
+
+	/* Appropriately setting them. */
+	pch_can_bit_set(&priv->regs->cont,
+			((priv->int_enables & MSK_CTRL_IE_SIE_EIE) << 1));
+}
+
+/* This function retrieves interrupt enabled for the CAN device. */
+static void pch_can_get_int_enables(struct pch_can_priv *priv, u32
*enables)
+{
+	/* Obtaining the status of IE, SIE and EIE interrupt bits. */
+	*enables = ((ioread32(&priv->regs->cont) & CAN_CTRL_IE_SIE_EIE) >> 1);
+}
+
+static void pch_can_get_rx_enable(struct pch_can_priv *priv, u32 buff_num,
+				 u32 *enable)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->msgif_reg_lock, flags);
+	iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if1_cmask);
+	pch_can_check_if_busy(&priv->regs->if1_creq, buff_num);
+
+	if (((ioread32(&priv->regs->if1_id2)) & CAN_ID_MSGVAL) &&
+			((ioread32(&priv->regs->if1_mcont)) &
+			CAN_IF_MCONT_RXIE))
+		*enable = ENABLE;
+	else
+		*enable = DISABLE;
+	spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
+}
+
+static void pch_can_get_tx_enable(struct pch_can_priv *priv, u32 buff_num,
+				 u32 *enable)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->msgif_reg_lock, flags);
+	iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if2_cmask);
+	pch_can_check_if_busy(&priv->regs->if2_creq, buff_num);
+
+	if (((ioread32(&priv->regs->if2_id2)) & CAN_ID_MSGVAL) &&
+			((ioread32(&priv->regs->if2_mcont)) &
+			CAN_IF_MCONT_TXIE)) {
+		*enable = ENABLE;
+	} else {
+		*enable = DISABLE;
+	}
+	spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
+}
+
+static void pch_can_set_rx_buffer_link(struct pch_can_priv *priv,
+				       u32 buffer_num, u32 set)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->msgif_reg_lock, flags);
+	iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if1_cmask);
+	pch_can_check_if_busy(&priv->regs->if1_creq, buffer_num);
+	iowrite32(CAN_CMASK_RDWR | CAN_CMASK_CTRL, &priv->regs->if1_cmask);
+	if (set == ENABLE)
+		pch_can_bit_clear(&priv->regs->if1_mcont, CAN_IF_MCONT_EOB);
+	else
+		pch_can_bit_set(&priv->regs->if1_mcont, CAN_IF_MCONT_EOB);
+
+	pch_can_check_if_busy(&priv->regs->if1_creq, buffer_num);
+	spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
+}
+
+static void pch_can_get_rx_buffer_link(struct pch_can_priv *priv,
+				       u32 buffer_num, u32 *link)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->msgif_reg_lock, flags);
+	iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if1_cmask);
+	pch_can_check_if_busy(&priv->regs->if1_creq, buffer_num);
+
+	if (ioread32(&priv->regs->if1_mcont) & CAN_IF_MCONT_EOB)
+		*link = DISABLE;
+	else
+		*link = ENABLE;
+	spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
+}
+
+static int pch_can_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	int i;			/* Counter variable. */
+	int retval;		/* Return value. */
+	u32 buf_stat;	/* Variable for reading the transmit buffer status. */
+	u32 counter = 0xFFFFFF;
+
+	struct net_device *dev = pci_get_drvdata(pdev);
+	struct pch_can_priv *priv = netdev_priv(dev);
+
+	/* Stop the CAN controller */
+	pch_can_set_run_mode(priv, PCH_CAN_STOP);
+
+	/* Indicate that we are aboutto/in suspend */
+	priv->can.state = CAN_STATE_SLEEPING;
+
+	/* Waiting for all transmission to complete. */
+	while (counter) {
+		buf_stat = pch_can_get_buffer_status(priv);
+		if (!buf_stat)
+			break;
+		counter--;
+		udelay(1);
+	}
+	if (!counter)
+		dev_err(&pdev->dev, "%s -> Transmission time out.\n", __func__);
+
+	/* Save interrupt configuration and then disable them */
+	pch_can_get_int_enables(priv, &(priv->int_enables));
+	pch_can_set_int_enables(priv, PCH_CAN_DISABLE);
+
+	/* Save Tx buffer enable state */
+	for (i = 0; i < PCH_OBJ_NUM; i++) {
+		if (priv->msg_obj[i] == MSG_OBJ_TX)
+			pch_can_get_tx_enable(priv, i + 1,
+					      &(priv->tx_enable[i]));
+	}
+
+	/* Disable all Transmit buffers */
+	pch_can_tx_disable_all(priv);
+
+	/* Save Rx buffer enable state */
+	for (i = 0; i < PCH_OBJ_NUM; i++) {
+		if (priv->msg_obj[i] == MSG_OBJ_RX) {
+			pch_can_get_rx_enable(priv, i + 1,
+						&(priv->rx_enable[i]));
+			pch_can_get_rx_buffer_link(priv, i + 1,
+						&(priv->rx_link[i]));
+		}
+	}
+
+	/* Disable all Receive buffers */
+	pch_can_rx_disable_all(priv);
+	retval = pci_save_state(pdev);
+	if (retval) {
+		dev_err(&pdev->dev, "pci_save_state failed.\n");
+	} else {
+		pci_enable_wake(pdev, PCI_D3hot, 0);
+		pci_disable_device(pdev);
+		pci_set_power_state(pdev, pci_choose_state(pdev, state));
+	}
+
+	return retval;
+}
+
+static int pch_can_resume(struct pci_dev *pdev)
+{
+	int i;			/* Counter variable. */
+	int retval;		/* Return variable. */
+	struct net_device *dev = pci_get_drvdata(pdev);
+	struct pch_can_priv *priv = netdev_priv(dev);
+
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+	retval = pci_enable_device(pdev);
+	if (retval) {
+		dev_err(&pdev->dev, "pci_enable_device failed.\n");
+		return retval;
+	}
+
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+
+	priv->can.state = CAN_STATE_ERROR_ACTIVE;
+
+	/* Disabling all interrupts. */
+	pch_can_set_int_enables(priv, PCH_CAN_DISABLE);
+
+	/* Setting the CAN device in Stop Mode. */
+	pch_can_set_run_mode(priv, PCH_CAN_STOP);
+
+	/* Configuring the transmit and receive buffers. */
+	pch_can_config_rx_tx_buffers(priv);
+
+	/* Restore the CAN state */
+	pch_set_bittiming(dev);
+
+	/* Listen/Active */
+	pch_can_set_optmode(priv);
+
+	/* Enabling the transmit buffer. */
+	for (i = 0; i < PCH_OBJ_NUM; i++) {
+		if (priv->msg_obj[i] == MSG_OBJ_TX) {
+			pch_can_set_tx_enable(priv, i + 1,
+					      priv->tx_enable[i]);
+		}
+	}
+
+	/* Configuring the receive buffer and enabling them. */
+	for (i = 0; i < PCH_OBJ_NUM; i++) {
+		if (priv->msg_obj[i] == MSG_OBJ_RX) {
+			/* Restore buffer link */
+			pch_can_set_rx_buffer_link(priv, i + 1,
+						   priv->rx_link[i]);
+
+			/* Restore buffer enables */
+			pch_can_set_rx_enable(priv, i + 1, priv->rx_enable[i]);
+		}
+	}
+
+	/* Enable CAN Interrupts */
+	pch_can_set_int_custom(priv);
+
+	/* Restore Run Mode */
+	pch_can_set_run_mode(priv, PCH_CAN_RUN);
+
+	return retval;
+}
+#else
+#define pch_can_suspend NULL
+#define pch_can_resume NULL
+#endif
+
+static int pch_can_get_berr_counter(const struct net_device *dev,
+				    struct can_berr_counter *bec)
+{
+	struct pch_can_priv *priv = netdev_priv(dev);
+
+	bec->txerr = ioread32(&priv->regs->errc) & CAN_TEC;
+	bec->rxerr = (ioread32(&priv->regs->errc) & CAN_REC) >> 8;
+
+	return 0;
+}
+
+static int __devinit pch_can_probe(struct pci_dev *pdev,
+				   const struct pci_device_id *id)
+{
+	struct net_device *ndev;
+	struct pch_can_priv *priv;
+	int rc;
+	int index;
+	void __iomem *addr;
+
+	rc = pci_enable_device(pdev);
+	if (rc) {
+		dev_err(&pdev->dev, "Failed pci_enable_device %d\n", rc);
+		goto probe_exit_endev;
+	}
+
+	rc = pci_request_regions(pdev, KBUILD_MODNAME);
+	if (rc) {
+		dev_err(&pdev->dev, "Failed pci_request_regions %d\n", rc);
+		goto probe_exit_pcireq;
+	}
+
+	addr = pci_iomap(pdev, 1, 0);
+	if (!addr) {
+		rc = -EIO;
+		dev_err(&pdev->dev, "Failed pci_iomap\n");
+		goto probe_exit_ipmap;
+	}
+
+	ndev = alloc_candev(sizeof(struct pch_can_priv), PCH_TX_OBJ_NUM);
+	if (!ndev) {
+		rc = -ENOMEM;
+		dev_err(&pdev->dev, "Failed alloc_candev\n");
+		goto probe_exit_alloc_candev;
+	}
+
+	priv = netdev_priv(ndev);
+	priv->ndev = ndev;
+	priv->regs = addr;
+	priv->dev = pdev;
+	priv->can.bittiming_const = &pch_can_bittiming_const;
+	priv->can.do_set_mode = pch_can_do_set_mode;
+	priv->can.do_get_berr_counter = pch_can_get_berr_counter;
+	priv->can.ctrlmode_supported = CAN_CTRLMODE_LISTENONLY |
+				       CAN_CTRLMODE_LOOPBACK;
+	priv->tx_obj = PCH_RX_OBJ_NUM + 1; /* Point head of Tx Obj */
+
+	ndev->irq = pdev->irq;
+	ndev->flags |= IFF_ECHO;
+
+	pci_set_drvdata(pdev, ndev);
+	SET_NETDEV_DEV(ndev, &pdev->dev);
+	ndev->netdev_ops = &pch_can_netdev_ops;
+
+	priv->can.clock.freq = PCH_CAN_CLK; /* Hz */
+	for (index = 0; index < PCH_RX_OBJ_NUM;)
+		priv->msg_obj[index++] = MSG_OBJ_RX;
+
+	for (index = index;  index < PCH_OBJ_NUM;)
+		priv->msg_obj[index++] = MSG_OBJ_TX;
+
+	netif_napi_add(ndev, &priv->napi, pch_can_rx_poll, PCH_RX_OBJ_NUM);
+
+	rc = register_candev(ndev);
+	if (rc) {
+		dev_err(&pdev->dev, "Failed register_candev %d\n", rc);
+		goto probe_exit_reg_candev;
+	}
+
+	return 0;
+
+probe_exit_reg_candev:
+	free_candev(ndev);
+probe_exit_alloc_candev:
+	pci_iounmap(pdev, addr);
+probe_exit_ipmap:
+	pci_release_regions(pdev);
+probe_exit_pcireq:
+	pci_disable_device(pdev);
+probe_exit_endev:
+	return rc;
+}
+
+static struct pci_driver pch_can_pcidev = {
+	.name = "pch_can",
+	.id_table = pch_pci_tbl,
+	.probe = pch_can_probe,
+	.remove = __devexit_p(pch_can_remove),
+	.suspend = pch_can_suspend,
+	.resume = pch_can_resume,
+};
+
+static int __init pch_can_pci_init(void)
+{
+	return pci_register_driver(&pch_can_pcidev);
+}
+module_init(pch_can_pci_init);
+
+static void __exit pch_can_pci_exit(void)
+{
+	pci_unregister_driver(&pch_can_pcidev);
+}
+module_exit(pch_can_pci_exit);
+
+MODULE_DESCRIPTION("Controller Area Network Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION("0.94");
-- 
1.6.0.6


^ permalink raw reply related

* Re: [PATCH 3/3] vmxnet3: fix typo setting confPA
From: Harvey Harrison @ 2010-10-25  1:46 UTC (permalink / raw)
  To: David Miller; +Cc: sbhatewara, netdev, shemminger
In-Reply-To: <20101024.154417.116368884.davem@davemloft.net>

On Sun, Oct 24, 2010 at 3:44 PM, David Miller <davem@davemloft.net> wrote:
> From: Harvey Harrison <harvey.harrison@gmail.com>
>> <sbhatewara@vmware.com> wrote:
>>> Because values need to be written in LE orders in registers. For eg. when rx_ring.next2fill index is written to RXPROD reg, it should be converted from CPU order to LE.
>>
>> Yes, but (unless I'm mistaken) writel always writes out in
>> little-endian, so there isn't a need to swap the arguments,
>> similarly for readl in the other direction.
>
> That's right, readl() and writel() translate to little-endian.
>

OK, I'll submit patches for this and one more endian fix I found (only
visible on BE)

Harvey

^ permalink raw reply

* FYI: net-2.6 and net-next-2.6 rebased
From: David Miller @ 2010-10-24 23:55 UTC (permalink / raw)
  To: netdev; +Cc: linux-wireless, netfilter-devel, kaber, linville, sfr


I've rebased both the net-2.6 and net-next-2.6 trees.

All of the commits that were in those trees are in Linus's
tree now, so in fact this event ought to be %100 transparent
for people pulling from my trees.

No commits will appear in net-next-2.6 until the merge
window is closed, it's just a dummy clone of Linus's current
tree so that Stephen Rothwell's -next pulls "just work."

Thanks.

^ permalink raw reply

* Re: [Uclinux-dist-devel] [PATCH 1/5] netdev: bfin_mac: push settings to platform resources
From: Mike Frysinger @ 2010-10-24 23:51 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, uclinux-dist-devel
In-Reply-To: <20101024.164534.241451843.davem@davemloft.net>

On Sun, Oct 24, 2010 at 19:45, David Miller wrote:
> From: Mike Frysinger
>> and i have the Blackfin changes waiting for you to merge this patch.
>> i can squash them into this change and have you merge the result, or i
>> can merge it.  i dont really care either way.
>
> Why don't you just apply this to your tree then.  Feel free to add my:

thanks, i'll do that
-mike

^ permalink raw reply

* Re: [Uclinux-dist-devel] [PATCH 1/5] netdev: bfin_mac: push settings to platform resources
From: David Miller @ 2010-10-24 23:45 UTC (permalink / raw)
  To: vapier; +Cc: netdev, uclinux-dist-devel
In-Reply-To: <AANLkTik5_a6t5xJ9TWJf37UCL52O02nAQY4YwB6mgnQx@mail.gmail.com>

From: Mike Frysinger <vapier@gentoo.org>
Date: Sun, 24 Oct 2010 19:40:31 -0400

> and i have the Blackfin changes waiting for you to merge this patch.
> i can squash them into this change and have you merge the result, or i
> can merge it.  i dont really care either way.

Why don't you just apply this to your tree then.  Feel free to add my:

Acked-by: David S. Miller <davem@davemloft.net>

^ permalink raw reply

* Re: [Uclinux-dist-devel] [PATCH 1/5] netdev: bfin_mac: push settings to platform resources
From: Mike Frysinger @ 2010-10-24 23:40 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, uclinux-dist-devel
In-Reply-To: <20101024.161722.258113499.davem@davemloft.net>

On Sun, Oct 24, 2010 at 19:17, David Miller wrote:
> From: Mike Frysinger <vapier@gentoo.org>
>> From: Sonic Zhang <sonic.zhang@analog.com>
>>
>> Move all the pin settings out of the Kconfig and into the platform
>> resources (MII vs RMII).  This clean up also lets us push out the
>> phy settings so that board porters may control the layout.
>
> You'll have to approach this differently.
>
> The platform specific bfin_mac changes have to be in place
> before this change goes in.
>
> Not the other way around.
>
> Right now, in fact, there is only one blackfin board support
> file that has the bfin_mii_bus_platform_data bits, but that's
> not even going to compile because this patch being discussed
> isn't applied.
>
> You guys really have to sort this stuff out so that things
> get staged in cleanly and the tree compiles properly commit
> to commit.

and i have the Blackfin changes waiting for you to merge this patch.
i can squash them into this change and have you merge the result, or i
can merge it.  i dont really care either way.
-mike

^ permalink raw reply

* Re: [PATCH] cxgb3: slay double assignment
From: Kyle McMartin @ 2010-10-24 23:40 UTC (permalink / raw)
  To: David Miller; +Cc: kyle, divy, netdev
In-Reply-To: <20101024.162611.02282476.davem@davemloft.net>

On Sun, Oct 24, 2010 at 04:26:11PM -0700, David Miller wrote:
> > Noticed this while building Fedora today... It's been
> > there since around 2007, so I guess a new gcc must be catching
> > these.
> > 
> > Signed-off-by: Kyle McMartin <kyle@redhat.com>
> 
> This patch doesn't apply.
> 

You already merged a patch to fix it, sorry for the noise.

--Kyle

^ permalink raw reply

* Re: [PATCH 2/2] typhoon: update to new VLAN acceleration model
From: David Miller @ 2010-10-24 23:26 UTC (permalink / raw)
  To: dave; +Cc: netdev
In-Reply-To: <1287951621-25170-2-git-send-email-dave@thedillows.org>

From: David Dillow <dave@thedillows.org>
Date: Sun, 24 Oct 2010 16:20:21 -0400

> Also correct the byteswapping as we keep the TCI in host order.
> 
> Signed-off-by: David Dillow <dave@thedillows.org>

Applied.

^ permalink raw reply

* Re: [PATCH 1/2] typhoon: wait for RX mode commands to finish
From: David Miller @ 2010-10-24 23:26 UTC (permalink / raw)
  To: dave; +Cc: netdev
In-Reply-To: <1287951621-25170-1-git-send-email-dave@thedillows.org>

From: David Dillow <dave@thedillows.org>
Date: Sun, 24 Oct 2010 16:20:20 -0400

> When adding VLAN devices, we can get several calls to
> typhoon_set_rx_mode() in quick succession. Because we didn't wait for
> the commands to complete, we could run out of command descriptors and
> fail to set the RX mode.
> 
> Signed-off-by: David Dillow <dave@thedillows.org>

Applied.

^ permalink raw reply

* Re: [PATCH] netlink: fix netlink_change_ngroups()
From: David Miller @ 2010-10-24 23:26 UTC (permalink / raw)
  To: eric.dumazet; +Cc: netdev, johannes, paulmck
In-Reply-To: <1287930430.2658.805.camel@edumazet-laptop>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Sun, 24 Oct 2010 16:27:10 +0200

> commit 6c04bb18ddd633 (netlink: use call_rcu for netlink_change_ngroups)
> used a somewhat convoluted and racy way to perform call_rcu().
> 
> The old block of memory is freed after a grace period, but the rcu_head
> used to track it is located in new block.
> 
> This can clash if we call two times or more netlink_change_ngroups(),
> and a block is freed before another. call_rcu() called on different cpus
> makes no guarantee in order of callbacks.
> 
> Fix this using a more standard way of handling this : Each block of
> memory contains its own rcu_head, so that no 'use after free' can
> happens.
> 
> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>

Applied, thanks a lot.

^ permalink raw reply

* Re: [PATCH] cxgb3: slay double assignment
From: David Miller @ 2010-10-24 23:26 UTC (permalink / raw)
  To: kyle; +Cc: divy, netdev
In-Reply-To: <20101022180003.GO8332@bombadil.infradead.org>

From: Kyle McMartin <kyle@mcmartin.ca>
Date: Fri, 22 Oct 2010 14:00:03 -0400

> Noticed this while building Fedora today... It's been
> there since around 2007, so I guess a new gcc must be catching
> these.
> 
> Signed-off-by: Kyle McMartin <kyle@redhat.com>

This patch doesn't apply.

^ permalink raw reply

* Re: [PATCH v2 net-2.6] jme: Support WoL after shutdown
From: David Miller @ 2010-10-24 23:18 UTC (permalink / raw)
  To: cooldavid; +Cc: netdev, Taoga, arieslee, devinchiu, hcchao, ethanhsiao
In-Reply-To: <1287962062-30714-1-git-send-email-cooldavid@cooldavid.org>

From: "Guo-Fu Tseng" <cooldavid@cooldavid.org>
Date: Mon, 25 Oct 2010 07:14:22 +0800

> From: Guo-Fu Tseng <cooldavid@cooldavid.org>
> 
> Adding shutdown function that setup wake if wol is enabled.
> Add jme_phy_on in jme_set_100m_half in case it is shutting down
> or suspending when interface is down(phy_off by default).
> 
> v2 updates:
> Removed CONFIG_PM ifdef for jme_set_100m_half and jme_wait_link.
> It would be nice if it can be applied to net-2.6 along with other patches
> sent few days ago. If it is not appropriate, please ignore the net-2.6
> request, and apply it to net-next-2.6 as previous patch. :)
> 
> Reported-and-helped-by: Сtac <Taoga@yandex.ru>
> Signed-off-by: Guo-Fu Tseng <cooldavid@cooldavid.org>

Applied.

^ permalink raw reply

* Re: [PATCH 1/5] netdev: bfin_mac: push settings to platform resources
From: David Miller @ 2010-10-24 23:17 UTC (permalink / raw)
  To: vapier; +Cc: netdev, uclinux-dist-devel, sonic.zhang
In-Reply-To: <1287727161-24671-1-git-send-email-vapier@gentoo.org>

From: Mike Frysinger <vapier@gentoo.org>
Date: Fri, 22 Oct 2010 01:59:17 -0400

> From: Sonic Zhang <sonic.zhang@analog.com>
> 
> Move all the pin settings out of the Kconfig and into the platform
> resources (MII vs RMII).  This clean up also lets us push out the
> phy settings so that board porters may control the layout.
> 
> Signed-off-by: Sonic Zhang <sonic.zhang@analog.com>
> Signed-off-by: Mike Frysinger <vapier@gentoo.org>

You'll have to approach this differently.

The platform specific bfin_mac changes have to be in place
before this change goes in.

Not the other way around.

Right now, in fact, there is only one blackfin board support
file that has the bfin_mii_bus_platform_data bits, but that's
not even going to compile because this patch being discussed
isn't applied.

You guys really have to sort this stuff out so that things
get staged in cleanly and the tree compiles properly commit
to commit.

Thanks.

^ permalink raw reply

* [PATCH v2 net-2.6] jme: Support WoL after shutdown
From: Guo-Fu Tseng @ 2010-10-24 23:14 UTC (permalink / raw)
  To: David Miller
  Cc: Guo-Fu Tseng, linux-netdev, Ctac, Aries Lee, Devinchiu,
	Hsiu-Che Chao, Ethan Hsiao

From: Guo-Fu Tseng <cooldavid@cooldavid.org>

Adding shutdown function that setup wake if wol is enabled.
Add jme_phy_on in jme_set_100m_half in case it is shutting down
or suspending when interface is down(phy_off by default).

v2 updates:
Removed CONFIG_PM ifdef for jme_set_100m_half and jme_wait_link.
It would be nice if it can be applied to net-2.6 along with other patches
sent few days ago. If it is not appropriate, please ignore the net-2.6
request, and apply it to net-next-2.6 as previous patch. :)

Reported-and-helped-by: Сtac <Taoga@yandex.ru>
Signed-off-by: Guo-Fu Tseng <cooldavid@cooldavid.org>
---
 drivers/net/jme.c |   45 ++++++++++++++++++++++++++++++---------------
 1 files changed, 30 insertions(+), 15 deletions(-)

diff --git a/drivers/net/jme.c b/drivers/net/jme.c
index d7a975e..d85edf3 100644
--- a/drivers/net/jme.c
+++ b/drivers/net/jme.c
@@ -1623,12 +1623,12 @@ err_out:
 	return rc;
 }
 
-#ifdef CONFIG_PM
 static void
 jme_set_100m_half(struct jme_adapter *jme)
 {
 	u32 bmcr, tmp;
 
+	jme_phy_on(jme);
 	bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR);
 	tmp = bmcr & ~(BMCR_ANENABLE | BMCR_SPEED100 |
 		       BMCR_SPEED1000 | BMCR_FULLDPLX);
@@ -1656,7 +1656,6 @@ jme_wait_link(struct jme_adapter *jme)
 		phylink = jme_linkstat_from_phy(jme);
 	}
 }
-#endif
 
 static inline void
 jme_phy_off(struct jme_adapter *jme)
@@ -1664,6 +1663,21 @@ jme_phy_off(struct jme_adapter *jme)
 	jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, BMCR_PDOWN);
 }
 
+static void
+jme_powersave_phy(struct jme_adapter *jme)
+{
+	if (jme->reg_pmcs) {
+		jme_set_100m_half(jme);
+
+		if (jme->reg_pmcs & (PMCS_LFEN | PMCS_LREN))
+			jme_wait_link(jme);
+
+		jwrite32(jme, JME_PMCS, jme->reg_pmcs);
+	} else {
+		jme_phy_off(jme);
+	}
+}
+
 static int
 jme_close(struct net_device *netdev)
 {
@@ -2991,6 +3005,16 @@ jme_remove_one(struct pci_dev *pdev)
 
 }
 
+static void
+jme_shutdown(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct jme_adapter *jme = netdev_priv(netdev);
+
+	jme_powersave_phy(jme);
+	pci_pme_active(pdev, true);
+}
+
 #ifdef CONFIG_PM
 static int
 jme_suspend(struct pci_dev *pdev, pm_message_t state)
@@ -3028,19 +3052,9 @@ jme_suspend(struct pci_dev *pdev, pm_message_t state)
 	tasklet_hi_enable(&jme->rxempty_task);
 
 	pci_save_state(pdev);
-	if (jme->reg_pmcs) {
-		jme_set_100m_half(jme);
-
-		if (jme->reg_pmcs & (PMCS_LFEN | PMCS_LREN))
-			jme_wait_link(jme);
-
-		jwrite32(jme, JME_PMCS, jme->reg_pmcs);
-
-		pci_enable_wake(pdev, PCI_D3cold, true);
-	} else {
-		jme_phy_off(jme);
-	}
-	pci_set_power_state(pdev, PCI_D3cold);
+	jme_powersave_phy(jme);
+	pci_enable_wake(jme->pdev, PCI_D3hot, true);
+	pci_set_power_state(pdev, PCI_D3hot);
 
 	return 0;
 }
@@ -3087,6 +3101,7 @@ static struct pci_driver jme_driver = {
 	.suspend        = jme_suspend,
 	.resume         = jme_resume,
 #endif /* CONFIG_PM */
+	.shutdown       = jme_shutdown,
 };
 
 static int __init
-- 
1.7.2.2


^ permalink raw reply related

* Re: [PATCH 5/9] tproxy: allow non-local binds of IPv6 sockets if IP_TRANSPARENT is enabled
From: David Miller @ 2010-10-24 23:08 UTC (permalink / raw)
  To: bazsi; +Cc: yoshfuji, hidden, netdev, netfilter-devel, kaber
In-Reply-To: <1287845294.13882.4.camel@bzorp.lan>

From: Balazs Scheidler <bazsi@balabit.hu>
Date: Sat, 23 Oct 2010 16:48:14 +0200

> IP_TRANSPARENT requires root (more precisely CAP_NET_ADMIN privielges)
> for IPV6.
> 
> However as I see right now this check was missed from the IPv6
> implementation.
> 
> Is that enough as a safeguard? e.g. something like this:

Applied, thanks everyone.

^ permalink raw reply

* Re: [PATCH net-next-2.6] jme: Support WoL after shutdown
From: David Miller @ 2010-10-24 22:51 UTC (permalink / raw)
  To: cooldavid; +Cc: netdev, Taoga, arieslee, devinchiu, hcchao, ethanhsiao
In-Reply-To: <20101024.154227.232753445.davem@davemloft.net>

From: David Miller <davem@davemloft.net>
Date: Sun, 24 Oct 2010 15:42:27 -0700 (PDT)

> From: "Guo-Fu Tseng" <cooldavid@cooldavid.org>
> Date: Fri, 22 Oct 2010 09:33:40 +0800
> 
>> From: Guo-Fu Tseng <cooldavid@cooldavid.org>
>> 
>> Adding shutdown function that setup wake if wol is enabled.
>> Add jme_phy_on in jme_set_100m_half in case it is shutting down
>> or suspending when interface is down(phy_off by default).
>> 
>> Reported_and_helped_by: Сtac <Taoga@yandex.ru>
>> Signed-off-by: Guo-Fu Tseng <cooldavid@cooldavid.org>
> 
> Applied.

Actually, I had to undo this patch.  It generates build
failures:

drivers/net/jme.c: In function 'jme_powersave_phy':
drivers/net/jme.c:1672:3: error: implicit declaration of function 'jme_set_100m_half'
drivers/net/jme.c:1675:4: error: implicit declaration of function 'jme_wait_link'

I guess I'm one of the few people who build with CONFIG_PM
disabled :-)

Please fix this up and resubmit your patch.


^ permalink raw reply

* Re: [PATCH 3/3] vmxnet3: fix typo setting confPA
From: David Miller @ 2010-10-24 22:44 UTC (permalink / raw)
  To: harvey.harrison; +Cc: sbhatewara, netdev, shemminger
In-Reply-To: <AANLkTimy5Pg1aUMfCZG+r+Zb=A_udx8NsYf3TXVHHTsf@mail.gmail.com>

From: Harvey Harrison <harvey.harrison@gmail.com>
Date: Fri, 22 Oct 2010 10:52:15 -0700

> On Fri, Oct 22, 2010 at 10:46 AM, Shreyas Bhatewara
> <sbhatewara@vmware.com> wrote:
>>> From: Harvey Harrison [mailto:harvey.harrison@gmail.com]
>>> One question I had when looking into this, why are you doing
>>> byteswapping in the VMXNET_{READ,WRITE}_BAR{0,1}
>>> macros?
>>
>> Because values need to be written in LE orders in registers. For eg. when rx_ring.next2fill index is written to RXPROD reg, it should be converted from CPU order to LE.
> 
> Yes, but (unless I'm mistaken) writel always writes out in
> little-endian, so there isn't a need to swap the arguments,
> similarly for readl in the other direction.

That's right, readl() and writel() translate to little-endian.



^ permalink raw reply

* Re: [PATCH 3/3] vmxnet3: fix typo setting confPA
From: David Miller @ 2010-10-24 22:43 UTC (permalink / raw)
  To: harvey.harrison; +Cc: sbhatewara, netdev, shemminger
In-Reply-To: <1287720334-15469-3-git-send-email-harvey.harrison@gmail.com>

From: Harvey Harrison <harvey.harrison@gmail.com>
Date: Thu, 21 Oct 2010 21:05:34 -0700

> It's a le64, not a le32, typo in one place only.
> 
> Noticed by sparse:
> drivers/net/vmxnet3/vmxnet3_drv.c:2668:52: warning: incorrect type in assignment (different base types)
> drivers/net/vmxnet3/vmxnet3_drv.c:2668:52:    expected restricted __le64 [usertype] confPA
> drivers/net/vmxnet3/vmxnet3_drv.c:2668:52:    got restricted __le32 [usertype] <noident>
> 
> Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com>

Applied.

^ permalink raw reply

* Re: [PATCH 2/3] vmxnet3: annotate hwaddr members as __iomem pointers
From: David Miller @ 2010-10-24 22:43 UTC (permalink / raw)
  To: harvey.harrison; +Cc: sbhatewara, netdev, shemminger
In-Reply-To: <1287720334-15469-2-git-send-email-harvey.harrison@gmail.com>

From: Harvey Harrison <harvey.harrison@gmail.com>
Date: Thu, 21 Oct 2010 21:05:33 -0700

> Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com>

Applied.

^ permalink raw reply

* Re: [PATCH 1/3] vmxnet3: remove set_flag_le{16,64} helpers
From: David Miller @ 2010-10-24 22:43 UTC (permalink / raw)
  To: harvey.harrison; +Cc: sbhatewara, netdev, shemminger
In-Reply-To: <1287720334-15469-1-git-send-email-harvey.harrison@gmail.com>

From: Harvey Harrison <harvey.harrison@gmail.com>
Date: Thu, 21 Oct 2010 21:05:32 -0700

> It's easier to just annotate the constants as little endian types and set/clear
> the flags directly.
> 
> Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com>

Applied.

^ permalink raw reply


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