Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH net-next RFC 0/5] xen-netback: TX grant mapping instead of copy
From: Zoltan Kiss @ 2013-11-01 19:00 UTC (permalink / raw)
  To: Ian Campbell; +Cc: wei.liu2, xen-devel, netdev, linux-kernel, jonathan.davies
In-Reply-To: <1383303035.672.29.camel@kazak.uk.xensource.com>

On 01/11/13 10:50, Ian Campbell wrote:
> Does this always avoid copying when bridging/openvswitching/forwarding
> (e.g. masquerading etc)? For both domU->domU and domU->physical NIC?
I've tested the domU->domU, domU->physical with bridge and openvswitch 
usecase, and now I've created a new stat counter to see how often copy 
happens (the callback's second parameter tells you whether the skb was 
freed or copied). It doesn't do copy in all of these scenarios.
What do you mean by forwarding? The scenario when you use bridge and 
iptables mangling with the packet, not just filtering?

> How does it deal with broadcast traffic?
Most of the real broadcast traffic actually small packets fit in the 
PKT_PROT_LEN sized linear space, so it doesn't make any difference, 
apart from doing a mapping before copy. But that will be eliminated 
later on, I plan to add an incremental improvement to grant copy the 
linear part.
I haven't spent too much time on that, but I couldn't find any broadcast 
protocol which use large enough packets and easy to test, so I'm open to 
ideas.
What I already know, skb_clone trigger a copy, and if the caller use the 
original skb for every cloning, it will do several copy. I think that 
could be fixed by using the first clone to do any further clones.

> Do you have any numbers for the dom0 cpu usage impact?
DomU->NIC: the vif took 40% according to top, I guess the bottleneck 
there is the TLB flushing.
DomU->DomU: the vif of the RX side cause the bottleneck due to grant 
copy to the guest

> Aggregate throughput for many guests would be a useful datapoint too.
I will do measurements about that.

 >> Based on my investigations the packet get only copied if it is 
delivered to
 >>Dom0 stack, which is due to this patch:
 >>https://lkml.org/lkml/2012/7/20/363
 >>That's a bit unfortunate, but as far as I know for the huge majority 
this use
 >>case is not too important.
> Likely to be true, but it would still be interesting to know how badly
> this use case suffers with this change, and any increase in CPU usage
> would be interesting to know about as well.
I can't find my numbers, but as far as I remember it wasn't 
significantly worse than grant copy. I will check that again.

Zoli

^ permalink raw reply

* Re: [RFC PATCH 1/2] ipv6: select oif corresponding to source address
From: Sergei Shtylyov @ 2013-11-01 19:42 UTC (permalink / raw)
  To: Emmanuel Thierry, netdev@vger.kernel.org; +Cc: Hannes Frederic Sowa
In-Reply-To: <06F9072B-27A3-4A21-ADE2-A5B3FE817A1F@telecom-bretagne.eu>

Hello.

On 11/01/2013 08:17 PM, Emmanuel Thierry wrote:

> When selecting the next hop, prefer the interface to which the
> source address is associated. This preference fixes problems for
> IPv6 hosts in multi-interfaces setup.

> In the case where a host has:
> * multiple links, each providing internet connectivity
> * both links advertising prefix and default route via Router
> Advertisements

> The current route selection process completly ignores whether or
> not the next hop is consistent with the source address. This may
> lead to packets being sent with a specific source address on the
> wrong link, then dropped by a router enforcing reverse path
> filtering.

> This fix pre-selects the output interface corresponding to the
> source address bound to the socket. The fl6->flowi6_oif
> attribute gives to the route selection algorithm an hint about
> what interface to choose in case of a tie between several routes
> of equal preferences (equal netmask, equal metrics and equal
> RFC 4191 preference values).

> Signed-off-by: Emmanuel Thierry <emmanuel.thierry@telecom-bretagne.eu>
> ---
>   net/ipv6/ip6_output.c |    8 +++++++-
>   1 file changed, 7 insertions(+), 1 deletion(-)

> diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
> index 91fb4e8..1a05395 100644
> --- a/net/ipv6/ip6_output.c
> +++ b/net/ipv6/ip6_output.c
> @@ -848,8 +848,14 @@ static int ip6_dst_lookup_tail(struct sock *sk,
>   #endif
>   	int err;
>
> -	if (*dst == NULL)
> +	if (*dst == NULL) {
> +		struct inet6_ifaddr *ifp;

    Empty line needed between declaration and other code.

> +		if (!ipv6_addr_any(&fl6->saddr)) {
> +			ifp = ipv6_get_ifaddr(net, &fl6->saddr, NULL, 1);
> +			fl6->flowi6_oif = ifp->idev->dev->ifindex;
> +		}
>   		*dst = ip6_route_output(net, sk, fl6);
> +	}
>
>   	if ((err = (*dst)->error))
>   		goto out_err_release;

WBR, Sergei

^ permalink raw reply

* Re: [RFC PATCH 1/2] ipv6: select oif corresponding to source address
From: Hannes Frederic Sowa @ 2013-11-01 18:04 UTC (permalink / raw)
  To: Emmanuel Thierry; +Cc: netdev@vger.kernel.org
In-Reply-To: <06F9072B-27A3-4A21-ADE2-A5B3FE817A1F@telecom-bretagne.eu>

On Fri, Nov 01, 2013 at 06:17:36PM +0100, Emmanuel Thierry wrote:
> --- a/net/ipv6/ip6_output.c
> +++ b/net/ipv6/ip6_output.c
> @@ -848,8 +848,14 @@ static int ip6_dst_lookup_tail(struct sock *sk,
>  #endif
>  	int err;
>  
> -	if (*dst == NULL)
> +	if (*dst == NULL) {
> +		struct inet6_ifaddr *ifp;
> +		if (!ipv6_addr_any(&fl6->saddr)) {
> +			ifp = ipv6_get_ifaddr(net, &fl6->saddr, NULL, 1);
> +			fl6->flowi6_oif = ifp->idev->dev->ifindex;

Cool that you are working on this! :)

Small feedback that might help while you play with this:

You have to be careful here, ipv6_get_ifaddr increments the reference
count of the ifp, so you have to drop it again: in6_ifa_put(ifp);

For such short periods holding a reference does not always make sense. You
could check ipv6_get_lladdr/__ipv6_get_lladdr how you could do this
without touching the reference counters if you put this section in
a rcu_read_lock. This especially makes sense if this is a often used
code path.

> +		}
>  		*dst = ip6_route_output(net, sk, fl6);
> +	}
>  
>  	if ((err = (*dst)->error))
>  		goto out_err_release;

I'll have to think about this carefully.

Thanks,

  Hannes

^ permalink raw reply

* Re: [PATCH] x86: Run checksumming in parallel accross multiple alu's
From: Neil Horman @ 2013-11-01 17:37 UTC (permalink / raw)
  To: David Laight
  Cc: Ben Hutchings, Doug Ledford, Ingo Molnar, Eric Dumazet,
	linux-kernel, netdev
In-Reply-To: <AE90C24D6B3A694183C094C60CF0A2F6026B73D3@saturn3.aculab.com>

On Fri, Nov 01, 2013 at 04:18:50PM -0000, David Laight wrote:
> > How would you suggest replacing the jumps in this case?  I agree it would be
> > faster here, but I'm not sure how I would implement an increment using a single
> > conditional move.
> 
> I think you need 3 instructions, move a 0, conditionally move a 1
> then add. I suspect it won't be a win!
> 
> If you do 'win' it is probably very dependent on how the instructions
> get scheduled onto the execution units - which will probably make
> it very cpu type dependant.
> 
> 	David
> 
I agree, that sounds interesting, but very cpu dependent.  Thanks for the
suggestion, Ben, but I think it would be better if we just did the prefetch here
and re-addressed this area when AVX (or addcx/addox) instructions were available
for testing on hardware.

Neil

^ permalink raw reply

* Re: [RFC PATCH 1/2] ipv6: select oif corresponding to source address
From: Emmanuel Thierry @ 2013-11-01 17:34 UTC (permalink / raw)
  To: netdev@vger.kernel.org; +Cc: Hannes Frederic Sowa
In-Reply-To: <06F9072B-27A3-4A21-ADE2-A5B3FE817A1F@telecom-bretagne.eu>

Hello,

These two rfc patches fix problems stated in "ipv6: strange routing behaviors on a multi-interfaces setup" on 2013-09-25:

> 
> I'm working on multi-interfaces setups on IPv6. I found several disturbing route behaviors which sounds like bugs to me.
> 
> Both eth1 and eth2 interfaces receive RAs from distinct routers and autoconfigure:
> * their slaac address
> * their default route, both with the same priority
> Under these conditions, the following happen depending on the expiration time of each route.
> 
> 
> 1/ A ping with a specified source address and interface may go through the wrong interface.
> 
> # ping6  -c 1 -I "<slaac_eth1>%eth1" <dest>
> … uses the right interface (eth1) with the right source address (<slaac_eth1>).
> 
> # ping6  -c 1 -I "<slaac_eth2>%eth2" <dest>
> … uses the wrong interface (eth1) with the right source address (<slaac_eth2>).
> 
> The ping6 utility performed a bind() on <slaac_ethx> with scope id set to <ifindex_ethx>.
> If we flush the routing cache between each ping, the routing is done as expected.
> 
> As i could observe in the kernel. When ip6_pol_route() is called, oif is equal to <ifindex_eth2> but the flag RT6_LOOKUP_F_IFACE is not set. This makes routes through other interfaces to still be valid.
> Shouldn't we set the RT6_LOOKUP_F_IFACE flag when a scope id is specified ?
> 
> 
> 2/ A ping from a specified source address may go through the wrong interface.
> 
> # ping6  -I "<slaac_eth2>" <dest>
> … may use eth1 with <slaac_eth2>.
> 
> The ping6 utility performed a bind() on <slaac_eth2>
> This is a derivative from the first one, with the significative difference that it also happens if the routing cache is empty. The most recent default route is chosen regardless of the source address.
> 
> Shouldn't we look in a first try for routes on the device corresponding to the source address, and in a second try for others ?
> 
> 
> 3/ A ping from a specified interface may go through the wrong interface with the wrong source address.
> 
> # ping6  -I "eth2" <dest>
> … may use eth1 with <slaac_eth1>.
> 
> The ping6 performs a setsockopt(IPV6_PKTINFO) with <ifindex_ethx>, then a connect() to the destination. In this case, source address selection is concerned, but also routing since source address selection depends on routing.
> 
> 
> I experienced these problems on a 3.11.1 kernel but they look to be quite recurrent in the past versions as well. 
> 

Best regards
Emmanuel Thierry

^ permalink raw reply

* [RFC PATCH 2/2] ipv6: don't use routing cache for inexact matchings
From: Emmanuel Thierry @ 2013-11-01 17:21 UTC (permalink / raw)
  To: netdev@vger.kernel.org; +Cc: Hannes Frederic Sowa
In-Reply-To: <06F9072B-27A3-4A21-ADE2-A5B3FE817A1F@telecom-bretagne.eu>


On route selection, make the cache to be used only when the flow
output interface corresponds to the next hop interface. This
fixes problems for IPv6 hosts in multi-interfaces setup.

When a packet is sent through an interface, the RTF_CACHE entry
is created based on a specific flow information (e.g. with
fl6->flowi6_oif set to a specific value). If another packet is
sent with a different flow information than the first one, the
RTF_CACHE entry is used regardless of flow information, even if
this information would make the route selection algorithm to
select a different route.

By ignoring RTF_CACHE entries for which rt6_check_dev() fails,
we ensure consistency of the route selection algorithm.

Signed-off-by: Emmanuel Thierry <emmanuel.thierry@telecom-bretagne.eu>
---
 net/ipv6/route.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index f54e3a1..65ce3d9 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -595,7 +595,8 @@ static int rt6_score_route(struct rt6_info *rt, int oif,
 	int m;
 
 	m = rt6_check_dev(rt, oif);
-	if (!m && (strict & RT6_LOOKUP_F_IFACE))
+	if (!m &&
+	    ((strict & RT6_LOOKUP_F_IFACE) || (rt->rt6i_flags & RTF_CACHE)))
 		return RT6_NUD_FAIL_HARD;
 #ifdef CONFIG_IPV6_ROUTER_PREF
 	m |= IPV6_DECODE_PREF(IPV6_EXTRACT_PREF(rt->rt6i_flags)) << 2;
-- 
1.7.9.5

^ permalink raw reply related

* [RFC PATCH 1/2] ipv6: select oif corresponding to source address
From: Emmanuel Thierry @ 2013-11-01 17:17 UTC (permalink / raw)
  To: netdev@vger.kernel.org; +Cc: Hannes Frederic Sowa


When selecting the next hop, prefer the interface to which the
source address is associated. This preference fixes problems for
IPv6 hosts in multi-interfaces setup.

In the case where a host has:
* multiple links, each providing internet connectivity
* both links advertising prefix and default route via Router
Advertisements

The current route selection process completly ignores whether or
not the next hop is consistent with the source address. This may
lead to packets being sent with a specific source address on the
wrong link, then dropped by a router enforcing reverse path
filtering.

This fix pre-selects the output interface corresponding to the
source address bound to the socket. The fl6->flowi6_oif
attribute gives to the route selection algorithm an hint about
what interface to choose in case of a tie between several routes
of equal preferences (equal netmask, equal metrics and equal
RFC 4191 preference values).

Signed-off-by: Emmanuel Thierry <emmanuel.thierry@telecom-bretagne.eu>
---
 net/ipv6/ip6_output.c |    8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 91fb4e8..1a05395 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -848,8 +848,14 @@ static int ip6_dst_lookup_tail(struct sock *sk,
 #endif
 	int err;
 
-	if (*dst == NULL)
+	if (*dst == NULL) {
+		struct inet6_ifaddr *ifp;
+		if (!ipv6_addr_any(&fl6->saddr)) {
+			ifp = ipv6_get_ifaddr(net, &fl6->saddr, NULL, 1);
+			fl6->flowi6_oif = ifp->idev->dev->ifindex;
+		}
 		*dst = ip6_route_output(net, sk, fl6);
+	}
 
 	if ((err = (*dst)->error))
 		goto out_err_release;
-- 
1.7.9.5

^ permalink raw reply related

* Re: [PATCH] phy: Add MOXA RTL8201CP PHY support
From: Kishon Vijay Abraham I @ 2013-11-01 17:17 UTC (permalink / raw)
  To: Jonas Jensen, netdev, David Miller
  Cc: linux-arm-kernel, linux-kernel, devicetree
In-Reply-To: <1383317673-14704-1-git-send-email-jonas.jensen@gmail.com>

Hi Jonas,

On Friday 01 November 2013 08:24 PM, Jonas Jensen wrote:

> The MOXA UC-711X hardware(s) has an ethernet controller that seem
> to be developed internally. The IC used is "RTL8201CP".
>
> This patch adds an MDIO driver and also patches realtek to include
> RTL8201CP PHY driver.
>
> Signed-off-by: Jonas Jensen <jonas.jensen@gmail.com>

Added netdev mailing list and David Miller as I don't maintain ethernet 
PHYs.

Thanks
Kishon

> ---
>
> Notes:
>      The hardware does not use a separate IRQ for PHY.
>
>      The link state change interrupt can instead be caught by MAC but the
>      current drivers/of/of_mdio.c does not allow it to be handled in MAC.
>
>      Applies to next-20131031
>
>   .../devicetree/bindings/net/moxa,moxart-mdio.txt   |  19 ++
>   drivers/net/phy/Kconfig                            |   7 +
>   drivers/net/phy/Makefile                           |   1 +
>   drivers/net/phy/mdio-moxart.c                      | 201 +++++++++++++++++++++
>   drivers/net/phy/realtek.c                          |  15 ++
>   5 files changed, 243 insertions(+)
>   create mode 100644 Documentation/devicetree/bindings/net/moxa,moxart-mdio.txt
>   create mode 100644 drivers/net/phy/mdio-moxart.c
>
> diff --git a/Documentation/devicetree/bindings/net/moxa,moxart-mdio.txt b/Documentation/devicetree/bindings/net/moxa,moxart-mdio.txt
> new file mode 100644
> index 0000000..de0b90c
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/moxa,moxart-mdio.txt
> @@ -0,0 +1,19 @@
> +* MOXA ART MDIO Ethernet Controller interface
> +
> +Required properties:
> +- compatible: should be "moxa,moxart-mdio".
> +- reg: address and length of the register set for the device.
> +
> +Example:
> +mdio1: mdio@92000090 {
> +	compatible = "moxa,moxart-mdio";
> +	reg = <0x92000090 0x8>;
> +	#address-cells = <1>;
> +	#size-cells = <0>;
> +
> +	ethphy1: ethernet-phy@1 {
> +		device_type = "ethernet-phy";
> +		compatible = "moxa,moxart-rtl8201cp";
> +		reg = <1>;
> +	};
> +};
> diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
> index 342561a..9b5d46c 100644
> --- a/drivers/net/phy/Kconfig
> +++ b/drivers/net/phy/Kconfig
> @@ -154,6 +154,13 @@ config MDIO_SUN4I
>   	  interface units of the Allwinner SoC that have an EMAC (A10,
>   	  A12, A10s, etc.)
>
> +config MDIO_MOXART
> +        tristate "MOXA ART MDIO interface support"
> +        depends on ARCH_MOXART
> +        help
> +          This driver supports the MDIO interface found in the network
> +          interface units of the MOXA ART SoC
> +
>   config MDIO_BUS_MUX
>   	tristate
>   	depends on OF_MDIO
> diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
> index 23a2ab2..9013dfa 100644
> --- a/drivers/net/phy/Makefile
> +++ b/drivers/net/phy/Makefile
> @@ -31,3 +31,4 @@ obj-$(CONFIG_MDIO_BUS_MUX)	+= mdio-mux.o
>   obj-$(CONFIG_MDIO_BUS_MUX_GPIO)	+= mdio-mux-gpio.o
>   obj-$(CONFIG_MDIO_BUS_MUX_MMIOREG) += mdio-mux-mmioreg.o
>   obj-$(CONFIG_MDIO_SUN4I)	+= mdio-sun4i.o
> +obj-$(CONFIG_MDIO_MOXART)	+= mdio-moxart.o
> diff --git a/drivers/net/phy/mdio-moxart.c b/drivers/net/phy/mdio-moxart.c
> new file mode 100644
> index 0000000..ad5d0f8
> --- /dev/null
> +++ b/drivers/net/phy/mdio-moxart.c
> @@ -0,0 +1,201 @@
> +/* MOXA ART Ethernet (RTL8201CP) MDIO interface driver
> + *
> + * Copyright (C) 2013 Jonas Jensen <jonas.jensen@gmail.com>
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2.  This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#include <linux/delay.h>
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/of_address.h>
> +#include <linux/of_mdio.h>
> +#include <linux/phy.h>
> +#include <linux/platform_device.h>
> +#include <linux/regulator/consumer.h>
> +
> +#define REG_PHY_CTRL            0
> +#define REG_PHY_WRITE_DATA      4
> +
> +/* REG_PHY_CTRL */
> +#define MIIWR                   BIT(27) /* init write sequence (auto cleared)*/
> +#define MIIRD                   BIT(26)
> +#define REGAD_MASK              0x3e00000
> +#define PHYAD_MASK              0x1f0000
> +#define MIIRDATA_MASK           0xffff
> +
> +/* REG_PHY_WRITE_DATA */
> +#define MIIWDATA_MASK           0xffff
> +
> +struct moxart_mdio_data {
> +	void __iomem		*base;
> +};
> +
> +static int moxart_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
> +{
> +	struct moxart_mdio_data *data = bus->priv;
> +	u32 ctrl = 0;
> +	unsigned int count = 5;
> +
> +	dev_dbg(&bus->dev, "%s\n", __func__);
> +
> +	ctrl |= MIIRD | ((mii_id << 16) & PHYAD_MASK) |
> +		((regnum << 21) & REGAD_MASK);
> +
> +	writel(ctrl, data->base + REG_PHY_CTRL);
> +
> +	do {
> +		ctrl = readl(data->base + REG_PHY_CTRL);
> +
> +		if (!(ctrl & MIIRD))
> +			return ctrl & MIIRDATA_MASK;
> +
> +		mdelay(10);
> +		count--;
> +	} while (count > 0);
> +
> +	dev_err(&bus->dev, "%s timed out\n", __func__);
> +
> +	return -ETIMEDOUT;
> +}
> +
> +static int moxart_mdio_write(struct mii_bus *bus, int mii_id,
> +			     int regnum, u16 value)
> +{
> +	struct moxart_mdio_data *data = bus->priv;
> +	u32 ctrl = 0;
> +	unsigned int count = 5;
> +
> +	dev_dbg(&bus->dev, "%s\n", __func__);
> +
> +	ctrl |= MIIWR | ((mii_id << 16) & PHYAD_MASK) |
> +		((regnum << 21) & REGAD_MASK);
> +
> +	value &= MIIWDATA_MASK;
> +
> +	writel(value, data->base + REG_PHY_WRITE_DATA);
> +	writel(ctrl, data->base + REG_PHY_CTRL);
> +
> +	do {
> +		ctrl = readl(data->base + REG_PHY_CTRL);
> +
> +		if (!(ctrl & MIIWR))
> +			return 0;
> +
> +		mdelay(10);
> +		count--;
> +	} while (count > 0);
> +
> +	dev_err(&bus->dev, "%s timed out\n", __func__);
> +
> +	return -ETIMEDOUT;
> +}
> +
> +static int moxart_mdio_reset(struct mii_bus *bus)
> +{
> +	int data, i;
> +
> +	for (i = 0; i < PHY_MAX_ADDR; i++) {
> +		data = moxart_mdio_read(bus, i, MII_BMCR);
> +		if (data < 0)
> +			continue;
> +
> +		data |= BMCR_RESET;
> +		if (moxart_mdio_write(bus, i, MII_BMCR, data) < 0)
> +			continue;
> +	}
> +
> +	return 0;
> +}
> +
> +static int moxart_mdio_probe(struct platform_device *pdev)
> +{
> +	struct device_node *np = pdev->dev.of_node;
> +	struct mii_bus *bus;
> +	struct moxart_mdio_data *data;
> +	struct resource *res;
> +	int ret, i;
> +
> +	bus = mdiobus_alloc_size(sizeof(*data));
> +	if (!bus)
> +		return -ENOMEM;
> +
> +	bus->name = "MOXA ART Ethernet MII";
> +	bus->read = &moxart_mdio_read;
> +	bus->write = &moxart_mdio_write;
> +	bus->reset = &moxart_mdio_reset;
> +	snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii", dev_name(&pdev->dev));
> +	bus->parent = &pdev->dev;
> +
> +	bus->irq = devm_kzalloc(&pdev->dev, sizeof(int) * PHY_MAX_ADDR,
> +			GFP_KERNEL);
> +	if (!bus->irq) {
> +		ret = -ENOMEM;
> +		goto err_out_free_mdiobus;
> +	}
> +
> +	/* Setting PHY_IGNORE_INTERRUPT here even if it has no effect,
> +	 * of_mdiobus_register() sets these PHY_POLL.
> +	 * Ideally, the interrupt from MAC controller could be used to
> +	 * detect link state changes, not polling, i.e. if there was
> +	 * a way phy_driver could set PHY_HAS_INTERRUPT but have that
> +	 * interrupt handled in ethernet drivercode.
> +	 */
> +	for (i = 0; i < PHY_MAX_ADDR; i++)
> +		bus->irq[i] = PHY_IGNORE_INTERRUPT;
> +
> +	data = bus->priv;
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	data->base = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(data->base)) {
> +		ret = PTR_ERR(data->base);
> +		goto err_out_free_mdiobus;
> +	}
> +
> +	ret = of_mdiobus_register(bus, np);
> +	if (ret < 0)
> +		return ret;
> +
> +	platform_set_drvdata(pdev, bus);
> +
> +	return 0;
> +
> +err_out_free_mdiobus:
> +	mdiobus_free(bus);
> +	return ret;
> +}
> +
> +static int moxart_mdio_remove(struct platform_device *pdev)
> +{
> +	struct mii_bus *bus = platform_get_drvdata(pdev);
> +
> +	mdiobus_unregister(bus);
> +	mdiobus_free(bus);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id moxart_mdio_dt_ids[] = {
> +	{ .compatible = "moxa,moxart-mdio" },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(of, moxart_mdio_dt_ids);
> +
> +static struct platform_driver moxart_mdio_driver = {
> +	.probe = moxart_mdio_probe,
> +	.remove = moxart_mdio_remove,
> +	.driver = {
> +		.name = "moxart-mdio",
> +		.of_match_table = moxart_mdio_dt_ids,
> +	},
> +};
> +
> +module_platform_driver(moxart_mdio_driver);
> +
> +MODULE_DESCRIPTION("MOXA ART MDIO interface driver");
> +MODULE_AUTHOR("Jonas Jensen <jonas.jensen@gmail.com>");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
> index 138de83..fa1d69a 100644
> --- a/drivers/net/phy/realtek.c
> +++ b/drivers/net/phy/realtek.c
> @@ -64,6 +64,18 @@ static int rtl8211e_config_intr(struct phy_device *phydev)
>   	return err;
>   }
>
> +/* RTL8201CP */
> +static struct phy_driver rtl8201cp_driver = {
> +	.phy_id         = 0x00008201,
> +	.name           = "RTL8201CP Ethernet",
> +	.phy_id_mask    = 0x0000ffff,
> +	.features       = PHY_BASIC_FEATURES,
> +	.flags          = PHY_HAS_INTERRUPT,
> +	.config_aneg    = &genphy_config_aneg,
> +	.read_status    = &genphy_read_status,
> +	.driver         = { .owner = THIS_MODULE,},
> +};
> +
>   /* RTL8211B */
>   static struct phy_driver rtl8211b_driver = {
>   	.phy_id		= 0x001cc912,
> @@ -98,6 +110,9 @@ static int __init realtek_init(void)
>   {
>   	int ret;
>
> +	ret = phy_driver_register(&rtl8201cp_driver);
> +	if (ret < 0)
> +		return -ENODEV;
>   	ret = phy_driver_register(&rtl8211b_driver);
>   	if (ret < 0)
>   		return -ENODEV;
>

^ permalink raw reply

* Re: [PATCH net] net: flow_dissector: fail on evil iph->ihl
From: Ben Hutchings @ 2013-11-01 16:29 UTC (permalink / raw)
  To: Jason Wang
  Cc: davem, edumazet, netdev, linux-kernel, Petr Matousek,
	Michael S. Tsirkin, Daniel Borkmann
In-Reply-To: <1383289270-18952-1-git-send-email-jasowang@redhat.com>

On Fri, 2013-11-01 at 15:01 +0800, Jason Wang wrote:
> We don't validate iph->ihl which may lead a dead loop if we meet a IPIP
> skb whose iph->ihl is zero. Fix this by failing immediately when iph->ihl
> is evil (less than 5).
> 
> This issue were introduced by commit ec5efe7946280d1e84603389a1030ccec0a767ae
> (rps: support IPIP encapsulation).

It would be helpful to include the CVE ID here:

CVE-2013-4348

Ben.

> Cc: Eric Dumazet <edumazet@google.com>
> Cc: Petr Matousek <pmatouse@redhat.com>
> Cc: Michael S. Tsirkin <mst@redhat.com>
> Cc: Daniel Borkmann <dborkman@redhat.com>
> Signed-off-by: Jason Wang <jasowang@redhat.com>
> ---
> This patch is needed for stable.
> ---
>  net/core/flow_dissector.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
> index 8d7d0dd..143b6fd 100644
> --- a/net/core/flow_dissector.c
> +++ b/net/core/flow_dissector.c
> @@ -40,7 +40,7 @@ again:
>  		struct iphdr _iph;
>  ip:
>  		iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph);
> -		if (!iph)
> +		if (!iph || iph->ihl < 5)
>  			return false;
>  
>  		if (ip_is_fragment(iph))

-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply

* RE: [PATCH] x86: Run checksumming in parallel accross multiple alu's
From: David Laight @ 2013-11-01 16:18 UTC (permalink / raw)
  To: Neil Horman, Ben Hutchings
  Cc: Doug Ledford, Ingo Molnar, Eric Dumazet, linux-kernel, netdev
In-Reply-To: <20131101160802.GB8467@hmsreliant.think-freely.org>

> How would you suggest replacing the jumps in this case?  I agree it would be
> faster here, but I'm not sure how I would implement an increment using a single
> conditional move.

I think you need 3 instructions, move a 0, conditionally move a 1
then add. I suspect it won't be a win!

If you do 'win' it is probably very dependent on how the instructions
get scheduled onto the execution units - which will probably make
it very cpu type dependant.

	David

^ permalink raw reply

* [PATCH net-next 1/1] ipv6: remove the destination condition on flow label sharing
From: Florent Fourcot @ 2013-11-01 16:11 UTC (permalink / raw)
  To: netdev; +Cc: Florent Fourcot

In case of label sharing, it should be possible to use
one label to more than one destination. This
old restriction is not mandatory, so we can remove it.

Signed-off-by: Florent Fourcot <florent.fourcot@enst-bretagne.fr>
---
 net/ipv6/ip6_flowlabel.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index 46e8843..f8102d0 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -604,8 +604,7 @@ recheck:
 					goto release;

 				err = -EINVAL;
-				if (!ipv6_addr_equal(&fl1->dst, &fl->dst) ||
-				    ipv6_opt_cmp(fl1->opt, fl->opt))
+				if (ipv6_opt_cmp(fl1->opt, fl->opt))
 					goto release;

 				err = -ENOMEM;
--
1.8.4.rc3

^ permalink raw reply related

* Re: [PATCH] x86: Run checksumming in parallel accross multiple alu's
From: Ben Hutchings @ 2013-11-01 16:16 UTC (permalink / raw)
  To: Neil Horman
  Cc: Doug Ledford, Ingo Molnar, Eric Dumazet, linux-kernel, netdev,
	David Laight
In-Reply-To: <20131101160802.GB8467@hmsreliant.think-freely.org>

On Fri, 2013-11-01 at 12:08 -0400, Neil Horman wrote:
> On Fri, Nov 01, 2013 at 03:42:46PM +0000, Ben Hutchings wrote:
> > On Thu, 2013-10-31 at 14:30 -0400, Neil Horman wrote:
> > [...]
> > > It
> > > functions, but unfortunately the performance lost to the completely broken
> > > branch prediction that this inflicts makes it a non starter:
> > [...]
> > 
> > Conditional branches are no good but conditional moves might be worth a shot.
> > 
> > Ben.
> > 
> How would you suggest replacing the jumps in this case?  I agree it would be
> faster here, but I'm not sure how I would implement an increment using a single
> conditional move.

You can't, but it lets you use additional registers as carry flags.
Whether there are enough registers and enough parallelism to cancel out
the extra additions required, I don't know.

Ben.

-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply

* Re: [PATCH net-next] tcp: enable sockets to use MSG_FASTOPEN by default
From: Yuchung Cheng @ 2013-11-01 16:09 UTC (permalink / raw)
  To: Rick Jones
  Cc: Eric Dumazet, David Miller, Eric Dumazet, netdev, Neal Cardwell,
	Sivasankar Radhakrishnan
In-Reply-To: <5273C8D1.5080608@hp.com>

On Fri, Nov 1, 2013 at 8:29 AM, Rick Jones <rick.jones2@hp.com> wrote:
> On 10/31/2013 04:19 PM, Eric Dumazet wrote:
>>
>> On Thu, 2013-10-31 at 09:19 -0700, Yuchung Cheng wrote:
>>>
>>> Applications have started to use Fast Open (e.g., Chrome browser has
>>> such an optional flag) and the feature has gone through several
>>> generations of kernels since 3.7 with many real network tests. It's
>>> time to enable this flag by default for applications to test more
>>> conveniently and extensively.
>>>
>>> Signed-off-by: Yuchung Cheng <ycheng@google.com>
>>> Signed-off-by: Neal Cardwell <ncardwell@google.com>
>>> ---
>>
>>
>> Acked-by: Eric Dumazet <edumazet@google.com>
>
>
> Which TCP/IP stacks besides Linux have Fast Open at this point and for how
> long have they had it?  Basically, how prevalent are servers out there (both
> Internet and intranet) with support for Fast Open?
google.com supports it. we are working on enabling more Android and
ChromeOS to use it.

>
> http://news.netcraft.com/archives/2013/11/01/november-2013-web-server-survey.html
> doesn't go down to the OS level, and
> http://www.netcraft.com/internet-data-mining/ssl-survey/ is only from May
> and was in the context of SSL sides, but it does provide an interesting
> break-down of "OS share" which looks reasonably stable going back three
> years and so probably isn't too far off presently.
>
> <insert the same sort of question about those firewalls and intermediate
> devices which make our lives so much fun here>
>
> rick jones
>

^ permalink raw reply

* Re: [Xen-devel] [PATCH net-next RFC 2/5] xen-netback: Change TX path from grant copy to mapping
From: Zoltan Kiss @ 2013-11-01 16:09 UTC (permalink / raw)
  To: Paul Durrant, Ian Campbell, Wei Liu,
	xen-devel@lists.xenproject.org, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org, Jonathan Davies, David Vrabel
In-Reply-To: <527175DB.8070400@citrix.com>

On 30/10/13 21:10, Zoltan Kiss wrote:
> On 30/10/13 09:11, Paul Durrant wrote:
>>> +    err = alloc_xenballooned_pages(MAX_PENDING_REQS,
>>> +        vif->mmap_pages,
>>> +        false);
>>
>> Since this is a per-vif allocation, is this going to scale?
> Good question, I'll look after this.
I've talked to David Vrabel about this: if ballooning is disabled, this 
will reserve real memory, therefore for every VIF you allocate usually 
1MB memory. But if you enable ballooning, it will use pages which are 
not actually reserved, and that's fine, because we never gonna really 
use them. The only issue is that you need to set the maximum at boot 
time, and it will consume memory also because of the page table 
reservations.
The long term solution would be to just use a bunch of struct pages, 
David said the ballooning driver has something like that, but it's 
broken at the moment.

>>>           if (data_len < txp->size) {
>>>               /* Append the packet payload as a fragment. */
>>>               txp->offset += data_len;
>>>               txp->size -= data_len;
>>> -        } else {
>>> +            skb_shinfo(skb)->destructor_arg =
>>> +                &vif-
>>>> pending_tx_info[pending_idx].callback_struct;
>>> +        } else if (!skb_shinfo(skb)->nr_frags) {
>>>               /* Schedule a response immediately. */
>>> +            skb_shinfo(skb)->destructor_arg = NULL;
>>> +            xenvif_idx_unmap(vif, pending_idx);
>>>               xenvif_idx_release(vif, pending_idx,
>>>                          XEN_NETIF_RSP_OKAY);
>>> +        } else {
>>> +            /* FIXME: first request fits linear space, I don't know
>>> +             * if any guest would do that, but I think it's possible
>>> +             */
>>
>> The Windows frontend, because it has to parse the packet headers, will
>> coalesce everything up to the payload in a single frag and it would be
>> a good idea to copy this directly into the linear area.
> I forgot to clarify this comment: the problem I wanted to handle here if
> the first request's size is PKT_PROT_LEN and there is more fragments.
> Then skb->len will be PKT_PROT_LEN as well, and the if statement falls
> through to the else branch. That might be problematic if we release the
> slot of the first request separately from the others. Or am I
> overlooking something? Does that matter to netfront anyway?
> And this problem, if it's true, applies to the previous, grant copy
> method as well.
> However, as I think, it might be better to change the condition to
> (data_len <= txp->size), rather than putting an if-else statement into
> the else branch.
I've talked to Wei, we think this is a broken guest behaviour, and 
therefore we shouldn't care if someone does such a stupid thing.

Zoli

^ permalink raw reply

* Re: [PATCH] x86: Run checksumming in parallel accross multiple alu's
From: Neil Horman @ 2013-11-01 16:08 UTC (permalink / raw)
  To: Ben Hutchings
  Cc: Doug Ledford, Ingo Molnar, Eric Dumazet, linux-kernel, netdev,
	David Laight
In-Reply-To: <1383320566.1737.0.camel@bwh-desktop.uk.level5networks.com>

On Fri, Nov 01, 2013 at 03:42:46PM +0000, Ben Hutchings wrote:
> On Thu, 2013-10-31 at 14:30 -0400, Neil Horman wrote:
> [...]
> > It
> > functions, but unfortunately the performance lost to the completely broken
> > branch prediction that this inflicts makes it a non starter:
> [...]
> 
> Conditional branches are no good but conditional moves might be worth a shot.
> 
> Ben.
> 
How would you suggest replacing the jumps in this case?  I agree it would be
faster here, but I'm not sure how I would implement an increment using a single
conditional move.
Neil

> -- 
> Ben Hutchings, Staff Engineer, Solarflare
> Not speaking for my employer; that's the marketing department's job.
> They asked us to note that Solarflare product names are trademarked.
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply

* Re: [PATCH] x86: Run checksumming in parallel accross multiple alu's
From: Ben Hutchings @ 2013-11-01 15:42 UTC (permalink / raw)
  To: Neil Horman
  Cc: Doug Ledford, Ingo Molnar, Eric Dumazet, linux-kernel, netdev,
	David Laight
In-Reply-To: <20131031183003.GC25894@hmsreliant.think-freely.org>

On Thu, 2013-10-31 at 14:30 -0400, Neil Horman wrote:
[...]
> It
> functions, but unfortunately the performance lost to the completely broken
> branch prediction that this inflicts makes it a non starter:
[...]

Conditional branches are no good but conditional moves might be worth a shot.

Ben.

-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply

* Re: [PATCH v2] WAN: Adding support for Infineon PEF2256 E1 chipset (FALC56)
From: Govindarajulu Varadarajan @ 2013-11-01 15:36 UTC (permalink / raw)
  To: Christophe Leroy
  Cc: Rob Herring, Pawel Moll, Mark Rutland, Stephen Warren,
	Ian Campbell, Rob Landley, Grant Likely, Krzysztof Halasa,
	devicetree, linux-doc, linux-kernel, netdev, devicetree,
	jerome.chantelauze.ext
In-Reply-To: <201311011501.rA1F1suj007279@localhost.localdomain>



On Fri, 1 Nov 2013, Christophe Leroy wrote:

> diff -urN a/drivers/net/wan/pef2256.c b/drivers/net/wan/pef2256.c
[..]
> +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_regs);
> +	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->base_addr);
> +
> +	kfree(priv);
> +
> +	dev_set_drvdata(&pdev->dev, NULL);

dev_set_drvdata is not necessary. driver core clears the driver data to NULL
after device_release or on probe failure.

//govind

^ permalink raw reply

* Re: [PATCH net-next] tcp: enable sockets to use MSG_FASTOPEN by default
From: Rick Jones @ 2013-11-01 15:29 UTC (permalink / raw)
  To: Eric Dumazet, Yuchung Cheng
  Cc: davem, edumazet, netdev, ncardwell, sivasankar
In-Reply-To: <1383261598.19864.0.camel@edumazet-glaptop2.roam.corp.google.com>

On 10/31/2013 04:19 PM, Eric Dumazet wrote:
> On Thu, 2013-10-31 at 09:19 -0700, Yuchung Cheng wrote:
>> Applications have started to use Fast Open (e.g., Chrome browser has
>> such an optional flag) and the feature has gone through several
>> generations of kernels since 3.7 with many real network tests. It's
>> time to enable this flag by default for applications to test more
>> conveniently and extensively.
>>
>> Signed-off-by: Yuchung Cheng <ycheng@google.com>
>> Signed-off-by: Neal Cardwell <ncardwell@google.com>
>> ---
>
> Acked-by: Eric Dumazet <edumazet@google.com>

Which TCP/IP stacks besides Linux have Fast Open at this point and for 
how long have they had it?  Basically, how prevalent are servers out 
there (both Internet and intranet) with support for Fast Open?

http://news.netcraft.com/archives/2013/11/01/november-2013-web-server-survey.html 
  doesn't go down to the OS level, and 
http://www.netcraft.com/internet-data-mining/ssl-survey/ is only from 
May and was in the context of SSL sides, but it does provide an 
interesting break-down of "OS share" which looks reasonably stable going 
back three years and so probably isn't too far off presently.

<insert the same sort of question about those firewalls and intermediate 
devices which make our lives so much fun here>

rick jones

^ permalink raw reply

* [PATCH v2] WAN: Adding support for Infineon PEF2256 E1 chipset (FALC56)
From: Christophe Leroy @ 2013-11-01 15:01 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 Infineon 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,1197 @@
+/* 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 irqreturn_t pef2256_irq(int irq, void *dev_priv);
+static int Config_HDLC(struct pef2256_dev_priv *priv);
+static int init_FALC(struct pef2256_dev_priv *priv);
+static int pef2256_open(struct net_device *netdev);
+static int pef2256_close(struct net_device *netdev);
+
+void print_regs(struct device *dev)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct pef2256_dev_priv *priv = dev_to_hdlc(ndev)->priv;
+	unsigned char *base_addr = priv->base_addr;
+
+	netdev_info(ndev, "	MODE = 0x%02x\n", readb(base_addr + MODE));
+	netdev_info(ndev, "	RAH1 = 0x%02x\n", readb(base_addr + RAH1));
+	netdev_info(ndev, "	RAH2 = 0x%02x\n", readb(base_addr + RAH2));
+	netdev_info(ndev, "	RAL1 = 0x%02x\n", readb(base_addr + RAL1));
+	netdev_info(ndev, "	RAL2 = 0x%02x\n", readb(base_addr + RAL2));
+	netdev_info(ndev, "	IPC = 0x%02x\n", readb(base_addr + IPC));
+	netdev_info(ndev, "	CCR1 = 0x%02x\n", readb(base_addr + CCR1));
+	netdev_info(ndev, "	CCR2 = 0x%02x\n", readb(base_addr + CCR2));
+	netdev_info(ndev, "	RTR1 = 0x%02x\n", readb(base_addr + RTR1));
+	netdev_info(ndev, "	RTR2 = 0x%02x\n", readb(base_addr + RTR2));
+	netdev_info(ndev, "	RTR3 = 0x%02x\n", readb(base_addr + RTR3));
+	netdev_info(ndev, "	RTR4 = 0x%02x\n", readb(base_addr + RTR4));
+	netdev_info(ndev, "	TTR1 = 0x%02x\n", readb(base_addr + TTR1));
+	netdev_info(ndev, "	TTR2 = 0x%02x\n", readb(base_addr + TTR2));
+	netdev_info(ndev, "	TTR3 = 0x%02x\n", readb(base_addr + TTR3));
+	netdev_info(ndev, "	TTR4 = 0x%02x\n", readb(base_addr + TTR4));
+	netdev_info(ndev, "	IMR0 = 0x%02x\n", readb(base_addr + IMR0));
+	netdev_info(ndev, "	IMR1 = 0x%02x\n", readb(base_addr + IMR1));
+	netdev_info(ndev, "	IMR2 = 0x%02x\n", readb(base_addr + IMR2));
+	netdev_info(ndev, "	IMR3 = 0x%02x\n", readb(base_addr + IMR3));
+	netdev_info(ndev, "	IMR4 = 0x%02x\n", readb(base_addr + IMR4));
+	netdev_info(ndev, "	IMR5 = 0x%02x\n", readb(base_addr + IMR5));
+	netdev_info(ndev, "	IERR = 0x%02x\n", readb(base_addr + IERR));
+	netdev_info(ndev, "	FMR0 = 0x%02x\n", readb(base_addr + FMR0));
+	netdev_info(ndev, "	FMR1 = 0x%02x\n", readb(base_addr + FMR1));
+	netdev_info(ndev, "	FMR2 = 0x%02x\n", readb(base_addr + FMR2));
+	netdev_info(ndev, "	LOOP = 0x%02x\n", readb(base_addr + LOOP));
+	netdev_info(ndev, "	XSW = 0x%02x\n", readb(base_addr + XSW));
+	netdev_info(ndev, "	XSP = 0x%02x\n", readb(base_addr + XSP));
+	netdev_info(ndev, "	XC0 = 0x%02x\n", readb(base_addr + XC0));
+	netdev_info(ndev, "	XC1 = 0x%02x\n", readb(base_addr + XC1));
+	netdev_info(ndev, "	RC0 = 0x%02x\n", readb(base_addr + RC0));
+	netdev_info(ndev, "	RC1 = 0x%02x\n", readb(base_addr + RC1));
+	netdev_info(ndev, "	XPM0 = 0x%02x\n", readb(base_addr + XPM0));
+	netdev_info(ndev, "	XPM1 = 0x%02x\n", readb(base_addr + XPM1));
+	netdev_info(ndev, "	XPM2 = 0x%02x\n", readb(base_addr + XPM2));
+	netdev_info(ndev, "	TSWM = 0x%02x\n", readb(base_addr + TSWM));
+	netdev_info(ndev, "	IDLE = 0x%02x\n", readb(base_addr + IDLE));
+	netdev_info(ndev, "	XSA4 = 0x%02x\n", readb(base_addr + XSA4));
+	netdev_info(ndev, "	XSA5 = 0x%02x\n", readb(base_addr + XSA5));
+	netdev_info(ndev, "	XSA6 = 0x%02x\n", readb(base_addr + XSA6));
+	netdev_info(ndev, "	XSA7 = 0x%02x\n", readb(base_addr + XSA7));
+	netdev_info(ndev, "	XSA8 = 0x%02x\n", readb(base_addr + XSA8));
+	netdev_info(ndev, "	FMR3 = 0x%02x\n", readb(base_addr + FMR3));
+	netdev_info(ndev, "	ICB1 = 0x%02x\n", readb(base_addr + ICB1));
+	netdev_info(ndev, "	ICB2 = 0x%02x\n", readb(base_addr + ICB2));
+	netdev_info(ndev, "	ICB3 = 0x%02x\n", readb(base_addr + ICB3));
+	netdev_info(ndev, "	ICB4 = 0x%02x\n", readb(base_addr + ICB4));
+	netdev_info(ndev, "	LIM0 = 0x%02x\n", readb(base_addr + LIM0));
+	netdev_info(ndev, "	LIM1 = 0x%02x\n", readb(base_addr + LIM1));
+	netdev_info(ndev, "	PCD = 0x%02x\n", readb(base_addr + PCD));
+	netdev_info(ndev, "	PCR = 0x%02x\n", readb(base_addr + PCR));
+	netdev_info(ndev, "	LIM2 = 0x%02x\n", readb(base_addr + LIM2));
+	netdev_info(ndev, "	LCR1 = 0x%02x\n", readb(base_addr + LCR1));
+	netdev_info(ndev, "	LCR2 = 0x%02x\n", readb(base_addr + LCR2));
+	netdev_info(ndev, "	LCR3 = 0x%02x\n", readb(base_addr + LCR3));
+	netdev_info(ndev, "	SIC1 = 0x%02x\n", readb(base_addr + SIC1));
+	netdev_info(ndev, "	SIC2 = 0x%02x\n", readb(base_addr + SIC2));
+	netdev_info(ndev, "	SIC3 = 0x%02x\n", readb(base_addr + SIC3));
+	netdev_info(ndev, "	CMR1 = 0x%02x\n", readb(base_addr + CMR1));
+	netdev_info(ndev, "	CMR2 = 0x%02x\n", readb(base_addr + CMR2));
+	netdev_info(ndev, "	GCR = 0x%02x\n", readb(base_addr + GCR));
+	netdev_info(ndev, "	ESM = 0x%02x\n", readb(base_addr + ESM));
+	netdev_info(ndev, "	CMR3 = 0x%02x\n", readb(base_addr + CMR3));
+	netdev_info(ndev, "	PC1 = 0x%02x\n", readb(base_addr + PC1));
+	netdev_info(ndev, "	PC2 = 0x%02x\n", readb(base_addr + PC2));
+	netdev_info(ndev, "	PC3 = 0x%02x\n", readb(base_addr + PC3));
+	netdev_info(ndev, "	PC4 = 0x%02x\n", readb(base_addr + PC4));
+	netdev_info(ndev, "	PC5 = 0x%02x\n", readb(base_addr + PC5));
+	netdev_info(ndev, "	GPC1 = 0x%02x\n", readb(base_addr + GPC1));
+	netdev_info(ndev, "	PC6 = 0x%02x\n", readb(base_addr + PC6));
+	netdev_info(ndev, "	CCR3 = 0x%02x\n", readb(base_addr + CCR3));
+	netdev_info(ndev, "	CCR4 = 0x%02x\n", readb(base_addr + CCR4));
+	netdev_info(ndev, "	CCR5 = 0x%02x\n", readb(base_addr + CCR5));
+	netdev_info(ndev, "	MODE2 = 0x%02x\n", readb(base_addr + MODE2));
+	netdev_info(ndev, "	MODE3 = 0x%02x\n", readb(base_addr + MODE3));
+	netdev_info(ndev, "	RBC2 = 0x%02x\n", readb(base_addr + RBC2));
+	netdev_info(ndev, "	RBC3 = 0x%02x\n", readb(base_addr + RBC3));
+	netdev_info(ndev, "	GCM1 = 0x%02x\n", readb(base_addr + GCM1));
+	netdev_info(ndev, "	GCM2 = 0x%02x\n", readb(base_addr + GCM2));
+	netdev_info(ndev, "	GCM3 = 0x%02x\n", readb(base_addr + GCM3));
+	netdev_info(ndev, "	GCM4 = 0x%02x\n", readb(base_addr + GCM4));
+	netdev_info(ndev, "	GCM5 = 0x%02x\n", readb(base_addr + GCM5));
+	netdev_info(ndev, "	GCM6 = 0x%02x\n", readb(base_addr + GCM6));
+	netdev_info(ndev, "	SIS2/GCM7 = 0x%02x\n",
+			readb(base_addr + SIS2_1));
+	netdev_info(ndev, "	RSIS2/GCM8 = 0x%02x\n",
+			readb(base_addr + RSIS2_1));
+	netdev_info(ndev, "	TSEO = 0x%02x\n", readb(base_addr + TSEO));
+	netdev_info(ndev, "	TSBS1 = 0x%02x\n", readb(base_addr + TSBS1));
+	netdev_info(ndev, "	TSBS2 = 0x%02x\n", readb(base_addr + TSBS2));
+	netdev_info(ndev, "	TSBS3 = 0x%02x\n", readb(base_addr + TSBS3));
+	netdev_info(ndev, "	TSS2 = 0x%02x\n", readb(base_addr + TSS2));
+	netdev_info(ndev, "	TSS3 = 0x%02x\n", readb(base_addr + TSS3));
+	netdev_info(ndev, "	Res10 = 0x%02x\n", readb(base_addr + Res10));
+	netdev_info(ndev, "	Res11 = 0x%02x\n", readb(base_addr + Res11));
+	netdev_info(ndev, "	TPC0 = 0x%02x\n", readb(base_addr + TPC0));
+	netdev_info(ndev, "	GLC1 = 0x%02x\n", readb(base_addr + GLC1));
+}
+
+static ssize_t fs_attr_regs_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	print_regs(dev);
+	return sprintf(buf, "*** printk DEBUG ***\n");
+}
+
+static DEVICE_ATTR(regs, S_IRUGO, fs_attr_regs_show, NULL);
+
+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 && priv->init_done) {
+			pef2256_close(ndev);
+			init_FALC(priv);
+			pef2256_open(ndev);
+		}
+	}
+
+	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 && priv->init_done)
+			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 && priv->init_done)
+			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);
+
+/* Setting up HDLC channel */
+int Config_HDLC(struct pef2256_dev_priv *priv)
+{
+	int i;
+	int TS_idx;
+	unsigned char *base_addr;
+	u8 dummy;
+
+	/* Set framer E1 address */
+	base_addr = priv->base_addr;
+
+	/* Read to remove pending IT */
+	dummy = readb(base_addr + ISR0);
+	dummy = readb(base_addr + ISR1);
+
+	/* Mask HDLC 1 Transmit IT */
+	writeb(readb(base_addr + IMR1) | 1, base_addr + IMR1);
+	writeb(readb(base_addr + IMR1) | (1 << 4), base_addr + IMR1);
+	writeb(readb(base_addr + IMR1) | (1 << 5), base_addr + IMR1);
+
+	/* Mask HDLC 1 Receive IT */
+	writeb(readb(base_addr + IMR0) | 1, base_addr + IMR0);
+	writeb(readb(base_addr + IMR0) | (1 << 7), base_addr + IMR0);
+	writeb(readb(base_addr + IMR1) | (1 << 6), base_addr + IMR1);
+
+	/* The hardware requires a delay up to 2*32*125 usec to take commands
+	 * into account
+	 */
+	udelay((2 * 32) * 125);
+
+	/* 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)
+	 */
+	writeb(1 << 3, base_addr + MODE);
+	/* 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)
+	 */
+	writeb(0x10 | (1 << 3), base_addr + CCR1);
+	/* CCR2.XCRC = 0 (Transmit CRC ON)
+	 * CCR2.RCRC = 0 (Receive CRC ON, no write in RFIFO)
+	 * CCR2.RADD = 0 (No write address in RFIFO)
+	 */
+	writeb(0x00, base_addr + CCR2);
+
+	/* The hardware requires a delay up to 2*32*125 usec to take commands
+	 * into account
+	 */
+	udelay((2 * 32) * 125);
+
+	/* 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)
+	 */
+	writeb(1 << 3, base_addr + MODE);
+	/* 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)
+	 */
+	writeb(0x10 | (1 << 3), base_addr + CCR1);
+	/* CCR2.XCRC = 0 (Transmit CRC ON)
+	 * CCR2.RCRC = 0 (Receive CRC ON, no write in RFIFO)
+	 * CCR2.RADD = 0 (No write address in RFIFO)
+	 */
+	writeb(0x00, base_addr + CCR2);
+
+	/* The hardware requires a delay up to 2*32*125 usec to take commands
+	 * into account
+	 */
+	udelay((2 * 32) * 125);
+
+	/* 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)
+	 */
+	writeb(1 << 3, base_addr + MODE);
+	/* 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)
+	 */
+	writeb(0x10 | (1 << 3), base_addr + CCR1);
+	/* CCR2.XCRC = 0 (Transmit CRC ON)
+	 * CCR2.RCRC = 0 (Receive CRC ON, no write in RFIFO)
+	 * CCR2.RADD = 0 (No write address in RFIFO)
+	 */
+	writeb(0x00, base_addr + CCR2);
+
+	/* The hardware requires a delay up to 2*32*125 usec to take commands
+	 * into account
+	 */
+	udelay((2 * 32) * 125);
+
+	/* Init  Time Slot select */
+	writeb(0x00, base_addr + TTR1);
+	writeb(0x00, base_addr + TTR2);
+	writeb(0x00, base_addr + TTR3);
+	writeb(0x00, base_addr + TTR4);
+	writeb(0x00, base_addr + RTR1);
+	writeb(0x00, base_addr + RTR2);
+	writeb(0x00, base_addr + RTR3);
+	writeb(0x00, base_addr + RTR4);
+	/* Set selected TS bits */
+	/* Starting at TS 1, TS 0 is reserved */
+	for (TS_idx = 1; TS_idx < 32; TS_idx++) {
+		i = 7 - (TS_idx % 8);
+		switch (TS_idx / 8) {
+		case 0:
+			if (priv->Tx_TS & (1 << (31 - TS_idx)))
+				writeb(readb(base_addr + TTR1) | (1 << i),
+					base_addr + TTR1);
+			if (priv->Rx_TS & (1 << (31 - TS_idx)))
+				writeb(readb(base_addr + RTR1) | (1 << i),
+					base_addr + RTR1);
+			break;
+		case 1:
+			if (priv->Tx_TS & (1 << (31 - TS_idx)))
+				writeb(readb(base_addr + TTR2) | (1 << i),
+					base_addr + TTR2);
+			if (priv->Rx_TS & (1 << (31 - TS_idx)))
+				writeb(readb(base_addr + RTR2) | (1 << i),
+					base_addr + RTR2);
+			break;
+		case 2:
+			if (priv->Tx_TS & (1 << (31 - TS_idx)))
+				writeb(readb(base_addr + TTR3) | (1 << i),
+					base_addr + TTR3);
+			if (priv->Rx_TS & (1 << (31 - TS_idx)))
+				writeb(readb(base_addr + RTR3) | (1 << i),
+					base_addr + RTR3);
+			break;
+		case 3:
+			if (priv->Tx_TS & (1 << (31 - TS_idx)))
+				writeb(readb(base_addr + TTR4) | (1 << i),
+					base_addr + TTR4);
+			if (priv->Rx_TS & (1 << (31 - TS_idx)))
+				writeb(readb(base_addr + RTR4) | (1 << i),
+					base_addr + RTR4);
+			break;
+		}
+	}
+
+	/* The hardware requires a delay up to 2*32*125 usec to take commands
+	 * into account
+	 */
+	udelay((2 * 32) * 125);
+
+	/* Unmask HDLC 1 Transmit IT */
+	writeb(readb(base_addr + IMR1) & ~1, base_addr + IMR1);
+	writeb(readb(base_addr + IMR1) & ~(1 << 4), base_addr + IMR1);
+	writeb(readb(base_addr + IMR1) & ~(1 << 5), base_addr + IMR1);
+
+	/* Unmask HDLC 1 Receive IT */
+	writeb(readb(base_addr + IMR0) & ~1, base_addr + IMR0);
+	writeb(readb(base_addr + IMR0) & ~(1 << 7), base_addr + IMR0);
+	writeb(readb(base_addr + IMR1) & ~(1 << 6), base_addr + IMR1);
+
+	/* The hardware requires a delay up to 2*32*125 usec to take commands
+	 * into account
+	 */
+	udelay((2 * 32) * 125);
+
+	return 0;
+}
+
+
+/* Init FALC56 */
+static int init_FALC(struct pef2256_dev_priv *priv)
+{
+	unsigned char *base_addr;
+	int Version;
+
+	/* Get controller version */
+	Version = priv->component_id;
+
+	/* Init FALC56 */
+	base_addr = priv->base_addr;
+	/* RCLK output : DPLL clock, DCO-X enabled, DCO-X internal reference
+	 * clock
+	 */
+	writeb(0x00, base_addr + CMR1);
+	/* SCLKR selected, SCLKX selected, receive synchro pulse sourced by
+	 * SYPR, transmit synchro pulse sourced by SYPX
+	 */
+	writeb(0x00, base_addr + CMR2);
+	/* NRZ coding, no alarm simulation */
+	writeb(0x00, base_addr + FMR0);
+	/* 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
+	 */
+	writeb(0x00, base_addr + FMR1);
+	writeb(0x02, base_addr + FMR2);
+	/* E1 default for LIM2 */
+	writeb(0x20, base_addr + LIM2);
+	if (priv->mode == MASTER_MODE)
+		/* SEC input, active high */
+		writeb(0x00, base_addr + GPC1);
+	else
+		/* FSC output, active high */
+		writeb(0x40, base_addr + GPC1);
+	/* internal second timer, power on */
+	writeb(0x00, base_addr + GCR);
+	/* slave mode, local loop off, mode short-haul */
+	if (Version == VERSION_1_2)
+		writeb(0x00, base_addr + LIM0);
+	else
+		writeb(0x08, base_addr + LIM0);
+	/* analog interface selected, remote loop off */
+	writeb(0x00, base_addr + LIM1);
+	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
+		 */
+		writeb(0x77, base_addr + PC1);
+		writeb(0x77, base_addr + PC2);
+		writeb(0x77, base_addr + PC3);
+		writeb(0x77, base_addr + PC4);
+	} else {
+		/* function of ports RP(A to D) : output high
+		 * function of ports XP(A to D) : output high
+		 */
+		writeb(0xAA, base_addr + PC1);
+		writeb(0xAA, base_addr + PC2);
+		writeb(0xAA, base_addr + PC3);
+		writeb(0xAA, base_addr + PC4);
+	}
+	/* function of port RPA : input SYPR
+	 * function of port XPA : input SYPX
+	 */
+	writeb(0x00, base_addr + PC1);
+	/* SCLKR, SCLKX, RCLK configured to inputs,
+	 * XFMS active low, CLK1 and CLK2 pin configuration
+	 */
+	writeb(0x00, base_addr + PC5);
+	writeb(0x00, base_addr + PC6);
+	/* the receive clock offset is cleared
+	 * the receive time slot offset is cleared
+	 */
+	writeb(0x00, base_addr + RC0);
+	writeb(0x9C, base_addr + RC1);
+	/* 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
+	 */
+	writeb(0x00, base_addr + SIC1);
+	writeb(0x00, base_addr + SIC2);
+	writeb(0x00, base_addr + SIC3);
+	/* channel loop-back and single frame mode are disabled */
+	writeb(0x00, base_addr + LOOP);
+	/* all bits of the transmitted service word are cleared */
+	writeb(0x1F, base_addr + XSW);
+	/* spare bit values are cleared */
+	writeb(0x00, base_addr + XSP);
+	/* no transparent mode active */
+	writeb(0x00, base_addr + TSWM);
+	/* the transmit clock offset is cleared
+	 * the transmit time slot offset is cleared
+	 */
+	writeb(0x00, base_addr + XC0);
+	writeb(0x9C, base_addr + XC1);
+	/* transmitter in tristate mode */
+	writeb(0x40, base_addr + XPM2);
+	/* transmit pulse mask */
+	if (Version != VERSION_1_2)
+		writeb(0x9C, base_addr + XPM0);
+
+	if (Version == VERSION_1_2) {
+		/* master clock is 16,384 MHz (flexible master clock) */
+		writeb(0x58, base_addr + GCM2);
+		writeb(0xD2, base_addr + GCM3);
+		writeb(0xC2, base_addr + GCM4);
+		writeb(0x07, base_addr + GCM5);
+		writeb(0x10, base_addr + GCM6);
+	} else {
+		/* master clock is 16,384 MHz (flexible master clock) */
+		writeb(0x18, base_addr + GCM2);
+		writeb(0xFB, base_addr + GCM3);
+		writeb(0x0B, base_addr + GCM4);
+		writeb(0x01, base_addr + GCM5);
+		writeb(0x0B, base_addr + GCM6);
+		writeb(0xDB, base_addr + GCM7);
+		writeb(0xDF, base_addr + GCM8);
+	}
+
+	/* master mode => LIM0.MAS = 1 (bit 0) */
+	if (priv->mode == MASTER_MODE)
+		writeb(readb(base_addr + LIM0) | (1 << 0), base_addr + LIM0);
+
+	/* transmit line in normal operation => XPM2.XLT = 0 (bit 6) */
+	writeb(readb(base_addr + XPM2) & ~(1 << 6), base_addr + XPM2);
+
+	if (Version == VERSION_1_2) {
+		/* receive input threshold = 0,21V =>
+		 * LIM1.RIL2:0 = 101 (bits 6, 5 et 4)
+		 */
+		writeb(readb(base_addr + LIM1) | (1 << 4), base_addr + LIM1);
+		writeb(readb(base_addr + LIM1) | (1 << 6), base_addr + LIM1);
+	} else {
+		/* receive input threshold = 0,21V =>
+		 * LIM1.RIL2:0 = 100 (bits 6, 5 et 4)
+		 */
+		writeb(readb(base_addr + LIM1) | (1 << 6), base_addr + LIM1);
+	}
+	/* transmit line coding = HDB3 => FMR0.XC1:0 = 11 (bits 7 et 6) */
+	writeb(readb(base_addr + FMR0) | (1 << 6), base_addr + FMR0);
+	writeb(readb(base_addr + FMR0) | (1 << 7), base_addr + FMR0);
+	/* receive line coding = HDB3 => FMR0.RC1:0 = 11 (bits 5 et 4) */
+	writeb(readb(base_addr + FMR0) | (1 << 4), base_addr + FMR0);
+	writeb(readb(base_addr + FMR0) | (1 << 5), base_addr + FMR0);
+	/* detection of LOS alarm = 176 pulses (soit (10 + 1) * 16) */
+	writeb(10, base_addr + PCD);
+	/* recovery of LOS alarm = 22 pulses (soit 21 + 1) */
+	writeb(21, base_addr + PCR);
+	/* DCO-X center frequency => CMR2.DCOXC = 1 (bit 5) */
+	writeb(readb(base_addr + CMR2) | (1 << 5), base_addr + CMR2);
+	if (priv->mode == SLAVE_MODE) {
+		/* select RCLK source = 2M => CMR1.RS(1:0) = 10 (bits 5 et 4) */
+		writeb(readb(base_addr + CMR1) | (1 << 5), base_addr + CMR1);
+		/* disable switching RCLK -> SYNC => CMR1.DCS = 1 (bit 3) */
+		writeb(readb(base_addr + CMR1) | (1 << 3), base_addr + CMR1);
+	}
+	if (Version != VERSION_1_2)
+		/* during inactive channel phase RDO into tri-state mode */
+		writeb(readb(base_addr + SIC3) | (1 << 5), base_addr + SIC3);
+	if (!strcmp(priv->rising_edge_sync_pulse, "transmit")) {
+		/* rising edge sync pulse transmit => SIC3.RESX = 1 (bit 3) */
+		writeb(readb(base_addr + SIC3) | (1 << 3), base_addr + SIC3);
+	} else {
+		/* rising edge sync pulse receive => SIC3.RESR = 1 (bit 2) */
+		writeb(readb(base_addr + SIC3) | (1 << 2), base_addr + SIC3);
+	}
+	/* transmit offset counter = 4
+	 *  => XC0.XCO10:8 = 000 (bits 2, 1 et 0);
+	 *     XC1.XCO7:0 = 4 (bits 7 ... 0)
+	 */
+	writeb(4, base_addr + XC1);
+	/* receive offset counter = 4
+	 * => RC0.RCO10:8 = 000 (bits 2, 1 et 0);
+	 *    RC1.RCO7:0 = 4 (bits 7 ... 0)
+	 */
+	writeb(4, base_addr + RC1);
+
+	/* Nothing to do if clock rate = 8 Mhz or data rate = 2 Mb/s */
+
+	/* clocking rate 4M  */
+	if (priv->clock_rate == CLOCK_RATE_4M)
+		writeb(readb(base_addr + SIC1) | (1 << 3), base_addr + SIC1);
+	/* clocking rate 8M  */
+	if (priv->clock_rate == CLOCK_RATE_8M)
+		writeb(readb(base_addr + SIC1) | (1 << 7), base_addr + SIC1);
+	/* clocking rate 16M  */
+	if (priv->clock_rate == CLOCK_RATE_16M) {
+		writeb(readb(base_addr + SIC1) | (1 << 3), base_addr + SIC1);
+		writeb(readb(base_addr + SIC1) | (1 << 7), base_addr + SIC1);
+	}
+
+	/* data rate 4M on the system data bus */
+	if (priv->data_rate == DATA_RATE_4M)
+		writeb(readb(base_addr + FMR1) | (1 << 1), base_addr + FMR1);
+	/* data rate 8M on the system data bus */
+	if (priv->data_rate == DATA_RATE_8M)
+		writeb(readb(base_addr + SIC1) | (1 << 6), base_addr + SIC1);
+	/* data rate 16M on the system data bus */
+	if (priv->data_rate == DATA_RATE_16M) {
+		writeb(readb(base_addr + FMR1) | (1 << 1), base_addr + FMR1);
+		writeb(readb(base_addr + SIC1) | (1 << 6), base_addr + SIC1);
+	}
+
+	/* channel phase for FALC56 */
+	if ((priv->channel_phase == CHANNEL_PHASE_1)
+		|| (priv->channel_phase == CHANNEL_PHASE_3))
+		writeb(readb(base_addr + SIC2) | (1 << 1), base_addr + SIC2);
+	if ((priv->channel_phase == CHANNEL_PHASE_2)
+		|| (priv->channel_phase == CHANNEL_PHASE_3))
+		writeb(readb(base_addr + SIC2) | (1 << 2), base_addr + SIC2);
+
+	if (priv->mode == SLAVE_MODE) {
+		/* transmit buffer size = 2 frames =>
+		 * SIC1.XBS1:0 = 10 (bits 1 et 0)
+		 */
+		writeb(readb(base_addr + SIC1) | (1 << 1), base_addr + SIC1);
+	}
+
+	/* transmit in multiframe => FMR1.XFS = 1 (bit 3) */
+	writeb(readb(base_addr + FMR1) | (1 << 3), base_addr + FMR1);
+	/* receive in multiframe => FMR2.RFS1:0 = 10 (bits 7 et 6) */
+	writeb(readb(base_addr + FMR2) | (1 << 7), base_addr + FMR2);
+	/* Automatic transmission of submultiframe status =>
+	 * SP.AXS = 1 (bit 3)
+	 */
+	writeb(readb(base_addr + XSP) | (1 << 3), base_addr + XSP);
+
+	/* error counter mode toutes les 1s => FMR1.ECM = 1 (bit 2) */
+	writeb(readb(base_addr + FMR1) | (1 << 2), base_addr + FMR1);
+	/* error counter mode COFA => GCR.ECMC = 1 (bit 4) */
+	writeb(readb(base_addr + GCR) | (1 << 4), base_addr + GCR);
+	/* errors in service words with no influence => RC0.SWD = 1 (bit 7) */
+	writeb(readb(base_addr + RC0) | (1 << 7), base_addr + RC0);
+	/* 4 consecutive incorrect FAS = loss of sync => RC0.ASY4 = 1 (bit 6) */
+	writeb(readb(base_addr + RC0) | (1 << 6), base_addr + RC0);
+	/* Si-Bit in service word from XDI => XSW.XSIS = 1 (bit 7) */
+	writeb(readb(base_addr + XSW) | (1 << 7), base_addr + XSW);
+	/* Si-Bit in FAS word from XDI => XSP.XSIF = 1 (bit 2) */
+	writeb(readb(base_addr + XSP) | (1 << 2), base_addr + XSP);
+
+	/* port RCLK is output => PC5.CRP = 1 (bit 0) */
+	writeb(readb(base_addr + PC5) | (1 << 0), base_addr + PC5);
+	/* visibility of the masked interrupts => GCR.VIS = 1 (bit 7) */
+	writeb(readb(base_addr + GCR) | (1 << 7), base_addr + GCR);
+	/* reset lines
+	 *  => CMDR.RRES = 1 (bit 6); CMDR.XRES = 1 (bit 4);
+	 *     CMDR.SRES = 1 (bit 0)
+	 */
+	writeb(0x51, base_addr + CMDR);
+
+	return 0;
+}
+
+
+
+static int pef2256_open(struct net_device *netdev)
+{
+	struct pef2256_dev_priv *priv = dev_to_hdlc(netdev)->priv;
+	unsigned char *base_addr = priv->base_addr;
+	int ret;
+
+	if (hdlc_open(netdev))
+		return -EAGAIN;
+
+	ret = request_irq(priv->irq, pef2256_irq, 0, "e1-wan", priv);
+	if (ret) {
+		dev_err(priv->dev, "Cannot request irq. Device seems busy.\n");
+		return -EBUSY;
+	}
+
+	if (priv->component_id != VERSION_UNDEF) {
+		ret = init_FALC(priv);
+	} else {
+		dev_err(priv->dev, "Composant ident (%X/%X) = %d\n",
+			readb(base_addr + VSTR), readb(base_addr + WID),
+				priv->component_id);
+		ret = -ENODEV;
+	}
+
+	if (ret < 0)
+		return ret;
+
+	priv->tx_skb = NULL;
+	priv->rx_len = 0;
+
+	Config_HDLC(priv);
+
+	netif_carrier_on(netdev);
+	netif_start_queue(netdev);
+
+	priv->init_done = 1;
+
+	return 0;
+}
+
+
+static int pef2256_close(struct net_device *netdev)
+{
+	struct pef2256_dev_priv *priv = dev_to_hdlc(netdev)->priv;
+
+	if (!priv->init_done)
+		return 0;
+
+	priv->init_done = 0;
+	netif_stop_queue(netdev);
+	hdlc_close(netdev);
+	free_irq(priv->irq, priv);
+
+	return 0;
+}
+
+
+
+static int pef2256_rx(struct pef2256_dev_priv *priv)
+{
+	struct sk_buff *skb;
+	int idx, size;
+	unsigned char *base_addr;
+
+	base_addr = priv->base_addr;
+
+	/* RDO has been received -> wait for RME */
+	if (priv->rx_len == -1) {
+		/* Acknowledge the FIFO */
+		writeb(readb(base_addr + CMDR) | (1 << 7), base_addr + CMDR);
+
+		if (priv->R_ISR0 & (1 << 7))
+			priv->rx_len = 0;
+
+		return 0;
+	}
+
+	/* RPF : a block is available in the receive FIFO */
+	if (priv->R_ISR0 & 1) {
+		for (idx = 0; idx < 32; idx++)
+			priv->rx_buff[priv->rx_len + idx] =
+				readb(base_addr + RFIFO + (idx & 1));
+
+		/* Acknowledge the FIFO */
+		writeb(readb(base_addr + CMDR) | (1 << 7), base_addr + CMDR);
+
+		priv->rx_len += 32;
+	}
+
+	/* RME : Message end : Read the receive FIFO */
+	if (priv->R_ISR0 & (1 << 7)) {
+		/* Get size of last block */
+		size = readb(base_addr + RBCL) & 0x1F;
+
+		/* Read last block */
+		for (idx = 0; idx < size; idx++)
+			priv->rx_buff[priv->rx_len + idx] =
+				readb(base_addr + RFIFO + (idx & 1));
+
+		/* Acknowledge the FIFO */
+		writeb(readb(base_addr + CMDR) | (1 << 7), base_addr + CMDR);
+
+		priv->rx_len += size;
+
+		/* Packet received */
+		if (priv->rx_len > 0) {
+			skb = dev_alloc_skb(priv->rx_len);
+			if (!skb) {
+				priv->rx_len = 0;
+				priv->netdev->stats.rx_dropped++;
+				return -ENOMEM;
+			}
+			memcpy(skb->data, priv->rx_buff, priv->rx_len);
+			skb_put(skb, priv->rx_len);
+			priv->rx_len = 0;
+			skb->protocol = hdlc_type_trans(skb, priv->netdev);
+			priv->netdev->stats.rx_packets++;
+			priv->netdev->stats.rx_bytes += skb->len;
+			netif_rx(skb);
+		}
+	}
+
+	return 0;
+}
+
+
+static int pef2256_tx(struct pef2256_dev_priv *priv)
+{
+	int idx, size;
+	unsigned char *base_addr;
+	u8 *tx_buff = priv->tx_skb->data;
+
+	base_addr = priv->base_addr;
+
+	/* ALLS : transmit all done */
+	if (priv->R_ISR1 & (1 << 5)) {
+		priv->netdev->stats.tx_packets++;
+		priv->netdev->stats.tx_bytes += priv->tx_skb->len;
+		/* dev_kfree_skb(priv->tx_skb); */
+		priv->tx_skb = NULL;
+		priv->tx_len = 0;
+		netif_wake_queue(priv->netdev);
+	}
+	/* XPR : write a new block in transmit FIFO */
+	else if (priv->tx_len < priv->tx_skb->len) {
+		size = priv->tx_skb->len - priv->tx_len;
+		if (size > 32)
+			size = 32;
+
+		for (idx = 0; idx < size; idx++)
+			writeb(tx_buff[priv->tx_len + idx],
+				base_addr + XFIFO + (idx & 1));
+
+		priv->tx_len += size;
+
+		if (priv->tx_len == priv->tx_skb->len)
+			writeb(readb(base_addr + CMDR) | ((1 << 3) | (1 << 1)),
+				base_addr + CMDR);
+		else
+			writeb(readb(base_addr + CMDR) | (1 << 3),
+				base_addr + CMDR);
+	}
+
+	return 0;
+}
+
+
+irqreturn_t pef2256_irq(int irq, void *dev_priv)
+{
+	struct pef2256_dev_priv *priv = (struct pef2256_dev_priv *)dev_priv;
+	unsigned char *base_addr;
+	u8 R_GIS;
+
+	base_addr = priv->base_addr;
+	R_GIS = readb(base_addr + GIS);
+
+	priv->R_ISR0 = priv->R_ISR1 = 0;
+
+	/* We only care about ISR0 and ISR1 */
+	/* ISR0 */
+	if (R_GIS & 1)
+		priv->R_ISR0 =
+			readb(base_addr + ISR0) & ~(readb(base_addr + IMR0));
+
+	/* ISR1 */
+	if (R_GIS & (1 << 1))
+		priv->R_ISR1 =
+			readb(base_addr + ISR1) & ~(readb(base_addr + IMR1));
+
+	/* Don't do anything else before init is done */
+	if (!priv->init_done)
+		return IRQ_HANDLED;
+
+	/* RDO : Receive data overflow -> RX error */
+	if (priv->R_ISR1 & (1 << 6)) {
+		/* Acknowledge the FIFO */
+		writeb(readb(base_addr + CMDR) | (1 << 7), base_addr + CMDR);
+		priv->netdev->stats.rx_errors++;
+		/* RME received ? */
+		if (priv->R_ISR0 & (1 << 7))
+			priv->rx_len = 0;
+		else
+			priv->rx_len = -1;
+		return IRQ_HANDLED;
+	}
+
+	/* XDU : Transmit data underrun -> TX error */
+	if (priv->R_ISR1 & (1 << 4)) {
+		priv->netdev->stats.tx_errors++;
+		/* dev_kfree_skb(priv->tx_skb); */
+		priv->tx_skb = NULL;
+		netif_wake_queue(priv->netdev);
+		return IRQ_HANDLED;
+	}
+
+	/* RPF or RME : FIFO received */
+	if (priv->R_ISR0 & (1 | (1 << 7)))
+		pef2256_rx(priv);
+
+	/* XPR or ALLS : FIFO sent */
+	if (priv->R_ISR1 & (1 | (1 << 5)))
+		pef2256_tx(priv);
+
+	return IRQ_HANDLED;
+}
+
+
+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;
+	unsigned char *base_addr;
+	u8 *tx_buff = skb->data;
+
+	base_addr = priv->base_addr;
+
+	priv->tx_skb = skb;
+	priv->tx_len = 0;
+
+	size = priv->tx_skb->len - priv->tx_len;
+	if (size > 32)
+		size = 32;
+
+	for (idx = 0; idx < size; idx++)
+		writeb(tx_buff[priv->tx_len + idx],
+			base_addr + XFIFO + (idx & 1));
+
+	priv->tx_len += size;
+
+	writeb(readb(base_addr + CMDR) | (1 << 3), base_addr + CMDR);
+	if (priv->tx_len == priv->tx_skb->len)
+		writeb(readb(base_addr + CMDR) | (1 << 1), base_addr + CMDR);
+
+	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;
+}
+
+
+/* Loading module */
+static int pef2256_probe(struct platform_device *pdev)
+{
+	struct pef2256_dev_priv *priv;
+	int ret = -ENOMEM;
+	struct net_device *netdev;
+	hdlc_device *hdlc;
+	unsigned char *base_addr;
+	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");
+		return -EINVAL;
+	}
+
+	priv->base_addr = of_iomap(np, 0);
+	if (!priv->base_addr) {
+		dev_err(&pdev->dev, "of_iomap failed\n");
+		goto free_priv;
+	}
+
+	/* Get the component Id */
+	base_addr = priv->base_addr;
+	priv->component_id = VERSION_UNDEF;
+	if (readb(base_addr + VSTR) == 0x00) {
+		if ((readb(base_addr + WID) & WID_IDENT_1) ==
+			WID_IDENT_1_2)
+			priv->component_id = VERSION_1_2;
+	} else if (readb(base_addr + VSTR) == 0x05) {
+		if ((readb(base_addr + WID) & WID_IDENT_2) ==
+			WID_IDENT_2_1)
+			priv->component_id = VERSION_2_1;
+		else if ((readb(base_addr + 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;
+
+	/* This file is only used to display debug infos.
+	 * A failure can be safely ignored.
+	 */
+	device_create_file(priv->dev, &dev_attr_regs);
+
+	priv->init_done = 0;
+
+	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->base_addr);
+free_priv:;
+	kfree(priv);
+
+	return ret;
+}
+
+
+/* Removing module */
+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_regs);
+	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->base_addr);
+
+	kfree(priv);
+
+	dev_set_drvdata(&pdev->dev, NULL);
+	kfree(pdev);
+	return 0;
+}
+
+static const struct of_device_id pef2256_match[] = {
+	{
+		.compatible = "infineon,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("Infineon 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,256 @@
+/* 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 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
+
+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
+
+
+struct pef2256_dev_priv {
+	struct sk_buff *tx_skb;
+	u16 tx_len;
+	struct device *dev;
+
+	int init_done;
+
+	unsigned char *base_addr;
+	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];
+
+	u16 rx_len;
+	u8 rx_buff[2048];
+
+	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 */
+};
+
+
+/* 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,74 @@
+* Wan on Infineon PEF2256 E1 controller, also known as FALC56
+
+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 "infineon,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.
+  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 = "infineon,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 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] x86: Run checksumming in parallel accross multiple alu's
From: Neil Horman @ 2013-11-01 14:06 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Eric Dumazet, linux-kernel, sebastien.dugue, Thomas Gleixner,
	Ingo Molnar, H. Peter Anvin, x86, netdev
In-Reply-To: <20131101091337.GA27063@gmail.com>

On Fri, Nov 01, 2013 at 10:13:37AM +0100, Ingo Molnar wrote:
> 
> * Neil Horman <nhorman@tuxdriver.com> wrote:
> 
> > On Thu, Oct 31, 2013 at 11:22:00AM +0100, Ingo Molnar wrote:
> > > 
> > > * Neil Horman <nhorman@tuxdriver.com> wrote:
> > > 
> > > > > etc. For such short runtimes make sure the last column displays 
> > > > > close to 100%, so that the PMU results become trustable.
> > > > > 
> > > > > A nehalem+ PMU will allow 2-4 events to be measured in parallel, 
> > > > > plus generics like 'cycles', 'instructions' can be added 'for free' 
> > > > > because they get counted in a separate (fixed purpose) PMU register.
> > > > > 
> > > > > The last colum tells you what percentage of the runtime that 
> > > > > particular event was actually active. 100% (or empty last column) 
> > > > > means it was active all the time.
> > > > > 
> > > > > Thanks,
> > > > > 
> > > > > 	Ingo
> > > > > 
> > > > 
> > > > Hmm, 
> > > > 
> > > > I ran this test:
> > > > 
> > > > for i in `seq 0 1 3`
> > > > do
> > > > echo $i > /sys/module/csum_test/parameters/module_test_mode
> > > > taskset -c 0 perf stat --repeat 20 -C 0 -e L1-dcache-load-misses -e L1-dcache-prefetches -e cycles -e instructions -ddd ./test.sh
> > > > done
> > > 
> > > You need to remove '-ddd' which is a shortcut for a ton of useful 
> > > events, but here you want to use fewer events, to increase the 
> > > precision of the measurement.
> > > 
> > > Thanks,
> > > 
> > > 	Ingo
> > > 
> > 
> > Thank you ingo, that fixed it.  I'm trying some other variants of 
> > the csum algorithm that Doug and I discussed last night, but FWIW, 
> > the relative performance of the 4 test cases 
> > (base/prefetch/parallel/both) remains unchanged. I'm starting to 
> > feel like at this point, theres very little point in doing 
> > parallel alu operations (unless we can find a way to break the 
> > dependency on the carry flag, which is what I'm tinkering with 
> > now).
> 
> I would still like to encourage you to pick up the improvements that 
> Doug measured (mostly via prefetch tweaking?) - that looked like 
> some significant speedups that we don't want to lose!
> 
Well, yes, I made a line item of that in my subsequent note below.  I'm going to
repost that shortly, and I suggested that we revisit this when the AVX
instruction extensions are available.

> Also, trying to stick the in-kernel implementation into 'perf bench' 
> would be a useful first step as well, for this and future efforts.
> 
> See what we do in tools/perf/bench/mem-memcpy-x86-64-asm.S to pick 
> up the in-kernel assembly memcpy implementations:
> 
Yes, I'll look into adding this as well
Regards
Neil

^ permalink raw reply

* Re: [net-next 3/6] igb: Don't let ethtool try to write to iNVM in i210/i211
From: Sergei Shtylyov @ 2013-11-01 14:05 UTC (permalink / raw)
  To: Jeff Kirsher, davem; +Cc: Fujinaka, Todd, netdev, gospo, sassmann
In-Reply-To: <1383314210-24289-4-git-send-email-jeffrey.t.kirsher@intel.com>

Hello.

On 01-11-2013 17:56, Jeff Kirsher wrote:

> From: "Fujinaka, Todd" <todd.fujinaka@intel.com>

> Don't let ethtool try to write to iNVM in i210/i211.

> This fixes an issue seen by Marek Vasut.

> Reported-by: Marek Vasut <marex@denx.de>
> Signed-off-by: Todd Fujinaka <todd.fujinaka@intel.com>
> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
> ---
>   drivers/net/ethernet/intel/igb/igb_ethtool.c | 4 +++-
>   1 file changed, 3 insertions(+), 1 deletion(-)

> diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c
> index 0ae3177..b918ba3 100644
> --- a/drivers/net/ethernet/intel/igb/igb_ethtool.c
> +++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c
> @@ -771,8 +771,10 @@ static int igb_set_eeprom(struct net_device *netdev,
>   	if (eeprom->len == 0)
>   		return -EOPNOTSUPP;
>
> -	if (hw->mac.type == e1000_i211)
> +	if ((hw->mac.type >= e1000_i210) &&
> +	    !igb_get_flash_presence_i210(hw)) {
>   		return -EOPNOTSUPP;
> +	}

    Why have you added {}?

WBR, Sergei

^ permalink raw reply

* [net-next 6/6] ixgbe: fix inconsistent clearing of the multicast table
From: Jeff Kirsher @ 2013-11-01 13:56 UTC (permalink / raw)
  To: davem; +Cc: Emil Tantilov, netdev, gospo, sassmann, Jeff Kirsher
In-Reply-To: <1383314210-24289-1-git-send-email-jeffrey.t.kirsher@intel.com>

From: Emil Tantilov <emil.s.tantilov@intel.com>

This patch resolves an issue where the MTA table can be cleared when the
interface is reset while in promisc mode. As result IPv6 traffic between
VFs will be interrupted.

This patch makes the update of the MTA table unconditional to avoid the
inconsistent clearing on reset.

Signed-off-by: Emil Tantilov <emil.s.tantilov@intel.com>
Tested-by: Phil Schmitt <phillip.j.schmitt@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index a7d1a1c..5191b3c 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -3823,14 +3823,6 @@ void ixgbe_set_rx_mode(struct net_device *netdev)
 		if (netdev->flags & IFF_ALLMULTI) {
 			fctrl |= IXGBE_FCTRL_MPE;
 			vmolr |= IXGBE_VMOLR_MPE;
-		} else {
-			/*
-			 * Write addresses to the MTA, if the attempt fails
-			 * then we should just turn on promiscuous mode so
-			 * that we can at least receive multicast traffic
-			 */
-			hw->mac.ops.update_mc_addr_list(hw, netdev);
-			vmolr |= IXGBE_VMOLR_ROMPE;
 		}
 		ixgbe_vlan_filter_enable(adapter);
 		hw->addr_ctrl.user_set_promisc = false;
@@ -3847,6 +3839,13 @@ void ixgbe_set_rx_mode(struct net_device *netdev)
 		vmolr |= IXGBE_VMOLR_ROPE;
 	}
 
+	/* Write addresses to the MTA, if the attempt fails
+	 * then we should just turn on promiscuous mode so
+	 * that we can at least receive multicast traffic
+	 */
+	hw->mac.ops.update_mc_addr_list(hw, netdev);
+	vmolr |= IXGBE_VMOLR_ROMPE;
+
 	if (adapter->num_vfs)
 		ixgbe_restore_vf_multicasts(adapter);
 
-- 
1.8.3.1

^ permalink raw reply related

* [net-next 5/6] ixgbe: cleanup IXGBE_DESC_UNUSED
From: Jeff Kirsher @ 2013-11-01 13:56 UTC (permalink / raw)
  To: davem; +Cc: Don Skidmore, netdev, gospo, sassmann, Alexander Duyck,
	Jeff Kirsher
In-Reply-To: <1383314210-24289-1-git-send-email-jeffrey.t.kirsher@intel.com>

From: Don Skidmore <donald.c.skidmore@intel.com>

This patch just replaces the IXGBE_DESC_UNUSED macro with a like named
inline function ixgbevf_desc_unused. The inline function makes the logic
a bit more readable.

Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Don Skidmore <donald.c.skidmore@intel.com>
Tested-by: Phil Schmitt <phillip.j.schmitt@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
 drivers/net/ethernet/intel/ixgbevf/ixgbevf.h      | 10 +++++++---
 drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 10 +++++-----
 2 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
index acf3806..8971e2d 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
@@ -286,9 +286,13 @@ static inline bool ixgbevf_qv_disable(struct ixgbevf_q_vector *q_vector)
 	((_eitr) ? (1000000000 / ((_eitr) * 256)) : 8)
 #define EITR_REG_TO_INTS_PER_SEC EITR_INTS_PER_SEC_TO_REG
 
-#define IXGBE_DESC_UNUSED(R) \
-	((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \
-	(R)->next_to_clean - (R)->next_to_use - 1)
+static inline u16 ixgbevf_desc_unused(struct ixgbevf_ring *ring)
+{
+	u16 ntc = ring->next_to_clean;
+	u16 ntu = ring->next_to_use;
+
+	return ((ntc > ntu) ? 0 : ring->count) + ntc - ntu - 1;
+}
 
 #define IXGBEVF_RX_DESC(R, i)	    \
 	(&(((union ixgbe_adv_rx_desc *)((R)->desc))[i]))
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index 9685354..038bfc8 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -251,7 +251,7 @@ static bool ixgbevf_clean_tx_irq(struct ixgbevf_q_vector *q_vector,
 
 #define TX_WAKE_THRESHOLD (DESC_NEEDED * 2)
 	if (unlikely(count && netif_carrier_ok(tx_ring->netdev) &&
-		     (IXGBE_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD))) {
+		     (ixgbevf_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD))) {
 		/* Make sure that anybody stopping the queue after this
 		 * sees the new next_to_clean.
 		 */
@@ -529,7 +529,7 @@ next_desc:
 	}
 
 	rx_ring->next_to_clean = i;
-	cleaned_count = IXGBE_DESC_UNUSED(rx_ring);
+	cleaned_count = ixgbevf_desc_unused(rx_ring);
 
 	if (cleaned_count)
 		ixgbevf_alloc_rx_buffers(adapter, rx_ring, cleaned_count);
@@ -1380,7 +1380,7 @@ static void ixgbevf_configure(struct ixgbevf_adapter *adapter)
 	for (i = 0; i < adapter->num_rx_queues; i++) {
 		struct ixgbevf_ring *ring = &adapter->rx_ring[i];
 		ixgbevf_alloc_rx_buffers(adapter, ring,
-					 IXGBE_DESC_UNUSED(ring));
+					 ixgbevf_desc_unused(ring));
 	}
 }
 
@@ -3102,7 +3102,7 @@ static int __ixgbevf_maybe_stop_tx(struct ixgbevf_ring *tx_ring, int size)
 
 	/* We need to check again in a case another CPU has just
 	 * made room available. */
-	if (likely(IXGBE_DESC_UNUSED(tx_ring) < size))
+	if (likely(ixgbevf_desc_unused(tx_ring) < size))
 		return -EBUSY;
 
 	/* A reprieve! - use start_queue because it doesn't call schedule */
@@ -3113,7 +3113,7 @@ static int __ixgbevf_maybe_stop_tx(struct ixgbevf_ring *tx_ring, int size)
 
 static int ixgbevf_maybe_stop_tx(struct ixgbevf_ring *tx_ring, int size)
 {
-	if (likely(IXGBE_DESC_UNUSED(tx_ring) >= size))
+	if (likely(ixgbevf_desc_unused(tx_ring) >= size))
 		return 0;
 	return __ixgbevf_maybe_stop_tx(tx_ring, size);
 }
-- 
1.8.3.1

^ permalink raw reply related

* [net-next 3/6] igb: Don't let ethtool try to write to iNVM in i210/i211
From: Jeff Kirsher @ 2013-11-01 13:56 UTC (permalink / raw)
  To: davem; +Cc: Fujinaka, Todd, netdev, gospo, sassmann, Jeff Kirsher
In-Reply-To: <1383314210-24289-1-git-send-email-jeffrey.t.kirsher@intel.com>

From: "Fujinaka, Todd" <todd.fujinaka@intel.com>

Don't let ethtool try to write to iNVM in i210/i211.

This fixes an issue seen by Marek Vasut.

Reported-by: Marek Vasut <marex@denx.de>
Signed-off-by: Todd Fujinaka <todd.fujinaka@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
 drivers/net/ethernet/intel/igb/igb_ethtool.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c
index 0ae3177..b918ba3 100644
--- a/drivers/net/ethernet/intel/igb/igb_ethtool.c
+++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c
@@ -771,8 +771,10 @@ static int igb_set_eeprom(struct net_device *netdev,
 	if (eeprom->len == 0)
 		return -EOPNOTSUPP;
 
-	if (hw->mac.type == e1000_i211)
+	if ((hw->mac.type >= e1000_i210) &&
+	    !igb_get_flash_presence_i210(hw)) {
 		return -EOPNOTSUPP;
+	}
 
 	if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
 		return -EFAULT;
-- 
1.8.3.1

^ permalink raw reply related

* [net-next 4/6] ixgbe: Reduce memory consumption with larger page sizes
From: Jeff Kirsher @ 2013-11-01 13:56 UTC (permalink / raw)
  To: davem; +Cc: Anton Blanchard, netdev, gospo, sassmann, Jeff Kirsher
In-Reply-To: <1383314210-24289-1-git-send-email-jeffrey.t.kirsher@intel.com>

From: Anton Blanchard <anton@samba.org>

The ixgbe driver allocates pages for its receive rings. It currently
uses 512 pages, regardless of page size. During receive handling it
adds the unused part of the page back into the rx ring, avoiding the
need for a new allocation.

On a ppc64 box with 64 threads and 64kB pages, we end up with
512 entries * 64 rx queues * 64kB = 2GB memory used. Even more of a
concern is that we use up 2GB of IOMMU space in order to map all this
memory.

The driver makes a number of decisions based on if PAGE_SIZE is less
than 8kB, so use this as the breakpoint and only allocate 128 entries
on 8kB or larger page sizes.

Signed-off-by: Anton Blanchard <anton@samba.org>
Tested-by: Phil Schmitt <phillip.j.schmitt@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
 drivers/net/ethernet/intel/ixgbe/ixgbe.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
index f51fd1f..0914914 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -67,7 +67,11 @@
 #define IXGBE_MAX_TXD			   4096
 #define IXGBE_MIN_TXD			     64
 
+#if (PAGE_SIZE < 8192)
 #define IXGBE_DEFAULT_RXD		    512
+#else
+#define IXGBE_DEFAULT_RXD		    128
+#endif
 #define IXGBE_MAX_RXD			   4096
 #define IXGBE_MIN_RXD			     64
 
-- 
1.8.3.1

^ permalink raw reply related


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