Netdev List
 help / color / mirror / Atom feed
* [PATCH net v2 1/3] net: bcmgenet: fix off-by-one in incrementing read pointer
From: Florian Fainelli @ 2014-10-10 17:51 UTC (permalink / raw)
  To: netdev; +Cc: davem, pgynther, jaedon.shin, Florian Fainelli
In-Reply-To: <1412963514-7718-1-git-send-email-f.fainelli@gmail.com>

Commit b629be5c8399d7c423b92135eb43a86c924d1cbc ("net: bcmgenet: check
harder for out of memory conditions") moved the increment of the local
read pointer *before* reading from the hardware descriptor using
dmadesc_get_length_status(), which creates an off-by-one situation.

Fix this by moving again the read_ptr increment after we have read the
hardware descriptor to get both the control block and the read pointer
back in sync.

Fixes: b629be5c8399 ("net: bcmgenet: check harder for out of memory conditions")
Signed-off-by: Jaedon Shin <jaedon.shin@gmail.com>
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
Changes in v2:
- moved the rxpktprocessed and rx_read_ptr increment after refiling the control
  block

 drivers/net/ethernet/broadcom/genet/bcmgenet.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
index fff2634b6f34..fdc9ec09e453 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -1285,11 +1285,6 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_priv *priv,
 		cb = &priv->rx_cbs[priv->rx_read_ptr];
 		skb = cb->skb;
 
-		rxpktprocessed++;
-
-		priv->rx_read_ptr++;
-		priv->rx_read_ptr &= (priv->num_rx_bds - 1);
-
 		/* We do not have a backing SKB, so we do not have a
 		 * corresponding DMA mapping for this incoming packet since
 		 * bcmgenet_rx_refill always either has both skb and mapping or
@@ -1404,6 +1399,10 @@ refill:
 		err = bcmgenet_rx_refill(priv, cb);
 		if (err)
 			netif_err(priv, rx_err, dev, "Rx refill failed\n");
+
+		rxpktprocessed++;
+		priv->rx_read_ptr++;
+		priv->rx_read_ptr &= (priv->num_rx_bds - 1);
 	}
 
 	return rxpktprocessed;
-- 
1.9.1

^ permalink raw reply related

* [PATCH net v2 2/3] net: bcmgenet: avoid unbalanced enable_irq_wake calls
From: Florian Fainelli @ 2014-10-10 17:51 UTC (permalink / raw)
  To: netdev; +Cc: davem, pgynther, jaedon.shin, Florian Fainelli
In-Reply-To: <1412963514-7718-1-git-send-email-f.fainelli@gmail.com>

Multiple enable_irq_wake() calls will keep increasing the IRQ
wake_depth, which ultimately leads to the following types of
situation:

1) enable Wake-on-LAN interrupt w/o password
2) enable Wake-on-LAN interrupt w/ password
3) enable Wake-on-LAN interrupt w/o password
4) disable Wake-on-LAN interrupt

After step 4), GENET would always wake-up the system no matter what
wake-up device we use, which is not what we want. Fix this by making
sure there are no unbalanced enable_irq_wake() calls.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c b/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c
index b82b7e4e06b2..149a0d70c108 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c
@@ -86,7 +86,9 @@ int bcmgenet_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 	/* Flag the device and relevant IRQ as wakeup capable */
 	if (wol->wolopts) {
 		device_set_wakeup_enable(kdev, 1);
-		enable_irq_wake(priv->wol_irq);
+		/* Avoid unbalanced enable_irq_wake calls */
+		if (priv->wol_irq_disabled)
+			enable_irq_wake(priv->wol_irq);
 		priv->wol_irq_disabled = false;
 	} else {
 		device_set_wakeup_enable(kdev, 0);
-- 
1.9.1

^ permalink raw reply related

* [PATCH net v2 3/3] net: systemport: avoid unbalanced enable_irq_wake calls
From: Florian Fainelli @ 2014-10-10 17:51 UTC (permalink / raw)
  To: netdev; +Cc: davem, pgynther, jaedon.shin, Florian Fainelli
In-Reply-To: <1412963514-7718-1-git-send-email-f.fainelli@gmail.com>

Multiple enable_irq_wake() calls will keep increasing the IRQ
wake_depth, which ultimately leads to the following types of
situation:

1) enable Wake-on-LAN interrupt w/o password
2) enable Wake-on-LAN interrupt w/ password
3) enable Wake-on-LAN interrupt w/o password
4) disable Wake-on-LAN interrupt

After step 4), SYSTEMPORT would always wake-up the system no matter what
wake-up device we use, which is not what we want. Fix this by making
sure there are no unbalanced enable_irq_wake() calls.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 drivers/net/ethernet/broadcom/bcmsysport.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c
index 075688188644..9ae36979bdee 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.c
+++ b/drivers/net/ethernet/broadcom/bcmsysport.c
@@ -436,7 +436,8 @@ static int bcm_sysport_set_wol(struct net_device *dev,
 	/* Flag the device and relevant IRQ as wakeup capable */
 	if (wol->wolopts) {
 		device_set_wakeup_enable(kdev, 1);
-		enable_irq_wake(priv->wol_irq);
+		if (priv->wol_irq_disabled)
+			enable_irq_wake(priv->wol_irq);
 		priv->wol_irq_disabled = 0;
 	} else {
 		device_set_wakeup_enable(kdev, 0);
-- 
1.9.1

^ permalink raw reply related

* Re: [PATCH v2] flow-dissector: Fix alignment issue in __skb_flow_get_ports
From: David Miller @ 2014-10-10 17:55 UTC (permalink / raw)
  To: eric.dumazet; +Cc: alexander.duyck, netdev
In-Reply-To: <1412955376.9362.15.camel@edumazet-glaptop2.roam.corp.google.com>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Fri, 10 Oct 2014 08:36:16 -0700

> On Fri, 2014-10-10 at 07:59 -0700, alexander.duyck@gmail.com wrote:
>> From: Alexander Duyck <alexander.h.duyck@redhat.com>
>> 
>> This patch addresses a kernel unaligned access bug seen on a sparc64 system
>> with an igb adapter.  Specifically the __skb_flow_get_ports was returning a
>> be32 pointer which was then having the value directly returned.
>> 
>> In order to keep the handling of the ports consistent with how we were
>> handling the IPv4 and IPv6 addresses I have instead replaced the assignment
>> with a memcpy to the flow key ports value.  This way it should stay a
>> memcpy on systems that cannot handle unaligned access, and will likely be
>> converted to a 32b assignment on the systems that can support it.
>> 
>> Signed-off-by: Alexander Duyck <alexander.h.duyck@redhat.com>
>> ---
> 
> I believe you also need to take care of calls to ipv6_addr_hash()
> 
> The IPv4 part also needs something in iph_to_flow_copy_addrs(),
> otherwise compiler might assume  &iph->saddr is word aligned.

Right, I still get the unaligned accesses even with this patch:

[487667.804777] Kernel unaligned access at TPC[81de40] __skb_get_poff+0xa0/0x100
[487667.818767] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 3.17.0+ #3
[487667.830930] Call Trace:
[487667.835954]  [0000000000433288] kernel_unaligned_trap+0x368/0x5c0
[487667.848276]  [000000000042a824] sun4v_do_mna+0x84/0xa0
[487667.858698]  [0000000000406cd0] sun4v_mna+0x5c/0x68
[487667.868592]  [000000000081de40] __skb_get_poff+0xa0/0x100
[487667.879531]  [0000000000843d2c] eth_get_headlen+0x6c/0xa0
[487667.890486]  [000000001003ed54] igb_poll+0x8d4/0xf60 [igb]
[487667.901584]  [0000000000824428] net_rx_action+0xa8/0x1c0
[487667.912348]  [000000000046a1fc] __do_softirq+0xdc/0x2e0
[487667.922932]  [000000000042b96c] do_softirq_own_stack+0x2c/0x40
[487667.934751]  [000000000046a6b8] irq_exit+0x98/0xc0
[487667.944473]  [000000000042b900] handler_irq+0xc0/0x100
[487667.954888]  [00000000004208b4] tl0_irq5+0x14/0x20
[487667.964610]  [000000000042c0d4] arch_cpu_idle+0x74/0xa0
[487667.975201]  [0000000000499cdc] cpu_startup_entry+0x17c/0x2c0
[487667.986843]  [0000000000ab69b8] start_kernel+0x408/0x418
[487667.997603]  [00000000008c3628] tlb_fixup_done+0x98/0xb0

^ permalink raw reply

* Re: [PATCH] flow-dissector: Fix alignment issue in __skb_flow_get_ports
From: David Miller @ 2014-10-10 17:58 UTC (permalink / raw)
  To: alexander.h.duyck; +Cc: eric.dumazet, David.Laight, alexander.duyck, netdev
In-Reply-To: <54380E49.5050504@redhat.com>

From: Alexander Duyck <alexander.h.duyck@redhat.com>
Date: Fri, 10 Oct 2014 09:50:17 -0700

> If I just use get_unaligned that is pretty easy in terms of cleanup
> for the ports and IPv4 addresses, the IPv6 will still be a significant
> hurdle to overcome though.

Actually, it's not that simple.

When the compiler sees things like "th->doff" it will load the 32-bit
word that 4-bit field contains and extract the value using shifts and
masking.

So we might need to sprinkle a "attribute((packed))" here and there
to make it work.

^ permalink raw reply

* [PATCH v3] flow-dissector: Fix alignment issue in __skb_flow_get_ports
From: alexander.duyck @ 2014-10-10 18:00 UTC (permalink / raw)
  To: netdev, davem; +Cc: eric.dumazet

From: Alexander Duyck <alexander.h.duyck@redhat.com>

This patch addresses a kernel unaligned access bug seen on a sparc64 system
with an igb adapter.  Specifically the __skb_flow_get_ports was returning a
be32 pointer which was then having the value directly returned.

In order to prevent this it is actually easier to simply not populate the
ports or address values when an skb is not present.  In this case the
assumption is that the data isn't needed and rather than slow down the
faster aligned accesses by making them have to assume the unaligned path on
architectures that don't support efficent unaligned access it makes more
sense to simply switch off the bits that were copying the source and
destination address/port for the case where we only care about the protocol
types and lengths which are normally 16 bit fields anyway.

Reported-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Alexander Duyck <alexander.h.duyck@redhat.com>
---

v2: Fixed alignment to __be16 on ports
v3: Discarded previous approach and instead simplified things by
    not populating ports, or src/dst addresses if skb is not present.
    By doing this we avoid the unaligned access issue entirely and do not
    populate fields that will not be used by the eth_get_headlen function.

 net/core/flow_dissector.c |   24 +++++++++++++++++-------
 1 file changed, 17 insertions(+), 7 deletions(-)

diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 8560dea..80ca371 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -100,7 +100,15 @@ ip:
 		if (ip_is_fragment(iph))
 			ip_proto = 0;
 
+		/* skip the address processing if skb is NULL.  The assumption
+		 * here is that if there is no skb we are not looking for flow
+		 * info but lengths and protocols.
+		 */
+		if (!skb)
+			break;
+
 		iph_to_flow_copy_addrs(flow, iph);
+
 		break;
 	}
 	case htons(ETH_P_IPV6): {
@@ -114,17 +122,15 @@ ipv6:
 			return false;
 
 		ip_proto = iph->nexthdr;
-		flow->src = (__force __be32)ipv6_addr_hash(&iph->saddr);
-		flow->dst = (__force __be32)ipv6_addr_hash(&iph->daddr);
 		nhoff += sizeof(struct ipv6hdr);
 
-		/* skip the flow label processing if skb is NULL.  The
-		 * assumption here is that if there is no skb we are not
-		 * looking for flow info as much as we are length.
-		 */
+		/* see comment above in IPv4 section */
 		if (!skb)
 			break;
 
+		flow->src = (__force __be32)ipv6_addr_hash(&iph->saddr);
+		flow->dst = (__force __be32)ipv6_addr_hash(&iph->daddr);
+
 		flow_label = ip6_flowlabel(iph);
 		if (flow_label) {
 			/* Awesome, IPv6 packet has a flow label so we can
@@ -231,9 +237,13 @@ ipv6:
 
 	flow->n_proto = proto;
 	flow->ip_proto = ip_proto;
-	flow->ports = __skb_flow_get_ports(skb, nhoff, ip_proto, data, hlen);
 	flow->thoff = (u16) nhoff;
 
+	/* unless skb is set we don't need to record port info */
+	if (skb)
+		flow->ports = __skb_flow_get_ports(skb, nhoff, ip_proto,
+						   data, hlen);
+
 	return true;
 }
 EXPORT_SYMBOL(__skb_flow_dissect);

^ permalink raw reply related

* Re: [PATCH] flow-dissector: Fix alignment issue in __skb_flow_get_ports
From: Alexander Duyck @ 2014-10-10 18:02 UTC (permalink / raw)
  To: David Miller, alexander.h.duyck; +Cc: eric.dumazet, David.Laight, netdev
In-Reply-To: <20141010.135851.1743803688676076555.davem@davemloft.net>

On 10/10/2014 10:58 AM, David Miller wrote:
> From: Alexander Duyck <alexander.h.duyck@redhat.com>
> Date: Fri, 10 Oct 2014 09:50:17 -0700
>
>> If I just use get_unaligned that is pretty easy in terms of cleanup
>> for the ports and IPv4 addresses, the IPv6 will still be a significant
>> hurdle to overcome though.
> Actually, it's not that simple.
>
> When the compiler sees things like "th->doff" it will load the 32-bit
> word that 4-bit field contains and extract the value using shifts and
> masking.
>
> So we might need to sprinkle a "attribute((packed))" here and there
> to make it work.

I'll do some digging.  I know I had this working in igb/ixgbe before so
I probably just need to add a few small tweaks to resolve the remaining
issues for v4 of the patch.

Thanks,

Alex

^ permalink raw reply

* Re: [PATCH] flow-dissector: Fix alignment issue in __skb_flow_get_ports
From: David Miller @ 2014-10-10 18:14 UTC (permalink / raw)
  To: alexander.duyck; +Cc: alexander.h.duyck, eric.dumazet, David.Laight, netdev
In-Reply-To: <54381F1C.2030800@gmail.com>

From: Alexander Duyck <alexander.duyck@gmail.com>
Date: Fri, 10 Oct 2014 11:02:04 -0700

> On 10/10/2014 10:58 AM, David Miller wrote:
>> From: Alexander Duyck <alexander.h.duyck@redhat.com>
>> Date: Fri, 10 Oct 2014 09:50:17 -0700
>>
>>> If I just use get_unaligned that is pretty easy in terms of cleanup
>>> for the ports and IPv4 addresses, the IPv6 will still be a significant
>>> hurdle to overcome though.
>> Actually, it's not that simple.
>>
>> When the compiler sees things like "th->doff" it will load the 32-bit
>> word that 4-bit field contains and extract the value using shifts and
>> masking.
>>
>> So we might need to sprinkle a "attribute((packed))" here and there
>> to make it work.
> 
> I'll do some digging.  I know I had this working in igb/ixgbe before so
> I probably just need to add a few small tweaks to resolve the remaining
> issues for v4 of the patch.

Ok, I think v3 + resolving the th->doff thing will get rid of everything.

^ permalink raw reply

* Re: [PATCH net v2 1/3] net: bcmgenet: fix off-by-one in incrementing read pointer
From: Petri Gynther @ 2014-10-10 18:15 UTC (permalink / raw)
  To: Florian Fainelli; +Cc: netdev, David Miller, Jaedon Shin
In-Reply-To: <1412963514-7718-2-git-send-email-f.fainelli@gmail.com>

Looks good to me.

On Fri, Oct 10, 2014 at 10:51 AM, Florian Fainelli <f.fainelli@gmail.com> wrote:
> Commit b629be5c8399d7c423b92135eb43a86c924d1cbc ("net: bcmgenet: check
> harder for out of memory conditions") moved the increment of the local
> read pointer *before* reading from the hardware descriptor using
> dmadesc_get_length_status(), which creates an off-by-one situation.
>
> Fix this by moving again the read_ptr increment after we have read the
> hardware descriptor to get both the control block and the read pointer
> back in sync.
>
> Fixes: b629be5c8399 ("net: bcmgenet: check harder for out of memory conditions")
> Signed-off-by: Jaedon Shin <jaedon.shin@gmail.com>
> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>

Acked-by: Petri Gynther <pgynther@google.com>

> ---
> Changes in v2:
> - moved the rxpktprocessed and rx_read_ptr increment after refiling the control
>   block
>
>  drivers/net/ethernet/broadcom/genet/bcmgenet.c | 9 ++++-----
>  1 file changed, 4 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
> index fff2634b6f34..fdc9ec09e453 100644
> --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
> +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
> @@ -1285,11 +1285,6 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_priv *priv,
>                 cb = &priv->rx_cbs[priv->rx_read_ptr];
>                 skb = cb->skb;
>
> -               rxpktprocessed++;
> -
> -               priv->rx_read_ptr++;
> -               priv->rx_read_ptr &= (priv->num_rx_bds - 1);
> -
>                 /* We do not have a backing SKB, so we do not have a
>                  * corresponding DMA mapping for this incoming packet since
>                  * bcmgenet_rx_refill always either has both skb and mapping or
> @@ -1404,6 +1399,10 @@ refill:
>                 err = bcmgenet_rx_refill(priv, cb);
>                 if (err)
>                         netif_err(priv, rx_err, dev, "Rx refill failed\n");
> +
> +               rxpktprocessed++;
> +               priv->rx_read_ptr++;
> +               priv->rx_read_ptr &= (priv->num_rx_bds - 1);
>         }
>
>         return rxpktprocessed;
> --
> 1.9.1
>

^ permalink raw reply

* Re: [PATCH] flow-dissector: Fix alignment issue in __skb_flow_get_ports
From: David Miller @ 2014-10-10 18:15 UTC (permalink / raw)
  To: alexander.duyck; +Cc: alexander.h.duyck, eric.dumazet, David.Laight, netdev
In-Reply-To: <54381F1C.2030800@gmail.com>

From: Alexander Duyck <alexander.duyck@gmail.com>
Date: Fri, 10 Oct 2014 11:02:04 -0700

> On 10/10/2014 10:58 AM, David Miller wrote:
>> From: Alexander Duyck <alexander.h.duyck@redhat.com>
>> Date: Fri, 10 Oct 2014 09:50:17 -0700
>>
>>> If I just use get_unaligned that is pretty easy in terms of cleanup
>>> for the ports and IPv4 addresses, the IPv6 will still be a significant
>>> hurdle to overcome though.
>> Actually, it's not that simple.
>>
>> When the compiler sees things like "th->doff" it will load the 32-bit
>> word that 4-bit field contains and extract the value using shifts and
>> masking.
>>
>> So we might need to sprinkle a "attribute((packed))" here and there
>> to make it work.
> 
> I'll do some digging.  I know I had this working in igb/ixgbe before so
> I probably just need to add a few small tweaks to resolve the remaining
> issues for v4 of the patch.

Your original code works because you do things like "byte[12] & 0xf0" to
extract these fields.

^ permalink raw reply

* Re: [PATCH] flow-dissector: Fix alignment issue in __skb_flow_get_ports
From: David Miller @ 2014-10-10 18:22 UTC (permalink / raw)
  To: alexander.duyck; +Cc: alexander.h.duyck, eric.dumazet, David.Laight, netdev
In-Reply-To: <20141010.141559.2024576018585843684.davem@davemloft.net>

From: David Miller <davem@davemloft.net>
Date: Fri, 10 Oct 2014 14:15:59 -0400 (EDT)

> Your original code works because you do things like "byte[12] & 0xf0" to
> extract these fields.

Changing that th->doff sequence to instead be:

		const u8 *bp;
		u8 buf[13];

		bp = __skb_header_pointer(skb, poff, sizeof(buf),
					  data, hlen, &buf);
		if (!bp)
			return poff;

		poff += max_t(u32, sizeof(struct tcphdr), (bp[12] & 0xf0) >> 2);
		break;

on top of your v3 patch works for me.

Please double-check my calculations.

^ permalink raw reply

* Re: [PATCH 1/1] Checkpatch: coding style errors in Nvidia ethernet driver
From: David Miller @ 2014-10-10 18:25 UTC (permalink / raw)
  To: akshaysarode21; +Cc: john.stultz, netdev, linux-kernel
In-Reply-To: <1412928102-1696-1-git-send-email-akshaysarode21@gmail.com>

From: Akshay Sarode <akshaysarode21@gmail.com>
Date: Fri, 10 Oct 2014 13:31:42 +0530

> ERROR: "foo* bar" should be "foo *bar"
> ERROR: do not initialise statics to 0 or NULL
> CHECK: spinlock_t definition without comment
> Signed-off-by: Akshay Sarode <akshaysarode21@gmail.com>

The Subject "Subsystem: " prefix is meant to refer to what area of
the kernel you are changing.

You aren't making changes to "Checkpatch: " so that isn't an
appropriate prefix.  Someone scanning the commit header lines
won't be able to tell what part of the kernel your change is
touching.

In this case you should use "nvidia: " as your subsystem
prefix.

^ permalink raw reply

* [PATCH net-next] net: bcmgenet: enable driver to work without a device tree
From: Petri Gynther @ 2014-10-10 18:35 UTC (permalink / raw)
  To: netdev; +Cc: davem, f.fainelli

Broadcom 7xxx MIPS-based STB platforms do not use device trees.
Modify bcmgenet driver so that it can be used on those platforms.

Signed-off-by: Petri Gynther <pgynther@google.com>
---
 drivers/net/ethernet/broadcom/Kconfig          |   1 -
 drivers/net/ethernet/broadcom/genet/bcmgenet.c |  30 +++--
 drivers/net/ethernet/broadcom/genet/bcmgenet.h |  11 ++
 drivers/net/ethernet/broadcom/genet/bcmmii.c   | 169 +++++++++++++++++++++----
 4 files changed, 179 insertions(+), 32 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig
index c3e260c..888247a 100644
--- a/drivers/net/ethernet/broadcom/Kconfig
+++ b/drivers/net/ethernet/broadcom/Kconfig
@@ -62,7 +62,6 @@ config BCM63XX_ENET
 
 config BCMGENET
 	tristate "Broadcom GENET internal MAC support"
-	depends on OF
 	select MII
 	select PHYLIB
 	select FIXED_PHY if BCMGENET=y
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
index fff2634..1ec7a32 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -2475,6 +2475,7 @@ static const struct of_device_id bcmgenet_match[] = {
 
 static int bcmgenet_probe(struct platform_device *pdev)
 {
+	struct bcmgenet_platform_data *pd = pdev->dev.platform_data;
 	struct device_node *dn = pdev->dev.of_node;
 	const struct of_device_id *of_id;
 	struct bcmgenet_priv *priv;
@@ -2490,9 +2491,13 @@ static int bcmgenet_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
-	of_id = of_match_node(bcmgenet_match, dn);
-	if (!of_id)
-		return -EINVAL;
+	if (dn) {
+		of_id = of_match_node(bcmgenet_match, dn);
+		if (!of_id)
+			return -EINVAL;
+	} else {
+		of_id = NULL;
+	}
 
 	priv = netdev_priv(dev);
 	priv->irq0 = platform_get_irq(pdev, 0);
@@ -2504,11 +2509,15 @@ static int bcmgenet_probe(struct platform_device *pdev)
 		goto err;
 	}
 
-	macaddr = of_get_mac_address(dn);
-	if (!macaddr) {
-		dev_err(&pdev->dev, "can't find MAC address\n");
-		err = -EINVAL;
-		goto err;
+	if (dn) {
+		macaddr = of_get_mac_address(dn);
+		if (!macaddr) {
+			dev_err(&pdev->dev, "can't find MAC address\n");
+			err = -EINVAL;
+			goto err;
+		}
+	} else {
+		macaddr = pd->macaddr;
 	}
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -2548,7 +2557,10 @@ static int bcmgenet_probe(struct platform_device *pdev)
 
 	priv->dev = dev;
 	priv->pdev = pdev;
-	priv->version = (enum bcmgenet_version)of_id->data;
+	if (of_id)
+		priv->version = (enum bcmgenet_version)of_id->data;
+	else
+		priv->version = pd->genet_version;
 
 	priv->clk = devm_clk_get(&priv->pdev->dev, "enet");
 	if (IS_ERR(priv->clk))
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
index dbf524e..5191e3f 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
@@ -17,6 +17,17 @@
 #include <linux/if_vlan.h>
 #include <linux/phy.h>
 
+struct bcmgenet_platform_data {
+	void __iomem	*base_reg;
+	int		irq0;
+	int		irq1;
+	int		phy_type;
+	int		phy_addr;
+	int		phy_speed;
+	u8		macaddr[ETH_ALEN];
+	int		genet_version;
+};
+
 /* total number of Buffer Descriptors, same for Rx/Tx */
 #define TOTAL_DESC				256
 
diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c
index 9ff799a..e5ff913 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmmii.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c
@@ -157,6 +157,21 @@ static void bcmgenet_mii_setup(struct net_device *dev)
 	phy_print_status(phydev);
 }
 
+static int bcmgenet_moca_fphy_update(struct net_device *dev,
+				     struct fixed_phy_status *status)
+{
+	struct bcmgenet_priv *priv = netdev_priv(dev);
+	struct phy_device *phydev = priv->phydev;
+
+	/*
+	 * MoCA daemon updates phydev->autoneg to reflect the link status.
+	 * Update MoCA fixed PHY status accordingly, so that the PHY state
+	 * machine becomes aware of the real link status.
+	 */
+	status->link = phydev->autoneg;
+	return 0;
+}
+
 void bcmgenet_mii_reset(struct net_device *dev)
 {
 	struct bcmgenet_priv *priv = netdev_priv(dev);
@@ -311,22 +326,6 @@ static int bcmgenet_mii_probe(struct net_device *dev)
 	u32 phy_flags;
 	int ret;
 
-	if (priv->phydev) {
-		pr_info("PHY already attached\n");
-		return 0;
-	}
-
-	/* In the case of a fixed PHY, the DT node associated
-	 * to the PHY is the Ethernet MAC DT node.
-	 */
-	if (!priv->phy_dn && of_phy_is_fixed_link(dn)) {
-		ret = of_phy_register_fixed_link(dn);
-		if (ret)
-			return ret;
-
-		priv->phy_dn = of_node_get(dn);
-	}
-
 	/* Communicate the integrated PHY revision */
 	phy_flags = priv->gphy_rev;
 
@@ -336,11 +335,39 @@ static int bcmgenet_mii_probe(struct net_device *dev)
 	priv->old_duplex = -1;
 	priv->old_pause = -1;
 
-	phydev = of_phy_connect(dev, priv->phy_dn, bcmgenet_mii_setup,
-				phy_flags, priv->phy_interface);
-	if (!phydev) {
-		pr_err("could not attach to PHY\n");
-		return -ENODEV;
+	if (dn) {
+		if (priv->phydev) {
+			pr_info("PHY already attached\n");
+			return 0;
+		}
+
+		/* In the case of a fixed PHY, the DT node associated
+		 * to the PHY is the Ethernet MAC DT node.
+		 */
+		if (!priv->phy_dn && of_phy_is_fixed_link(dn)) {
+			ret = of_phy_register_fixed_link(dn);
+			if (ret)
+				return ret;
+
+			priv->phy_dn = of_node_get(dn);
+		}
+
+		phydev = of_phy_connect(dev, priv->phy_dn, bcmgenet_mii_setup,
+					phy_flags, priv->phy_interface);
+		if (!phydev) {
+			pr_err("could not attach to PHY\n");
+			return -ENODEV;
+		}
+	} else {
+		phydev = priv->phydev;
+		phydev->dev_flags = phy_flags;
+
+		ret = phy_connect_direct(dev, phydev, bcmgenet_mii_setup,
+					 priv->phy_interface);
+		if (ret) {
+			pr_err("could not attach to PHY\n");
+			return -ENODEV;
+		}
 	}
 
 	priv->phydev = phydev;
@@ -437,6 +464,104 @@ static int bcmgenet_mii_of_init(struct bcmgenet_priv *priv)
 	return 0;
 }
 
+static int bcmgenet_mii_pd_init(struct bcmgenet_priv *priv)
+{
+	struct device *kdev = &priv->pdev->dev;
+	struct bcmgenet_platform_data *pd = kdev->platform_data;
+	struct mii_bus *mdio = priv->mii_bus;
+	int phy_addr = pd->phy_addr;
+	struct phy_device *phydev;
+	int ret;
+	int i;
+
+	/* Disable automatic MDIO bus scan */
+	mdio->phy_mask = ~0;
+
+	/* Clear all the IRQ properties */
+	if (mdio->irq)
+		for (i = 0; i < PHY_MAX_ADDR; i++)
+			mdio->irq[i] = PHY_POLL;
+
+	/* Register the MDIO bus */
+	ret = mdiobus_register(mdio);
+	if (ret) {
+		dev_err(kdev, "failed to register MDIO bus\n");
+		return ret;
+	}
+
+	/*
+	 * bcmgenet_platform_data needs to pass a valid PHY address for
+	 * internal/external PHY or -1 for MoCA PHY.
+	 */
+	if (phy_addr >= 0 && phy_addr < PHY_MAX_ADDR) {
+		/*
+		 * 10/100/1000 Ethernet port with external or internal PHY.
+		 */
+		phydev = get_phy_device(mdio, phy_addr, false);
+		if (!phydev || IS_ERR(phydev)) {
+			dev_err(kdev, "failed to create PHY device\n");
+			mdiobus_unregister(mdio);
+			return 1;
+		}
+
+		phydev->irq = PHY_POLL;
+
+		ret = phy_device_register(phydev);
+		if (ret) {
+			dev_err(kdev, "failed to register PHY device\n");
+			phy_device_free(phydev);
+			mdiobus_unregister(mdio);
+			return 1;
+		}
+
+		priv->phydev = phydev;
+		priv->phy_interface = pd->phy_type;
+	} else {
+		/*
+		 * MoCA port with no MDIO-accessible PHY.
+		 * We need to use 1000/HD fixed PHY to represent the link layer.
+		 * MoCA daemon interacts with this PHY via ethtool.
+		 */
+		struct fixed_phy_status moca_fphy_status = {
+			.link = 0,
+			.duplex = 0,
+			.speed = 1000,
+			.pause = 0,
+			.asym_pause = 0,
+		};
+
+		phydev = fixed_phy_register(PHY_POLL, &moca_fphy_status, NULL);
+		if (!phydev || IS_ERR(phydev)) {
+			dev_err(kdev, "failed to register fixed PHY device\n");
+			mdiobus_unregister(mdio);
+			return 1;
+		}
+
+		phydev->autoneg = AUTONEG_DISABLE;
+
+		ret = fixed_phy_set_link_update(phydev,
+						bcmgenet_moca_fphy_update);
+		if (ret) {
+			dev_err(kdev, "failed to set fixed PHY link update\n");
+		}
+
+		priv->phydev = phydev;
+		priv->phy_interface = PHY_INTERFACE_MODE_MOCA;
+	}
+
+	return 0;
+}
+
+static int bcmgenet_mii_bus_init(struct bcmgenet_priv *priv)
+{
+	struct device_node *dn = priv->pdev->dev.of_node;
+
+	if (dn)
+		return bcmgenet_mii_of_init(priv);
+	else
+		return bcmgenet_mii_pd_init(priv);
+}
+
 int bcmgenet_mii_init(struct net_device *dev)
 {
 	struct bcmgenet_priv *priv = netdev_priv(dev);
@@ -446,7 +571,7 @@ int bcmgenet_mii_init(struct net_device *dev)
 	if (ret)
 		return ret;
 
-	ret = bcmgenet_mii_of_init(priv);
+	ret = bcmgenet_mii_bus_init(priv);
 	if (ret)
 		goto out_free;
 
-- 
2.1.0.rc2.206.gedb03e5

^ permalink raw reply related

* Re: eth_get_headlen() and unaligned accesses...
From: Tom Herbert @ 2014-10-10 18:41 UTC (permalink / raw)
  To: David Miller; +Cc: Linux Netdev List, Alexander Duyck
In-Reply-To: <20141009.201248.1210454965155680255.davem@davemloft.net>

On Thu, Oct 9, 2014 at 5:12 PM, David Miller <davem@davemloft.net> wrote:
>
> So, we have a bit of a problem, this is on sparc64:
>
> [423475.740836] Kernel unaligned access at TPC[81d330] __skb_flow_get_ports+0x70/0xe0
> [423475.755756] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 3.17.0+ #2
> [423475.767854] Call Trace:
> [423475.772877]  [0000000000433288] kernel_unaligned_trap+0x368/0x5c0
> [423475.785203]  [000000000042a824] sun4v_do_mna+0x84/0xa0
> [423475.795624]  [0000000000406cd0] sun4v_mna+0x5c/0x68
> [423475.805521]  [000000000081d330] __skb_flow_get_ports+0x70/0xe0
> [423475.817323]  [000000000081d6ac] __skb_flow_dissect+0x1ac/0x460
> [423475.829128]  [0000000000843c98] eth_get_headlen+0x38/0xa0
> [423475.840083]  [0000000010064d54] igb_poll+0x8d4/0xf60 [igb]
> [423475.851184]  [00000000008243c8] net_rx_action+0xa8/0x1c0
>
> The chip DMA's to the beginning of a frag page and (unless timestamps
> are enabled) that's where the ethernet header begins.
>
> So any larger than 16-bit access to the IP and later headers will be
> unaligned.
>
Will this also be a problem for GRE packet carrying Ethernet packet?

> We have various ways we can deal with this based upon the capabilities
> of the chips involved.  Can we configure the IGB to put 2 "don't care"
> bytes at the beginning of the packet?
> --
> 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] net: pxa168_eth: PXA168_ETH should depend on HAS_DMA
From: David Miller @ 2014-10-10 18:46 UTC (permalink / raw)
  To: geert; +Cc: netdev, linux-kernel
In-Reply-To: <1412864142-21468-1-git-send-email-geert@linux-m68k.org>

From: Geert Uytterhoeven <geert@linux-m68k.org>
Date: Thu,  9 Oct 2014 16:15:42 +0200

> If NO_DMA=y:
...
> Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>

Applied, thank you.

^ permalink raw reply

* [PATCH RFC v4 net 0/3]: ipv6: Reduce the number of fib6_lookup() calls from ip6_pol_route()
From: Martin KaFai Lau @ 2014-10-10 18:48 UTC (permalink / raw)
  To: netdev

Hi,

This patch set is trying to reduce the number of fib6_lookup()
calls from ip6_pol_route().

I have adapted davem's udpflood and kbench_mod test
(https://git.kernel.org/pub/scm/linux/kernel/git/davem/net_test_tools.git) to
support IPv6 and here is the result:


Before:
[root]# for i in $(seq 1 3); do time ./udpflood -l 20000000 -c 250 2401:face:face:face::2; done

real    0m34.190s
user    0m3.047s
sys     0m31.108s

real    0m34.635s
user    0m3.125s
sys     0m31.475s

real    0m34.517s
user    0m3.034s
sys     0m31.449s

[root]# insmod ip6_route_kbench.ko oif=2 src=2401:face:face:face::1 dst=2401:face:face:face::2
[  660.160976] ip6_route_kbench: ip6_route_output tdiff: 933
[  660.207261] ip6_route_kbench: ip6_route_output tdiff: 988
[  660.253492] ip6_route_kbench: ip6_route_output tdiff: 896
[  660.298862] ip6_route_kbench: ip6_route_output tdiff: 898

After:
[root]# for i in $(seq 1 3); do time ./udpflood -l 20000000 -c 250 2401:face:face:face::2; done

real    0m32.695s
user    0m2.925s
sys     0m29.737s

real    0m32.636s
user    0m3.007s
sys     0m29.596s

real    0m32.797s
user    0m2.866s
sys     0m29.898s

[root]# insmod ip6_route_kbench.ko oif=2 src=2401:face:face:face::1 dst=2401:face:face:face::2
[  881.220793] ip6_route_kbench: ip6_route_output tdiff: 684
[  881.253477] ip6_route_kbench: ip6_route_output tdiff: 640
[  881.286867] ip6_route_kbench: ip6_route_output tdiff: 630
[  881.320749] ip6_route_kbench: ip6_route_output tdiff: 653


/****************************** udpflood.c ******************************/
/* It is an adaptation of the Eric Dumazet's and David Miller's
 * udpflood tool, by adding IPv6 support.
 */

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <malloc.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <stdint.h>
#include <assert.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define _GNU_SOURCE
#include <getopt.h>

typedef uint32_t u32;

static int debug =3D 0;

/* Allow -fstrict-aliasing */
typedef union sa_u {
	struct sockaddr_storage a46;
	struct sockaddr_in a4;
	struct sockaddr_in6 a6;
} sa_u;

static int usage(void)
{
	printf("usage: udpflood [ -l count ] [ -m message_size ] [ -c num_ip_addrs=
 ] IP_ADDRESS\n");
	return -1;
}

static u32 get_last32h(const sa_u *sa)
{
	if (sa->a46.ss_family =3D=3D PF_INET)
		return ntohl(sa->a4.sin_addr.s_addr);
	else
		return ntohl(sa->a6.sin6_addr.s6_addr32[3]);
}

static void set_last32h(sa_u *sa, u32 last32h)
{
	if (sa->a46.ss_family =3D=3D PF_INET)
		sa->a4.sin_addr.s_addr =3D htonl(last32h);
	else
		sa->a6.sin6_addr.s6_addr32[3] =3D htonl(last32h);
}

static void print_saddr(const sa_u *sa, const char *msg)
{
	char buf[64];

	if (!debug)
		return;

	switch (sa->a46.ss_family) {
	case PF_INET:
		inet_ntop(PF_INET, &(sa->a4.sin_addr.s_addr), buf,
			  sizeof(buf));
		break;
	case PF_INET6:
		inet_ntop(PF_INET6, &(sa->a6.sin6_addr), buf, sizeof(buf));
		break;
	}

	printf("%s: %s\n", msg, buf);
}

static int send_packets(const sa_u *sa, size_t num_addrs, int count, int ms=
g_sz)
{
	char *msg =3D malloc(msg_sz);
	sa_u saddr;
	u32 start_addr32h, end_addr32h, cur_addr32h;
	int fd, i, err;

	if (!msg)
		return -ENOMEM;

	memset(msg, 0, msg_sz);

	memcpy(&saddr, sa, sizeof(saddr));
	cur_addr32h =3D start_addr32h =3D get_last32h(&saddr);
	end_addr32h =3D start_addr32h + num_addrs;

	fd =3D socket(saddr.a46.ss_family, SOCK_DGRAM, 0);
	if (fd < 0) {
		perror("socket");
		err =3D fd;
		goto out_nofd;
	}

	/* connect to avoid the kernel spending time in figuring
	 * out the source address (i.e pin the src address)
	 */
	err =3D connect(fd, (struct sockaddr *) &saddr, sizeof(saddr));
	if (err < 0) {
		perror("connect");
		goto out;
	}

	print_saddr(&saddr, "start_addr");
	for (i =3D 0; i < count; i++) {
		print_saddr(&saddr, "sendto");
		err =3D sendto(fd, msg, msg_sz, 0, (struct sockaddr *)&saddr,
			     sizeof(saddr));
		if (err < 0) {
			perror("sendto");
			goto out;
		}

		if (++cur_addr32h >=3D end_addr32h)
			cur_addr32h =3D start_addr32h;
		set_last32h(&saddr, cur_addr32h);
	}

	err =3D 0;
out:
	close(fd);
out_nofd:
	free(msg);
	return err;
}

int main(int argc, char **argv, char **envp)
{
	int port, msg_sz, count, num_addrs, ret;

	sa_u start_addr;

	port =3D 6000;
	msg_sz =3D 32;
	count =3D 10000000;
	num_addrs =3D 1;

	while ((ret =3D getopt(argc, argv, "dl:s:p:c:")) >=3D 0) {
		switch (ret) {
		case 'l':
			sscanf(optarg, "%d", &count);
			break;
		case 's':
			sscanf(optarg, "%d", &msg_sz);
			break;
		case 'p':
			sscanf(optarg, "%d", &port);
			break;
		case 'c':
			sscanf(optarg, "%d", &num_addrs);
			break;
		case 'd':
			debug =3D 1;
			break;
		case '?':
			return usage();
		}
	}

	if (num_addrs < 1)
		return usage();

	if (!argv[optind])
		return usage();

	start_addr.a4.sin_port =3D htons(port);
	if (inet_pton(PF_INET, argv[optind], &start_addr.a4.sin_addr))
		start_addr.a46.ss_family =3D PF_INET;
	else if (inet_pton(PF_INET6, argv[optind], &start_addr.a6.sin6_addr.s6_add=
r))
		start_addr.a46.ss_family =3D PF_INET6;
	else
		return usage();

	return send_packets(&start_addr, num_addrs, count, msg_sz);
}

/****************** ip6_route_kbench_mod.c ******************/
#define pr_fmt(fmt) "ip6_route_kbench: " fmt

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/inet.h>
#include <linux/in6.h>

#include <net/route.h>
#include <net/ip6_route.h>

#include <linux/timex.h>
#include <uapi/linux/icmpv6.h>

/* We can't just use "get_cycles()" as on some platforms, such
 * as sparc64, that gives system cycles rather than cpu clock
 * cycles.
 */

#ifdef CONFIG_SPARC64
static inline unsigned long long get_tick(void)
{
	unsigned long long t;

	__asm__ __volatile__("rd %%tick, %0" : "=r" (t));
	return t;
}
#elif defined(CONFIG_X86)
static inline unsigned long long get_tick(void)
{
	unsigned long long t;

	rdtscll(t);

	return t;
}
#elif defined(CONFIG_POWERPC)
static inline unsigned long long get_tick(void)
{
	return get_cycles();
}
#else
#error Unsupported architecture, please implement get_tick()
#endif

#define DEFAULT_WARMUP_COUNT 100000

#define DEFAULT_DST_IP_ADDR	0x4a800001
#define DEFAULT_SRC_IP_ADDR	0x00000000
#define DEFAULT_OIF		0
#define DEFAULT_IIF		0
#define DEFAULT_MARK		0x00000000
#define DEFAULT_TOS		0x00

static int flow_oif = DEFAULT_OIF;
static int flow_iif = DEFAULT_IIF;
static u32 flow_mark = DEFAULT_MARK;
static struct in6_addr flow_dst_ip_addr;
static struct in6_addr flow_src_ip_addr;
static int flow_tos = DEFAULT_TOS;

static char dst_string[64];
static char src_string[64];

module_param_string(dst, dst_string, sizeof(dst_string), 0);
module_param_string(src, src_string, sizeof(src_string), 0);

static int __init flow_setup(void)
{
	if (dst_string[0] &&
	    !in6_pton(dst_string, -1, &flow_dst_ip_addr.s6_addr[0], -1, NULL)) {
		pr_info("cannot parse \"%s\"\n", dst_string);
		return -1;
	}

	if (src_string[0] &&
	    !in6_pton(src_string, -1, &flow_src_ip_addr.s6_addr[0], -1, NULL)) {
		pr_info("cannot parse \"%s\"\n", dst_string);
		return -1;
	}

	return 0;
}

module_param_named(oif, flow_oif, int, 0);
module_param_named(iif, flow_iif, int, 0);
module_param_named(mark, flow_mark, uint, 0);
module_param_named(tos, flow_tos, int, 0);

static int warmup_count = DEFAULT_WARMUP_COUNT;
module_param_named(count, warmup_count, int, 0);

static void flow_init(struct flowi6 *fl6)
{
	memset(fl6, 0, sizeof(*fl6));
	fl6->flowi6_proto = IPPROTO_ICMPV6;
	fl6->flowi6_oif = flow_oif;
	fl6->flowi6_iif = flow_iif;
	fl6->flowi6_mark = flow_mark;
	fl6->flowi6_tos = flow_tos;
	fl6->daddr = flow_dst_ip_addr;
	fl6->saddr = flow_src_ip_addr;
}

static struct sk_buff * fake_skb_get(void)
{
	struct ipv6hdr *hdr;
	struct sk_buff *skb;

	skb = alloc_skb(4096, GFP_KERNEL);
	if (!skb) {
		pr_info("Cannot alloc SKB for test\n");
		return NULL;
	}
	skb->dev = __dev_get_by_index(&init_net, flow_iif);
	if (skb->dev == NULL) {
		pr_info("Input device (%d) does not exist\n", flow_iif);
		goto err;
	}

	skb_reset_mac_header(skb);
	skb_reset_network_header(skb);
	skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr));
	hdr = ipv6_hdr(skb);

	hdr->priority = 0;
	hdr->version = 6;
	memset(hdr->flow_lbl, 0, sizeof(hdr->flow_lbl));
	hdr->payload_len = htons(sizeof(struct icmp6hdr));
	hdr->nexthdr = IPPROTO_ICMPV6;
	hdr->saddr = flow_src_ip_addr;
	hdr->daddr = flow_dst_ip_addr;
	skb->protocol = htons(ETH_P_IPV6);
	skb->mark = flow_mark;

	return skb;
err:
	kfree_skb(skb);
	return NULL;
}

static void do_full_output_lookup_bench(void)
{
	unsigned long long t1, t2, tdiff;
	struct rt6_info *rt;
	struct flowi6 fl6;
	int i;

	rt = NULL;

	for (i = 0; i < warmup_count; i++) {
		flow_init(&fl6);

		rt = (struct rt6_info *)ip6_route_output(&init_net, NULL, &fl6);
		if (IS_ERR(rt))
			break;
		ip6_rt_put(rt);
	}
	if (IS_ERR(rt)) {
		pr_info("ip_route_output_key: err=%ld\n", PTR_ERR(rt));
		return;
	}

	flow_init(&fl6);

	t1 = get_tick();
	rt = (struct rt6_info *)ip6_route_output(&init_net, NULL, &fl6);
	t2 = get_tick();
	if (!IS_ERR(rt))
		ip6_rt_put(rt);

	tdiff = t2 - t1;
	pr_info("ip6_route_output tdiff: %llu\n", tdiff);
}

static void do_full_input_lookup_bench(void)
{
	unsigned long long t1, t2, tdiff;
	struct sk_buff *skb;
	struct rt6_info *rt;
	int err, i;

	skb = fake_skb_get();
	if (skb == NULL)
		goto out_free;

	err = 0;
	local_bh_disable();
	for (i = 0; i < warmup_count; i++) {
		ip6_route_input(skb);
		rt = (struct rt6_info *)skb_dst(skb);
		err = (!rt || rt == init_net.ipv6.ip6_null_entry);
		skb_dst_drop(skb);
		if (err)
			break;
	}
	local_bh_enable();

	if (err) {
		pr_info("Input route lookup fails\n");
		goto out_free;
	}

	local_bh_disable();
	t1 = get_tick();
	ip6_route_input(skb);
	t2 = get_tick();
	local_bh_enable();

	rt = (struct rt6_info *)skb_dst(skb);
	err = (!rt || rt == init_net.ipv6.ip6_null_entry);
	skb_dst_drop(skb);
	if (err) {
		pr_info("Input route lookup fails\n");
		goto out_free;
	}

	tdiff = t2 - t1;
	pr_info("ip6_route_input tdiff: %llu\n", tdiff);

out_free:
	kfree_skb(skb);
}

static void do_full_lookup_bench(void)
{
	if (!flow_iif)
		do_full_output_lookup_bench();
	else
		do_full_input_lookup_bench();
}

static void do_bench(void)
{
	do_full_lookup_bench();
	do_full_lookup_bench();
	do_full_lookup_bench();
	do_full_lookup_bench();
}

static int __init kbench_init(void)
{
	if (flow_setup())
		return -EINVAL;

	pr_info("flow [IIF(%d),OIF(%d),MARK(0x%08x),D("IP6_FMT"),"
		"S("IP6_FMT"),TOS(0x%02x)]\n",
		flow_iif, flow_oif, flow_mark,
		IP6_PRT(flow_dst_ip_addr),
		IP6_PRT(flow_src_ip_addr),
		flow_tos);

#if defined(CONFIG_X86)
	if (!cpu_has_tsc) {
		pr_err("X86 TSC is required, but is unavailable.\n");
		return -EINVAL;
	}
#endif

	pr_info("sizeof(struct rt6_info)==%zu\n", sizeof(struct rt6_info));

	do_bench();

	return -ENODEV;
}

static void __exit kbench_exit(void)
{
}

module_init(kbench_init);
module_exit(kbench_exit);
MODULE_LICENSE("GPL");

^ permalink raw reply

* [PATCH RFC v4 net 2/3] ipv6: Avoid redoing fib6_lookup() for RTF_CACHE hit case
From: Martin KaFai Lau @ 2014-10-10 18:48 UTC (permalink / raw)
  To: netdev; +Cc: David Miller, Hannes Frederic Sowa
In-Reply-To: <1412966888-31384-1-git-send-email-kafai@fb.com>

When there is a RTF_CACHE hit, no need to redo fib6_lookup()
with reachable=0.

Cc: David Miller <davem@davemloft.net>
Cc: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: Martin KaFai Lau <kafai@fb.com>
---
 net/ipv6/route.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 797a6e7..5469ecf 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -927,12 +927,12 @@ redo_rt6_select:
 			goto out;
 	}
 
-	if (rt->rt6i_flags & RTF_CACHE)
-		goto out;
-
 	dst_hold(&rt->dst);
 	read_unlock_bh(&table->tb6_lock);
 
+	if (rt->rt6i_flags & RTF_CACHE)
+		goto out2;
+
 	if (!(rt->rt6i_flags & (RTF_NONEXTHOP | RTF_GATEWAY)))
 		nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr);
 	else if (!(rt->dst.flags & DST_HOST))
-- 
1.8.1

^ permalink raw reply related

* [PATCH RFC v4 net 3/3] ipv6: Avoid redo-ing fib6_lookup() with reachable = 0 by saving fn
From: Martin KaFai Lau @ 2014-10-10 18:48 UTC (permalink / raw)
  To: netdev; +Cc: David Miller, Hannes Frederic Sowa
In-Reply-To: <1412966888-31384-1-git-send-email-kafai@fb.com>

This patch saves the fn before doing rt6_backtrack.
Hence, without redo-ing the fib6_lookup(), saved_fn can be used
to redo rt6_select() with RT6_LOOKUP_F_REACHABLE off.

Some minor changes I think make sense to review as a single patch:
* Remove the 'out:' goto label.
* Remove the 'reachable' variable.

After this patch, "failing ip6_ins_rt()" is the only case that
requires a redo of fib6_lookup().

Cc: David Miller <davem@davemloft.net>
Cc: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: Martin KaFai Lau <kafai@fb.com>
---
 net/ipv6/route.c | 30 ++++++++++++++++--------------
 1 file changed, 16 insertions(+), 14 deletions(-)

diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 5469ecf..a8ecb9f 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -900,31 +900,40 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort,
 static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, int oif,
 				      struct flowi6 *fl6, int flags)
 {
-	struct fib6_node *fn;
+	struct fib6_node *fn, *saved_fn;
 	struct rt6_info *rt, *nrt;
 	int strict = 0;
 	int attempts = 3;
 	int err;
-	int reachable = net->ipv6.devconf_all->forwarding ? 0 : RT6_LOOKUP_F_REACHABLE;
 
 	strict |= flags & RT6_LOOKUP_F_IFACE;
+	if (net->ipv6.devconf_all->forwarding == 0)
+		strict |= RT6_LOOKUP_F_REACHABLE;
 
 redo_fib6_lookup_lock:
 	read_lock_bh(&table->tb6_lock);
 
-redo_fib6_lookup:
 	fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
+	saved_fn = fn;
 
 redo_rt6_select:
-	rt = rt6_select(fn, oif, strict | reachable);
+	rt = rt6_select(fn, oif, strict);
 	if (rt->rt6i_nsiblings)
-		rt = rt6_multipath_select(rt, fl6, oif, strict | reachable);
+		rt = rt6_multipath_select(rt, fl6, oif, strict);
 	if (rt == net->ipv6.ip6_null_entry) {
 		fn = fib6_backtrack(fn, &fl6->saddr);
 		if (fn)
 			goto redo_rt6_select;
-		else
-			goto out;
+		else if (strict & RT6_LOOKUP_F_REACHABLE) {
+			/* also consider unreachable route */
+			strict &= ~RT6_LOOKUP_F_REACHABLE;
+			fn = saved_fn;
+			goto redo_rt6_select;
+		} else {
+			dst_hold(&rt->dst);
+			read_unlock_bh(&table->tb6_lock);
+			goto out2;
+		}
 	}
 
 	dst_hold(&rt->dst);
@@ -960,13 +969,6 @@ redo_rt6_select:
 	ip6_rt_put(rt);
 	goto redo_fib6_lookup_lock;
 
-out:
-	if (reachable) {
-		reachable = 0;
-		goto redo_fib6_lookup;
-	}
-	dst_hold(&rt->dst);
-	read_unlock_bh(&table->tb6_lock);
 out2:
 	rt->dst.lastuse = jiffies;
 	rt->dst.__use++;
-- 
1.8.1

^ permalink raw reply related

* [PATCH RFC v4 net 1/3] ipv6: Remove BACKTRACK macro
From: Martin KaFai Lau @ 2014-10-10 18:48 UTC (permalink / raw)
  To: netdev; +Cc: David Miller, Hannes Frederic Sowa
In-Reply-To: <1412966888-31384-1-git-send-email-kafai@fb.com>

It is the prep work to reduce the number of calls to fib6_lookup().

The BACKTRACK macro could be hard-to-read and error-prone due to
its side effects (mainly goto).

This patch is to:
1. Replace BACKTRACK macro with a function (fib6_backtrack) with the following
   return values:
   * If it is backtrack-able, returns next fn for retry.
   * If it reaches the root, returns NULL.
2. The caller needs to decide if a backtrack is needed (by testing
   rt == net->ipv6.ip6_null_entry).
3. Rename the goto labels in ip6_pol_route() to make the next few
   patches easier to read.

Cc: David Miller <davem@davemloft.net>
Cc: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: Martin KaFai Lau <kafai@fb.com>
---
 include/net/ip6_fib.h |  3 +++
 net/ipv6/ip6_fib.c    | 17 ++++++++++++++++
 net/ipv6/route.c      | 55 ++++++++++++++++++++++-----------------------------
 3 files changed, 44 insertions(+), 31 deletions(-)

diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index 8eea35d..1f1d7f8 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -288,6 +288,9 @@ struct fib6_node *fib6_locate(struct fib6_node *root,
 			      const struct in6_addr *daddr, int dst_len,
 			      const struct in6_addr *saddr, int src_len);
 
+struct fib6_node *fib6_backtrack(struct fib6_node *fn,
+				 struct in6_addr *saddr);
+
 void fib6_clean_all(struct net *net, int (*func)(struct rt6_info *, void *arg),
 		    void *arg);
 
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index b2d1838..594d189 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -1139,6 +1139,23 @@ struct fib6_node *fib6_locate(struct fib6_node *root,
 	return NULL;
 }
 
+struct fib6_node* fib6_backtrack(struct fib6_node *fn,
+				 struct in6_addr *saddr)
+{
+	struct fib6_node *pn;
+	while (1) {
+		if (fn->fn_flags & RTN_TL_ROOT)
+			return NULL;
+		pn = fn->parent;
+		if (FIB6_SUBTREE(pn) && FIB6_SUBTREE(pn) != fn)
+			fn = fib6_lookup(FIB6_SUBTREE(pn), NULL, saddr);
+		else
+			fn = pn;
+		if (fn->fn_flags & RTN_RTINFO)
+			return fn;
+	}
+}
+
 
 /*
  *	Deletion
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index a318dd89..797a6e7 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -772,24 +772,6 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
 }
 #endif
 
-#define BACKTRACK(__net, saddr)			\
-do { \
-	if (rt == __net->ipv6.ip6_null_entry) {	\
-		struct fib6_node *pn; \
-		while (1) { \
-			if (fn->fn_flags & RTN_TL_ROOT) \
-				goto out; \
-			pn = fn->parent; \
-			if (FIB6_SUBTREE(pn) && FIB6_SUBTREE(pn) != fn) \
-				fn = fib6_lookup(FIB6_SUBTREE(pn), NULL, saddr); \
-			else \
-				fn = pn; \
-			if (fn->fn_flags & RTN_RTINFO) \
-				goto restart; \
-		} \
-	} \
-} while (0)
-
 static struct rt6_info *ip6_pol_route_lookup(struct net *net,
 					     struct fib6_table *table,
 					     struct flowi6 *fl6, int flags)
@@ -804,8 +786,11 @@ restart:
 	rt = rt6_device_match(net, rt, &fl6->saddr, fl6->flowi6_oif, flags);
 	if (rt->rt6i_nsiblings && fl6->flowi6_oif == 0)
 		rt = rt6_multipath_select(rt, fl6, fl6->flowi6_oif, flags);
-	BACKTRACK(net, &fl6->saddr);
-out:
+	if (rt == net->ipv6.ip6_null_entry) {
+		fn = fib6_backtrack(fn, &fl6->saddr);
+		if (fn)
+			goto restart;
+	}
 	dst_use(&rt->dst, jiffies);
 	read_unlock_bh(&table->tb6_lock);
 	return rt;
@@ -924,19 +909,25 @@ static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
 
 	strict |= flags & RT6_LOOKUP_F_IFACE;
 
-relookup:
+redo_fib6_lookup_lock:
 	read_lock_bh(&table->tb6_lock);
 
-restart_2:
+redo_fib6_lookup:
 	fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
 
-restart:
+redo_rt6_select:
 	rt = rt6_select(fn, oif, strict | reachable);
 	if (rt->rt6i_nsiblings)
 		rt = rt6_multipath_select(rt, fl6, oif, strict | reachable);
-	BACKTRACK(net, &fl6->saddr);
-	if (rt == net->ipv6.ip6_null_entry ||
-	    rt->rt6i_flags & RTF_CACHE)
+	if (rt == net->ipv6.ip6_null_entry) {
+		fn = fib6_backtrack(fn, &fl6->saddr);
+		if (fn)
+			goto redo_rt6_select;
+		else
+			goto out;
+	}
+
+	if (rt->rt6i_flags & RTF_CACHE)
 		goto out;
 
 	dst_hold(&rt->dst);
@@ -967,12 +958,12 @@ restart:
 	 * released someone could insert this route.  Relookup.
 	 */
 	ip6_rt_put(rt);
-	goto relookup;
+	goto redo_fib6_lookup_lock;
 
 out:
 	if (reachable) {
 		reachable = 0;
-		goto restart_2;
+		goto redo_fib6_lookup;
 	}
 	dst_hold(&rt->dst);
 	read_unlock_bh(&table->tb6_lock);
@@ -1235,10 +1226,12 @@ restart:
 		rt = net->ipv6.ip6_null_entry;
 	else if (rt->dst.error) {
 		rt = net->ipv6.ip6_null_entry;
-		goto out;
+	} else if (rt == net->ipv6.ip6_null_entry) {
+		fn = fib6_backtrack(fn, &fl6->saddr);
+		if (fn)
+			goto restart;
 	}
-	BACKTRACK(net, &fl6->saddr);
-out:
+
 	dst_hold(&rt->dst);
 
 	read_unlock_bh(&table->tb6_lock);
-- 
1.8.1

^ permalink raw reply related

* Re: [PATCH net] stmmac: correct mc_filter local variable in set_filter and set_mac_addr call
From: David Miller @ 2014-10-10 18:48 UTC (permalink / raw)
  To: vbridger; +Cc: peppe.cavallaro, netdev, linux-kernel, vbridger
In-Reply-To: <1412867436-22153-1-git-send-email-vbridger@opensource.altera.com>

From: Vince Bridgers <vbridger@opensource.altera.com>
Date: Thu, 9 Oct 2014 10:10:36 -0500

> Testing revealed that the local variable mc_filter was dimensioned
> incorrectly for all possible configurations and get_mac_addr should
> have been set_mac_addr (a typo). Make sure mc_filter is dimensioned
> to 8 32-bit unsigned longs - the largest size of the Synopsys
> multicast filter register set.
> 
> Signed-off-by: Vince Bridgers <vbridger@opensource.altera.com>

Applied, thanks vince.

^ permalink raw reply

* Re: pull request: wireless-next 2014-10-09
From: David Miller @ 2014-10-10 18:50 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, netdev, linux-kernel
In-Reply-To: <20141009154402.GB13986@tuxdriver.com>

From: "John W. Linville" <linville@tuxdriver.com>
Date: Thu, 9 Oct 2014 11:44:02 -0400

> Please pull this batch of fixes intended for the 3.18 stream!
> 
> Andrea Merello makes rtl818x_pci use a more reasonable transmission
> rate for HW generated frames.
> 
> Fabian Frederick tweaks some kernel-doc bits to avoid warnings.
> 
> Larry Finger corrects a possible unaligned access in the rtlwifi code.
> 
> Marek Puzyniak avoids a kernel panic in ath9k_hw_reset.
> 
> Sujith Manoharan goes for the hat trick -- he fixes a smatch warning
> in the shared ath code, he fixes a crash in ath9k, and he corrects
> a sequence number assignment problem in ath9k too.
> 
> For ease of merging, I pulled the last bits of the wireless tree as well...
> 
> Please let me know if there are problems!

Pulled, thank you John.

^ permalink raw reply

* Re: [PATCH] flow-dissector: Fix alignment issue in __skb_flow_get_ports
From: Alexander Duyck @ 2014-10-10 18:53 UTC (permalink / raw)
  To: David Miller, alexander.duyck; +Cc: eric.dumazet, David.Laight, netdev
In-Reply-To: <20141010.142255.359367991309840826.davem@davemloft.net>

On 10/10/2014 11:22 AM, David Miller wrote:
> From: David Miller <davem@davemloft.net>
> Date: Fri, 10 Oct 2014 14:15:59 -0400 (EDT)
>
>> Your original code works because you do things like "byte[12] & 0xf0" to
>> extract these fields.
> Changing that th->doff sequence to instead be:
>
> 		const u8 *bp;
> 		u8 buf[13];
>
> 		bp = __skb_header_pointer(skb, poff, sizeof(buf),
> 					  data, hlen, &buf);
> 		if (!bp)
> 			return poff;
>
> 		poff += max_t(u32, sizeof(struct tcphdr), (bp[12] & 0xf0) >> 2);
> 		break;
>
> on top of your v3 patch works for me.
>
> Please double-check my calculations.

Any reason why you are grabbing all 13 bytes instead of just the 1 we 
care about?  Seems like we could just use a u8 buf instead of the array 
since we are only grabbing doff.

Thanks,

Alex

^ permalink raw reply

* Re: [PATCH net-next] net: bcmgenet: enable driver to work without a device tree
From: Florian Fainelli @ 2014-10-10 18:59 UTC (permalink / raw)
  To: Petri Gynther, netdev; +Cc: davem
In-Reply-To: <20141010183501.0189F1008A3@puck.mtv.corp.google.com>

On 10/10/2014 11:35 AM, Petri Gynther wrote:
> Broadcom 7xxx MIPS-based STB platforms do not use device trees.
> Modify bcmgenet driver so that it can be used on those platforms.
> 
> Signed-off-by: Petri Gynther <pgynther@google.com>
> ---

[snip]

> diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
> index dbf524e..5191e3f 100644
> --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h
> +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
> @@ -17,6 +17,17 @@
>  #include <linux/if_vlan.h>
>  #include <linux/phy.h>
>  
> +struct bcmgenet_platform_data {
> +	void __iomem	*base_reg;
> +	int		irq0;
> +	int		irq1;

Why would these members here? The platform device should provide those
as standard resources that the driver fetches using
platform_get_resource() and platform_get_irq().

> +	int		phy_type;
> +	int		phy_addr;
> +	int		phy_speed;
> +	u8		macaddr[ETH_ALEN];
> +	int		genet_version;
> +};

I would rather we put this in include/linux/platform_data/bcmgenet.h
where it belongs.

> +
>  /* total number of Buffer Descriptors, same for Rx/Tx */
>  #define TOTAL_DESC				256
>  
> diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c
> index 9ff799a..e5ff913 100644
> --- a/drivers/net/ethernet/broadcom/genet/bcmmii.c
> +++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c
> @@ -157,6 +157,21 @@ static void bcmgenet_mii_setup(struct net_device *dev)
>  	phy_print_status(phydev);
>  }
>  
> +static int bcmgenet_moca_fphy_update(struct net_device *dev,
> +				     struct fixed_phy_status *status)
> +{
> +	struct bcmgenet_priv *priv = netdev_priv(dev);
> +	struct phy_device *phydev = priv->phydev;
> +
> +	/*
> +	 * MoCA daemon updates phydev->autoneg to reflect the link status.
> +	 * Update MoCA fixed PHY status accordingly, so that the PHY state
> +	 * machine becomes aware of the real link status.
> +	 */
> +	status->link = phydev->autoneg;
> +	return 0;
> +}

I don't want to see that in the upstream driver, please enable the link
interrupts like I suggested before and do not use the autoneg field at
all, which should require no MoCA daemon modifications.

[snip]

>  
>  	priv->phydev = phydev;
> @@ -437,6 +464,104 @@ static int bcmgenet_mii_of_init(struct bcmgenet_priv *priv)
>  	return 0;
>  }
>  
> +static int bcmgenet_mii_pd_init(struct bcmgenet_priv *priv)
> +{
> +	struct device *kdev = &priv->pdev->dev;
> +	struct bcmgenet_platform_data *pd = kdev->platform_data;
> +	struct mii_bus *mdio = priv->mii_bus;
> +	int phy_addr = pd->phy_addr;
> +	struct phy_device *phydev;
> +	int ret;
> +	int i;
> +
> +	/* Disable automatic MDIO bus scan */
> +	mdio->phy_mask = ~0;
> +
> +	/* Clear all the IRQ properties */
> +	if (mdio->irq)
> +		for (i = 0; i < PHY_MAX_ADDR; i++)
> +			mdio->irq[i] = PHY_POLL;
> +
> +	/* Register the MDIO bus */
> +	ret = mdiobus_register(mdio);
> +	if (ret) {
> +		dev_err(kdev, "failed to register MDIO bus\n");
> +		return ret;
> +	}
> +
> +	/*
> +	 * bcmgenet_platform_data needs to pass a valid PHY address for
> +	 * internal/external PHY or -1 for MoCA PHY.
> +	 */
> +	if (phy_addr >= 0 && phy_addr < PHY_MAX_ADDR) {

We do too much low-level PHY device handling, and since you already have
the phy_type provided via platform_data, we can use that hint to do the
following:

1) an internal or external PHY with MDIO accesses should leave the bus
auto-probing on with the specified PHY address in the mdio bus phy_mask

2) a MoCA PHY or an external PHY with MDIO accesses disabled should use
the fixed-0 MII bus instead.

This would look like this:

if (pd->phy_type != PHY_INTERFACE_MODE_MOCA || pd->mdio_enabled)
	mdio->phy_mask = ~(1 << pd->phy_addr);

	...
	mdiobus_register()

	priv->phydev = mdio->bus->phy_map[pd->phy_addr];

	phydev->phy_flags |= mask;

if (pd->phy_type == PHY_INTERFACE_MODE_MOCA || !pd->mdio_enabled)
	priv->phydev = fixed_phy_register(...);

and in both cases, later on you do connect to the PHY device

I can cook a patch to illustrate what I think this could look like since
I realize using pseudo-code to explain might not be the best thing.

> +		/*
> +		 * 10/100/1000 Ethernet port with external or internal PHY.
> +		 */
> +		phydev = get_phy_device(mdio, phy_addr, false);
> +		if (!phydev || IS_ERR(phydev)) {
> +			dev_err(kdev, "failed to create PHY device\n");
> +			mdiobus_unregister(mdio);
> +			return 1;
> +		}
> +
> +		phydev->irq = PHY_POLL;
> +
> +		ret = phy_device_register(phydev);
> +		if (ret) {
> +			dev_err(kdev, "failed to register PHY device\n");
> +			phy_device_free(phydev);
> +			mdiobus_unregister(mdio);
> +			return 1;
> +		}
> +
> +		priv->phydev = phydev;
> +		priv->phy_interface = pd->phy_type;
> +	} else {
> +		/*
> +		 * MoCA port with no MDIO-accessible PHY.
> +		 * We need to use 1000/HD fixed PHY to represent the link layer.
> +		 * MoCA daemon interacts with this PHY via ethtool.
> +		 */
> +		struct fixed_phy_status moca_fphy_status = {
> +			.link = 0,
> +			.duplex = 0,

This should be DUPLEX_FULL here, the link between GENET and the MoCA
Ethernet convergence layer is full-duplex by nature (despite we report
the PHY being half-duplex, which is a mistake in the downstream driver),
the MoCA medium on the coaxial cable is half-duplex though, but that is
handled by the MoCA HW.

NB: I had issues in the past using a half-duplex link with the MoCA
ethernet convergence layer, causing various types of packet loss because
we use a simplified signaling internally in the hardware.

> +			.speed = 1000,
> +			.pause = 0,
> +			.asym_pause = 0,
> +		};
> +
> +		phydev = fixed_phy_register(PHY_POLL, &moca_fphy_status, NULL);
> +		if (!phydev || IS_ERR(phydev)) {
> +			dev_err(kdev, "failed to register fixed PHY device\n");
> +			mdiobus_unregister(mdio);
> +			return 1;
> +		}
> +
> +		phydev->autoneg = AUTONEG_DISABLE;
> +
> +		ret = fixed_phy_set_link_update(phydev,
> +						bcmgenet_moca_fphy_update);
> +		if (ret) {
> +			dev_err(kdev, "failed to set fixed PHY link update\n");
> +		}

Should not we propagate this error to the caller?
--
Florian

^ permalink raw reply

* Re: [PATCH 0/2] Netfilter fixes for net-next
From: David Miller @ 2014-10-10 19:01 UTC (permalink / raw)
  To: pablo; +Cc: netfilter-devel, netdev
In-Reply-To: <1412879261-25045-1-git-send-email-pablo@netfilter.org>

From: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Thu,  9 Oct 2014 20:27:39 +0200

> This batch contains two fixes for what you have in your net-next,
> they are:
> 
> 1) Remove nf_send_reset6() from header file. This function now resides
>    in the nf_reject_ipv6 module. Reported by Eric Dumazet.
> 
> 2) Fix wrong NFT_REJECT_ICMPX_MAX definition and adjust code to fix
>    errors reported by Dan Carpenter's static analysis tools.
> 
> You can pull these changes from:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git

Pulled, thanks Pablo.

^ permalink raw reply

* Re: [PATCH net] net: bpf: fix bpf syscall dependence on anon_inodes
From: David Miller @ 2014-10-10 19:03 UTC (permalink / raw)
  To: ast; +Cc: sojkam1, netdev, linux-kernel
In-Reply-To: <1412893001-8401-1-git-send-email-ast@plumgrid.com>

From: Alexei Starovoitov <ast@plumgrid.com>
Date: Thu,  9 Oct 2014 15:16:41 -0700

> minimal configurations where EPOLL, PERF_EVENTS, etc are disabled,
> but NET is enabled, are failing to build with link error:
> kernel/built-in.o: In function `bpf_prog_load':
> syscall.c:(.text+0x3b728): undefined reference to `anon_inode_getfd'
> 
> fix it by selecting ANON_INODES when NET is enabled
> 
> Reported-by: Michal Sojka <sojkam1@fel.cvut.cz>
> Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
> ---
> 
> I understand that 'select' is highly non-recommended for all good reasons,
> but here 'depends on' is very user unfriendly, since ANON_INODES is
> a hidden config that users cannot select directly.

Applied, thanks.

^ permalink raw reply


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