Netdev List
 help / color / mirror / Atom feed
* Re: [1/2] gro: Only verify TCP checksums for candidates
From: Eric Dumazet @ 2013-11-22  5:55 UTC (permalink / raw)
  To: Herbert Xu
  Cc: David Miller, alexander.h.duyck, alexander.duyck, netdev,
	edumazet
In-Reply-To: <20131122023129.GA6506@gondor.apana.org.au>

On Fri, 2013-11-22 at 10:31 +0800, Herbert Xu wrote:
> In some cases we may receive IP packets that are longer than
> their stated lengths.  Such packets are never merged in GRO.
> However, we may end up computing their checksums incorrectly
> and end up allowing packets with a bogus checksum enter our
> stack with the checksum status set as verified.
> 
> Since such packets are rare and not performance-critical, this
> patch simply skips the checksum verification for them.
> 
> Reported-by: Alexander Duyck <alexander.h.duyck@intel.com>
> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
> Acked-by: Alexander Duyck <alexander.h.duyck@intel.com>

Acked-by: Eric Dumazet <edumazet@google.com>

^ permalink raw reply

* Re: [2/2] gro: Clean up tcpX_gro_receive checksum verification
From: Eric Dumazet @ 2013-11-22  5:58 UTC (permalink / raw)
  To: Herbert Xu
  Cc: David Miller, alexander.h.duyck, alexander.duyck, netdev,
	edumazet
In-Reply-To: <20131122023210.GB6506@gondor.apana.org.au>

On Fri, 2013-11-22 at 10:32 +0800, Herbert Xu wrote:
> This patch simplifies the checksum verification in tcpX_gro_receive
> by reusing the CHECKSUM_COMPLETE code for CHECKSUM_NONE.  All it
> does for CHECKSUM_NONE is compute the partial checksum and then
> treat it as if it came from the hardware (CHECKSUM_COMPLETE).
>     
> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

Acked-by: Eric Dumazet <edumazet@google.com>

^ permalink raw reply

* [PATCH iproute2] tc: more user friendly rates
From: Eric Dumazet @ 2013-11-22  6:37 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev

From: Eric Dumazet <edumazet@google.com>

Display more user friendly rates.

10Mbit is more readable than 10000Kbit

Before : 
class htb 1:2 root prio 0 rate 10000Kbit ceil 10000Kbit ...

After:
class htb 1:2 root prio 0 rate 10Mbit ceil 10Mbit ...

Signed-off-by: Eric Dumazet <edumazet@google.com>
---
 tc/tc_util.c |   32 +++++++++++++-------------------
 1 file changed, 13 insertions(+), 19 deletions(-)

diff --git a/tc/tc_util.c b/tc/tc_util.c
index be3ed07..67f6948 100644
--- a/tc/tc_util.c
+++ b/tc/tc_util.c
@@ -173,28 +173,22 @@ int get_rate(unsigned *rate, const char *str)
 
 void print_rate(char *buf, int len, __u64 rate)
 {
-	double tmp = (double)rate*8;
 	extern int use_iec;
+	unsigned long kilo = use_iec ? 1024 : 1000;
+	const char *str = use_iec ? "i" : "";
+	int i = 0;
+	static char *units[5] = {"", "K", "M", "G", "T"};
 
-	if (use_iec) {
-		if (tmp >= 1000.0*1024.0*1024.0*1024.0)
-			snprintf(buf, len, "%.0fGibit", tmp/(1024.0*1024.0*1024.0));
-		else if (tmp >= 1000.0*1024.0*1024.0)
-			snprintf(buf, len, "%.0fMibit", tmp/(1024.0*1024.0));
-		else if (tmp >= 1000.0*1024)
-			snprintf(buf, len, "%.0fKibit", tmp/1024);
-		else
-			snprintf(buf, len, "%.0fbit", tmp);
-	} else {
-		if (tmp >= 1000.0*1000000000.0)
-			snprintf(buf, len, "%.0fGbit", tmp/1000000000.0);
-		else if (tmp >= 1000.0*1000000.0)
-			snprintf(buf, len, "%.0fMbit", tmp/1000000.0);
-		else if (tmp >= 1000.0 * 1000.0)
-			snprintf(buf, len, "%.0fKbit", tmp/1000.0);
-		else
-			snprintf(buf, len, "%.0fbit",  tmp);
+	rate <<= 3; /* bytes/sec -> bits/sec */
+
+	for (i = 0; i < ARRAY_SIZE(units); i++)  {
+		if (rate < kilo)
+			break;
+		if (((rate % kilo) != 0) && rate < 1000*kilo)
+			break;
+		rate /= kilo;
 	}
+	snprintf(buf, len, "%.0f%s%sbit", (double)rate, units[i], str);
 }
 
 char * sprint_rate(__u64 rate, char *buf)

^ permalink raw reply related

* Re: [PATCH] net: rework recvmsg handler msg_name and msg_namelen logic
From: Hannes Frederic Sowa @ 2013-11-22  6:45 UTC (permalink / raw)
  To: David Miller; +Cc: eric.dumazet, vyasevich, netdev
In-Reply-To: <20131121.125707.653753874005080724.davem@davemloft.net>

On Thu, Nov 21, 2013 at 12:57:07PM -0500, David Miller wrote:
> From: Eric Dumazet <eric.dumazet@gmail.com>
> Date: Thu, 21 Nov 2013 07:00:14 -0800
> 
> > So a protocol should use BUILD_BUG_ON() to make sure sockaddr_storage is
> > big enough.
> 
> Hannes mentioned trying to do this, somehow, automatically.  Best I could
> come up with is something like:
> 
> #define DECLARE_RECVMSG_HANDLER(name, ..., sockaddr_type) \
> static ... __name(...); \
> static ... name(...)	\
> {	\
> 	BUILD_BUG_ON(sizeof(sockaddr_type) > sizeof(sockaddr_storage); \
> 	__name(...); \
> } \
> static ... __name(...)
> 
> And then the protocols go:
> 
> DECLARE_RECVMSG_HANDLER(udp_recvmsg, ..., struct sockaddr_in)
> {
> 	struct inet_sock *inet = inet_sk(sk);
> 	struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name;
>  ...
> 
> You get the idea.
> 
> Slightly convoluted, and we can do something special with types or the
> prot ops member name to enforce usage of the macro.

Actually we already have a simpler solution in the tree:

#define __sockaddr_check_size(size)     \
        BUILD_BUG_ON(((size) > sizeof(struct __kernel_sockaddr_storage)))

and

#define DECLARE_SOCKADDR(type, dst, src)        \
        type dst = ({ __sockaddr_check_size(sizeof(*dst)); (type) src; })

Unfortunately I missed it before (it only gets used in the getname functions).
So, some checks are already in place (af_packet, af_inet, llcp_sock, af_unix
and af_netlink).

I still want to explore my idea regarding coccinelle or sparse. Checking
these with sparse should be relatively straightforward. We would just
have to lift the msg_name pointer into its own address_space universe
and add a __force to the cast in DECLARE_SOCKADDR. But because sparse
errors are already high in numbers I fear it will be simply overlooked.

I'll want to test if a coccicheck is reasonable, too.

Will cook something up soon.

Greetings,

  Hannes

^ permalink raw reply

* [PATCH] tcp_memcg: remove useless var old_lim
From: Gao feng @ 2013-11-22  6:48 UTC (permalink / raw)
  To: netdev; +Cc: glommer, Gao feng

nobody needs it. remove.

Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
---
 net/ipv4/tcp_memcontrol.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/net/ipv4/tcp_memcontrol.c b/net/ipv4/tcp_memcontrol.c
index 03e9154..269a89e 100644
--- a/net/ipv4/tcp_memcontrol.c
+++ b/net/ipv4/tcp_memcontrol.c
@@ -60,7 +60,6 @@ EXPORT_SYMBOL(tcp_destroy_cgroup);
 static int tcp_update_limit(struct mem_cgroup *memcg, u64 val)
 {
 	struct cg_proto *cg_proto;
-	u64 old_lim;
 	int i;
 	int ret;
 
@@ -71,7 +70,6 @@ static int tcp_update_limit(struct mem_cgroup *memcg, u64 val)
 	if (val > RES_COUNTER_MAX)
 		val = RES_COUNTER_MAX;
 
-	old_lim = res_counter_read_u64(&cg_proto->memory_allocated, RES_LIMIT);
 	ret = res_counter_set_limit(&cg_proto->memory_allocated, val);
 	if (ret)
 		return ret;
-- 
1.8.3.1

^ permalink raw reply related

* Re: [PATCH linux-next] hisax: disable build for big-endian arm
From: Takashi Iwai @ 2013-11-22  7:29 UTC (permalink / raw)
  To: Vincent Stehlé; +Cc: netdev, linux-kernel, linux-next, Karsten Keil
In-Reply-To: <1385077794-17022-1-git-send-email-vincent.stehle@laposte.net>

At Fri, 22 Nov 2013 00:49:54 +0100,
Vincent Stehlé wrote:
> 
> Teles PCI and HFC PCI-bus refuse to build on big-endian ARM; disable them in
> Kconfig.
> 
> Signed-off-by: Vincent Stehlé <vincent.stehle@laposte.net>
> Cc: Karsten Keil <isdn@linux-pingi.de>
> ---
> 
> Hi,
> 
> This can be seen on e.g. linux next-20131121 with arm allyesconfig.
> 
> Best regards,
> 
> V.
> 
>  drivers/isdn/hisax/Kconfig | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/isdn/hisax/Kconfig b/drivers/isdn/hisax/Kconfig
> index d9edcc9..53dbb75 100644
> --- a/drivers/isdn/hisax/Kconfig
> +++ b/drivers/isdn/hisax/Kconfig
> @@ -109,7 +109,7 @@ config HISAX_16_3
>  
>  config HISAX_TELESPCI
>  	bool "Teles PCI"
> -	depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV || (XTENSA && !CPU_LITTLE_ENDIAN)))
> +	depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV || (XTENSA && !CPU_LITTLE_ENDIAN) || (ARM && !CPU_LITTLE_ENDIAN)))

Isn't it a bit better to exclude CPU_LITTLE_ENDIAN globally?

	depends on PCI && CPU_LITTLE_ENDIAN && (BROKEN || !(SPARC || PPC || PARISC || M68K || MIPS || FRV || XTENSA || ARM))

Or maybe just

	depends on PCI && (X86 || BROKEN)

(Alpha?  Can anyone test? :)


Takashi

^ permalink raw reply

* Re: [PATCH linux-next] hisax: disable build for big-endian arm
From: Karsten Keil @ 2013-11-22  7:45 UTC (permalink / raw)
  To: Takashi Iwai
  Cc: Vincent Stehlé, netdev, linux-kernel, linux-next,
	Karsten Keil
In-Reply-To: <s5hzjowhp2l.wl%tiwai@suse.de>

Am 22.11.2013 08:29, schrieb Takashi Iwai:
> At Fri, 22 Nov 2013 00:49:54 +0100,
> Vincent Stehlé wrote:
>>
>> Teles PCI and HFC PCI-bus refuse to build on big-endian ARM; disable them in
>> Kconfig.
>>
>> Signed-off-by: Vincent Stehlé <vincent.stehle@laposte.net>
>> Cc: Karsten Keil <isdn@linux-pingi.de>
>> ---
>>
>> Hi,
>>
>> This can be seen on e.g. linux next-20131121 with arm allyesconfig.
>>
>> Best regards,
>>
>> V.
>>
>>  drivers/isdn/hisax/Kconfig | 4 ++--
>>  1 file changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/isdn/hisax/Kconfig b/drivers/isdn/hisax/Kconfig
>> index d9edcc9..53dbb75 100644
>> --- a/drivers/isdn/hisax/Kconfig
>> +++ b/drivers/isdn/hisax/Kconfig
>> @@ -109,7 +109,7 @@ config HISAX_16_3
>>  
>>  config HISAX_TELESPCI
>>  	bool "Teles PCI"
>> -	depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV || (XTENSA && !CPU_LITTLE_ENDIAN)))
>> +	depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV || (XTENSA && !CPU_LITTLE_ENDIAN) || (ARM && !CPU_LITTLE_ENDIAN)))
> 
> Isn't it a bit better to exclude CPU_LITTLE_ENDIAN globally?
> 
> 	depends on PCI && CPU_LITTLE_ENDIAN && (BROKEN || !(SPARC || PPC || PARISC || M68K || MIPS || FRV || XTENSA || ARM))
> 
> Or maybe just
> 
> 	depends on PCI && (X86 || BROKEN)
> 
> (Alpha?  Can anyone test? :)

I never got this card so it was never in my tests, if I remember
correctely  somebody had it running with Alpha before 2000.
And yes I'm fine if we simplify this mess to only X86.

Karsten

^ permalink raw reply

* DO YOU NEED BUSINESS AND PERSONAL LOAN
From: ''Hyde Loan Finance Company @ 2013-11-22  7:44 UTC (permalink / raw)
  To: Recipients

Loans available at 3%.Contact us for more info if interested.Serious minded only.Contact us Via Email: hydenance@gmail.com

^ permalink raw reply

* [PATCH] net: sctp: set chunk->tsn_gap_acked at the end of cycle
From: Chang Xiangzhong @ 2013-11-22  7:49 UTC (permalink / raw)
  To: vyasevich, nhorman, davem
  Cc: linux-sctp, netdev, linux-kernel, Chang Xiangzhong

tsn_gap_acked is an important state flag in chunk, which indicates if the
chunk has been acked in gap reports before. SFR-CACC algorithm depends on this
variable. So set this at the end of each iteration, otherwise the SFR-CACC
algorithm would never be toggled.

Signed-off-by: Chang Xiangzhong <changxiangzhong@gmail.com>
---
 net/sctp/outqueue.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index 1b494fa..bff828c 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -1396,7 +1396,6 @@ static void sctp_check_transmitted(struct sctp_outq *q,
 			 * while DATA was outstanding).
 			 */
 			if (!tchunk->tsn_gap_acked) {
-				tchunk->tsn_gap_acked = 1;
 				if (TSN_lt(*highest_new_tsn_in_sack, tsn))
 					*highest_new_tsn_in_sack = tsn;
 				bytes_acked += sctp_data_size(tchunk);
@@ -1460,6 +1459,8 @@ static void sctp_check_transmitted(struct sctp_outq *q,
 				 */
 				list_add_tail(lchunk, &tlist);
 			}
+
+			tchunk->tsn_gap_acked = 1;
 		} else {
 			if (tchunk->tsn_gap_acked) {
 				pr_debug("%s: receiver reneged on data TSN:0x%x\n",
-- 
1.8.4.3

^ permalink raw reply related

* [PATCH 1/1] e1000: prevent oops when adapter is being closed and reset simultaneously
From: yzhu1 @ 2013-11-22  7:54 UTC (permalink / raw)
  To: linux-kernel, netdev, zhuyj

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

Hi, maintainers

This change is based on a similar change made to e1000e support in
commit bb9e44d0d0f4 ("e1000e: prevent oops when adapter is being closed
and reset simultaneously").  The same issue has also been observed
on the older e1000 cards.

Here, we have increased the RESET_COUNT value to 50 because there are too
many accesses to e1000 nic on stress tests to e1000 nic, it is not enough
to set RESET_COUT 25. Experimentation has shown that it is enough to set
RESET_COUNT 50.

Please help me to merge this patch. Thanks a lot.

Zhu Yanjun

[-- Attachment #2: 0001-e1000-prevent-oops-when-adapter-is-being-closed-and-.patch --]
[-- Type: text/x-patch, Size: 2463 bytes --]

>From 54e9e48a9f878eb45f0cc6322415244d7a9f1598 Mon Sep 17 00:00:00 2001
From: yzhu1 <yanjun.zhu@windriver.com>
Date: Fri, 22 Nov 2013 15:46:48 +0800
Subject: [PATCH 1/1] e1000: prevent oops when adapter is being closed and
 reset simultaneously

This change is based on a similar change made to e1000e support in
commit bb9e44d0d0f4 ("e1000e: prevent oops when adapter is being closed
and reset simultaneously").  The same issue has also been observed
on the older e1000 cards.

Here, we have increased the RESET_COUNT value to 50 because there are too
many accesses to e1000 nic on stress tests to e1000 nic, it is not enough
to set RESET_COUT 25. Experimentation has shown that it is enough to set
RESET_COUNT 50.

Signed-off-by: yzhu1 <yanjun.zhu@windriver.com>
---
 drivers/net/ethernet/intel/e1000/e1000.h      |    5 +++++
 drivers/net/ethernet/intel/e1000/e1000_main.c |    9 +++++++++
 2 files changed, 14 insertions(+)

diff --git a/drivers/net/ethernet/intel/e1000/e1000.h b/drivers/net/ethernet/intel/e1000/e1000.h
index 58c1472..0af4a8e 100644
--- a/drivers/net/ethernet/intel/e1000/e1000.h
+++ b/drivers/net/ethernet/intel/e1000/e1000.h
@@ -83,6 +83,11 @@ struct e1000_adapter;
 
 #define E1000_MAX_INTR			10
 
+/*
+ * Count for polling __E1000_RESET condition every 10-20msec.
+ */
+#define E1000_CHECK_RESET_COUNT         50
+
 /* TX/RX descriptor defines */
 #define E1000_DEFAULT_TXD		256
 #define E1000_MAX_TXD			256
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
index e386228..c0f5217 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -1440,6 +1440,10 @@ static int e1000_close(struct net_device *netdev)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
+	int count = E1000_CHECK_RESET_COUNT;
+
+	while (test_bit(__E1000_RESETTING, &adapter->flags) && count--)
+		usleep_range(10000, 20000);
 
 	WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags));
 	e1000_down(adapter);
@@ -4963,6 +4967,11 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)
 	netif_device_detach(netdev);
 
 	if (netif_running(netdev)) {
+		int count = E1000_CHECK_RESET_COUNT;
+
+		while (test_bit(__E1000_RESETTING, &adapter->flags) && count--)
+			usleep_range(10000, 20000);
+
 		WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags));
 		e1000_down(adapter);
 	}
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH] tipc: fix a lockdep warning
From: wangweidong @ 2013-11-22  8:18 UTC (permalink / raw)
  To: jon.maloy, allan.stephens, davem; +Cc: dingtianhong, netdev, tipc-discussion

PC1:tipc-config -netid=1234 -a=1.1.2 -be=eth:eth0/1.1.0
PC2:tipc-config -netid=1234 -a=1.1.3 -be=eth:eth0/1.1.0

I used a server code Like this:
----------------
    sk=socket(AF_TIPC,SOCK_RDM,0);
    bind(sk, &addr, len);
    while(1) {
        recvfrom(sk,...);
        ...
        sendto(sk,...);
    }
----------------

when I did ./server in PC1, I got a lockdep as bellow:

======================================================
[ INFO: possible circular locking dependency detected ]
3.12.0-lockdep+ #4 Not tainted
-------------------------------------------------------
server/3772 is trying to acquire lock:
(tipc_net_lock){++.-..}, at: [<ffffffffa02e324f>] tipc_link_send+0x2f/0xc0 [tipc]

but task is already holding lock:
(tipc_nametbl_lock){++--..}, at: [<ffffffffa02e83e6>] tipc_nametbl_publish+0x46/0xc0 [tipc]
 which lock already depends on the new lock.

the existing dependency chain (in reverse order) is:
 -> #1 (tipc_nametbl_lock){++--..}:
        [<ffffffff810a2547>] validate_chain+0x6a7/0x7d0
        [<ffffffff810a29d1>] __lock_acquire+0x361/0x610
        [<ffffffff810a2d62>] lock_acquire+0xe2/0x110
        [<ffffffff8151e061>] _raw_write_lock_bh+0x31/0x40
        [<ffffffffa02e5d40>] tipc_named_reinit+0x10/0x70 [tipc]
        [<ffffffffa02e8512>] tipc_net_start+0x22/0x80 [tipc]
        [<ffffffffa02dff0e>] tipc_core_start_net+0xe/0x40 [tipc]
        [<ffffffffa02df625>] cfg_set_own_addr+0x75/0xc0 [tipc]
        [<ffffffffa02df8f5>] tipc_cfg_do_cmd+0x135/0x550 [tipc]
        [<ffffffffa02e87f9>] handle_cmd+0x49/0xe0 [tipc]
        [<ffffffff814764fd>] genl_family_rcv_msg+0x22d/0x3c0
        [<ffffffff81476700>] genl_rcv_msg+0x70/0xd0
        [<ffffffff81474dc9>] netlink_rcv_skb+0x89/0xb0
        [<ffffffff81475f87>] genl_rcv+0x27/0x40
        [<ffffffff81474b1e>] netlink_unicast+0x14e/0x1a0
        [<ffffffff81475735>] netlink_sendmsg+0x245/0x420
        [<ffffffff814294f6>] __sock_sendmsg+0x66/0x80
        [<ffffffff814295c2>] sock_aio_write+0xb2/0xc0
        [<ffffffff811968f0>] do_sync_write+0x60/0x90
        [<ffffffff81198891>] vfs_write+0x1d1/0x1e0
        [<ffffffff811989bd>] SyS_write+0x5d/0xa0
        [<ffffffff81527522>] system_call_fastpath+0x16/0x1b

 -> #0 (tipc_net_lock){++.-..}:
        [<ffffffff810a1e2e>] check_prev_add+0x41e/0x490
        [<ffffffff810a2547>] validate_chain+0x6a7/0x7d0
        [<ffffffff810a29d1>] __lock_acquire+0x361/0x610
        [<ffffffff810a2d62>] lock_acquire+0xe2/0x110
        [<ffffffff8151e2f4>] _raw_read_lock_bh+0x34/0x50
        [<ffffffffa02e324f>] tipc_link_send+0x2f/0xc0 [tipc]
        [<ffffffffa02e617b>] named_cluster_distribute+0x6b/0x80 [tipc]
        [<ffffffffa02e62ab>] tipc_named_publish+0x7b/0x90 [tipc]
        [<ffffffffa02e841b>] tipc_nametbl_publish+0x7b/0xc0 [tipc]
        [<ffffffffa02e9958>] tipc_publish+0x98/0xf0 [tipc]
        [<ffffffffa02ebf58>] bind+0x78/0xb0 [tipc]
        [<ffffffff81428dc0>] SyS_bind+0xb0/0xd0
        [<ffffffff81527522>] system_call_fastpath+0x16/0x1b

 other info that might help us debug this:

  Possible unsafe locking scenario:

        CPU0                    CPU1
        ----                    ----
   lock(tipc_nametbl_lock);
                                lock(tipc_net_lock);
                                lock(tipc_nametbl_lock);
   lock(tipc_net_lock);

  *** DEADLOCK ***
----------------------------------------------------------

problem is that tipc_nametbl_publish which will hold tipc_nametbl_lock
and acquire tipc_net_lock, while the tipc_net_start which hold
tipc_net_lock and acquir tipc_nametbl_lock, so the dead lock occurs.

tipc_link_send protected by tipc_net_lock, we can unlock the
tipc_nametbl_lock, and it no need the tipc_nametbl_lock to protect it.
so I just unlock the tbl_lock before it, and lock the tbl_lock after it.

Signed-off-by: Wang Weidong <wangweidong1@huawei.com>
---
 net/tipc/name_distr.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c
index e0d0805..ab8f96c 100644
--- a/net/tipc/name_distr.c
+++ b/net/tipc/name_distr.c
@@ -138,7 +138,9 @@ static void named_cluster_distribute(struct sk_buff *buf)
 			if (!buf_copy)
 				break;
 			msg_set_destnode(buf_msg(buf_copy), n_ptr->addr);
+			write_unlock_bh(&tipc_nametbl_lock);
 			tipc_link_send(buf_copy, n_ptr->addr, n_ptr->addr);
+			write_lock_bh(&tipc_nametbl_lock);
 		}
 	}
 
-- 
1.7.12

^ permalink raw reply related

* [PATCH 1/2] e1000: fix lockdep warning in e1000_reset_task
From: Vladimir Davydov @ 2013-11-22  8:20 UTC (permalink / raw)
  To: Jesse Brandeburg, Jeff Kirsher
  Cc: David S. Miller, e1000-devel, netdev, linux-kernel,
	Patrick McHardy, devel

The patch fixes the following lockdep warning, which is 100%
reproducible on network restart:

======================================================
[ INFO: possible circular locking dependency detected ]
3.12.0+ #47 Tainted: GF
-------------------------------------------------------
kworker/1:1/27 is trying to acquire lock:
 ((&(&adapter->watchdog_task)->work)){+.+...}, at: [<ffffffff8108a5b0>] flush_work+0x0/0x70

but task is already holding lock:
 (&adapter->mutex){+.+...}, at: [<ffffffffa0177c0a>] e1000_reset_task+0x4a/0xa0 [e1000]

which lock already depends on the new lock.

the existing dependency chain (in reverse order) is:

-> #1 (&adapter->mutex){+.+...}:
       [<ffffffff810bdb5d>] lock_acquire+0x9d/0x120
       [<ffffffff816b8cbc>] mutex_lock_nested+0x4c/0x390
       [<ffffffffa017233d>] e1000_watchdog+0x7d/0x5b0 [e1000]
       [<ffffffff8108b972>] process_one_work+0x1d2/0x510
       [<ffffffff8108ca80>] worker_thread+0x120/0x3a0
       [<ffffffff81092c1e>] kthread+0xee/0x110
       [<ffffffff816c3d7c>] ret_from_fork+0x7c/0xb0

-> #0 ((&(&adapter->watchdog_task)->work)){+.+...}:
       [<ffffffff810bd9c0>] __lock_acquire+0x1710/0x1810
       [<ffffffff810bdb5d>] lock_acquire+0x9d/0x120
       [<ffffffff8108a5eb>] flush_work+0x3b/0x70
       [<ffffffff8108b5d8>] __cancel_work_timer+0x98/0x140
       [<ffffffff8108b693>] cancel_delayed_work_sync+0x13/0x20
       [<ffffffffa0170cec>] e1000_down_and_stop+0x3c/0x60 [e1000]
       [<ffffffffa01775b1>] e1000_down+0x131/0x220 [e1000]
       [<ffffffffa0177c12>] e1000_reset_task+0x52/0xa0 [e1000]
       [<ffffffff8108b972>] process_one_work+0x1d2/0x510
       [<ffffffff8108ca80>] worker_thread+0x120/0x3a0
       [<ffffffff81092c1e>] kthread+0xee/0x110
       [<ffffffff816c3d7c>] ret_from_fork+0x7c/0xb0

other info that might help us debug this:

 Possible unsafe locking scenario:

       CPU0                    CPU1
       ----                    ----
  lock(&adapter->mutex);
                               lock((&(&adapter->watchdog_task)->work));
                               lock(&adapter->mutex);
  lock((&(&adapter->watchdog_task)->work));

 *** DEADLOCK ***

3 locks held by kworker/1:1/27:
 #0:  (events){.+.+.+}, at: [<ffffffff8108b906>] process_one_work+0x166/0x510
 #1:  ((&adapter->reset_task)){+.+...}, at: [<ffffffff8108b906>] process_one_work+0x166/0x510
 #2:  (&adapter->mutex){+.+...}, at: [<ffffffffa0177c0a>] e1000_reset_task+0x4a/0xa0 [e1000]

stack backtrace:
CPU: 1 PID: 27 Comm: kworker/1:1 Tainted: GF            3.12.0+ #47
Hardware name: System manufacturer System Product Name/P5B-VM SE, BIOS 0501    05/31/2007
Workqueue: events e1000_reset_task [e1000]
 ffffffff820f6000 ffff88007b9dba98 ffffffff816b54a2 0000000000000002
 ffffffff820f5e50 ffff88007b9dbae8 ffffffff810ba936 ffff88007b9dbac8
 ffff88007b9dbb48 ffff88007b9d8f00 ffff88007b9d8780 ffff88007b9d8f00
Call Trace:
 [<ffffffff816b54a2>] dump_stack+0x49/0x5f
 [<ffffffff810ba936>] print_circular_bug+0x216/0x310
 [<ffffffff810bd9c0>] __lock_acquire+0x1710/0x1810
 [<ffffffff8108a5b0>] ? __flush_work+0x250/0x250
 [<ffffffff810bdb5d>] lock_acquire+0x9d/0x120
 [<ffffffff8108a5b0>] ? __flush_work+0x250/0x250
 [<ffffffff8108a5eb>] flush_work+0x3b/0x70
 [<ffffffff8108a5b0>] ? __flush_work+0x250/0x250
 [<ffffffff8108b5d8>] __cancel_work_timer+0x98/0x140
 [<ffffffff8108b693>] cancel_delayed_work_sync+0x13/0x20
 [<ffffffffa0170cec>] e1000_down_and_stop+0x3c/0x60 [e1000]
 [<ffffffffa01775b1>] e1000_down+0x131/0x220 [e1000]
 [<ffffffffa0177c12>] e1000_reset_task+0x52/0xa0 [e1000]
 [<ffffffff8108b972>] process_one_work+0x1d2/0x510
 [<ffffffff8108b906>] ? process_one_work+0x166/0x510
 [<ffffffff8108ca80>] worker_thread+0x120/0x3a0
 [<ffffffff8108c960>] ? manage_workers+0x2c0/0x2c0
 [<ffffffff81092c1e>] kthread+0xee/0x110
 [<ffffffff81092b30>] ? __init_kthread_worker+0x70/0x70
 [<ffffffff816c3d7c>] ret_from_fork+0x7c/0xb0
 [<ffffffff81092b30>] ? __init_kthread_worker+0x70/0x70

== The issue background ==

The problem occurs, because e1000_down(), which is called under
adapter->mutex by e1000_reset_task(), tries to synchronously cancel
e1000 auxiliary works (reset_task, watchdog_task, phy_info_task,
fifo_stall_task), which take adapter->mutex in their handlers. So the
question is what does adapter->mutex protect there?

The adapter->mutex was introduced by commit 0ef4ee ("e1000: convert to
private mutex from rtnl") as a replacement for rtnl_lock() taken in the
asynchronous handlers. It targeted on fixing a similar lockdep warning
issued when e1000_down() was called under rtnl_lock(), and it fixed it,
but unfortunately it introduced the lockdep warning described above.
Anyway, that said the source of this bug is that the asynchronous works
were made to take rtnl_lock() some time ago, so let's look deeper and
find why it was added there.

The rtnl_lock() was added to asynchronous handlers by commit 338c15
("e1000: fix occasional panic on unload") in order to prevent
asynchronous handlers from execution after the module is unloaded
(e1000_down() is called) as it follows from the comment to the commit:

> Net drivers in general have an issue where timers fired
> by mod_timer or work threads with schedule_work are running
> outside of the rtnl_lock.
>
> With no other lock protection these routines are vulnerable
> to races with driver unload or reset paths.
>
> The longer term solution to this might be a redesign with
> safer locks being taken in the driver to guarantee no
> reentrance, but for now a safe and effective fix is
> to take the rtnl_lock in these routines.

I'm not sure if this locking scheme fixed the problem or just made it
unlikely, although I incline to the latter. Anyway, this was long time
ago when e1000 auxiliary works were implemented as timers scheduling
real work handlers in their routines. The e1000_down() function only
canceled the timers, but left the real handlers running if they were
running, which could result in work execution after module unload.
Today, the e1000 driver uses sane delayed works instead of the pair
timer+work to implement its delayed asynchronous handlers, and the
e1000_down() synchronously cancels all the works so that the problem
that commit 338c15 tried to cope with disappeared, and we don't need any
locks in the handlers any more. Moreover, any locking there can
potentially result in a deadlock.

So, this patch reverts commits 0ef4ee and 338c15.

Signed-off-by: Vladimir Davydov <vdavydov@parallels.com>
Cc: Tushar Dave <tushar.n.dave@intel.com>
Cc: Patrick McHardy <kaber@trash.net>
Cc: David S. Miller <davem@davemloft.net>
---
 drivers/net/ethernet/intel/e1000/e1000.h      |    2 --
 drivers/net/ethernet/intel/e1000/e1000_main.c |   36 +++----------------------
 2 files changed, 3 insertions(+), 35 deletions(-)

diff --git a/drivers/net/ethernet/intel/e1000/e1000.h b/drivers/net/ethernet/intel/e1000/e1000.h
index 58c1472..8b0b97d 100644
--- a/drivers/net/ethernet/intel/e1000/e1000.h
+++ b/drivers/net/ethernet/intel/e1000/e1000.h
@@ -312,8 +312,6 @@ struct e1000_adapter {
 	struct delayed_work watchdog_task;
 	struct delayed_work fifo_stall_task;
 	struct delayed_work phy_info_task;
-
-	struct mutex mutex;
 };
 
 enum e1000_state_t {
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
index ad6800a..ca0723f 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -544,21 +544,8 @@ void e1000_down(struct e1000_adapter *adapter)
 	e1000_clean_all_rx_rings(adapter);
 }
 
-static void e1000_reinit_safe(struct e1000_adapter *adapter)
-{
-	while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
-		msleep(1);
-	mutex_lock(&adapter->mutex);
-	e1000_down(adapter);
-	e1000_up(adapter);
-	mutex_unlock(&adapter->mutex);
-	clear_bit(__E1000_RESETTING, &adapter->flags);
-}
-
 void e1000_reinit_locked(struct e1000_adapter *adapter)
 {
-	/* if rtnl_lock is not held the call path is bogus */
-	ASSERT_RTNL();
 	WARN_ON(in_interrupt());
 	while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
 		msleep(1);
@@ -1321,7 +1308,6 @@ static int e1000_sw_init(struct e1000_adapter *adapter)
 	e1000_irq_disable(adapter);
 
 	spin_lock_init(&adapter->stats_lock);
-	mutex_init(&adapter->mutex);
 
 	set_bit(__E1000_DOWN, &adapter->flags);
 
@@ -2330,11 +2316,8 @@ static void e1000_update_phy_info_task(struct work_struct *work)
 	struct e1000_adapter *adapter = container_of(work,
 						     struct e1000_adapter,
 						     phy_info_task.work);
-	if (test_bit(__E1000_DOWN, &adapter->flags))
-		return;
-	mutex_lock(&adapter->mutex);
+
 	e1000_phy_get_info(&adapter->hw, &adapter->phy_info);
-	mutex_unlock(&adapter->mutex);
 }
 
 /**
@@ -2350,9 +2333,6 @@ static void e1000_82547_tx_fifo_stall_task(struct work_struct *work)
 	struct net_device *netdev = adapter->netdev;
 	u32 tctl;
 
-	if (test_bit(__E1000_DOWN, &adapter->flags))
-		return;
-	mutex_lock(&adapter->mutex);
 	if (atomic_read(&adapter->tx_fifo_stall)) {
 		if ((er32(TDT) == er32(TDH)) &&
 		   (er32(TDFT) == er32(TDFH)) &&
@@ -2373,7 +2353,6 @@ static void e1000_82547_tx_fifo_stall_task(struct work_struct *work)
 			schedule_delayed_work(&adapter->fifo_stall_task, 1);
 		}
 	}
-	mutex_unlock(&adapter->mutex);
 }
 
 bool e1000_has_link(struct e1000_adapter *adapter)
@@ -2427,10 +2406,6 @@ static void e1000_watchdog(struct work_struct *work)
 	struct e1000_tx_ring *txdr = adapter->tx_ring;
 	u32 link, tctl;
 
-	if (test_bit(__E1000_DOWN, &adapter->flags))
-		return;
-
-	mutex_lock(&adapter->mutex);
 	link = e1000_has_link(adapter);
 	if ((netif_carrier_ok(netdev)) && link)
 		goto link_up;
@@ -2521,7 +2496,7 @@ link_up:
 			adapter->tx_timeout_count++;
 			schedule_work(&adapter->reset_task);
 			/* exit immediately since reset is imminent */
-			goto unlock;
+			return;
 		}
 	}
 
@@ -2549,9 +2524,6 @@ link_up:
 	/* Reschedule the task */
 	if (!test_bit(__E1000_DOWN, &adapter->flags))
 		schedule_delayed_work(&adapter->watchdog_task, 2 * HZ);
-
-unlock:
-	mutex_unlock(&adapter->mutex);
 }
 
 enum latency_range {
@@ -3500,10 +3472,8 @@ static void e1000_reset_task(struct work_struct *work)
 	struct e1000_adapter *adapter =
 		container_of(work, struct e1000_adapter, reset_task);
 
-	if (test_bit(__E1000_DOWN, &adapter->flags))
-		return;
 	e_err(drv, "Reset adapter\n");
-	e1000_reinit_safe(adapter);
+	e1000_reinit_locked(adapter);
 }
 
 /**
-- 
1.7.10.4


------------------------------------------------------------------------------
Shape the Mobile Experience: Free Subscription
Software experts and developers: Be at the forefront of tech innovation.
Intel(R) Software Adrenaline delivers strategic insight and game-changing 
conversations that shape the rapidly evolving mobile landscape. Sign up now. 
http://pubads.g.doubleclick.net/gampad/clk?id=63431311&iu=/4140/ostg.clktrk
_______________________________________________
E1000-devel mailing list
E1000-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/e1000-devel
To learn more about Intel&#174; Ethernet, visit http://communities.intel.com/community/wired

^ permalink raw reply related

* [PATCH 2/2] e1000: fix possible reset_task running after adapter down
From: Vladimir Davydov @ 2013-11-22  8:20 UTC (permalink / raw)
  To: Jesse Brandeburg, Jeff Kirsher
  Cc: e1000-devel, netdev, linux-kernel, devel, Tushar Dave,
	Patrick McHardy, David S. Miller
In-Reply-To: <0555e8c422c9d920758399edfa08f72df9120713.1385107870.git.vdavydov@parallels.com>

On e1000_down(), we should ensure every asynchronous work is canceled
before proceeding. Since the watchdog_task can schedule other works
apart from itself, it should be stopped first, but currently it is
stopped after the reset_task. This can result in the following race
leading to the reset_task running after the module unload:

e1000_down_and_stop():			e1000_watchdog():
----------------------			-----------------

cancel_work_sync(reset_task)
					schedule_work(reset_task)
cancel_delayed_work_sync(watchdog_task)

The patch moves cancel_delayed_work_sync(watchdog_task) at the beginning
of e1000_down_and_stop() thus ensuring the race is impossible.

Signed-off-by: Vladimir Davydov <vdavydov@parallels.com>
Cc: Tushar Dave <tushar.n.dave@intel.com>
Cc: Patrick McHardy <kaber@trash.net>
Cc: David S. Miller <davem@davemloft.net>
---
 drivers/net/ethernet/intel/e1000/e1000_main.c |   15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
index ca0723f..2d914de 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -494,13 +494,20 @@ static void e1000_down_and_stop(struct e1000_adapter *adapter)
 {
 	set_bit(__E1000_DOWN, &adapter->flags);
 
-	/* Only kill reset task if adapter is not resetting */
-	if (!test_bit(__E1000_RESETTING, &adapter->flags))
-		cancel_work_sync(&adapter->reset_task);
-
 	cancel_delayed_work_sync(&adapter->watchdog_task);
+
+	/*
+	 * Since the watchdog task can reschedule other tasks, we should cancel
+	 * it first, otherwise we can run into the situation when a work is
+	 * still running after the adapter has been turned down.
+	 */
+
 	cancel_delayed_work_sync(&adapter->phy_info_task);
 	cancel_delayed_work_sync(&adapter->fifo_stall_task);
+
+	/* Only kill reset task if adapter is not resetting */
+	if (!test_bit(__E1000_RESETTING, &adapter->flags))
+		cancel_work_sync(&adapter->reset_task);
 }
 
 void e1000_down(struct e1000_adapter *adapter)
-- 
1.7.10.4

^ permalink raw reply related

* [Patch v2] IPv6: Fixed support for blackhole and prohibit routes
From: Kamala R @ 2013-11-22  8:21 UTC (permalink / raw)
  To: Hannes Frederic Sowa, netdev, David Miller; +Cc: linux-kernel, Kamala R

From: Kamala R <kamala@aristanetworks.com>

The behaviour of blackhole and prohibit routes has been corrected by setting
the input and output function pointers of the dst variable appropriately. For
blackhole routes, they are set to dst_discard and to ip6_pkt_prohibit and
ip6_pkt_prohbit_out respectively for prohibit routes.

Changes from v1: Logic is the same. Changes made for readability and so it
looks pleasing.

Signed-off-by: Kamala R <kamala@aristanetworks.com>
---
 net/ipv6/route.c |   11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index f54e3a1..d90b9ab 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1564,21 +1564,24 @@ int ip6_route_add(struct fib6_config *cfg)
 				goto out;
 			}
 		}
-		rt->dst.output = ip6_pkt_discard_out;
-		rt->dst.input = ip6_pkt_discard;
 		rt->rt6i_flags = RTF_REJECT|RTF_NONEXTHOP;
+		rt->dst.error = -ENETUNREACH;
 		switch (cfg->fc_type) {
 		case RTN_BLACKHOLE:
 			rt->dst.error = -EINVAL;
+			rt->dst.output = dst_discard;
+			rt->dst.input = dst_discard;
 			break;
 		case RTN_PROHIBIT:
 			rt->dst.error = -EACCES;
+			rt->dst.output = ip6_pkt_prohibit_out;
+			rt->dst.input = ip6_pkt_prohibit;
 			break;
 		case RTN_THROW:
 			rt->dst.error = -EAGAIN;
-			break;
 		default:
-			rt->dst.error = -ENETUNREACH;
+			rt->dst.output = ip6_pkt_discard_out;
+			rt->dst.input = ip6_pkt_discard;
 			break;
 		}
 		goto install_route;
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH] sctp: Restore 'resent' bit to avoid retransmitted chunks for RTT measurements
From: Xufeng Zhang @ 2013-11-22  8:30 UTC (permalink / raw)
  To: vyasevich, nhorman; +Cc: davem, linux-sctp, netdev, linux-kernel

From: Signed-off-by: Xufeng Zhang <xufeng.zhang@windriver.com>

Currently retransmitted DATA chunks could also be used for
RTT measurements since there are no flag to identify whether
the transmitted DATA chunk is a new one or a retransmitted one.
This problem is introduced by commit ae19c5486 ("sctp: remove
'resent' bit from the chunk") which inappropriately removed the
'resent' bit completely, instead of doing this, we should set 
the resent bit only for the retransmitted DATA chunks.

Signed-off-by: Xufeng Zhang <xufeng.zhang@windriver.com>
---
 include/net/sctp/structs.h |    1 +
 net/sctp/output.c          |   23 +++++++++++++----------
 net/sctp/outqueue.c        |    3 +++
 net/sctp/sm_make_chunk.c   |    1 +
 4 files changed, 18 insertions(+), 10 deletions(-)

diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 2174d8d..ea0ca5f 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -629,6 +629,7 @@ struct sctp_chunk {
 #define SCTP_NEED_FRTX 0x1
 #define SCTP_DONT_FRTX 0x2
 	__u16	rtt_in_progress:1,	/* This chunk used for RTT calc? */
+		resent:1,		/* Has this chunk ever been resent. */
 		has_tsn:1,		/* Does this chunk have a TSN yet? */
 		has_ssn:1,		/* Does this chunk have a SSN yet? */
 		singleton:1,		/* Only chunk in the packet? */
diff --git a/net/sctp/output.c b/net/sctp/output.c
index e650978..32c214d 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -467,17 +467,20 @@ int sctp_packet_transmit(struct sctp_packet *packet)
 	list_for_each_entry_safe(chunk, tmp, &packet->chunk_list, list) {
 		list_del_init(&chunk->list);
 		if (sctp_chunk_is_data(chunk)) {
-			/* 6.3.1 C4) When data is in flight and when allowed
-			 * by rule C5, a new RTT measurement MUST be made each
-			 * round trip.  Furthermore, new RTT measurements
-			 * SHOULD be made no more than once per round-trip
-			 * for a given destination transport address.
-			 */
-
-			if (!tp->rto_pending) {
-				chunk->rtt_in_progress = 1;
-				tp->rto_pending = 1;
+			if (!chunk->resent) {
+				/* 6.3.1 C4) When data is in flight and when allowed
+				 * by rule C5, a new RTT measurement MUST be made each
+				 * round trip.  Furthermore, new RTT measurements
+				 * SHOULD be made no more than once per round-trip
+				 * for a given destination transport address.
+				 */
+
+				if (!tp->rto_pending) {
+					chunk->rtt_in_progress = 1;
+					tp->rto_pending = 1;
+				}
 			}
+
 			has_data = 1;
 		}
 
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index 94df758..70f4f56 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -446,6 +446,8 @@ void sctp_retransmit_mark(struct sctp_outq *q,
 				transport->rto_pending = 0;
 			}
 
+			chunk->resent = 1;
+
 			/* Move the chunk to the retransmit queue. The chunks
 			 * on the retransmit queue are always kept in order.
 			 */
@@ -1375,6 +1377,7 @@ static void sctp_check_transmitted(struct sctp_outq *q,
 				 * instance).
 				 */
 				if (!tchunk->tsn_gap_acked &&
+				    !tchunk->resent &&
 				    tchunk->rtt_in_progress) {
 					tchunk->rtt_in_progress = 0;
 					rtt = jiffies - tchunk->sent_at;
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index fe69032..8fe89f8 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -1321,6 +1321,7 @@ struct sctp_chunk *sctp_chunkify(struct sk_buff *skb,
 	INIT_LIST_HEAD(&retval->list);
 	retval->skb		= skb;
 	retval->asoc		= (struct sctp_association *)asoc;
+	retval->resent          = 0;
 	retval->singleton	= 1;
 
 	retval->fast_retransmit = SCTP_CAN_FRTX;
-- 
1.7.0.2

^ permalink raw reply related

* Re: [PATCH] bonding: If IP route look-up to send an ARP fails, mark in bonding structure as no ARP sent.
From: rama nichanamatlu @ 2013-11-22  8:28 UTC (permalink / raw)
  To: Jay Vosburgh; +Cc: Veaceslav Falico, netdev
In-Reply-To: <8059.1385088224@death.nxdomain>

On 11/21/2013 6:43 PM, Jay Vosburgh wrote:
> rama nichanamatlu <rama.nichanamatlu@oracle.com> wrote:

>> Yes correct. Bonding primary param is set.
>> ex: primary=eth1 and primary_reselect=2.
>> Hence it is expected to be on primary on every reboot.
> 
> 	If I set up a basic bonding configuration like:
> 
Extremely thankful to U for investigating it to this extent.
Need to admit our test requirement here. Reboot test is done 300 times
and requirement is all 300 should see bond intf on primary upon boot.
What is observed is, reboot test never could achieve this until we put
this change.

> [ eth3, eth4 ] -> bond0 -> bond0.66, with primary=eth3 primary_reselect=2
> 
Our config is complex. Here (please ask if not clear):
First niC card  Intel 82599 sr-iov PF0 -> eth0 [dom0]
                                   VF0 -> eth1 [domU] ->
                                                        bond0 -> bond0.1
                                   VF0 -> eth2 [domU] ->
Second niC card Intel 82599 sr-iov PF0 -> eth1 [dom0]

PF = Physical Func
VF = Virtual  Func [are bond slaves]
XEN based OVM [Oracle]

2 arp targets configured.
A lan switch connected to *each* PF hosts a vlan arp target.

AFAIK sr-iov code (can get clarification from Donald/Keller sr-iov
owning team, as we did temp fix of another issue in intel sr-iov driver,
so we are connected) addition of vlan's to sr-iov functions is *as*
simple adding an entry into a table. That is they don't go thru a
re-init like an mtu change. Meaning the intf stays UP during that time.
*But* takes a little while as this table addition is done by PF driver
in dom0 upon request by domU VF driver as there is MBox communication.

> 	Then look at dmesg, I see this sequence:
> 
> 	The bond is set up first, with an arp_ip_target on a VLAN
> destination.  The slaves are added to the bond.
> 
> 	The VLAN interface is configured above the bond, and brought up.
> 
> 	The slaves become link up after autonegotiation, the ARP monitor
> commences, and eth3 is made the active slave.  Even if eth4 is set by
> the bond to be "link status up," eth3 becomes the active slave when it
> becomes "link status up."
> 
> 	What network device are you using for the slaves?  Are they
> virtualized devices of some kind?  My suspicion is that Ethernet
> autonegotiation either does not take place or occurs so quickly that the
> slaves are carrier up before the VLAN is even added.
> 
That is so correct of a guess.
We never saw a link loss message, neither nic driver nor bonding
reporting during vlan addition. Because as carrier is up bond has a
curr_active_slave hence tries to arp but fails as ip_route_output() fails.

> 	Can you check your dmesg output for the sequence of events?  In
> my test, I do not see the slaves go "NIC Link is Up 1000 Mbps Full
> Duplex" until about 3 seconds after the VLAN interface has been
> configured.
> 
so it means bonding driver would not have had a curr_active_slave for
almost 3 secs as none slave would have qualified to become so, hence
bonding never even would attempted to send an arp out.

What we observed is "no route to arp_ip_target" message.
We see 10 of them (5 pairs, as there 2 arp targets and arp interval is
200 msecs) lasting for a 1 sec, then no more error messages. With out
this fix, we would see that bonding failover messages in between those
messages. Eventually when arp'ing is working bonding would be on some
interface, need not be primary.  With this fix, we would not see those
bonding failover messages, and when arp'ing is working bond is on primary.

Requirement of this product being built is to achieve an extremely quick
failover, hence 200 msecs arp interval.

> 
> 	-J
> 
> ---
> 	-Jay Vosburgh, IBM Linux Technology Center, fubar@us.ibm.com

^ permalink raw reply

* Re: [PATCH] tipc: fix a lockdep warning
From: Ying Xue @ 2013-11-22  8:35 UTC (permalink / raw)
  To: wangweidong, jon.maloy, allan.stephens, davem,
	Paul.Gortmaker@windriver.com
  Cc: netdev, tipc-discussion, dingtianhong
In-Reply-To: <528F136E.1030506@huawei.com>

Hi Weidong,

I know you ever posted below patch into netdev mail list last month. And
at that moment I also told you we already had one better solution to fix
the issue. However, after our TIPC internal development team went
through a long and bitter dispute about that "better" solution, we
eventually made a consensus by proposing below approach to fix your met
issue:

http://thread.gmane.org/gmane.network.tipc.general/4926/

I think the patchset should be ready now.

Sorry for your inconvenience.

Regards,
Ying

On 11/22/2013 04:18 PM, wangweidong wrote:
> PC1:tipc-config -netid=1234 -a=1.1.2 -be=eth:eth0/1.1.0
> PC2:tipc-config -netid=1234 -a=1.1.3 -be=eth:eth0/1.1.0
> 
> I used a server code Like this:
> ----------------
>     sk=socket(AF_TIPC,SOCK_RDM,0);
>     bind(sk, &addr, len);
>     while(1) {
>         recvfrom(sk,...);
>         ...
>         sendto(sk,...);
>     }
> ----------------
> 
> when I did ./server in PC1, I got a lockdep as bellow:
> 
> ======================================================
> [ INFO: possible circular locking dependency detected ]
> 3.12.0-lockdep+ #4 Not tainted
> -------------------------------------------------------
> server/3772 is trying to acquire lock:
> (tipc_net_lock){++.-..}, at: [<ffffffffa02e324f>] tipc_link_send+0x2f/0xc0 [tipc]
> 
> but task is already holding lock:
> (tipc_nametbl_lock){++--..}, at: [<ffffffffa02e83e6>] tipc_nametbl_publish+0x46/0xc0 [tipc]
>  which lock already depends on the new lock.
> 
> the existing dependency chain (in reverse order) is:
>  -> #1 (tipc_nametbl_lock){++--..}:
>         [<ffffffff810a2547>] validate_chain+0x6a7/0x7d0
>         [<ffffffff810a29d1>] __lock_acquire+0x361/0x610
>         [<ffffffff810a2d62>] lock_acquire+0xe2/0x110
>         [<ffffffff8151e061>] _raw_write_lock_bh+0x31/0x40
>         [<ffffffffa02e5d40>] tipc_named_reinit+0x10/0x70 [tipc]
>         [<ffffffffa02e8512>] tipc_net_start+0x22/0x80 [tipc]
>         [<ffffffffa02dff0e>] tipc_core_start_net+0xe/0x40 [tipc]
>         [<ffffffffa02df625>] cfg_set_own_addr+0x75/0xc0 [tipc]
>         [<ffffffffa02df8f5>] tipc_cfg_do_cmd+0x135/0x550 [tipc]
>         [<ffffffffa02e87f9>] handle_cmd+0x49/0xe0 [tipc]
>         [<ffffffff814764fd>] genl_family_rcv_msg+0x22d/0x3c0
>         [<ffffffff81476700>] genl_rcv_msg+0x70/0xd0
>         [<ffffffff81474dc9>] netlink_rcv_skb+0x89/0xb0
>         [<ffffffff81475f87>] genl_rcv+0x27/0x40
>         [<ffffffff81474b1e>] netlink_unicast+0x14e/0x1a0
>         [<ffffffff81475735>] netlink_sendmsg+0x245/0x420
>         [<ffffffff814294f6>] __sock_sendmsg+0x66/0x80
>         [<ffffffff814295c2>] sock_aio_write+0xb2/0xc0
>         [<ffffffff811968f0>] do_sync_write+0x60/0x90
>         [<ffffffff81198891>] vfs_write+0x1d1/0x1e0
>         [<ffffffff811989bd>] SyS_write+0x5d/0xa0
>         [<ffffffff81527522>] system_call_fastpath+0x16/0x1b
> 
>  -> #0 (tipc_net_lock){++.-..}:
>         [<ffffffff810a1e2e>] check_prev_add+0x41e/0x490
>         [<ffffffff810a2547>] validate_chain+0x6a7/0x7d0
>         [<ffffffff810a29d1>] __lock_acquire+0x361/0x610
>         [<ffffffff810a2d62>] lock_acquire+0xe2/0x110
>         [<ffffffff8151e2f4>] _raw_read_lock_bh+0x34/0x50
>         [<ffffffffa02e324f>] tipc_link_send+0x2f/0xc0 [tipc]
>         [<ffffffffa02e617b>] named_cluster_distribute+0x6b/0x80 [tipc]
>         [<ffffffffa02e62ab>] tipc_named_publish+0x7b/0x90 [tipc]
>         [<ffffffffa02e841b>] tipc_nametbl_publish+0x7b/0xc0 [tipc]
>         [<ffffffffa02e9958>] tipc_publish+0x98/0xf0 [tipc]
>         [<ffffffffa02ebf58>] bind+0x78/0xb0 [tipc]
>         [<ffffffff81428dc0>] SyS_bind+0xb0/0xd0
>         [<ffffffff81527522>] system_call_fastpath+0x16/0x1b
> 
>  other info that might help us debug this:
> 
>   Possible unsafe locking scenario:
> 
>         CPU0                    CPU1
>         ----                    ----
>    lock(tipc_nametbl_lock);
>                                 lock(tipc_net_lock);
>                                 lock(tipc_nametbl_lock);
>    lock(tipc_net_lock);
> 
>   *** DEADLOCK ***
> ----------------------------------------------------------
> 
> problem is that tipc_nametbl_publish which will hold tipc_nametbl_lock
> and acquire tipc_net_lock, while the tipc_net_start which hold
> tipc_net_lock and acquir tipc_nametbl_lock, so the dead lock occurs.
> 
> tipc_link_send protected by tipc_net_lock, we can unlock the
> tipc_nametbl_lock, and it no need the tipc_nametbl_lock to protect it.
> so I just unlock the tbl_lock before it, and lock the tbl_lock after it.
> 
> Signed-off-by: Wang Weidong <wangweidong1@huawei.com>
> ---
>  net/tipc/name_distr.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c
> index e0d0805..ab8f96c 100644
> --- a/net/tipc/name_distr.c
> +++ b/net/tipc/name_distr.c
> @@ -138,7 +138,9 @@ static void named_cluster_distribute(struct sk_buff *buf)
>  			if (!buf_copy)
>  				break;
>  			msg_set_destnode(buf_msg(buf_copy), n_ptr->addr);
> +			write_unlock_bh(&tipc_nametbl_lock);
>  			tipc_link_send(buf_copy, n_ptr->addr, n_ptr->addr);
> +			write_lock_bh(&tipc_nametbl_lock);
>  		}
>  	}
>  
> 


------------------------------------------------------------------------------
Shape the Mobile Experience: Free Subscription
Software experts and developers: Be at the forefront of tech innovation.
Intel(R) Software Adrenaline delivers strategic insight and game-changing 
conversations that shape the rapidly evolving mobile landscape. Sign up now. 
http://pubads.g.doubleclick.net/gampad/clk?id=63431311&iu=/4140/ostg.clktrk

^ permalink raw reply

* Re: [PATCH] tipc: fix a lockdep warning
From: wangweidong @ 2013-11-22  8:47 UTC (permalink / raw)
  To: Ying Xue, jon.maloy, allan.stephens, davem,
	Paul.Gortmaker@windriver.com
  Cc: dingtianhong, netdev, tipc-discussion, Erik Hugne
In-Reply-To: <528F1745.4050202@windriver.com>

On 2013/11/22 16:35, Ying Xue wrote:
> Hi Weidong,
> 
> I know you ever posted below patch into netdev mail list last month. And
> at that moment I also told you we already had one better solution to fix
> the issue. However, after our TIPC internal development team went
> through a long and bitter dispute about that "better" solution, we
> eventually made a consensus by proposing below approach to fix your met
> issue:
> 
> http://thread.gmane.org/gmane.network.tipc.general/4926/
> 
> I think the patchset should be ready now.
> 

Sorry for that fogot what you had told me. And I will look at the patchset.
it looks nice.
Thanks. 

> Sorry for your inconvenience.
> 
> Regards,
> Ying
> 
> 

^ permalink raw reply

* Re: [PATCH] tipc: fix a lockdep warning
From: Ying Xue @ 2013-11-22  9:08 UTC (permalink / raw)
  To: wangweidong, jon.maloy, allan.stephens, davem
  Cc: netdev, tipc-discussion, dingtianhong
In-Reply-To: <528F136E.1030506@huawei.com>

Hi Weidong,

Please ignore my last mail because you are to fix the issue which is
different with my mentioned one, and please see my below comments about
your patch;

On 11/22/2013 04:18 PM, wangweidong wrote:
> PC1:tipc-config -netid=1234 -a=1.1.2 -be=eth:eth0/1.1.0
> PC2:tipc-config -netid=1234 -a=1.1.3 -be=eth:eth0/1.1.0
> 
> I used a server code Like this:
> ----------------
>     sk=socket(AF_TIPC,SOCK_RDM,0);
>     bind(sk, &addr, len);
>     while(1) {
>         recvfrom(sk,...);
>         ...
>         sendto(sk,...);
>     }
> ----------------
> 
> when I did ./server in PC1, I got a lockdep as bellow:
> 
> ======================================================
> [ INFO: possible circular locking dependency detected ]
> 3.12.0-lockdep+ #4 Not tainted
> -------------------------------------------------------
> server/3772 is trying to acquire lock:
> (tipc_net_lock){++.-..}, at: [<ffffffffa02e324f>] tipc_link_send+0x2f/0xc0 [tipc]
> 
> but task is already holding lock:
> (tipc_nametbl_lock){++--..}, at: [<ffffffffa02e83e6>] tipc_nametbl_publish+0x46/0xc0 [tipc]
>  which lock already depends on the new lock.
> 
> the existing dependency chain (in reverse order) is:
>  -> #1 (tipc_nametbl_lock){++--..}:
>         [<ffffffff810a2547>] validate_chain+0x6a7/0x7d0
>         [<ffffffff810a29d1>] __lock_acquire+0x361/0x610
>         [<ffffffff810a2d62>] lock_acquire+0xe2/0x110
>         [<ffffffff8151e061>] _raw_write_lock_bh+0x31/0x40
>         [<ffffffffa02e5d40>] tipc_named_reinit+0x10/0x70 [tipc]
>         [<ffffffffa02e8512>] tipc_net_start+0x22/0x80 [tipc]
>         [<ffffffffa02dff0e>] tipc_core_start_net+0xe/0x40 [tipc]
>         [<ffffffffa02df625>] cfg_set_own_addr+0x75/0xc0 [tipc]
>         [<ffffffffa02df8f5>] tipc_cfg_do_cmd+0x135/0x550 [tipc]
>         [<ffffffffa02e87f9>] handle_cmd+0x49/0xe0 [tipc]
>         [<ffffffff814764fd>] genl_family_rcv_msg+0x22d/0x3c0
>         [<ffffffff81476700>] genl_rcv_msg+0x70/0xd0
>         [<ffffffff81474dc9>] netlink_rcv_skb+0x89/0xb0
>         [<ffffffff81475f87>] genl_rcv+0x27/0x40
>         [<ffffffff81474b1e>] netlink_unicast+0x14e/0x1a0
>         [<ffffffff81475735>] netlink_sendmsg+0x245/0x420
>         [<ffffffff814294f6>] __sock_sendmsg+0x66/0x80
>         [<ffffffff814295c2>] sock_aio_write+0xb2/0xc0
>         [<ffffffff811968f0>] do_sync_write+0x60/0x90
>         [<ffffffff81198891>] vfs_write+0x1d1/0x1e0
>         [<ffffffff811989bd>] SyS_write+0x5d/0xa0
>         [<ffffffff81527522>] system_call_fastpath+0x16/0x1b
> 
>  -> #0 (tipc_net_lock){++.-..}:
>         [<ffffffff810a1e2e>] check_prev_add+0x41e/0x490
>         [<ffffffff810a2547>] validate_chain+0x6a7/0x7d0
>         [<ffffffff810a29d1>] __lock_acquire+0x361/0x610
>         [<ffffffff810a2d62>] lock_acquire+0xe2/0x110
>         [<ffffffff8151e2f4>] _raw_read_lock_bh+0x34/0x50
>         [<ffffffffa02e324f>] tipc_link_send+0x2f/0xc0 [tipc]
>         [<ffffffffa02e617b>] named_cluster_distribute+0x6b/0x80 [tipc]
>         [<ffffffffa02e62ab>] tipc_named_publish+0x7b/0x90 [tipc]
>         [<ffffffffa02e841b>] tipc_nametbl_publish+0x7b/0xc0 [tipc]
>         [<ffffffffa02e9958>] tipc_publish+0x98/0xf0 [tipc]
>         [<ffffffffa02ebf58>] bind+0x78/0xb0 [tipc]
>         [<ffffffff81428dc0>] SyS_bind+0xb0/0xd0
>         [<ffffffff81527522>] system_call_fastpath+0x16/0x1b
> 
>  other info that might help us debug this:
> 
>   Possible unsafe locking scenario:
> 
>         CPU0                    CPU1
>         ----                    ----
>    lock(tipc_nametbl_lock);
>                                 lock(tipc_net_lock);
>                                 lock(tipc_nametbl_lock);
>    lock(tipc_net_lock);
> 
>   *** DEADLOCK ***
> ----------------------------------------------------------
> 
> problem is that tipc_nametbl_publish which will hold tipc_nametbl_lock
> and acquire tipc_net_lock, while the tipc_net_start which hold
> tipc_net_lock and acquir tipc_nametbl_lock, so the dead lock occurs.
> 
> tipc_link_send protected by tipc_net_lock, we can unlock the
> tipc_nametbl_lock, and it no need the tipc_nametbl_lock to protect it.
> so I just unlock the tbl_lock before it, and lock the tbl_lock after it.
> 
> Signed-off-by: Wang Weidong <wangweidong1@huawei.com>
> ---
>  net/tipc/name_distr.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c
> index e0d0805..ab8f96c 100644
> --- a/net/tipc/name_distr.c
> +++ b/net/tipc/name_distr.c
> @@ -138,7 +138,9 @@ static void named_cluster_distribute(struct sk_buff *buf)
>  			if (!buf_copy)
>  				break;
>  			msg_set_destnode(buf_msg(buf_copy), n_ptr->addr);
> +			write_unlock_bh(&tipc_nametbl_lock);
>  			tipc_link_send(buf_copy, n_ptr->addr, n_ptr->addr);
> +			write_lock_bh(&tipc_nametbl_lock);

We cannot temporarily release/hold tipc_nametbl_lock here, please see
below call path:

tipc_nametbl_withdraw()
  tipc_named_withdraw()
    named_cluster_distribute()
      tipc_link_send()

Especially in tipc_nametbl_withdraw(), we must hold tipc_nametbl_lock to
protect name table before tipc_named_withdraw() is called. If we
temporarily release tipc_nametbl_lock in named_cluster_distribute(), I
am afraid that name table might be changed by another thread at the
moment, having name table inconsistent possibly.

Actually we are implementing another patchset purging the tipc_net_lock
from TIPC stack. If the patchset is involved, I guess the issue would
disappear.

If you have an interesting to see how to purge to tipc_net_lock, please
monitor tipc-discussion mail list.

Regards,
Ying


>  		}
>  	}
>  
> 


------------------------------------------------------------------------------
Shape the Mobile Experience: Free Subscription
Software experts and developers: Be at the forefront of tech innovation.
Intel(R) Software Adrenaline delivers strategic insight and game-changing 
conversations that shape the rapidly evolving mobile landscape. Sign up now. 
http://pubads.g.doubleclick.net/gampad/clk?id=63431311&iu=/4140/ostg.clktrk

^ permalink raw reply

* [PATCH v3] WAN: Adding support for Lantiq PEF2256 E1 chipset (FALC56)
From: Christophe Leroy @ 2013-11-22  9:10 UTC (permalink / raw)
  To: Rob Herring, Pawel Moll, Mark Rutland, Stephen Warren,
	Ian Campbell, Rob Landley, Grant Likely, Krzysztof Halasa
  Cc: devicetree, linux-doc, linux-kernel, netdev, devicetree,
	jerome.chantelauze.ext

The patch adds WAN support for Lantiq FALC56 - PEF2256 E1 Chipset.

Signed-off-by: Jerome Chantelauze <jerome.chantelauze.ext@c-s.fr>
Acked-by: Christophe Leroy <christophe.leroy@c-s.fr>

diff -urN a/drivers/net/wan/pef2256.c b/drivers/net/wan/pef2256.c
--- a/drivers/net/wan/pef2256.c	1970-01-01 01:00:00.000000000 +0100
+++ b/drivers/net/wan/pef2256.c	2013-10-13 13:05:01.000000000 +0200
@@ -0,0 +1,1113 @@
+/* drivers/net/wan/pef2256.c : a PEF2256 HDLC driver for Linux
+ *
+ * This software may be used and distributed according to the terms of the
+ * GNU General Public License.
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/list.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+
+#include <linux/cache.h>
+#include <asm/byteorder.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <asm/irq.h>
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/string.h>
+
+#include <linux/if_arp.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+#include <linux/hdlc.h>
+#include <linux/mutex.h>
+#include <linux/of_device.h>
+#include <linux/etherdevice.h>
+#include "pef2256.h"
+
+static int pef2256_open(struct net_device *netdev);
+static int pef2256_close(struct net_device *netdev);
+
+/* helper function - Read a register */
+static u8 pef2256_r8(struct pef2256_dev_priv *priv, u32 offset)
+{
+	return ioread8(priv->ioaddr + offset);
+}
+
+/* helper function - Write a value to a register */
+static void pef2256_w8(struct pef2256_dev_priv *priv, u32 offset, u8 val)
+{
+	iowrite8(val, priv->ioaddr + offset);
+}
+
+/* helper function - Clear bits in a register */
+static void pef2256_c8(struct pef2256_dev_priv *priv, u32 offset, u8 mask)
+{
+	u8 val = pef2256_r8(priv, offset);
+	iowrite8(val & ~mask, priv->ioaddr + offset);
+}
+
+/* helper function - Set bits in a register */
+static void pef2256_s8(struct pef2256_dev_priv *priv, u32 offset, u8 mask)
+{
+	u8 val = pef2256_r8(priv, offset);
+	iowrite8(val | mask, priv->ioaddr + offset);
+}
+
+static void config_hdlc_timeslot(struct pef2256_dev_priv *priv, int ts)
+{
+	static struct {
+		u32 ttr;
+		u32 rtr;
+	} regs[] = {
+		{ TTR1, RTR1 },
+		{ TTR2, RTR2 },
+		{ TTR3, RTR3 },
+		{ TTR4, RTR4 },
+	};
+	int cfg_bit = 1 << (31 - ts);
+	int reg_bit = 1 << (7 - (ts % 8));
+	int j = ts / 8;
+
+	if (j >= 4)
+		return;
+
+	if (priv->Tx_TS & cfg_bit)
+		pef2256_s8(priv, regs[j].ttr, 1 << reg_bit);
+
+	if (priv->Rx_TS & cfg_bit)
+		pef2256_s8(priv, regs[j].rtr, 1 << reg_bit);
+}
+
+
+/* Setting up HDLC channel */
+static void config_hdlc(struct pef2256_dev_priv *priv)
+{
+	int TS_idx;
+	u8 dummy;
+
+	/* Read to remove pending IT */
+	dummy = pef2256_r8(priv, ISR0);
+	dummy = pef2256_r8(priv, ISR1);
+	dummy = pef2256_r8(priv, ISR2);
+
+	/* Mask HDLC 1 Transmit IT */
+	pef2256_s8(priv, IMR1, IMR1_XPR);
+	pef2256_s8(priv, IMR1, IMR1_XDU);
+	pef2256_s8(priv, IMR1, IMR1_ALLS);
+
+	/* Mask HDLC 1 Receive IT */
+	pef2256_s8(priv, IMR0, IMR0_RPF);
+	pef2256_s8(priv, IMR0, IMR0_RME);
+	pef2256_s8(priv, IMR1, IMR1_RDO);
+
+	/* Mask errors IT */
+	pef2256_s8(priv, IMR0, IMR0_PDEN);
+	pef2256_s8(priv, IMR2, IMR2_LOS);
+	pef2256_s8(priv, IMR2, IMR2_AIS);
+
+	udelay(FALC_HW_CMD_DELAY_US);
+
+	/* MODE.HRAC = 0 (Receiver inactive)
+	 * MODE.DIV = 0 (Data normal operation)
+	 * for FALC V2.2 : MODE.HDLCI = 0 (normal operation)
+	 * MODE.MDS2:0 = 100 (No address comparison)
+	 * MODE.HRAC = 1 (Receiver active)
+	 */
+	pef2256_w8(priv, MODE, 1 << 3);
+	/* CCR1.EITS = 1 (Enable internal Time Slot 31:0 Signaling)
+	 * CCR1.XMFA = 0 (No transmit multiframe alignment)
+	 * CCR1.RFT1:0 = 00 (RFIFO is 32 bytes)
+	 * setting up Interframe Time Fill
+	 * CCR1.ITF = 1 (Interframe Time Fill Continuous flag)
+	 */
+	pef2256_w8(priv, CCR1, 0x10 | (1 << 3));
+	/* CCR2.XCRC = 0 (Transmit CRC ON)
+	 * CCR2.RCRC = 0 (Receive CRC ON, no write in RFIFO)
+	 * CCR2.RADD = 0 (No write address in RFIFO)
+	 */
+	pef2256_w8(priv, CCR2, 0x00);
+
+	udelay(FALC_HW_CMD_DELAY_US);
+
+	/* MODE.HRAC = 0 (Receiver inactive)
+	 * MODE.DIV = 0 (Data normal operation)
+	 * for FALC V2.2 : MODE.HDLCI = 0 (normal operation)
+	 * MODE.MDS2:0 = 100 (No address comparison)
+	 * MODE.HRAC = 1 (Receiver active)
+	 */
+	pef2256_w8(priv, MODE, 1 << 3);
+	/* CCR1.EITS = 1 (Enable internal Time Slot 31:0 Signaling)
+	 * CCR1.XMFA = 0 (No transmit multiframe alignment)
+	 * CCR1.RFT1:0 = 00 (RFIFO is 32 bytes)
+	 * setting up Interframe Time Fill
+	 * CCR1.ITF = 1 (Interframe Time Fill Continuous flag)
+	 */
+	pef2256_w8(priv, CCR1, 0x10 | (1 << 3));
+	/* CCR2.XCRC = 0 (Transmit CRC ON)
+	 * CCR2.RCRC = 0 (Receive CRC ON, no write in RFIFO)
+	 * CCR2.RADD = 0 (No write address in RFIFO)
+	 */
+	pef2256_w8(priv, CCR2, 0x00);
+
+	udelay(FALC_HW_CMD_DELAY_US);
+
+	/* MODE.HRAC = 0 (Receiver inactive)
+	 * MODE.DIV = 0 (Data normal operation)
+	 * for FALC V2.2 : MODE.HDLCI = 0 (normal operation)
+	 * MODE.MDS2:0 = 100 (No address comparison)
+	 * MODE.HRAC = 1 (Receiver active)
+	 */
+	pef2256_w8(priv, MODE, 1 << 3);
+	/* CCR1.EITS = 1 (Enable internal Time Slot 31:0 Signaling)
+	 * CCR1.XMFA = 0 (No transmit multiframe alignment)
+	 * CCR1.RFT1:0 = 00 (RFIFO is 32 bytes)
+	 * setting up Interframe Time Fill
+	 * CCR1.ITF = 1 (Interframe Time Fill Continuous flag)
+	 */
+	pef2256_w8(priv, CCR1, 0x10 | (1 << 3));
+	/* CCR2.XCRC = 0 (Transmit CRC ON)
+	 * CCR2.RCRC = 0 (Receive CRC ON, no write in RFIFO)
+	 * CCR2.RADD = 0 (No write address in RFIFO)
+	 */
+	pef2256_w8(priv, CCR2, 0x00);
+
+	udelay(FALC_HW_CMD_DELAY_US);
+
+	/* Init  Time Slot select */
+	pef2256_w8(priv, TTR1, 0x00);
+	pef2256_w8(priv, TTR2, 0x00);
+	pef2256_w8(priv, TTR3, 0x00);
+	pef2256_w8(priv, TTR4, 0x00);
+	pef2256_w8(priv, RTR1, 0x00);
+	pef2256_w8(priv, RTR2, 0x00);
+	pef2256_w8(priv, RTR3, 0x00);
+	pef2256_w8(priv, RTR4, 0x00);
+	/* Set selected TS bits */
+	/* Starting at TS 1, TS 0 is reserved */
+	for (TS_idx = 1; TS_idx < 32; TS_idx++)
+		config_hdlc_timeslot(priv, TS_idx);
+
+	udelay(FALC_HW_CMD_DELAY_US);
+
+	/* Unmask HDLC 1 Transmit IT */
+	pef2256_c8(priv, IMR1, IMR1_XPR);
+	pef2256_c8(priv, IMR1, IMR1_XDU);
+	pef2256_c8(priv, IMR1, IMR1_ALLS);
+
+	/* Unmask HDLC 1 Receive IT */
+	pef2256_c8(priv, IMR0, IMR0_RPF);
+	pef2256_c8(priv, IMR0, IMR0_RME);
+	pef2256_c8(priv, IMR1, IMR1_RDO);
+
+	/* Unmask errors IT */
+	pef2256_c8(priv, IMR0, IMR0_PDEN);
+	pef2256_c8(priv, IMR2, IMR2_LOS);
+	pef2256_c8(priv, IMR2, IMR2_AIS);
+}
+
+
+static void init_falc(struct pef2256_dev_priv *priv)
+{
+	int version;
+
+	/* Get controller version */
+	version = priv->component_id;
+
+	/* Init FALC56 */
+	/* RCLK output : DPLL clock, DCO-X enabled, DCO-X internal reference
+	 * clock
+	 */
+	pef2256_w8(priv, CMR1, 0x00);
+	/* SCLKR selected, SCLKX selected, receive synchro pulse sourced by
+	 * SYPR, transmit synchro pulse sourced by SYPX
+	 */
+	pef2256_w8(priv, CMR2, 0x00);
+	/* NRZ coding, no alarm simulation */
+	pef2256_w8(priv, FMR0, 0x00);
+	/* E1 double frame format, 2 Mbit/s system data rate, no AIS
+	 * transmission to remote end or system interface, payload loop
+	 * off, transmit remote alarm on
+	 */
+	pef2256_w8(priv, FMR1, 0x00);
+	pef2256_w8(priv, FMR2, 0x02);
+	/* E1 default for LIM2 */
+	pef2256_w8(priv, LIM2, 0x20);
+	if (priv->mode == MASTER_MODE)
+		/* SEC input, active high */
+		pef2256_w8(priv, GPC1, 0x00);
+	else
+		/* FSC output, active high */
+		pef2256_w8(priv, GPC1, 0x40);
+	/* internal second timer, power on */
+	pef2256_w8(priv, GCR, 0x00);
+	/* slave mode, local loop off, mode short-haul */
+	if (version == VERSION_1_2)
+		pef2256_w8(priv, LIM0, 0x00);
+	else
+		pef2256_w8(priv, LIM0, 0x08);
+	/* analog interface selected, remote loop off */
+	pef2256_w8(priv, LIM1, 0x00);
+	if (version == VERSION_1_2) {
+		/* function of ports RP(A to D) : output receive sync pulse
+		 * function of ports XP(A to D) : output transmit line clock
+		 */
+		pef2256_w8(priv, PC1, 0x77);
+		pef2256_w8(priv, PC2, 0x77);
+		pef2256_w8(priv, PC3, 0x77);
+		pef2256_w8(priv, PC4, 0x77);
+	} else {
+		/* function of ports RP(A to D) : output high
+		 * function of ports XP(A to D) : output high
+		 */
+		pef2256_w8(priv, PC1, 0xAA);
+		pef2256_w8(priv, PC2, 0xAA);
+		pef2256_w8(priv, PC3, 0xAA);
+		pef2256_w8(priv, PC4, 0xAA);
+	}
+	/* function of port RPA : input SYPR
+	 * function of port XPA : input SYPX
+	 */
+	pef2256_w8(priv, PC1, 0x00);
+	/* SCLKR, SCLKX, RCLK configured to inputs,
+	 * XFMS active low, CLK1 and CLK2 pin configuration
+	 */
+	pef2256_w8(priv, PC5, 0x00);
+	pef2256_w8(priv, PC6, 0x00);
+	/* the receive clock offset is cleared
+	 * the receive time slot offset is cleared
+	 */
+	pef2256_w8(priv, RC0, 0x00);
+	pef2256_w8(priv, RC1, 0x9C);
+	/* 2.048 MHz system clocking rate, receive buffer 2 frames, transmit
+	 * buffer bypass, data sampled and transmitted on the falling edge of
+	 * SCLKR/X, automatic freeze signaling, data is active in the first
+	 * channel phase
+	 */
+	pef2256_w8(priv, SIC1, 0x00);
+	pef2256_w8(priv, SIC2, 0x00);
+	pef2256_w8(priv, SIC3, 0x00);
+	/* channel loop-back and single frame mode are disabled */
+	pef2256_w8(priv, LOOP, 0x00);
+	/* all bits of the transmitted service word are cleared */
+	pef2256_w8(priv, XSW, 0x1F);
+	/* spare bit values are cleared */
+	pef2256_w8(priv, XSP, 0x00);
+	/* no transparent mode active */
+	pef2256_w8(priv, TSWM, 0x00);
+	/* the transmit clock offset is cleared
+	 * the transmit time slot offset is cleared
+	 */
+	pef2256_w8(priv, XC0, 0x00);
+	pef2256_w8(priv, XC1, 0x9C);
+	/* transmitter in tristate mode */
+	pef2256_w8(priv, XPM2, 0x40);
+	/* transmit pulse mask */
+	if (version != VERSION_1_2)
+		pef2256_w8(priv, XPM0, 0x9C);
+
+	if (version == VERSION_1_2) {
+		/* master clock is 16,384 MHz (flexible master clock) */
+		pef2256_w8(priv, GCM2, 0x58);
+		pef2256_w8(priv, GCM3, 0xD2);
+		pef2256_w8(priv, GCM4, 0xC2);
+		pef2256_w8(priv, GCM5, 0x07);
+		pef2256_w8(priv, GCM6, 0x10);
+	} else {
+		/* master clock is 16,384 MHz (flexible master clock) */
+		pef2256_w8(priv, GCM2, 0x18);
+		pef2256_w8(priv, GCM3, 0xFB);
+		pef2256_w8(priv, GCM4, 0x0B);
+		pef2256_w8(priv, GCM5, 0x01);
+		pef2256_w8(priv, GCM6, 0x0B);
+		pef2256_w8(priv, GCM7, 0xDB);
+		pef2256_w8(priv, GCM8, 0xDF);
+	}
+
+	/* master mode */
+	if (priv->mode == MASTER_MODE)
+		pef2256_s8(priv, LIM0, LIM0_MAS);
+
+	/* transmit line in normal operation */
+	pef2256_c8(priv, XPM2, XPM2_XLT);
+
+	if (version == VERSION_1_2) {
+		/* receive input threshold = 0,21V */
+		pef2256_s8(priv, LIM1, LIM1_RIL0);
+		pef2256_c8(priv, LIM1, LIM1_RIL1);
+		pef2256_s8(priv, LIM1, LIM1_RIL2);
+	} else {
+		/* receive input threshold = 0,21V */
+		pef2256_c8(priv, LIM1, LIM1_RIL0);
+		pef2256_c8(priv, LIM1, LIM1_RIL1);
+		pef2256_s8(priv, LIM1, LIM1_RIL2);
+	}
+	/* transmit line coding = HDB3 */
+	pef2256_s8(priv, FMR0, FMR0_XC0);
+	pef2256_s8(priv, FMR0, FMR0_XC1);
+	/* receive line coding = HDB3 */
+	pef2256_s8(priv, FMR0, FMR0_RC0);
+	pef2256_s8(priv, FMR0, FMR0_RC1);
+	/* detection of LOS alarm = 176 pulses (soit (10 + 1) * 16) */
+	pef2256_w8(priv, PCD, 10);
+	/* recovery of LOS alarm = 22 pulses (soit 21 + 1) */
+	pef2256_w8(priv, PCR, 21);
+	/* DCO-X center frequency => CMR2.DCOXC */
+	pef2256_s8(priv, CMR2, CMR2_DCOXC);
+	if (priv->mode == SLAVE_MODE) {
+		/* select RCLK source = 2M */
+		pef2256_c8(priv, CMR1, CMR1_RS0);
+		pef2256_s8(priv, CMR1, CMR1_RS1);
+		/* disable switching RCLK -> SYNC */
+		pef2256_s8(priv, CMR1, CMR1_DCS);
+	}
+	if (version != VERSION_1_2)
+		/* during inactive channel phase RDO into tri-state mode */
+		pef2256_s8(priv, SIC3, 1 << 5);
+	if (!strcmp(priv->rising_edge_sync_pulse, "transmit")) {
+		/* rising edge sync pulse transmit */
+		pef2256_c8(priv, SIC3, SIC3_RESR);
+		pef2256_s8(priv, SIC3, SIC3_RESX);
+	} else {
+		/* rising edge sync pulse receive */
+		pef2256_c8(priv, SIC3, SIC3_RESX);
+		pef2256_s8(priv, SIC3, SIC3_RESR);
+	}
+	/* transmit offset counter = 4
+	 *  => XC0.XCO10:8 = 000 (bits 2, 1 et 0);
+	 *     XC1.XCO7:0 = 4 (bits 7 ... 0)
+	 */
+	pef2256_w8(priv, XC1, 4);
+	/* receive offset counter = 4
+	 * => RC0.RCO10:8 = 000 (bits 2, 1 et 0);
+	 *    RC1.RCO7:0 = 4 (bits 7 ... 0)
+	 */
+	pef2256_w8(priv, RC1, 4);
+
+	/* Clocking rate for FALC56 */
+
+	/* Nothing to do for clocking rate 2M  */
+
+	/* clocking rate 4M  */
+	if (priv->clock_rate == CLOCK_RATE_4M)
+		pef2256_s8(priv, SIC1, SIC1_SSC0);
+
+	/* clocking rate 8M  */
+	if (priv->clock_rate == CLOCK_RATE_8M)
+		pef2256_s8(priv, SIC1, SIC1_SSC1);
+
+	/* clocking rate 16M  */
+	if (priv->clock_rate == CLOCK_RATE_16M) {
+		pef2256_s8(priv, SIC1, SIC1_SSC0);
+		pef2256_s8(priv, SIC1, SIC1_SSC1);
+	}
+
+	/* data rate for FALC56 */
+
+	/* Nothing to do for data rate 2M on the system data bus */
+
+	/* data rate 4M on the system data bus */
+	if (priv->data_rate == DATA_RATE_4M)
+		pef2256_s8(priv, FMR1, FMR1_SSD0);
+
+	/* data rate 8M on the system data bus */
+	if (priv->data_rate == DATA_RATE_8M)
+		pef2256_s8(priv, SIC1, SIC1_SSD1);
+
+	/* data rate 16M on the system data bus */
+	if (priv->data_rate == DATA_RATE_16M) {
+		pef2256_s8(priv, FMR1, FMR1_SSD0);
+		pef2256_s8(priv, SIC1, SIC1_SSD1);
+	}
+
+	/* channel phase for FALC56 */
+
+	/* Nothing to do for channel phase 1 */
+
+	if (priv->channel_phase == CHANNEL_PHASE_2)
+		pef2256_s8(priv, SIC2, SIC2_SICS0);
+
+	if (priv->channel_phase == CHANNEL_PHASE_3)
+		pef2256_s8(priv, SIC2, SIC2_SICS1);
+
+	if (priv->channel_phase == CHANNEL_PHASE_4) {
+		pef2256_s8(priv, SIC2, SIC2_SICS0);
+		pef2256_s8(priv, SIC2, SIC2_SICS1);
+	}
+
+	if (priv->channel_phase == CHANNEL_PHASE_5)
+		pef2256_s8(priv, SIC2, SIC2_SICS2);
+
+	if (priv->channel_phase == CHANNEL_PHASE_6) {
+		pef2256_s8(priv, SIC2, SIC2_SICS0);
+		pef2256_s8(priv, SIC2, SIC2_SICS2);
+	}
+
+	if (priv->channel_phase == CHANNEL_PHASE_7) {
+		pef2256_s8(priv, SIC2, SIC2_SICS1);
+		pef2256_s8(priv, SIC2, SIC2_SICS2);
+	}
+
+	if (priv->channel_phase == CHANNEL_PHASE_8) {
+		pef2256_s8(priv, SIC2, SIC2_SICS0);
+		pef2256_s8(priv, SIC2, SIC2_SICS1);
+		pef2256_s8(priv, SIC2, SIC2_SICS2);
+	}
+
+	if (priv->mode == SLAVE_MODE)
+		/* transmit buffer size = 2 frames */
+		pef2256_s8(priv, SIC1, SIC1_XBS1);
+
+	/* transmit in multiframe */
+	pef2256_s8(priv, FMR1, FMR1_XFS);
+	/* receive in multiframe */
+	pef2256_s8(priv, FMR2, FMR2_RFS1);
+	/* Automatic transmission of submultiframe status */
+	pef2256_s8(priv, XSP, XSP_AXS);
+
+	/* error counter mode toutes les 1s */
+	pef2256_s8(priv, FMR1, FMR1_ECM);
+	/* error counter mode COFA => GCR.ECMC = 1 (bit 4) */
+	pef2256_s8(priv, GCR, GCR_ECMC);
+	/* errors in service words with no influence */
+	pef2256_s8(priv, RC0, RC0_SWD);
+	/* 4 consecutive incorrect FAS = loss of sync */
+	pef2256_s8(priv, RC0, RC0_ASY4);
+	/* Si-Bit in service word from XDI */
+	pef2256_s8(priv, XSW, XSW_XSIS);
+	/* Si-Bit in FAS word from XDI */
+	pef2256_s8(priv, XSP, XSP_XSIF);
+
+	/* port RCLK is output */
+	pef2256_s8(priv, PC5, PC5_CRP);
+	/* visibility of the masked interrupts */
+	pef2256_s8(priv, GCR, GCR_VIS);
+	/* reset lines
+	 *  => CMDR.RRES = 1 (bit 6); CMDR.XRES = 1 (bit 4);
+	 *     CMDR.SRES = 1 (bit 0)
+	 */
+	pef2256_w8(priv, CMDR, 0x51);
+}
+
+static ssize_t fs_attr_mode_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct pef2256_dev_priv *priv = dev_to_hdlc(ndev)->priv;
+
+	return sprintf(buf, "%d\n", priv->mode);
+}
+
+
+static ssize_t fs_attr_mode_store(struct device *dev,
+			struct device_attribute *attr,  const char *buf,
+			size_t count)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct pef2256_dev_priv *priv = dev_to_hdlc(ndev)->priv;
+	long int value;
+	int ret = kstrtol(buf, 10, &value);
+	int reconfigure = (value != priv->mode);
+
+	if (value != MASTER_MODE && value != SLAVE_MODE)
+		ret = -EINVAL;
+
+	if (ret < 0)
+		netdev_info(ndev, "Invalid mode (0 or 1 expected\n");
+	else {
+		priv->mode = value;
+		if (reconfigure && netif_carrier_ok(ndev))
+			init_falc(priv);
+	}
+
+	return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, fs_attr_mode_show,
+						fs_attr_mode_store);
+
+
+
+static ssize_t fs_attr_Tx_TS_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct pef2256_dev_priv *priv = dev_to_hdlc(ndev)->priv;
+
+	return sprintf(buf, "0x%08x\n", priv->Tx_TS);
+}
+
+
+static ssize_t fs_attr_Tx_TS_store(struct device *dev,
+			struct device_attribute *attr,  const char *buf,
+			size_t count)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct pef2256_dev_priv *priv = dev_to_hdlc(ndev)->priv;
+	unsigned long value;
+	int ret = kstrtoul(buf, 16, (long int *)&value);
+	int reconfigure = (value != priv->mode);
+
+	/* TS 0 is reserved */
+	if (ret < 0 || value > TS_0)
+		ret = -EINVAL;
+
+	if (ret < 0)
+		netdev_info(ndev, "Invalid Tx_TS (hex number > 0 and < 0x80000000 expected\n");
+	else {
+		priv->Tx_TS = value;
+		if (reconfigure && netif_carrier_ok(ndev))
+			config_hdlc(priv);
+	}
+
+	return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(Tx_TS, S_IRUGO | S_IWUSR, fs_attr_Tx_TS_show,
+			fs_attr_Tx_TS_store);
+
+
+static ssize_t fs_attr_Rx_TS_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct pef2256_dev_priv *priv = dev_to_hdlc(ndev)->priv;
+
+	return sprintf(buf, "0x%08x\n", priv->Rx_TS);
+}
+
+
+static ssize_t fs_attr_Rx_TS_store(struct device *dev,
+			struct device_attribute *attr,  const char *buf,
+			size_t count)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct pef2256_dev_priv *priv = dev_to_hdlc(ndev)->priv;
+	unsigned long value;
+	int ret = kstrtoul(buf, 16, &value);
+	int reconfigure = (value != priv->mode);
+
+	/* TS 0 is reserved */
+	if (ret < 0 || value > TS_0)
+		ret = -EINVAL;
+
+	if (ret < 0)
+		netdev_info(ndev, "Invalid Rx_TS (hex number > 0 and < 0x80000000 expected\n");
+	else {
+		priv->Rx_TS = value;
+		if (reconfigure && netif_carrier_ok(ndev))
+			config_hdlc(priv);
+	}
+
+	return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(Rx_TS, S_IRUGO | S_IWUSR, fs_attr_Rx_TS_show,
+	 fs_attr_Rx_TS_store);
+
+
+static void pef2256_fifo_ack(struct pef2256_dev_priv *priv)
+{
+	pef2256_s8(priv, CMDR, 1 << 7);
+}
+
+
+static void pef2256_rx(struct pef2256_dev_priv *priv)
+{
+	int idx;
+
+	/* RDO has been received -> wait for RME */
+	if (priv->stats.rx_bytes == -1) {
+		pef2256_fifo_ack(priv);
+
+		if (priv->r_isr0 & ISR0_RME)
+			priv->stats.rx_bytes = 0;
+
+		return;
+	}
+
+	/* RPF : a block is available in the receive FIFO */
+	if (priv->r_isr0 & ISR0_RPF) {
+		for (idx = 0; idx < 32; idx++)
+			priv->rx_buff[priv->stats.rx_bytes + idx] =
+				pef2256_r8(priv, RFIFO + (idx & 1));
+
+		pef2256_fifo_ack(priv);
+
+		priv->stats.rx_bytes += 32;
+	}
+
+	/* RME : Message end : Read the receive FIFO */
+	if (priv->r_isr0 & ISR0_RME) {
+		/* Get size of last block */
+		int size = pef2256_r8(priv, RBCL) & 0x1F;
+
+		/* Read last block */
+		for (idx = 0; idx < size; idx++)
+			priv->rx_buff[priv->stats.rx_bytes + idx] =
+				pef2256_r8(priv, RFIFO + (idx & 1));
+
+		pef2256_fifo_ack(priv);
+
+		priv->stats.rx_bytes += size;
+
+		/* Packet received */
+		if (priv->stats.rx_bytes > 0) {
+			struct sk_buff *skb =
+				dev_alloc_skb(priv->stats.rx_bytes);
+
+			if (!skb) {
+				priv->stats.rx_bytes = 0;
+				priv->netdev->stats.rx_dropped++;
+				return;
+			}
+			memcpy(skb->data, priv->rx_buff, priv->stats.rx_bytes);
+			skb_put(skb, priv->stats.rx_bytes);
+			priv->stats.rx_bytes = 0;
+			skb->protocol = hdlc_type_trans(skb, priv->netdev);
+			priv->netdev->stats.rx_packets++;
+			priv->netdev->stats.rx_bytes += skb->len;
+			netif_rx(skb);
+		}
+	}
+}
+
+
+static void pef2256_tx(struct pef2256_dev_priv *priv)
+{
+	int idx, size;
+	u8 *tx_buff = priv->tx_skb->data;
+
+	/* ALLS : transmit all done */
+	if (priv->r_isr1 & ISR1_ALLS) {
+		priv->netdev->stats.tx_packets++;
+		priv->netdev->stats.tx_bytes += priv->tx_skb->len;
+		priv->tx_skb = NULL;
+		priv->stats.tx_bytes = 0;
+		netif_wake_queue(priv->netdev);
+	} else
+		/* XPR : write a new block in transmit FIFO */
+		if (priv->stats.tx_bytes < priv->tx_skb->len) {
+			size = priv->tx_skb->len - priv->stats.tx_bytes;
+			if (size > 32)
+				size = 32;
+
+			for (idx = 0; idx < size; idx++)
+				pef2256_w8(priv, XFIFO + (idx & 1),
+					tx_buff[priv->stats.tx_bytes + idx]);
+
+			priv->stats.tx_bytes += size;
+
+			if (priv->stats.tx_bytes == priv->tx_skb->len)
+				pef2256_s8(priv, CMDR, (1 << 3) | (1 << 1));
+			else
+				pef2256_s8(priv, CMDR, 1 << 3);
+		}
+}
+
+static void pef2256_errors(struct pef2256_dev_priv *priv)
+{
+	if (pef2256_r8(priv, FRS1) & FRS1_PDEN ||
+	    pef2256_r8(priv, FRS0) & (FRS0_LOS | FRS0_AIS)) {
+		if (priv->tx_skb) {
+			priv->netdev->stats.tx_errors++;
+			priv->tx_skb = NULL;
+			priv->stats.tx_bytes = 0;
+			netif_wake_queue(priv->netdev);
+		}
+		if (priv->stats.rx_bytes > 0) {
+			priv->netdev->stats.rx_errors++;
+			priv->stats.rx_bytes = 0;
+		}
+		netif_carrier_off(priv->netdev);
+	} else
+		netif_carrier_on(priv->netdev);
+}
+
+static irqreturn_t pef2256_irq(int irq, void *dev_priv)
+{
+	struct pef2256_dev_priv *priv = (struct pef2256_dev_priv *)dev_priv;
+	u8 r_gis;
+
+	r_gis = pef2256_r8(priv, GIS);
+
+	priv->r_isr0 = priv->r_isr1 = 0;
+
+	/* We only care about ISR0, ISR1 and ISR2 */
+	/* ISR0 */
+	if (r_gis & GIS_ISR0)
+		priv->r_isr0 =
+			pef2256_r8(priv, ISR0) & ~(pef2256_r8(priv, IMR0));
+
+	/* ISR1 */
+	if (r_gis & GIS_ISR1)
+		priv->r_isr1 =
+			pef2256_r8(priv, ISR1) & ~(pef2256_r8(priv, IMR1));
+
+	/* ISR2 */
+	if (r_gis & GIS_ISR2)
+		priv->r_isr2 =
+			pef2256_r8(priv, ISR2) & ~(pef2256_r8(priv, IMR2));
+
+	/* An error status has changed */
+	if (priv->r_isr0 & ISR0_PDEN || priv->r_isr2 & ISR2_LOS ||
+	    priv->r_isr2 & ISR2_AIS)
+		pef2256_errors(priv);
+
+	/* RDO : Receive data overflow -> RX error */
+	if (priv->r_isr1 & ISR1_RDO) {
+		pef2256_fifo_ack(priv);
+		priv->netdev->stats.rx_errors++;
+		/* RME received ? */
+		if (priv->r_isr0 & ISR0_RME)
+			priv->stats.rx_bytes = 0;
+		else
+			priv->stats.rx_bytes = -1;
+	} else
+		/* RPF or RME : FIFO received */
+		if (priv->r_isr0 & (ISR0_RPF | ISR0_RME))
+			pef2256_rx(priv);
+
+	/* XDU : Transmit data underrun -> TX error */
+	if (priv->r_isr1 & ISR1_XDU) {
+		priv->netdev->stats.tx_errors++;
+		priv->tx_skb = NULL;
+		netif_wake_queue(priv->netdev);
+	} else
+		/* XPR or ALLS : FIFO sent */
+		if (priv->r_isr1 & (ISR1_XPR | ISR1_ALLS))
+			pef2256_tx(priv);
+
+	return IRQ_HANDLED;
+}
+
+
+static int pef2256_open(struct net_device *netdev)
+{
+	struct pef2256_dev_priv *priv = dev_to_hdlc(netdev)->priv;
+	int ret;
+	u8 dummy;
+
+	if (priv->component_id == VERSION_UNDEF) {
+		dev_err(priv->dev, "Composant ident (%X/%X) = %d\n",
+			pef2256_r8(priv, VSTR), pef2256_r8(priv, WID),
+				priv->component_id);
+		return -ENODEV;
+	}
+
+	ret = hdlc_open(netdev);
+	if (ret)
+		return ret;
+
+	/* We mask HDLC 1 receive/transmit IT to prevent the component sending
+	 * such interrupts before it is initialized and configured.
+	*/
+
+	/* Read to remove pending IT */
+	dummy = pef2256_r8(priv, ISR0);
+	dummy = pef2256_r8(priv, ISR1);
+	dummy = pef2256_r8(priv, ISR2);
+
+	/* Mask HDLC 1 Transmit IT */
+	pef2256_s8(priv, IMR1, IMR1_XPR);
+	pef2256_s8(priv, IMR1, IMR1_XDU);
+	pef2256_s8(priv, IMR1, IMR1_ALLS);
+
+	/* Mask HDLC 1 Receive IT */
+	pef2256_s8(priv, IMR0, IMR0_RPF);
+	pef2256_s8(priv, IMR0, IMR0_RME);
+	pef2256_s8(priv, IMR1, IMR1_RDO);
+
+	/* Mask errors IT */
+	pef2256_s8(priv, IMR0, IMR0_PDEN);
+	pef2256_s8(priv, IMR2, IMR2_LOS);
+	pef2256_s8(priv, IMR2, IMR2_AIS);
+
+	ret = request_irq(priv->irq, pef2256_irq, 0, "e1-wan", priv);
+	if (ret) {
+		dev_err(priv->dev, "Cannot request irq. Device seems busy.\n");
+		hdlc_close(netdev);
+		return -EBUSY;
+	}
+
+	init_falc(priv);
+
+	priv->tx_skb = NULL;
+	priv->stats.rx_bytes = 0;
+
+	config_hdlc(priv);
+
+	netif_start_queue(netdev);
+	pef2256_errors(priv);
+
+	return 0;
+}
+
+
+static int pef2256_close(struct net_device *netdev)
+{
+	struct pef2256_dev_priv *priv = dev_to_hdlc(netdev)->priv;
+
+	netif_stop_queue(netdev);
+	netif_carrier_off(netdev);
+	hdlc_close(netdev);
+	free_irq(priv->irq, priv);
+
+	return 0;
+}
+
+
+
+static netdev_tx_t pef2256_start_xmit(struct sk_buff *skb,
+					  struct net_device *netdev)
+{
+	struct pef2256_dev_priv *priv = dev_to_hdlc(netdev)->priv;
+	int idx, size;
+	u8 *tx_buff = skb->data;
+
+	priv->tx_skb = skb;
+	priv->stats.tx_bytes = 0;
+
+	size = priv->tx_skb->len - priv->stats.tx_bytes;
+	if (size > 32)
+		size = 32;
+
+	for (idx = 0; idx < size; idx++)
+		pef2256_w8(priv, XFIFO + (idx & 1),
+			tx_buff[priv->stats.tx_bytes + idx]);
+
+	priv->stats.tx_bytes += size;
+
+	pef2256_s8(priv, CMDR, 1 << 3);
+	if (priv->stats.tx_bytes == priv->tx_skb->len)
+		pef2256_s8(priv, CMDR, 1 << 1);
+
+	netif_stop_queue(netdev);
+	return NETDEV_TX_OK;
+}
+
+static const struct net_device_ops pef2256_ops = {
+	.ndo_open       = pef2256_open,
+	.ndo_stop       = pef2256_close,
+	.ndo_change_mtu = hdlc_change_mtu,
+	.ndo_start_xmit = hdlc_start_xmit,
+	.ndo_do_ioctl   = hdlc_ioctl,
+};
+
+
+static int pef2256_hdlc_attach(struct net_device *netdev,
+				unsigned short encoding, unsigned short parity)
+{
+	struct pef2256_dev_priv *priv = dev_to_hdlc(netdev)->priv;
+
+	if (encoding != ENCODING_NRZ &&
+	    encoding != ENCODING_NRZI &&
+	    encoding != ENCODING_FM_MARK &&
+	    encoding != ENCODING_FM_SPACE &&
+	    encoding != ENCODING_MANCHESTER)
+		return -EINVAL;
+
+	if (parity != PARITY_NONE &&
+	    parity != PARITY_CRC16_PR0_CCITT &&
+	    parity != PARITY_CRC16_PR1_CCITT &&
+	    parity != PARITY_CRC32_PR0_CCITT &&
+	    parity != PARITY_CRC32_PR1_CCITT)
+		return -EINVAL;
+
+	priv->encoding = encoding;
+	priv->parity = parity;
+	return 0;
+}
+
+
+static int pef2256_probe(struct platform_device *pdev)
+{
+	struct pef2256_dev_priv *priv;
+	int ret = -ENOMEM;
+	struct net_device *netdev;
+	hdlc_device *hdlc;
+	struct device_node *np = (&pdev->dev)->of_node;
+	const char *str_data;
+
+	if (!pdev->dev.of_node)
+		return -EINVAL;
+
+	dev_err(&pdev->dev, "Found PEF2256\n");
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return ret;
+
+	priv->dev = &pdev->dev;
+
+	if (of_property_read_u32(np, "clock-rate", &priv->clock_rate)) {
+		dev_err(&pdev->dev, "failed to read clock-rate -> using 8Mhz\n");
+		priv->clock_rate = CLOCK_RATE_8M;
+	}
+
+	if (of_property_read_u32(np, "data-rate", &priv->data_rate)) {
+		dev_err(&pdev->dev, "failed to read data-rate -> using 8Mb\n");
+		priv->data_rate = DATA_RATE_8M;
+	}
+
+	if (of_property_read_u32(np, "channel-phase", &priv->channel_phase)) {
+		dev_err(&pdev->dev, "failed to read channel phase -> using 0\n");
+		priv->channel_phase = CHANNEL_PHASE_0;
+	}
+
+	if (of_property_read_string(np, "rising-edge-sync-pulse", &str_data)) {
+		dev_err(&pdev->dev,
+"failed to read rising edge sync pulse -> using \"transmit\"\n");
+		strcpy(priv->rising_edge_sync_pulse, "transmit");
+	} else if (strcmp(str_data, "transmit") &&
+		   strcmp(str_data, "receive")) {
+		dev_err(&pdev->dev,
+"invalid rising edge sync pulse \"%s\" -> using \"transmit\"\n", str_data);
+		strcpy(priv->rising_edge_sync_pulse, "transmit");
+	} else
+		strncpy(priv->rising_edge_sync_pulse, str_data, 10);
+
+	priv->irq = platform_get_irq(pdev, 0);
+	if (!priv->irq) {
+		dev_err(priv->dev, "no irq defined\n");
+		goto free_priv;
+	}
+
+	priv->ioaddr = of_iomap(np, 0);
+	if (!priv->ioaddr) {
+		dev_err(&pdev->dev, "of_iomap failed\n");
+		goto free_priv;
+	}
+
+	/* Get the component Id */
+	priv->component_id = VERSION_UNDEF;
+	if (pef2256_r8(priv, VSTR) == 0x00) {
+		if ((pef2256_r8(priv, WID) & WID_IDENT_1) ==
+			WID_IDENT_1_2)
+			priv->component_id = VERSION_1_2;
+	} else if (pef2256_r8(priv, VSTR) == 0x05) {
+		if ((pef2256_r8(priv, WID) & WID_IDENT_2) ==
+			WID_IDENT_2_1)
+			priv->component_id = VERSION_2_1;
+		else if ((pef2256_r8(priv, WID) & WID_IDENT_2) ==
+			WID_IDENT_2_2)
+			priv->component_id = VERSION_2_2;
+	}
+
+	priv->tx_skb = NULL;
+
+	/* Default settings ; Rx and Tx use TS 1, mode = MASTER */
+	priv->Rx_TS = 0x40000000;
+	priv->Tx_TS = 0x40000000;
+	priv->mode = 0;
+
+	netdev = alloc_hdlcdev(priv);
+	if (!netdev) {
+		dev_err(&pdev->dev, "alloc_hdlcdev failed\n");
+		ret = -ENOMEM;
+		goto free_regs;
+	}
+
+	priv->netdev = netdev;
+	hdlc = dev_to_hdlc(netdev);
+	netdev->netdev_ops = &pef2256_ops;
+	SET_NETDEV_DEV(netdev, &pdev->dev);
+	hdlc->attach = pef2256_hdlc_attach;
+	hdlc->xmit = pef2256_start_xmit;
+
+	dev_set_drvdata(&pdev->dev, netdev);
+
+	ret = register_hdlc_device(netdev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Can't register hdlc device\n");
+		goto free_dev;
+	}
+
+	/* These files are required to configure HDLC : mode
+	 * (master or slave), time slots used to transmit and
+	 * receive data. They are mandatory.
+	 */
+	ret = device_create_file(priv->dev, &dev_attr_mode);
+	ret |= device_create_file(priv->dev, &dev_attr_Tx_TS);
+	ret |= device_create_file(priv->dev, &dev_attr_Rx_TS);
+
+	if (ret)
+		goto remove_files;
+
+	return 0;
+
+remove_files:
+	device_remove_file(priv->dev, &dev_attr_Tx_TS);
+	device_remove_file(priv->dev, &dev_attr_Rx_TS);
+	device_remove_file(priv->dev, &dev_attr_mode);
+
+	unregister_hdlc_device(priv->netdev);
+free_dev:
+	free_netdev(priv->netdev);
+free_regs:
+	iounmap(priv->ioaddr);
+free_priv:;
+	kfree(priv);
+
+	return ret;
+}
+
+
+static int pef2256_remove(struct platform_device *pdev)
+{
+	struct net_device *ndev = dev_get_drvdata(&pdev->dev);
+	struct pef2256_dev_priv *priv = dev_to_hdlc(ndev)->priv;
+
+
+	device_remove_file(priv->dev, &dev_attr_Tx_TS);
+	device_remove_file(priv->dev, &dev_attr_Rx_TS);
+	device_remove_file(priv->dev, &dev_attr_mode);
+
+	unregister_hdlc_device(priv->netdev);
+
+	free_netdev(priv->netdev);
+
+	iounmap(priv->ioaddr);
+
+	kfree(priv);
+
+	kfree(pdev);
+	return 0;
+}
+
+static const struct of_device_id pef2256_match[] = {
+	{
+		.compatible = "lantiq,pef2256",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, pef2256_match);
+
+
+static struct platform_driver pef2256_driver = {
+	.probe		= pef2256_probe,
+	.remove		= pef2256_remove,
+	.driver		= {
+		.name	= "pef2256",
+		.owner	= THIS_MODULE,
+		.of_match_table	= pef2256_match,
+	},
+};
+
+
+module_platform_driver(pef2256_driver);
+
+/* GENERAL INFORMATIONS */
+MODULE_AUTHOR("CHANTELAUZE Jerome - April 2013");
+MODULE_VERSION("0.1");
+MODULE_DESCRIPTION("Lantiq PEF 2256 E1 Controller");
+MODULE_LICENSE("GPL");
diff -urN a/drivers/net/wan/pef2256.h b/drivers/net/wan/pef2256.h
--- a/drivers/net/wan/pef2256.h	1970-01-01 01:00:00.000000000 +0100
+++ b/drivers/net/wan/pef2256.h	2013-10-13 13:06:00.000000000 +0200
@@ -0,0 +1,327 @@
+/* drivers/net/wan/pef2256.c : a PEF2256 HDLC driver for Linux
+ *
+ * This software may be used and distributed according to the terms of the
+ * GNU General Public License.
+ */
+
+#ifndef _PEF2256_H
+#define _PEF2256_H
+
+#define MASTER_MODE 0
+#define SLAVE_MODE  1
+
+#define CHANNEL_PHASE_0 0
+#define CHANNEL_PHASE_1 1
+#define CHANNEL_PHASE_2 2
+#define CHANNEL_PHASE_3 3
+#define CHANNEL_PHASE_4 4
+#define CHANNEL_PHASE_5 5
+#define CHANNEL_PHASE_6 6
+#define CHANNEL_PHASE_7 7
+#define CHANNEL_PHASE_8 8
+
+#define CLOCK_RATE_2M 2
+#define CLOCK_RATE_4M 4
+#define CLOCK_RATE_8M 8
+#define CLOCK_RATE_16M 16
+
+#define DATA_RATE_2M 2
+#define DATA_RATE_4M 4
+#define DATA_RATE_8M 8
+#define DATA_RATE_16M 16
+
+#define RX_TIMEOUT 500
+
+#define TS_0 0x80000000
+
+/* The hardware requires a delay up to 2*32*125 usec to take commands
+ * into account
+ */
+#define FALC_HW_CMD_DELAY_US (2 * 32 * 125)
+
+enum versions {
+	VERSION_UNDEF = 0,
+	VERSION_1_2 = 0x12,
+	VERSION_2_1 = 0x21,
+	VERSION_2_2 = 0x22,
+};
+
+#define WID_IDENT_1		0x03
+#define WID_IDENT_1_2		0x03
+#define WID_IDENT_2		0xC0
+#define WID_IDENT_2_1		0x00
+#define WID_IDENT_2_2		0x40
+
+/* Registers' bits */
+#define GIS_ISR0			1
+#define GIS_ISR1			(1 << 1)
+#define GIS_ISR2			(1 << 2)
+#define ISR0_RPF			1
+#define ISR0_PDEN			(1 << 1)
+#define ISR0_RME			(1 << 7)
+#define ISR1_XPR			1
+#define ISR1_XDU			(1 << 4)
+#define ISR1_ALLS			(1 << 5)
+#define ISR1_RDO			(1 << 6)
+#define ISR2_LOS			(1 << 2)
+#define ISR2_AIS			(1 << 3)
+#define IMR0_RPF			1
+#define IMR0_PDEN			1
+#define IMR0_RME			(1 << 7)
+#define IMR1_XPR			1
+#define IMR1_XDU			(1 << 4)
+#define IMR1_ALLS			(1 << 5)
+#define IMR1_RDO			(1 << 6)
+#define IMR2_LOS			(1 << 2)
+#define IMR2_AIS			(1 << 3)
+#define LIM0_MAS			1
+#define LIM1_RIL0			(1 << 4)
+#define LIM1_RIL1			(1 << 5)
+#define LIM1_RIL2			(1 << 6)
+#define FMR0_RC0			(1 << 4)
+#define FMR0_RC1			(1 << 5)
+#define FMR0_XC0			(1 << 6)
+#define FMR0_XC1			(1 << 7)
+#define FMR1_SSD0			(1 << 1)
+#define FMR1_ECM			(1 << 2)
+#define FMR1_XFS			(1 << 3)
+#define FMR2_RFS0			(1 << 6)
+#define FMR2_RFS1			(1 << 7)
+#define FRS0_AIS			(1 << 7)
+#define FRS0_LOS			(1 << 6)
+#define FRS1_PDEN			(1 << 6)
+#define CMR2_DCOXC			(1 << 5)
+#define CMR1_DCS			(1 << 3)
+#define CMR1_RS0			(1 << 4)
+#define CMR1_RS1			(1 << 5)
+#define SIC3_RESR			(1 << 2)
+#define SIC3_RESX			(1 << 3)
+#define SIC2_SICS0			(1 << 1)
+#define SIC2_SICS1			(1 << 2)
+#define SIC2_SICS2			(1 << 3)
+#define SIC1_XBS0			(1 << 1)
+#define SIC1_XBS1			(1 << 1)
+#define SIC1_SSC0			(1 << 3)
+#define SIC1_SSD1			(1 << 6)
+#define SIC1_SSC1			(1 << 7)
+#define XSP_XSIF			(1 << 2)
+#define XSP_AXS				(1 << 3)
+#define GCR_ECMC			(1 << 4)
+#define GCR_SCI				(1 << 6)
+#define GCR_VIS				(1 << 7)
+#define RC0_SWD				(1 << 7)
+#define RC0_ASY4			(1 << 6)
+#define XSW_XSIS			(1 << 7)
+#define PC5_CRP				1
+#define XPM2_XLT			(1 << 6)
+
+struct pef2256_dev_priv {
+	struct sk_buff *tx_skb;
+	struct device *dev;
+
+	void __iomem *ioaddr;
+	int component_id;
+	int mode;	/* MASTER or SLAVE */
+	int board_type;
+	int channel_phase;
+	int clock_rate;
+	int data_rate;
+	char rising_edge_sync_pulse[10];
+
+	u8 rx_buff[2048];
+
+	struct net_device_stats stats;
+
+	u32 Tx_TS;	/* Transmit Time Slots */
+	u32 Rx_TS;	/* Receive Time Slots */
+
+	unsigned short encoding;
+	unsigned short parity;
+	struct net_device *netdev;
+
+	int irq;
+
+	u8 r_isr0;			/* ISR0 register */
+	u8 r_isr1;			/* ISR1 register */
+	u8 r_isr2;			/* ISR2 register */
+};
+
+
+/* Framer E1 registers offsets */
+#define XFIFO	0x00	/* 0x00/0x01	Tx FIFO */
+#define RFIFO	0x00	/* 0x00/0x01	Rx FIFO */
+#define	CMDR	0x02	/* 0x02	Command Register */
+#define	MODE	0x03	/* 0x03	Mode Register */
+#define	RAH1	0x04	/* 0x04	Receive Address High 1 */
+#define	RAH2	0x05	/* 0x05	Receive Address High 2 */
+#define	RAL1	0x06	/* 0x06	Receive Address Low 1 */
+#define	RAL2	0x07	/* 0x07	Receive Address Low 2 */
+#define	IPC	0x08	/* 0x08	Interrupt Port Configuration */
+#define	CCR1	0x09	/* 0x09	Common Configuration Register 1 */
+#define	CCR2	0x0A	/* 0x0A	Common Configuration Register 2 */
+#define	Res1	0x0B	/* 0x0B	Free Register 1 */
+#define	RTR1	0x0C	/* 0x0C	Receive Time Slot Register 1 */
+#define	RTR2	0x0D	/* 0x0D	Receive Time Slot Register 2 */
+#define	RTR3	0x0E	/* 0x0E	Receive Time Slot Register 3 */
+#define	RTR4	0x0F	/* 0x0F	Receive Time Slot Register 4 */
+#define	TTR1	0x10	/* 0x10	Transmit Time Slot Register 1 */
+#define	TTR2	0x11	/* 0x11	Transmit Time Slot Register 2 */
+#define	TTR3	0x12	/* 0x12	Transmit Time Slot Register 3 */
+#define	TTR4	0x13	/* 0x13	Transmit Time Slot Register 4 */
+#define	IMR0	0x14	/* 0x14	Interrupt Mask Register 0 */
+#define	IMR1	0x15	/* 0x15	Interrupt Mask Register 1 */
+#define	IMR2	0x16	/* 0x16	Interrupt Mask Register 2 */
+#define	IMR3	0x17	/* 0x17	Interrupt Mask Register 3 */
+#define	IMR4	0x18	/* 0x18	Interrupt Mask Register 4 */
+#define	IMR5	0x19	/* 0x19	Interrupt Mask Register 5 */
+#define	Res2	0x1A	/* 0x1A	Free Register 2 */
+#define	IERR	0x1B	/* 0x1B	Single Bit Error Insertion Register */
+#define	FMR0	0x1C	/* 0x1C	Framer Mode Register 0 */
+#define	FMR1	0x1D	/* 0x1D	Framer Mode Register 1 */
+#define	FMR2	0x1E	/* 0x1E	Framer Mode Register 2 */
+#define	LOOP	0x1F	/* 0x1F	Channel Loop-Back */
+#define	XSW	0x20	/* 0x20	Transmit Service Word */
+#define	XSP	0x21	/* 0x21	Transmit Spare Bits */
+#define	XC0	0x22	/* 0x22	Transmit Control 0 */
+#define	XC1	0x23	/* 0x23	Transmit Control 1 */
+#define	RC0	0x24	/* 0x24	Receive Control 0 */
+#define	RC1	0x25	/* 0x25	Receive Control 1 */
+#define	XPM0	0x26	/* 0x26	Transmit Pulse Mask 0 */
+#define	XPM1	0x27	/* 0x27	Transmit Pulse Mask 1 */
+#define	XPM2	0x28	/* 0x28	Transmit Pulse Mask 2 */
+#define	TSWM	0x29	/* 0x29	Transparent Service Word Mask */
+#define	Res3	0x2A	/* 0x2A	Free Register 3 */
+#define	IDLE	0x2B	/* 0x2B	Idle Channel Code */
+#define	XSA4	0x2C	/* 0x2C	Transmit Sa4-Bit Register */
+#define	XSA5	0x2D	/* 0x2D	Transmit Sa5-Bit Register */
+#define	XSA6	0x2E	/* 0x2E	Transmit Sa6-Bit Register */
+#define	XSA7	0x2F	/* 0x2F	Transmit Sa7-Bit Register */
+#define	XSA8	0x30	/* 0x30	Transmit Sa8-Bit Register */
+#define	FMR3	0x31	/* 0x31	Framer Mode Register 3 */
+#define	ICB1	0x32	/* 0x32	Idle Channel Register 1 */
+#define	ICB2	0x33	/* 0x33	Idle Channel Register 2 */
+#define	ICB3	0x34	/* 0x34	Idle Channel Register 3 */
+#define	ICB4	0x35	/* 0x35	Idle Channel Register 4 */
+#define	LIM0	0x36	/* 0x36	Line Interface Mode 0 */
+#define	LIM1	0x37	/* 0x37	Line Interface Mode 1 */
+#define	PCD	0x38	/* 0x38	Pulse Count Detection */
+#define	PCR	0x39	/* 0x39	Pulse Count Recovery */
+#define	LIM2	0x3A	/* 0x3A	Line Interface Mode 2 */
+#define	LCR1	0x3B	/* 0x3B	Loop Code Register 1 */
+#define	LCR2	0x3C	/* 0x3C	Loop Code Register 2 */
+#define	LCR3	0x3D	/* 0x3D	Loop Code Register 3 */
+#define	SIC1	0x3E	/* 0x3E	System Interface Control 1 */
+#define	SIC2	0x3F	/* 0x3F	System Interface Control 2 */
+#define	SIC3	0x40	/* 0x40	System Interface Control 3 */
+#define	Res4	0x41	/* 0x41	Free Register 4 */
+#define	Res5	0x42	/* 0x42	Free Register 5 */
+#define	Res6	0x43	/* 0x43	Free Register 6 */
+#define	CMR1	0x44	/* 0x44	Clock Mode Register 1 */
+#define	CMR2	0x45	/* 0x45	Clock Mode Register 2 */
+#define	GCR	0x46	/* 0x46	Global Configuration Register */
+#define	ESM	0x47	/* 0x47	Errored Second Mask */
+#define	CMR3	0x48	/* 0x48	Clock Mode Register 3 en V2.2 */
+#define	RBD	0x49	/* 0x49	Receive Buffer Delay */
+#define	VSTR	0x4A	/* 0x4A	Version Status Regiter */
+#define	RES	0x4B	/* 0x4B	Receive Equalizer Status */
+#define	FRS0	0x4C	/* 0x4C	Framer Receive Status 0 */
+#define	FRS1	0x4D	/* 0x4D	Framer Receive Status 1 */
+#define	RSW	0x4E	/* 0x4E	Receive Service Word */
+#define	RSP	0x4F	/* 0x4F	Receive Spare Bits */
+#define	FEC	0x50	/* 0x50/0x51 Framing Error Counter */
+#define	CVC	0x52	/* 0x52/0x53 Code Violation Counter */
+#define	CEC1	0x54	/* 0x54/0x55 CRC Error Counter 1 */
+#define	EBC	0x56	/* 0x56/0x57 E-Bit Error Counter */
+#define	CEC2	0x58	/* 0x58/0x59 CRC Error Counter 2 */
+#define	CEC3	0x5A	/* 0x5A/0x5B CRC Error Counter 3 */
+#define	RSA4	0x5C	/* 0x5C	Receive Sa4-Bit Register */
+#define	RSA5	0x5D	/* 0x5D	Receive Sa5-Bit Register */
+#define	RSA6	0x5E	/* 0x5E	Receive Sa6-Bit Register */
+#define	RSA7	0x5F	/* 0x5F	Receive Sa7-Bit Register */
+#define DEC	0x60	/* 0x60 Common Register - Disable Error Counter */
+#define RSA8	0x60	/* 0x60 Common Register - Receive Sa8-Bit Regiter */
+#define	RSA6S	0x61	/* 0x61	Receive Sa6-Bit Status Register */
+#define	RSP1	0x62	/* 0x62	Receive Signaling Pointer 1 */
+#define	RSP2	0x63	/* 0x63	Receive Signaling Pointer 2 */
+#define	SIS	0x64	/* 0x64	Signaling Status Register */
+#define	RSIS	0x65	/* 0x65	Receive Signaling Status Register */
+#define	RBCL	0x66	/* 0x66	Receive Byte Control */
+#define	RBCH	0x67	/* 0x67	Receive Byte Control */
+#define	ISR0	0x68	/* 0x68	Interrupt Status Register 0 */
+#define	ISR1	0x69	/* 0x69	Interrupt Status Register 1 */
+#define	ISR2	0x6A	/* 0x6A	Interrupt Status Register 2 */
+#define	ISR3	0x6B	/* 0x6B	Interrupt Status Register 3 */
+#define	ISR4	0x6C	/* 0x6C	Interrupt Status Register 4 */
+#define	ISR5	0x6D	/* 0x6D	Interrupt Status Register 5 */
+#define	GIS	0x6E	/* 0x6E	Global Interrupt Status */
+#define	Res8	0x6F	/* 0x6F	Free Register 8 */
+#define	CAS1	0x70	/* 0x70	CAS Register 1 */
+#define	CAS2	0x71	/* 0x71	CAS Register 2 */
+#define	CAS3	0x72	/* 0x72	CAS Register 3 */
+#define	CAS4	0x73	/* 0x73	CAS Register 4 */
+#define	CAS5	0x74	/* 0x74	CAS Register 5 */
+#define	CAS6	0x75	/* 0x75	CAS Register 6 */
+#define	CAS7	0x76	/* 0x76	CAS Register 7 */
+#define	CAS8	0x77	/* 0x77	CAS Register 8 */
+#define	CAS9	0x78	/* 0x78	CAS Register 9 */
+#define	CAS10	0x79	/* 0x79	CAS Register 10 */
+#define	CAS11	0x7A	/* 0x7A	CAS Register 11 */
+#define	CAS12	0x7B	/* 0x7B	CAS Register 12 */
+#define	CAS13	0x7C	/* 0x7C	CAS Register 13 */
+#define	CAS14	0x7D	/* 0x7D	CAS Register 14 */
+#define	CAS15	0x7E	/* 0x7E	CAS Register 15 */
+#define	CAS16	0x7F	/* 0x7F	CAS Register 16 */
+#define	PC1	0x80	/* 0x80	Port Configuration 1 */
+#define	PC2	0x81	/* 0x81	Port Configuration 2 */
+#define	PC3	0x82	/* 0x82	Port Configuration 3 */
+#define	PC4	0x83	/* 0x83	Port Configuration 4 */
+#define	PC5	0x84	/* 0x84	Port Configuration 5 */
+#define	GPC1	0x85	/* 0x85	Global Port Configuration 1 */
+#define	PC6	0x86	/* 0x86	Port Configuration 6 */
+#define	CMDR2	0x87	/* 0x87	Command Register 2 */
+#define	CMDR3	0x88	/* 0x88	Command Register 3 */
+#define	CMDR4	0x89	/* 0x89	Command Register 4 */
+#define	Res9	0x8A	/* 0x8A	Free Register 9 */
+#define	CCR3	0x8B	/* 0x8B	Common Control Register 3 */
+#define	CCR4	0x8C	/* 0x8C	Common Control Register 4 */
+#define	CCR5	0x8D	/* 0x8D	Common Control Register 5 */
+#define	MODE2	0x8E	/* 0x8E	Mode Register 2 */
+#define	MODE3	0x8F	/* 0x8F	Mode Register 3 */
+#define	RBC2	0x90	/* 0x90	Receive Byte Count Register 2 */
+#define	RBC3	0x91	/* 0x91	Receive Byte Count Register 3 */
+#define	GCM1	0x92	/* 0x92	Global Counter Mode 1 */
+#define	GCM2	0x93	/* 0x93	Global Counter Mode 2 */
+#define	GCM3	0x94	/* 0x94	Global Counter Mode 3 */
+#define	GCM4	0x95	/* 0x95	Global Counter Mode 4 */
+#define	GCM5	0x96	/* 0x96	Global Counter Mode 5 */
+#define	GCM6	0x97	/* 0x97	Global Counter Mode 6 */
+#define SIS2_1	0x98	/* 0x98 V1.2 : Signaling Status Register 2 */
+#define GCM7	0x98	/* 0x98 V2.2 : Global Counter Mode 7 */
+#define RSIS2_1	0x99	/* 0x99 V1.2 : Rx Signaling Status Register 2 */
+#define GCM8	0x99	/* 0x99 V2.2 : Global Counter Mode 8 */
+#define	SIS3	0x9A	/* 0x9A	Signaling Status Register 3 */
+#define	RSIS3	0x9B	/* 0x9B	Receive Signaling Status Register 3 */
+#define XFIFO2	0x9C	/* 0x9C/0x9D	Tx FIFO 2 */
+#define RFIFO2	0x9C	/* 0x9C/0x9D	Rx FIFO 2 */
+#define XFIFO3	0x9E	/* 0x9E/0x9F	Tx FIFO 3 */
+#define RFIFO3	0x9E	/* 0x9E/0x9F	Rx FIFO 3 */
+#define	TSEO	0xA0	/* 0xA0	Time Slot Even/Odd select */
+#define	TSBS1	0xA1	/* 0xA1	Time Slot Bit select 1 */
+#define	TSBS2	0xA2	/* 0xA2	Time Slot Bit select 2 */
+#define	TSBS3	0xA3	/* 0xA3	Time Slot Bit select 3 */
+#define	TSS2	0xA4	/* 0xA4	Time Slot select 2 */
+#define	TSS3	0xA5	/* 0xA5	Time Slot select 3 */
+#define	Res10	0xA6	/* 0xA6	Free Register 10 */
+#define	Res11	0xA7	/* 0xA7	Free Register 11 */
+#define	TPC0	0xA8	/* 0xA8	Test Pattern Control Register 0 */
+#define	SIS2	0xA9	/* 0xA9	Signaling Status Register 2 (V2.2) */
+#define	RSIS2	0xAA	/* 0xAA	Rx Signaling Status Register 2 (V2.2) */
+#define	MFPI	0xAB	/* 0xAB	Multi Function Port Input Status */
+#define	Res12	0xAC	/* 0xAC	Free Register 12 */
+#define	Res13	0xAD	/* 0xAD	Free Register 13 */
+#define	Res14	0xAE	/* 0xAE	Free Register 14 */
+#define	GLC1	0xAF	/* 0xAF	Global Line Control Register 1 */
+#define Res15	0xB0	/* 0xB0/0xEB Free Registers */
+#define WID	0xEC	/* 0xEC	Identification Register */
+
+#endif /* _PEF2256_H */
diff -urN a/Documentation/devicetree/bindings/net/pef2256.txt b/Documentation/devicetree/bindings/net/pef2256.txt
--- a/Documentation/devicetree/bindings/net/pef2256.txt	1970-01-01 01:00:00.000000000 +0100
+++ b/Documentation/devicetree/bindings/net/pef2256.txt	2013-10-13 15:05:42.000000000 +0200
@@ -0,0 +1,77 @@
+* Wan on Lantiq PEF2256 E1 controller, also known as FALC56
+
+This chip was originally called "Infineon PEF2256" before the transfer of the
+former "wire-line" business-unit into an own company.
+
+The PEF2256 is a E1/T1/J1 Framer and Line Interface Component for Long- and
+Short-Haul Applications.
+Its datashhet can be downloaded at
+http://www.datasheetcatalog.com/datasheets_pdf/P/E/F/2/PEF2256E.shtml
+
+The FALC56 framer and line interface component is designed to fulfill all
+required interfacing between analog E1 lines and the digital PCM system
+highway, H.100/H.110 or H-MVIP bus.
+
+Required properties:
+- compatible: Should contain "lantiq,pef2256"
+- reg: Address and length of the register set for the device.
+  There should be a single continuous bank.
+- interrupts: Should contain the single interrupt used by the component to
+  notify special events (error, data received, data transmitted, ...).
+
+Optional properties:
+
+These properties can be defined to adjust the system interface in E1 mode.
+
+The FALC56 offers a flexible feature for system designers where for transmit and
+receive direction different system clocks and system pulses are necessary. The
+interface to the receive system highway is realized by two data buses, one for
+the data RDO and one for the signaling data RSIG. The receive highway is clocked
+on pin SCLKR, while the interface to the transmit system highway is
+independently clocked on pin SCLKX. The frequency of these working clocks and
+the data rate of 2.048/4.096/8.192/16.384 Mbit/s for the receive and transmit
+system interface is programmable.
+
+- clock-rate:
+  Supported values are: 2 (2.048 Mhz), 4 (4.096 Mhz), 8 (8.192 Mhz),
+    16 (16.384 Mhz).
+  8 if not defined.
+
+- data-rate:
+  Supported values are: 2 (2.048 Mbit/sec), 4 (4.096 Mbit/sec),
+    8 (8.192 Mbit/sec), 16 (16.384 Mbit/sec).
+  8 if not defined.
+
+Adjusting the frame begin (time slot 0, bit 0) relative to SYPR/X or XMFS is
+possible in the range of 0 to 125 µs. The minimum shift of varying the
+time slot 0 begin can be programmed between 1 bit and 1/8 bit depending of the
+system clocking and data rate, e.g. with a clocking/data rate of 2.048 MHz
+shifting is done bit by bit, while running the FALC56 with 16.384 MHz and
+2.048 Mbit/s data rate it is done by 1/8 bit
+
+- channel-phase: First time slot transmission channel phase.
+  Supported values are: 0, 1, 2, 3, 4, 5, 6, 7. 8
+  0 if not defined.
+
+All transmit or receive system interface data and marker are clocked or sampled
+with the following active edge :
+* Latched with the first falling edge of the selected PCM highway clock.
+* Latched with the first rising edge of the selected PCM highway clock.
+The behaviour of "transmit" and "receive" signals is inverse.
+
+- rising-edge-sync-pulse: rising edge synchronous pulse.
+  Supported values are: "receive", "transmit".
+  "transmit" if not defined.
+
+Examples:
+
+	e1-wan@4,2000000 {
+		compatible = "lantiq,pef2256";
+		reg = <4 0x2000000 0xFF>;
+		interrupts = <8 1>;
+		interrupt-parent = <&PIC>;
+		clock-rate = <4>;
+		data-rate = <4>;
+		channel-phase = <1>;
+		rising-edge-sync-pulse = "transmit";
+	};
diff -urN a/drivers/net/wan/Makefile b/drivers/net/wan/Makefile
--- a/drivers/net/wan/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ b/drivers/net/wan/Makefile	2013-10-13 13:05:01.000000000 +0200
@@ -22,6 +22,7 @@
 obj-$(CONFIG_COSA)		+= cosa.o
 obj-$(CONFIG_FARSYNC)		+= farsync.o
 obj-$(CONFIG_DSCC4)             += dscc4.o
+obj-$(CONFIG_PEF2256)           += pef2256.o
 obj-$(CONFIG_X25_ASY)		+= x25_asy.o
 
 obj-$(CONFIG_LANMEDIA)		+= lmc/
diff -urN a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig
--- a/drivers/net/wan/Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ b/drivers/net/wan/Kconfig	2013-10-13 13:05:01.000000000 +0200
@@ -266,6 +266,16 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called farsync.
 
+config PEF2256
+	tristate "PEF2256 support"
+	depends on HDLC && OF && SYSFS
+	help
+	  Driver for Lantiq (ex. Infineon) FALC56 E1/T1/J1 Framer and
+	  Line Interface based on PEF2256 chipset.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called pef2256.
+
 config DSCC4
 	tristate "Etinc PCISYNC serial board support"
 	depends on HDLC && PCI && m

^ permalink raw reply

* Re: [PATCH linux-next] hisax: disable build for big-endian arm
From: Geert Uytterhoeven @ 2013-11-22  9:19 UTC (permalink / raw)
  To: Takashi Iwai
  Cc: Vincent Stehlé, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org, Linux-Next, Karsten Keil
In-Reply-To: <s5hzjowhp2l.wl%tiwai@suse.de>

On Fri, Nov 22, 2013 at 8:29 AM, Takashi Iwai <tiwai@suse.de> wrote:
>>  config HISAX_TELESPCI
>>       bool "Teles PCI"
>> -     depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV || (XTENSA && !CPU_LITTLE_ENDIAN)))
>> +     depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV || (XTENSA && !CPU_LITTLE_ENDIAN) || (ARM && !CPU_LITTLE_ENDIAN)))
>
> Isn't it a bit better to exclude CPU_LITTLE_ENDIAN globally?
>
>         depends on PCI && CPU_LITTLE_ENDIAN && (BROKEN || !(SPARC || PPC || PARISC || M68K || MIPS || FRV || XTENSA || ARM))

CPU_LITTLE_ENDIAN is not defined on all little endian platforms,
only on those that can support both big and little endian.

But I guess it wouldn't hurt to move CPU_{BIG,LITTLE}_ENDIAN to
a common Kconfig file.

> Or maybe just
>
>         depends on PCI && (X86 || BROKEN)
>
> (Alpha?  Can anyone test? :)

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply

* Re: [PATCH linux-next] hisax: disable build for big-endian arm
From: Takashi Iwai @ 2013-11-22  9:25 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Vincent Stehlé, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org, Linux-Next, Karsten Keil
In-Reply-To: <CAMuHMdXXO2Rnkaac8_-a91Pob53V=Zs7huirCMpA1ha+oWaHBw@mail.gmail.com>

At Fri, 22 Nov 2013 10:19:07 +0100,
Geert Uytterhoeven wrote:
> 
> On Fri, Nov 22, 2013 at 8:29 AM, Takashi Iwai <tiwai@suse.de> wrote:
> >>  config HISAX_TELESPCI
> >>       bool "Teles PCI"
> >> -     depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV || (XTENSA && !CPU_LITTLE_ENDIAN)))
> >> +     depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV || (XTENSA && !CPU_LITTLE_ENDIAN) || (ARM && !CPU_LITTLE_ENDIAN)))
> >
> > Isn't it a bit better to exclude CPU_LITTLE_ENDIAN globally?
> >
> >         depends on PCI && CPU_LITTLE_ENDIAN && (BROKEN || !(SPARC || PPC || PARISC || M68K || MIPS || FRV || XTENSA || ARM))
> 
> CPU_LITTLE_ENDIAN is not defined on all little endian platforms,
> only on those that can support both big and little endian.

Ah, a good point.

> But I guess it wouldn't hurt to move CPU_{BIG,LITTLE}_ENDIAN to
> a common Kconfig file.

Yeah, this make life easier.


thanks,

Takashi

^ permalink raw reply

* [PATCH] net: sched: tbf: fix an oops when a GSO packet cannot be enqueued
From: Yang Yingliang @ 2013-11-22  9:27 UTC (permalink / raw)
  To: davem, netdev; +Cc: eric.dumazet, ben, jpirko, jhs

It seems commit e43ac79a4b("sch_tbf: segment too big GSO packets")
introduce this oops.

When GSO mode is on, use the following command:
tc qdisc add dev eth0 root handle 1: tbf latency 50ms burst 1KB rate 50mbit mtu 1KB
iperf -c host -t 30

Oops happened:

[16884.119862] BUG: unable to handle kernel NULL pointer dereference at 00000000000000c8
[16884.212742] IP: [<ffffffff813dd3e1>] tcp_gso_segment+0x251/0x3a0
[16884.283951] PGD 1f14258067 PUD 1f34e7e067 PMD 0
[16884.338656] Oops: 0000 [#1] SMP
[16884.376851] Modules linked in: sch_tbf(O) tun ip6table_filter ip6_tables iptable_filter ip_tables x_tables edd af_packet bridge stp llc microcode fuse loop dm_mod igb dca i2c_algo_bit ptp ipv6 kvm_intel kvm i2c_i801 sg i2c_core pps_core ehci_pci mptctl pcspkr button iTCO_wdt iTCO_vendor_support lpc_ich mfd_core hid_generic serio_raw ext3 jbd mbcache usbhid hid uhci_hcd ehci_hcd usbcore usb_common sd_mod crc_t10dif crct10dif_common processor thermal_sys hwmon scsi_dh_hp_sw scsi_dh_emc scsi_dh_alua scsi_dh_rdac scsi_dh ata_generic ata_piix libata mptsas mptscsih mptbase scsi_transport_sas scsi_mod [last unloaded: sch_tbf]
[16885.029346] CPU: 15 PID: 546 Comm: iperf Tainted: G           O 3.12.0-rc6-0.7-default+ #7
[16885.127372] Hardware name: Huawei Technologies Co., Ltd. Tecal XH620           /BC21THSA              , BIOS TTSAV020 12/02/2011
[16885.264597] task: ffff881fa8940240 ti: ffff881fbd64e000 task.ti: ffff881fbd64e000
[16885.353331] RIP: 0010:[<ffffffff813dd3e1>]  [<ffffffff813dd3e1>] tcp_gso_segment+0x251/0x3a0
[16885.453424] RSP: 0018:ffff881fbd64f738  EFLAGS: 00010286
[16885.516364] RAX: 000000000ea96820 RBX: 0000000000000000 RCX: 0000000020368706
[16885.600973] RDX: 000000001b1b0000 RSI: 00000000000002c0 RDI: ffff881fa8bfbb70
[16885.685584] RBP: ffff881fbd64f778 R08: 000000000000e93f R09: ffff881fbcaac400
[16885.770191] R10: 0000000000000004 R11: ffff881fbc93e840 R12: ffff881fbcaac510
[16885.854799] R13: ffff881fa8bfbb70 R14: 00000000000005a8 R15: ffff881fa8bfbd70
[16885.939409] FS:  00007f255987e700(0000) GS:ffff88203f3e0000(0000) knlGS:0000000000000000
[16886.035364] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[16886.103466] CR2: 00000000000000c8 CR3: 0000001f13c07000 CR4: 00000000000027e0
[16886.188075] Stack:
[16886.211809]  ffff881fbd64f788 00000020813dd2d5 2068a90e0164230a 0000000000000006
[16886.299540]  ffff881fa8bfbb70 ffff881fa8bfbb98 0000000000000014 0000000390004bb3
[16886.387268]  ffff881fbd64f7d8 ffffffff813ed38d 06ff881fbd64f7e8 0000000000000046
[16886.475000] Call Trace:
[16886.503900]  [<ffffffff813ed38d>] inet_gso_segment+0x14d/0x310
[16886.573036]  [<ffffffff8107093b>] ? try_to_wake_up+0x1eb/0x290
[16886.642187]  [<ffffffff81382c4d>] skb_mac_gso_segment+0xad/0x170
[16886.713392]  [<ffffffff81382d79>] __skb_gso_segment+0x69/0xe0
[16886.781499]  [<ffffffffa0038763>] tbf_enqueue+0x63/0x1e0 [sch_tbf]
[16886.854765]  [<ffffffff81383466>] dev_queue_xmit+0x186/0x440
[16886.921844]  [<ffffffffa08a13d0>] ? br_forward+0x60/0x60 [bridge]
[16886.994078]  [<ffffffffa08a145b>] br_dev_queue_push_xmit+0x8b/0xd0 [bridge]
[16887.076622]  [<ffffffffa08a14f8>] br_forward_finish+0x58/0x60 [bridge]
[16887.154010]  [<ffffffffa08a1578>] __br_deliver+0x78/0x100 [bridge]
[16887.227275]  [<ffffffffa08a163d>] br_deliver+0x3d/0x50 [bridge]
[16887.297439]  [<ffffffffa089f8ae>] br_dev_xmit+0xce/0x230 [bridge]
[16887.369668]  [<ffffffff813830bf>] dev_hard_start_xmit+0x2cf/0x4f0
[16887.441901]  [<ffffffff81383697>] dev_queue_xmit+0x3b7/0x440
[16887.508970]  [<ffffffff8138c4e1>] neigh_resolve_output+0x131/0x200
[16887.582230]  [<ffffffff813bb31d>] ip_finish_output+0x23d/0x440
[16887.651368]  [<ffffffff813bb5a8>] ip_output+0x88/0x90
[16887.711219]  [<ffffffff813b9f34>] ip_local_out+0x24/0x30
[16887.774168]  [<ffffffff813ba3dd>] ip_queue_xmit+0x14d/0x3e0
[16887.840208]  [<ffffffff813d1661>] tcp_transmit_skb+0x501/0x840
[16887.909346]  [<ffffffff813d29b3>] tcp_write_xmit+0x1e3/0xb20
[16887.976415]  [<ffffffff813d335d>] __tcp_push_pending_frames+0x2d/0x70
[16888.052770]  [<ffffffff813c6034>] tcp_sendmsg+0xc74/0xc90
[16888.116751]  [<ffffffff813ec3f1>] inet_sendmsg+0x61/0xc0
[16888.179702]  [<ffffffff81368981>] sock_aio_write+0x101/0x120
[16888.246776]  [<ffffffff8121d530>] ? timerqueue_add+0x60/0xb0
[16888.313851]  [<ffffffff81134720>] do_sync_write+0x60/0x90
[16888.377827]  [<ffffffff81134904>] ? rw_verify_area+0x54/0xf0
[16888.444897]  [<ffffffff81134b26>] vfs_write+0x186/0x190
[16888.506808]  [<ffffffff811353bd>] SyS_write+0x5d/0xa0
[16888.566657]  [<ffffffff8143e0e2>] system_call_fastpath+0x16/0x1b
[16888.637857] Code: 8b 85 80 00 00 00 48 89 83 80 00 00 00 49 8b 45 18 44 89 b3 e8 00 00 00 48 89 43 18 45 29 b5 e8 00 00 00 48 8b 1b 8b 45 d4 0f c8 <44> 0f b7 a3 c8 00 00 00 4c 03 a3 d8 00 00 00 41 89 44 24 04 41
[16888.862165] RIP  [<ffffffff813dd3e1>] tcp_gso_segment+0x251/0x3a0
-----------------------cut here--------------------------------------------

If max_size is too small, a GSO segment cannot be enqueued,
we need to free the segment.

Signed-off-by: Yang Yingliang <yangyingliang@huawei.com>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Ben Hutchings <ben@decadent.org.uk>
Cc: Jiri Pirko <jiri@resnulli.us>
Cc: Jamal Hadi Salim <jhs@mojatatu.com>
---
 net/sched/sch_tbf.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
index 68f9859..f246589 100644
--- a/net/sched/sch_tbf.c
+++ b/net/sched/sch_tbf.c
@@ -140,7 +140,7 @@ static int tbf_segment(struct sk_buff *skb, struct Qdisc *sch)
 			qdisc_skb_cb(segs)->pkt_len = segs->len;
 			ret = qdisc_enqueue(segs, q->qdisc);
 		} else {
-			ret = qdisc_reshape_fail(skb, sch);
+			ret = qdisc_reshape_fail(segs, q->qdisc);
 		}
 		if (ret != NET_XMIT_SUCCESS) {
 			if (net_xmit_drop_count(ret))
-- 
1.7.12

^ permalink raw reply related

* Re: [PATCH] tipc: fix a lockdep warning
From: wangweidong @ 2013-11-22  9:30 UTC (permalink / raw)
  To: Ying Xue, jon.maloy, allan.stephens, davem
  Cc: dingtianhong, netdev, tipc-discussion
In-Reply-To: <528F1F2B.3080205@windriver.com>

On 2013/11/22 17:08, Ying Xue wrote:
> Hi Weidong,
> 
> Please ignore my last mail because you are to fix the issue which is
> different with my mentioned one, and please see my below comments about
> your patch;
> 
> On 11/22/2013 04:18 PM, wangweidong wrote:
>> PC1:tipc-config -netid=1234 -a=1.1.2 -be=eth:eth0/1.1.0
>> PC2:tipc-config -netid=1234 -a=1.1.3 -be=eth:eth0/1.1.0
>>
>> I used a server code Like this:
>> ----------------
>>     sk=socket(AF_TIPC,SOCK_RDM,0);
>>     bind(sk, &addr, len);
>>     while(1) {
>>         recvfrom(sk,...);
>>         ...
>>         sendto(sk,...);
>>     }
>> ----------------
>>
>> when I did ./server in PC1, I got a lockdep as bellow:
>>
>> ======================================================
>> [ INFO: possible circular locking dependency detected ]
>> 3.12.0-lockdep+ #4 Not tainted
>> -------------------------------------------------------
>> server/3772 is trying to acquire lock:
>> (tipc_net_lock){++.-..}, at: [<ffffffffa02e324f>] tipc_link_send+0x2f/0xc0 [tipc]
>>
>> but task is already holding lock:
>> (tipc_nametbl_lock){++--..}, at: [<ffffffffa02e83e6>] tipc_nametbl_publish+0x46/0xc0 [tipc]
>>  which lock already depends on the new lock.
>>
>> the existing dependency chain (in reverse order) is:
>>  -> #1 (tipc_nametbl_lock){++--..}:
>>         [<ffffffff810a2547>] validate_chain+0x6a7/0x7d0
>>         [<ffffffff810a29d1>] __lock_acquire+0x361/0x610
>>         [<ffffffff810a2d62>] lock_acquire+0xe2/0x110
>>         [<ffffffff8151e061>] _raw_write_lock_bh+0x31/0x40
>>         [<ffffffffa02e5d40>] tipc_named_reinit+0x10/0x70 [tipc]
>>         [<ffffffffa02e8512>] tipc_net_start+0x22/0x80 [tipc]
>>         [<ffffffffa02dff0e>] tipc_core_start_net+0xe/0x40 [tipc]
>>         [<ffffffffa02df625>] cfg_set_own_addr+0x75/0xc0 [tipc]
>>         [<ffffffffa02df8f5>] tipc_cfg_do_cmd+0x135/0x550 [tipc]
>>         [<ffffffffa02e87f9>] handle_cmd+0x49/0xe0 [tipc]
>>         [<ffffffff814764fd>] genl_family_rcv_msg+0x22d/0x3c0
>>         [<ffffffff81476700>] genl_rcv_msg+0x70/0xd0
>>         [<ffffffff81474dc9>] netlink_rcv_skb+0x89/0xb0
>>         [<ffffffff81475f87>] genl_rcv+0x27/0x40
>>         [<ffffffff81474b1e>] netlink_unicast+0x14e/0x1a0
>>         [<ffffffff81475735>] netlink_sendmsg+0x245/0x420
>>         [<ffffffff814294f6>] __sock_sendmsg+0x66/0x80
>>         [<ffffffff814295c2>] sock_aio_write+0xb2/0xc0
>>         [<ffffffff811968f0>] do_sync_write+0x60/0x90
>>         [<ffffffff81198891>] vfs_write+0x1d1/0x1e0
>>         [<ffffffff811989bd>] SyS_write+0x5d/0xa0
>>         [<ffffffff81527522>] system_call_fastpath+0x16/0x1b
>>
>>  -> #0 (tipc_net_lock){++.-..}:
>>         [<ffffffff810a1e2e>] check_prev_add+0x41e/0x490
>>         [<ffffffff810a2547>] validate_chain+0x6a7/0x7d0
>>         [<ffffffff810a29d1>] __lock_acquire+0x361/0x610
>>         [<ffffffff810a2d62>] lock_acquire+0xe2/0x110
>>         [<ffffffff8151e2f4>] _raw_read_lock_bh+0x34/0x50
>>         [<ffffffffa02e324f>] tipc_link_send+0x2f/0xc0 [tipc]
>>         [<ffffffffa02e617b>] named_cluster_distribute+0x6b/0x80 [tipc]
>>         [<ffffffffa02e62ab>] tipc_named_publish+0x7b/0x90 [tipc]
>>         [<ffffffffa02e841b>] tipc_nametbl_publish+0x7b/0xc0 [tipc]
>>         [<ffffffffa02e9958>] tipc_publish+0x98/0xf0 [tipc]
>>         [<ffffffffa02ebf58>] bind+0x78/0xb0 [tipc]
>>         [<ffffffff81428dc0>] SyS_bind+0xb0/0xd0
>>         [<ffffffff81527522>] system_call_fastpath+0x16/0x1b
>>
>>  other info that might help us debug this:
>>
>>   Possible unsafe locking scenario:
>>
>>         CPU0                    CPU1
>>         ----                    ----
>>    lock(tipc_nametbl_lock);
>>                                 lock(tipc_net_lock);
>>                                 lock(tipc_nametbl_lock);
>>    lock(tipc_net_lock);
>>
>>   *** DEADLOCK ***
>> ----------------------------------------------------------
>>
>> problem is that tipc_nametbl_publish which will hold tipc_nametbl_lock
>> and acquire tipc_net_lock, while the tipc_net_start which hold
>> tipc_net_lock and acquir tipc_nametbl_lock, so the dead lock occurs.
>>
>> tipc_link_send protected by tipc_net_lock, we can unlock the
>> tipc_nametbl_lock, and it no need the tipc_nametbl_lock to protect it.
>> so I just unlock the tbl_lock before it, and lock the tbl_lock after it.
>>
>> Signed-off-by: Wang Weidong <wangweidong1@huawei.com>
>> ---
>>  net/tipc/name_distr.c | 2 ++
>>  1 file changed, 2 insertions(+)
>>
>> diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c
>> index e0d0805..ab8f96c 100644
>> --- a/net/tipc/name_distr.c
>> +++ b/net/tipc/name_distr.c
>> @@ -138,7 +138,9 @@ static void named_cluster_distribute(struct sk_buff *buf)
>>  			if (!buf_copy)
>>  				break;
>>  			msg_set_destnode(buf_msg(buf_copy), n_ptr->addr);
>> +			write_unlock_bh(&tipc_nametbl_lock);
>>  			tipc_link_send(buf_copy, n_ptr->addr, n_ptr->addr);
>> +			write_lock_bh(&tipc_nametbl_lock);
> 
> We cannot temporarily release/hold tipc_nametbl_lock here, please see
> below call path:
> 
> tipc_nametbl_withdraw()
>   tipc_named_withdraw()
>     named_cluster_distribute()
>       tipc_link_send()
> 
> Especially in tipc_nametbl_withdraw(), we must hold tipc_nametbl_lock to
> protect name table before tipc_named_withdraw() is called. If we
> temporarily release tipc_nametbl_lock in named_cluster_distribute(), I
> am afraid that name table might be changed by another thread at the
> moment, having name table inconsistent possibly.
> 

Hi Ying,
You are right. I will monitor the tipc-discussion mail list.

Thanks. 

> Actually we are implementing another patchset purging the tipc_net_lock
> from TIPC stack. If the patchset is involved, I guess the issue would
> disappear.
> 
> If you have an interesting to see how to purge to tipc_net_lock, please
> monitor tipc-discussion mail list.
> 
> Regards,
> Ying
> 
> 
>>  		}
>>  	}
>>  
>>
> 
> 
> .
> 

^ permalink raw reply

* Re: [PATCH] net: sctp: find the correct highest_new_tsn in sack
From: Neil Horman @ 2013-11-22 11:56 UTC (permalink / raw)
  To: Chang Xiangzhong; +Cc: vyasevich, davem, linux-sctp, netdev, linux-kernel
In-Reply-To: <1385070988-29554-1-git-send-email-changxiangzhong@gmail.com>

On Thu, Nov 21, 2013 at 10:56:28PM +0100, Chang Xiangzhong wrote:
> Function sctp_check_transmitted(transport t, ...) would iterate all of
> transport->transmitted queue and looking for the highest __newly__ acked tsn.
> The original algorithm would depend on the order of the assoc->transport_list
> (in function sctp_outq_sack line 1215 - 1226). The result might not be the
> expected due to the order of the tranport_list.
> 
> Solution: checking if the exising is smaller than the new one before assigning
> 
> Signed-off-by: Chang Xiangzhong <changxiangzhong@gmail.com>
> ---
>  net/sctp/outqueue.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
> index ef9e2bb..1b494fa 100644
> --- a/net/sctp/outqueue.c
> +++ b/net/sctp/outqueue.c
> @@ -1397,7 +1397,8 @@ static void sctp_check_transmitted(struct sctp_outq *q,
>  			 */
>  			if (!tchunk->tsn_gap_acked) {
>  				tchunk->tsn_gap_acked = 1;
> -				*highest_new_tsn_in_sack = tsn;
> +				if (TSN_lt(*highest_new_tsn_in_sack, tsn))
> +					*highest_new_tsn_in_sack = tsn;
>  				bytes_acked += sctp_data_size(tchunk);
>  				if (!tchunk->transport)
>  					migrate_bytes += sctp_data_size(tchunk);
> -- 
> 1.8.4.3
> 
> 

Acked-by: Neil Horman <nhorman@tuxdriver.com>

^ 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