Re: [PATCH RFC 19/28] net: dsa: bcm_sf2: make it a real platform driver

2015-12-23 Thread Florian Fainelli
Hi Andrew,

Le 23/12/2015 04:56, Andrew Lunn a écrit :
> diff --git a/Documentation/devicetree/bindings/net/dsa/broadcom.txt 
> b/Documentation/devicetree/bindings/net/dsa/broadcom.txt
> new file mode 100644
> index ..bd92be0ef2c8
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/dsa/broadcom.txt
> @@ -0,0 +1,48 @@
> +* Broadcom Starfighter 2 integrated switch device
> +
> +Required properties:
> +
> +- compatible: should be "brcm,brcm-sf2"
> +- reg: addresses and length of the register sets for the device, must be 6
> +  pairs of register addresses and lengths
> +- interrupts: interrupts for the devices, must be two interrupts
> +
> +Optional properties:
> +
> +- reg-names: litteral names for the device base register addresses,
> +  when present must be: "core", "reg", "intrl2_0", "intrl2_1", "fcb",
> +  "acb"

These are in fact mandatory properties.

> +
> +- interrupt-names: litternal names for the device interrupt lines,
> +  when present must be: "switch_0" and "switch_1"

Likewise

> +
> +- brcm,num-gphy: specify the maximum number of integrated gigabit PHYs
> +  in the switch

Likewise

> +
> +- brcm,num-rgmii-ports: specify the maximum number of RGMII interfaces
> +  supported by the switch
> +
> +- brcm,fcb-pause-override: boolean property, if present indicates that
> +  the switch supports Failover Control Block pause override capability
> +
> +- brcm,acb-packets-inflight: boolean property, if present indicates
> +  that the switch Admission Control Block supports reporting the
> +  number of packets in-flight in a switch queue

All of these above are indeed optional.

Having to introduce a new binding for this driver to be converted is a
major deal breaker, the platforms I use have a frozen, yet wrongly
specified Device Tree binding, but still, we need to keep backward
compatibility with it.

My initial attempt, if you remove the part where I tried to convert
every switch driver into a PHY device handled that:

https://github.com/ffainelli/linux/commit/287fc1b33cdd6155c507a95531fd820a5c6dbaf4

Since we have dsa_of_probe(), that alone should be enough to allow us to
maintain a dsa_platform_data structure along with the old binding. This
is not a whole lot different from your patch 13.

Thanks!
-- 
Florian
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH RFC 21/28] net: dsa: Add some debug prints for error cases

2015-12-23 Thread Florian Fainelli
Le 23/12/2015 04:56, Andrew Lunn a écrit :
> Due to the complexity it can be hard to know why DSA fails to probe.
> Add some debug prints for the common error cases.
> 
> Signed-off-by: Andrew Lunn <and...@lunn.ch>

Acked-by: Florian Fainelli <f.faine...@gmail.com>

I had something similar here since, thanks!
-- 
Florian
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH RFC 12/28] net: dsa: Make dsa,mii-bus optional

2015-12-23 Thread Florian Fainelli
Le 23/12/2015 04:56, Andrew Lunn a écrit :
> When all the switches are devices and register to the DSA framework,
> having a dsa,mii-bus property is not required.
> 
> Signed-off-by: Andrew Lunn <and...@lunn.ch>

Acked-by: Florian Fainelli <f.faine...@gmail.com>
-- 
Florian
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH RFC 06/28] net: dsa: Have the switch driver allocate there own private memory

2015-12-23 Thread Florian Fainelli
Le 23/12/2015 04:56, Andrew Lunn a écrit :
> Now the switch devices have a dev pointer, make use if it for allocating
> the drivers private data structures using a devm_kzalloc().
> 
> Signed-off-by: Andrew Lunn <and...@lunn.ch>
> ---
>  drivers/net/dsa/bcm_sf2.c   |  7 +--
>  drivers/net/dsa/mv88e6123.c |  6 +++---
>  drivers/net/dsa/mv88e6131.c |  6 +++---
>  drivers/net/dsa/mv88e6171.c |  6 +++---
>  drivers/net/dsa/mv88e6352.c |  6 +++---
>  drivers/net/dsa/mv88e6xxx.c | 13 ++---
>  drivers/net/dsa/mv88e6xxx.h |  5 -
>  include/net/dsa.h   |  8 +++-
>  8 files changed, 38 insertions(+), 19 deletions(-)
> 
> diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
> index 6925b3c13895..23326c2a01b8 100644
> --- a/drivers/net/dsa/bcm_sf2.c
> +++ b/drivers/net/dsa/bcm_sf2.c
> @@ -929,7 +929,7 @@ static void bcm_sf2_identify_ports(struct bcm_sf2_priv 
> *priv,
>  static int bcm_sf2_sw_setup(struct dsa_switch *ds, struct device *dev)
>  {
>   const char *reg_names[BCM_SF2_REGS_NUM] = BCM_SF2_REGS_NAME;
> - struct bcm_sf2_priv *priv = ds_to_priv(ds);
> + struct bcm_sf2_priv *priv;
>   struct device_node *dn;
>   void __iomem **base;
>   unsigned int port;
> @@ -937,6 +937,10 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds, 
> struct device *dev)
>   u32 reg, rev;
>   int ret;
>  
> + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;

This looks fine overall, except that part, there is an earlier priv =
ds_to_priv() in the function so we might be missing a ds->priv = priv
here once the allocation is successful.

With that fixed: Acked-by: Florian Fainelli <f.faine...@gmail.com>
-- 
Florian
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH RFC 07/28] net: dsa: Remove allocation of driver private memory

2015-12-23 Thread Florian Fainelli
Le 23/12/2015 04:56, Andrew Lunn a écrit :
> The drivers now allocate their own memory for private usage. Remove
> the allocation from the core code.
> 
> Signed-off-by: Andrew Lunn <and...@lunn.ch>

Acked-by: Florian Fainelli <f.faine...@gmail.com>
-- 
Florian
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH RFC 08/28] net: dsa: Keep the mii bus and address in the private structure

2015-12-23 Thread Florian Fainelli
Le 23/12/2015 04:56, Andrew Lunn a écrit :
> Rather than looking up the mii bus and address every time, do it once
> and setup, and keep it in the private structure.
> 
> Signed-off-by: Andrew Lunn <and...@lunn.ch>

Acked-by: Florian Fainelli <f.faine...@gmail.com>
-- 
Florian
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH RFC 25/28] Documentation: DSA: Describe how probe of DSA and switches work.

2015-12-23 Thread Florian Fainelli
Le 23/12/2015 04:56, Andrew Lunn a écrit :
> With the introduction of switches as linux devices and the use of the
> component framework, probing has become more complex. Add some
> documentation.
> 
> Signed-off-by: Andrew Lunn 
> ---
>  Documentation/networking/dsa/dsa.txt | 48 
> 
>  1 file changed, 48 insertions(+)
> 
> diff --git a/Documentation/networking/dsa/dsa.txt 
> b/Documentation/networking/dsa/dsa.txt
> index aa9c1f9313cd..376afa135a81 100644
> --- a/Documentation/networking/dsa/dsa.txt
> +++ b/Documentation/networking/dsa/dsa.txt
> @@ -398,6 +398,54 @@ Switch configuration
>on the management interface and "hardcode"/"force" this MAC address for the
>CPU/management interface as an optimization
>  
> +Call flow
> +-
> +
> +With the ability for switch devices to be true linux devices, the call
> +flow is somewhat complex. The component framework is used to link the
> +dsa framework as the master, with switch devices, as slaves.
> +
> +A switch device should add itself as a component in its probe
> +function.
> +
> +The DSA framework can either be configured using a platform_data
> +structure or from the device tree. If device tree is being used, the
> +dsa framework probe function will allocate a platform_data structure,
> +and populate it using the device tree, via the dsa_of_probe()
> +function.  Within the DSA device tree, switch devices are represented
> +by a phandle to the switch device. These phandles are saved into the
> +platform data so that when switch slaves register themselves, they can
> +be correctly positioned in the DSA cluster.

Humm, I guess I am still not clear on that, in a DT-only system, do I
still need to get the DSA platform device to be probed via DT, along
with references to the switches I want? If that is the case, that seems
a little awkward, could not we probe the individual switches, and see if
they need DSA instead? Or is that how the component framework works,
just being a bit confused here.

Thanks!
-- 
Florian
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH RFC 24/28] net: dsa: If a switch fails to probe, defer probing

2015-12-23 Thread Florian Fainelli
Le 23/12/2015 04:56, Andrew Lunn a écrit :
> Switches are either listed in device tree of platform_data. They
> should exist. If the probe fails, defer the probe, which is the likely
> cause of failure, not broken device tree or platform data.
> 
> Signed-off-by: Andrew Lunn <and...@lunn.ch>

Acked-by: Florian Fainelli <f.faine...@gmail.com>
-- 
Florian
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH net-next] net: phy: bcm7xxx: Add entry for Broadcom BCM7435

2015-11-24 Thread Florian Fainelli
Add a PHY entry for the Broadcom BCM7435 chips, this is a 40nm
generation Ethernet PHY which is analogous to its 7425 and 7429 counter
parts.

Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 drivers/net/phy/bcm7xxx.c | 14 ++
 include/linux/brcmphy.h   |  1 +
 2 files changed, 15 insertions(+)

diff --git a/drivers/net/phy/bcm7xxx.c b/drivers/net/phy/bcm7xxx.c
index 03d4809a9126..d4083c381cd1 100644
--- a/drivers/net/phy/bcm7xxx.c
+++ b/drivers/net/phy/bcm7xxx.c
@@ -361,6 +361,19 @@ static struct phy_driver bcm7xxx_driver[] = {
.resume = bcm7xxx_config_init,
.driver = { .owner = THIS_MODULE },
 }, {
+   .phy_id = PHY_ID_BCM7435,
+   .phy_id_mask= 0xfff0,
+   .name   = "Broadcom BCM7435",
+   .features   = PHY_GBIT_FEATURES |
+ SUPPORTED_Pause | SUPPORTED_Asym_Pause,
+   .flags  = PHY_IS_INTERNAL,
+   .config_init= bcm7xxx_config_init,
+   .config_aneg= genphy_config_aneg,
+   .read_status= genphy_read_status,
+   .suspend= bcm7xxx_suspend,
+   .resume = bcm7xxx_config_init,
+   .driver = { .owner = THIS_MODULE },
+}, {
.phy_id = PHY_BCM_OUI_4,
.phy_id_mask= 0x,
.name   = "Broadcom BCM7XXX 40nm",
@@ -395,6 +408,7 @@ static struct mdio_device_id __maybe_unused bcm7xxx_tbl[] = 
{
{ PHY_ID_BCM7425, 0xfff0, },
{ PHY_ID_BCM7429, 0xfff0, },
{ PHY_ID_BCM7439, 0xfff0, },
+   { PHY_ID_BCM7435, 0xfff0, },
{ PHY_ID_BCM7445, 0xfff0, },
{ PHY_BCM_OUI_4, 0x },
{ PHY_BCM_OUI_5, 0xff00 },
diff --git a/include/linux/brcmphy.h b/include/linux/brcmphy.h
index 59f4a7304419..f0ba9c2ec639 100644
--- a/include/linux/brcmphy.h
+++ b/include/linux/brcmphy.h
@@ -26,6 +26,7 @@
 #define PHY_ID_BCM7366 0x600d8490
 #define PHY_ID_BCM7425 0x600d86b0
 #define PHY_ID_BCM7429 0x600d8730
+#define PHY_ID_BCM7435 0x600d8750
 #define PHY_ID_BCM7439 0x600d8480
 #define PHY_ID_BCM7439_2   0xae025080
 #define PHY_ID_BCM7445 0x600d8510
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH net-next] MAINTAINERS: PHY: Change maintainer to reviewer

2015-11-24 Thread Florian Fainelli
Now that there is a reviewer role, add myself as reviewer since the PHY
library code is maintained via the networking tree.

Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 MAINTAINERS | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index ea1751283b49..950c321eef73 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4195,7 +4195,7 @@ F:include/linux/netfilter_bridge/
 F: net/bridge/
 
 ETHERNET PHY LIBRARY
-M: Florian Fainelli <f.faine...@gmail.com>
+R: Florian Fainelli <f.faine...@gmail.com>
 L: netdev@vger.kernel.org
 S: Maintained
 F: include/linux/phy.h
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: bridge-utils: wrong sysfs path odds

2015-11-25 Thread Florian Fainelli
On 25/11/15 01:21, Richard Weinberger wrote:
> Am 25.11.2015 um 01:37 schrieb Stephen Hemminger:
>> On Wed, 25 Nov 2015 01:24:47 +0100
>> Richard Weinberger  wrote:
>>
>>> Am 25.11.2015 um 01:15 schrieb Richard Weinberger:
 Hi!

 Today I was hunting down an issue where "brctl stp br0 off"
 always failed on mips64be with n32 userland.

 It turned out that the ioctl(fd, SIOCDEVPRIVATE, ) with 
 BRCTL_SET_BRIDGE_STP_STATE
 returned -EOPNOTSUPP.
 First I thought that this is a plain ABI issue on mips as in 
 old_dev_ioctl()
 the ioctl() argument was 0x1 instead of the expected 
 BRCTL_SET_BRIDGE_STP_STATE (0x14)
>>>
>>> Should be 0xe and not 0x14. It is 14 in decimal. :)
>>>
>>> Thanks,
>>> //richard
>>
>> Ask Debian maintainer to send his patches, I don't go patch hunting.
>>
> 
> While looking what other distros do I came across this patch:
> https://pkgs.fedoraproject.org/cgit/bridge-utils.git/tree/bridge-utils-1.5-check-error-returns-from-write-to-sysfs.patch
> 
> Beside of checking return errors is fixes also the sysfs path in br_set().
> Can you please merge it upstream?
> 
> Distros seems to carry more patches for that package, if it helps I can do 
> the patch hunting for you.
> It would be nice to have a recent bridge-utils release. The last one is from 
> 2011.

Most of what bridge-utils does can be done by iproute2's bridge
sub-command FWIW.
-- 
Florian
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH net-next] MAINTAINERS: PHY: Change maintainer to reviewer

2015-11-25 Thread Florian Fainelli
On 25/11/15 08:36, David Miller wrote:
> From: Joe Perches <j...@perches.com>
> Date: Tue, 24 Nov 2015 17:04:11 -0800
> 
>> On Tue, 2015-11-24 at 15:29 -0800, Florian Fainelli wrote:
>>> Now that there is a reviewer role, add myself as reviewer since the PHY
>>> library code is maintained via the networking tree.
>>
>> []
>>
>>> diff --git a/MAINTAINERS b/MAINTAINERS
>> []
>>> @@ -4195,7 +4195,7 @@ F:include/linux/netfilter_bridge/
>>>  F:>> net/bridge/
>>>  
>>>  ETHERNET PHY LIBRARY
>>> -M: Florian Fainelli <f.faine...@gmail.com>
>>> +R: Florian Fainelli <f.faine...@gmail.com>
>>>  L: netdev@vger.kernel.org
>>>  S: Maintained
>>>  F: include/linux/phy.h
>>
>> Just because the upstream path is not a tree you
>> manage doesn't mean you aren't a maintainer.
>>
>> I think the status should be something other than
>> "Maintained" if you are not the maintainer.
> 
> Yeah, I kinda agree, Florian you are pretty much the de-facto
> maintainer and I usually wait for you to review any PHY library
> changes before applying them unless they are _really_ obvious.

Sounds good, let's drop this patch then, thanks!
-- 
Florian
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 00/13] mvneta Buffer Management and enhancements

2015-11-25 Thread Florian Fainelli
On 21/11/15 23:53, Marcin Wojtas wrote:
> 
> 4. Buffer manager (BM) support with two preparatory commits. As it is a
> separate block, common for all network ports, a new driver is introduced,
> which configures it and exposes API to the main network driver. It is
> throughly described in binding documentation and commit log. Please note,
> that enabling per-port BM usage is done using phandle and the data passed
> in mvneta_bm_probe. It is designed for usage of on-demand device probe
> and dev_set/get_drvdata, however it's awaiting merge to linux-next.
> Therefore, deferring probe is not used - if something goes wrong (same
> in case of errors during changing MTU or suspend/resume cycle) mvneta
> driver falls back to software buffer management and works in a regular way.

Looking at your patches, it was not entirely clear to me how the buffer
manager on these Marvell SoCs work, but other networking products have
something similar, like Broadcom's Cable Modem SoCs (BCM33xx) FPM, and
maybe Freescale's FMAN/DPAA seems to do something similar.

Does the buffer manager allocation work by giving you a reference/token
to a buffer as opposed to its address? If that is the case, it would be
good to design support for such hardware in a way that it can be used by
more drivers.

Eric Dumazet suggested a while ago to me that you could get abstract
such allocation using hardware-assisted buffer allocation by either
introducing a new mm zone (instead of ZONE_NORMAL/DMA/HIGHMEM etc.), or
using a different NUMA node id, such that SKB allocation and freeing
helpers could deal with the specifics, and your networking stack and
driver would be mostly unaware of the buffer manager underlying
implementation. The purpose would be to get a 'struct page' reference to
your buffer pool allocation object, so it becomes mostly transparent to
other areas of the kernel, and you could further specialize everything
that needs to be based on this node id or zone.

Finally, these hardware-assisted allocation schemes typically work very
well when there is a forwarding/routing workload involved, because you
can easily steal packets and SKBs from the network stack, but that does
not necessarily play nicely with host-terminated/initiated traffic which
wants to have good feedback on what's happening at the NIC level
(queueing, buffering, etc.).

> 
> Known issues:
> - problems with obtaining all mapped buffers from internal SRAM, when
> destroying the buffer pointer pool
> - problems with unmapping chunk of SRAM during driver removal
> Above do not have an impact on the operation, as they are called during
> driver removal or in error path.

Humm, what is the reason for using the on-chip SRAM here, is it because
that's the only storage location the Buffer Manager can allocate from,
or is it because it is presumably faster or with constant access times
than DRAM? Would be nice to explain a bit more in details how the buffer
manager works and its interfacing with the network controllers.

Can I use the buffer manager with other peripherals as well? Like if I
wanted to do zero-copy or hardware-assisted memcpy DMA, would that be a
suitable scheme?

Thanks!
-- 
Florian
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC 2/8] net-next: phy: dont auto handle carrier state when multiple phys are attached

2015-11-24 Thread Florian Fainelli
On 22/11/15 00:40, John Crispin wrote:
> A network core might have more than one phy attached to its cpu port via a
> switch. The current code will set the carrier state to on/off when ever a
> cable is plugged into any of these ports.

Not really, no. The current PHY library implementation does not allow
more than one net_device instance to be bound to multiple PHY devices.
Since this is an integrated switch, you should really expose per-port
network devices, that is the paradigm we settled down on using for
Ethernet switches now (irrespective of using DSA or switchdev, or both).

> 
> The patch adds a new bool that allows the driver to tell the phy_device to not
> set the carrier state. Instead the driver can manually handle the carrier
> state.

I am missing the bigger picture of how this is used, also, if link down
is a problem, would not link up be for the same reasons?

> 
> Signed-off-by: John Crispin <blo...@openwrt.org>
> Signed-off-by: Felix Fietkau <n...@openwrt.org>
> Signed-off-by: Michael Lee <igv...@gmail.com>
> Cc: Florian Fainelli <f.faine...@gmail.com>
> ---
>  drivers/net/phy/phy.c |9 ++---
>  include/linux/phy.h   |1 +
>  2 files changed, 7 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
> index 48ce6ef..bd2df40 100644
> --- a/drivers/net/phy/phy.c
> +++ b/drivers/net/phy/phy.c
> @@ -843,7 +843,8 @@ void phy_state_machine(struct work_struct *work)
>   /* If the link is down, give up on negotiation for now */
>   if (!phydev->link) {
>   phydev->state = PHY_NOLINK;
> - netif_carrier_off(phydev->attached_dev);
> + if (!phydev->no_auto_carrier_off)
> + netif_carrier_off(phydev->attached_dev);
>   phydev->adjust_link(phydev->attached_dev);
>   break;
>   }
> @@ -926,7 +927,8 @@ void phy_state_machine(struct work_struct *work)
>   netif_carrier_on(phydev->attached_dev);
>   } else {
>   phydev->state = PHY_NOLINK;
> - netif_carrier_off(phydev->attached_dev);
> + if (!phydev->no_auto_carrier_off)
> + netif_carrier_off(phydev->attached_dev);
>   }
>  
>   phydev->adjust_link(phydev->attached_dev);
> @@ -938,7 +940,8 @@ void phy_state_machine(struct work_struct *work)
>   case PHY_HALTED:
>   if (phydev->link) {
>   phydev->link = 0;
> - netif_carrier_off(phydev->attached_dev);
> + if (!phydev->no_auto_carrier_off)
> + netif_carrier_off(phydev->attached_dev);
>   phydev->adjust_link(phydev->attached_dev);
>   do_suspend = true;
>   }
> diff --git a/include/linux/phy.h b/include/linux/phy.h
> index 05fde31..276ab8a 100644
> --- a/include/linux/phy.h
> +++ b/include/linux/phy.h
> @@ -377,6 +377,7 @@ struct phy_device {
>   bool is_pseudo_fixed_link;
>   bool has_fixups;
>   bool suspended;
> + bool no_auto_carrier_off;
>  
>   enum phy_state state;
>  
> 


-- 
Florian
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH net-next 2/2] dsa: mv88e6xxx.c: Hardware reset the chip if available

2015-11-18 Thread Florian Fainelli
On 18/11/15 15:29, Andrew Lunn wrote:
> The device tree binding now allows a gpio to be specified which is
> attached to the switch chips reset line. If it is defined, perform
> a hardware reset on the switch during setup.
> 
> Signed-off-by: Andrew Lunn 
> ---
>  drivers/net/dsa/mv88e6xxx.c | 14 ++
>  1 file changed, 14 insertions(+)
> 
> diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
> index b06dba05594a..c0bbbe7713c5 100644
> --- a/drivers/net/dsa/mv88e6xxx.c
> +++ b/drivers/net/dsa/mv88e6xxx.c
> @@ -19,6 +19,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -2323,7 +2324,10 @@ int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool 
> ppu_active)
>  {
>   struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
>   u16 is_reset = (ppu_active ? 0x8800 : 0xc800);
> + int gpio = ds->pd->reset;
> + int flags = ds->pd->reset_flags;
>   unsigned long timeout;
> + int on = 1;
>   int ret;
>   int i;
>  
> @@ -2336,6 +2340,16 @@ int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool 
> ppu_active)
>   /* Wait for transmit queues to drain. */
>   usleep_range(2000, 4000);
>  
> + /* If there is a gpio connected to the reset pin, toggle it */
> + if (gpio_is_valid(gpio)) {
> + if (flags && OF_GPIO_ACTIVE_LOW)
> + on = !on;
> + gpio_set_value_cansleep(gpio, on);
> + usleep_range(1, 2);
> + gpio_set_value_cansleep(gpio, !on);
> + usleep_range(1, 2);
> + }

We are embedding reset logic here about the delays and polarity, while
there is now a proper abstraction for this within the reset controller
subsystem under drivers/reset/core.c. Could we utilize that facility
instead which would make us more robust wrt. non-GPIO reset lines (for
instance some SF2 switches on DSL gateways could definitively benefit
from this).

There does not seem to be a reset controller GPIO binding and generic
driver, but this seems like an appropriate candidate?
-- 
Florian
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] net: tulip: turn compile-time warning into dev_warn()

2015-11-19 Thread Florian Fainelli
On 19/11/15 04:26, Will Deacon wrote:
> On Thu, Nov 19, 2015 at 11:42:26AM +0100, Arnd Bergmann wrote:
>> The tulip driver causes annoying build-time warnings for allmodconfig
>> builds for all recent architectures:
>>
>> dec/tulip/winbond-840.c:910:2: warning: #warning Processor architecture 
>> undefined
>> dec/tulip/tulip_core.c:101:2: warning: #warning Processor architecture 
>> undefined!
>>
>> This is the last remaining warning for arm64, and I'd like to get rid of
>> it. We don't really know the cache line size, architecturally it would
>> be at least 16 bytes, but all implementations I found have 64 or 128
>> bytes. Configuring tulip for 32-byte lines as we do on ARM32 seems to
>> be the safe but slow default, and nobody who cares about performance these
>> days would use a tulip chip anyway, so we can just use that.
>>
>> To save the next person the job of trying to find out what this is for
>> and picking a default for their architecture just to kill off the warning,
>> I'm now removing the preprocessor #warning and turning it into a pr_warn
>> or dev_warn that prints the equivalent information when the driver gets
>> loaded.
>>
>> Signed-off-by: Arnd Bergmann 
>>
>> diff --git a/drivers/net/ethernet/dec/tulip/tulip_core.c 
>> b/drivers/net/ethernet/dec/tulip/tulip_core.c
>> index ed41559bae77..b553409e04ad 100644
>> --- a/drivers/net/ethernet/dec/tulip/tulip_core.c
>> +++ b/drivers/net/ethernet/dec/tulip/tulip_core.c
>> @@ -98,8 +98,7 @@ static int csr0 = 0x01A0 | 0x4800;
>>  #elif defined(__mips__)
>>  static int csr0 = 0x0020 | 0x4000;
>>  #else
>> -#warning Processor architecture undefined!
>> -static int csr0 = 0x00A0 | 0x4800;
>> +static int csr0;
>>  #endif
>>  
>>  /* Operational parameters that usually are not changed. */
>> @@ -1982,6 +1981,12 @@ static int __init tulip_init (void)
>>  pr_info("%s", version);
>>  #endif
>>  
>> +if (!csr0) {
>> +pr_warn("tulip: unknown CPU architecture, using default 
>> csr0\n");
>> +/* default to 8 longword cache line alignment */
>> +csr0 = 0x00A0 | 0x4800;
> 
> Maybe print "defaulting to 8 longword cache line alignment" instead of
> "default csr0"?
> 
>> diff --git a/drivers/net/ethernet/dec/tulip/winbond-840.c 
>> b/drivers/net/ethernet/dec/tulip/winbond-840.c
>> index 9beb3d34d4ba..3c0e4d5c5fef 100644
>> --- a/drivers/net/ethernet/dec/tulip/winbond-840.c
>> +++ b/drivers/net/ethernet/dec/tulip/winbond-840.c
>> @@ -907,7 +907,7 @@ static void init_registers(struct net_device *dev)
>>  #elif defined(CONFIG_SPARC) || defined (CONFIG_PARISC) || 
>> defined(CONFIG_ARM)
>>  i |= 0x4800;
>>  #else
>> -#warning Processor architecture undefined
>> +dev_warn(>dev, "unknown CPU architecture, using default csr0 
>> setting\n");
>>  i |= 0x4800;
> 
> Then we could print the default csr0 value here.
> 
> But, to be honest, this patch fixes a #warning on arm64 for a driver that
> I never expect to be used. So whatever you do to silence it:
> 
>   Acked-by: Will Deacon 
> 
> /me waits for on-soc tulip integration.

FWIW, this already happened, the ADMtek/Infineon ADM8668 actually
integrated a Tulip chip. I have not submitted these patches below from
the OpenWrt tree because the chip is barely used nowadays, and it was
only mostly popular with the Linksys WRTU54G.

The patches could be made less intrusive if we did convert the pci_dma*
calls into regular DMA-API calls, which they are nowadays, oh well!

https://dev.openwrt.org/browser/trunk/target/linux/adm8668/patches-3.18/004-tulip_pci_split.patch
https://dev.openwrt.org/browser/trunk/target/linux/adm8668/patches-3.18/005-tulip_platform.patch
-- 
Florian
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] net: tulip: update MAINTAINER status to Orphan

2015-11-19 Thread Florian Fainelli
On 19/11/15 17:56, Grant Grundler wrote:
> From: Grant Grundler 
> 
> I haven't had any PCI tulip HW for the past ~5 years. I have
> been reviewing tulip patches and can continue doing that.
> 
> Signed-off-by: Grant Grundler 
> ---
> I'm also proposing to add linux-parisc to the list since AFAIK, all
> parisc systems but the C8000 workstations (PA8800/PA8900 CPU)
> use tulip for onboard LAN.
> 
> Specific mips and alpha systems also care about tulip driver too.
> But I don't know either well enough to suggest respective mailing
> lists should see every tulip patch.

For MIPS, is not Cobalt the primary (and sole) user? You could add
linux-m...@linux-mips.org if that helps. My Cobalt stayed behind me when
I moved to the US, so outside of Yoichi, I am not sure who else cares
these days...

> 
>  MAINTAINERS | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index ea17512..ec07061 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -10888,9 +10888,9 @@ S:Maintained
>  F:   drivers/media/tuners/tua9001*
>  
>  TULIP NETWORK DRIVERS
> -M:   Grant Grundler 
>  L:   netdev@vger.kernel.org
> -S:   Maintained
> +L:   linux-par...@vger.kernel.org
> +S:   Orphan
>  F:   drivers/net/ethernet/dec/tulip/
>  
>  TUN/TAP driver
> 


-- 
Florian
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH net-next 01/17] net: dsa: slave: chip data is optional, don't dereference NULL

2016-06-03 Thread Florian Fainelli
On 06/03/2016 09:44 AM, Andrew Lunn wrote:
> The new binding does not make use of dsa_chip_data, a.k.a cd.  When
> retrieving the size of the EEPROM attached to a switch, don't assume
> there is a cd attached to the switch structure.
> 
> Signed-off-by: Andrew Lunn <and...@lunn.ch>

Reviewed-by: Florian Fainelli <f.faine...@gmail.com>
-- 
Florian


Re: [PATCH net-next 03/17] net: dsa: slave: Remove MDIO address from switch MDIO bus name

2016-06-03 Thread Florian Fainelli
On 06/03/2016 09:44 AM, Andrew Lunn wrote:
> The DSA layer should no longer assume the switch is connected to an
> MDIO bus. As a result, we cannot use the address on the MDIO bus when
> forming the name of the switches internal MDIO bus for its builtin and
> possibly external PHYs. The switch index is sufficient to make the
> name unique, so drop the MDIO address.
> 
> Signed-off-by: Andrew Lunn <and...@lunn.ch>

Reviewed-by: Florian Fainelli <f.faine...@gmail.com>
-- 
Florian


[PATCH net-next 2/2] bgmac: Add support for ethtool statistics

2016-06-03 Thread Florian Fainelli
Read the statistics from the BGMAC's builtin MAC and return them to
user-space using the standard ethtool helpers.

Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 drivers/net/ethernet/broadcom/bgmac.c | 125 ++
 drivers/net/ethernet/broadcom/bgmac.h |   4 +-
 2 files changed, 127 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bgmac.c 
b/drivers/net/ethernet/broadcom/bgmac.c
index 156fa6323745..d5877365d81a 100644
--- a/drivers/net/ethernet/broadcom/bgmac.c
+++ b/drivers/net/ethernet/broadcom/bgmac.c
@@ -1382,6 +1382,128 @@ static const struct net_device_ops bgmac_netdev_ops = {
  * ethtool_ops
  **/
 
+struct bgmac_stat {
+   u8 size;
+   u32 offset;
+   const char *name;
+};
+
+static struct bgmac_stat bgmac_get_strings_stats[] = {
+   { 8, BGMAC_TX_GOOD_OCTETS, "tx_good_octets" },
+   { 4, BGMAC_TX_GOOD_PKTS, "tx_good" },
+   { 8, BGMAC_TX_OCTETS, "tx_octets" },
+   { 4, BGMAC_TX_PKTS, "tx_pkts" },
+   { 4, BGMAC_TX_BROADCAST_PKTS, "tx_broadcast" },
+   { 4, BGMAC_TX_MULTICAST_PKTS, "tx_multicast" },
+   { 4, BGMAC_TX_LEN_64, "tx_64" },
+   { 4, BGMAC_TX_LEN_65_TO_127, "tx_65_127" },
+   { 4, BGMAC_TX_LEN_128_TO_255, "tx_128_255" },
+   { 4, BGMAC_TX_LEN_256_TO_511, "tx_256_511" },
+   { 4, BGMAC_TX_LEN_512_TO_1023, "tx_512_1023" },
+   { 4, BGMAC_TX_LEN_1024_TO_1522, "tx_1024_1522" },
+   { 4, BGMAC_TX_LEN_1523_TO_2047, "tx_1523_2047" },
+   { 4, BGMAC_TX_LEN_2048_TO_4095, "tx_2048_4095" },
+   { 4, BGMAC_TX_LEN_4096_TO_8191, "tx_4096_8191" },
+   { 4, BGMAC_TX_LEN_8192_TO_MAX, "tx_8192_max" },
+   { 4, BGMAC_TX_JABBER_PKTS, "tx_jabber" },
+   { 4, BGMAC_TX_OVERSIZE_PKTS, "tx_oversize" },
+   { 4, BGMAC_TX_FRAGMENT_PKTS, "tx_fragment" },
+   { 4, BGMAC_TX_UNDERRUNS, "tx_underruns" },
+   { 4, BGMAC_TX_TOTAL_COLS, "tx_total_cols" },
+   { 4, BGMAC_TX_SINGLE_COLS, "tx_single_cols" },
+   { 4, BGMAC_TX_MULTIPLE_COLS, "tx_multiple_cols" },
+   { 4, BGMAC_TX_EXCESSIVE_COLS, "tx_excessive_cols" },
+   { 4, BGMAC_TX_LATE_COLS, "tx_late_cols" },
+   { 4, BGMAC_TX_DEFERED, "tx_defered" },
+   { 4, BGMAC_TX_CARRIER_LOST, "tx_carrier_lost" },
+   { 4, BGMAC_TX_PAUSE_PKTS, "tx_pause" },
+   { 4, BGMAC_TX_UNI_PKTS, "tx_unicast" },
+   { 4, BGMAC_TX_Q0_PKTS, "tx_q0" },
+   { 8, BGMAC_TX_Q0_OCTETS, "tx_q0_octets" },
+   { 4, BGMAC_TX_Q1_PKTS, "tx_q1" },
+   { 8, BGMAC_TX_Q1_OCTETS, "tx_q1_octets" },
+   { 4, BGMAC_TX_Q2_PKTS, "tx_q2" },
+   { 8, BGMAC_TX_Q2_OCTETS, "tx_q2_octets" },
+   { 4, BGMAC_TX_Q3_PKTS, "tx_q3" },
+   { 8, BGMAC_TX_Q3_OCTETS, "tx_q3_octets" },
+   { 8, BGMAC_RX_GOOD_OCTETS, "rx_good_octets" },
+   { 4, BGMAC_RX_GOOD_PKTS, "rx_good" },
+   { 8, BGMAC_RX_OCTETS, "rx_octets" },
+   { 4, BGMAC_RX_PKTS, "rx_pkts" },
+   { 4, BGMAC_RX_BROADCAST_PKTS, "rx_broadcast" },
+   { 4, BGMAC_RX_MULTICAST_PKTS, "rx_multicast" },
+   { 4, BGMAC_RX_LEN_64, "rx_64" },
+   { 4, BGMAC_RX_LEN_65_TO_127, "rx_65_127" },
+   { 4, BGMAC_RX_LEN_128_TO_255, "rx_128_255" },
+   { 4, BGMAC_RX_LEN_256_TO_511, "rx_256_511" },
+   { 4, BGMAC_RX_LEN_512_TO_1023, "rx_512_1023" },
+   { 4, BGMAC_RX_LEN_1024_TO_1522, "rx_1024_1522" },
+   { 4, BGMAC_RX_LEN_1523_TO_2047, "rx_1523_2047" },
+   { 4, BGMAC_RX_LEN_2048_TO_4095, "rx_2048_4095" },
+   { 4, BGMAC_RX_LEN_4096_TO_8191, "rx_4096_8191" },
+   { 4, BGMAC_RX_LEN_8192_TO_MAX, "rx_8192_max" },
+   { 4, BGMAC_RX_JABBER_PKTS, "rx_jabber" },
+   { 4, BGMAC_RX_OVERSIZE_PKTS, "rx_oversize" },
+   { 4, BGMAC_RX_FRAGMENT_PKTS, "rx_fragment" },
+   { 4, BGMAC_RX_MISSED_PKTS, "rx_missed" },
+   { 4, BGMAC_RX_CRC_ALIGN_ERRS, "rx_crc_align" },
+   { 4, BGMAC_RX_UNDERSIZE, "rx_undersize" },
+   { 4, BGMAC_RX_CRC_ERRS, "rx_crc" },
+   { 4, BGMAC_RX_ALIGN_ERRS, "rx_align" },
+   { 4, BGMAC_RX_SYMBOL_ERRS, "rx_symbol" },
+   { 4, BGMAC_RX_PAUSE_PKTS, "rx_pause" },
+   { 4, BGMAC_RX_NONPAUSE_PKTS, "rx_nonpause" },
+   { 4, BGMAC_RX_SACHANGES, "rx_sa_changes" },
+   { 4, BGMAC_RX_UNI_PKTS, "rx_unicast" },
+};
+
+#define BGMAC_STATS_LEN

[PATCH net-next 1/2] bgmac: Bind net_device with backing device structure

2016-06-03 Thread Florian Fainelli
In preparation for allowing different helpers to be utilized against
network devices created by the bgmac driver, make sure that we bind the
net_device with core->dev.

Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 drivers/net/ethernet/broadcom/bgmac.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/ethernet/broadcom/bgmac.c 
b/drivers/net/ethernet/broadcom/bgmac.c
index ee5f431ab32a..156fa6323745 100644
--- a/drivers/net/ethernet/broadcom/bgmac.c
+++ b/drivers/net/ethernet/broadcom/bgmac.c
@@ -1588,6 +1588,7 @@ static int bgmac_probe(struct bcma_device *core)
bgmac->net_dev = net_dev;
bgmac->core = core;
bcma_set_drvdata(core, bgmac);
+   SET_NETDEV_DEV(net_dev, >dev);
 
/* Defaults */
memcpy(bgmac->net_dev->dev_addr, mac, ETH_ALEN);
-- 
2.7.4



[PATCH net-next 0/2] net: bgmac: Misc improvements

2016-06-03 Thread Florian Fainelli
Hi David, Rafal, Hauke, Felix,

This patch series add minor changes to the bgmac driver:

- properly bind net_device with its backing device structure such that
  we can locate the device using common helper functions

- add support for ethtool statistics reading the HW MIB counters which
  is useful for debugging

Thanks

Florian Fainelli (2):
  bgmac: Bind net_device with backing device structure
  bgmac: Add support for ethtool statistics

 drivers/net/ethernet/broadcom/bgmac.c | 126 ++
 drivers/net/ethernet/broadcom/bgmac.h |   4 +-
 2 files changed, 128 insertions(+), 2 deletions(-)

-- 
2.7.4



Re: [PATCH net-next 2/2] bgmac: Add support for ethtool statistics

2016-06-03 Thread Florian Fainelli
On 06/03/2016 10:57 AM, Ben Hutchings wrote:
> On Fri, 2016-06-03 at 10:07 -0700, Florian Fainelli wrote:
> [...]
>> +static void bgmac_get_strings(struct net_device *dev, u32 stringset,
>> +  u8 *data)
>> +{
>> +int i;
>> +
>> +if (stringset != ETH_SS_STATS)
>> +return;
>> +
>> +for (i = 0; i < BGMAC_STATS_LEN; i++)
>> +memcpy(data + i * ETH_GSTRING_LEN,
>> +   bgmac_get_strings_stats[i].name,
>> +   ETH_GSTRING_LEN);
> 
> These strings are null-terminated, not padded to ETH_GSTRING_LEN.  So
> here you should be using strlcpy() instead of memcpy().
> 
>> +}
>> +
>> +static void bgmac_get_ethtool_stats(struct net_device *dev,
>> +struct ethtool_stats *ss, uint64_t *data)
>> +{
>> +struct bgmac *bgmac = netdev_priv(dev);
>> +const struct bgmac_stat *s;
>> +unsigned int i;
>> +u64 val;
>> +
>> +if (!netif_running(dev))
>> +return;
>> +
>> +for (i = 0; i < BGMAC_STATS_LEN; i++) {
>> +s = _get_strings_stats[i];
>> +val = 0;
>> +if (s->size == 8)
>> +val = (u64)bgmac_read(bgmac, s->offset + 4);
> 
> Isn't this missing a << 32?

It is, guess I should have made sure there was 4GB+ worth of traffic to
make sure this seemed reasonable.
> 
> Does reading the high 32 bits latch the value of the low 32 bits?  If
> not, you need to read the high bits again after the low bits and retry
> if they changed.

Yes these registers are latched.

> 
>> +val |= bgmac_read(bgmac, s->offset);
>> +data[i] = (u64)val;
> 
> Redundant cast.

Indeed, thanks.
-- 
Florian


Re: [PATCH net-next 04/17] net: dsa: tag_{e}dsa.c: Remove dependency on platform data

2016-06-03 Thread Florian Fainelli
On 06/03/2016 09:44 AM, Andrew Lunn wrote:
> The platform data nr_chips is used when validating a received packet,
> to ensure it comes from a know switch chip. The number of possible
> switches is limited to DSA_MAX_SWITCHES, so use this as the first
> validation step. The new binding allows holes in the dst->ds[] array,
> so also ensure ensure there is a valid dsa_switch for this packet.
> 
> Signed-off-by: Andrew Lunn <and...@lunn.ch>

Reviewed-by: Florian Fainelli <f.faine...@gmail.com>
-- 
Florian


Re: [PATCH net-next 11/17] net: dsa: Refactor selection of tag ops into a function

2016-06-03 Thread Florian Fainelli
On 06/03/2016 09:44 AM, Andrew Lunn wrote:
> Replace the two switch statements with an array lookup, and store the
> result in the dsa tree structure. The drivers no longer need to know
> the selected tag protocol, so remove it from the dsa switch structure.
> 
> Signed-off-by: Andrew Lunn <and...@lunn.ch>

Reviewed-by: Florian Fainelli <f.faine...@gmail.com>
-- 
Florian


Re: [PATCH net-next 00/17] New DSA bind, switches as devices

2016-06-03 Thread Florian Fainelli
On 06/03/2016 09:43 AM, Andrew Lunn wrote:
> The interesting patches here are the last three. They implement a new
> binding for DSA, which removes a few limitations of the current DSA
> binding. In particular, it allows switches to be true Linux devices.
> These devices can be on any type of bus, unlike the old DSA binding
> which assumes MDIO. See the commit log for more details. The second to
> last patch modifies an existing boards device tree to use the new
> binding, giving a good example of how switches can be true MDIO
> devices. The last patch documents the new binding.
> 
> I know both John Crispin and Bryan Whitehead are interesting in
> implementing DSA drivers, hence i have CC: you. Comments welcome.
> 
> Thanks go to Florian and Vivien for reviewing, testing and bug fixing
> these patches.

Will keep reviewing patches by one, but a quick smoke test here on a
BCM7445 with bcm_sf2 gives me all thumbs up.

Tested-by: Florian Fainelli <f.faine...@gmail.com>

Thanks!

> 
> Since RFC:
> 
> * Split the mv88e6xxx MDIO refactor into a rename patch and a refactor
>   patch.
> * Extend commit message with comment about wrong of_node_put()
> * Fix destroy of cpu and dsa ports.
> * Rename _DSA_TAG_LAST to DSA_TAG_LAST and add a comment.
> 
> Andrew Lunn (16):
>   net: dsa: slave: chip data is optional, don't dereference NULL
>   net: dsa: slave: Remove MDIO address from switch MDIO bus name
>   net: dsa: tag_{e}dsa.c: Remove dependency on platform data
>   net: dsa: Add a ports structure and use it in the switch structure
>   net: dsa: Move port device node into port structure
>   net: dsa: Remove dynamic allocate of routing table
>   net: dsa: Copy the routing table into the switch structure
>   net: dsa: Split up creating/destroying of DSA and CPU ports
>   net: dsa: mv88e6xxx: Only support EDSA tagging
>   net: dsa: Refactor selection of tag ops into a function
>   net: dsa: Make mdio bus optional
>   net: dsa: mv88e6xxx: Rename _phy_ to _mdio_
>   net: dsa: mv88e6xxx: Refactor MDIO so driver registers mdio bus
>   net: dsa: Add new binding implementation
>   arm: dt: vf610-zii-devel-b: Make use of new DSA binding
>   net: dsa: Document new binding
> 
> Vivien Didelot (1):
>   net: dsa: mv88e6xxx: fix circular lock in PPU work
> 
>  Documentation/devicetree/bindings/net/dsa/dsa.txt | 278 -
>  arch/arm/boot/dts/vf610-zii-dev-rev-b.dts | 328 +--
>  drivers/net/dsa/bcm_sf2.c |   4 +-
>  drivers/net/dsa/mv88e6xxx.c   | 267 ++---
>  drivers/net/dsa/mv88e6xxx.h   |   6 +
>  include/net/dsa.h |  56 +-
>  net/dsa/Makefile  |   2 +-
>  net/dsa/dsa.c | 210 ---
>  net/dsa/dsa2.c| 653 
> ++
>  net/dsa/dsa_priv.h|   6 +-
>  net/dsa/slave.c   |  57 +-
>  net/dsa/tag_brcm.c|   4 +-
>  net/dsa/tag_dsa.c |  10 +-
>  net/dsa/tag_edsa.c|  10 +-
>  net/dsa/tag_trailer.c |   4 +-
>  15 files changed, 1485 insertions(+), 410 deletions(-)
>  create mode 100644 net/dsa/dsa2.c
> 


-- 
Florian


Re: [PATCH net-next 05/17] net: dsa: Add a ports structure and use it in the switch structure

2016-06-03 Thread Florian Fainelli
On 06/03/2016 09:44 AM, Andrew Lunn wrote:
> There are going to be more per-port members added to the switch
> structure. So add a port structure and move the netdev into it.
> 
> Signed-off-by: Andrew Lunn <and...@lunn.ch>

Reviewed-by: Florian Fainelli <f.faine...@gmail.com>
-- 
Florian


Re: [PATCH net-next 06/17] net: dsa: Move port device node into port structure

2016-06-03 Thread Florian Fainelli
On 06/03/2016 09:44 AM, Andrew Lunn wrote:
> Move the port device node structure into the port structure, from the
> chip data. This information is needed in the next step of implementing
> the new binding.
> 
> The chip data structure is used while parsing the whole old binding,
> before the individual switch structures exist. With the new bindings,
> this is reversed, the switches exist first, and the interconnections
> between the switches is derived from the individual switch
> bindings. Thus this chip data structure becomes unneeded.
> 
> Signed-off-by: Andrew Lunn <and...@lunn.ch>

Reviewed-by: Florian Fainelli <f.faine...@gmail.com>
-- 
Florian


Re: [PATCH net-next 09/17] net: dsa: Split up creating/destroying of DSA and CPU ports

2016-06-03 Thread Florian Fainelli
On 06/03/2016 09:44 AM, Andrew Lunn wrote:
> Refactor the code to setup a single DSA/CPU port into a function of
> its own, and export it, so it can be used by the new binding.
> 
> Similarly, refactor the destroy code into a function.  When destroying
> the ports, don't put the of node. They should be released at the end
> along with the normal ports.
> 
> Signed-off-by: Andrew Lunn <and...@lunn.ch>

Reviewed-by: Florian Fainelli <f.faine...@gmail.com>
-- 
Florian


Re: [PATCH net-next 08/17] net: dsa: Copy the routing table into the switch structure

2016-06-03 Thread Florian Fainelli
On 06/03/2016 09:44 AM, Andrew Lunn wrote:
> The new binding will not have a chip data structure, it will place the
> routing directly into the switch structure. To enable backwards
> compatibility, copy the routing from the chip data into the switch
> structure.
> 
> Signed-off-by: Andrew Lunn <and...@lunn.ch>

Reviewed-by: Florian Fainelli <f.faine...@gmail.com>
-- 
Florian


Re: [PATCH net-next 10/17] net: dsa: mv88e6xxx: Only support EDSA tagging

2016-06-03 Thread Florian Fainelli
On 06/03/2016 09:44 AM, Andrew Lunn wrote:
> The merged driver no longer offers the option to use DSA tagging. So
> remove the code to setup the switch to do DSA tagging and hard code
> the use of EDSA.
> 
> Signed-off-by: Andrew Lunn <and...@lunn.ch>

Reviewed-by: Florian Fainelli <f.faine...@gmail.com>
-- 
Florian


Re: [PATCH net-next 02/17] net: dsa: mv88e6xxx: fix circular lock in PPU work

2016-06-03 Thread Florian Fainelli
ce:
> [4.679674] [<8010d354>] (dump_backtrace) from [<8010d5a0>] 
> (show_stack+0x20/0x24)
> [4.687252]  r6:80fb3c88 r5:80fb3c88 r4:80fb4728 r3:0002
> [4.693003] [<8010d580>] (show_stack) from [<803b45e8>] 
> (dump_stack+0x24/0x28)
> [4.700246] [<803b45c4>] (dump_stack) from [<80157398>] 
> (print_circular_bug+0x208/0x32c)
> [4.708361] [<80157190>] (print_circular_bug) from [<8015a630>] 
> (__lock_acquire+0x185c/0x1b80)
> [4.716982]  r10:9ec22a00 r9:0060 r8:8164b6bc r7:0040 
> r6:0003 r5:8163a5b4
> [4.724905]  r4:0003 r3:9ec22de8
> [4.728537] [<80158dd4>] (__lock_acquire) from [<8015ad5c>] 
> (lock_acquire+0xb4/0x1dc)
> [4.736378]  r10:6013 r9: r8: r7: 
> r6:9e5e9c50 r5:80e618e0
> [4.744301]  r4:
> [4.746879] [<8015aca8>] (lock_acquire) from [<806d86bc>] 
> (mutex_lock_nested+0x54/0x360)
> [4.754976]  r10:9e5e9c1c r9:80e616c4 r8:9f685ea0 r7:001b 
> r6:9ec22a00 r5:8163a5b4
> [4.762899]  r4:9e5e9c1c
> [4.765477] [<806d8668>] (mutex_lock_nested) from [<8049c758>] 
> (mv88e6xxx_reg_read+0x30/0x54)
> [4.774008]  r10:80e60c5b r9:80e616c4 r8:9f685ea0 r7:001b 
> r6:0004 r5:9e5e9c10
> [4.781930]  r4:9e5e9c1c
> [4.784507] [<8049c728>] (mv88e6xxx_reg_read) from [<8049cad8>] 
> (mv88e6xxx_ppu_reenable_work+0x40/0xd4)
> [4.793907]  r7:9ffd5400 r6:9e5e9c68 r5:9e5e9cb0 r4:9e5e9c10
> [4.799659] [<8049ca98>] (mv88e6xxx_ppu_reenable_work) from 
> [<8013a794>] (process_one_work+0x1a8/0x604)
> [4.809059]  r9:80e616c4 r8:9f685ea0 r7:9ffd5400 r6:80e0a1c8 
> r5:9f5f2e80 r4:9e5e9cb0
>     [4.816910] [<8013a5ec>] (process_one_work) from [<8013ac54>] 
> (worker_thread+0x64/0x528)
> [4.825010]  r10:9f5f2e80 r9:0008 r8:80e0dc80 r7:80e0a1fc 
> r6:80e0a1c8 r5:9f5f2e98
> [4.832933]  r4:80e0a1c8
> [4.835510] [<8013abf0>] (worker_thread) from [<801409e8>] 
> (kthread+0xec/0x100)
> [4.842827]  r10: r9: r8: r7:8013abf0 
> r6:9f5f2e80 r5:9ec15740
> [4.850749]  r4:
> [4.853327] [<801408fc>] (kthread) from [<80108f30>] 
> (ret_from_fork+0x14/0x24)
> [4.860557]  r7: r6: r5:801408fc r4:9ec15740
> 
> Signed-off-by: Vivien Didelot <vivien.dide...@savoirfairelinux.com>

Reviewed-by: Florian Fainelli <f.faine...@gmail.com>
-- 
Florian


Re: [PATCH net-next 07/17] net: dsa: Remove dynamic allocate of routing table

2016-06-03 Thread Florian Fainelli
On 06/03/2016 09:44 AM, Andrew Lunn wrote:
> With a maximum of four switches, the size of the routing table is the
> same as the pointer to it. Removing it makes the code simpler.
> 
> Signed-off-by: Andrew Lunn <and...@lunn.ch>

Reviewed-by: Florian Fainelli <f.faine...@gmail.com>
-- 
Florian


Re: [PATCH net-next 15/17] net: dsa: Add new binding implementation

2016-06-03 Thread Florian Fainelli
On 06/03/2016 09:44 AM, Andrew Lunn wrote:
> The existing DSA binding has a number of limitations and problems. The
> main problem is that it cannot represent a switch as a linux device,
> hanging off some bus. It is limited to one CPU port. The DSA platform
> device is artificial, and does not really represent hardware.
> 
> Implement a new binding which can be embedded into any type of node on
> a bus to represent one switch device, and its links to other switches.
> 
> Signed-off-by: Andrew Lunn <and...@lunn.ch>
> Signed-off-by: Florian Fainelli <f.faine...@gmail.com>

Just a few nits that I had not seen before...


> diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
> index 6c314f300424..d8cb2acd4f0a 100644
> --- a/net/dsa/dsa.c
> +++ b/net/dsa/dsa.c
> @@ -294,6 +294,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, 
> struct device *parent)
>   }
>   dst->cpu_switch = index;
>   dst->cpu_port = i;
> + ds->cpu_port_mask |= 1 << i;
>   } else if (!strcmp(name, "dsa")) {
>   ds->dsa_port_mask |= 1 << i;
>   } else {

We might want to undo setting the cpu_port_mask bit in
dsa_cpu_dsa_destroy()?

[snip]

> +static int dsa_ds_complete(struct dsa_switch_tree *dst, struct dsa_switch 
> *ds)
> +{
> + struct device_node *port;
> + u32 index;
> + int err;
> +
> + for (index = 0; index < DSA_MAX_PORTS; index++) {
> + port = ds->ports[index].dn;
> + if (!port)
> + continue;
> +
> + if (!dsa_port_is_dsa(port))
> + continue;
> +
> + ds->dsa_port_mask |= 1 << index;
> +
> + err = dsa_port_complete(dst, ds, port, index);
> + if (err != 0)

Should we move ds->dsa_port_mask |= 1 << index into dsa_port_complete,
for a) symetry with code undoing this, and b) avoid letting this bit be
set in case dsa_port_complete() returns an error?
-- 
Florian


[PATCH net-next v4 0/6] net: dsa: misc improvements

2016-06-07 Thread Florian Fainelli
Hi all,

This patch series builds on top of Andrew's "New DSA bind, switches as devices"
patch set and does the following:

- add a few helper functions/goodies for net/dsa/dsa2.c to be as close as 
possible
  from net/dsa/dsa.c in terms of what drivers can expect, in particular the 
slave
  MDIO bus and the enabled_port_mask and phy_mii_mask

- fix the CPU port ethtools ops to work in a multiple tree setup since we can
  no longer assume a single tree is supported

- make the bcm_sf2 driver register its own MDIO bus, yet assign it to
  ds->slave_mii_bus for everything to work in net/dsa/slave.c wrt. PHY probing,
  this is a tad cleaner than what we have now

Changes in v2:

Most of the previous patches have been dropped to just keep the relevant ones
now.

Changes in v3:
- split the addition of the slave MII bus as a separate patch
- properly unwind all operations at the right place and right time (ethtool ops,
  slave MDIO bus
- fixed a few typos here and there

Changes in v4:
- removed superfluous dst agrument to dsa_cpu_port_ethtool_{setup,restore}

Florian Fainelli (6):
  net: dsa: Provide unique DSA slave MII bus names
  net: dsa: Initialize ds->enabled_port_mask and ds->phys_mii_mask
  net: dsa: Provide a slave MII bus if needed
  net: dsa: Add initialization helper for CPU port ethtool_ops
  net: dsa: Initialize CPU port ethtool ops per tree
  net: dsa: bcm_sf2: Register our slave MDIO bus

 drivers/net/dsa/bcm_sf2.c | 215 +-
 drivers/net/dsa/bcm_sf2.h |   6 ++
 include/net/dsa.h |   1 +
 net/dsa/dsa.c |  41 +
 net/dsa/dsa2.c|  36 
 net/dsa/dsa_priv.h|   5 ++
 net/dsa/slave.c   |  25 ++
 7 files changed, 232 insertions(+), 97 deletions(-)

-- 
2.7.4



[PATCH net-next v4 4/6] net: dsa: Add initialization helper for CPU port ethtool_ops

2016-06-07 Thread Florian Fainelli
Add a helper function: dsa_cpu_port_ethtool_init() which initializes a
custom ethtool_ops structure with custom DSA ethtool operations for CPU
ports. This is a preliminary change to move the initialization outside
of net/dsa/slave.c.

Reviewed-by: Vivien Didelot <vivien.dide...@savoirfairelinux.com>
Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 net/dsa/dsa_priv.h |  1 +
 net/dsa/slave.c| 14 --
 2 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index b42f1a5f95f3..106a9f067f94 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -58,6 +58,7 @@ const struct dsa_device_ops *dsa_resolve_tag_protocol(int 
tag_protocol);
 /* slave.c */
 extern const struct dsa_device_ops notag_netdev_ops;
 void dsa_slave_mii_bus_init(struct dsa_switch *ds);
+void dsa_cpu_port_ethtool_init(struct ethtool_ops *ops);
 int dsa_slave_create(struct dsa_switch *ds, struct device *parent,
 int port, const char *name);
 void dsa_slave_destroy(struct net_device *slave_dev);
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index a51dfedf0014..8d159932e082 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -865,6 +865,13 @@ static void dsa_slave_poll_controller(struct net_device 
*dev)
 }
 #endif
 
+void dsa_cpu_port_ethtool_init(struct ethtool_ops *ops)
+{
+   ops->get_sset_count = dsa_cpu_port_get_sset_count;
+   ops->get_ethtool_stats = dsa_cpu_port_get_ethtool_stats;
+   ops->get_strings = dsa_cpu_port_get_strings;
+}
+
 static const struct ethtool_ops dsa_slave_ethtool_ops = {
.get_settings   = dsa_slave_get_settings,
.set_settings   = dsa_slave_set_settings,
@@ -1124,12 +1131,7 @@ int dsa_slave_create(struct dsa_switch *ds, struct 
device *parent,
   sizeof(struct ethtool_ops));
memcpy(_cpu_port_ethtool_ops, >master_ethtool_ops,
   sizeof(struct ethtool_ops));
-   dsa_cpu_port_ethtool_ops.get_sset_count =
-   dsa_cpu_port_get_sset_count;
-   dsa_cpu_port_ethtool_ops.get_ethtool_stats =
-   dsa_cpu_port_get_ethtool_stats;
-   dsa_cpu_port_ethtool_ops.get_strings =
-   dsa_cpu_port_get_strings;
+   dsa_cpu_port_ethtool_init(_cpu_port_ethtool_ops);
master->ethtool_ops = _cpu_port_ethtool_ops;
}
eth_hw_addr_inherit(slave_dev, master);
-- 
2.7.4



[PATCH net-next v4 3/6] net: dsa: Provide a slave MII bus if needed

2016-06-07 Thread Florian Fainelli
Mimic what net/dsa/dsa.c does and provide a slave MII bus by default
which will be created if the driver implements a phy_read method.

Reviewed-by: Andrew Lunn <and...@lunn.ch>
Reviewed-by: Vivien Didelot <vivien.dide...@savoirfairelinux.com>
Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 net/dsa/dsa2.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index 921a36fd139d..4e0f3c268103 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -312,6 +312,18 @@ static int dsa_ds_apply(struct dsa_switch_tree *dst, 
struct dsa_switch *ds)
if (err < 0)
return err;
 
+   if (!ds->slave_mii_bus && ds->drv->phy_read) {
+   ds->slave_mii_bus = devm_mdiobus_alloc(ds->dev);
+   if (!ds->slave_mii_bus)
+   return -ENOMEM;
+
+   dsa_slave_mii_bus_init(ds);
+
+   err = mdiobus_register(ds->slave_mii_bus);
+   if (err < 0)
+   return err;
+   }
+
for (index = 0; index < DSA_MAX_PORTS; index++) {
port = ds->ports[index].dn;
if (!port)
@@ -361,6 +373,9 @@ static void dsa_ds_unapply(struct dsa_switch_tree *dst, 
struct dsa_switch *ds)
 
dsa_user_port_unapply(port, index, ds);
}
+
+   if (ds->slave_mii_bus && ds->drv->phy_read)
+   mdiobus_unregister(ds->slave_mii_bus);
 }
 
 static int dsa_dst_apply(struct dsa_switch_tree *dst)
-- 
2.7.4



[PATCH net-next v4 2/6] net: dsa: Initialize ds->enabled_port_mask and ds->phys_mii_mask

2016-06-07 Thread Florian Fainelli
Some drivers rely on these two bitmasks to contain the correct values
for them to successfully probe and initialize at drv->setup() time,
calculate correct values to put in both masks as early as possible in
dsa_get_ports_dn().

Reviewed-by: Andrew Lunn <and...@lunn.ch>
Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 net/dsa/dsa2.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index 80dfe08db825..921a36fd139d 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -283,6 +283,7 @@ static void dsa_user_port_unapply(struct device_node *port, 
u32 index,
if (ds->ports[index].netdev) {
dsa_slave_destroy(ds->ports[index].netdev);
ds->ports[index].netdev = NULL;
+   ds->enabled_port_mask &= ~(1 << index);
}
 }
 
@@ -292,6 +293,13 @@ static int dsa_ds_apply(struct dsa_switch_tree *dst, 
struct dsa_switch *ds)
u32 index;
int err;
 
+   /* Initialize ds->phys_mii_mask before registering the slave MDIO bus
+* driver and before drv->setup() has run, since the switch drivers and
+* the slave MDIO bus driver rely on these values for probing PHY
+* devices or not
+*/
+   ds->phys_mii_mask = ds->enabled_port_mask;
+
err = ds->drv->setup(ds);
if (err < 0)
return err;
@@ -511,6 +519,13 @@ static int dsa_parse_ports_dn(struct device_node *ports, 
struct dsa_switch *ds)
return -EINVAL;
 
ds->ports[reg].dn = port;
+
+   /* Initialize enabled_port_mask now for drv->setup()
+* to have access to a correct value, just like what
+* net/dsa/dsa.c::dsa_switch_setup_one does.
+*/
+   if (!dsa_port_is_cpu(port))
+   ds->enabled_port_mask |= 1 << reg;
}
 
return 0;
-- 
2.7.4



[PATCH net-next v4 1/6] net: dsa: Provide unique DSA slave MII bus names

2016-06-07 Thread Florian Fainelli
In case we have multiples trees and switches with the same index, we
need to add another discriminating id: the switch tree.

Reviewed-by: Andrew Lunn <and...@lunn.ch>
Reviewed-by: Vivien Didelot <vivien.dide...@savoirfairelinux.com>
Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 net/dsa/slave.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 15a492261895..a51dfedf0014 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -49,7 +49,8 @@ void dsa_slave_mii_bus_init(struct dsa_switch *ds)
ds->slave_mii_bus->name = "dsa slave smi";
ds->slave_mii_bus->read = dsa_slave_phy_read;
ds->slave_mii_bus->write = dsa_slave_phy_write;
-   snprintf(ds->slave_mii_bus->id, MII_BUS_ID_SIZE, "dsa-%d", ds->index);
+   snprintf(ds->slave_mii_bus->id, MII_BUS_ID_SIZE, "dsa-%d.%d",
+ds->dst->tree, ds->index);
ds->slave_mii_bus->parent = ds->dev;
ds->slave_mii_bus->phy_mask = ~ds->phys_mii_mask;
 }
-- 
2.7.4



[PATCH net-next v4 6/6] net: dsa: bcm_sf2: Register our slave MDIO bus

2016-06-07 Thread Florian Fainelli
Register a slave MDIO bus which allows us to divert problematic
read/writes towards conflicting pseudo-PHY address (30). Do no longer
rely on DSA's slave_mii_bus, but instead provide our own implementation
which offers more flexibility as to what to do, and when to register it.

We need to register it by the time we are able to get access to our
memory mapped registers, which is not until drv->setup() time. In order
to avoid forward declarations, we need to re-order the function bodies a
bit.

Reviewed-by: Andrew Lunn <and...@lunn.ch>
Reviewed-by: Vivien Didelot <vivien.dide...@savoirfairelinux.com>
Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 drivers/net/dsa/bcm_sf2.c | 215 +-
 drivers/net/dsa/bcm_sf2.h |   6 ++
 2 files changed, 140 insertions(+), 81 deletions(-)

diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 73df91bb0466..d6625783703f 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -836,6 +837,66 @@ static int bcm_sf2_sw_fdb_dump(struct dsa_switch *ds, int 
port,
return 0;
 }
 
+static int bcm_sf2_sw_indir_rw(struct bcm_sf2_priv *priv, int op, int addr,
+  int regnum, u16 val)
+{
+   int ret = 0;
+   u32 reg;
+
+   reg = reg_readl(priv, REG_SWITCH_CNTRL);
+   reg |= MDIO_MASTER_SEL;
+   reg_writel(priv, reg, REG_SWITCH_CNTRL);
+
+   /* Page << 8 | offset */
+   reg = 0x70;
+   reg <<= 2;
+   core_writel(priv, addr, reg);
+
+   /* Page << 8 | offset */
+   reg = 0x80 << 8 | regnum << 1;
+   reg <<= 2;
+
+   if (op)
+   ret = core_readl(priv, reg);
+   else
+   core_writel(priv, val, reg);
+
+   reg = reg_readl(priv, REG_SWITCH_CNTRL);
+   reg &= ~MDIO_MASTER_SEL;
+   reg_writel(priv, reg, REG_SWITCH_CNTRL);
+
+   return ret & 0x;
+}
+
+static int bcm_sf2_sw_mdio_read(struct mii_bus *bus, int addr, int regnum)
+{
+   struct bcm_sf2_priv *priv = bus->priv;
+
+   /* Intercept reads from Broadcom pseudo-PHY address, else, send
+* them to our master MDIO bus controller
+*/
+   if (addr == BRCM_PSEUDO_PHY_ADDR && priv->indir_phy_mask & BIT(addr))
+   return bcm_sf2_sw_indir_rw(priv, 1, addr, regnum, 0);
+   else
+   return mdiobus_read(priv->master_mii_bus, addr, regnum);
+}
+
+static int bcm_sf2_sw_mdio_write(struct mii_bus *bus, int addr, int regnum,
+u16 val)
+{
+   struct bcm_sf2_priv *priv = bus->priv;
+
+   /* Intercept writes to the Broadcom pseudo-PHY address, else,
+* send them to our master MDIO bus controller
+*/
+   if (addr == BRCM_PSEUDO_PHY_ADDR && priv->indir_phy_mask & BIT(addr))
+   bcm_sf2_sw_indir_rw(priv, 0, addr, regnum, val);
+   else
+   mdiobus_write(priv->master_mii_bus, addr, regnum, val);
+
+   return 0;
+}
+
 static irqreturn_t bcm_sf2_switch_0_isr(int irq, void *dev_id)
 {
struct bcm_sf2_priv *priv = dev_id;
@@ -932,6 +993,72 @@ static void bcm_sf2_identify_ports(struct bcm_sf2_priv 
*priv,
}
 }
 
+static int bcm_sf2_mdio_register(struct dsa_switch *ds)
+{
+   struct bcm_sf2_priv *priv = ds_to_priv(ds);
+   struct device_node *dn;
+   static int index;
+   int err;
+
+   /* Find our integrated MDIO bus node */
+   dn = of_find_compatible_node(NULL, NULL, "brcm,unimac-mdio");
+   priv->master_mii_bus = of_mdio_find_bus(dn);
+   if (!priv->master_mii_bus)
+   return -EPROBE_DEFER;
+
+   get_device(>master_mii_bus->dev);
+   priv->master_mii_dn = dn;
+
+   priv->slave_mii_bus = devm_mdiobus_alloc(ds->dev);
+   if (!priv->slave_mii_bus)
+   return -ENOMEM;
+
+   priv->slave_mii_bus->priv = priv;
+   priv->slave_mii_bus->name = "sf2 slave mii";
+   priv->slave_mii_bus->read = bcm_sf2_sw_mdio_read;
+   priv->slave_mii_bus->write = bcm_sf2_sw_mdio_write;
+   snprintf(priv->slave_mii_bus->id, MII_BUS_ID_SIZE, "sf2-%d",
+index++);
+   priv->slave_mii_bus->dev.of_node = dn;
+
+   /* Include the pseudo-PHY address to divert reads towards our
+* workaround. This is only required for 7445D0, since 7445E0
+* disconnects the internal switch pseudo-PHY such that we can use the
+* regular SWITCH_MDIO master controller instead.
+*
+* Here we flag the pseudo PHY as needing special treatment and would
+* otherwise make all other PHY read/writes go to the master MDIO bus
+* controller that comes with this switch backed by the "

[PATCH net-next v4 5/6] net: dsa: Initialize CPU port ethtool ops per tree

2016-06-07 Thread Florian Fainelli
Now that we can properly support multiple distinct trees in the system,
using a global variable: dsa_cpu_port_ethtool_ops is getting clobbered
as soon as the second switch tree gets probed, and we don't want that.

We need to move this to be dynamically allocated, and since we can't
really be comparing addresses anymore to determine first time
initialization versus any other times, just move this to dsa.c and
dsa2.c where the remainder of the dst/ds initialization happens.

The operations teardown restores the master netdev's ethtool_ops to its
original ethtool_ops pointer (typically within the Ethernet driver)

Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 include/net/dsa.h  |  1 +
 net/dsa/dsa.c  | 41 +
 net/dsa/dsa2.c |  6 ++
 net/dsa/dsa_priv.h |  2 ++
 net/dsa/slave.c| 10 --
 5 files changed, 50 insertions(+), 10 deletions(-)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index cca7ef230742..20b3087ad193 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -116,6 +116,7 @@ struct dsa_switch_tree {
 * Original copy of the master netdev ethtool_ops
 */
struct ethtool_ops  master_ethtool_ops;
+   const struct ethtool_ops *master_orig_ethtool_ops;
 
/*
 * The switch and port to which the CPU is attached.
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index ce3b942dce76..766d2a525ada 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -266,6 +266,41 @@ const struct dsa_device_ops *dsa_resolve_tag_protocol(int 
tag_protocol)
return ops;
 }
 
+int dsa_cpu_port_ethtool_setup(struct dsa_switch *ds)
+{
+   struct net_device *master;
+   struct ethtool_ops *cpu_ops;
+
+   master = ds->dst->master_netdev;
+   if (ds->master_netdev)
+   master = ds->master_netdev;
+
+   cpu_ops = devm_kzalloc(ds->dev, sizeof(*cpu_ops), GFP_KERNEL);
+   if (!cpu_ops)
+   return -ENOMEM;
+
+   memcpy(>dst->master_ethtool_ops, master->ethtool_ops,
+  sizeof(struct ethtool_ops));
+   ds->dst->master_orig_ethtool_ops = master->ethtool_ops;
+   memcpy(cpu_ops, >dst->master_ethtool_ops,
+  sizeof(struct ethtool_ops));
+   dsa_cpu_port_ethtool_init(cpu_ops);
+   master->ethtool_ops = cpu_ops;
+
+   return 0;
+}
+
+void dsa_cpu_port_ethtool_restore(struct dsa_switch *ds)
+{
+   struct net_device *master;
+
+   master = ds->dst->master_netdev;
+   if (ds->master_netdev)
+   master = ds->master_netdev;
+
+   master->ethtool_ops = ds->dst->master_orig_ethtool_ops;
+}
+
 static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
 {
struct dsa_switch_driver *drv = ds->drv;
@@ -379,6 +414,10 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, 
struct device *parent)
ret = 0;
}
 
+   ret = dsa_cpu_port_ethtool_setup(ds);
+   if (ret)
+   return ret;
+
 #ifdef CONFIG_NET_DSA_HWMON
/* If the switch provides a temperature sensor,
 * register with hardware monitoring subsystem.
@@ -963,6 +1002,8 @@ static void dsa_remove_dst(struct dsa_switch_tree *dst)
dsa_switch_destroy(ds);
}
 
+   dsa_cpu_port_ethtool_restore(dst->ds[0]);
+
dev_put(dst->master_netdev);
 }
 
diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index 4e0f3c268103..83b95fc4cede 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -394,6 +394,10 @@ static int dsa_dst_apply(struct dsa_switch_tree *dst)
return err;
}
 
+   err = dsa_cpu_port_ethtool_setup(dst->ds[0]);
+   if (err)
+   return err;
+
/* If we use a tagging format that doesn't have an ethertype
 * field, make sure that all packets from this point on get
 * sent to the tag format's receive function.
@@ -429,6 +433,8 @@ static void dsa_dst_unapply(struct dsa_switch_tree *dst)
dsa_ds_unapply(dst, ds);
}
 
+   dsa_cpu_port_ethtool_restore(dst->ds[0]);
+
pr_info("DSA: tree %d unapplied\n", dst->tree);
dst->applied = false;
 }
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 106a9f067f94..00077a9c97f4 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -54,6 +54,8 @@ int dsa_cpu_dsa_setup(struct dsa_switch *ds, struct device 
*dev,
  struct device_node *port_dn, int port);
 void dsa_cpu_dsa_destroy(struct device_node *port_dn);
 const struct dsa_device_ops *dsa_resolve_tag_protocol(int tag_protocol);
+int dsa_cpu_port_ethtool_setup(struct dsa_switch *ds);
+void dsa_cpu_port_ethtool_restore(struct dsa_switch *ds);
 
 /* slave.c */
 extern const struct dsa_device_ops notag_netdev_ops;
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 8d159932e082..7236eb26dc97 100644
--- a/net/dsa/sla

Re: [PATCH net-next v2 5/5] net: dsa: bcm_sf2: Register our slave MDIO bus

2016-06-07 Thread Florian Fainelli
On 06/07/2016 12:11 PM, Vivien Didelot wrote:
> Hi Andrew,
> 
> Andrew Lunn  writes:
> 
 With the legacy interface it is tricky. When would you call such a
 remove/tairdown function when using the old binding?
>>>
>>> That'd go in dsa_switch_destroy I guess, but it just covers the case
>>> where the whole DSA code is unloaded...
>>
>> I don't think that helps you. It should not be possible to unload the
>> DSA core while there is an active driver. The drivers needs to unload
>> first
> 
> Well, dsa_switch_destroy() is where ds->slave_mii_bus gets unregistered
> (if registered by the framework), so it seems fair to do something like:
> 
> if (ds->drv->shutdown)
> ds->drv->shutdown(ds);
> 
> But I'm still not sure if it is worth it to add a new legacy specific
> function to DSA drivers, unless there is a use case for such optional
> teardown callback for the new bindings too.

The new binding requires the use of dsa_unregister_switch() so this is
where all the teardown and resource freeing should occur.

I do not really think it is worth trying to fix the old binding and
support code now, unless we want to migrate it somehow to using the code
from net/dsa/dsa2.c.
-- 
Florian


[PATCH net-next v3 6/6] net: dsa: bcm_sf2: Register our slave MDIO bus

2016-06-07 Thread Florian Fainelli
Register a slave MDIO bus which allows us to divert problematic
read/writes towards conflicting pseudo-PHY address (30). Do no longer
rely on DSA's slave_mii_bus, but instead provide our own implementation
which offers more flexibility as to what to do, and when to register it.

We need to register it by the time we are able to get access to our
memory mapped registers, which is not until drv->setup() time. In order
to avoid forward declarations, we need to re-order the function bodies a
bit.

Reviewed-by: Andrew Lunn <and...@lunn.ch>
Reviewed-by: Vivien Didelot <vivien.dide...@savoirfairelinux.com>
Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 drivers/net/dsa/bcm_sf2.c | 215 +-
 drivers/net/dsa/bcm_sf2.h |   6 ++
 2 files changed, 140 insertions(+), 81 deletions(-)

diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 73df91bb0466..d6625783703f 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -836,6 +837,66 @@ static int bcm_sf2_sw_fdb_dump(struct dsa_switch *ds, int 
port,
return 0;
 }
 
+static int bcm_sf2_sw_indir_rw(struct bcm_sf2_priv *priv, int op, int addr,
+  int regnum, u16 val)
+{
+   int ret = 0;
+   u32 reg;
+
+   reg = reg_readl(priv, REG_SWITCH_CNTRL);
+   reg |= MDIO_MASTER_SEL;
+   reg_writel(priv, reg, REG_SWITCH_CNTRL);
+
+   /* Page << 8 | offset */
+   reg = 0x70;
+   reg <<= 2;
+   core_writel(priv, addr, reg);
+
+   /* Page << 8 | offset */
+   reg = 0x80 << 8 | regnum << 1;
+   reg <<= 2;
+
+   if (op)
+   ret = core_readl(priv, reg);
+   else
+   core_writel(priv, val, reg);
+
+   reg = reg_readl(priv, REG_SWITCH_CNTRL);
+   reg &= ~MDIO_MASTER_SEL;
+   reg_writel(priv, reg, REG_SWITCH_CNTRL);
+
+   return ret & 0x;
+}
+
+static int bcm_sf2_sw_mdio_read(struct mii_bus *bus, int addr, int regnum)
+{
+   struct bcm_sf2_priv *priv = bus->priv;
+
+   /* Intercept reads from Broadcom pseudo-PHY address, else, send
+* them to our master MDIO bus controller
+*/
+   if (addr == BRCM_PSEUDO_PHY_ADDR && priv->indir_phy_mask & BIT(addr))
+   return bcm_sf2_sw_indir_rw(priv, 1, addr, regnum, 0);
+   else
+   return mdiobus_read(priv->master_mii_bus, addr, regnum);
+}
+
+static int bcm_sf2_sw_mdio_write(struct mii_bus *bus, int addr, int regnum,
+u16 val)
+{
+   struct bcm_sf2_priv *priv = bus->priv;
+
+   /* Intercept writes to the Broadcom pseudo-PHY address, else,
+* send them to our master MDIO bus controller
+*/
+   if (addr == BRCM_PSEUDO_PHY_ADDR && priv->indir_phy_mask & BIT(addr))
+   bcm_sf2_sw_indir_rw(priv, 0, addr, regnum, val);
+   else
+   mdiobus_write(priv->master_mii_bus, addr, regnum, val);
+
+   return 0;
+}
+
 static irqreturn_t bcm_sf2_switch_0_isr(int irq, void *dev_id)
 {
struct bcm_sf2_priv *priv = dev_id;
@@ -932,6 +993,72 @@ static void bcm_sf2_identify_ports(struct bcm_sf2_priv 
*priv,
}
 }
 
+static int bcm_sf2_mdio_register(struct dsa_switch *ds)
+{
+   struct bcm_sf2_priv *priv = ds_to_priv(ds);
+   struct device_node *dn;
+   static int index;
+   int err;
+
+   /* Find our integrated MDIO bus node */
+   dn = of_find_compatible_node(NULL, NULL, "brcm,unimac-mdio");
+   priv->master_mii_bus = of_mdio_find_bus(dn);
+   if (!priv->master_mii_bus)
+   return -EPROBE_DEFER;
+
+   get_device(>master_mii_bus->dev);
+   priv->master_mii_dn = dn;
+
+   priv->slave_mii_bus = devm_mdiobus_alloc(ds->dev);
+   if (!priv->slave_mii_bus)
+   return -ENOMEM;
+
+   priv->slave_mii_bus->priv = priv;
+   priv->slave_mii_bus->name = "sf2 slave mii";
+   priv->slave_mii_bus->read = bcm_sf2_sw_mdio_read;
+   priv->slave_mii_bus->write = bcm_sf2_sw_mdio_write;
+   snprintf(priv->slave_mii_bus->id, MII_BUS_ID_SIZE, "sf2-%d",
+index++);
+   priv->slave_mii_bus->dev.of_node = dn;
+
+   /* Include the pseudo-PHY address to divert reads towards our
+* workaround. This is only required for 7445D0, since 7445E0
+* disconnects the internal switch pseudo-PHY such that we can use the
+* regular SWITCH_MDIO master controller instead.
+*
+* Here we flag the pseudo PHY as needing special treatment and would
+* otherwise make all other PHY read/writes go to the master MDIO bus
+* controller that comes with this switch backed by the "

[PATCH net-next v3 5/6] net: dsa: Initialize CPU port ethtool ops per tree

2016-06-07 Thread Florian Fainelli
Now that we can properly support multiple distinct trees in the system,
using a global variable: dsa_cpu_port_ethtool_ops is getting clobbered
as soon as the second switch tree gets probed, and we don't want that.

We need to move this to be dynamically allocated, and since we can't
really be comparing addresses anymore to determine first time
initialization versus any other times, just move this to dsa.c and
dsa2.c where the remainder of the dst/ds initialization happens.

The operations teardown restores the master netdev's ethtool_ops to its
original ethtool_ops pointer (typically within the Ethernet driver)

Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 include/net/dsa.h  |  1 +
 net/dsa/dsa.c  | 43 +++
 net/dsa/dsa2.c |  6 ++
 net/dsa/dsa_priv.h |  4 
 net/dsa/slave.c| 10 --
 5 files changed, 54 insertions(+), 10 deletions(-)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index cca7ef230742..20b3087ad193 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -116,6 +116,7 @@ struct dsa_switch_tree {
 * Original copy of the master netdev ethtool_ops
 */
struct ethtool_ops  master_ethtool_ops;
+   const struct ethtool_ops *master_orig_ethtool_ops;
 
/*
 * The switch and port to which the CPU is attached.
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index ce3b942dce76..80f930d38df1 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -266,6 +266,43 @@ const struct dsa_device_ops *dsa_resolve_tag_protocol(int 
tag_protocol)
return ops;
 }
 
+int dsa_cpu_port_ethtool_setup(struct dsa_switch_tree *dst,
+  struct dsa_switch *ds)
+{
+   struct net_device *master;
+   struct ethtool_ops *cpu_ops;
+
+   master = ds->dst->master_netdev;
+   if (ds->master_netdev)
+   master = ds->master_netdev;
+
+   cpu_ops = devm_kzalloc(ds->dev, sizeof(*cpu_ops), GFP_KERNEL);
+   if (!cpu_ops)
+   return -ENOMEM;
+
+   memcpy(>master_ethtool_ops, master->ethtool_ops,
+  sizeof(struct ethtool_ops));
+   dst->master_orig_ethtool_ops = master->ethtool_ops;
+   memcpy(cpu_ops, >master_ethtool_ops,
+  sizeof(struct ethtool_ops));
+   dsa_cpu_port_ethtool_init(cpu_ops);
+   master->ethtool_ops = cpu_ops;
+
+   return 0;
+}
+
+void dsa_cpu_port_ethtool_restore(struct dsa_switch_tree *dst,
+ struct dsa_switch *ds)
+{
+   struct net_device *master;
+
+   master = ds->dst->master_netdev;
+   if (ds->master_netdev)
+   master = ds->master_netdev;
+
+   master->ethtool_ops = dst->master_orig_ethtool_ops;
+}
+
 static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
 {
struct dsa_switch_driver *drv = ds->drv;
@@ -379,6 +416,10 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, 
struct device *parent)
ret = 0;
}
 
+   ret = dsa_cpu_port_ethtool_setup(dst, ds);
+   if (ret)
+   return ret;
+
 #ifdef CONFIG_NET_DSA_HWMON
/* If the switch provides a temperature sensor,
 * register with hardware monitoring subsystem.
@@ -963,6 +1004,8 @@ static void dsa_remove_dst(struct dsa_switch_tree *dst)
dsa_switch_destroy(ds);
}
 
+   dsa_cpu_port_ethtool_restore(dst, dst->ds[0]);
+
dev_put(dst->master_netdev);
 }
 
diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index 4e0f3c268103..7ffee268a526 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -394,6 +394,10 @@ static int dsa_dst_apply(struct dsa_switch_tree *dst)
return err;
}
 
+   err = dsa_cpu_port_ethtool_setup(dst, dst->ds[0]);
+   if (err)
+   return err;
+
/* If we use a tagging format that doesn't have an ethertype
 * field, make sure that all packets from this point on get
 * sent to the tag format's receive function.
@@ -429,6 +433,8 @@ static void dsa_dst_unapply(struct dsa_switch_tree *dst)
dsa_ds_unapply(dst, ds);
}
 
+   dsa_cpu_port_ethtool_restore(dst, dst->ds[0]);
+
pr_info("DSA: tree %d unapplied\n", dst->tree);
dst->applied = false;
 }
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 106a9f067f94..9c920c27f22c 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -54,6 +54,10 @@ int dsa_cpu_dsa_setup(struct dsa_switch *ds, struct device 
*dev,
  struct device_node *port_dn, int port);
 void dsa_cpu_dsa_destroy(struct device_node *port_dn);
 const struct dsa_device_ops *dsa_resolve_tag_protocol(int tag_protocol);
+int dsa_cpu_port_ethtool_setup(struct dsa_switch_tree *dst,
+  struct dsa_switch *ds);
+void dsa_cpu_port_ethtool_restore(struct dsa_switch_tree 

[PATCH net-next v3 0/6] net: dsa: misc improvements

2016-06-07 Thread Florian Fainelli
Hi all,

This patch series builds on top of Andrew's "New DSA bind, switches as devices"
patch set and does the following:

- add a few helper functions/goodies for net/dsa/dsa2.c to be as close as 
possible
  from net/dsa/dsa.c in terms of what drivers can expect, in particular the 
slave
  MDIO bus and the enabled_port_mask and phy_mii_mask

- fix the CPU port ethtools ops to work in a multiple tree setup since we can
  no longer assume a single tree is supported

- make the bcm_sf2 driver register its own MDIO bus, yet assign it to
  ds->slave_mii_bus for everything to work in net/dsa/slave.c wrt. PHY probing,
  this is a tad cleaner than what we have now

Changes in v2:

Most of the previous patches have been dropped to just keep the relevant ones
now.

Changes in v3:
- split the addition of the slave MII bus as a separate patch
- properly unwind all operations at the right place and right time (ethtool ops,
  slave MDIO bus
- fixed a few typos here and there

Florian Fainelli (6):
  net: dsa: Provide unique DSA slave MII bus names
  net: dsa: Initialize ds->enabled_port_mask and ds->phys_mii_mask
  net: dsa: Provide a slave MII bus if needed
  net: dsa: Add initialization helper for CPU port ethtool_ops
  net: dsa: Initialize CPU port ethtool ops per tree
  net: dsa: bcm_sf2: Register our slave MDIO bus

 drivers/net/dsa/bcm_sf2.c | 215 +-
 drivers/net/dsa/bcm_sf2.h |   6 ++
 include/net/dsa.h |   1 +
 net/dsa/dsa.c |  41 +
 net/dsa/dsa2.c|  36 
 net/dsa/dsa_priv.h|   5 ++
 net/dsa/slave.c   |  25 ++
 7 files changed, 232 insertions(+), 97 deletions(-)

-- 
2.7.4



[PATCH net-next v3 2/6] net: dsa: Initialize ds->enabled_port_mask and ds->phys_mii_mask

2016-06-07 Thread Florian Fainelli
Some drivers rely on these two bitmasks to contain the correct values
for them to successfully probe and initialize at drv->setup() time,
calculate correct values to put in both masks as early as possible in
dsa_get_ports_dn().

Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 net/dsa/dsa2.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index 80dfe08db825..921a36fd139d 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -283,6 +283,7 @@ static void dsa_user_port_unapply(struct device_node *port, 
u32 index,
if (ds->ports[index].netdev) {
dsa_slave_destroy(ds->ports[index].netdev);
ds->ports[index].netdev = NULL;
+   ds->enabled_port_mask &= ~(1 << index);
}
 }
 
@@ -292,6 +293,13 @@ static int dsa_ds_apply(struct dsa_switch_tree *dst, 
struct dsa_switch *ds)
u32 index;
int err;
 
+   /* Initialize ds->phys_mii_mask before registering the slave MDIO bus
+* driver and before drv->setup() has run, since the switch drivers and
+* the slave MDIO bus driver rely on these values for probing PHY
+* devices or not
+*/
+   ds->phys_mii_mask = ds->enabled_port_mask;
+
err = ds->drv->setup(ds);
if (err < 0)
return err;
@@ -511,6 +519,13 @@ static int dsa_parse_ports_dn(struct device_node *ports, 
struct dsa_switch *ds)
return -EINVAL;
 
ds->ports[reg].dn = port;
+
+   /* Initialize enabled_port_mask now for drv->setup()
+* to have access to a correct value, just like what
+* net/dsa/dsa.c::dsa_switch_setup_one does.
+*/
+   if (!dsa_port_is_cpu(port))
+   ds->enabled_port_mask |= 1 << reg;
}
 
return 0;
-- 
2.7.4



[PATCH net-next v3 1/6] net: dsa: Provide unique DSA slave MII bus names

2016-06-07 Thread Florian Fainelli
In case we have multiples trees and switches with the same index, we
need to add another discriminating id: the switch tree.

Reviewed-by: Andrew Lunn <and...@lunn.ch>
Reviewed-by: Vivien Didelot <vivien.dide...@savoirfairelinux.com>
Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 net/dsa/slave.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 15a492261895..a51dfedf0014 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -49,7 +49,8 @@ void dsa_slave_mii_bus_init(struct dsa_switch *ds)
ds->slave_mii_bus->name = "dsa slave smi";
ds->slave_mii_bus->read = dsa_slave_phy_read;
ds->slave_mii_bus->write = dsa_slave_phy_write;
-   snprintf(ds->slave_mii_bus->id, MII_BUS_ID_SIZE, "dsa-%d", ds->index);
+   snprintf(ds->slave_mii_bus->id, MII_BUS_ID_SIZE, "dsa-%d.%d",
+ds->dst->tree, ds->index);
ds->slave_mii_bus->parent = ds->dev;
ds->slave_mii_bus->phy_mask = ~ds->phys_mii_mask;
 }
-- 
2.7.4



[PATCH net-next v3 3/6] net: dsa: Provide a slave MII bus if needed

2016-06-07 Thread Florian Fainelli
Mimic what net/dsa/dsa.c does and provide a slave MII bus by default
which will be created if the driver implements a phy_read method.

Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 net/dsa/dsa2.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index 921a36fd139d..4e0f3c268103 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -312,6 +312,18 @@ static int dsa_ds_apply(struct dsa_switch_tree *dst, 
struct dsa_switch *ds)
if (err < 0)
return err;
 
+   if (!ds->slave_mii_bus && ds->drv->phy_read) {
+   ds->slave_mii_bus = devm_mdiobus_alloc(ds->dev);
+   if (!ds->slave_mii_bus)
+   return -ENOMEM;
+
+   dsa_slave_mii_bus_init(ds);
+
+   err = mdiobus_register(ds->slave_mii_bus);
+   if (err < 0)
+   return err;
+   }
+
for (index = 0; index < DSA_MAX_PORTS; index++) {
port = ds->ports[index].dn;
if (!port)
@@ -361,6 +373,9 @@ static void dsa_ds_unapply(struct dsa_switch_tree *dst, 
struct dsa_switch *ds)
 
dsa_user_port_unapply(port, index, ds);
}
+
+   if (ds->slave_mii_bus && ds->drv->phy_read)
+   mdiobus_unregister(ds->slave_mii_bus);
 }
 
 static int dsa_dst_apply(struct dsa_switch_tree *dst)
-- 
2.7.4



[PATCH net-next v3 4/6] net: dsa: Add initialization helper for CPU port ethtool_ops

2016-06-07 Thread Florian Fainelli
Add a helper function: dsa_cpu_port_ethtool_init() which initializes a
custom ethtool_ops structure with custom DSA ethtool operations for CPU
ports. This is a preliminary change to move the initialization outside
of net/dsa/slave.c.

Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 net/dsa/dsa_priv.h |  1 +
 net/dsa/slave.c| 14 --
 2 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index b42f1a5f95f3..106a9f067f94 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -58,6 +58,7 @@ const struct dsa_device_ops *dsa_resolve_tag_protocol(int 
tag_protocol);
 /* slave.c */
 extern const struct dsa_device_ops notag_netdev_ops;
 void dsa_slave_mii_bus_init(struct dsa_switch *ds);
+void dsa_cpu_port_ethtool_init(struct ethtool_ops *ops);
 int dsa_slave_create(struct dsa_switch *ds, struct device *parent,
 int port, const char *name);
 void dsa_slave_destroy(struct net_device *slave_dev);
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index a51dfedf0014..8d159932e082 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -865,6 +865,13 @@ static void dsa_slave_poll_controller(struct net_device 
*dev)
 }
 #endif
 
+void dsa_cpu_port_ethtool_init(struct ethtool_ops *ops)
+{
+   ops->get_sset_count = dsa_cpu_port_get_sset_count;
+   ops->get_ethtool_stats = dsa_cpu_port_get_ethtool_stats;
+   ops->get_strings = dsa_cpu_port_get_strings;
+}
+
 static const struct ethtool_ops dsa_slave_ethtool_ops = {
.get_settings   = dsa_slave_get_settings,
.set_settings   = dsa_slave_set_settings,
@@ -1124,12 +1131,7 @@ int dsa_slave_create(struct dsa_switch *ds, struct 
device *parent,
   sizeof(struct ethtool_ops));
memcpy(_cpu_port_ethtool_ops, >master_ethtool_ops,
   sizeof(struct ethtool_ops));
-   dsa_cpu_port_ethtool_ops.get_sset_count =
-   dsa_cpu_port_get_sset_count;
-   dsa_cpu_port_ethtool_ops.get_ethtool_stats =
-   dsa_cpu_port_get_ethtool_stats;
-   dsa_cpu_port_ethtool_ops.get_strings =
-   dsa_cpu_port_get_strings;
+   dsa_cpu_port_ethtool_init(_cpu_port_ethtool_ops);
master->ethtool_ops = _cpu_port_ethtool_ops;
}
eth_hw_addr_inherit(slave_dev, master);
-- 
2.7.4



[PATCH net-next v2 1/3] bgmac: Bind net_device with backing device structure

2016-06-07 Thread Florian Fainelli
In preparation for allowing different helpers to be utilized against
network devices created by the bgmac driver, make sure that we bind the
net_device with core->dev.

Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 drivers/net/ethernet/broadcom/bgmac.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/ethernet/broadcom/bgmac.c 
b/drivers/net/ethernet/broadcom/bgmac.c
index ee5f431ab32a..156fa6323745 100644
--- a/drivers/net/ethernet/broadcom/bgmac.c
+++ b/drivers/net/ethernet/broadcom/bgmac.c
@@ -1588,6 +1588,7 @@ static int bgmac_probe(struct bcma_device *core)
bgmac->net_dev = net_dev;
bgmac->core = core;
bcma_set_drvdata(core, bgmac);
+   SET_NETDEV_DEV(net_dev, >dev);
 
/* Defaults */
memcpy(bgmac->net_dev->dev_addr, mac, ETH_ALEN);
-- 
2.7.4



[PATCH net-next v2 2/3] bgmac: Add support for ethtool statistics

2016-06-07 Thread Florian Fainelli
Read the statistics from the BGMAC's builtin MAC and return them to
user-space using the standard ethtool helpers.

Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
Changes in v2:
- use strlcpy()
- properly fix the latching of the hi/lo reads
- remove redundant cast

 drivers/net/ethernet/broadcom/bgmac.c | 124 ++
 drivers/net/ethernet/broadcom/bgmac.h |   4 +-
 2 files changed, 126 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bgmac.c 
b/drivers/net/ethernet/broadcom/bgmac.c
index 156fa6323745..133bf64c7a8b 100644
--- a/drivers/net/ethernet/broadcom/bgmac.c
+++ b/drivers/net/ethernet/broadcom/bgmac.c
@@ -1382,6 +1382,127 @@ static const struct net_device_ops bgmac_netdev_ops = {
  * ethtool_ops
  **/
 
+struct bgmac_stat {
+   u8 size;
+   u32 offset;
+   const char *name;
+};
+
+static struct bgmac_stat bgmac_get_strings_stats[] = {
+   { 8, BGMAC_TX_GOOD_OCTETS, "tx_good_octets" },
+   { 4, BGMAC_TX_GOOD_PKTS, "tx_good" },
+   { 8, BGMAC_TX_OCTETS, "tx_octets" },
+   { 4, BGMAC_TX_PKTS, "tx_pkts" },
+   { 4, BGMAC_TX_BROADCAST_PKTS, "tx_broadcast" },
+   { 4, BGMAC_TX_MULTICAST_PKTS, "tx_multicast" },
+   { 4, BGMAC_TX_LEN_64, "tx_64" },
+   { 4, BGMAC_TX_LEN_65_TO_127, "tx_65_127" },
+   { 4, BGMAC_TX_LEN_128_TO_255, "tx_128_255" },
+   { 4, BGMAC_TX_LEN_256_TO_511, "tx_256_511" },
+   { 4, BGMAC_TX_LEN_512_TO_1023, "tx_512_1023" },
+   { 4, BGMAC_TX_LEN_1024_TO_1522, "tx_1024_1522" },
+   { 4, BGMAC_TX_LEN_1523_TO_2047, "tx_1523_2047" },
+   { 4, BGMAC_TX_LEN_2048_TO_4095, "tx_2048_4095" },
+   { 4, BGMAC_TX_LEN_4096_TO_8191, "tx_4096_8191" },
+   { 4, BGMAC_TX_LEN_8192_TO_MAX, "tx_8192_max" },
+   { 4, BGMAC_TX_JABBER_PKTS, "tx_jabber" },
+   { 4, BGMAC_TX_OVERSIZE_PKTS, "tx_oversize" },
+   { 4, BGMAC_TX_FRAGMENT_PKTS, "tx_fragment" },
+   { 4, BGMAC_TX_UNDERRUNS, "tx_underruns" },
+   { 4, BGMAC_TX_TOTAL_COLS, "tx_total_cols" },
+   { 4, BGMAC_TX_SINGLE_COLS, "tx_single_cols" },
+   { 4, BGMAC_TX_MULTIPLE_COLS, "tx_multiple_cols" },
+   { 4, BGMAC_TX_EXCESSIVE_COLS, "tx_excessive_cols" },
+   { 4, BGMAC_TX_LATE_COLS, "tx_late_cols" },
+   { 4, BGMAC_TX_DEFERED, "tx_defered" },
+   { 4, BGMAC_TX_CARRIER_LOST, "tx_carrier_lost" },
+   { 4, BGMAC_TX_PAUSE_PKTS, "tx_pause" },
+   { 4, BGMAC_TX_UNI_PKTS, "tx_unicast" },
+   { 4, BGMAC_TX_Q0_PKTS, "tx_q0" },
+   { 8, BGMAC_TX_Q0_OCTETS, "tx_q0_octets" },
+   { 4, BGMAC_TX_Q1_PKTS, "tx_q1" },
+   { 8, BGMAC_TX_Q1_OCTETS, "tx_q1_octets" },
+   { 4, BGMAC_TX_Q2_PKTS, "tx_q2" },
+   { 8, BGMAC_TX_Q2_OCTETS, "tx_q2_octets" },
+   { 4, BGMAC_TX_Q3_PKTS, "tx_q3" },
+   { 8, BGMAC_TX_Q3_OCTETS, "tx_q3_octets" },
+   { 8, BGMAC_RX_GOOD_OCTETS, "rx_good_octets" },
+   { 4, BGMAC_RX_GOOD_PKTS, "rx_good" },
+   { 8, BGMAC_RX_OCTETS, "rx_octets" },
+   { 4, BGMAC_RX_PKTS, "rx_pkts" },
+   { 4, BGMAC_RX_BROADCAST_PKTS, "rx_broadcast" },
+   { 4, BGMAC_RX_MULTICAST_PKTS, "rx_multicast" },
+   { 4, BGMAC_RX_LEN_64, "rx_64" },
+   { 4, BGMAC_RX_LEN_65_TO_127, "rx_65_127" },
+   { 4, BGMAC_RX_LEN_128_TO_255, "rx_128_255" },
+   { 4, BGMAC_RX_LEN_256_TO_511, "rx_256_511" },
+   { 4, BGMAC_RX_LEN_512_TO_1023, "rx_512_1023" },
+   { 4, BGMAC_RX_LEN_1024_TO_1522, "rx_1024_1522" },
+   { 4, BGMAC_RX_LEN_1523_TO_2047, "rx_1523_2047" },
+   { 4, BGMAC_RX_LEN_2048_TO_4095, "rx_2048_4095" },
+   { 4, BGMAC_RX_LEN_4096_TO_8191, "rx_4096_8191" },
+   { 4, BGMAC_RX_LEN_8192_TO_MAX, "rx_8192_max" },
+   { 4, BGMAC_RX_JABBER_PKTS, "rx_jabber" },
+   { 4, BGMAC_RX_OVERSIZE_PKTS, "rx_oversize" },
+   { 4, BGMAC_RX_FRAGMENT_PKTS, "rx_fragment" },
+   { 4, BGMAC_RX_MISSED_PKTS, "rx_missed" },
+   { 4, BGMAC_RX_CRC_ALIGN_ERRS, "rx_crc_align" },
+   { 4, BGMAC_RX_UNDERSIZE, "rx_undersize" },
+   { 4, BGMAC_RX_CRC_ERRS, "rx_crc" },
+   { 4, BGMAC_RX_ALIGN_ERRS, "rx_align" },
+   { 4, BGMAC_RX_SYMBOL_ERRS, "rx_symbol" },
+   { 4, BGMAC_RX_PAUSE_PKTS, "rx_pause" },
+   { 4, BGMAC_RX_NONPAUSE_PKTS, "rx_nonpause" },
+   { 4, BGMAC_RX_SACHANGES, "

[PATCH net-next v2 0/3] net: bgmac: Misc improvements

2016-06-07 Thread Florian Fainelli
Hi David, Rafal, Hauke, Felix,

This patch series add minor changes to the bgmac driver:

- properly bind net_device with its backing device structure such that
  we can locate the device using common helper functions

- add support for ethtool statistics reading the HW MIB counters which
  is useful for debugging

- add netdev statistics throughout the TX/RX path to know what is going on

Thanks

Florian Fainelli (3):
  bgmac: Bind net_device with backing device structure
  bgmac: Add support for ethtool statistics
  bgmac: Maintain some netdev statistics

 drivers/net/ethernet/broadcom/bgmac.c | 135 ++
 drivers/net/ethernet/broadcom/bgmac.h |   4 +-
 2 files changed, 137 insertions(+), 2 deletions(-)

-- 
2.7.4



[PATCH net-next v2 3/3] bgmac: Maintain some netdev statistics

2016-06-07 Thread Florian Fainelli
Add a few netdev statistics to report transmitted and received bytes and
packets and a few obvious errors.

Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 drivers/net/ethernet/broadcom/bgmac.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/drivers/net/ethernet/broadcom/bgmac.c 
b/drivers/net/ethernet/broadcom/bgmac.c
index 133bf64c7a8b..0ee34cc96bc9 100644
--- a/drivers/net/ethernet/broadcom/bgmac.c
+++ b/drivers/net/ethernet/broadcom/bgmac.c
@@ -246,6 +246,8 @@ err_dma_head:
 
 err_drop:
dev_kfree_skb(skb);
+   net_dev->stats.tx_dropped++;
+   net_dev->stats.tx_errors++;
return NETDEV_TX_OK;
 }
 
@@ -284,6 +286,8 @@ static void bgmac_dma_tx_free(struct bgmac *bgmac, struct 
bgmac_dma_ring *ring)
   DMA_TO_DEVICE);
 
if (slot->skb) {
+   bgmac->net_dev->stats.tx_bytes += slot->skb->len;
+   bgmac->net_dev->stats.tx_packets++;
bytes_compl += slot->skb->len;
pkts_compl++;
 
@@ -464,6 +468,7 @@ static int bgmac_dma_rx_read(struct bgmac *bgmac, struct 
bgmac_dma_ring *ring,
bgmac_err(bgmac, "Found poisoned packet at slot 
%d, DMA issue!\n",
  ring->start);
put_page(virt_to_head_page(buf));
+   bgmac->net_dev->stats.rx_errors++;
break;
}
 
@@ -471,6 +476,8 @@ static int bgmac_dma_rx_read(struct bgmac *bgmac, struct 
bgmac_dma_ring *ring,
bgmac_err(bgmac, "Found oversized packet at 
slot %d, DMA issue!\n",
  ring->start);
put_page(virt_to_head_page(buf));
+   bgmac->net_dev->stats.rx_length_errors++;
+   bgmac->net_dev->stats.rx_errors++;
break;
}
 
@@ -481,6 +488,7 @@ static int bgmac_dma_rx_read(struct bgmac *bgmac, struct 
bgmac_dma_ring *ring,
if (unlikely(!skb)) {
bgmac_err(bgmac, "build_skb failed\n");
put_page(virt_to_head_page(buf));
+   bgmac->net_dev->stats.rx_errors++;
break;
}
skb_put(skb, BGMAC_RX_FRAME_OFFSET +
@@ -490,6 +498,8 @@ static int bgmac_dma_rx_read(struct bgmac *bgmac, struct 
bgmac_dma_ring *ring,
 
skb_checksum_none_assert(skb);
skb->protocol = eth_type_trans(skb, bgmac->net_dev);
+   bgmac->net_dev->stats.rx_bytes += len;
+   bgmac->net_dev->stats.rx_packets++;
napi_gro_receive(>napi, skb);
handled++;
} while (0);
-- 
2.7.4



Re: [PATCH net-next v3 5/6] net: dsa: Initialize CPU port ethtool ops per tree

2016-06-07 Thread Florian Fainelli
On 06/07/2016 02:51 PM, Andrew Lunn wrote:
>> +int dsa_cpu_port_ethtool_setup(struct dsa_switch_tree *dst,
>> +   struct dsa_switch *ds)
>> +{
>> +struct net_device *master;
>> +struct ethtool_ops *cpu_ops;
>> +
>> +master = ds->dst->master_netdev;
> 
> You pass in dst as a parameter, and then don't use it!

I do use it here:

memcpy(>master_ethtool_ops, master->ethtool_ops,
   sizeof(struct ethtool_ops));

> 
>> +void dsa_cpu_port_ethtool_restore(struct dsa_switch_tree *dst,
>> +  struct dsa_switch *ds)
>> +{
>> +struct net_device *master;
>> +
>> +master = ds->dst->master_netdev;
> 
> Same here.

and here:

master->ethtool_ops = dst->master_orig_ethtool_ops;

I sure could simplify that and use ds->dst instead if you find it more
elegant, works for me.
-- 
Florian


Re: [PATCH v4 7/7] phy: Add Northstar2 PCI Phy support

2016-06-06 Thread Florian Fainelli
On 06/06/2016 05:41 AM, Pramod Kumar wrote:
> Add PCI Phy support for Broadcom Northstar2 SoCs.  This driver uses the
> interface from the iproc mdio mux driver to enable the devices
> respective phys.
> 
> Reviewed-by: Andrew Lunn 
> Signed-off-by: Jon Mason 
> Signed-off-by: Pramod Kumar 
> ---
>  drivers/phy/Kconfig|   8 +++
>  drivers/phy/Makefile   |   2 +-
>  drivers/phy/phy-bcm-ns2-pcie.c | 115 
> +
>  3 files changed, 124 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/phy/phy-bcm-ns2-pcie.c
> 
> diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
> index b869b98..01fb93b 100644
> --- a/drivers/phy/Kconfig
> +++ b/drivers/phy/Kconfig
> @@ -434,4 +434,12 @@ config PHY_CYGNUS_PCIE
>  
>  source "drivers/phy/tegra/Kconfig"
>  
> +config PHY_NS2_PCIE
> + tristate "Broadcom Northstar2 PCIe PHY driver"
> + depends on OF && MDIO_BUS_MUX_BCM_IPROC
> + select GENERIC_PHY
> + default ARCH_BCM_IPROC

Are not you missing a dependency on PHYLIB too to provide
mdio_module_register() etc. (at least make it build)?

-- 
Florian


Re: [PATCH v4 3/7] binding: mdio-mux: Add DT binding doc for Broadcom MDIO bus multiplexer

2016-06-06 Thread Florian Fainelli
On 06/06/2016 05:41 AM, Pramod Kumar wrote:
> Add DT binding doc for Broadcom MDIO bus multiplexer driver.
> 
> Reviewed-by: Andrew Lunn <and...@lunn.ch>
> Signed-off-by: Pramod Kumar <pramod.ku...@broadcom.com>

Reviewed-by: Florian Fainelli <f.faine...@gmail.com>


> +for example:
> + mdio_mux_iproc: mdio-mux@6602023c {

I think Rob wanted you to drop the underscores here in favor of dashes,
there are more below, not critical imho.

> + compatible = "brcm,mdio-mux-iproc";
> + reg = <0x6602023c 0x14>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + mdio@0 {
> + reg = <0x0>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + pci_phy0: pci-phy@0 {


-- 
Florian


Re: [PATCH v4 4/7] dt: mdio-mux: Add mdio multiplexer driver node

2016-06-06 Thread Florian Fainelli
On 06/06/2016 05:41 AM, Pramod Kumar wrote:
> Add integrated MDIO multiplexer driver node which contains
> two mux PCIe bus and one ethernet bus along with phys
> lying on these bus.
> 
> Signed-off-by: Pramod Kumar 
> ---
> + mdio_mux_iproc: mdio-mux@6602023c {
> + compatible = "brcm,mdio-mux-iproc";
> + reg = <0x6602023c 0x14>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + mdio@0 {
> + reg = <0x0>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + pci_phy0: pci-phy@0 {
> + compatible = "brcm,ns2-pcie-phy";
> + reg = <0x0>;
> + #phy-cells = <0>;
> + };
> + };
> +
> + mdio@7 {
> + reg = <0x7>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + pci_phy1: pci-phy@0 {
> + compatible = "brcm,ns2-pcie-phy";
> + reg = <0x0>;
> + #phy-cells = <0>;
> + };

Are these two PHYs always available in the NS2 SoC, or does that depend
on interfaces exposed at the board level? Should not they be flagged
with a disabled status property by default and enabled in their
respective board files?
-- 
Florian


Re: [PATCH v4 1/7] mdio: mux: Enhanced MDIO mux framework for integrated multiplexers

2016-06-06 Thread Florian Fainelli
On 06/06/2016 05:41 AM, Pramod Kumar wrote:
> An integrated multiplexer uses same address space for
> "muxed bus selection" and "generation of mdio transaction"
> hence its good to register parent bus from mux driver.
> 
> Hence added a mechanism where mux driver could register a
> parent bus and pass it down to framework via mdio_mux_init api.
> 
> Signed-off-by: Pramod Kumar <pramod.ku...@broadcom.com>

Reviewed-by: Florian Fainelli <f.faine...@gmail.com>


> diff --git a/include/linux/mdio-mux.h b/include/linux/mdio-mux.h
> index a243dbb..61f5b21 100644
> --- a/include/linux/mdio-mux.h
> +++ b/include/linux/mdio-mux.h
> @@ -10,11 +10,13 @@
>  #ifndef __LINUX_MDIO_MUX_H
>  #define __LINUX_MDIO_MUX_H
>  #include 
> +#include 

You could have added just a forward declaration, this is a pointer to
the structure so you don't need the compiler to have full knowledge of
the storage type. Not a biggie.
-- 
Florian


Re: [PATCH 1/5] ethernet: add sun8i-emac driver

2016-06-06 Thread Florian Fainelli
On 06/03/2016 02:56 AM, LABBE Corentin wrote:
> This patch add support for sun8i-emac ethernet MAC hardware.
> It could be found in Allwinner H3/A83T/A64 SoCs.
> 
> It supports 10/100/1000 Mbit/s speed with half/full duplex.
> It can use an internal PHY (MII 10/100) or an external PHY
> via RGMII/RMII.
> 
> Signed-off-by: LABBE Corentin 
> ---

[snip]

> +
> +struct ethtool_str {
> + char name[ETH_GSTRING_LEN];

You might as well drop the encapsulating structure and just use an array
of strings?

> +};
> +

[snip]

> +
> +/* The datasheet said that each descriptor can transfers up to 4096bytes
> + * But latter, a register documentation reduce that value to 2048
> + * Anyway using 2048 cause strange behaviours and even BSP driver use 2047
> + */
> +#define DESC_BUF_MAX 2044
> +#if (DESC_BUF_MAX < (ETH_FRAME_LEN + 4))
> +#error "DESC_BUF_MAX must be set at minimum to ETH_FRAME_LEN + 4"
> +#endif

You can probably drop that, it would not make much sense to enable
fragments and a buffer size smaller than ETH_FRAME_LEN + ETH_FCS_LEN anyway.

> +
> +/* MAGIC value for knowing if a descriptor is available or not */
> +#define DCLEAN (BIT(16) | BIT(14) | BIT(12) | BIT(10) | BIT(9))
> +
> +/* Structure of DMA descriptor used by the hardware  */
> +struct dma_desc {
> + u32 status; /* status of the descriptor */
> + u32 st; /* Information on the frame */
> + u32 buf_addr; /* physical address of the frame data */
> + u32 next; /* physical address of next dma_desc */
> +} __packed __aligned(4);

This has been noticed in other emails, no need for the __packed here,
they are all naturally aligned.

> +
> +/* Benched on OPIPC with 100M, setting more than 256 does not give any
> + * perf boost
> + */
> +static int nbdesc_tx = 256;
> +module_param(nbdesc_tx, int, S_IRUGO | S_IWUSR);
> +MODULE_PARM_DESC(nbdesc_tx, "Number of descriptors in the TX list");
> +static int nbdesc_rx = 128;
> +module_param(nbdesc_rx, int, S_IRUGO | S_IWUSR);
> +MODULE_PARM_DESC(nbdesc_rx, "Number of descriptors in the RX list");

This needs to be statically defined to begin driver operation with, and
then implement the ethtool operations to re-size the rings would you
want that.

[snip]

> +/* Return the number of contiguous free descriptors
> + * starting from tx_slot
> + */
> +static int rb_tx_numfreedesc(struct net_device *ndev)
> +{
> + struct sun8i_emac_priv *priv = netdev_priv(ndev);
> +
> + if (priv->tx_slot < priv->tx_dirty)
> + return priv->tx_dirty - priv->tx_slot;

Does this work with if tx_dirty wraps around?

> +
> + return (nbdesc_tx - priv->tx_slot) + priv->tx_dirty;
> +}
> +
> +/* Allocate a skb in a DMA descriptor
> + *
> + * @i index of slot to fill
> +*/
> +static int sun8i_emac_rx_sk(struct net_device *ndev, int i)
> +{
> + struct sun8i_emac_priv *priv = netdev_priv(ndev);
> + struct dma_desc *ddesc;
> + struct sk_buff *sk;

The networking stack typically refers to "sk" as socket and skb as
socket buffers.

> +
> + ddesc = priv->dd_rx + i;
> +
> + ddesc->st = 0;
> +
> + sk = netdev_alloc_skb_ip_align(ndev, DESC_BUF_MAX);
> + if (!sk)
> + return -ENOMEM;
> +
> + /* should not happen */
> + if (unlikely(priv->rx_sk[i]))
> + dev_warn(priv->dev, "BUG: Leaking a skbuff\n");
> +
> + priv->rx_sk[i] = sk;
> +
> + ddesc->buf_addr = dma_map_single(priv->dev, sk->data,
> +  DESC_BUF_MAX, DMA_FROM_DEVICE);
> + if (dma_mapping_error(priv->dev, ddesc->buf_addr)) {
> + dev_err(priv->dev, "ERROR: Cannot dma_map RX buffer\n");
> + dev_kfree_skb(sk);
> + return -EFAULT;
> + }
> + ddesc->st |= DESC_BUF_MAX;
> + ddesc->status = BIT(31);

You are missing a lightweight barrier here to ensure there is no
re-ordering done by the compiler in how you write to the descriptors in
DRAM, even though they are allocated from dma_alloc_coherent().

[snip]

> +static void sun8i_emac_set_link_mode(struct sun8i_emac_priv *priv)
> +{
> + u32 v;
> +
> + v = readl(priv->base + SUN8I_EMAC_BASIC_CTL0);
> +
> + if (priv->duplex)
> + v |= BIT(0);
> + else
> + v &= ~BIT(0);
> +
> + v &= ~0x0C;
> + switch (priv->speed) {
> + case 1000:
> + break;
> + case 100:
> + v |= BIT(2);
> + v |= BIT(3);
> + break;
> + case 10:
> + v |= BIT(3);
> + break;
> + }

Proper defines for all of these bits and masks?

> +
> + writel(v, priv->base + SUN8I_EMAC_BASIC_CTL0);
> +}
> +
> +static void sun8i_emac_flow_ctrl(struct sun8i_emac_priv *priv, int duplex,
> +  int fc, int pause)
> +{
> + u32 flow = 0;

pause is unused (outside of printing it) here

> +
> + netif_dbg(priv, link, priv->ndev, "%s %d %d %d\n", __func__,
> +   duplex, fc, pause);
> +
> + flow = readl(priv->base + 

Re: [PATCH v4 5/7] net: mdio-mux: Add MDIO mux driver for iProc SoCs

2016-06-06 Thread Florian Fainelli
On 06/06/2016 05:41 AM, Pramod Kumar wrote:
> iProc based SoCs supports the integrated mdio multiplexer which
> has the bus selection as well as mdio transaction generation logic
> inside.
> 
> This multiplexer has child buses for PCIe, SATA, USB and ETH. These
> buses could be internal or external to SOC where PHYs are attached.
> These buses could use C-45 or C-22 mdio transaction.
> 
> Signed-off-by: Pramod Kumar <pramod.ku...@broadcom.com>

Reviewed-by: Florian Fainelli <f.faine...@gmail.com>
-- 
Florian


Re: [PATCH net-next 2/9] net: dsa: Add support for parsing the old binding

2016-06-06 Thread Florian Fainelli
On 06/05/2016 08:19 PM, Andrew Lunn wrote:
>> How much support do we want to have for the old binding for in tree
>> platforms? Is the plan to migrate them all to the new binding?
> 
> I think there are three cases to consider.
> 
> 1) There are some old boards using setup.c files which have a platform
>device, platform data, etc. I've never used DSA in this way, and it
>could be all the recent additions have broken this. We might want
>to test this, and if it is in fact broken, and has been for a
>while, it indicates nobody uses those boards any more. We might
>suggest removing them. Even if they do work, i doubt anybody is
>interested in converting them to device tree. So we might have to
>keep the platform data support around.

We had a report a while ago of breakage, which got addressed and fixed
upstream, so if it breaks again, it will get fixed again.

> 
> 2) In tree devices using the DT binding. We can update them all to the
>new binding. The kirkwood boards don't have a u-boot which is DT
>capable. Some of the armada boards do have a DT capable uboot, but
>all these boards have been added by the community, so i suspect
>they are not flashed never to be changed again.
> 
> 3) Out of tree devices using the DT binding. As far as i can see,
>there is no in three board actually using the Broadcom SF2 driver
>and its odd binding. However from talking to you, i know there are
>devices out in the wild using this binding, and their DT blob is
>fixed, never to be changed again.

The concept of an "in-tree" board does not make much sense once the
bootloader provides a blob to the kernel, and synchronizing the Device
Tree sources with what a bootloader provides is just a pain with no
reward as long as the binding remains standard and works.

> 
> It actually seems odd to me that we have a nice new binding and an
> implement which is reasonably clean, and we want to add code to
> support a legacy binding for an out of tree board.
> 
> I need to think on this for a while. However, i don't see the old code
> and binding going away anytime soon. It will take a few cycles to
> determine if the old platform device/platform data still works, and to
> remove the old boards if not. We can update the in tree devices to the
> new binding, but we should keep the old binding a while to aid the
> transition.

I do not see the need for platform data going away actually, there are
tons of devices out there that are not supported using Device Tree, yet
feature Ethernet switches that could easily be supported would we want
to add support for that, and clearly an answer along the lines of let's
add Device Tree support for these platforms is not going to fly.

> 
> I'm tempted to say you should keep using the old code to support your
> out of tree devices. You should define a new binding for SF2 which
> conforms to the device tree binding document which just got accepted,
> and add it to SF 2 alongside the legacy binding. And it would be great
> if you could go the last step and actually add a boards device tree
> file using it.

I suppose I could do that.

> 
> I'm hesitant to add legacy binding support for SF2 to the new DSA2
> code. We should try to keep it free of cruft, and set a good example
> for others to follow when they bring along there new drivers.

What if this code was moved to the bcm_sf2.c where it matters and there
is just the bottom part of dsa_register_switch() exposed instead?
-- 
Florian


Re: [PATCH 1/5] ethernet: add sun8i-emac driver

2016-06-12 Thread Florian Fainelli
Le 09/06/2016 02:44, LABBE Corentin a écrit :
> Hello
> 
> I agree to all your comments, but for some I have additionnal questions
> 
> On Mon, Jun 06, 2016 at 11:25:15AM -0700, Florian Fainelli wrote:
>> On 06/03/2016 02:56 AM, LABBE Corentin wrote:
>>
>> [snip]
>>
>>> +
>>> +/* The datasheet said that each descriptor can transfers up to 4096bytes
>>> + * But latter, a register documentation reduce that value to 2048
>>> + * Anyway using 2048 cause strange behaviours and even BSP driver use 2047
>>> + */
>>> +#define DESC_BUF_MAX 2044
>>> +#if (DESC_BUF_MAX < (ETH_FRAME_LEN + 4))
>>> +#error "DESC_BUF_MAX must be set at minimum to ETH_FRAME_LEN + 4"
>>> +#endif
>>
>> You can probably drop that, it would not make much sense to enable
>> fragments and a buffer size smaller than ETH_FRAME_LEN + ETH_FCS_LEN anyway.
>>
> 
> I has added this test for preventing someone who want to "optimize" 
> DESC_BUF_MAX to doing mistake.
> But I agree that it is of low use.

It's actually dangerous, and if you don't make sure that the value is
properly rounded to whatever the DMA controller's alignment should be,
performance could be terribel too.

> 
>>> +/* Return the number of contiguous free descriptors
>>> + * starting from tx_slot
>>> + */
>>> +static int rb_tx_numfreedesc(struct net_device *ndev)
>>> +{
>>> +   struct sun8i_emac_priv *priv = netdev_priv(ndev);
>>> +
>>> +   if (priv->tx_slot < priv->tx_dirty)
>>> +   return priv->tx_dirty - priv->tx_slot;
>>
>> Does this work with if tx_dirty wraps around?
>>
> 
> The tx_dirty cannot wrap since I always keep an empty slot. (tx_slot cannot 
> go equal or after tx_dirty)

OK, fair enough.

> 
>>> +/* Grab a frame into a skb from descriptor number i */
>>> +static int sun8i_emac_rx_from_ddesc(struct net_device *ndev, int i)
>>> +{
>>> +   struct sk_buff *skb;
>>> +   struct sun8i_emac_priv *priv = netdev_priv(ndev);
>>> +   struct dma_desc *ddesc = priv->dd_rx + i;
>>> +   int frame_len;
>>> +   int crc_checked = 0;
>>> +
>>> +   if (ndev->features & NETIF_F_RXCSUM)
>>> +   crc_checked = 1;
>>
>> Assuming CRC here refers to the Ethernet frame's FCS, then this is
>> absolutely not how NETIF_F_RXCSUM works. NETIF_F_RXCSUM is about your
>> Ethernet adapter supporting L3/L4 checksum offloads, while the Ethernet
>> FCS is pretty much mandatory for the frame to be properly received in
>> the first place. Can you clarify which way it is?
>>
> 
> No CRC here is RXCSUM. I understand the misnaming.
> I will rename the variable to rxcsum_done.

Thanks

> 
>>> +
>>> +   priv->ndev->stats.rx_packets++;
>>> +   priv->ndev->stats.rx_bytes += frame_len;
>>> +   priv->rx_sk[i] = NULL;
>>> +
>>> +   /* this frame is not the last */
>>> +   if ((ddesc->status & BIT(8)) == 0) {
>>> +   dev_warn(priv->dev, "Multi frame not implemented currlen=%d\n",
>>> +frame_len);
>>> +   }
>>> +
>>> +   sun8i_emac_rx_sk(ndev, i);
>>> +
>>> +   netif_rx(skb);
>>
>> netif_receive_skb() at the very least, or if you implement NAPI, like
>> you shoud napi_gro_receive().
>>
> 
> netif_receive_skb documentation say
> "This function may only be called from softirq context and interrupts should 
> be enabled."
> but the calling functions is in hardirq context.

Well, yes, because you are not implementing NAPI, while you should, you
execute in hard interrupt context. Once you move to NAPI, you can and
should use netif_receive_skb().

> 
>>> +   return 0;
>>> +}
>>> +
>>> +/* Cycle over RX DMA descriptors for finding frame to receive
>>> + */
>>> +static int sun8i_emac_receive_all(struct net_device *ndev)
>>> +{
>>> +   struct sun8i_emac_priv *priv = netdev_priv(ndev);
>>> +   struct dma_desc *ddesc;
>>> +
>>> +   ddesc = priv->dd_rx + priv->rx_dirty;
>>> +   while (!(ddesc->status & BIT(31))) {
>>> +   sun8i_emac_rx_from_ddesc(ndev, priv->rx_dirty);
>>> +   rb_inc(>rx_dirty, nbdesc_rx);
>>> +   ddesc = priv->dd_rx + priv->rx_dirty;
>>> +   };
>>
>> So, what if we ping flood your device here, is not there a remote chance
>> that we keep the RX interrupt so busy we can't break out of this loop

Re: [PATCH net-next 4/4] net: dsa: bcm_sf2: Add VLAN support

2016-06-10 Thread Florian Fainelli
On 06/10/2016 05:00 AM, Andrew Lunn wrote:
>> @@ -148,6 +155,9 @@ struct bcm_sf2_priv {
>>  struct device_node  *master_mii_dn;
>>  struct mii_bus  *slave_mii_bus;
>>  struct mii_bus  *master_mii_bus;
>> +
>> +/* Cache of programmed VLANs */
>> +struct bcm_sf2_vlan vlans[VLAN_N_VID];
> 
> Hi Florian
> 
> This is a 16Kbyte array. So i assume the whole priv structure needs 5
> pages. Have you had any trouble allocating this much memory,
> particularly once it has been used for a while and fragmented?

Well, since this is using the old binding, we can't unload the driver,
it's built into the kernel, so initializes early enough we have got
plenty of memory.

> 
> I just wondered if it might be better to use vmalloc() for the
> vlans.

That's a very good point, I can't really see a drawback to doing this,
will submit a patch moving this to a dynamic allocation.

Another possible approach would have been to allocate the vlan structure
upong port_vlan_prepare() though that would typically result in more
fragmentation over time once se start using more VLANs.
-- 
Florian


Re: [PATCH net-next 1/5] net: dsa: b53: Add support for Broadcom RoboSwitch

2016-06-10 Thread Florian Fainelli
On 06/10/2016 05:11 AM, Andrew Lunn wrote:
>> +static void b53_switch_reset_gpio(struct b53_device *dev)
>> +{
>> +int gpio = dev->reset_gpio;
>> +
>> +if (gpio < 0)
>> +return;
>> +
>> +/* Reset sequence: RESET low(50ms)->high(20ms)
>> + */
>> +gpio_set_value(gpio, 0);
>> +mdelay(50);
>> +
>> +gpio_set_value(gpio, 1);
>> +mdelay(20);
>> +
>> +dev->current_page = 0xff;
>> +}
> 
> Hi Florian
> 
> It would be better to use the gpiod API here, so the active hi/active
> low flag is respected.

OK.

> 
>> +dev->reset_gpio = b53_switch_get_reset_gpio(dev);
>> +if (dev->reset_gpio >= 0) {
>> +ret = devm_gpio_request_one(dev->dev, dev->reset_gpio,
>> +GPIOF_OUT_INIT_HIGH, "robo_reset");
>> +if (ret)
>> +return ret;
>> +}
>> +
>> +return 0;
>> +}
> 
>> +static inline int b53_switch_get_reset_gpio(struct b53_device *dev)
>> +{
>> +enum bcm47xx_board board = bcm47xx_board_get();
>> +
>> +switch (board) {
>> +case BCM47XX_BOARD_LINKSYS_WRT300NV11:
>> +case BCM47XX_BOARD_LINKSYS_WRT310NV1:
>> +return 8;
> 
> Rather than hard coding it, could we get it from device tree?

Difficult for now, this is for in-tree MIPS-based platforms under
arch/mips/bcm47xx, which are using SSB/platform data.
-- 
Florian


[PATCH net-next 3/4] net: dsa: bcm_sf2: Add VLAN registers definitions

2016-06-09 Thread Florian Fainelli
Add the definitions for the VLAN registers that we are going to
manipulate in subsequent patches.

Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 drivers/net/dsa/bcm_sf2_regs.h | 70 ++
 1 file changed, 70 insertions(+)

diff --git a/drivers/net/dsa/bcm_sf2_regs.h b/drivers/net/dsa/bcm_sf2_regs.h
index 97780d43b5c0..9f2a9cb42074 100644
--- a/drivers/net/dsa/bcm_sf2_regs.h
+++ b/drivers/net/dsa/bcm_sf2_regs.h
@@ -274,6 +274,23 @@
 #define CORE_ARLA_SRCH_RSLT_MACVID(x)  (CORE_ARLA_SRCH_RSLT_0_MACVID + ((x) * 
0x40))
 #define CORE_ARLA_SRCH_RSLT(x) (CORE_ARLA_SRCH_RSLT_0 + ((x) * 0x40))
 
+#define CORE_ARLA_VTBL_RWCTRL  0x1600
+#define  ARLA_VTBL_CMD_WRITE   0
+#define  ARLA_VTBL_CMD_READ1
+#define  ARLA_VTBL_CMD_CLEAR   2
+#define  ARLA_VTBL_STDN(1 << 7)
+
+#define CORE_ARLA_VTBL_ADDR0x1604
+#define  VTBL_ADDR_INDEX_MASK  0xfff
+
+#define CORE_ARLA_VTBL_ENTRY   0x160c
+#define  FWD_MAP_MASK  0x1ff
+#define  UNTAG_MAP_MASK0x1ff
+#define  UNTAG_MAP_SHIFT   9
+#define  MSTP_INDEX_MASK   0x7
+#define  MSTP_INDEX_SHIFT  18
+#define  FWD_MODE  (1 << 21)
+
 #define CORE_MEM_PSM_VDD_CTRL  0x2380
 #define  P_TXQ_PSM_VDD_SHIFT   2
 #define  P_TXQ_PSM_VDD_MASK0x3
@@ -287,6 +304,59 @@
 #define CORE_PORT_VLAN_CTL_PORT(x) (0xc400 + ((x) * 0x8))
 #define  PORT_VLAN_CTRL_MASK   0x1ff
 
+#define CORE_VLAN_CTRL00xd000
+#define  CHANGE_1P_VID_INNER   (1 << 0)
+#define  CHANGE_1P_VID_OUTER   (1 << 1)
+#define  CHANGE_1Q_VID (1 << 3)
+#define  VLAN_LEARN_MODE_SVL   (0 << 5)
+#define  VLAN_LEARN_MODE_IVL   (3 << 5)
+#define  VLAN_EN   (1 << 7)
+
+#define CORE_VLAN_CTRL10xd004
+#define  EN_RSV_MCAST_FWDMAP   (1 << 2)
+#define  EN_RSV_MCAST_UNTAG(1 << 3)
+#define  EN_IPMC_BYPASS_FWDMAP (1 << 5)
+#define  EN_IPMC_BYPASS_UNTAG  (1 << 6)
+
+#define CORE_VLAN_CTRL20xd008
+#define  EN_MIIM_BYPASS_V_FWDMAP   (1 << 2)
+#define  EN_GMRP_GVRP_V_FWDMAP (1 << 5)
+#define  EN_GMRP_GVRP_UNTAG_MAP(1 << 6)
+
+#define CORE_VLAN_CTRL30xd00c
+#define  EN_DROP_NON1Q_MASK0x1ff
+
+#define CORE_VLAN_CTRL40xd014
+#define  RESV_MCAST_FLOOD  (1 << 1)
+#define  EN_DOUBLE_TAG_MASK0x3
+#define  EN_DOUBLE_TAG_SHIFT   2
+#define  EN_MGE_REV_GMRP   (1 << 4)
+#define  EN_MGE_REV_GVRP   (1 << 5)
+#define  INGR_VID_CHK_SHIFT6
+#define  INGR_VID_CHK_MASK 0x3
+#define  INGR_VID_CHK_FWD  (0 << INGR_VID_CHK_SHIFT)
+#define  INGR_VID_CHK_DROP (1 << INGR_VID_CHK_SHIFT)
+#define  INGR_VID_CHK_NO_CHK   (2 << INGR_VID_CHK_SHIFT)
+#define  INGR_VID_CHK_VID_VIOL_IMP (3 << INGR_VID_CHK_SHIFT)
+
+#define CORE_VLAN_CTRL50xd018
+#define  EN_CPU_RX_BYP_INNER_CRCCHCK   (1 << 0)
+#define  EN_VID_FFF_FWD(1 << 2)
+#define  DROP_VTABLE_MISS  (1 << 3)
+#define  EGRESS_DIR_FRM_BYP_TRUNK_EN   (1 << 4)
+#define  PRESV_NON1Q   (1 << 6)
+
+#define CORE_VLAN_CTRL60xd01c
+#define  STRICT_SFD_DETECT (1 << 0)
+#define  DIS_ARL_BUST_LMIT (1 << 4)
+
+#define CORE_DEFAULT_1Q_TAG_P(x)   (0xd040 + ((x) * 8))
+#define  CFI_SHIFT 12
+#define  PRI_SHIFT 13
+#define  PRI_MASK  0x7
+
+#define CORE_JOIN_ALL_VLAN_EN  0xd140
+
 #define CORE_EEE_EN_CTRL   0x24800
 #define CORE_EEE_LPI_INDICATE  0x24810
 
-- 
2.7.4



[PATCH net-next 1/4] net: dsa: bcm_sf2: Split fast age into a helper function

2016-06-09 Thread Florian Fainelli
Add a helper function to fast age something that is controlled by the
caller: port, VLAN. We will use this to implement a VLAN fast age
operation.

Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 drivers/net/dsa/bcm_sf2.c | 20 +---
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index d6625783703f..ad22caba51e5 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -461,17 +461,11 @@ static int bcm_sf2_sw_set_eee(struct dsa_switch *ds, int 
port,
return 0;
 }
 
-/* Fast-ageing of ARL entries for a given port, equivalent to an ARL
- * flush for that port.
- */
-static int bcm_sf2_sw_fast_age_port(struct dsa_switch  *ds, int port)
+static int bcm_sf2_fast_age_op(struct bcm_sf2_priv *priv)
 {
-   struct bcm_sf2_priv *priv = ds_to_priv(ds);
unsigned int timeout = 1000;
u32 reg;
 
-   core_writel(priv, port, CORE_FAST_AGE_PORT);
-
reg = core_readl(priv, CORE_FAST_AGE_CTRL);
reg |= EN_AGE_PORT | EN_AGE_DYNAMIC | FAST_AGE_STR_DONE;
core_writel(priv, reg, CORE_FAST_AGE_CTRL);
@@ -492,6 +486,18 @@ static int bcm_sf2_sw_fast_age_port(struct dsa_switch  
*ds, int port)
return 0;
 }
 
+/* Fast-ageing of ARL entries for a given port, equivalent to an ARL
+ * flush for that port.
+ */
+static int bcm_sf2_sw_fast_age_port(struct dsa_switch *ds, int port)
+{
+   struct bcm_sf2_priv *priv = ds_to_priv(ds);
+
+   core_writel(priv, port, CORE_FAST_AGE_PORT);
+
+   return bcm_sf2_fast_age_op(priv);
+}
+
 static int bcm_sf2_sw_br_join(struct dsa_switch *ds, int port,
  struct net_device *bridge)
 {
-- 
2.7.4



[PATCH net-next 5/5] net: dsa: b53: Plug in VLAN support

2016-06-09 Thread Florian Fainelli
Add support for configuration VLANs on B53 devices by implementing the
port VLAN add/del/dump functions. We currently default to a behavior
which is equivalent to having VLAN filtering turned on, where all VLANs
not programmed into the VLAN port-based vector will be discarded on
ingress.

Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 drivers/net/dsa/b53/b53_common.c | 256 +++
 drivers/net/dsa/b53/b53_priv.h   |  13 +-
 2 files changed, 243 insertions(+), 26 deletions(-)

diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
index ad1d68272016..5321083379c7 100644
--- a/drivers/net/dsa/b53/b53_common.c
+++ b/drivers/net/dsa/b53/b53_common.c
@@ -186,15 +186,15 @@ static int b53_do_vlan_op(struct b53_device *dev, u8 op)
return -EIO;
 }
 
-static void b53_set_vlan_entry(struct b53_device *dev, u16 vid, u16 members,
-  u16 untag)
+static void b53_set_vlan_entry(struct b53_device *dev, u16 vid,
+  struct b53_vlan *vlan)
 {
if (is5325(dev)) {
u32 entry = 0;
 
-   if (members) {
-   entry = ((untag & VA_UNTAG_MASK_25) << VA_UNTAG_S_25) |
-   members;
+   if (vlan->members) {
+   entry = ((vlan->untag & VA_UNTAG_MASK_25) <<
+VA_UNTAG_S_25) | vlan->members;
if (dev->core_rev >= 3)
entry |= VA_VALID_25_R4 | vid << VA_VID_HIGH_S;
else
@@ -207,9 +207,9 @@ static void b53_set_vlan_entry(struct b53_device *dev, u16 
vid, u16 members,
} else if (is5365(dev)) {
u16 entry = 0;
 
-   if (members)
-   entry = ((untag & VA_UNTAG_MASK_65) << VA_UNTAG_S_65) |
-   members | VA_VALID_65;
+   if (vlan->members)
+   entry = ((vlan->untag & VA_UNTAG_MASK_65) <<
+VA_UNTAG_S_65) | vlan->members | VA_VALID_65;
 
b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_WRITE_65, entry);
b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_TABLE_ACCESS_65, vid |
@@ -217,13 +217,55 @@ static void b53_set_vlan_entry(struct b53_device *dev, 
u16 vid, u16 members,
} else {
b53_write16(dev, B53_ARLIO_PAGE, dev->vta_regs[1], vid);
b53_write32(dev, B53_ARLIO_PAGE, dev->vta_regs[2],
-   (untag << VTE_UNTAG_S) | members);
+   (vlan->untag << VTE_UNTAG_S) | vlan->members);
 
b53_do_vlan_op(dev, VTA_CMD_WRITE);
}
+
+   dev_dbg(dev->ds->dev, "VID: %d, members: 0x%04x, untag: 0x%04x\n",
+   vid, vlan->members, vlan->untag);
+}
+
+static void b53_get_vlan_entry(struct b53_device *dev, u16 vid,
+  struct b53_vlan *vlan)
+{
+   if (is5325(dev)) {
+   u32 entry = 0;
+
+   b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_TABLE_ACCESS_25, vid |
+   VTA_RW_STATE_RD | VTA_RW_OP_EN);
+   b53_read32(dev, B53_VLAN_PAGE, B53_VLAN_WRITE_25, );
+
+   if (dev->core_rev >= 3)
+   vlan->valid = !!(entry & VA_VALID_25_R4);
+   else
+   vlan->valid = !!(entry & VA_VALID_25);
+   vlan->members = entry & VA_MEMBER_MASK;
+   vlan->untag = (entry >> VA_UNTAG_S_25) & VA_UNTAG_MASK_25;
+
+   } else if (is5365(dev)) {
+   u16 entry = 0;
+
+   b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_TABLE_ACCESS_65, vid |
+   VTA_RW_STATE_WR | VTA_RW_OP_EN);
+   b53_read16(dev, B53_VLAN_PAGE, B53_VLAN_WRITE_65, );
+
+   vlan->valid = !!(entry & VA_VALID_65);
+   vlan->members = entry & VA_MEMBER_MASK;
+   vlan->untag = (entry >> VA_UNTAG_S_65) & VA_UNTAG_MASK_65;
+   } else {
+   u32 entry = 0;
+
+   b53_write16(dev, B53_ARLIO_PAGE, dev->vta_regs[1], vid);
+   b53_do_vlan_op(dev, VTA_CMD_READ);
+   b53_read32(dev, B53_ARLIO_PAGE, dev->vta_regs[2], );
+   vlan->members = entry & VTE_MEMBERS;
+   vlan->untag = (entry >> VTE_UNTAG_S) & VTE_MEMBERS;
+   vlan->valid = true;
+   }
 }
 
-void b53_set_forwarding(struct b53_device *dev, int enable)
+static void b53_set_forwarding(struct b53_device *dev, int enable)
 {
u8 mgmt;
 
@@ -237,7 +279,7 @@ void b53_set_forwarding(struct b53_device *dev, int enable)
b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, mgmt);
 }
 
-static

[PATCH net-next 0/5] net: dsa: Broadcom BCM53xx switches support

2016-06-09 Thread Florian Fainelli
Hi all,

This patch series adds support for the Broadcom BCM53xx series aka RoboSwitches.

This driver is largely based on Jonas Gorski's b53 driver for OpenWrt which can
be found here:

https://dev.openwrt.org/browser/trunk/target/linux/generic/files/drivers/net/phy/b53

a few bug fixes and DSA-ifycation later, here is what we got.

This has been successfully tested in the following configurations:

- Broadcom BCM53011 using the SRAB bus layer with 4 ports LAN, 1 port WAN

- A Broadcom BCM7445 device with an internal Starfighter 2 switch (bcm_sf2.c)
  and a Broadcom BCM53125 hanging off one of its ports connected via MDIO, 
creating
  two trees hanging off each other, and this works!

- A Broadcom BCM53125 MDIO connected to a Lamobo/Bananapi R1 board using the 
STMMAC
  MDIO driver

For now, we do not enable Broadcom tags, because there are different
generations of switches being supported which have different tag formats, but
the plan is to enable them later on.

Support for different HW features will be added later: EEE, Compact Field
Processor (TCAM) once this initial cut gets accepted.

Testing and bug reports welcome!

Florian Fainelli (5):
  net: dsa: b53: Add support for Broadcom RoboSwitch
  net: dsa: b53: Add BCM7445 quirk
  net: dsa: b53: Implement ARL add/del/dump operations
  net: dsa: b53: Add bridge support
  net: dsa: b53: Plug in VLAN support

 Documentation/devicetree/bindings/net/dsa/b53.txt |   90 ++
 MAINTAINERS   |8 +
 drivers/net/dsa/Kconfig   |2 +
 drivers/net/dsa/Makefile  |2 +
 drivers/net/dsa/b53/Kconfig   |   33 +
 drivers/net/dsa/b53/Makefile  |6 +
 drivers/net/dsa/b53/b53_common.c  | 1787 +
 drivers/net/dsa/b53/b53_mdio.c|  392 +
 drivers/net/dsa/b53/b53_mmap.c|  260 +++
 drivers/net/dsa/b53/b53_priv.h|  387 +
 drivers/net/dsa/b53/b53_regs.h|  434 +
 drivers/net/dsa/b53/b53_spi.c |  331 
 drivers/net/dsa/b53/b53_srab.c|  415 +
 include/linux/platform_data/b53.h |   33 +
 14 files changed, 4180 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/dsa/b53.txt
 create mode 100644 drivers/net/dsa/b53/Kconfig
 create mode 100644 drivers/net/dsa/b53/Makefile
 create mode 100644 drivers/net/dsa/b53/b53_common.c
 create mode 100644 drivers/net/dsa/b53/b53_mdio.c
 create mode 100644 drivers/net/dsa/b53/b53_mmap.c
 create mode 100644 drivers/net/dsa/b53/b53_priv.h
 create mode 100644 drivers/net/dsa/b53/b53_regs.h
 create mode 100644 drivers/net/dsa/b53/b53_spi.c
 create mode 100644 drivers/net/dsa/b53/b53_srab.c
 create mode 100644 include/linux/platform_data/b53.h

-- 
2.7.4



[PATCH net-next 4/5] net: dsa: b53: Add bridge support

2016-06-09 Thread Florian Fainelli
Add support for HW bridging by tying the ports together in the same port
VLAN mask when they belong to the same bridge, and isolating them to be
alone with the CPU port when they are not.

Propagate STP states from the bridge layer to the switch's HW mapping
when requested.

Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 drivers/net/dsa/b53/b53_common.c | 162 ++-
 drivers/net/dsa/b53/b53_priv.h   |   3 +
 drivers/net/dsa/b53/b53_regs.h   |  12 +++
 3 files changed, 174 insertions(+), 3 deletions(-)

diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
index a9f1de407f57..ad1d68272016 100644
--- a/drivers/net/dsa/b53/b53_common.c
+++ b/drivers/net/dsa/b53/b53_common.c
@@ -27,6 +27,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -339,12 +340,12 @@ static int b53_set_jumbo(struct b53_device *dev, bool 
enable, bool allow_10_100)
return b53_write16(dev, B53_JUMBO_PAGE, dev->jumbo_size_reg, max_size);
 }
 
-static int b53_flush_arl(struct b53_device *dev)
+static int b53_flush_arl(struct b53_device *dev, u8 mask)
 {
unsigned int i;
 
b53_write8(dev, B53_CTRL_PAGE, B53_FAST_AGE_CTRL,
-  FAST_AGE_DONE | FAST_AGE_DYNAMIC | FAST_AGE_STATIC);
+  FAST_AGE_DONE | FAST_AGE_DYNAMIC | mask);
 
for (i = 0; i < 10; i++) {
u8 fast_age_ctrl;
@@ -365,14 +366,52 @@ out:
return 0;
 }
 
+static int b53_fast_age_port(struct b53_device *dev, int port)
+{
+   b53_write8(dev, B53_CTRL_PAGE, B53_FAST_AGE_PORT_CTRL, port);
+
+   return b53_flush_arl(dev, FAST_AGE_PORT);
+}
+
+static void b53_imp_vlan_setup(struct dsa_switch *ds, int cpu_port)
+{
+   struct b53_device *dev = ds_to_priv(ds);
+   unsigned int i;
+   u16 pvlan;
+
+   /* Enable the IMP port to be in the same VLAN as the other ports
+* on a per-port basis such that we only have Port i and IMP in
+* the same VLAN.
+*/
+   b53_for_each_port(dev, i) {
+   b53_read16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(i), );
+   pvlan |= BIT(cpu_port);
+   b53_write16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(i), pvlan);
+   }
+}
+
 static int b53_enable_port(struct dsa_switch *ds, int port,
   struct phy_device *phy)
 {
struct b53_device *dev = ds_to_priv(ds);
+   unsigned int cpu_port = dev->cpu_port;
+   u16 pvlan;
 
/* Clear the Rx and Tx disable bits and set to no spanning tree */
b53_write8(dev, B53_CTRL_PAGE, B53_PORT_CTRL(port), 0);
 
+   /* Set this port, and only this one to be in the default VLAN,
+* if member of a bridge, restore its membership prior to
+* bringing down this port.
+*/
+   b53_read16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(port), );
+   pvlan &= ~0x1ff;
+   pvlan |= BIT(port);
+   pvlan |= dev->ports[port].vlan_ctl_mask;
+   b53_write16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(port), pvlan);
+
+   b53_imp_vlan_setup(ds, cpu_port);
+
return 0;
 }
 
@@ -482,7 +521,7 @@ static int b53_switch_reset(struct b53_device *dev)
 
b53_enable_mib(dev);
 
-   return b53_flush_arl(dev);
+   return b53_flush_arl(dev, FAST_AGE_STATIC);
 }
 
 static int b53_phy_read16(struct dsa_switch *ds, int addr, int reg)
@@ -1019,6 +1058,120 @@ static int b53_fdb_dump(struct dsa_switch *ds, int port,
return 0;
 }
 
+static int b53_br_join(struct dsa_switch *ds, int port,
+  struct net_device *bridge)
+{
+   struct b53_device *dev = ds_to_priv(ds);
+   u16 pvlan, reg;
+   unsigned int i;
+
+   dev->ports[port].bridge_dev = bridge;
+   b53_read16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(port), );
+
+   b53_for_each_port(dev, i) {
+   if (dev->ports[i].bridge_dev != bridge)
+   continue;
+
+   /* Add this local port to the remote port VLAN control
+* membership and update the remote port bitmask
+*/
+   b53_read16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(i), );
+   reg |= BIT(port);
+   b53_write16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(i), reg);
+   dev->ports[i].vlan_ctl_mask = reg;
+
+   pvlan |= BIT(i);
+   }
+
+   /* Configure the local port VLAN control membership to include
+* remote ports and update the local port bitmask
+*/
+   b53_write16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(port), pvlan);
+   dev->ports[port].vlan_ctl_mask = pvlan;
+
+   return 0;
+}
+
+static void b53_br_leave(struct dsa_switch *ds, int port)
+{
+   struct b53_device *dev = ds_to_priv(ds);
+   struct net_device *bridge = dev->ports[port].bridge_dev;
+   unsigned int i;
+   u16 pvlan, reg;
+
+   b53_read16(dev, B53

[PATCH net-next 4/4] net: dsa: bcm_sf2: Add VLAN support

2016-06-09 Thread Florian Fainelli
Add support for configuring VLANs on the Broadcom Starfigther2 switch.
This is all done through the bridge vlan facility just like other DSA
drivers.

Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 drivers/net/dsa/bcm_sf2.c | 266 +-
 drivers/net/dsa/bcm_sf2.h |  10 ++
 2 files changed, 275 insertions(+), 1 deletion(-)

diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index d726f5906ef9..cd1d630ae3a9 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -467,7 +467,7 @@ static int bcm_sf2_fast_age_op(struct bcm_sf2_priv *priv)
u32 reg;
 
reg = core_readl(priv, CORE_FAST_AGE_CTRL);
-   reg |= EN_AGE_PORT | EN_AGE_DYNAMIC | FAST_AGE_STR_DONE;
+   reg |= EN_AGE_PORT | EN_AGE_VLAN | EN_AGE_DYNAMIC | FAST_AGE_STR_DONE;
core_writel(priv, reg, CORE_FAST_AGE_CTRL);
 
do {
@@ -498,13 +498,86 @@ static int bcm_sf2_sw_fast_age_port(struct dsa_switch 
*ds, int port)
return bcm_sf2_fast_age_op(priv);
 }
 
+static int bcm_sf2_sw_fast_age_vlan(struct bcm_sf2_priv *priv, u16 vid)
+{
+   core_writel(priv, vid, CORE_FAST_AGE_VID);
+
+   return bcm_sf2_fast_age_op(priv);
+}
+
+static int bcm_sf2_vlan_op_wait(struct bcm_sf2_priv *priv)
+{
+   unsigned int timeout = 10;
+   u32 reg;
+
+   do {
+   reg = core_readl(priv, CORE_ARLA_VTBL_RWCTRL);
+   if (!(reg & ARLA_VTBL_STDN))
+   return 0;
+
+   usleep_range(1000, 2000);
+   } while (timeout--);
+
+   return -ETIMEDOUT;
+}
+
+static int bcm_sf2_vlan_op(struct bcm_sf2_priv *priv, u8 op)
+{
+   core_writel(priv, ARLA_VTBL_STDN | op, CORE_ARLA_VTBL_RWCTRL);
+
+   return bcm_sf2_vlan_op_wait(priv);
+}
+
+static void bcm_sf2_set_vlan_entry(struct bcm_sf2_priv *priv, u16 vid,
+  struct bcm_sf2_vlan *vlan)
+{
+   int ret;
+
+   core_writel(priv, vid & VTBL_ADDR_INDEX_MASK, CORE_ARLA_VTBL_ADDR);
+   core_writel(priv, vlan->untag << UNTAG_MAP_SHIFT | vlan->members,
+   CORE_ARLA_VTBL_ENTRY);
+
+   ret = bcm_sf2_vlan_op(priv, ARLA_VTBL_CMD_WRITE);
+   if (ret)
+   pr_err("failed to write VLAN entry\n");
+}
+
+static int bcm_sf2_get_vlan_entry(struct bcm_sf2_priv *priv, u16 vid,
+ struct bcm_sf2_vlan *vlan)
+{
+   u32 entry;
+   int ret;
+
+   core_writel(priv, vid & VTBL_ADDR_INDEX_MASK, CORE_ARLA_VTBL_ADDR);
+
+   ret = bcm_sf2_vlan_op(priv, ARLA_VTBL_CMD_READ);
+   if (ret)
+   return ret;
+
+   entry = core_readl(priv, CORE_ARLA_VTBL_ENTRY);
+   vlan->members = entry & FWD_MAP_MASK;
+   vlan->untag = (entry >> UNTAG_MAP_SHIFT) & UNTAG_MAP_MASK;
+
+   return 0;
+}
+
 static int bcm_sf2_sw_br_join(struct dsa_switch *ds, int port,
  struct net_device *bridge)
 {
struct bcm_sf2_priv *priv = ds_to_priv(ds);
+   s8 cpu_port = ds->dst->cpu_port;
unsigned int i;
u32 reg, p_ctl;
 
+   /* Make this port leave the all VLANs join since we will have proper
+* VLAN entries from now on
+*/
+   reg = core_readl(priv, CORE_JOIN_ALL_VLAN_EN);
+   reg &= ~BIT(port);
+   if ((reg & BIT(cpu_port)) == BIT(cpu_port))
+   reg &= ~BIT(cpu_port);
+   core_writel(priv, reg, CORE_JOIN_ALL_VLAN_EN);
+
priv->port_sts[port].bridge_dev = bridge;
p_ctl = core_readl(priv, CORE_PORT_VLAN_CTL_PORT(port));
 
@@ -536,6 +609,7 @@ static void bcm_sf2_sw_br_leave(struct dsa_switch *ds, int 
port)
 {
struct bcm_sf2_priv *priv = ds_to_priv(ds);
struct net_device *bridge = priv->port_sts[port].bridge_dev;
+   s8 cpu_port = ds->dst->cpu_port;
unsigned int i;
u32 reg, p_ctl;
 
@@ -559,6 +633,13 @@ static void bcm_sf2_sw_br_leave(struct dsa_switch *ds, int 
port)
core_writel(priv, p_ctl, CORE_PORT_VLAN_CTL_PORT(port));
priv->port_sts[port].vlan_ctl_mask = p_ctl;
priv->port_sts[port].bridge_dev = NULL;
+
+   /* Make this port join all VLANs without VLAN entries */
+   reg = core_readl(priv, CORE_JOIN_ALL_VLAN_EN);
+   reg |= BIT(port);
+   if (!(reg & BIT(cpu_port)))
+   reg |= BIT(cpu_port);
+   core_writel(priv, reg, CORE_JOIN_ALL_VLAN_EN);
 }
 
 static void bcm_sf2_sw_br_set_stp_state(struct dsa_switch *ds, int port,
@@ -1312,6 +1393,182 @@ static int bcm_sf2_sw_set_wol(struct dsa_switch *ds, 
int port,
return p->ethtool_ops->set_wol(p, wol);
 }
 
+static void bcm_sf2_enable_vlan(struct bcm_sf2_priv *priv, bool enable)
+{
+   u32 mgmt, vc0, vc1, vc4, vc5;
+
+   mgmt = core_readl(priv, CORE_SWMODE);
+   vc0 = core_readl(priv, CORE_VLAN_CTRL0);
+   vc1 = core_readl(priv, CORE_VLAN_CTRL1);
+ 

[PATCH net-next 2/4] net: dsa: bcm_sf2: Move setup function at the far end

2016-06-09 Thread Florian Fainelli
Re-order the bcm_sf2_sw_setup() function so that it is at the far end of
the driver to avoid any kind of forward declarations.

Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 drivers/net/dsa/bcm_sf2.c | 238 +++---
 1 file changed, 119 insertions(+), 119 deletions(-)

diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index ad22caba51e5..d726f5906ef9 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -1065,125 +1065,6 @@ static void bcm_sf2_mdio_unregister(struct bcm_sf2_priv 
*priv)
of_node_put(priv->master_mii_dn);
 }
 
-static int bcm_sf2_sw_setup(struct dsa_switch *ds)
-{
-   const char *reg_names[BCM_SF2_REGS_NUM] = BCM_SF2_REGS_NAME;
-   struct bcm_sf2_priv *priv = ds_to_priv(ds);
-   struct device_node *dn;
-   void __iomem **base;
-   unsigned int port;
-   unsigned int i;
-   u32 reg, rev;
-   int ret;
-
-   spin_lock_init(>indir_lock);
-   mutex_init(>stats_mutex);
-
-   /* All the interesting properties are at the parent device_node
-* level
-*/
-   dn = ds->cd->of_node->parent;
-   bcm_sf2_identify_ports(priv, ds->cd->of_node);
-
-   priv->irq0 = irq_of_parse_and_map(dn, 0);
-   priv->irq1 = irq_of_parse_and_map(dn, 1);
-
-   base = >core;
-   for (i = 0; i < BCM_SF2_REGS_NUM; i++) {
-   *base = of_iomap(dn, i);
-   if (*base == NULL) {
-   pr_err("unable to find register: %s\n", reg_names[i]);
-   ret = -ENOMEM;
-   goto out_unmap;
-   }
-   base++;
-   }
-
-   ret = bcm_sf2_sw_rst(priv);
-   if (ret) {
-   pr_err("unable to software reset switch: %d\n", ret);
-   goto out_unmap;
-   }
-
-   ret = bcm_sf2_mdio_register(ds);
-   if (ret) {
-   pr_err("failed to register MDIO bus\n");
-   goto out_unmap;
-   }
-
-   /* Disable all interrupts and request them */
-   bcm_sf2_intr_disable(priv);
-
-   ret = request_irq(priv->irq0, bcm_sf2_switch_0_isr, 0,
- "switch_0", priv);
-   if (ret < 0) {
-   pr_err("failed to request switch_0 IRQ\n");
-   goto out_unmap;
-   }
-
-   ret = request_irq(priv->irq1, bcm_sf2_switch_1_isr, 0,
- "switch_1", priv);
-   if (ret < 0) {
-   pr_err("failed to request switch_1 IRQ\n");
-   goto out_free_irq0;
-   }
-
-   /* Reset the MIB counters */
-   reg = core_readl(priv, CORE_GMNCFGCFG);
-   reg |= RST_MIB_CNT;
-   core_writel(priv, reg, CORE_GMNCFGCFG);
-   reg &= ~RST_MIB_CNT;
-   core_writel(priv, reg, CORE_GMNCFGCFG);
-
-   /* Get the maximum number of ports for this switch */
-   priv->hw_params.num_ports = core_readl(priv, CORE_IMP0_PRT_ID) + 1;
-   if (priv->hw_params.num_ports > DSA_MAX_PORTS)
-   priv->hw_params.num_ports = DSA_MAX_PORTS;
-
-   /* Assume a single GPHY setup if we can't read that property */
-   if (of_property_read_u32(dn, "brcm,num-gphy",
->hw_params.num_gphy))
-   priv->hw_params.num_gphy = 1;
-
-   /* Enable all valid ports and disable those unused */
-   for (port = 0; port < priv->hw_params.num_ports; port++) {
-   /* IMP port receives special treatment */
-   if ((1 << port) & ds->enabled_port_mask)
-   bcm_sf2_port_setup(ds, port, NULL);
-   else if (dsa_is_cpu_port(ds, port))
-   bcm_sf2_imp_setup(ds, port);
-   else
-   bcm_sf2_port_disable(ds, port, NULL);
-   }
-
-   rev = reg_readl(priv, REG_SWITCH_REVISION);
-   priv->hw_params.top_rev = (rev >> SWITCH_TOP_REV_SHIFT) &
-   SWITCH_TOP_REV_MASK;
-   priv->hw_params.core_rev = (rev & SF2_REV_MASK);
-
-   rev = reg_readl(priv, REG_PHY_REVISION);
-   priv->hw_params.gphy_rev = rev & PHY_REVISION_MASK;
-
-   pr_info("Starfighter 2 top: %x.%02x, core: %x.%02x base: 0x%p, IRQs: 
%d, %d\n",
-   priv->hw_params.top_rev >> 8, priv->hw_params.top_rev & 0xff,
-   priv->hw_params.core_rev >> 8, priv->hw_params.core_rev & 0xff,
-   priv->core, priv->irq0, priv->irq1);
-
-   return 0;
-
-out_free_irq0:
-   free_irq(priv->irq0, priv);
-out_unmap:
-   base = >core;
-   for (i = 0; i < BCM_SF2_REGS_NUM; i++) {
-   if (*base)
-   iounmap(*base);
-   base++;
-   }
-

[PATCH net-next 0/4] net: dsa: bcm_sf2: add VLAN support

2016-06-09 Thread Florian Fainelli
Hi all,

This is long overdue, finally add support for VLANs in the Broadcom Starfigther
2 switch driver.

There are a few things that make us differ from e.g; mv88e6xxx.c:

- we keep a software cache of which VLANs are enabled and which are not to
  dramatically speed up the VLAN dump operation, we do not have any HW operation
  which would only return the list of valid VLAN entries, they would have to be
  all queried one by one, with 4K vlans, this takes a while

- the default behavior is equivalent to setting VLAN filtering to 1, still 
working
  on implementing a proper port_vlan_filtering callback, but I figured the most
  conservative behavior is probably okay anyway

- without enabling VLANs, the default behavior is to receive any 802.1q frames
  (per the DSA documentation), however, once we start enabling VLAN support, if
  an interface leaves the bridge, we still want it to receive all 802.1q frames
  so we utiliez the "Join all VLAN" feature of the switch to perform that

Thanks!

Florian Fainelli (4):
  net: dsa: bcm_sf2: Split fast age into a helper function
  net: dsa: bcm_sf2: Move setup function at the far end
  net: dsa: bcm_sf2: Add VLAN registers definitions
  net: dsa: bcm_sf2: Add VLAN support

 drivers/net/dsa/bcm_sf2.c  | 524 +++--
 drivers/net/dsa/bcm_sf2.h  |  10 +
 drivers/net/dsa/bcm_sf2_regs.h |  70 ++
 3 files changed, 477 insertions(+), 127 deletions(-)

-- 
2.7.4



[PATCH net-next 1/5] net: dsa: b53: Add support for Broadcom RoboSwitch

2016-06-09 Thread Florian Fainelli
This patch adds support for Broadcom's BCM53xx switch family, also known
as RoboSwitch. Some of these switches are ubiquituous, found in home
routers, Wi-Fi routers, DSL and cable modem gateways and other
networking related products.

This drivers adds the library driver (b53_common.c) as well as a few bus
glue drivers for MDIO, SPI, Switch Register Access Block (SRAB) and
memory-mapped I/O into a SoC's address space (Broadcom BCM63xx/33xx).

Basic operations are supported to bring the Layer 1/2 up and running,
but not much more at this point, subsequent patches add the remaining
features.

Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 Documentation/devicetree/bindings/net/dsa/b53.txt |   90 ++
 MAINTAINERS   |8 +
 drivers/net/dsa/Kconfig   |2 +
 drivers/net/dsa/Makefile  |2 +
 drivers/net/dsa/b53/Kconfig   |   33 +
 drivers/net/dsa/b53/Makefile  |6 +
 drivers/net/dsa/b53/b53_common.c  | 1158 +
 drivers/net/dsa/b53/b53_mdio.c|  381 +++
 drivers/net/dsa/b53/b53_mmap.c|  260 +
 drivers/net/dsa/b53/b53_priv.h|  322 ++
 drivers/net/dsa/b53/b53_regs.h|  358 +++
 drivers/net/dsa/b53/b53_spi.c |  331 ++
 drivers/net/dsa/b53/b53_srab.c|  415 
 include/linux/platform_data/b53.h |   33 +
 14 files changed, 3399 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/dsa/b53.txt
 create mode 100644 drivers/net/dsa/b53/Kconfig
 create mode 100644 drivers/net/dsa/b53/Makefile
 create mode 100644 drivers/net/dsa/b53/b53_common.c
 create mode 100644 drivers/net/dsa/b53/b53_mdio.c
 create mode 100644 drivers/net/dsa/b53/b53_mmap.c
 create mode 100644 drivers/net/dsa/b53/b53_priv.h
 create mode 100644 drivers/net/dsa/b53/b53_regs.h
 create mode 100644 drivers/net/dsa/b53/b53_spi.c
 create mode 100644 drivers/net/dsa/b53/b53_srab.c
 create mode 100644 include/linux/platform_data/b53.h

diff --git a/Documentation/devicetree/bindings/net/dsa/b53.txt 
b/Documentation/devicetree/bindings/net/dsa/b53.txt
new file mode 100644
index ..4a5349a09655
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/dsa/b53.txt
@@ -0,0 +1,90 @@
+Broadcom BCM53xx Ethernet switches
+==
+
+Required properties:
+
+- compatible: For external switch chips, compatible string must be exactly one
+  of: "brcm,bcm5325"
+  "brcm,bcm53115"
+  "brcm,bcm53125"
+  "brcm,bcm53128"
+  "brcm,bcm5365"
+  "brcm,bcm5395"
+  "brcm,bcm5397"
+  "brcm,bcm5398"
+
+  For the BCM5310x SoCs with an integrated switch, must be one of:
+  "brcm,bcm53010-srab"
+  "brcm,bcm53011-srab"
+  "brcm,bcm53012-srab"
+  "brcm,bcm53018-srab"
+  "brcm,bcm53019-srab" and the mandatory "brcm,bcm5301x-srab" string
+
+  For the BCM63xx/33xx SoCs with an integrated switch, must be one of:
+  "brcm,bcm3384-switch"
+  "brcm,bcm6328-switch"
+  "brcm,bcm6368-switch" and the mandatory "brcm,bcm63xx-switch"
+
+See Documentation/devicetree/bindings/dsa/dsa.txt for a list of additional
+required and optional properties.
+
+Examples:
+
+Ethernet switch connected via MDIO to the host, CPU port wired to eth0:
+
+   eth0: ethernet@10001000 {
+   compatible = "brcm,unimac";
+   reg = <0x10001000 0x1000>;
+
+   fixed-link {
+   speed = <1000>;
+   duplex-full;
+   };
+   };
+
+   mdio0: mdio@1000 {
+   compatible = "brcm,unimac-mdio";
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   switch0: ethernet-switch@30 {
+   compatible = "brcm,bcm53125";
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   ports {
+   port0@0 {
+   reg = <0>;
+   label = "lan1";
+   };
+
+   port1@1 {
+   reg = <1>;
+   label = "lan2";
+   };
+
+   port5@5 {
+   reg = <5>;
+   label = "cable-modem";
+   fixed-link {
+

[PATCH net-next 2/5] net: dsa: b53: Add BCM7445 quirk

2016-06-09 Thread Florian Fainelli
The Broadcom BCM7445 STB chip has an issued in its revision D0 which was
previously worked around in drivers/net/dsa/bcm_sf2.c where we may
end-up double programming the integrated BCM7445 switch (bcm_sf2) and an
external Broadcom switch such as BCM53125, since these are mostly
register compatible.

Add a small quirk which just defers probing until we are sitting on the
slave DSA MDIO bus, which will allow us to intercept reads/writes and
funnel them through the SF2 internal MDIO master (which happens to
disconnect its pseudo PHY).

Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 drivers/net/dsa/b53/b53_mdio.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/drivers/net/dsa/b53/b53_mdio.c b/drivers/net/dsa/b53/b53_mdio.c
index c6cf7cf57cc3..aa87c3fffdac 100644
--- a/drivers/net/dsa/b53/b53_mdio.c
+++ b/drivers/net/dsa/b53/b53_mdio.c
@@ -316,6 +316,17 @@ static int b53_mdio_probe(struct mdio_device *mdiodev)
return -ENODEV;
}
 
+   /* First probe will come from SWITCH_MDIO controller on the 7445D0
+* switch, which will conflict with the 7445 integrated switch
+* pseudo-phy (we end-up programming both). In that case, we return
+* -EPROBE_DEFER for the first time we get here, and wait until we come
+* back with the slave MDIO bus which has the correct indirection
+* layer setup
+*/
+   if (of_machine_is_compatible("brcm,bcm7445d0") &&
+   strcmp(mdiodev->bus->name, "sf2 slave mii"))
+   return -EPROBE_DEFER;
+
dev = b53_switch_alloc(>dev, _mdio_ops, mdiodev->bus);
if (!dev)
return -ENOMEM;
-- 
2.7.4



[PATCH net-next 3/5] net: dsa: b53: Implement ARL add/del/dump operations

2016-06-09 Thread Florian Fainelli
Adds support for FDB add/delete/dump using the ARL read/write logic and
the ARL search logic for faster dumps. The code is made flexible enough
it could support devices with a different register layout like BCM5325
and BCM5365 which have fewer number of entries or pack values into a
single 64 bits register.

Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 drivers/net/dsa/b53/b53_common.c | 261 +++
 drivers/net/dsa/b53/b53_priv.h   |  57 +
 drivers/net/dsa/b53/b53_regs.h   |  64 ++
 3 files changed, 382 insertions(+)

diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
index 6f0337d6dfa4..a9f1de407f57 100644
--- a/drivers/net/dsa/b53/b53_common.c
+++ b/drivers/net/dsa/b53/b53_common.c
@@ -26,7 +26,9 @@
 #include 
 #include 
 #include 
+#include 
 #include 
+#include 
 
 #include "b53_regs.h"
 #include "b53_priv.h"
@@ -777,6 +779,246 @@ static void b53_adjust_link(struct dsa_switch *ds, int 
port,
}
 }
 
+/* Address Resolution Logic routines */
+static int b53_arl_op_wait(struct b53_device *dev)
+{
+   unsigned int timeout = 10;
+   u8 reg;
+
+   do {
+   b53_read8(dev, B53_ARLIO_PAGE, B53_ARLTBL_RW_CTRL, );
+   if (!(reg & ARLTBL_START_DONE))
+   return 0;
+
+   usleep_range(1000, 2000);
+   } while (timeout--);
+
+   dev_warn(dev->dev, "timeout waiting for ARL to finish: 0x%02x\n", reg);
+
+   return -ETIMEDOUT;
+}
+
+static int b53_arl_rw_op(struct b53_device *dev, unsigned int op)
+{
+   u8 reg;
+
+   if (op > ARLTBL_RW)
+   return -EINVAL;
+
+   b53_read8(dev, B53_ARLIO_PAGE, B53_ARLTBL_RW_CTRL, );
+   reg |= ARLTBL_START_DONE;
+   if (op)
+   reg |= ARLTBL_RW;
+   else
+   reg &= ~ARLTBL_RW;
+   b53_write8(dev, B53_ARLIO_PAGE, B53_ARLTBL_RW_CTRL, reg);
+
+   return b53_arl_op_wait(dev);
+}
+
+static int b53_arl_read(struct b53_device *dev, u64 mac,
+   u16 vid, struct b53_arl_entry *ent, u8 *idx,
+   bool is_valid)
+{
+   unsigned int i;
+   int ret;
+
+   ret = b53_arl_op_wait(dev);
+   if (ret)
+   return ret;
+
+   /* Read the bins */
+   for (i = 0; i < dev->num_arl_entries; i++) {
+   u64 mac_vid;
+   u32 fwd_entry;
+
+   b53_read64(dev, B53_ARLIO_PAGE,
+  B53_ARLTBL_MAC_VID_ENTRY(i), _vid);
+   b53_read32(dev, B53_ARLIO_PAGE,
+  B53_ARLTBL_DATA_ENTRY(i), _entry);
+   b53_arl_to_entry(ent, mac_vid, fwd_entry);
+
+   if (!(fwd_entry & ARLTBL_VALID))
+   continue;
+   if ((mac_vid & ARLTBL_MAC_MASK) != mac)
+   continue;
+   *idx = i;
+   }
+
+   return -ENOENT;
+}
+
+static int b53_arl_op(struct b53_device *dev, int op, int port,
+ const unsigned char *addr, u16 vid, bool is_valid)
+{
+   struct b53_arl_entry ent;
+   u32 fwd_entry;
+   u64 mac, mac_vid = 0;
+   u8 idx = 0;
+   int ret;
+
+   /* Convert the array into a 64-bit MAC */
+   mac = b53_mac_to_u64(addr);
+
+   /* Perform a read for the given MAC and VID */
+   b53_write48(dev, B53_ARLIO_PAGE, B53_MAC_ADDR_IDX, mac);
+   b53_write16(dev, B53_ARLIO_PAGE, B53_VLAN_ID_IDX, vid);
+
+   /* Issue a read operation for this MAC */
+   ret = b53_arl_rw_op(dev, 1);
+   if (ret)
+   return ret;
+
+   ret = b53_arl_read(dev, mac, vid, , , is_valid);
+   /* If this is a read, just finish now */
+   if (op)
+   return ret;
+
+   /* We could not find a matching MAC, so reset to a new entry */
+   if (ret) {
+   fwd_entry = 0;
+   idx = 1;
+   }
+
+   memset(, 0, sizeof(ent));
+   ent.port = port;
+   ent.is_valid = is_valid;
+   ent.vid = vid;
+   ent.is_static = true;
+   memcpy(ent.mac, addr, ETH_ALEN);
+   b53_arl_from_entry(_vid, _entry, );
+
+   b53_write64(dev, B53_ARLIO_PAGE,
+   B53_ARLTBL_MAC_VID_ENTRY(idx), mac_vid);
+   b53_write32(dev, B53_ARLIO_PAGE,
+   B53_ARLTBL_DATA_ENTRY(idx), fwd_entry);
+
+   return b53_arl_rw_op(dev, 0);
+}
+
+static int b53_fdb_prepare(struct dsa_switch *ds, int port,
+  const struct switchdev_obj_port_fdb *fdb,
+  struct switchdev_trans *trans)
+{
+   struct b53_device *priv = ds_to_priv(ds);
+
+   /* 5325 and 5365 require some more massaging, but could
+* be supported eventually
+*/
+   if (is5325(priv) || is5365(priv))
+   return -EOPNOTSUPP;
+
+   return 0;
+}
+
+static void b53_fdb_add(struct dsa_switch *ds, int port,

[PATCH net-next] net: dsa: Provide CPU port statistics to master netdev

2016-06-03 Thread Florian Fainelli
This patch overloads the DSA master netdev, aka CPU Ethernet MAC to also
include switch-side statistics, which is useful for debugging purposes,
when the switch is not properly connected to the Ethernet MAC (duplex
mismatch, (RG)MII electrical issues etc.).

We accomplish this by retaining the original copy of the master netdev's
ethtool_ops, and just overload the 3 operations we care about:
get_sset_count, get_strings and get_ethtool_stats so as to intercept
these calls and call into the original master_netdev ethtool_ops, plus
our own.

We take this approach as opposed to providing a set of DSA helper
functions that would retrive the CPU port's statistics, because the
entire purpose of DSA is to allow unmodified Ethernet MAC drivers to be
used as CPU conduit interfaces, therefore, statistics overlay in such
drivers would simply not scale.

The new ethtool -S  output would therefore look like this now:
 statistics
p<2 digits cpu port number>_

Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
Changes from RFC:

- prepend the CPU port as a prefix to make it clear what the stats are
  about, master netdev interface stats are unchanged

 include/net/dsa.h |  5 
 net/dsa/slave.c   | 88 +++
 2 files changed, 93 insertions(+)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index 2d280aba97e2..8e86af87c84f 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -111,6 +111,11 @@ struct dsa_switch_tree {
enum dsa_tag_protocol   tag_protocol;
 
/*
+* Original copy of the master netdev ethtool_ops
+*/
+   struct ethtool_ops  master_ethtool_ops;
+
+   /*
 * The switch and port to which the CPU is attached.
 */
s8  cpu_switch;
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 3b6750f5e68b..5ea8a40c8d33 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -666,6 +666,78 @@ static void dsa_slave_get_strings(struct net_device *dev,
}
 }
 
+static void dsa_cpu_port_get_ethtool_stats(struct net_device *dev,
+  struct ethtool_stats *stats,
+  uint64_t *data)
+{
+   struct dsa_switch_tree *dst = dev->dsa_ptr;
+   struct dsa_switch *ds = dst->ds[0];
+   s8 cpu_port = dst->cpu_port;
+   int count = 0;
+
+   if (dst->master_ethtool_ops.get_sset_count) {
+   count = dst->master_ethtool_ops.get_sset_count(dev,
+  ETH_SS_STATS);
+   dst->master_ethtool_ops.get_ethtool_stats(dev, stats, data);
+   }
+
+   if (ds->drv->get_ethtool_stats)
+   ds->drv->get_ethtool_stats(ds, cpu_port, data + count);
+}
+
+static int dsa_cpu_port_get_sset_count(struct net_device *dev, int sset)
+{
+   struct dsa_switch_tree *dst = dev->dsa_ptr;
+   struct dsa_switch *ds = dst->ds[0];
+   int count = 0;
+
+   if (dst->master_ethtool_ops.get_sset_count)
+   count += dst->master_ethtool_ops.get_sset_count(dev, sset);
+
+   if (sset == ETH_SS_STATS && ds->drv->get_sset_count)
+   count += ds->drv->get_sset_count(ds);
+
+   return count;
+}
+
+static void dsa_cpu_port_get_strings(struct net_device *dev,
+uint32_t stringset, uint8_t *data)
+{
+   struct dsa_switch_tree *dst = dev->dsa_ptr;
+   struct dsa_switch *ds = dst->ds[0];
+   s8 cpu_port = dst->cpu_port;
+   int len = ETH_GSTRING_LEN;
+   int mcount = 0, count;
+   unsigned int i;
+   uint8_t pfx[4];
+   uint8_t *ndata;
+
+   snprintf(pfx, sizeof(pfx), "p%.2d", cpu_port);
+   /* We do not want to be NULL-terminated, since this is a prefix */
+   pfx[sizeof(pfx) - 1] = '_';
+
+   if (dst->master_ethtool_ops.get_sset_count) {
+   mcount = dst->master_ethtool_ops.get_sset_count(dev,
+   ETH_SS_STATS);
+   dst->master_ethtool_ops.get_strings(dev, stringset, data);
+   }
+
+   if (stringset == ETH_SS_STATS && ds->drv->get_strings) {
+   ndata = data + mcount * len;
+   /* This function copies ETH_GSTRINGS_LEN bytes, we will mangle
+* the output after to prepend our CPU port prefix we
+* constructed earlier
+*/
+   ds->drv->get_strings(ds, cpu_port, ndata);
+   count = ds->drv->get_sset_count(ds);
+   for (i = 0; i < count; i++) {
+   memmove(ndata + (i * len + sizeof(pfx)),
+   ndata + i * len, len - sizeof(pfx));
+   memcpy(ndata + i * len, pfx, sizeof(pfx));
+   }
+   }
+}
+
 

[PATCH net-next 1/9] net: dsa: Prepare to support legacy DT binding

2016-06-03 Thread Florian Fainelli
In preparation for supporting the legacy DT binding, call
dsa_get_ports() early on to allow two different parsing code paths to be
called.

Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 net/dsa/dsa2.c | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index 4e5051bed643..b5640d8ffbae 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -552,7 +552,7 @@ static struct device_node *dsa_get_ports(struct dsa_switch 
*ds,
return ports;
 }
 
-static int _dsa_register_switch(struct dsa_switch *ds, struct device_node *np)
+static int __dsa_register_switch(struct dsa_switch *ds, struct device_node *np)
 {
struct device_node *ports = dsa_get_ports(ds, np);
struct dsa_switch_tree *dst;
@@ -622,6 +622,16 @@ out:
return err;
 }
 
+static int _dsa_register_switch(struct dsa_switch *ds, struct device_node *np)
+{
+   struct device_node *ports = dsa_get_ports(ds, np);
+
+   if (IS_ERR(ports))
+   return PTR_ERR(ports);
+
+   return __dsa_register_switch(ds, np);
+}
+
 int dsa_register_switch(struct dsa_switch *ds, struct device_node *np)
 {
int err;
-- 
2.7.4



[PATCH net-next 0/9] net: dsa: misc improvements

2016-06-03 Thread Florian Fainelli
Hi all,

This patch series builds on top of Andrew's "New DSA bind, switches as devices"
patch set and does the following:

- add support for the old DSA binding with the new dsa_register_switch() API
  which is needed by some platforms where the Device Tree is pretty much frozen

- add a few helper functions/goodies for net/dsa/dsa2.c to be as close as 
possible
  from net/dsa/dsa.c in terms of what drivers can expect, in particular the 
slave
  MDIO bus and the enabled_port_mask and phy_mii_mask

- fix the CPU port ethtools ops to work in a multiple tree setup since we can
  no longer assume a single tree is supported

- finally conver the bcm_sf2 driver to be a true platform device driver and
  slightly rework its internal vs. external MDIO bus indirect read/writes to
  be cleaner

Florian Fainelli (9):
  net: dsa: Prepare to support legacy DT binding
  net: dsa: Add support for parsing the old binding
  net: dsa: Provide unique DSA slave MII bus names
  net: dsa: Initialize ds->enabled_port_mask and ds->phys_mii_mask
  net: dsa: Export suspend/resume functions
  net: dsa: Add initialization helper for CPU port ethtool_ops
  net: dsa: Initialize CPU port ethtool ops per tree
  net: dsa: bcm_sf2: Make it a real platform device driver
  net: dsa: bcm_sf2: Register our slave MDIO bus

 drivers/net/dsa/bcm_sf2.c | 390 +-
 drivers/net/dsa/bcm_sf2.h |   6 +
 include/net/dsa.h |  14 ++
 net/dsa/dsa.c |  35 -
 net/dsa/dsa2.c| 199 ---
 net/dsa/dsa_priv.h|   3 +
 net/dsa/slave.c   |  25 ++-
 7 files changed, 491 insertions(+), 181 deletions(-)

-- 
2.7.4



[PATCH net-next 7/7] net: dsa: bcm_sf2: Register our slave MDIO bus

2016-06-03 Thread Florian Fainelli
Register a slave MDIO bus which allows us to divert problematic
read/writes towards conflicting pseudo-PHY address (30). Do no longer
rely on DSA's slave_mii_bus, but instead provide our own implementation
which offers more flexibility as to what to do, and when to register it.

Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 drivers/net/dsa/bcm_sf2.c | 141 --
 drivers/net/dsa/bcm_sf2.h |   6 ++
 2 files changed, 106 insertions(+), 41 deletions(-)

diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 8dac74a6b5df..502ca65435bf 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -948,23 +949,6 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds)
bcm_sf2_port_disable(ds, port, NULL);
}
 
-   /* Include the pseudo-PHY address and the broadcast PHY address to
-* divert reads towards our workaround. This is only required for
-* 7445D0, since 7445E0 disconnects the internal switch pseudo-PHY such
-* that we can use the regular SWITCH_MDIO master controller instead.
-*
-* By default, DSA initializes ds->phys_mii_mask to
-* ds->enabled_port_mask to have a 1:1 mapping between Port address
-* and PHY address in order to utilize the slave_mii_bus instance to
-* read from Port PHYs. This is not what we want here, so we
-* initialize phys_mii_mask 0 to always utilize the "master" MDIO
-* bus backed by the "mdio-unimac" driver.
-*/
-   if (of_machine_is_compatible("brcm,bcm7445d0"))
-   ds->phys_mii_mask |= ((1 << BRCM_PSEUDO_PHY_ADDR) | (1 << 0));
-   else
-   ds->phys_mii_mask = 0;
-
return 0;
 }
 
@@ -985,10 +969,9 @@ static u32 bcm_sf2_sw_get_phy_flags(struct dsa_switch *ds, 
int port)
return priv->hw_params.gphy_rev;
 }
 
-static int bcm_sf2_sw_indir_rw(struct dsa_switch *ds, int op, int addr,
+static int bcm_sf2_sw_indir_rw(struct bcm_sf2_priv *priv, int op, int addr,
   int regnum, u16 val)
 {
-   struct bcm_sf2_priv *priv = ds_to_priv(ds);
int ret = 0;
u32 reg;
 
@@ -1017,32 +1000,31 @@ static int bcm_sf2_sw_indir_rw(struct dsa_switch *ds, 
int op, int addr,
return ret & 0x;
 }
 
-static int bcm_sf2_sw_phy_read(struct dsa_switch *ds, int addr, int regnum)
+static int bcm_sf2_sw_phy_read(struct mii_bus *bus, int addr, int regnum)
 {
-   /* Intercept reads from the MDIO broadcast address or Broadcom
-* pseudo-PHY address
+   struct bcm_sf2_priv *priv = bus->priv;
+
+   /* Intercept reads from Broadcom pseudo-PHY address, else, send
+* them to our master MDIO bus controller
 */
-   switch (addr) {
-   case 0:
-   case BRCM_PSEUDO_PHY_ADDR:
-   return bcm_sf2_sw_indir_rw(ds, 1, addr, regnum, 0);
-   default:
-   return 0x;
-   }
+   if (addr == BRCM_PSEUDO_PHY_ADDR && priv->indir_phy_mask & BIT(addr))
+   return bcm_sf2_sw_indir_rw(priv, 1, addr, regnum, 0);
+   else
+   return mdiobus_read(priv->master_mii_bus, addr, regnum);
 }
 
-static int bcm_sf2_sw_phy_write(struct dsa_switch *ds, int addr, int regnum,
+static int bcm_sf2_sw_phy_write(struct mii_bus *bus, int addr, int regnum,
u16 val)
 {
-   /* Intercept writes to the MDIO broadcast address or Broadcom
-* pseudo-PHY address
+   struct bcm_sf2_priv *priv = bus->priv;
+
+   /* Intercept writes to the Broadcom pseudo-PHY address, else,
+* send them to our master MDIO bus controller
 */
-   switch (addr) {
-   case 0:
-   case BRCM_PSEUDO_PHY_ADDR:
-   bcm_sf2_sw_indir_rw(ds, 0, addr, regnum, val);
-   break;
-   }
+   if (addr == BRCM_PSEUDO_PHY_ADDR && priv->indir_phy_mask & BIT(addr))
+   bcm_sf2_sw_indir_rw(priv, 0, addr, regnum, val);
+   else
+   mdiobus_write(priv->master_mii_bus, addr, regnum, val);
 
return 0;
 }
@@ -1283,8 +1265,6 @@ static struct dsa_switch_driver bcm_sf2_switch_ops = {
.setup  = bcm_sf2_sw_setup,
.set_addr   = bcm_sf2_sw_set_addr,
.get_phy_flags  = bcm_sf2_sw_get_phy_flags,
-   .phy_read   = bcm_sf2_sw_phy_read,
-   .phy_write  = bcm_sf2_sw_phy_write,
.get_strings= bcm_sf2_sw_get_strings,
.get_ethtool_stats  = bcm_sf2_sw_get_ethtool_stats,
.get_sset_count = bcm_sf2_sw_get_sset_count,
@@ -1307,6 +1287,75 @@ static struct dsa_switch_driver bcm_sf2_switch_ops = {
.port_fdb_dump  = bcm_sf2_sw_

[PATCH net-next 5/9] net: dsa: Export suspend/resume functions

2016-06-03 Thread Florian Fainelli
In preparation for allowing switch drivers to implement system-wide
suspend/resume functions, export dsa_switch_suspend and
dsa_switch_resume() such that these are callable from the appropriate
driver specific suspend/resume functions.

Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 include/net/dsa.h | 14 ++
 net/dsa/dsa.c |  6 --
 2 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index d6ed5dee73e5..c5abaeda84f3 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -382,4 +382,18 @@ static inline bool dsa_uses_tagged_protocol(struct 
dsa_switch_tree *dst)
 
 void dsa_unregister_switch(struct dsa_switch *ds);
 int dsa_register_switch(struct dsa_switch *ds, struct device_node *np);
+#ifdef CONFIG_PM_SLEEP
+int dsa_switch_suspend(struct dsa_switch *ds);
+int dsa_switch_resume(struct dsa_switch *ds);
+#else
+static inline int dsa_switch_suspend(struct dsa_switch *ds)
+{
+   return 0;
+}
+static inline int dsa_switch_resume(struct dsa_switch *ds)
+{
+   return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
 #endif
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index d8cb2acd4f0a..ebc29a1bee08 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -500,7 +500,7 @@ static void dsa_switch_destroy(struct dsa_switch *ds)
 }
 
 #ifdef CONFIG_PM_SLEEP
-static int dsa_switch_suspend(struct dsa_switch *ds)
+int dsa_switch_suspend(struct dsa_switch *ds)
 {
int i, ret = 0;
 
@@ -519,8 +519,9 @@ static int dsa_switch_suspend(struct dsa_switch *ds)
 
return ret;
 }
+EXPORT_SYMBOL_GPL(dsa_switch_suspend);
 
-static int dsa_switch_resume(struct dsa_switch *ds)
+int dsa_switch_resume(struct dsa_switch *ds)
 {
int i, ret = 0;
 
@@ -542,6 +543,7 @@ static int dsa_switch_resume(struct dsa_switch *ds)
 
return 0;
 }
+EXPORT_SYMBOL_GPL(dsa_switch_resume);
 #endif
 
 /* platform driver init and cleanup */
-- 
2.7.4



[PATCH net-next 4/9] net: dsa: Initialize ds->enabled_port_mask and ds->phys_mii_mask

2016-06-03 Thread Florian Fainelli
Some drivers heavily rely on these two bitmasks to contain the correct
values for them to successfully probe and initialize at drv->setup()
time, calculate correct values to put in both masks.

To avoid multiple ports lookup, we also try to set dst->cpu_port during
dsa_parse_ports_dn(), which is mostly useful for the case where we probe
using the legacy binding which has properties/nodes in different places
and does not use dsa_dst_parse().

Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 net/dsa/dsa2.c | 59 ++
 1 file changed, 47 insertions(+), 12 deletions(-)

diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index 23273fd984a8..e8386157de30 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -281,6 +281,7 @@ static void dsa_user_port_unapply(struct device_node *port, 
u32 index,
if (ds->ports[index].netdev) {
dsa_slave_destroy(ds->ports[index].netdev);
ds->ports[index].netdev = NULL;
+   ds->enabled_port_mask &= ~(1 << index);
}
 }
 
@@ -290,6 +291,13 @@ static int dsa_ds_apply(struct dsa_switch_tree *dst, 
struct dsa_switch *ds)
u32 index;
int err;
 
+   /* Initialize ds->phys_mii_mask before registering the slave MDIO bus
+* driver and before drv->setup() has run, since the switch drivers and
+* the slave MDIO bus driver rely on these values for probing PHY
+* devices or not
+*/
+   ds->phys_mii_mask = ds->enabled_port_mask;
+
err = ds->drv->setup(ds);
if (err < 0)
return err;
@@ -302,6 +310,18 @@ static int dsa_ds_apply(struct dsa_switch_tree *dst, 
struct dsa_switch *ds)
if (err < 0)
return err;
 
+   if (!ds->slave_mii_bus && ds->drv->phy_read) {
+   ds->slave_mii_bus = devm_mdiobus_alloc(ds->dev);
+   if (!ds->slave_mii_bus)
+   return err;
+
+   dsa_slave_mii_bus_init(ds);
+
+   err = mdiobus_register(ds->slave_mii_bus);
+   if (err < 0)
+   return err;
+   }
+
for (index = 0; index < DSA_MAX_PORTS; index++) {
port = ds->ports[index].dn;
if (!port)
@@ -421,7 +441,11 @@ static int _dsa_cpu_parse(struct dsa_switch_tree *dst,
 
if (dst->cpu_switch == -1) {
dst->cpu_switch = ds->index;
-   dst->cpu_port = index;
+   /* Only assign dst->cpu_port if not done already by
+* dsa_parse_ports_dn
+*/
+   if (!dst->cpu_port)
+   dst->cpu_port = index;
}
 
dst->tag_ops = dsa_resolve_tag_protocol(ds->drv->tag_protocol);
@@ -517,6 +541,15 @@ static int dsa_parse_ports_dn(struct device_node *ports, 
struct dsa_switch *ds)
return -EINVAL;
 
ds->ports[reg].dn = port;
+
+   if (dsa_port_is_cpu(port))
+   ds->dst->cpu_port = reg;
+   else
+   /* Initialize enabled_port_mask now for drv->setup()
+* to have access to a correct value, just like what
+* net/dsa/dsa.c::dsa_switch_setup_one does.
+*/
+   ds->enabled_port_mask |= 1 << reg;
}
 
return 0;
@@ -585,10 +618,6 @@ static int _dsa_register_switch_legacy(struct dsa_switch 
*ds, struct device_node
if (index >= DSA_MAX_SWITCHES)
return -EINVAL;
 
-   err = dsa_parse_ports_dn(np->child, ds);
-   if (err)
-   return err;
-
dst = dsa_get_dst(tree);
if (!dst) {
dst = dsa_add_dst(tree);
@@ -596,12 +625,17 @@ static int _dsa_register_switch_legacy(struct dsa_switch 
*ds, struct device_node
return -ENOMEM;
}
 
+   ds->dst = dst;
+
+   err = dsa_parse_ports_dn(np->child, ds);
+   if (err)
+   return err;
+
if (dst->ds[index]) {
err = -EBUSY;
goto out;
}
 
-   ds->dst = dst;
ds->index = index;
dsa_dst_add_ds(dst, ds, index);
 
@@ -633,7 +667,7 @@ static int _dsa_register_switch_legacy(struct dsa_switch 
*ds, struct device_node
goto out_del_dst;
}
 
-   err = _dsa_cpu_parse(dst, ds, ethernet_dev, index);
+   err = _dsa_cpu_parse(dst, ds, ethernet_dev, dst->cpu_port);
if (err)
goto out_del_dst;
 
@@ -676,10 +710,6 @@ static int __dsa_register_switch(struct dsa_switch *ds, 
struct device_node *np)
if (IS_ERR(ports))
return PTR_ERR(ports);
 
-   err = dsa_parse_ports_dn(ports, ds);
-   if (err)
-   return er

Re: [PATCH net-next] net: dsa: bcm_sf2: Implement FDB operations

2016-06-03 Thread Florian Fainelli
On 06/03/2016 05:05 PM, Florian Fainelli wrote:
> Add support for the FDB add, delete, and dump operations. The add and
> delete operations are implemented using directed ARL operations using
> the specified MAC address and consist in a read operation, write and
> readback operation.
> 
> The dump operation consists in using the ARL search and software
> filtering entries which are not for the desired port.

And this one too should be discarded.
-- 
Florian


Re: [PATCH net-next 0/9] net: dsa: misc improvements

2016-06-03 Thread Florian Fainelli
On 06/03/2016 05:05 PM, Florian Fainelli wrote:
> Hi all,
> 
> This patch series builds on top of Andrew's "New DSA bind, switches as 
> devices"
> patch set and does the following:
> 
> - add support for the old DSA binding with the new dsa_register_switch() API
>   which is needed by some platforms where the Device Tree is pretty much 
> frozen
> 
> - add a few helper functions/goodies for net/dsa/dsa2.c to be as close as 
> possible
>   from net/dsa/dsa.c in terms of what drivers can expect, in particular the 
> slave
>   MDIO bus and the enabled_port_mask and phy_mii_mask
> 
> - fix the CPU port ethtools ops to work in a multiple tree setup since we can
>   no longer assume a single tree is supported
> 
> - finally conver the bcm_sf2 driver to be a true platform device driver and
>   slightly rework its internal vs. external MDIO bus indirect read/writes to
>   be cleaner

David, I cleaned up my mess in patchwork to leave just the relevant
patches for you to review and apply, sorry about that, it's Friday.
-- 
Florian


[PATCH net-next] net: dsa: bcm_sf2: Implement FDB operations

2016-06-03 Thread Florian Fainelli
Add support for the FDB add, delete, and dump operations. The add and
delete operations are implemented using directed ARL operations using
the specified MAC address and consist in a read operation, write and
readback operation.

The dump operation consists in using the ARL search and software
filtering entries which are not for the desired port.

Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 drivers/net/dsa/bcm_sf2.c  | 236 +
 drivers/net/dsa/bcm_sf2.h  |  56 ++
 drivers/net/dsa/bcm_sf2_regs.h |  43 
 3 files changed, 335 insertions(+)

diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 9d56515f4c4d..4f32b8a530bf 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -25,6 +25,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 #include "bcm_sf2.h"
 #include "bcm_sf2_regs.h"
@@ -555,6 +557,236 @@ static int bcm_sf2_sw_br_set_stp_state(struct dsa_switch 
*ds, int port,
return 0;
 }
 
+/* Address Resolution Logic routines */
+static int bcm_sf2_arl_op_wait(struct bcm_sf2_priv *priv)
+{
+   unsigned int timeout = 10;
+   u32 reg;
+
+   do {
+   reg = core_readl(priv, CORE_ARLA_RWCTL);
+   if (!(reg & ARL_STRTDN))
+   return 0;
+
+   usleep_range(1000, 2000);
+   } while (timeout--);
+
+   return -ETIMEDOUT;
+}
+
+static int bcm_sf2_arl_rw_op(struct bcm_sf2_priv *priv, unsigned int op)
+{
+   u32 cmd;
+
+   if (op > ARL_RW)
+   return -EINVAL;
+
+   cmd = core_readl(priv, CORE_ARLA_RWCTL);
+   cmd &= ~IVL_SVL_SELECT;
+   cmd |= ARL_STRTDN;
+   if (op)
+   cmd |= ARL_RW;
+   else
+   cmd &= ~ARL_RW;
+   core_writel(priv, cmd, CORE_ARLA_RWCTL);
+
+   return bcm_sf2_arl_op_wait(priv);
+}
+
+static int bcm_sf2_arl_read(struct bcm_sf2_priv *priv, u64 mac,
+   u16 vid, struct bcm_sf2_arl_entry *ent, u8 *idx,
+   bool is_valid)
+{
+   unsigned int i;
+   int ret;
+
+   ret = bcm_sf2_arl_op_wait(priv);
+   if (ret)
+   return ret;
+
+   /* Read the 4 bins */
+   for (i = 0; i < 4; i++) {
+   u64 mac_vid;
+   u32 fwd_entry;
+
+   mac_vid = core_readq(priv, CORE_ARLA_MACVID_ENTRY(i));
+   fwd_entry = core_readl(priv, CORE_ARLA_FWD_ENTRY(i));
+   bcm_sf2_arl_to_entry(ent, mac_vid, fwd_entry);
+
+   if (ent->is_valid && is_valid) {
+   *idx = i;
+   return 0;
+   }
+
+   /* This is the MAC we just deleted */
+   if (!is_valid && (mac_vid & mac))
+   return 0;
+   }
+
+   return -ENOENT;
+}
+
+static int bcm_sf2_arl_op(struct bcm_sf2_priv *priv, int op, int port,
+ const unsigned char *addr, u16 vid, bool is_valid)
+{
+   struct bcm_sf2_arl_entry ent;
+   u32 fwd_entry;
+   u64 mac, mac_vid = 0;
+   u8 idx = 0;
+   int ret;
+
+   /* Convert the array into a 64-bit MAC */
+   mac = bcm_sf2_mac_to_u64(addr);
+
+   /* Perform a read for the given MAC and VID */
+   core_writeq(priv, mac, CORE_ARLA_MAC);
+   core_writel(priv, vid, CORE_ARLA_VID);
+
+   /* Issue a read operation for this MAC */
+   ret = bcm_sf2_arl_rw_op(priv, 1);
+   if (ret)
+   return ret;
+
+   ret = bcm_sf2_arl_read(priv, mac, vid, , , is_valid);
+   /* If this is a read, just finish now */
+   if (op)
+   return ret;
+
+   /* We could not find a matching MAC, so reset to a new entry */
+   if (ret) {
+   fwd_entry = 0;
+   idx = 0;
+   }
+
+   memset(, 0, sizeof(ent));
+   ent.port = port;
+   ent.is_valid = is_valid;
+   ent.vid = vid;
+   ent.is_static = true;
+   memcpy(ent.mac, addr, ETH_ALEN);
+   bcm_sf2_arl_from_entry(_vid, _entry, );
+
+   core_writeq(priv, mac_vid, CORE_ARLA_MACVID_ENTRY(idx));
+   core_writel(priv, fwd_entry, CORE_ARLA_FWD_ENTRY(idx));
+
+   ret = bcm_sf2_arl_rw_op(priv, 0);
+   if (ret)
+   return ret;
+
+   /* Re-read the entry to check */
+   return bcm_sf2_arl_read(priv, mac, vid, , , is_valid);
+}
+
+static int bcm_sf2_sw_fdb_prepare(struct dsa_switch *ds, int port,
+ const struct switchdev_obj_port_fdb *fdb,
+ struct switchdev_trans *trans)
+{
+   /* We do not need to do anything specific here yet */
+   return 0;
+}
+
+static int bcm_sf2_sw_fdb_add(struct dsa_switch *ds, int port,
+ const struct switchdev_obj_port_fdb *fdb,
+ struct switchdev_trans *trans)
+{
+   struct bcm_sf2_p

[PATCH net-next 6/9] net: dsa: Add initialization helper for CPU port ethtool_ops

2016-06-03 Thread Florian Fainelli
Add a helper function: dsa_cpu_port_ethtool_init() which initializes a
custom ethtool_ops structure with custom DSA ethtool operations for CPU
ports. This is a preliminary change to move the initialization outside
of net/dsa/slave.c.

Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 net/dsa/dsa_priv.h |  1 +
 net/dsa/slave.c| 14 --
 2 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index b42f1a5f95f3..106a9f067f94 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -58,6 +58,7 @@ const struct dsa_device_ops *dsa_resolve_tag_protocol(int 
tag_protocol);
 /* slave.c */
 extern const struct dsa_device_ops notag_netdev_ops;
 void dsa_slave_mii_bus_init(struct dsa_switch *ds);
+void dsa_cpu_port_ethtool_init(struct ethtool_ops *ops);
 int dsa_slave_create(struct dsa_switch *ds, struct device *parent,
 int port, const char *name);
 void dsa_slave_destroy(struct net_device *slave_dev);
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index a51dfedf0014..8d159932e082 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -865,6 +865,13 @@ static void dsa_slave_poll_controller(struct net_device 
*dev)
 }
 #endif
 
+void dsa_cpu_port_ethtool_init(struct ethtool_ops *ops)
+{
+   ops->get_sset_count = dsa_cpu_port_get_sset_count;
+   ops->get_ethtool_stats = dsa_cpu_port_get_ethtool_stats;
+   ops->get_strings = dsa_cpu_port_get_strings;
+}
+
 static const struct ethtool_ops dsa_slave_ethtool_ops = {
.get_settings   = dsa_slave_get_settings,
.set_settings   = dsa_slave_set_settings,
@@ -1124,12 +1131,7 @@ int dsa_slave_create(struct dsa_switch *ds, struct 
device *parent,
   sizeof(struct ethtool_ops));
memcpy(_cpu_port_ethtool_ops, >master_ethtool_ops,
   sizeof(struct ethtool_ops));
-   dsa_cpu_port_ethtool_ops.get_sset_count =
-   dsa_cpu_port_get_sset_count;
-   dsa_cpu_port_ethtool_ops.get_ethtool_stats =
-   dsa_cpu_port_get_ethtool_stats;
-   dsa_cpu_port_ethtool_ops.get_strings =
-   dsa_cpu_port_get_strings;
+   dsa_cpu_port_ethtool_init(_cpu_port_ethtool_ops);
master->ethtool_ops = _cpu_port_ethtool_ops;
}
eth_hw_addr_inherit(slave_dev, master);
-- 
2.7.4



[PATCH net-next 7/9] net: dsa: Initialize CPU port ethtool ops per tree

2016-06-03 Thread Florian Fainelli
Now that we can properly support multiple distinct trees in the system,
using a global variable: dsa_cpu_port_ethtool_ops is getting clobbered
as soon as the second switch tree gets probed, and we don't want that.

We need to move this to be dynamically allocated, and since we can't
really be comparing addresses anymore to determine first time
initialization versus any other times, just move this to dsa.c and
dsa2.c where the remainder of the dst/ds initialization happens.

Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 net/dsa/dsa.c  | 28 
 net/dsa/dsa2.c |  2 +-
 net/dsa/dsa_priv.h |  2 ++
 net/dsa/slave.c| 10 --
 4 files changed, 31 insertions(+), 11 deletions(-)

diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index ebc29a1bee08..8fb8de6fb82d 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -266,6 +266,30 @@ const struct dsa_device_ops *dsa_resolve_tag_protocol(int 
tag_protocol)
return ops;
 }
 
+int dsa_cpu_port_ethtool_setup(struct dsa_switch_tree *dst,
+  struct dsa_switch *ds)
+{
+   struct net_device *master;
+   struct ethtool_ops *cpu_ops;
+
+   master = ds->dst->master_netdev;
+   if (ds->master_netdev)
+   master = ds->master_netdev;
+
+   cpu_ops = devm_kzalloc(ds->dev, sizeof(*cpu_ops), GFP_KERNEL);
+   if (!cpu_ops)
+   return -ENOMEM;
+
+   memcpy(>master_ethtool_ops, master->ethtool_ops,
+  sizeof(struct ethtool_ops));
+   memcpy(cpu_ops, >master_ethtool_ops,
+  sizeof(struct ethtool_ops));
+   dsa_cpu_port_ethtool_init(cpu_ops);
+   master->ethtool_ops = cpu_ops;
+
+   return 0;
+}
+
 static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
 {
struct dsa_switch_driver *drv = ds->drv;
@@ -379,6 +403,10 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, 
struct device *parent)
ret = 0;
}
 
+   ret = dsa_cpu_port_ethtool_setup(dst, ds);
+   if (ret)
+   return ret;
+
 #ifdef CONFIG_NET_DSA_HWMON
/* If the switch provides a temperature sensor,
 * register with hardware monitoring subsystem.
diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index e8386157de30..938262010524 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -346,7 +346,7 @@ static int dsa_ds_apply(struct dsa_switch_tree *dst, struct 
dsa_switch *ds)
continue;
}
 
-   return 0;
+   return dsa_cpu_port_ethtool_setup(dst, ds);
 }
 
 static void dsa_ds_unapply(struct dsa_switch_tree *dst, struct dsa_switch *ds)
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 106a9f067f94..3bb88b2fb580 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -54,6 +54,8 @@ int dsa_cpu_dsa_setup(struct dsa_switch *ds, struct device 
*dev,
  struct device_node *port_dn, int port);
 void dsa_cpu_dsa_destroy(struct device_node *port_dn);
 const struct dsa_device_ops *dsa_resolve_tag_protocol(int tag_protocol);
+int dsa_cpu_port_ethtool_setup(struct dsa_switch_tree *dst,
+  struct dsa_switch *ds);
 
 /* slave.c */
 extern const struct dsa_device_ops notag_netdev_ops;
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 8d159932e082..7236eb26dc97 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -892,8 +892,6 @@ static const struct ethtool_ops dsa_slave_ethtool_ops = {
.get_eee= dsa_slave_get_eee,
 };
 
-static struct ethtool_ops dsa_cpu_port_ethtool_ops;
-
 static const struct net_device_ops dsa_slave_netdev_ops = {
.ndo_open   = dsa_slave_open,
.ndo_stop   = dsa_slave_close,
@@ -1126,14 +1124,6 @@ int dsa_slave_create(struct dsa_switch *ds, struct 
device *parent,
 
slave_dev->features = master->vlan_features;
slave_dev->ethtool_ops = _slave_ethtool_ops;
-   if (master->ethtool_ops != _cpu_port_ethtool_ops) {
-   memcpy(>master_ethtool_ops, master->ethtool_ops,
-  sizeof(struct ethtool_ops));
-   memcpy(_cpu_port_ethtool_ops, >master_ethtool_ops,
-  sizeof(struct ethtool_ops));
-   dsa_cpu_port_ethtool_init(_cpu_port_ethtool_ops);
-   master->ethtool_ops = _cpu_port_ethtool_ops;
-   }
eth_hw_addr_inherit(slave_dev, master);
slave_dev->priv_flags |= IFF_NO_QUEUE;
slave_dev->netdev_ops = _slave_netdev_ops;
-- 
2.7.4



[PATCH net-next 2/9] net: dsa: Add support for parsing the old binding

2016-06-03 Thread Florian Fainelli
Extend dsa2.c to support parsing for the old binding, which mostly means
looking for more or less the same properties in different places.

Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 net/dsa/dsa2.c | 142 ++---
 1 file changed, 126 insertions(+), 16 deletions(-)

diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index b5640d8ffbae..23273fd984a8 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -408,21 +408,11 @@ static void dsa_dst_unapply(struct dsa_switch_tree *dst)
dst->applied = false;
 }
 
-static int dsa_cpu_parse(struct device_node *port, u32 index,
-struct dsa_switch_tree *dst,
-struct dsa_switch *ds)
+static int _dsa_cpu_parse(struct dsa_switch_tree *dst,
+  struct dsa_switch *ds,
+  struct net_device *ethernet_dev,
+  u32 index)
 {
-   struct net_device *ethernet_dev;
-   struct device_node *ethernet;
-
-   ethernet = of_parse_phandle(port, "ethernet", 0);
-   if (!ethernet)
-   return -EINVAL;
-
-   ethernet_dev = of_find_net_device_by_node(ethernet);
-   if (!ethernet_dev)
-   return -EPROBE_DEFER;
-
if (!ds->master_netdev)
ds->master_netdev = ethernet_dev;
 
@@ -445,6 +435,24 @@ static int dsa_cpu_parse(struct device_node *port, u32 
index,
return 0;
 }
 
+static int dsa_cpu_parse(struct device_node *port, u32 index,
+struct dsa_switch_tree *dst,
+struct dsa_switch *ds)
+{
+   struct net_device *ethernet_dev;
+   struct device_node *ethernet;
+
+   ethernet = of_parse_phandle(port, "ethernet", 0);
+   if (!ethernet)
+   return -EINVAL;
+
+   ethernet_dev = of_find_net_device_by_node(ethernet);
+   if (!ethernet_dev)
+   return -EPROBE_DEFER;
+
+   return _dsa_cpu_parse(dst, ds, ethernet_dev, index);
+}
+
 static int dsa_ds_parse(struct dsa_switch_tree *dst, struct dsa_switch *ds)
 {
struct device_node *port;
@@ -552,6 +560,108 @@ static struct device_node *dsa_get_ports(struct 
dsa_switch *ds,
return ports;
 }
 
+static int _dsa_register_switch_legacy(struct dsa_switch *ds, struct 
device_node *np)
+{
+   const char *compat = of_get_property(np, "compatible", NULL);
+   struct device_node *dn, *ethernet;
+   struct net_device *ethernet_dev;
+   struct dsa_switch_tree *dst;
+   u32 tree = 0, index;
+   int err;
+
+   /* Tree is implied by how many devices are present in the DT with the
+* supported compatible strings from net/dsa/dsa.c
+*/
+   for_each_compatible_node(dn, NULL, compat) {
+   if (dn != np)
+   tree++;
+   }
+
+   /* index is present in the "reg" property, second cell */
+   err = of_property_read_u32_index(np->child, "reg", 1, );
+   if (err)
+   return err;
+
+   if (index >= DSA_MAX_SWITCHES)
+   return -EINVAL;
+
+   err = dsa_parse_ports_dn(np->child, ds);
+   if (err)
+   return err;
+
+   dst = dsa_get_dst(tree);
+   if (!dst) {
+   dst = dsa_add_dst(tree);
+   if (!dst)
+   return -ENOMEM;
+   }
+
+   if (dst->ds[index]) {
+   err = -EBUSY;
+   goto out;
+   }
+
+   ds->dst = dst;
+   ds->index = index;
+   dsa_dst_add_ds(dst, ds, index);
+
+   err = dsa_dst_complete(dst);
+   if (err < 0)
+   goto out;
+
+   if (err == 1) {
+   /* Not all switches registered yet */
+   err = 0;
+   goto out;
+   }
+
+   if (dst->applied) {
+   pr_info("DSA: Disjoint trees?\n");
+   err = -EINVAL;
+   goto out_del_dst;
+   }
+
+   ethernet = of_parse_phandle(np, "dsa,ethernet", 0);
+   if (!ethernet) {
+   err = -EINVAL;
+   goto out_del_dst;
+   }
+
+   ethernet_dev = of_find_net_device_by_node(ethernet);
+   if (!ethernet_dev) {
+   err = -EPROBE_DEFER;
+   goto out_del_dst;
+   }
+
+   err = _dsa_cpu_parse(dst, ds, ethernet_dev, index);
+   if (err)
+   goto out_del_dst;
+
+   if (!dst->master_netdev) {
+   pr_warn("Tree has no master device\n");
+   goto out_del_dst;
+   }
+
+   pr_info("DSA: tree %d parsed\n", dst->tree);
+
+   err = dsa_dst_apply(dst);
+   if (err) {
+   dsa_dst_unapply(dst);
+   goto out_del_dst;
+   }
+
+   dsa_put_dst(dst);
+
+   return 0;
+
+out_del_dst:
+   dsa_dst_del_ds(dst, ds, ds->index);
+out:
+   dsa_put_dst(dst);

[PATCH net-next 9/9] net: dsa: bcm_sf2: Register our slave MDIO bus

2016-06-03 Thread Florian Fainelli
Register a slave MDIO bus which allows us to divert problematic
read/writes towards conflicting pseudo-PHY address (30). Do no longer
rely on DSA's slave_mii_bus, but instead provide our own implementation
which offers more flexibility as to what to do, and when to register it.

Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 drivers/net/dsa/bcm_sf2.c | 141 --
 drivers/net/dsa/bcm_sf2.h |   6 ++
 2 files changed, 106 insertions(+), 41 deletions(-)

diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 8dac74a6b5df..502ca65435bf 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -948,23 +949,6 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds)
bcm_sf2_port_disable(ds, port, NULL);
}
 
-   /* Include the pseudo-PHY address and the broadcast PHY address to
-* divert reads towards our workaround. This is only required for
-* 7445D0, since 7445E0 disconnects the internal switch pseudo-PHY such
-* that we can use the regular SWITCH_MDIO master controller instead.
-*
-* By default, DSA initializes ds->phys_mii_mask to
-* ds->enabled_port_mask to have a 1:1 mapping between Port address
-* and PHY address in order to utilize the slave_mii_bus instance to
-* read from Port PHYs. This is not what we want here, so we
-* initialize phys_mii_mask 0 to always utilize the "master" MDIO
-* bus backed by the "mdio-unimac" driver.
-*/
-   if (of_machine_is_compatible("brcm,bcm7445d0"))
-   ds->phys_mii_mask |= ((1 << BRCM_PSEUDO_PHY_ADDR) | (1 << 0));
-   else
-   ds->phys_mii_mask = 0;
-
return 0;
 }
 
@@ -985,10 +969,9 @@ static u32 bcm_sf2_sw_get_phy_flags(struct dsa_switch *ds, 
int port)
return priv->hw_params.gphy_rev;
 }
 
-static int bcm_sf2_sw_indir_rw(struct dsa_switch *ds, int op, int addr,
+static int bcm_sf2_sw_indir_rw(struct bcm_sf2_priv *priv, int op, int addr,
   int regnum, u16 val)
 {
-   struct bcm_sf2_priv *priv = ds_to_priv(ds);
int ret = 0;
u32 reg;
 
@@ -1017,32 +1000,31 @@ static int bcm_sf2_sw_indir_rw(struct dsa_switch *ds, 
int op, int addr,
return ret & 0x;
 }
 
-static int bcm_sf2_sw_phy_read(struct dsa_switch *ds, int addr, int regnum)
+static int bcm_sf2_sw_phy_read(struct mii_bus *bus, int addr, int regnum)
 {
-   /* Intercept reads from the MDIO broadcast address or Broadcom
-* pseudo-PHY address
+   struct bcm_sf2_priv *priv = bus->priv;
+
+   /* Intercept reads from Broadcom pseudo-PHY address, else, send
+* them to our master MDIO bus controller
 */
-   switch (addr) {
-   case 0:
-   case BRCM_PSEUDO_PHY_ADDR:
-   return bcm_sf2_sw_indir_rw(ds, 1, addr, regnum, 0);
-   default:
-   return 0x;
-   }
+   if (addr == BRCM_PSEUDO_PHY_ADDR && priv->indir_phy_mask & BIT(addr))
+   return bcm_sf2_sw_indir_rw(priv, 1, addr, regnum, 0);
+   else
+   return mdiobus_read(priv->master_mii_bus, addr, regnum);
 }
 
-static int bcm_sf2_sw_phy_write(struct dsa_switch *ds, int addr, int regnum,
+static int bcm_sf2_sw_phy_write(struct mii_bus *bus, int addr, int regnum,
u16 val)
 {
-   /* Intercept writes to the MDIO broadcast address or Broadcom
-* pseudo-PHY address
+   struct bcm_sf2_priv *priv = bus->priv;
+
+   /* Intercept writes to the Broadcom pseudo-PHY address, else,
+* send them to our master MDIO bus controller
 */
-   switch (addr) {
-   case 0:
-   case BRCM_PSEUDO_PHY_ADDR:
-   bcm_sf2_sw_indir_rw(ds, 0, addr, regnum, val);
-   break;
-   }
+   if (addr == BRCM_PSEUDO_PHY_ADDR && priv->indir_phy_mask & BIT(addr))
+   bcm_sf2_sw_indir_rw(priv, 0, addr, regnum, val);
+   else
+   mdiobus_write(priv->master_mii_bus, addr, regnum, val);
 
return 0;
 }
@@ -1283,8 +1265,6 @@ static struct dsa_switch_driver bcm_sf2_switch_ops = {
.setup  = bcm_sf2_sw_setup,
.set_addr   = bcm_sf2_sw_set_addr,
.get_phy_flags  = bcm_sf2_sw_get_phy_flags,
-   .phy_read   = bcm_sf2_sw_phy_read,
-   .phy_write  = bcm_sf2_sw_phy_write,
.get_strings= bcm_sf2_sw_get_strings,
.get_ethtool_stats  = bcm_sf2_sw_get_ethtool_stats,
.get_sset_count = bcm_sf2_sw_get_sset_count,
@@ -1307,6 +1287,75 @@ static struct dsa_switch_driver bcm_sf2_switch_ops = {
.port_fdb_dump  = bcm_sf2_sw_

Re: [PATCH net-next] net: dsa: Provide CPU port statistics to master netdev

2016-06-03 Thread Florian Fainelli
On 06/03/2016 05:05 PM, Florian Fainelli wrote:
> This patch overloads the DSA master netdev, aka CPU Ethernet MAC to also
> include switch-side statistics, which is useful for debugging purposes,
> when the switch is not properly connected to the Ethernet MAC (duplex
> mismatch, (RG)MII electrical issues etc.).
> 
> We accomplish this by retaining the original copy of the master netdev's
> ethtool_ops, and just overload the 3 operations we care about:
> get_sset_count, get_strings and get_ethtool_stats so as to intercept
> these calls and call into the original master_netdev ethtool_ops, plus
> our own.
> 
> We take this approach as opposed to providing a set of DSA helper
> functions that would retrive the CPU port's statistics, because the
> entire purpose of DSA is to allow unmodified Ethernet MAC drivers to be
> used as CPU conduit interfaces, therefore, statistics overlay in such
> drivers would simply not scale.

Disregard this patch, it was left in the patches folder...
-- 
Florian


[PATCH net-next 3/9] net: dsa: Provide unique DSA slave MII bus names

2016-06-03 Thread Florian Fainelli
In case we have multiples trees and switches with the same index, we
need to add another discriminating id: the switch tree.

Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 net/dsa/slave.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 15a492261895..a51dfedf0014 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -49,7 +49,8 @@ void dsa_slave_mii_bus_init(struct dsa_switch *ds)
ds->slave_mii_bus->name = "dsa slave smi";
ds->slave_mii_bus->read = dsa_slave_phy_read;
ds->slave_mii_bus->write = dsa_slave_phy_write;
-   snprintf(ds->slave_mii_bus->id, MII_BUS_ID_SIZE, "dsa-%d", ds->index);
+   snprintf(ds->slave_mii_bus->id, MII_BUS_ID_SIZE, "dsa-%d.%d",
+ds->dst->tree, ds->index);
ds->slave_mii_bus->parent = ds->dev;
ds->slave_mii_bus->phy_mask = ~ds->phys_mii_mask;
 }
-- 
2.7.4



[PATCH net-next 6/7] net: dsa: bcm_sf2: Make it a real platform device driver

2016-06-03 Thread Florian Fainelli
The Broadcom Starfighter 2 switch driver should be a proper platform
driver, now that the DSA code has been updated to allow that, register a
switch device, feed it with the proper configuration data coming from
Device Tree and register our switch device with DSA.

The bulk of the changes consist in moving what bcm_sf2_sw_setup() did
into the platform driver probe function.

Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 drivers/net/dsa/bcm_sf2.c | 251 --
 net/dsa/dsa.c |   1 -
 2 files changed, 151 insertions(+), 101 deletions(-)

diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 73df91bb0466..8dac74a6b5df 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -934,77 +934,8 @@ static void bcm_sf2_identify_ports(struct bcm_sf2_priv 
*priv,
 
 static int bcm_sf2_sw_setup(struct dsa_switch *ds)
 {
-   const char *reg_names[BCM_SF2_REGS_NUM] = BCM_SF2_REGS_NAME;
struct bcm_sf2_priv *priv = ds_to_priv(ds);
-   struct device_node *dn;
-   void __iomem **base;
unsigned int port;
-   unsigned int i;
-   u32 reg, rev;
-   int ret;
-
-   spin_lock_init(>indir_lock);
-   mutex_init(>stats_mutex);
-
-   /* All the interesting properties are at the parent device_node
-* level
-*/
-   dn = ds->cd->of_node->parent;
-   bcm_sf2_identify_ports(priv, ds->cd->of_node);
-
-   priv->irq0 = irq_of_parse_and_map(dn, 0);
-   priv->irq1 = irq_of_parse_and_map(dn, 1);
-
-   base = >core;
-   for (i = 0; i < BCM_SF2_REGS_NUM; i++) {
-   *base = of_iomap(dn, i);
-   if (*base == NULL) {
-   pr_err("unable to find register: %s\n", reg_names[i]);
-   ret = -ENOMEM;
-   goto out_unmap;
-   }
-   base++;
-   }
-
-   ret = bcm_sf2_sw_rst(priv);
-   if (ret) {
-   pr_err("unable to software reset switch: %d\n", ret);
-   goto out_unmap;
-   }
-
-   /* Disable all interrupts and request them */
-   bcm_sf2_intr_disable(priv);
-
-   ret = request_irq(priv->irq0, bcm_sf2_switch_0_isr, 0,
- "switch_0", priv);
-   if (ret < 0) {
-   pr_err("failed to request switch_0 IRQ\n");
-   goto out_unmap;
-   }
-
-   ret = request_irq(priv->irq1, bcm_sf2_switch_1_isr, 0,
- "switch_1", priv);
-   if (ret < 0) {
-   pr_err("failed to request switch_1 IRQ\n");
-   goto out_free_irq0;
-   }
-
-   /* Reset the MIB counters */
-   reg = core_readl(priv, CORE_GMNCFGCFG);
-   reg |= RST_MIB_CNT;
-   core_writel(priv, reg, CORE_GMNCFGCFG);
-   reg &= ~RST_MIB_CNT;
-   core_writel(priv, reg, CORE_GMNCFGCFG);
-
-   /* Get the maximum number of ports for this switch */
-   priv->hw_params.num_ports = core_readl(priv, CORE_IMP0_PRT_ID) + 1;
-   if (priv->hw_params.num_ports > DSA_MAX_PORTS)
-   priv->hw_params.num_ports = DSA_MAX_PORTS;
-
-   /* Assume a single GPHY setup if we can't read that property */
-   if (of_property_read_u32(dn, "brcm,num-gphy",
->hw_params.num_gphy))
-   priv->hw_params.num_gphy = 1;
 
/* Enable all valid ports and disable those unused */
for (port = 0; port < priv->hw_params.num_ports; port++) {
@@ -1034,31 +965,7 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds)
else
ds->phys_mii_mask = 0;
 
-   rev = reg_readl(priv, REG_SWITCH_REVISION);
-   priv->hw_params.top_rev = (rev >> SWITCH_TOP_REV_SHIFT) &
-   SWITCH_TOP_REV_MASK;
-   priv->hw_params.core_rev = (rev & SF2_REV_MASK);
-
-   rev = reg_readl(priv, REG_PHY_REVISION);
-   priv->hw_params.gphy_rev = rev & PHY_REVISION_MASK;
-
-   pr_info("Starfighter 2 top: %x.%02x, core: %x.%02x base: 0x%p, IRQs: 
%d, %d\n",
-   priv->hw_params.top_rev >> 8, priv->hw_params.top_rev & 0xff,
-   priv->hw_params.core_rev >> 8, priv->hw_params.core_rev & 0xff,
-   priv->core, priv->irq0, priv->irq1);
-
return 0;
-
-out_free_irq0:
-   free_irq(priv->irq0, priv);
-out_unmap:
-   base = >core;
-   for (i = 0; i < BCM_SF2_REGS_NUM; i++) {
-   if (*base)
-   iounmap(*base);
-   base++;
-   }
-   return ret;
 }
 
 static int bcm_sf2_sw_set_addr(struct dsa_switch *ds, u8 *addr)
@@ -1370,7 +1277,7 @@ static int bcm_sf2_sw_set_wol(struct dsa_switch *ds, int 
port,
return p->ethtool_ops->

[PATCH net-next 8/9] net: dsa: bcm_sf2: Make it a real platform device driver

2016-06-03 Thread Florian Fainelli
The Broadcom Starfighter 2 switch driver should be a proper platform
driver, now that the DSA code has been updated to allow that, register a
switch device, feed it with the proper configuration data coming from
Device Tree and register our switch device with DSA.

The bulk of the changes consist in moving what bcm_sf2_sw_setup() did
into the platform driver probe function.

Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 drivers/net/dsa/bcm_sf2.c | 251 --
 net/dsa/dsa.c |   1 -
 2 files changed, 151 insertions(+), 101 deletions(-)

diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 73df91bb0466..8dac74a6b5df 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -934,77 +934,8 @@ static void bcm_sf2_identify_ports(struct bcm_sf2_priv 
*priv,
 
 static int bcm_sf2_sw_setup(struct dsa_switch *ds)
 {
-   const char *reg_names[BCM_SF2_REGS_NUM] = BCM_SF2_REGS_NAME;
struct bcm_sf2_priv *priv = ds_to_priv(ds);
-   struct device_node *dn;
-   void __iomem **base;
unsigned int port;
-   unsigned int i;
-   u32 reg, rev;
-   int ret;
-
-   spin_lock_init(>indir_lock);
-   mutex_init(>stats_mutex);
-
-   /* All the interesting properties are at the parent device_node
-* level
-*/
-   dn = ds->cd->of_node->parent;
-   bcm_sf2_identify_ports(priv, ds->cd->of_node);
-
-   priv->irq0 = irq_of_parse_and_map(dn, 0);
-   priv->irq1 = irq_of_parse_and_map(dn, 1);
-
-   base = >core;
-   for (i = 0; i < BCM_SF2_REGS_NUM; i++) {
-   *base = of_iomap(dn, i);
-   if (*base == NULL) {
-   pr_err("unable to find register: %s\n", reg_names[i]);
-   ret = -ENOMEM;
-   goto out_unmap;
-   }
-   base++;
-   }
-
-   ret = bcm_sf2_sw_rst(priv);
-   if (ret) {
-   pr_err("unable to software reset switch: %d\n", ret);
-   goto out_unmap;
-   }
-
-   /* Disable all interrupts and request them */
-   bcm_sf2_intr_disable(priv);
-
-   ret = request_irq(priv->irq0, bcm_sf2_switch_0_isr, 0,
- "switch_0", priv);
-   if (ret < 0) {
-   pr_err("failed to request switch_0 IRQ\n");
-   goto out_unmap;
-   }
-
-   ret = request_irq(priv->irq1, bcm_sf2_switch_1_isr, 0,
- "switch_1", priv);
-   if (ret < 0) {
-   pr_err("failed to request switch_1 IRQ\n");
-   goto out_free_irq0;
-   }
-
-   /* Reset the MIB counters */
-   reg = core_readl(priv, CORE_GMNCFGCFG);
-   reg |= RST_MIB_CNT;
-   core_writel(priv, reg, CORE_GMNCFGCFG);
-   reg &= ~RST_MIB_CNT;
-   core_writel(priv, reg, CORE_GMNCFGCFG);
-
-   /* Get the maximum number of ports for this switch */
-   priv->hw_params.num_ports = core_readl(priv, CORE_IMP0_PRT_ID) + 1;
-   if (priv->hw_params.num_ports > DSA_MAX_PORTS)
-   priv->hw_params.num_ports = DSA_MAX_PORTS;
-
-   /* Assume a single GPHY setup if we can't read that property */
-   if (of_property_read_u32(dn, "brcm,num-gphy",
->hw_params.num_gphy))
-   priv->hw_params.num_gphy = 1;
 
/* Enable all valid ports and disable those unused */
for (port = 0; port < priv->hw_params.num_ports; port++) {
@@ -1034,31 +965,7 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds)
else
ds->phys_mii_mask = 0;
 
-   rev = reg_readl(priv, REG_SWITCH_REVISION);
-   priv->hw_params.top_rev = (rev >> SWITCH_TOP_REV_SHIFT) &
-   SWITCH_TOP_REV_MASK;
-   priv->hw_params.core_rev = (rev & SF2_REV_MASK);
-
-   rev = reg_readl(priv, REG_PHY_REVISION);
-   priv->hw_params.gphy_rev = rev & PHY_REVISION_MASK;
-
-   pr_info("Starfighter 2 top: %x.%02x, core: %x.%02x base: 0x%p, IRQs: 
%d, %d\n",
-   priv->hw_params.top_rev >> 8, priv->hw_params.top_rev & 0xff,
-   priv->hw_params.core_rev >> 8, priv->hw_params.core_rev & 0xff,
-   priv->core, priv->irq0, priv->irq1);
-
return 0;
-
-out_free_irq0:
-   free_irq(priv->irq0, priv);
-out_unmap:
-   base = >core;
-   for (i = 0; i < BCM_SF2_REGS_NUM; i++) {
-   if (*base)
-   iounmap(*base);
-   base++;
-   }
-   return ret;
 }
 
 static int bcm_sf2_sw_set_addr(struct dsa_switch *ds, u8 *addr)
@@ -1370,7 +1277,7 @@ static int bcm_sf2_sw_set_wol(struct dsa_switch *ds, int 
port,
return p->ethtool_ops->

Re: [PATCH net-next 12/17] net: dsa: Make mdio bus optional

2016-06-03 Thread Florian Fainelli
On 06/03/2016 09:44 AM, Andrew Lunn wrote:
> The switch may want to instantiate its own MDIO bus. Only do it
> centrally if the switch has not already created one, and the read op
> is implemented.
> 
> Signed-off-by: Andrew Lunn <and...@lunn.ch>

Reviewed-by: Florian Fainelli <f.faine...@gmail.com>
-- 
Florian


[PATCH net v2 0/3] Documentation: dsa: misc fixes

2016-05-24 Thread Florian Fainelli
Hi David,

Here are some miscelaneous documentation fixes for DSA, I targeted "net"
because these are not functional code changes, but still documentation fixes
per-se.

Changes in v2:

- reword what the port_vlan_filtering is about based on feedback from Vivien 
and Ido

Florian Fainelli (3):
  Documentation: networking: dsa: Remove poll_link description
  Documentation: networking: dsa: Remove priv_size description
  Documentation: networking: dsa: Describe port_vlan_filtering

 Documentation/networking/dsa/dsa.txt | 17 ++---
 1 file changed, 10 insertions(+), 7 deletions(-)

-- 
2.7.4



[PATCH net v2 1/3] Documentation: networking: dsa: Remove poll_link description

2016-05-24 Thread Florian Fainelli
This function has been removed in 4baee937b8d5 ("net: dsa: remove DSA
link polling") in favor of using the PHYLIB polling mechanism.

Reviewed-by: Vivien Didelot <vivien.dide...@savoirfairelinux.com>
Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 Documentation/networking/dsa/dsa.txt | 5 -
 1 file changed, 5 deletions(-)

diff --git a/Documentation/networking/dsa/dsa.txt 
b/Documentation/networking/dsa/dsa.txt
index 631b0f7ae16f..8303eb8ced79 100644
--- a/Documentation/networking/dsa/dsa.txt
+++ b/Documentation/networking/dsa/dsa.txt
@@ -416,11 +416,6 @@ PHY devices and link management
   to the switch port MDIO registers. If unavailable return a negative error
   code.
 
-- poll_link: Function invoked by DSA to query the link state of the switch
-  builtin Ethernet PHYs, per port. This function is responsible for calling
-  netif_carrier_{on,off} when appropriate, and can be used to poll all ports 
in a
-  single call. Executes from workqueue context.
-
 - adjust_link: Function invoked by the PHY library when a slave network device
   is attached to a PHY device. This function is responsible for appropriately
   configuring the switch port link parameters: speed, duplex, pause based on
-- 
2.7.4



[PATCH net v2 2/3] Documentation: networking: dsa: Remove priv_size description

2016-05-24 Thread Florian Fainelli
We no longer have a priv_size structure member since 5feebd0a8a79 ("net:
dsa: Remove allocation of driver private memory")

Reviewed-by: Vivien Didelot <vivien.dide...@savoirfairelinux.com>
Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 Documentation/networking/dsa/dsa.txt | 2 --
 1 file changed, 2 deletions(-)

diff --git a/Documentation/networking/dsa/dsa.txt 
b/Documentation/networking/dsa/dsa.txt
index 8303eb8ced79..411b57fd73aa 100644
--- a/Documentation/networking/dsa/dsa.txt
+++ b/Documentation/networking/dsa/dsa.txt
@@ -369,8 +369,6 @@ does not allocate any driver private context space.
 Switch configuration
 
 
-- priv_size: additional size needed by the switch driver for its private 
context
-
 - tag_protocol: this is to indicate what kind of tagging protocol is supported,
   should be a valid value from the dsa_tag_protocol enum
 
-- 
2.7.4



[PATCH net v2 3/3] Documentation: networking: dsa: Describe port_vlan_filtering

2016-05-24 Thread Florian Fainelli
Described what the port_vlan_filtering function is supposed to
accomplish.

Fixes: fb2dabad69f0 ("net: dsa: support VLAN filtering switchdev attr")
Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 Documentation/networking/dsa/dsa.txt | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/Documentation/networking/dsa/dsa.txt 
b/Documentation/networking/dsa/dsa.txt
index 411b57fd73aa..9d05ed7f7da5 100644
--- a/Documentation/networking/dsa/dsa.txt
+++ b/Documentation/networking/dsa/dsa.txt
@@ -535,6 +535,16 @@ Bridge layer
 Bridge VLAN filtering
 -
 
+- port_vlan_filtering: bridge layer function invoked when the bridge gets
+  configured for turning on or off VLAN filtering. If nothing specific needs to
+  be done at the hardware level, this callback does not need to be implemented.
+  When VLAN filtering is turned on, the hardware must be programmed with
+  rejecting 802.1Q frames which have VLAN IDs outside of the programmed allowed
+  VLAN ID map/rules.  If there is no PVID programmed into the switch port,
+  untagged frames must be rejected as well. When turned off the switch must
+  accept any 802.1Q frames irrespective of their VLAN ID, and untagged frames 
are
+  allowed.
+
 - port_vlan_prepare: bridge layer function invoked when the bridge prepares the
   configuration of a VLAN on the given port. If the operation is not supported
   by the hardware, this function should return -EOPNOTSUPP to inform the bridge
-- 
2.7.4



Re: [PATCH net-next v4 0/7] vmxnet3: upgrade to version 3

2016-06-14 Thread Florian Fainelli
On 06/14/2016 11:52 AM, Shrikrishna Khare wrote:
> This patchset upgrades vmxnet3 to version 3.
> 
> Changes in v2:
>  - Following patch is updated. See that patch for details:
>vmxnet3: add support for get_coalesce, set_coalesce ethtool
> 
> Changes in v3:
>  - fix subject line to use vmxnet3: instead of Driver:Vmxnet3
>  - resubmit when net-next is open
> 
> Changes in v4:
>  - Following patch is updated. See that patch for details:
>vmxnet3: add support for get_coalesce, set_coalesce ethtool

You really need to improve your commit messages, because right now they
are inexistent or too obvious to be of any value. A reviewer must be
introduced to what code changes he/she is going to review next by
looking at the diff and whether this will match or not the description
that was provided in the commit message.
-- 
Florian


Re: [PATCH 04/15] drivers: net: cpsw: ethtool: fix accessing to suspended device

2016-06-15 Thread Florian Fainelli
On 06/15/2016 04:55 AM, Grygorii Strashko wrote:
> The CPSW might be suspended by RPM if all ethX interfaces are down,
> but it still could be accesible through ethtool interfce. In this case
> ethtool operations, requiring registers access, will cause L3 errors and
> CPSW crash.
> 
> Hence, fix it by adding RPM get/put calls in ethtool callbcaks which
> can access CPSW registers: .set_coalesce(), .get_ethtool_stats(),
> .set_pauseparam(), .get_regs()

Provided that you implement an ethtool_ops::begin, it will be called
before each ethtool operation runs, so that could allow you to eliminate
some of the duplication here. Conversely ethtool_ops::end terminates
each operation and can be used for that purpose.

> 
> Signed-off-by: Grygorii Strashko 
> ---
>  drivers/net/ethernet/ti/cpsw.c | 36 +++-
>  1 file changed, 35 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
> index ba81d4e..1ba0c09 100644
> --- a/drivers/net/ethernet/ti/cpsw.c
> +++ b/drivers/net/ethernet/ti/cpsw.c
> @@ -931,6 +931,13 @@ static int cpsw_set_coalesce(struct net_device *ndev,
>   u32 prescale = 0;
>   u32 addnl_dvdr = 1;
>   u32 coal_intvl = 0;
> + int ret;
> +
> + ret = pm_runtime_get_sync(>pdev->dev);
> + if (ret < 0) {
> + pm_runtime_put_noidle(>pdev->dev);
> + return ret;
> + }
>  
>   coal_intvl = coal->rx_coalesce_usecs;
>  
> @@ -985,6 +992,8 @@ update_return:
>   priv->coal_intvl = coal_intvl;
>   }
>  
> + pm_runtime_put(>pdev->dev);
> +
>   return 0;
>  }
>  
> @@ -1022,7 +1031,13 @@ static void cpsw_get_ethtool_stats(struct net_device 
> *ndev,
>   struct cpdma_chan_stats tx_stats;
>   u32 val;
>   u8 *p;
> - int i;
> + int i, ret;
> +
> + ret = pm_runtime_get_sync(>pdev->dev);
> + if (ret < 0) {
> + pm_runtime_put_noidle(>pdev->dev);
> + return;
> + }
>  
>   /* Collect Davinci CPDMA stats for Rx and Tx Channel */
>   cpdma_chan_get_stats(priv->rxch, _stats);
> @@ -1049,6 +1064,8 @@ static void cpsw_get_ethtool_stats(struct net_device 
> *ndev,
>   break;
>   }
>   }
> +
> + pm_runtime_put(>pdev->dev);
>  }
>  
>  static int cpsw_common_res_usage_state(struct cpsw_priv *priv)
> @@ -1780,11 +1797,20 @@ static void cpsw_get_regs(struct net_device *ndev,
>  {
>   struct cpsw_priv *priv = netdev_priv(ndev);
>   u32 *reg = p;
> + int ret;
> +
> + ret = pm_runtime_get_sync(>pdev->dev);
> + if (ret < 0) {
> + pm_runtime_put_noidle(>pdev->dev);
> + return;
> + }
>  
>   /* update CPSW IP version */
>   regs->version = priv->version;
>  
>   cpsw_ale_dump(priv->ale, reg);
> +
> + pm_runtime_put(>pdev->dev);
>  }
>  
>  static void cpsw_get_drvinfo(struct net_device *ndev,
> @@ -1902,12 +1928,20 @@ static int cpsw_set_pauseparam(struct net_device 
> *ndev,
>  {
>   struct cpsw_priv *priv = netdev_priv(ndev);
>   bool link;
> + int ret;
> +
> + ret = pm_runtime_get_sync(>pdev->dev);
> + if (ret < 0) {
> + pm_runtime_put_noidle(>pdev->dev);
> + return ret;
> + }
>  
>   priv->rx_pause = pause->rx_pause ? true : false;
>   priv->tx_pause = pause->tx_pause ? true : false;
>  
>   for_each_slave(priv, _cpsw_adjust_link, priv, );
>  
> + pm_runtime_put(>pdev->dev);
>   return 0;
>  }
>  
> 


-- 
Florian


[PATCH net-next v2 5/5] net: dsa: bcm_sf2: Register our slave MDIO bus

2016-06-06 Thread Florian Fainelli
Register a slave MDIO bus which allows us to divert problematic
read/writes towards conflicting pseudo-PHY address (30). Do no longer
rely on DSA's slave_mii_bus, but instead provide our own implementation
which offers more flexibility as to what to do, and when to register it.

We need to register it by the time we are able to get access to our
memory mapped registers, which is not until drv->setup() time. In order
to avoid forward declarations, we need to re-order the function bodies a
bit.

Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 drivers/net/dsa/bcm_sf2.c | 215 +-
 drivers/net/dsa/bcm_sf2.h |   6 ++
 2 files changed, 140 insertions(+), 81 deletions(-)

diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 73df91bb0466..8026fc21c4fb 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -836,6 +837,66 @@ static int bcm_sf2_sw_fdb_dump(struct dsa_switch *ds, int 
port,
return 0;
 }
 
+static int bcm_sf2_sw_indir_rw(struct bcm_sf2_priv *priv, int op, int addr,
+  int regnum, u16 val)
+{
+   int ret = 0;
+   u32 reg;
+
+   reg = reg_readl(priv, REG_SWITCH_CNTRL);
+   reg |= MDIO_MASTER_SEL;
+   reg_writel(priv, reg, REG_SWITCH_CNTRL);
+
+   /* Page << 8 | offset */
+   reg = 0x70;
+   reg <<= 2;
+   core_writel(priv, addr, reg);
+
+   /* Page << 8 | offset */
+   reg = 0x80 << 8 | regnum << 1;
+   reg <<= 2;
+
+   if (op)
+   ret = core_readl(priv, reg);
+   else
+   core_writel(priv, val, reg);
+
+   reg = reg_readl(priv, REG_SWITCH_CNTRL);
+   reg &= ~MDIO_MASTER_SEL;
+   reg_writel(priv, reg, REG_SWITCH_CNTRL);
+
+   return ret & 0x;
+}
+
+static int bcm_sf2_sw_mdio_read(struct mii_bus *bus, int addr, int regnum)
+{
+   struct bcm_sf2_priv *priv = bus->priv;
+
+   /* Intercept reads from Broadcom pseudo-PHY address, else, send
+* them to our master MDIO bus controller
+*/
+   if (addr == BRCM_PSEUDO_PHY_ADDR && priv->indir_phy_mask & BIT(addr))
+   return bcm_sf2_sw_indir_rw(priv, 1, addr, regnum, 0);
+   else
+   return mdiobus_read(priv->master_mii_bus, addr, regnum);
+}
+
+static int bcm_sf2_sw_mdio_write(struct mii_bus *bus, int addr, int regnum,
+u16 val)
+{
+   struct bcm_sf2_priv *priv = bus->priv;
+
+   /* Intercept writes to the Broadcom pseudo-PHY address, else,
+* send them to our master MDIO bus controller
+*/
+   if (addr == BRCM_PSEUDO_PHY_ADDR && priv->indir_phy_mask & BIT(addr))
+   bcm_sf2_sw_indir_rw(priv, 0, addr, regnum, val);
+   else
+   mdiobus_write(priv->master_mii_bus, addr, regnum, val);
+
+   return 0;
+}
+
 static irqreturn_t bcm_sf2_switch_0_isr(int irq, void *dev_id)
 {
struct bcm_sf2_priv *priv = dev_id;
@@ -932,6 +993,72 @@ static void bcm_sf2_identify_ports(struct bcm_sf2_priv 
*priv,
}
 }
 
+static int bcm_sf2_mdio_register(struct dsa_switch *ds)
+{
+   struct bcm_sf2_priv *priv = ds_to_priv(ds);
+   struct device_node *dn;
+   static int index;
+   int err;
+
+   /* Find our integratd MDIO bus node */
+   dn = of_find_compatible_node(NULL, NULL, "brcm,unimac-mdio");
+   priv->master_mii_bus = of_mdio_find_bus(dn);
+   if (!priv->master_mii_bus)
+   return -EPROBE_DEFER;
+
+   get_device(>master_mii_bus->dev);
+   priv->master_mii_dn = dn;
+
+   priv->slave_mii_bus = devm_mdiobus_alloc(ds->dev);
+   if (!priv->slave_mii_bus)
+   return -ENOMEM;
+
+   priv->slave_mii_bus->priv = priv;
+   priv->slave_mii_bus->name = "sf2 slave mii";
+   priv->slave_mii_bus->read = bcm_sf2_sw_mdio_read;
+   priv->slave_mii_bus->write = bcm_sf2_sw_mdio_write;
+   snprintf(priv->slave_mii_bus->id, MII_BUS_ID_SIZE, "sf2-%d",
+index++);
+   priv->slave_mii_bus->dev.of_node = dn;
+
+   /* Include the pseudo-PHY address to divert reads towards our
+* workaround. This is only required for 7445D0, since 7445E0
+* disconnects the internal switch pseudo-PHY such that we can use the
+* regular SWITCH_MDIO master controller instead.
+*
+* Here we flag the pseudo PHY as needing special treatment and would
+* otherwise make all other PHY read/writes go to the master MDIO bus
+* controller that comes with this switch backed by the "mdio-unimac"
+* driver.
+*/
+   if (of_machine_is_compatible("brcm,bcm7445d0"))
+  

<    1   2   3   4   5   6   7   8   9   10   >