Re: [BUG] MVPP2 driver exploding in presence of a tap interface

2018-10-30 Thread Marcin Wojtas
[Resend in UTF-8]

Hi Marc,

You use _really_ archaic firmware, the bug you see is 99% caused by a
bug already fixed long time ago (cleanup all PP2 BM pools correctly
during exit boot services). Please grab the latest release:
https://github.com/MarvellEmbeddedProcessors/edk2-open-platform/wiki/files/flash-image-18.09.4.bin
and let know if you observe any further issues with vanilla kernel.

Best regards,
Marcin

wt., 30 paź 2018 o 13:16 Marc Zyngier  napisał(a):
>
> Antoine,
>
> On 30/10/18 10:50, Antoine Tenart wrote:
> > Marc,
> >
> > On Mon, Oct 29, 2018 at 03:05:53PM +, Marc Zyngier wrote:
> >>
> >> This is a follow-up on the conversation Thomas and I had last week at
> >> ELC, with me ranting at the sorry state of the MVPP2 driver.
> >
> >> Triggering this is dead simple:
> >> - Add a macvtap to one of the MVPP2 interfaces
> >> - Bring it online
> >> - Watch the kernel exploding and memory being corrupted
> >>
> >> You don't even need anything listening on the tap interface, just its
> >> simple existence triggers it. I use a similar setup on a large variety
> >> of machines, and this box is the only one that catches fire. Removing
> >> the macvtap interface makes it (more) reliable.
> >>
> >> Given that I cannot reproduce this issue on any other ARM (32 or 64bit)
> >> platform, including other Marvell stuff, I can only conclude that the
> >> MVPP2 driver is responsible for this.
> >>
> >> Example crash and .config below (4.19 vanilla, as linux/master dies in
> >> new and wonderful ways on this box). I'm looking forward to testing any
> >> idea you may have.
> >
> > I used a 4.19 vanilla kernel, with both your configuration and mine,
> > on 2 different Macchiatobins, but was unable to trigger the issue:
> >
> >   # ip link set eth0 up
> >   # ip link add link eth0 name macvtap0 type macvtap
> >   # ip link set macvtap0 up>
> > I can even configure the eth0/macvtap0 interfaces, and use them
> > generating or receiving tcp/udp/icmp traffic.
> >
> > (I also made other tests using macvtap and tap interfaces).
> >
> > How much memory do you have on the board? What version of ATF are you
> > using? Version of U-Boot?
>
> 4GB of RAM. As for the version numbers, see below. I don't use u-boot,
> but UEFI (EDK-II v2.60). The problem can be reproduced on two different
> machines, with the same configuration (and firmwares dating from a
> similar era):
>
> Starting CP-0 IOROM 1.07
> Booting from SD 0 (0x29)
> Found valid image at boot postion 0x002
> lNOTICE:  Starting binary extension
> NOTICE:  Gathering DRAM information
> mv_ddr: mv_ddr-armada-17.06.1-g47f4c8b (Jun  2 2017 - 17:07:23)
> mv_ddr: completed successfully
> NOTICE:  Booting Trusted Firmware
> NOTICE:  BL1: v1.3(release):armada-17.06.2:297d68f
> NOTICE:  BL1: Built : 17:07:27, Jun  2 2017
> NOTICE:  BL1: Booting BL2
> lNOTICE:  BL2: v1.3(release):armada-17.06.2:297d68f
> NOTICE:  BL2: Built : 17:07:28, Jun  2 2017
> NOTICE:  BL1: Booting BL31
> lNOTICE:  BL31: v1.3(release):armada-17.06.2:297d68f
> NOTICE:  BL31: Built : 17:07:30, Jun  2 2017
> lUEFI firmware (version MARVELL_EFI built at 17:12:21 on Jun  2 2017)
>
> Armada 8040 MachiatoBin Platform Init
>
> Comphy0-0: PCIE0 5 Gbps
> Comphy0-1: PCIE0 5 Gbps
> Comphy0-2: PCIE0 5 Gbps
> Comphy0-3: PCIE0 5 Gbps
> Comphy0-4: SFI   10.31 Gbps
> Comphy0-5: SATA1 5 Gbps
>
> Comphy1-0: SGMII11.25 Gbps
> Comphy1-1: SATA2 5 Gbps
> Comphy1-2: USB3_HOST05 Gbps
> Comphy1-3: SATA3 5 Gbps
> Comphy1-4: SFI   10.31 Gbps
> Comphy1-5: SGMII23.125 Gbps
>
> UTMI PHY 0 initialized to USB Host0
> UTMI PHY 1 initialized to USB Host1
> UTMI PHY 0 initialized to USB Host0
> RTC: Initialize controller 1
> Skip I2c chip 0
> Succesfully installed protocol interfaces
> ramdisk:blckio install. Status=Success
>
> With the latest mainline, and after fixing that other irq affinity
> bug (see patch posted yesterday), I only need to bring the interface
> up, without doing anything else:
>
> # ip link set eth0 up
> [  155.507877] mvpp2 f200.ethernet eth0: PHY [f212a600.mdio-mii:00] 
> driver [mv88x3310]
> [  155.526732] mvpp2 f200.ethernet eth0: configuring for phy/10gbase-kr 
> link mode
> [  157.592581] mvpp2 f200.ethernet eth0: Link is Up - 1Gbps/Full - flow 
> control rx/tx
> [  158.339396] BUG: Bad page state in process swapper/0  pfn:e6804
> [  158.345345] page:7e00039a0100 count:0 mapcount:0 
> mapping:8000e7bf3b00 index:0x8000e6804c00
> [  158.354696] flags: 0xfffc200(slab)
> [  158.358815] raw: 0fffc200 7e00039cff80 00040004 
> 8000e7bf3b00
> [  158.366594] raw: 8000e6804c00 801f  
> 
> [  158.374371] page dumped because: PAGE_FLAGS_CHECK_AT_FREE flag(s) set
> [  158.380840] bad because of flags: 0x200(slab)
> [  158.385216] Modules linked in:
> [  158.388288] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 
> 

Re: [net-next: PATCH v4 1/7] device property: Introduce fwnode_get_mac_address()

2018-01-23 Thread Marcin Wojtas
Hi Rafael,

2018-01-24 3:08 GMT+01:00 Rafael J. Wysocki <raf...@kernel.org>:
> On Tue, Jan 23, 2018 at 7:12 AM, Marcin Wojtas <m...@semihalf.com> wrote:
>> Hi Rafael,
>>
>>> > if (res)
>>> > return res;
>>> >
>>> > -   return device_get_mac_addr(dev, "address", addr, alen);
>>> > +   return fwnode_get_mac_addr(fwnode, "address", addr, alen);
>>> > +}
>>> > +EXPORT_SYMBOL(fwnode_get_mac_address);
>>>
>>> That should be EXPORT_SYMBOL_GPL().
>>>
>>> I have overlooked that previously, sorry about that.
>>
>> The series landed yesterday in net-next, so I need to send a fix on
>> top.
>
> OK
>
>> Would you be ok with single patch fixing all EXPORT_SYMBOL()
>> occurences? Those would be 2 new routines:
>> - fwnode_get_mac_address
>> - fwnode_irq_get
>> and  2 already existing in the file:
>> - device_get_mac_address
>> - fwnode_graph_parse_endpoint
>>
>> Please let know, how you prefer to handle it?
>
> I guess it's better to fix this up when the series gets merged.
>

Ok, I will do it at that time.

Thanks,
Marcin


Re: [net-next: PATCH v4 1/7] device property: Introduce fwnode_get_mac_address()

2018-01-22 Thread Marcin Wojtas
Hi Rafael,

> > if (res)
> > return res;
> >
> > -   return device_get_mac_addr(dev, "address", addr, alen);
> > +   return fwnode_get_mac_addr(fwnode, "address", addr, alen);
> > +}
> > +EXPORT_SYMBOL(fwnode_get_mac_address);
>
> That should be EXPORT_SYMBOL_GPL().
>
> I have overlooked that previously, sorry about that.

The series landed yesterday in net-next, so I need to send a fix on
top. Would you be ok with single patch fixing all EXPORT_SYMBOL()
occurences? Those would be 2 new routines:
- fwnode_get_mac_address
- fwnode_irq_get
and  2 already existing in the file:
- device_get_mac_address
- fwnode_graph_parse_endpoint

Please let know, how you prefer to handle it?

Best regards,
Marcin

>
> > +
> > +/**
> > + * device_get_mac_address - Get the MAC for a given device
> > + * @dev:   Pointer to the device
> > + * @addr:  Address of buffer to store the MAC in
> > + * @alen:  Length of the buffer pointed to by addr, should be ETH_ALEN
> > + */
> > +void *device_get_mac_address(struct device *dev, char *addr, int alen)
> > +{
> > +   return fwnode_get_mac_address(dev_fwnode(dev), addr, alen);
> >  }
> >  EXPORT_SYMBOL(device_get_mac_address);
>
> Same here.
>
> Generally speaking, you should use EXPORT_SYMBOL_GPL() everywhere
> unless there's a specific reason for not doing that in which cases
> that specific reason has to be clearly spelled out at least in the
> changelog of the patch, but really better in a code comment.
>
> >
> > diff --git a/include/linux/property.h b/include/linux/property.h
> > index f6189a3..35620e0 100644
> > --- a/include/linux/property.h
> > +++ b/include/linux/property.h
> > @@ -279,6 +279,8 @@ int device_get_phy_mode(struct device *dev);
> >
> >  void *device_get_mac_address(struct device *dev, char *addr, int alen);
> >
> > +void *fwnode_get_mac_address(struct fwnode_handle *fwnode,
> > +char *addr, int alen);
> >  struct fwnode_handle *fwnode_graph_get_next_endpoint(
> > const struct fwnode_handle *fwnode, struct fwnode_handle *prev);
> >  struct fwnode_handle *
> > --


Re: [net-next: PATCH v4 0/7] Armada 7k/8k PP2 ACPI support

2018-01-22 Thread Marcin Wojtas
2018-01-22 16:57 GMT+01:00 David Miller <da...@davemloft.net>:
> From: Andrew Lunn <and...@lunn.ch>
> Date: Mon, 22 Jan 2018 15:43:42 +0100
>
>> On Mon, Jan 22, 2018 at 09:35:25AM -0500, David Miller wrote:
>>> From: Marcin Wojtas <m...@semihalf.com>
>>> Date: Mon, 22 Jan 2018 14:00:37 +0100
>>>
>>> > There's a discussion about the ACPI vs generic MDIO/PHY change under
>>> > initial version of the patchset, however the patches in question were
>>> > for now abandoned from further re-sends.
>>>
>>> But doesn't the results of that discussion determine whether the way ACPI
>>> is being used in this patch series is what we want to do or not?
>>
>> Hi David
>>
>> The patches submitted here don't involve any ACPI for MDIO or PHY. It
>> is all MAC. And it is using standard ACPI primitives for devices,
>> nothing new.
>>
>> It is not setting any precedence for MDIO and PHY. That is totally out
>> of scope for these patches. Whatever is decided for MDIO and PHY can
>> be added later.
>
> Thanks for all of the clarifications.
>
> Series applied to net-next, thank you.

Great, thanks!


Re: [net-next: PATCH v4 0/7] Armada 7k/8k PP2 ACPI support

2018-01-22 Thread Marcin Wojtas
2018-01-22 15:43 GMT+01:00 Andrew Lunn <and...@lunn.ch>:
> On Mon, Jan 22, 2018 at 09:35:25AM -0500, David Miller wrote:
>> From: Marcin Wojtas <m...@semihalf.com>
>> Date: Mon, 22 Jan 2018 14:00:37 +0100
>>
>> > There's a discussion about the ACPI vs generic MDIO/PHY change under
>> > initial version of the patchset, however the patches in question were
>> > for now abandoned from further re-sends.
>>
>> But doesn't the results of that discussion determine whether the way ACPI
>> is being used in this patch series is what we want to do or not?
>
> Hi David
>
> The patches submitted here don't involve any ACPI for MDIO or PHY. It
> is all MAC. And it is using standard ACPI primitives for devices,
> nothing new.
>
> It is not setting any precedence for MDIO and PHY. That is totally out
> of scope for these patches. Whatever is decided for MDIO and PHY can
> be added later.
>

Indeed, generic helper routines will be used in drivers (net and
others) and the mvpp2 with this patchset is ready to whatever shape
MDIO+ACPI goes in future, so there will be no need to revert any
changes there.

Best regards,
Marcin


Re: [net-next: PATCH v4 0/7] Armada 7k/8k PP2 ACPI support

2018-01-22 Thread Marcin Wojtas
Hi David,

There's a discussion about the ACPI vs generic MDIO/PHY change under
initial version of the patchset, however the patches in question were
for now abandoned from further re-sends.

As the v4 has had no objections until now and:
- patches 1-2 were Acked-by: Rafael J. Wysocki <rafael.j.wyso...@intel.com>
- mvpp2 patches (5-7) were Tested-by: Antoine Tenart
<antoine.ten...@free-electrons.com>
- entire series was  Reviewed-by: Graeme Gregory <graeme.greg...@linaro.org>
Do you see any chance that it lands in net-next before the coming
merge window? It would be really much appreciated.

Thanks,
Marcin


2018-01-18 14:23 GMT+01:00 Antoine Tenart <antoine.ten...@free-electrons.com>:
> Hi Marcin,
>
> I tested the series on a MacchiatoBin to ensure the mvpp2 DT support was
> still working. I was able to use all supported ports as before, and saw
> no issue.
>
> For all mvpp2 patches, you can add:
>
> Tested-by: Antoine Tenart <antoine.ten...@free-electrons.com>
>
> Thanks!
> Antoine
>
> On Thu, Jan 18, 2018 at 01:31:37PM +0100, Marcin Wojtas wrote:
>> Hi,
>>
>> I quickly resend the series, thanks to Antoine Tenart's remark,
>> who spotted !CONFIG_ACPI compilation issue after introducing
>> the new fwnode_irq_get() routine. Please see the details in the changelog
>> below and the 3/7 commit log.
>>
>> mvpp2 driver can work with the ACPI representation, as exposed
>> on a public branch:
>> https://github.com/MarvellEmbeddedProcessors/edk2-open-platform/commits/marvell-armada-wip
>> It was compiled together with the most recent Tianocore EDK2 revision.
>> Please refer to the firmware build instruction on MacchiatoBin board:
>> http://wiki.macchiatobin.net/tiki-index.php?page=Build+from+source+-+UEFI+EDK+II
>>
>> ACPI representation of PP2 controllers (withouth PHY support) can
>> be viewed in the github:
>> * MacchiatoBin:
>> https://github.com/MarvellEmbeddedProcessors/edk2-open-platform/blob/71ae395da1661374b0f07d1602afb1eee56e9794/Platforms/Marvell/Armada/AcpiTables/Armada80x0McBin/Dsdt.asl#L201
>>
>> * Armada 7040 DB:
>> https://github.com/MarvellEmbeddedProcessors/edk2-open-platform/blob/71ae395da1661374b0f07d1602afb1eee56e9794/Platforms/Marvell/Armada/AcpiTables/Armada70x0/Dsdt.asl#L131
>>
>> I will appreciate any comments or remarks.
>>
>> Best regards,
>> Marcin
>>
>> Changelog:
>> v3 -> v4:
>> * 3/7
>> - add new macro (ACPI_HANDLE_FWNODE) and fix
>>   compilation with !CONFIG_ACPI
>> - extend commit log and mention usability of fwnode_irq_get
>>   for the child nodes as well
>>
>> v2 -> v3:
>> * 1/7, 2/7
>> - Add Rafael's Acked-by's
>> * 3/7, 4/7
>> - New patches
>> * 6/7, 7/7
>> - Update driver with new helper routines usage
>> - Improve commit log.
>>
>> v1 -> v2:
>> * Remove MDIO patches
>> * Use PP2 ports only with link interrupts
>> * Release second region resources in mvpp2 driver (code moved from
>>   mvmdio), as explained in details in 5/5 commit message.
>>
>> Marcin Wojtas (7):
>>   device property: Introduce fwnode_get_mac_address()
>>   device property: Introduce fwnode_get_phy_mode()
>>   device property: Introduce fwnode_irq_get()
>>   device property: Allow iterating over available child fwnodes
>>   net: mvpp2: simplify maintaining enabled ports' list
>>   net: mvpp2: use device_*/fwnode_* APIs instead of of_*
>>   net: mvpp2: enable ACPI support in the driver
>>
>>  drivers/base/property.c  | 104 --
>>  drivers/net/ethernet/marvell/mvpp2.c | 206 
>>  include/linux/acpi.h |   3 +
>>  include/linux/property.h |  11 ++
>>  4 files changed, 232 insertions(+), 92 deletions(-)
>>
>> --
>> 2.7.4
>>
>
> --
> Antoine Ténart, Free Electrons
> Embedded Linux and Kernel engineering
> http://free-electrons.com


Re: [net-next: PATCH 0/8] Armada 7k/8k PP2 ACPI support

2018-01-19 Thread Marcin Wojtas
Hi Mika,

2018-01-18 14:00 GMT+01:00 Andrew Lunn :
>> I CC'ed Mika since he is more familiar with handling these bits of ACPI
>> specs - I wonder whether this is a problem that cropped up on x86
>> systems too.
>
> Hi Lorenzo
>
> There is nothing about MDIO, PHYs, Ethernet switches, etc in version
> 6.2 of the spec. If x86 has this, it must be after 6.2 was released.
> I would not be too surprised if x86 has none of this. If you look at
> the typical drives used on x86, i210, e1000e, ixgb, r8169, etc. They
> are all PCI devices, and hide all this.
>
>> I do not think there is one and only answer but there must be a single
>> set of bindings and if the ACPI specs already cater for some of them
>> we have to reuse them.
>
> Agreed. Due diligence so far suggests there is nothing already
> defined. But im a newbie to ACPI, so could be looking in the wrong
> place. I really hope there is somebody like Rob Herring, the DT
> maintainer, who keeps an eye on all ACPI talk and would tell us if we
> are heading off in the wrong direction.
>

My initial approach with MDIO bus with PHYs as child nodes was super
easy to describe and handle in Linux - please refer to:
- typical representation of mdio bus with the phys -
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/net/mdio.txt?h=v4.15-rc8
- my patches in the initial series
However I guess it would be more proper to use the
GenericSerialBus-based description, as advised in ACPI Spec. The
question is, whether we should define new type of a bus or not
(MdioSerialBus, similar to e.g. I2cSerialBus).

Since I have a code that can be tested and easily modified to use
different ACPI approaches with real platform MDIO controller
(mvmdio.c) and NIC (mvpp2.c), in coming weeks I may be able to find
some time to prepare a proof of concept based on GenericSerialBus.
Please expect some RFC patches hopefully right after the coming merge
window is closed.

Of course, if I come up on some ACPI - specific implementation
questions, I won't hesitate to ask in this thred. I will also
appreciate any hints. For now my two main concerns are:
- The PHY address on the mdio bus - should it be put into _CRS ->
GenericSerialBus() field or separate _ADR? I'd lean towards first
option.
- The PHY type - in Linux it's resolved basing on two generic
compatible strings
(https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/net/phy.txt?h=v4.15-rc8).
I'd put it as a sort of ID into GenericSerialBus(). If you agree - any
specific filed that you would try to use?

Do I understand correctly that the MDIO controller node should
comprise OperationRegion() definition of the GenericSerialBus?

I'm looking forward to your feedback.

Thanks,
Marcin


[net-next: PATCH v4 4/7] device property: Allow iterating over available child fwnodes

2018-01-18 Thread Marcin Wojtas
Implement a new helper function fwnode_get_next_available_child_node(),
which enables obtaining next enabled child fwnode, which
works on a similar basis to OF's of_get_next_available_child().

This commit also introduces a macro, thanks to which it is
possible to iterate over the available fwnodes, using the
new function described above.

Signed-off-by: Marcin Wojtas <m...@semihalf.com>
---
 drivers/base/property.c  | 26 
 include/linux/property.h |  6 +
 2 files changed, 32 insertions(+)

diff --git a/drivers/base/property.c b/drivers/base/property.c
index 1d6c9d9..613ba82 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -998,6 +998,32 @@ fwnode_get_next_child_node(const struct fwnode_handle 
*fwnode,
 EXPORT_SYMBOL_GPL(fwnode_get_next_child_node);
 
 /**
+ * fwnode_get_next_available_child_node - Return the next
+ * available child node handle for a node
+ * @fwnode: Firmware node to find the next child node for.
+ * @child: Handle to one of the node's child nodes or a %NULL handle.
+ */
+struct fwnode_handle *
+fwnode_get_next_available_child_node(const struct fwnode_handle *fwnode,
+struct fwnode_handle *child)
+{
+   struct fwnode_handle *next_child = child;
+
+   if (!fwnode)
+   return NULL;
+
+   do {
+   next_child = fwnode_get_next_child_node(fwnode, next_child);
+
+   if (!next_child || fwnode_device_is_available(next_child))
+   break;
+   } while (next_child);
+
+   return next_child;
+}
+EXPORT_SYMBOL_GPL(fwnode_get_next_available_child_node);
+
+/**
  * device_get_next_child_node - Return the next child node handle for a device
  * @dev: Device to find the next child node for.
  * @child: Handle to one of the device's child nodes or a null handle.
diff --git a/include/linux/property.h b/include/linux/property.h
index e05889f..5b0563a 100644
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -83,11 +83,17 @@ struct fwnode_handle *fwnode_get_next_parent(
struct fwnode_handle *fwnode);
 struct fwnode_handle *fwnode_get_next_child_node(
const struct fwnode_handle *fwnode, struct fwnode_handle *child);
+struct fwnode_handle *fwnode_get_next_available_child_node(
+   const struct fwnode_handle *fwnode, struct fwnode_handle *child);
 
 #define fwnode_for_each_child_node(fwnode, child)  \
for (child = fwnode_get_next_child_node(fwnode, NULL); child;   \
 child = fwnode_get_next_child_node(fwnode, child))
 
+#define fwnode_for_each_available_child_node(fwnode, child)   \
+   for (child = fwnode_get_next_available_child_node(fwnode, NULL); child;\
+child = fwnode_get_next_available_child_node(fwnode, child))
+
 struct fwnode_handle *device_get_next_child_node(
struct device *dev, struct fwnode_handle *child);
 
-- 
2.7.4



[net-next: PATCH v4 2/7] device property: Introduce fwnode_get_phy_mode()

2018-01-18 Thread Marcin Wojtas
Until now there were two almost identical functions for
obtaining network PHY mode - of_get_phy_mode() and,
more generic, device_get_phy_mode(). However it is not uncommon,
that the network interface is represented as a child
of the actual controller, hence it is not associated
directly to any struct device, required by the latter
routine.

This commit allows for getting the PHY mode for
children nodes in the ACPI world by introducing a new function -
fwnode_get_phy_mode(). This commit also changes
device_get_phy_mode() routine to be its wrapper, in order
to prevent unnecessary duplication.

Signed-off-by: Marcin Wojtas <m...@semihalf.com>
Acked-by: Rafael J. Wysocki <rafael.j.wyso...@intel.com>
---
 drivers/base/property.c  | 24 
 include/linux/property.h |  1 +
 2 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/drivers/base/property.c b/drivers/base/property.c
index f261d1a..7c4a53d 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -1126,21 +1126,21 @@ enum dev_dma_attr device_get_dma_attr(struct device 
*dev)
 EXPORT_SYMBOL_GPL(device_get_dma_attr);
 
 /**
- * device_get_phy_mode - Get phy mode for given device
- * @dev:   Pointer to the given device
+ * fwnode_get_phy_mode - Get phy mode for given firmware node
+ * @fwnode:Pointer to the given node
  *
  * The function gets phy interface string from property 'phy-mode' or
  * 'phy-connection-type', and return its index in phy_modes table, or errno in
  * error case.
  */
-int device_get_phy_mode(struct device *dev)
+int fwnode_get_phy_mode(struct fwnode_handle *fwnode)
 {
const char *pm;
int err, i;
 
-   err = device_property_read_string(dev, "phy-mode", );
+   err = fwnode_property_read_string(fwnode, "phy-mode", );
if (err < 0)
-   err = device_property_read_string(dev,
+   err = fwnode_property_read_string(fwnode,
  "phy-connection-type", );
if (err < 0)
return err;
@@ -1151,6 +1151,20 @@ int device_get_phy_mode(struct device *dev)
 
return -ENODEV;
 }
+EXPORT_SYMBOL_GPL(fwnode_get_phy_mode);
+
+/**
+ * device_get_phy_mode - Get phy mode for given device
+ * @dev:   Pointer to the given device
+ *
+ * The function gets phy interface string from property 'phy-mode' or
+ * 'phy-connection-type', and return its index in phy_modes table, or errno in
+ * error case.
+ */
+int device_get_phy_mode(struct device *dev)
+{
+   return fwnode_get_phy_mode(dev_fwnode(dev));
+}
 EXPORT_SYMBOL_GPL(device_get_phy_mode);
 
 static void *fwnode_get_mac_addr(struct fwnode_handle *fwnode,
diff --git a/include/linux/property.h b/include/linux/property.h
index 35620e0..9b13332 100644
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -279,6 +279,7 @@ int device_get_phy_mode(struct device *dev);
 
 void *device_get_mac_address(struct device *dev, char *addr, int alen);
 
+int fwnode_get_phy_mode(struct fwnode_handle *fwnode);
 void *fwnode_get_mac_address(struct fwnode_handle *fwnode,
 char *addr, int alen);
 struct fwnode_handle *fwnode_graph_get_next_endpoint(
-- 
2.7.4



[net-next: PATCH v4 1/7] device property: Introduce fwnode_get_mac_address()

2018-01-18 Thread Marcin Wojtas
Until now there were two almost identical functions for
obtaining MAC address - of_get_mac_address() and, more generic,
device_get_mac_address(). However it is not uncommon,
that the network interface is represented as a child
of the actual controller, hence it is not associated
directly to any struct device, required by the latter
routine.

This commit allows for getting the MAC address for
children nodes in the ACPI world by introducing a new function -
fwnode_get_mac_address(). This commit also changes
device_get_mac_address() routine to be its wrapper, in order
to prevent unnecessary duplication.

Signed-off-by: Marcin Wojtas <m...@semihalf.com>
Acked-by: Rafael J. Wysocki <rafael.j.wyso...@intel.com>
---
 drivers/base/property.c  | 28 ++--
 include/linux/property.h |  2 ++
 2 files changed, 22 insertions(+), 8 deletions(-)

diff --git a/drivers/base/property.c b/drivers/base/property.c
index 851b1b6..f261d1a 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -1153,11 +1153,11 @@ int device_get_phy_mode(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(device_get_phy_mode);
 
-static void *device_get_mac_addr(struct device *dev,
+static void *fwnode_get_mac_addr(struct fwnode_handle *fwnode,
 const char *name, char *addr,
 int alen)
 {
-   int ret = device_property_read_u8_array(dev, name, addr, alen);
+   int ret = fwnode_property_read_u8_array(fwnode, name, addr, alen);
 
if (ret == 0 && alen == ETH_ALEN && is_valid_ether_addr(addr))
return addr;
@@ -1165,8 +1165,8 @@ static void *device_get_mac_addr(struct device *dev,
 }
 
 /**
- * device_get_mac_address - Get the MAC for a given device
- * @dev:   Pointer to the device
+ * fwnode_get_mac_address - Get the MAC from the firmware node
+ * @fwnode:Pointer to the firmware node
  * @addr:  Address of buffer to store the MAC in
  * @alen:  Length of the buffer pointed to by addr, should be ETH_ALEN
  *
@@ -1187,19 +1187,31 @@ static void *device_get_mac_addr(struct device *dev,
  * In this case, the real MAC is in 'local-mac-address', and 'mac-address'
  * exists but is all zeros.
 */
-void *device_get_mac_address(struct device *dev, char *addr, int alen)
+void *fwnode_get_mac_address(struct fwnode_handle *fwnode, char *addr, int 
alen)
 {
char *res;
 
-   res = device_get_mac_addr(dev, "mac-address", addr, alen);
+   res = fwnode_get_mac_addr(fwnode, "mac-address", addr, alen);
if (res)
return res;
 
-   res = device_get_mac_addr(dev, "local-mac-address", addr, alen);
+   res = fwnode_get_mac_addr(fwnode, "local-mac-address", addr, alen);
if (res)
return res;
 
-   return device_get_mac_addr(dev, "address", addr, alen);
+   return fwnode_get_mac_addr(fwnode, "address", addr, alen);
+}
+EXPORT_SYMBOL(fwnode_get_mac_address);
+
+/**
+ * device_get_mac_address - Get the MAC for a given device
+ * @dev:   Pointer to the device
+ * @addr:  Address of buffer to store the MAC in
+ * @alen:  Length of the buffer pointed to by addr, should be ETH_ALEN
+ */
+void *device_get_mac_address(struct device *dev, char *addr, int alen)
+{
+   return fwnode_get_mac_address(dev_fwnode(dev), addr, alen);
 }
 EXPORT_SYMBOL(device_get_mac_address);
 
diff --git a/include/linux/property.h b/include/linux/property.h
index f6189a3..35620e0 100644
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -279,6 +279,8 @@ int device_get_phy_mode(struct device *dev);
 
 void *device_get_mac_address(struct device *dev, char *addr, int alen);
 
+void *fwnode_get_mac_address(struct fwnode_handle *fwnode,
+char *addr, int alen);
 struct fwnode_handle *fwnode_graph_get_next_endpoint(
const struct fwnode_handle *fwnode, struct fwnode_handle *prev);
 struct fwnode_handle *
-- 
2.7.4



[net-next: PATCH v4 0/7] Armada 7k/8k PP2 ACPI support

2018-01-18 Thread Marcin Wojtas
Hi,

I quickly resend the series, thanks to Antoine Tenart's remark,
who spotted !CONFIG_ACPI compilation issue after introducing
the new fwnode_irq_get() routine. Please see the details in the changelog
below and the 3/7 commit log.

mvpp2 driver can work with the ACPI representation, as exposed
on a public branch:
https://github.com/MarvellEmbeddedProcessors/edk2-open-platform/commits/marvell-armada-wip
It was compiled together with the most recent Tianocore EDK2 revision.
Please refer to the firmware build instruction on MacchiatoBin board:
http://wiki.macchiatobin.net/tiki-index.php?page=Build+from+source+-+UEFI+EDK+II

ACPI representation of PP2 controllers (withouth PHY support) can
be viewed in the github:
* MacchiatoBin:
https://github.com/MarvellEmbeddedProcessors/edk2-open-platform/blob/71ae395da1661374b0f07d1602afb1eee56e9794/Platforms/Marvell/Armada/AcpiTables/Armada80x0McBin/Dsdt.asl#L201

* Armada 7040 DB:
https://github.com/MarvellEmbeddedProcessors/edk2-open-platform/blob/71ae395da1661374b0f07d1602afb1eee56e9794/Platforms/Marvell/Armada/AcpiTables/Armada70x0/Dsdt.asl#L131

I will appreciate any comments or remarks.

Best regards,
Marcin

Changelog:
v3 -> v4:
* 3/7
- add new macro (ACPI_HANDLE_FWNODE) and fix
  compilation with !CONFIG_ACPI
- extend commit log and mention usability of fwnode_irq_get
  for the child nodes as well

v2 -> v3:
* 1/7, 2/7
- Add Rafael's Acked-by's
* 3/7, 4/7
- New patches
* 6/7, 7/7
- Update driver with new helper routines usage
- Improve commit log.

v1 -> v2:
* Remove MDIO patches
* Use PP2 ports only with link interrupts
* Release second region resources in mvpp2 driver (code moved from
  mvmdio), as explained in details in 5/5 commit message.

Marcin Wojtas (7):
  device property: Introduce fwnode_get_mac_address()
  device property: Introduce fwnode_get_phy_mode()
  device property: Introduce fwnode_irq_get()
  device property: Allow iterating over available child fwnodes
  net: mvpp2: simplify maintaining enabled ports' list
  net: mvpp2: use device_*/fwnode_* APIs instead of of_*
  net: mvpp2: enable ACPI support in the driver

 drivers/base/property.c  | 104 --
 drivers/net/ethernet/marvell/mvpp2.c | 206 
 include/linux/acpi.h |   3 +
 include/linux/property.h |  11 ++
 4 files changed, 232 insertions(+), 92 deletions(-)

-- 
2.7.4



[net-next: PATCH v4 3/7] device property: Introduce fwnode_irq_get()

2018-01-18 Thread Marcin Wojtas
Until now there were two very similar functions allowing
to get Linux IRQ number from ACPI handle (acpi_irq_get())
and OF node (of_irq_get()). The first one appeared to be used
only as a subroutine of platform_irq_get(), which (in the generic
code) limited IRQ obtaining from _CRS method only to nodes
associated to kernel's struct platform_device.

This patch introduces a new helper routine - fwnode_irq_get(),
which allows to get the IRQ number directly from the fwnode
to be used as common for OF/ACPI worlds. It is usable not
only for the parents fwnodes, but also for the child nodes
comprising their own _CRS methods with interrupts description.

In order to be able o satisfy compilation with !CONFIG_ACPI
and also simplify the new code, introduce a helper macro
(ACPI_HANDLE_FWNODE), with which it is possible to reach
an ACPI handle directly from its fwnode.

Signed-off-by: Marcin Wojtas <m...@semihalf.com>
---
 drivers/base/property.c  | 26 
 include/linux/acpi.h |  3 +++
 include/linux/property.h |  2 ++
 3 files changed, 31 insertions(+)

diff --git a/drivers/base/property.c b/drivers/base/property.c
index 7c4a53d..1d6c9d9 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -16,6 +16,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -1230,6 +1231,31 @@ void *device_get_mac_address(struct device *dev, char 
*addr, int alen)
 EXPORT_SYMBOL(device_get_mac_address);
 
 /**
+ * fwnode_irq_get - Get IRQ directly from a fwnode
+ * @fwnode:Pointer to the firmware node
+ * @index: Zero-based index of the IRQ
+ *
+ * Returns Linux IRQ number on success. Other values are determined
+ * accordingly to acpi_/of_ irq_get() operation.
+ */
+int fwnode_irq_get(struct fwnode_handle *fwnode, unsigned int index)
+{
+   struct device_node *of_node = to_of_node(fwnode);
+   struct resource res;
+   int ret;
+
+   if (IS_ENABLED(CONFIG_OF) && of_node)
+   return of_irq_get(of_node, index);
+
+   ret = acpi_irq_get(ACPI_HANDLE_FWNODE(fwnode), index, );
+   if (ret)
+   return ret;
+
+   return res.start;
+}
+EXPORT_SYMBOL(fwnode_irq_get);
+
+/**
  * device_graph_get_next_endpoint - Get next endpoint firmware node
  * @fwnode: Pointer to the parent firmware node
  * @prev: Previous endpoint node or %NULL to get the first
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index dc1ebfe..f05b9b6 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -56,6 +56,8 @@ static inline acpi_handle acpi_device_handle(struct 
acpi_device *adev)
 #define ACPI_COMPANION_SET(dev, adev)  set_primary_fwnode(dev, (adev) ? \
acpi_fwnode_handle(adev) : NULL)
 #define ACPI_HANDLE(dev)   acpi_device_handle(ACPI_COMPANION(dev))
+#define ACPI_HANDLE_FWNODE(fwnode) \
+   acpi_device_handle(to_acpi_device_node(fwnode))
 
 static inline struct fwnode_handle *acpi_alloc_fwnode_static(void)
 {
@@ -626,6 +628,7 @@ int acpi_arch_timer_mem_init(struct arch_timer_mem 
*timer_mem, int *timer_count)
 #define ACPI_COMPANION(dev)(NULL)
 #define ACPI_COMPANION_SET(dev, adev)  do { } while (0)
 #define ACPI_HANDLE(dev)   (NULL)
+#define ACPI_HANDLE_FWNODE(fwnode) (NULL)
 #define ACPI_DEVICE_CLASS(_cls, _msk)  .cls = (0), .cls_msk = (0),
 
 struct fwnode_handle;
diff --git a/include/linux/property.h b/include/linux/property.h
index 9b13332..e05889f 100644
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -103,6 +103,8 @@ struct fwnode_handle *device_get_named_child_node(struct 
device *dev,
 struct fwnode_handle *fwnode_handle_get(struct fwnode_handle *fwnode);
 void fwnode_handle_put(struct fwnode_handle *fwnode);
 
+int fwnode_irq_get(struct fwnode_handle *fwnode, unsigned int index);
+
 unsigned int device_get_child_node_count(struct device *dev);
 
 static inline bool device_property_read_bool(struct device *dev,
-- 
2.7.4



[net-next: PATCH v4 5/7] net: mvpp2: simplify maintaining enabled ports' list

2018-01-18 Thread Marcin Wojtas
'port_count' field of the mvpp2 structure holds an overall amount
of available ports, based on DT nodes status. In order to be prepared
to support other HW description, obtain the value by incrementing it
upon each successful port initialization. This allowed for simplifying
port indexing in the controller's private array, whose size is now not
dynamically allocated, but fixed to MVPP2_MAX_PORTS.

This patch simplifies creating and filling list of enabled ports and
is a part of the preparation for adding ACPI support in the mvpp2 driver.

Signed-off-by: Marcin Wojtas <m...@semihalf.com>
---
 drivers/net/ethernet/marvell/mvpp2.c | 32 +++-
 1 file changed, 11 insertions(+), 21 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvpp2.c 
b/drivers/net/ethernet/marvell/mvpp2.c
index a197607..7f42d90 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -865,7 +865,7 @@ struct mvpp2 {
 
/* List of pointers to port structures */
int port_count;
-   struct mvpp2_port **port_list;
+   struct mvpp2_port *port_list[MVPP2_MAX_PORTS];
 
/* Aggregated TXQs */
struct mvpp2_tx_queue *aggr_txqs;
@@ -7741,7 +7741,7 @@ static void mvpp2_port_copy_mac_addr(struct net_device 
*dev, struct mvpp2 *priv,
 /* Ports initialization */
 static int mvpp2_port_probe(struct platform_device *pdev,
struct device_node *port_node,
-   struct mvpp2 *priv, int index)
+   struct mvpp2 *priv)
 {
struct device_node *phy_node;
struct phy *comphy;
@@ -7934,7 +7934,8 @@ static int mvpp2_port_probe(struct platform_device *pdev,
}
netdev_info(dev, "Using %s mac address %pM\n", mac_from, dev->dev_addr);
 
-   priv->port_list[index] = port;
+   priv->port_list[priv->port_count++] = port;
+
return 0;
 
 err_free_port_pcpu:
@@ -8313,28 +8314,17 @@ static int mvpp2_probe(struct platform_device *pdev)
goto err_mg_clk;
}
 
-   priv->port_count = of_get_available_child_count(dn);
-   if (priv->port_count == 0) {
-   dev_err(>dev, "no ports enabled\n");
-   err = -ENODEV;
-   goto err_mg_clk;
-   }
-
-   priv->port_list = devm_kcalloc(>dev, priv->port_count,
-  sizeof(*priv->port_list),
-  GFP_KERNEL);
-   if (!priv->port_list) {
-   err = -ENOMEM;
-   goto err_mg_clk;
-   }
-
/* Initialize ports */
-   i = 0;
for_each_available_child_of_node(dn, port_node) {
-   err = mvpp2_port_probe(pdev, port_node, priv, i);
+   err = mvpp2_port_probe(pdev, port_node, priv);
if (err < 0)
goto err_port_probe;
-   i++;
+   }
+
+   if (priv->port_count == 0) {
+   dev_err(>dev, "no ports enabled\n");
+   err = -ENODEV;
+   goto err_mg_clk;
}
 
/* Statistics must be gathered regularly because some of them (like
-- 
2.7.4



[net-next: PATCH v4 7/7] net: mvpp2: enable ACPI support in the driver

2018-01-18 Thread Marcin Wojtas
This patch introduces an alternative way of obtaining resources - via
ACPI tables provided by firmware. Enabling coexistence with the DT
support, in addition to the OF_*->device_*/fwnode_* API replacement,
required following steps to be taken:

* Add mvpp2_acpi_match table
* Omit clock configuration and obtain tclk from the property - in ACPI
  world, the firmware is responsible for clock maintenance.
* Disable comphy and syscon handling as they are not available for ACPI.
* Modify way of obtaining interrupts - use newly introduced
  fwnode_irq_get() routine
* Until proper MDIO bus and PHY handling with ACPI is established in the
  kernel, use only link interrupts feature in the driver. For the RGMII
  port it results in depending on GMAC settings done during firmware
  stage.
* When booting with ACPI MVPP2_QDIST_MULTI_MODE is picked by
  default, as there is no need to keep any kind of the backward
  compatibility.

Moreover, a memory region used by mvmdio driver is usually placed in
the middle of the address space of the PP2 network controller.
The MDIO base address is obtained without requesting memory region
(by devm_ioremap() call) in mvmdio.c, later overlapping resources are
requested by the network driver, which is responsible for avoiding
a concurrent access.

In case the MDIO memory region is declared in the ACPI, it can
already appear as 'in-use' in the OS. Because it is overlapped by second
region of the network controller, make sure it is released, before
requesting it again. The care is taken by mvpp2 driver to avoid
concurrent access to this memory region.

Signed-off-by: Marcin Wojtas <m...@semihalf.com>
---
 drivers/net/ethernet/marvell/mvpp2.c | 133 ++--
 1 file changed, 94 insertions(+), 39 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvpp2.c 
b/drivers/net/ethernet/marvell/mvpp2.c
index f16448e..a1d7b88 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -10,6 +10,7 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -7502,7 +7503,10 @@ static int mvpp2_multi_queue_vectors_init(struct 
mvpp2_port *port,
strncpy(irqname, "rx-shared", sizeof(irqname));
}
 
-   v->irq = of_irq_get_byname(port_node, irqname);
+   if (port_node)
+   v->irq = of_irq_get_byname(port_node, irqname);
+   else
+   v->irq = fwnode_irq_get(port->fwnode, i);
if (v->irq <= 0) {
ret = -EINVAL;
goto err;
@@ -7746,7 +7750,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
struct mvpp2 *priv)
 {
struct device_node *phy_node;
-   struct phy *comphy;
+   struct phy *comphy = NULL;
struct mvpp2_port *port;
struct mvpp2_port_pcpu *port_pcpu;
struct device_node *port_node = to_of_node(port_fwnode);
@@ -7760,7 +7764,12 @@ static int mvpp2_port_probe(struct platform_device *pdev,
int phy_mode;
int err, i, cpu;
 
-   has_tx_irqs = mvpp2_port_has_tx_irqs(priv, port_node);
+   if (port_node) {
+   has_tx_irqs = mvpp2_port_has_tx_irqs(priv, port_node);
+   } else {
+   has_tx_irqs = true;
+   queue_mode = MVPP2_QDIST_MULTI_MODE;
+   }
 
if (!has_tx_irqs)
queue_mode = MVPP2_QDIST_SINGLE_MODE;
@@ -7775,7 +7784,11 @@ static int mvpp2_port_probe(struct platform_device *pdev,
if (!dev)
return -ENOMEM;
 
-   phy_node = of_parse_phandle(port_node, "phy", 0);
+   if (port_node)
+   phy_node = of_parse_phandle(port_node, "phy", 0);
+   else
+   phy_node = NULL;
+
phy_mode = fwnode_get_phy_mode(port_fwnode);
if (phy_mode < 0) {
dev_err(>dev, "incorrect phy mode\n");
@@ -7783,13 +7796,15 @@ static int mvpp2_port_probe(struct platform_device 
*pdev,
goto err_free_netdev;
}
 
-   comphy = devm_of_phy_get(>dev, port_node, NULL);
-   if (IS_ERR(comphy)) {
-   if (PTR_ERR(comphy) == -EPROBE_DEFER) {
-   err = -EPROBE_DEFER;
-   goto err_free_netdev;
+   if (port_node) {
+   comphy = devm_of_phy_get(>dev, port_node, NULL);
+   if (IS_ERR(comphy)) {
+   if (PTR_ERR(comphy) == -EPROBE_DEFER) {
+   err = -EPROBE_DEFER;
+   goto err_free_netdev;
+   }
+   comphy = NULL;
}
-   comphy = NULL;
}
 
if (fwnode_property_read_u32(port_fwnode, "port-id", )) {
@@ -7805,6 +7820,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
 
   

[net-next: PATCH v4 6/7] net: mvpp2: use device_*/fwnode_* APIs instead of of_*

2018-01-18 Thread Marcin Wojtas
OF functions can be used only for the driver using DT.
As a preparation for introducing ACPI support in mvpp2
driver, use struct fwnode_handle in order to obtain
properties from the hardware description.

This patch replaces of_* function with device_*/fwnode_*
where possible in the mvpp2.

Signed-off-by: Marcin Wojtas <m...@semihalf.com>
---
 drivers/net/ethernet/marvell/mvpp2.c | 45 +++-
 1 file changed, 24 insertions(+), 21 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvpp2.c 
b/drivers/net/ethernet/marvell/mvpp2.c
index 7f42d90..f16448e 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -932,6 +932,9 @@ struct mvpp2_port {
 
struct mvpp2 *priv;
 
+   /* Firmware node associated to the port */
+   struct fwnode_handle *fwnode;
+
/* Per-port registers' base address */
void __iomem *base;
void __iomem *stats_base;
@@ -7711,17 +7714,16 @@ static bool mvpp2_port_has_tx_irqs(struct mvpp2 *priv,
 }
 
 static void mvpp2_port_copy_mac_addr(struct net_device *dev, struct mvpp2 
*priv,
-struct device_node *port_node,
+struct fwnode_handle *fwnode,
 char **mac_from)
 {
struct mvpp2_port *port = netdev_priv(dev);
char hw_mac_addr[ETH_ALEN] = {0};
-   const char *dt_mac_addr;
+   char fw_mac_addr[ETH_ALEN];
 
-   dt_mac_addr = of_get_mac_address(port_node);
-   if (dt_mac_addr && is_valid_ether_addr(dt_mac_addr)) {
-   *mac_from = "device tree";
-   ether_addr_copy(dev->dev_addr, dt_mac_addr);
+   if (fwnode_get_mac_address(fwnode, fw_mac_addr, ETH_ALEN)) {
+   *mac_from = "firmware node";
+   ether_addr_copy(dev->dev_addr, fw_mac_addr);
return;
}
 
@@ -7740,13 +7742,14 @@ static void mvpp2_port_copy_mac_addr(struct net_device 
*dev, struct mvpp2 *priv,
 
 /* Ports initialization */
 static int mvpp2_port_probe(struct platform_device *pdev,
-   struct device_node *port_node,
+   struct fwnode_handle *port_fwnode,
struct mvpp2 *priv)
 {
struct device_node *phy_node;
struct phy *comphy;
struct mvpp2_port *port;
struct mvpp2_port_pcpu *port_pcpu;
+   struct device_node *port_node = to_of_node(port_fwnode);
struct net_device *dev;
struct resource *res;
char *mac_from = "";
@@ -7773,7 +7776,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
return -ENOMEM;
 
phy_node = of_parse_phandle(port_node, "phy", 0);
-   phy_mode = of_get_phy_mode(port_node);
+   phy_mode = fwnode_get_phy_mode(port_fwnode);
if (phy_mode < 0) {
dev_err(>dev, "incorrect phy mode\n");
err = phy_mode;
@@ -7789,7 +7792,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
comphy = NULL;
}
 
-   if (of_property_read_u32(port_node, "port-id", )) {
+   if (fwnode_property_read_u32(port_fwnode, "port-id", )) {
err = -EINVAL;
dev_err(>dev, "missing port-id value\n");
goto err_free_netdev;
@@ -7820,7 +7823,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
/* the link irq is optional */
port->link_irq = 0;
 
-   if (of_property_read_bool(port_node, "marvell,loopback"))
+   if (fwnode_property_read_bool(port_fwnode, "marvell,loopback"))
port->flags |= MVPP2_F_LOOPBACK;
 
port->id = id;
@@ -7845,8 +7848,8 @@ static int mvpp2_port_probe(struct platform_device *pdev,
   MVPP21_MIB_COUNTERS_OFFSET +
   port->gop_id * MVPP21_MIB_COUNTERS_PORT_SZ;
} else {
-   if (of_property_read_u32(port_node, "gop-port-id",
->gop_id)) {
+   if (fwnode_property_read_u32(port_fwnode, "gop-port-id",
+>gop_id)) {
err = -EINVAL;
dev_err(>dev, "missing gop-port-id value\n");
goto err_deinit_qvecs;
@@ -7876,7 +7879,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
mutex_init(>gather_stats_lock);
INIT_DELAYED_WORK(>stats_work, mvpp2_gather_hw_statistics);
 
-   mvpp2_port_copy_mac_addr(dev, priv, port_node, _from);
+   mvpp2_port_copy_mac_addr(dev, priv, port_fwnode, _from);
 
port->tx_ring_size = MVPP2_MAX_TXD_DFLT;
port->rx_ring_size = MVPP2_MAX_RXD_DFLT;
@@ -8194,8 +8197,8 @@ static int mvpp2_i

Re: [net-next: PATCH v3 0/7] Armada 7k/8k PP2 ACPI support

2018-01-17 Thread Marcin Wojtas
Hi Andrew,

2018-01-17 19:11 GMT+01:00 Andrew Lunn <and...@lunn.ch>:
> On Wed, Jan 17, 2018 at 05:55:39PM +0100, Marcin Wojtas wrote:
>> Hi,
>>
>> This is a third version of the patchset introducing mvpp2 driver ability
>> to operate with ACPI. Until follow-up generic MDIO is introduced
>> it can using the link interrupt capability (a.k.a. in-band management)
>> on all ports, 1000BaseT RGMII included.
>> Driver operation was tested on top of the net-next branch
>> with both DT and ACPI on MacchiatoBin and Armada 7040 DB boards.
>>
>> The main changes were requested during v2 review, which was
>> adding generic helper routines for:
>> * interating over available fwnodes (new patch 4/7)
>> * getting IRQ directly from fwnode (new patch 3/7)
>
> Hi Marcin
>
> Thanks for adding these helpers. It makes the changes for ACPI much
> less invasive and more natural.
>
> Does the IRQ helper solve the issue of getting an interrupt from a
> child node? I don't see this explicitly mentioned in the commit.  It
> seems to be getting it from a device. Is the child a device?
>

I didn't use word 'child', but this is what exactly what the new
helper is capable of. Hence this should easily fit PHY IRQs,
regardless shape of their final ACPI representation. It's now enough
to have an ACPI handle with IRQ defined in its own _CRS method - it
does not have to be a parent / platform_device.

For the reference, please check the IRQs defined under ETHx subnodes
of the PP2 controllers nodes on MacchiatoBin:
https://github.com/MarvellEmbeddedProcessors/edk2-open-platform/blob/71ae395da1661374b0f07d1602afb1eee56e9794/Platforms/Marvell/Armada/AcpiTables/Armada80x0McBin/Dsdt.asl#L201

Best regards,
Marcin


[net-next: PATCH v3 1/7] device property: Introduce fwnode_get_mac_address()

2018-01-17 Thread Marcin Wojtas
Until now there were two almost identical functions for
obtaining MAC address - of_get_mac_address() and, more generic,
device_get_mac_address(). However it is not uncommon,
that the network interface is represented as a child
of the actual controller, hence it is not associated
directly to any struct device, required by the latter
routine.

This commit allows for getting the MAC address for
children nodes in the ACPI world by introducing a new function -
fwnode_get_mac_address(). This commit also changes
device_get_mac_address() routine to be its wrapper, in order
to prevent unnecessary duplication.

Signed-off-by: Marcin Wojtas <m...@semihalf.com>
Acked-by: Rafael J. Wysocki <rafael.j.wyso...@intel.com>
---
 drivers/base/property.c  | 28 ++--
 include/linux/property.h |  2 ++
 2 files changed, 22 insertions(+), 8 deletions(-)

diff --git a/drivers/base/property.c b/drivers/base/property.c
index 851b1b6..f261d1a 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -1153,11 +1153,11 @@ int device_get_phy_mode(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(device_get_phy_mode);
 
-static void *device_get_mac_addr(struct device *dev,
+static void *fwnode_get_mac_addr(struct fwnode_handle *fwnode,
 const char *name, char *addr,
 int alen)
 {
-   int ret = device_property_read_u8_array(dev, name, addr, alen);
+   int ret = fwnode_property_read_u8_array(fwnode, name, addr, alen);
 
if (ret == 0 && alen == ETH_ALEN && is_valid_ether_addr(addr))
return addr;
@@ -1165,8 +1165,8 @@ static void *device_get_mac_addr(struct device *dev,
 }
 
 /**
- * device_get_mac_address - Get the MAC for a given device
- * @dev:   Pointer to the device
+ * fwnode_get_mac_address - Get the MAC from the firmware node
+ * @fwnode:Pointer to the firmware node
  * @addr:  Address of buffer to store the MAC in
  * @alen:  Length of the buffer pointed to by addr, should be ETH_ALEN
  *
@@ -1187,19 +1187,31 @@ static void *device_get_mac_addr(struct device *dev,
  * In this case, the real MAC is in 'local-mac-address', and 'mac-address'
  * exists but is all zeros.
 */
-void *device_get_mac_address(struct device *dev, char *addr, int alen)
+void *fwnode_get_mac_address(struct fwnode_handle *fwnode, char *addr, int 
alen)
 {
char *res;
 
-   res = device_get_mac_addr(dev, "mac-address", addr, alen);
+   res = fwnode_get_mac_addr(fwnode, "mac-address", addr, alen);
if (res)
return res;
 
-   res = device_get_mac_addr(dev, "local-mac-address", addr, alen);
+   res = fwnode_get_mac_addr(fwnode, "local-mac-address", addr, alen);
if (res)
return res;
 
-   return device_get_mac_addr(dev, "address", addr, alen);
+   return fwnode_get_mac_addr(fwnode, "address", addr, alen);
+}
+EXPORT_SYMBOL(fwnode_get_mac_address);
+
+/**
+ * device_get_mac_address - Get the MAC for a given device
+ * @dev:   Pointer to the device
+ * @addr:  Address of buffer to store the MAC in
+ * @alen:  Length of the buffer pointed to by addr, should be ETH_ALEN
+ */
+void *device_get_mac_address(struct device *dev, char *addr, int alen)
+{
+   return fwnode_get_mac_address(dev_fwnode(dev), addr, alen);
 }
 EXPORT_SYMBOL(device_get_mac_address);
 
diff --git a/include/linux/property.h b/include/linux/property.h
index f6189a3..35620e0 100644
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -279,6 +279,8 @@ int device_get_phy_mode(struct device *dev);
 
 void *device_get_mac_address(struct device *dev, char *addr, int alen);
 
+void *fwnode_get_mac_address(struct fwnode_handle *fwnode,
+char *addr, int alen);
 struct fwnode_handle *fwnode_graph_get_next_endpoint(
const struct fwnode_handle *fwnode, struct fwnode_handle *prev);
 struct fwnode_handle *
-- 
2.7.4



[net-next: PATCH v3 0/7] Armada 7k/8k PP2 ACPI support

2018-01-17 Thread Marcin Wojtas
Hi,

This is a third version of the patchset introducing mvpp2 driver ability
to operate with ACPI. Until follow-up generic MDIO is introduced
it can using the link interrupt capability (a.k.a. in-band management)
on all ports, 1000BaseT RGMII included.
Driver operation was tested on top of the net-next branch
with both DT and ACPI on MacchiatoBin and Armada 7040 DB boards.

The main changes were requested during v2 review, which was
adding generic helper routines for:
* interating over available fwnodes (new patch 4/7)
* getting IRQ directly from fwnode (new patch 3/7)
Thanks to the latter the driver code could be simplified
and allowed to drop formula-based IRQ obtaining. Changes are
summarized in the changelog below.

mvpp2 driver can work with the ACPI representation, as exposed
on a public branch:
https://github.com/MarvellEmbeddedProcessors/edk2-open-platform/commits/marvell-armada-wip
It was compiled together with the most recent Tianocore EDK2 revision.
Please refer to the firmware build instruction on MacchiatoBin board:
http://wiki.macchiatobin.net/tiki-index.php?page=Build+from+source+-+UEFI+EDK+II

ACPI representation of PP2 controllers (withouth PHY support) can
be viewed in the github:
* MacchiatoBin:
https://github.com/MarvellEmbeddedProcessors/edk2-open-platform/blob/71ae395da1661374b0f07d1602afb1eee56e9794/Platforms/Marvell/Armada/AcpiTables/Armada80x0McBin/Dsdt.asl#L201

* Armada 7040 DB:
https://github.com/MarvellEmbeddedProcessors/edk2-open-platform/blob/71ae395da1661374b0f07d1602afb1eee56e9794/Platforms/Marvell/Armada/AcpiTables/Armada70x0/Dsdt.asl#L131

I will appreciate any comments or remarks.

Best regards,
Marcin

Changelog:
v2 -> v3:
* 1/7, 2/7
- Add Rafael's Acked-by's
* 3/7, 4/7
- New patches
* 6/7, 7/7
- Update driver with new helper routines usage
- Improve commit log.

v1 -> v2:
* Remove MDIO patches
* Use PP2 ports only with link interrupts
* Release second region resources in mvpp2 driver (code moved from
  mvmdio), as explained in details in 5/5 commit message.


Marcin Wojtas (7):
  device property: Introduce fwnode_get_mac_address()
  device property: Introduce fwnode_get_phy_mode()
  device property: Introduce fwnode_irq_get()
  device property: Allow iterating over available child fwnodes
  net: mvpp2: simplify maintaining enabled ports' list
  net: mvpp2: use device_*/fwnode_* APIs instead of of_*
  net: mvpp2: enable ACPI support in the driver

 drivers/base/property.c  | 105 --
 drivers/net/ethernet/marvell/mvpp2.c | 206 
 include/linux/property.h |  11 ++
 3 files changed, 230 insertions(+), 92 deletions(-)

-- 
2.7.4



[net-next: PATCH v3 2/7] device property: Introduce fwnode_get_phy_mode()

2018-01-17 Thread Marcin Wojtas
Until now there were two almost identical functions for
obtaining network PHY mode - of_get_phy_mode() and,
more generic, device_get_phy_mode(). However it is not uncommon,
that the network interface is represented as a child
of the actual controller, hence it is not associated
directly to any struct device, required by the latter
routine.

This commit allows for getting the PHY mode for
children nodes in the ACPI world by introducing a new function -
fwnode_get_phy_mode(). This commit also changes
device_get_phy_mode() routine to be its wrapper, in order
to prevent unnecessary duplication.

Signed-off-by: Marcin Wojtas <m...@semihalf.com>
Acked-by: Rafael J. Wysocki <rafael.j.wyso...@intel.com>
---
 drivers/base/property.c  | 24 
 include/linux/property.h |  1 +
 2 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/drivers/base/property.c b/drivers/base/property.c
index f261d1a..7c4a53d 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -1126,21 +1126,21 @@ enum dev_dma_attr device_get_dma_attr(struct device 
*dev)
 EXPORT_SYMBOL_GPL(device_get_dma_attr);
 
 /**
- * device_get_phy_mode - Get phy mode for given device
- * @dev:   Pointer to the given device
+ * fwnode_get_phy_mode - Get phy mode for given firmware node
+ * @fwnode:Pointer to the given node
  *
  * The function gets phy interface string from property 'phy-mode' or
  * 'phy-connection-type', and return its index in phy_modes table, or errno in
  * error case.
  */
-int device_get_phy_mode(struct device *dev)
+int fwnode_get_phy_mode(struct fwnode_handle *fwnode)
 {
const char *pm;
int err, i;
 
-   err = device_property_read_string(dev, "phy-mode", );
+   err = fwnode_property_read_string(fwnode, "phy-mode", );
if (err < 0)
-   err = device_property_read_string(dev,
+   err = fwnode_property_read_string(fwnode,
  "phy-connection-type", );
if (err < 0)
return err;
@@ -1151,6 +1151,20 @@ int device_get_phy_mode(struct device *dev)
 
return -ENODEV;
 }
+EXPORT_SYMBOL_GPL(fwnode_get_phy_mode);
+
+/**
+ * device_get_phy_mode - Get phy mode for given device
+ * @dev:   Pointer to the given device
+ *
+ * The function gets phy interface string from property 'phy-mode' or
+ * 'phy-connection-type', and return its index in phy_modes table, or errno in
+ * error case.
+ */
+int device_get_phy_mode(struct device *dev)
+{
+   return fwnode_get_phy_mode(dev_fwnode(dev));
+}
 EXPORT_SYMBOL_GPL(device_get_phy_mode);
 
 static void *fwnode_get_mac_addr(struct fwnode_handle *fwnode,
diff --git a/include/linux/property.h b/include/linux/property.h
index 35620e0..9b13332 100644
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -279,6 +279,7 @@ int device_get_phy_mode(struct device *dev);
 
 void *device_get_mac_address(struct device *dev, char *addr, int alen);
 
+int fwnode_get_phy_mode(struct fwnode_handle *fwnode);
 void *fwnode_get_mac_address(struct fwnode_handle *fwnode,
 char *addr, int alen);
 struct fwnode_handle *fwnode_graph_get_next_endpoint(
-- 
2.7.4



[net-next: PATCH v3 5/7] net: mvpp2: simplify maintaining enabled ports' list

2018-01-17 Thread Marcin Wojtas
'port_count' field of the mvpp2 structure holds an overall amount
of available ports, based on DT nodes status. In order to be prepared
to support other HW description, obtain the value by incrementing it
upon each successful port initialization. This allowed for simplifying
port indexing in the controller's private array, whose size is now not
dynamically allocated, but fixed to MVPP2_MAX_PORTS.

This patch simplifies creating and filling list of enabled ports and
is a part of the preparation for adding ACPI support in the mvpp2 driver.

Signed-off-by: Marcin Wojtas <m...@semihalf.com>
---
 drivers/net/ethernet/marvell/mvpp2.c | 32 +++-
 1 file changed, 11 insertions(+), 21 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvpp2.c 
b/drivers/net/ethernet/marvell/mvpp2.c
index a197607..7f42d90 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -865,7 +865,7 @@ struct mvpp2 {
 
/* List of pointers to port structures */
int port_count;
-   struct mvpp2_port **port_list;
+   struct mvpp2_port *port_list[MVPP2_MAX_PORTS];
 
/* Aggregated TXQs */
struct mvpp2_tx_queue *aggr_txqs;
@@ -7741,7 +7741,7 @@ static void mvpp2_port_copy_mac_addr(struct net_device 
*dev, struct mvpp2 *priv,
 /* Ports initialization */
 static int mvpp2_port_probe(struct platform_device *pdev,
struct device_node *port_node,
-   struct mvpp2 *priv, int index)
+   struct mvpp2 *priv)
 {
struct device_node *phy_node;
struct phy *comphy;
@@ -7934,7 +7934,8 @@ static int mvpp2_port_probe(struct platform_device *pdev,
}
netdev_info(dev, "Using %s mac address %pM\n", mac_from, dev->dev_addr);
 
-   priv->port_list[index] = port;
+   priv->port_list[priv->port_count++] = port;
+
return 0;
 
 err_free_port_pcpu:
@@ -8313,28 +8314,17 @@ static int mvpp2_probe(struct platform_device *pdev)
goto err_mg_clk;
}
 
-   priv->port_count = of_get_available_child_count(dn);
-   if (priv->port_count == 0) {
-   dev_err(>dev, "no ports enabled\n");
-   err = -ENODEV;
-   goto err_mg_clk;
-   }
-
-   priv->port_list = devm_kcalloc(>dev, priv->port_count,
-  sizeof(*priv->port_list),
-  GFP_KERNEL);
-   if (!priv->port_list) {
-   err = -ENOMEM;
-   goto err_mg_clk;
-   }
-
/* Initialize ports */
-   i = 0;
for_each_available_child_of_node(dn, port_node) {
-   err = mvpp2_port_probe(pdev, port_node, priv, i);
+   err = mvpp2_port_probe(pdev, port_node, priv);
if (err < 0)
goto err_port_probe;
-   i++;
+   }
+
+   if (priv->port_count == 0) {
+   dev_err(>dev, "no ports enabled\n");
+   err = -ENODEV;
+   goto err_mg_clk;
}
 
/* Statistics must be gathered regularly because some of them (like
-- 
2.7.4



[net-next: PATCH v3 3/7] device property: Introduce fwnode_irq_get()

2018-01-17 Thread Marcin Wojtas
Until now there were two very similar functions allowing
to get Linux IRQ number from ACPI handle (acpi_irq_get())
and OF node (of_irq_get()). The first one appeared to be used
only as a subroutine of platform_irq_get(), which (in the generic
code) limited IRQ obtaining from _CRS method only to nodes
associated to kernel's struct platform_device.

This patch introduces new helper routine - fwnode_irq_get(),
which allows to get the IRQ number directly from the fwnode
to be used as common for OF/ACPI worlds.

Signed-off-by: Marcin Wojtas <m...@semihalf.com>
---
 drivers/base/property.c  | 27 
 include/linux/property.h |  2 ++
 2 files changed, 29 insertions(+)

diff --git a/drivers/base/property.c b/drivers/base/property.c
index 7c4a53d..adb3893 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -16,6 +16,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -1230,6 +1231,32 @@ void *device_get_mac_address(struct device *dev, char 
*addr, int alen)
 EXPORT_SYMBOL(device_get_mac_address);
 
 /**
+ * fwnode_irq_get - Get IRQ directly from a fwnode
+ * @fwnode:Pointer to the firmware node
+ * @index: Zero-based index of the IRQ
+ *
+ * Returns Linux IRQ number on success. Other values are determined
+ * accordingly to acpi_/of_ irq_get() operation.
+ */
+int fwnode_irq_get(struct fwnode_handle *fwnode, unsigned int index)
+{
+   struct acpi_device *adev = to_acpi_device_node(fwnode);
+   struct device_node *of_node = to_of_node(fwnode);
+   struct resource res;
+   int ret;
+
+   if (IS_ENABLED(CONFIG_OF) && of_node)
+   return of_irq_get(of_node, index);
+
+   ret = acpi_irq_get(acpi_device_handle(adev), index, );
+   if (ret)
+   return ret;
+
+   return res.start;
+}
+EXPORT_SYMBOL(fwnode_irq_get);
+
+/**
  * device_graph_get_next_endpoint - Get next endpoint firmware node
  * @fwnode: Pointer to the parent firmware node
  * @prev: Previous endpoint node or %NULL to get the first
diff --git a/include/linux/property.h b/include/linux/property.h
index 9b13332..e05889f 100644
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -103,6 +103,8 @@ struct fwnode_handle *device_get_named_child_node(struct 
device *dev,
 struct fwnode_handle *fwnode_handle_get(struct fwnode_handle *fwnode);
 void fwnode_handle_put(struct fwnode_handle *fwnode);
 
+int fwnode_irq_get(struct fwnode_handle *fwnode, unsigned int index);
+
 unsigned int device_get_child_node_count(struct device *dev);
 
 static inline bool device_property_read_bool(struct device *dev,
-- 
2.7.4



[net-next: PATCH v3 6/7] net: mvpp2: use device_*/fwnode_* APIs instead of of_*

2018-01-17 Thread Marcin Wojtas
OF functions can be used only for the driver using DT.
As a preparation for introducing ACPI support in mvpp2
driver, use struct fwnode_handle in order to obtain
properties from the hardware description.

This patch replaces of_* function with device_*/fwnode_*
where possible in the mvpp2.

Signed-off-by: Marcin Wojtas <m...@semihalf.com>
---
 drivers/net/ethernet/marvell/mvpp2.c | 45 +++-
 1 file changed, 24 insertions(+), 21 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvpp2.c 
b/drivers/net/ethernet/marvell/mvpp2.c
index 7f42d90..f16448e 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -932,6 +932,9 @@ struct mvpp2_port {
 
struct mvpp2 *priv;
 
+   /* Firmware node associated to the port */
+   struct fwnode_handle *fwnode;
+
/* Per-port registers' base address */
void __iomem *base;
void __iomem *stats_base;
@@ -7711,17 +7714,16 @@ static bool mvpp2_port_has_tx_irqs(struct mvpp2 *priv,
 }
 
 static void mvpp2_port_copy_mac_addr(struct net_device *dev, struct mvpp2 
*priv,
-struct device_node *port_node,
+struct fwnode_handle *fwnode,
 char **mac_from)
 {
struct mvpp2_port *port = netdev_priv(dev);
char hw_mac_addr[ETH_ALEN] = {0};
-   const char *dt_mac_addr;
+   char fw_mac_addr[ETH_ALEN];
 
-   dt_mac_addr = of_get_mac_address(port_node);
-   if (dt_mac_addr && is_valid_ether_addr(dt_mac_addr)) {
-   *mac_from = "device tree";
-   ether_addr_copy(dev->dev_addr, dt_mac_addr);
+   if (fwnode_get_mac_address(fwnode, fw_mac_addr, ETH_ALEN)) {
+   *mac_from = "firmware node";
+   ether_addr_copy(dev->dev_addr, fw_mac_addr);
return;
}
 
@@ -7740,13 +7742,14 @@ static void mvpp2_port_copy_mac_addr(struct net_device 
*dev, struct mvpp2 *priv,
 
 /* Ports initialization */
 static int mvpp2_port_probe(struct platform_device *pdev,
-   struct device_node *port_node,
+   struct fwnode_handle *port_fwnode,
struct mvpp2 *priv)
 {
struct device_node *phy_node;
struct phy *comphy;
struct mvpp2_port *port;
struct mvpp2_port_pcpu *port_pcpu;
+   struct device_node *port_node = to_of_node(port_fwnode);
struct net_device *dev;
struct resource *res;
char *mac_from = "";
@@ -7773,7 +7776,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
return -ENOMEM;
 
phy_node = of_parse_phandle(port_node, "phy", 0);
-   phy_mode = of_get_phy_mode(port_node);
+   phy_mode = fwnode_get_phy_mode(port_fwnode);
if (phy_mode < 0) {
dev_err(>dev, "incorrect phy mode\n");
err = phy_mode;
@@ -7789,7 +7792,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
comphy = NULL;
}
 
-   if (of_property_read_u32(port_node, "port-id", )) {
+   if (fwnode_property_read_u32(port_fwnode, "port-id", )) {
err = -EINVAL;
dev_err(>dev, "missing port-id value\n");
goto err_free_netdev;
@@ -7820,7 +7823,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
/* the link irq is optional */
port->link_irq = 0;
 
-   if (of_property_read_bool(port_node, "marvell,loopback"))
+   if (fwnode_property_read_bool(port_fwnode, "marvell,loopback"))
port->flags |= MVPP2_F_LOOPBACK;
 
port->id = id;
@@ -7845,8 +7848,8 @@ static int mvpp2_port_probe(struct platform_device *pdev,
   MVPP21_MIB_COUNTERS_OFFSET +
   port->gop_id * MVPP21_MIB_COUNTERS_PORT_SZ;
} else {
-   if (of_property_read_u32(port_node, "gop-port-id",
->gop_id)) {
+   if (fwnode_property_read_u32(port_fwnode, "gop-port-id",
+>gop_id)) {
err = -EINVAL;
dev_err(>dev, "missing gop-port-id value\n");
goto err_deinit_qvecs;
@@ -7876,7 +7879,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
mutex_init(>gather_stats_lock);
INIT_DELAYED_WORK(>stats_work, mvpp2_gather_hw_statistics);
 
-   mvpp2_port_copy_mac_addr(dev, priv, port_node, _from);
+   mvpp2_port_copy_mac_addr(dev, priv, port_fwnode, _from);
 
port->tx_ring_size = MVPP2_MAX_TXD_DFLT;
port->rx_ring_size = MVPP2_MAX_RXD_DFLT;
@@ -8194,8 +8197,8 @@ static int mvpp2_i

[net-next: PATCH v3 4/7] device property: Allow iterating over available child fwnodes

2018-01-17 Thread Marcin Wojtas
Implement a new helper function fwnode_get_next_available_child_node(),
which enables obtaining next enabled child fwnode, which
works on a similar basis to OF's of_get_next_available_child().

This commit also introduces a macro, thanks to which it is
possible to iterate over the available fwnodes, using the
new function described above.

Signed-off-by: Marcin Wojtas <m...@semihalf.com>
---
 drivers/base/property.c  | 26 
 include/linux/property.h |  6 +
 2 files changed, 32 insertions(+)

diff --git a/drivers/base/property.c b/drivers/base/property.c
index adb3893..2343906 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -998,6 +998,32 @@ fwnode_get_next_child_node(const struct fwnode_handle 
*fwnode,
 EXPORT_SYMBOL_GPL(fwnode_get_next_child_node);
 
 /**
+ * fwnode_get_next_available_child_node - Return the next
+ * available child node handle for a node
+ * @fwnode: Firmware node to find the next child node for.
+ * @child: Handle to one of the node's child nodes or a %NULL handle.
+ */
+struct fwnode_handle *
+fwnode_get_next_available_child_node(const struct fwnode_handle *fwnode,
+struct fwnode_handle *child)
+{
+   struct fwnode_handle *next_child = child;
+
+   if (!fwnode)
+   return NULL;
+
+   do {
+   next_child = fwnode_get_next_child_node(fwnode, next_child);
+
+   if (!next_child || fwnode_device_is_available(next_child))
+   break;
+   } while (next_child);
+
+   return next_child;
+}
+EXPORT_SYMBOL_GPL(fwnode_get_next_available_child_node);
+
+/**
  * device_get_next_child_node - Return the next child node handle for a device
  * @dev: Device to find the next child node for.
  * @child: Handle to one of the device's child nodes or a null handle.
diff --git a/include/linux/property.h b/include/linux/property.h
index e05889f..5b0563a 100644
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -83,11 +83,17 @@ struct fwnode_handle *fwnode_get_next_parent(
struct fwnode_handle *fwnode);
 struct fwnode_handle *fwnode_get_next_child_node(
const struct fwnode_handle *fwnode, struct fwnode_handle *child);
+struct fwnode_handle *fwnode_get_next_available_child_node(
+   const struct fwnode_handle *fwnode, struct fwnode_handle *child);
 
 #define fwnode_for_each_child_node(fwnode, child)  \
for (child = fwnode_get_next_child_node(fwnode, NULL); child;   \
 child = fwnode_get_next_child_node(fwnode, child))
 
+#define fwnode_for_each_available_child_node(fwnode, child)   \
+   for (child = fwnode_get_next_available_child_node(fwnode, NULL); child;\
+child = fwnode_get_next_available_child_node(fwnode, child))
+
 struct fwnode_handle *device_get_next_child_node(
struct device *dev, struct fwnode_handle *child);
 
-- 
2.7.4



[net-next: PATCH v3 7/7] net: mvpp2: enable ACPI support in the driver

2018-01-17 Thread Marcin Wojtas
This patch introduces an alternative way of obtaining resources - via
ACPI tables provided by firmware. Enabling coexistence with the DT
support, in addition to the OF_*->device_*/fwnode_* API replacement,
required following steps to be taken:

* Add mvpp2_acpi_match table
* Omit clock configuration and obtain tclk from the property - in ACPI
  world, the firmware is responsible for clock maintenance.
* Disable comphy and syscon handling as they are not available for ACPI.
* Modify way of obtaining interrupts - use newly introduced
  fwnode_irq_get() routine
* Until proper MDIO bus and PHY handling with ACPI is established in the
  kernel, use only link interrupts feature in the driver. For the RGMII
  port it results in depending on GMAC settings done during firmware
  stage.
* When booting with ACPI MVPP2_QDIST_MULTI_MODE is picked by
  default, as there is no need to keep any kind of the backward
  compatibility.

Moreover, a memory region used by mvmdio driver is usually placed in
the middle of the address space of the PP2 network controller.
The MDIO base address is obtained without requesting memory region
(by devm_ioremap() call) in mvmdio.c, later overlapping resources are
requested by the network driver, which is responsible for avoiding
a concurrent access.

In case the MDIO memory region is declared in the ACPI, it can
already appear as 'in-use' in the OS. Because it is overlapped by second
region of the network controller, make sure it is released, before
requesting it again. The care is taken by mvpp2 driver to avoid
concurrent access to this memory region.

Signed-off-by: Marcin Wojtas <m...@semihalf.com>
---
 drivers/net/ethernet/marvell/mvpp2.c | 133 ++--
 1 file changed, 94 insertions(+), 39 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvpp2.c 
b/drivers/net/ethernet/marvell/mvpp2.c
index f16448e..a1d7b88 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -10,6 +10,7 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -7502,7 +7503,10 @@ static int mvpp2_multi_queue_vectors_init(struct 
mvpp2_port *port,
strncpy(irqname, "rx-shared", sizeof(irqname));
}
 
-   v->irq = of_irq_get_byname(port_node, irqname);
+   if (port_node)
+   v->irq = of_irq_get_byname(port_node, irqname);
+   else
+   v->irq = fwnode_irq_get(port->fwnode, i);
if (v->irq <= 0) {
ret = -EINVAL;
goto err;
@@ -7746,7 +7750,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
struct mvpp2 *priv)
 {
struct device_node *phy_node;
-   struct phy *comphy;
+   struct phy *comphy = NULL;
struct mvpp2_port *port;
struct mvpp2_port_pcpu *port_pcpu;
struct device_node *port_node = to_of_node(port_fwnode);
@@ -7760,7 +7764,12 @@ static int mvpp2_port_probe(struct platform_device *pdev,
int phy_mode;
int err, i, cpu;
 
-   has_tx_irqs = mvpp2_port_has_tx_irqs(priv, port_node);
+   if (port_node) {
+   has_tx_irqs = mvpp2_port_has_tx_irqs(priv, port_node);
+   } else {
+   has_tx_irqs = true;
+   queue_mode = MVPP2_QDIST_MULTI_MODE;
+   }
 
if (!has_tx_irqs)
queue_mode = MVPP2_QDIST_SINGLE_MODE;
@@ -7775,7 +7784,11 @@ static int mvpp2_port_probe(struct platform_device *pdev,
if (!dev)
return -ENOMEM;
 
-   phy_node = of_parse_phandle(port_node, "phy", 0);
+   if (port_node)
+   phy_node = of_parse_phandle(port_node, "phy", 0);
+   else
+   phy_node = NULL;
+
phy_mode = fwnode_get_phy_mode(port_fwnode);
if (phy_mode < 0) {
dev_err(>dev, "incorrect phy mode\n");
@@ -7783,13 +7796,15 @@ static int mvpp2_port_probe(struct platform_device 
*pdev,
goto err_free_netdev;
}
 
-   comphy = devm_of_phy_get(>dev, port_node, NULL);
-   if (IS_ERR(comphy)) {
-   if (PTR_ERR(comphy) == -EPROBE_DEFER) {
-   err = -EPROBE_DEFER;
-   goto err_free_netdev;
+   if (port_node) {
+   comphy = devm_of_phy_get(>dev, port_node, NULL);
+   if (IS_ERR(comphy)) {
+   if (PTR_ERR(comphy) == -EPROBE_DEFER) {
+   err = -EPROBE_DEFER;
+   goto err_free_netdev;
+   }
+   comphy = NULL;
}
-   comphy = NULL;
}
 
if (fwnode_property_read_u32(port_fwnode, "port-id", )) {
@@ -7805,6 +7820,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
 
   

Re: [net-next: PATCH 0/8] Armada 7k/8k PP2 ACPI support

2018-01-09 Thread Marcin Wojtas
2018-01-09 11:19 GMT+01:00 Graeme Gregory <graeme.greg...@linaro.org>:
> On Mon, Jan 08, 2018 at 06:17:06PM +0100, Marcin Wojtas wrote:
>> Hi Andrew,
>>
>>
>>
>> 2018-01-08 16:42 GMT+01:00 Andrew Lunn <and...@lunn.ch>:
>> > w> I am not familiar with MDIO, but if its similar or a specific
>> >> implementation of a serial bus that does sound sane!
>> >
>>
>> Thanks for digging, I will check if and how we can use
>> GenericSerialBus with MDIO.
>>
> Maybe Lorenzo, Hanjun, Sudeep can comment here they might have come
> across similar on other ARM boards.
>

I'm looking forward to their feedback, however, what I've noticed,
each driver handles mdio/phys on its own, not using any generic
solution, which is what I need to actually avoid :)

Best regards,
Marcin


Re: [net-next: PATCH 0/8] Armada 7k/8k PP2 ACPI support

2018-01-08 Thread Marcin Wojtas
Hi Andrew,



2018-01-08 16:42 GMT+01:00 Andrew Lunn :
> w> I am not familiar with MDIO, but if its similar or a specific
>> implementation of a serial bus that does sound sane!
>

Thanks for digging, I will check if and how we can use
GenericSerialBus with MDIO.

Best regards,
Marcin

> It is a two wire serial bus. A good overview can be found here:
>
> https://www.totalphase.com/support/articles/200349206-MDIO-Background
>


Re: [EXT] Re: [PATCH net-next 5/6] arm64: dts: marvell: mcbin: enable the fourth network interface

2018-01-03 Thread Marcin Wojtas
Russell,

2018-01-03 18:54 GMT+01:00 Russell King - ARM Linux :
> On Wed, Jan 03, 2018 at 05:00:47PM +, Stefan Chulski wrote:
>> > > > -Original Message-
>> > > > Hi Russell,
>> > > >
>> > > > Indeed. RGMII MAC behaves same way, although it shouldn't be named
>> > > > as 'in- band' to be on par with the specifications. Anyway - this
>> > > > one is rather a stub for being able to work with ACPI, so once the
>> > > > MDIO bus works there, this will be out of any concerns.
>> > >
>> > > Hi Marcin,
>> > >
>> > > This is correct.
>> > > "in-band" supported only for SGMII mode.
>> > > IRQ link interrupt depend on "in-band"' auto negation only if "in-band"'
>> > enabled.
>> > > But IRQ link interrupt could be triggered with "in-band", "out-band" or 
>> > > with
>> > specific fixed speed/duplex/flow_contol.
>> >
>> > Hi Stefan,
>> >
>> > How does this work in RGMII mode - is this handled by the PP2 polling the 
>> > PHY
>> > to get the speed, duplex and flow control settings?
>> >
>>
>> IRQ interrupt doesn't handled speed, duplex and flow control settings.
>> It's just raised if number of criterions met:
>> 1) Physical signal detected by MAC
>> 2) MAC auto negotiation succeeded(valid only auto negotiation enabled in MAC 
>> and "in-band" bypass disabled)
>>
>> So if auto negotiation mechanism disabled in MAC or bypassed, link status 
>> would changes to up and IRQ interrupt be triggered.
>>
>> In case of RGMII mode obviously we don't have "in-band" auto negotiation and 
>> "out-band" cannot be used in Kernel(due to missed locks).
>> So auto negotiation should be disabled on MAC level and 
>> speed/duplex/flow_contol would be negotiate by PHY.
>> phylink/phylib infrastructure should provide speed/duplex/flow_contol(that 
>> were agreed between PHY's) to ppv2 driver.
>
> Sorry, I find this very confusing.
>
> It seems we have some people telling me that when there's no PHY
> described in DT, we use this link interrupt, and have a functional
> network interface (presumably at whatever speed.)
>
> I can't see this working from what you describe - what you describe
> basically tells me that when in-band autonegotiation is disabled, and we
> have no PHY in the kernel, then effectively we are in fixed-link mode -
> since we need to know what speed, duplex and flow control settings to
> use.
>
> So, this means that mvpp2 should be enforcing the presence of a
> fixed-link description in DT if there is no PHY node at the moment, but
> it doesn't.
>
> Instead, it looks to me like the speed and duplex settings are inherited
> from the boot loader or whatever was running before - I can't find
> anything that configures MVPP2_GMAC_AUTONEG_CONFIG in this case.  That
> seems quite a mess.

Just 3 cents from me about the RGMII + link IRQ, which is only a
temporary solution for ACPI. It works basing on the results of UEFI HW
PHY polling and inherited GMAC settings. Once this MDIO bus / PHY
handling lands, this configuration will be out of any question and
usage in the pp2 driver.

Marcin

>
> Maybe I'm missing something, but I don't see how mvpp2 can be converted
> to phylink given this without causing some kind of regression, unless
> someone can be much clearer about exactly what kinds of link mvpp2
> supports and how they work (which is basically what I asked back in
> October.)
>
> --
> RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
> FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
> According to speedtest.net: 8.21Mbps down 510kbps up


Re: [net-next: PATCH 0/8] Armada 7k/8k PP2 ACPI support

2018-01-03 Thread Marcin Wojtas
2018-01-03 14:33 GMT+01:00 Andrew Lunn <and...@lunn.ch>:
> On Wed, Jan 03, 2018 at 02:13:09PM +0100, Marcin Wojtas wrote:
>> Hi Andrew,
>>
>> 2018-01-03 13:47 GMT+01:00 Andrew Lunn <and...@lunn.ch>:
>> >> I already agreed with 'reg' being awkward in the later emails.
>> >> Wouldn't _ADR be more appropriate to specify PHY address on MDIO bus?
>> >
>> > Also, how do you specify which MDIO bus the PHY is on. To fully
>> > specify a PHY, you need both bits of information.
>> >
>> > In DT, the phy-handle phandle can point to any PHY anywhere in the
>> > system. This is particularly important when a Ethernet device has two
>> > MDIO busses.
>> >
>>
>> For now, my local MDIO bus description is pretty DT-like, i.e. master
>> bus with children PHYs:
>> Device (MDIO)
>> {
>> Name (_HID, "MRVL0100") //
>> _HID: Hardware ID
>> Name (_UID, 0x00)   //
>> _UID: Unique ID
>> Name (_CRS, ResourceTemplate ()
>> {
>> Memory32Fixed (ReadWrite,
>> 0xf212a200, // Address 
>> Base
>> 0x0010, //
>> Address Length
>> )
>> })
>> Device (GPHY)
>> {
>>   Name (_ADR, 0x0)
>> }
>> }
>>
>> Device (XSMI)
>> {
>> Name (_HID, "MRVL0101") //
>> _HID: Hardware ID
>> Name (_UID, 0x00)   //
>> _UID: Unique ID
>> Name (_CRS, ResourceTemplate ()
>> {
>> Memory32Fixed (ReadWrite,
>> 0xf212a600, // Address 
>> Base
>> 0x0010, //
>> Address Length
>> )
>> })
>> Device (PHY0)
>> {
>>   Name (_ADR, 0x0)
>>   Name (_CID, "ethernet-phy-ieee802.3-c45")
>> }
>> Device (PHY8)
>> {
>>   Name (_ADR, 0x8)
>>   Name (_CID, "ethernet-phy-ieee802.3-c45")
>> }
>> }
>>
>> Which is referenced in the port's node:
>>
>> Package () { "phy", Package (){\_SB.XSMI.PHY0}},
>
> Hi Marcin
>
> This reference looks good, giving both the bus and the PHY on the bus.
>
> I assume you can use references like this within the Device (PHY8)
> node?

Yes.

> You need to be able to reference a GPIO used for resetting the
> PHY. And you also need to reference a GPIO at the Device (MDIO) level
> for resetting all the PHYs on the MDIO bus.
>

Yes, for full support of PHYs the GPIO must be supported, as well as
the PHY's IRQs.

Best regards,
Marcin


Re: [net-next: PATCH 0/8] Armada 7k/8k PP2 ACPI support

2018-01-03 Thread Marcin Wojtas
Hi Andrew,

2018-01-03 13:47 GMT+01:00 Andrew Lunn :
>> I already agreed with 'reg' being awkward in the later emails.
>> Wouldn't _ADR be more appropriate to specify PHY address on MDIO bus?
>
> Also, how do you specify which MDIO bus the PHY is on. To fully
> specify a PHY, you need both bits of information.
>
> In DT, the phy-handle phandle can point to any PHY anywhere in the
> system. This is particularly important when a Ethernet device has two
> MDIO busses.
>

For now, my local MDIO bus description is pretty DT-like, i.e. master
bus with children PHYs:
Device (MDIO)
{
Name (_HID, "MRVL0100") //
_HID: Hardware ID
Name (_UID, 0x00)   //
_UID: Unique ID
Name (_CRS, ResourceTemplate ()
{
Memory32Fixed (ReadWrite,
0xf212a200, // Address Base
0x0010, //
Address Length
)
})
Device (GPHY)
{
  Name (_ADR, 0x0)
}
}

Device (XSMI)
{
Name (_HID, "MRVL0101") //
_HID: Hardware ID
Name (_UID, 0x00)   //
_UID: Unique ID
Name (_CRS, ResourceTemplate ()
{
Memory32Fixed (ReadWrite,
0xf212a600, // Address Base
0x0010, //
Address Length
)
})
Device (PHY0)
{
  Name (_ADR, 0x0)
  Name (_CID, "ethernet-phy-ieee802.3-c45")
}
Device (PHY8)
{
  Name (_ADR, 0x8)
  Name (_CID, "ethernet-phy-ieee802.3-c45")
}
}

Which is referenced in the port's node:

Package () { "phy", Package (){\_SB.XSMI.PHY0}},

I'm studying an alternatives with graphs, as suggested by Tomasz
Nowicki, but to me above is pretty natural and not complicated.

Best regards,
Marcin


Re: [net-next: PATCH v2 5/5] net: mvpp2: enable ACPI support in the driver

2018-01-03 Thread Marcin Wojtas
Graeme,

2018-01-03 12:16 GMT+01:00  :
> On Sun, Dec 31, 2017 at 08:23:54PM +0100, Andrew Lunn wrote:
>> > * Modify way of obtaining interrupts - with ACPI they are resources
>> >   bound to struct platform_device and it's not possible to obtain
>> >   them directly from the child node. Hence a formula is used, depending
>> >   on the port_id and number of possible CPUs.
>>
>> Hi Marcin
>>
>> I know nothing about ACPI. Is this limitation with respect to
>> interrupts fundamental to ACPI, or just that nobody has implemented
>> flexible interrupt support yet?
>>
> The infrastructure is there to traverse trees of children, but I don't
> think there any helper functions.
>

Thanks, so if I implement such, do you expect any formal issues that
prevent its acceptance?

Best regards,
Marcin


Re: [net-next: PATCH 0/8] Armada 7k/8k PP2 ACPI support

2018-01-03 Thread Marcin Wojtas
Hi Graeme,

2018-01-03 12:00 GMT+01:00 Graeme Gregory <graeme.greg...@linaro.org>:
> On Mon, Dec 18, 2017 at 10:40:31AM +0100, Ard Biesheuvel wrote:
>> On 18 December 2017 at 10:17, Marcin Wojtas <m...@semihalf.com> wrote:
>> > Hi,
>> >
>> > This patchset introduces ACPI support in mvpp2 and mvmdio drivers.
>> > First three patches introduce fwnode helpers for obtaining PHY
>> > information from nodes and also MDIO fwnode API for registering
>> > the bus with its PHY/devices.
>> >
>> > Following patches update code of the mvmdio and mvpp2 drivers
>> > to support ACPI tables handling. The latter is done in 4 steps,
>> > as can be seen in the commits. For the details, please
>> > refer to the commit messages.
>> >
>> > Drivers operation was tested on top of the net-next branch
>> > with both DT and ACPI. Although for compatibility reasons
>> > with older platforms, the mvmdio driver keeps using
>> > of_ MDIO registering, new fwnode_ one proved to fully work
>> > with DT as well (tested on MacchiatoBin board).
>> >
>> > mvpp2/mvmdio driver can work with the ACPI representation, as exposed
>> > on a public branch:
>> > https://github.com/MarvellEmbeddedProcessors/edk2-open-platform/commits/marvell-armada-wip
>> > It was compiled together with the most recent Tianocore EDK2 revision.
>> > Please refer to the firmware build instruction on MacchiatoBin board:
>> > http://wiki.macchiatobin.net/tiki-index.php?page=Build+from+source+-+UEFI+EDK+II
>> >
>> > Above support configures 1G to use its PHY normally. 10G can work now
>> > only with the link interrupt mode. Somehow reading of the
>> > string property in fwnode_mdiobus_child_is_phy works only with
>> > DT and cannot cope with 10G PHY nodes as in:
>> > https://pastebin.com/3JnYpU0A
>> >
>> > Above root cause will be further checked. In the meantime I will
>> > appreciate any comments or remarks for the kernel patches.
>> >
>>
>> Hi Marcin,
>>
>> I have added linux-acpi and Graeme to cc. I think it makes sense to
>> discuss the way you describe the device topology before looking at the
>> patches in more detail.
>>
>> In particular, I would like to request feedback on the use of
>> [redundant] 'reg' properties and the use of _DSD + compatible to
>> describe PHYs. Usually, we try to avoid this, given that it is
>> essentially a ACPI encapsulated DT dialect that is difficult to
>> support in drivers unless they are based on DT to begin with. Also,
>> non-standard _DSD properties require a vendor prefix, it is not
>> freeform.
>>
>> For reference, the ACPI description is here (starting at line 175)
>> https://github.com/MarvellEmbeddedProcessors/edk2-open-platform/blob/72d5ac23b20dd74d479daa5e40ba443264b31261/Platforms/Marvell/Armada/AcpiTables/Armada80x0McBin/Dsdt.asl
>>
> So the representation of PHY's with _DSD was kind of formalised here
>
> http://www.uefi.org/sites/default/files/resources/nic-request-v2.pdf
>
> This is already in use in the kernel, and that DSDT seems to be along the same
> lines. So seems ok in that manner.
>
> The "reg", 0 property seems a little odd, it would probably make more
> sense to check for the lack of ranges passed in in ACPI manner _CRS.
>

I already agreed with 'reg' being awkward in the later emails.
Wouldn't _ADR be more appropriate to specify PHY address on MDIO bus?

Thanks,
Marcin


Re: [net-next: PATCH v2 5/5] net: mvpp2: enable ACPI support in the driver

2018-01-02 Thread Marcin Wojtas
2018-01-02 15:08 GMT+01:00 Andrew Lunn :
>> Indeed in of_mdio_bus_register_phy, there is of_irq_get. This is more
>> a discussion for a MDIO bus / ACPI patchset, but we either find a way
>> to use IRQs with ACPI obtained from child nodes or for this world the
>> functionality will be limited (at least for the beginning).
>
> Hi Marcin
>
> What i want to avoid is adding something which partially works, and
> then have to throw it all away and start again in order to add full
> support.
>
> If ACPI really limits interrupts to devices, maybe we need a totally
> different representation of MDIO and PHYs in ACPI to what it used in
> device tree? The same may be true for the Ethernet ports of the mvpp2?
> They might have to be represented as real devices, not children of a
> device? Maybe trying to map DT to ACPI on a one-to-one basis is the
> wrong approach?
>

In terms of PP2 controller, I'd prefer to keep as much as possible to
describing how real hardware looks like, i.e. single common controller
with multiple ports as its children. Those considerations are
reflected in the DT description shape and how the driver enumerates,
which was part of the design of the initial support. Bending the
driver (huge amount of shared initialization and resources) to
multiple instances just for the sake of possible avoidance of IRQ
description in ACPI is IMO a huge and unnecessary overkill.

Anyway, I'll do a more research on the resources / ACPI representation
and will get back with some conclusions. I hope that someone from this
thread recipents will be able to give some advice too :)

Best regards,
Marcin


Re: [net-next: PATCH v2 5/5] net: mvpp2: enable ACPI support in the driver

2018-01-02 Thread Marcin Wojtas
Hi Andrew,

2018-01-02 14:33 GMT+01:00 Andrew Lunn :
>> Apart from the phylink's SFP support that may require in-band
>> management, it's an alternative to the normal PHY handling. Once MDIO
>> bus + PHYs are supported for ACPI, phylib support will be used instead
>> of the IRQs, so there should be no problem here.
>
> Hi Marcin
>
> However, phylib and phylink can use IRQs. The PHY can interrupt when
> there is a change of state. This can be seen in the DT binding
> documentation example:
>
> ethernet-phy@0 {
> compatible = "ethernet-phy-id0141.0e90", "ethernet-phy-ieee802.3-c22";
> interrupt-parent = <>;
> interrupts = <35 IRQ_TYPE_EDGE_RISING>;
> reg = <0>;
>
> Whatever ACPI support you propose needs to include interrupts.
>
> May i suggest you take a look at
> arch/arm/boot/dts/vf610-zii-dev-rev-c.dts and ensure your ACPI work
> can support this. I know you tend to concentrate of Marvell parts.
> Although it is a Freescale SoC, the Ethernet parts are all Marvell.
>
> The SoC exports an MDIO bus. We then have an MDIO multiplexer, which
> exports 8 MDIO busses. Of these only 2 are used in this design. Each
> bus has an Ethernet switch. Each switch has an MDIO bus, which the
> embedded PHYs are on. The Ethernet switch is also an interrupt
> controller for the PHYs interrupts. So the PHYs have interrupt
> properties pointing back to the switch.
>

I thought you were pointing possible problems in mvpp2 with PHY/link
interrupts, sorry. Now I get it :)

Indeed in of_mdio_bus_register_phy, there is of_irq_get. This is more
a discussion for a MDIO bus / ACPI patchset, but we either find a way
to use IRQs with ACPI obtained from child nodes or for this world the
functionality will be limited (at least for the beginning).

Best regards,
Marcin


Re: [PATCH net-next 5/6] arm64: dts: marvell: mcbin: enable the fourth network interface

2018-01-01 Thread Marcin Wojtas
Hi Russell,

2017-12-30 18:31 GMT+01:00 Russell King - ARM Linux <li...@armlinux.org.uk>:
> Hi Marcin,
>
> On Sat, Dec 30, 2017 at 05:34:23PM +0100, Marcin Wojtas wrote:
>> Yes, I already split the series and will send first one right away. I
>> will be followed by MDIO bus / PHY handling proposal, including the
>> bits related to phylink. I'm looking forward to your opinion on that
>> once sent.
>
> I'm looking forward to the patches. :)
>
>> This my understanding of how the PP2 HW works in terms of signalling
>> the link interrupt:
>>
>> The full in-band management, similar to mvneta is supported only in
>> the SGMII mode (1G, not sure how it looks like in 2.5G mode). Such
>> handling is not yet implemented in the mvpp2.c
>>
>> 10G:
>> The XGMII MAC (XLG) is capable of generating link status change
>> interrupt upon information provided from the reconciliation layer (RS)
>> of the interface.
>>
>> 2.5G/1G SGMII:
>> Apart from the in-band management, the MAC is also capable of
>> generating IRQ during link-status change.
>>
>> 1G RGMII:
>> I was a bit surprised, but checked on my own - the link change IRQ can
>> be generated here as well.
>>
>> In addition to above the clause 22 PHYs can be automatically polled
>> via SMI bus and provide complete information about link status, speed,
>> etc., reflecting it directly in GMAC status registers. However, this
>> feature had to be disabled, in order not to conflict with SW PHY
>> management of the phylib.
>>
>> Stefan, is above correct?
>
> This sounds very much like mvneta's 'managed = "in-band"' mode.

Indeed. RGMII MAC behaves same way, although it shouldn't be named as
'in-band' to be on par with the specifications. Anyway - this one is
rather a stub for being able to work with ACPI, so once the MDIO bus
works there, this will be out of any concerns.

>
> Having done some research earlier this month on the "2.5G SGMII" I have
> a number of comments about this:
>
> 1. Beware of "SGMII" being used as a generic term for single lane serdes
>based ethernet. Marvell seem to use this for 802.3z BASE-X in their
>code, but it is not. SGMII is a modification of 802.3z BASE-X by
>Cisco.  This leads to some confusion!
>
> 2. For Cisco SGMII running at 2.5G, PHYs such as those from Xilinx do not
>support the speed bits, because the speed is defined to be 2.5G.  IOW,
>they do not support 250Mbps or 25Mbps speeds by data replication as is
>done with 100Mbps and 10Mbps over 1G SGMII.
>
> 3. There is also 1000BASE-X upclocked to 2.5G speeds, which mvneta and
>mvpp2 both support by appropriate configuration of the comphy.  I've
>already tested this with 4.3Mbps Fiberchannel SFPs between clearfog
>and mcbin - but needing devmem2 to reconfigure the clearfog comphy.

As for 3. I tested 2.5G link on Clearfog (FreeBSD) and Armada 8040
(UEFI), so yes - the comphy is a crucial component here.

>
>> > If my guessing is correct, I have to wonder why mvpp2 invented a
>> > different way to represent this from mvneta?  This makes it much more
>> > difficult to convert mvpp2 to phylink, and it also makes it difficult
>> > to add SFP support ignoring the phylink issue (since there is no phy
>> > handle there either.)
>>
>> Doesn't SFP require the fwnode handle to the sfp node? This is what I
>> understand at least from the phylink_register_sfp.
>
> Yes, internally within phylink.  What I'm concerned about is the
> following disparity between mvneta and mvpp2 - I'll try to explain it
> more clearly with DT examples:
>
> 1.1. mvneta phy
>  {
> phy = <>;
> phy-mode = "whatever";
> };
> 1.2. mvneta fixed-link
>  {
> fixed-link {
> speed = <1000>;
> full-duplex;
> };
> };
> 1.3. mvneta in-band
>  {
> phy-mode = "sgmii";
> managed = "in-band-status";
> };
> 2.1. mvpp2 phy
>  {
> phy = <>;
> phy-mode = "whatever";
> };
> 2.2. mvpp2 fixed-link
>  {
> fixed-link {
> speed = <1000>;
> full-duplex;
> };
> };
> 2.3. mvpp2 in-band (guess)
>  {
> phy-mode = "sgmii";
> };
>
> In both cases, the representation for phy and fixed-link mode are the
&

Re: [net-next: PATCH v2 5/5] net: mvpp2: enable ACPI support in the driver

2018-01-01 Thread Marcin Wojtas
HI Andrew,

2017-12-31 20:23 GMT+01:00 Andrew Lunn :
>> * Modify way of obtaining interrupts - with ACPI they are resources
>>   bound to struct platform_device and it's not possible to obtain
>>   them directly from the child node. Hence a formula is used, depending
>>   on the port_id and number of possible CPUs.
>
> Hi Marcin
>
> I know nothing about ACPI. Is this limitation with respect to
> interrupts fundamental to ACPI, or just that nobody has implemented
> flexible interrupt support yet?

I think it's a limitation, however it would be great, if some real
ACPI expert was able to give an opinion here. I'd really prefer to
declare IRQ's in the child nodes, but it seems not possible.

>
>> * Until proper MDIO bus and PHY handling with ACPI is established in the
>>   kernel, use only link interrupts feature in the driver.
>
> I think interrupts might be interesting with PHY devices, since they
> are child nodes of the MDIO device
>

Apart from the phylink's SFP support that may require in-band
management, it's an alternative to the normal PHY handling. Once MDIO
bus + PHYs are supported for ACPI, phylib support will be used instead
of the IRQs, so there should be no problem here.

Best regards,
Marcin


Re: [net-next: PATCH v2 4/5] net: mvpp2: use device_*/fwnode_* APIs instead of of_*

2018-01-01 Thread Marcin Wojtas
Hi Andrew,

2017-12-31 20:18 GMT+01:00 Andrew Lunn <and...@lunn.ch>:
> On Sun, Dec 31, 2017 at 12:58:39PM +0100, Marcin Wojtas wrote:
> Hi Marcin
>
>> Because there is no equivalent for for_each_available_child_of_node(),
>> use device_for_each_child_node() and check the port availability
>> inside the mvpp2_port_probe() routine.
>
> Could device_each_available_child_node() be added? I guess this will
> not be the last driver converted in this way, and having that macro
> will help with future ports.
>

Sure, I can add it in the next round.

Thanks,
Marcin


[net-next: PATCH v2 0/5] Armada 7k/8k PP2 ACPI support

2017-12-31 Thread Marcin Wojtas
Hi,

This a second version of a patchset, which introduces ACPI support
in mvpp2 driver. Comparing to the initial one, all patches
touching generic ACPI MDIO bus / PHY handling were removed
and after some modifications will be resend separately. They
may require a longer discussion in terms of phylink support
and ACPI specification extensions.

This way mvpp2 driver is able to operate using the link interrupt
capability (a.k.a. in-band management) on all ports, 1000BaseT RGMII
included. Driver operation was tested on top of the net-next branch
with both DT and ACPI on MacchiatoBin and Armada 7040 DB boards.

mvpp2 driver can work with the ACPI representation, as exposed
on a public branch:
https://github.com/MarvellEmbeddedProcessors/edk2-open-platform/commits/marvell-armada-wip
It was compiled together with the most recent Tianocore EDK2 revision.
Please refer to the firmware build instruction on MacchiatoBin board:
http://wiki.macchiatobin.net/tiki-index.php?page=Build+from+source+-+UEFI+EDK+II

ACPI representation of PP2 controllers (withouth PHY support) can
be viewed in the github:
* MacchiatoBin:
https://github.com/MarvellEmbeddedProcessors/edk2-open-platform/blob/marvell-armada-wip/Platforms/Marvell/Armada/AcpiTables/Armada80x0McBin/Dsdt.asl#L201

* Armada 7040 DB:
https://github.com/MarvellEmbeddedProcessors/edk2-open-platform/blob/marvell-armada-wip/Platforms/Marvell/Armada/AcpiTables/Armada70x0/Dsdt.asl#L131

I will appreciate any comments or remarks.

Best regards,
Marcin

Changelog:
v1 -> v2:
* Remove MDIO patches
* Use PP2 ports only with link interrupts
* Release second region resources in mvpp2 driver (code moved from
  mvmdio), as explained in details in 5/5 commit message.

Marcin Wojtas (5):
  device property: Introduce fwnode_get_mac_address()
  device property: Introduce fwnode_get_phy_mode()
  net: mvpp2: simplify maintaining enabled ports' list
  net: mvpp2: use device_*/fwnode_* APIs instead of of_*
  net: mvpp2: enable ACPI support in the driver

 drivers/base/property.c  |  52 +++--
 drivers/net/ethernet/marvell/mvpp2.c | 222 
 include/linux/property.h |   3 +
 3 files changed, 180 insertions(+), 97 deletions(-)

-- 
2.7.4



[net-next: PATCH v2 5/5] net: mvpp2: enable ACPI support in the driver

2017-12-31 Thread Marcin Wojtas
This patch introduces an alternative way of obtaining resources - via
ACPI tables provided by firmware. Enabling coexistence with the DT
support, in addition to the OF_*->device_*/fwnode_* API replacement,
required following steps to be taken:

* Add mvpp2_acpi_match table
* Omit clock configuration and obtain tclk from the property - in ACPI
  world, the firmware is responsible for clock maintenance.
* Disable comphy and syscon handling as they are not available for ACPI.
* Modify way of obtaining interrupts - with ACPI they are resources
  bound to struct platform_device and it's not possible to obtain
  them directly from the child node. Hence a formula is used, depending
  on the port_id and number of possible CPUs.
* Until proper MDIO bus and PHY handling with ACPI is established in the
  kernel, use only link interrupts feature in the driver.
* When booting with ACPI MVPP2_QDIST_MULTI_MODE is picked by
  default, as there is no need to keep any kind of the backward
  compatibility.

Moreover, a memory region used by mvmdio driver is usually placed in
the middle of the address space of the PP2 network controller.
The MDIO base address is obtained without requesting memory region
(by devm_ioremap() call) in mvmdio.c, later overlapping resources are
requested by the network driver, which is responsible for avoiding
a concurrent access.

In case the MDIO memory region is declared in the ACPI, it can
already appear as 'in-use' in the OS. Because it is overlapped by second
region of the network controller, make sure it is released, before
requesting it again. The care is taken by mvpp2 driver to avoid
concurrent access to this memory region.

Signed-off-by: Marcin Wojtas <m...@semihalf.com>
---
 drivers/net/ethernet/marvell/mvpp2.c | 147 ++--
 1 file changed, 103 insertions(+), 44 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvpp2.c 
b/drivers/net/ethernet/marvell/mvpp2.c
index 537474f..8b1c9a3 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -10,6 +10,7 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -7469,7 +7470,8 @@ static int mvpp2_simple_queue_vectors_init(struct 
mvpp2_port *port,
return 0;
 }
 
-static int mvpp2_multi_queue_vectors_init(struct mvpp2_port *port,
+static int mvpp2_multi_queue_vectors_init(struct platform_device *pdev,
+ struct mvpp2_port *port,
  struct device_node *port_node)
 {
struct mvpp2_queue_vector *v;
@@ -7502,7 +7504,11 @@ static int mvpp2_multi_queue_vectors_init(struct 
mvpp2_port *port,
strncpy(irqname, "rx-shared", sizeof(irqname));
}
 
-   v->irq = of_irq_get_byname(port_node, irqname);
+   if (port_node)
+   v->irq = of_irq_get_byname(port_node, irqname);
+   else
+   v->irq = platform_get_irq(pdev, port->id *
+ (port->nqvecs + 2) + i);
if (v->irq <= 0) {
ret = -EINVAL;
goto err;
@@ -7520,11 +7526,12 @@ static int mvpp2_multi_queue_vectors_init(struct 
mvpp2_port *port,
return ret;
 }
 
-static int mvpp2_queue_vectors_init(struct mvpp2_port *port,
+static int mvpp2_queue_vectors_init(struct platform_device *pdev,
+   struct mvpp2_port *port,
struct device_node *port_node)
 {
if (port->has_tx_irqs)
-   return mvpp2_multi_queue_vectors_init(port, port_node);
+   return mvpp2_multi_queue_vectors_init(pdev, port, port_node);
else
return mvpp2_simple_queue_vectors_init(port, port_node);
 }
@@ -7746,7 +7753,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
struct mvpp2 *priv)
 {
struct device_node *phy_node;
-   struct phy *comphy;
+   struct phy *comphy = NULL;
struct mvpp2_port *port;
struct mvpp2_port_pcpu *port_pcpu;
struct device_node *port_node = to_of_node(port_fwnode);
@@ -7764,7 +7771,12 @@ static int mvpp2_port_probe(struct platform_device *pdev,
if (!fwnode_device_is_available(port_fwnode))
return 0;
 
-   has_tx_irqs = mvpp2_port_has_tx_irqs(priv, port_node);
+   if (port_node) {
+   has_tx_irqs = mvpp2_port_has_tx_irqs(priv, port_node);
+   } else {
+   has_tx_irqs = true;
+   queue_mode = MVPP2_QDIST_MULTI_MODE;
+   }
 
if (!has_tx_irqs)
queue_mode = MVPP2_QDIST_SINGLE_MODE;
@@ -7779,7 +7791,11 @@ static int mvpp2_port_probe(struct platform_device *pdev,
if (!dev)
return -ENOMEM;
 
-   phy_node = of_parse_phandle(

[net-next: PATCH v2 3/5] net: mvpp2: simplify maintaining enabled ports' list

2017-12-31 Thread Marcin Wojtas
'port_count' field of the mvpp2 structure holds an overall amount
of available ports, based on DT nodes status. In order to be prepared
to support other HW description, obtain the value by incrementing it
upon each successful port initialization. This allowed for simplifying
port indexing in the controller's private array, whose size is now not
dynamically allocated, but fixed to MVPP2_MAX_PORTS.

This patch simplifies creating and filling list of enabled ports and
is a part of the preparation for adding ACPI support in the mvpp2 driver.

Signed-off-by: Marcin Wojtas <m...@semihalf.com>
---
 drivers/net/ethernet/marvell/mvpp2.c | 32 +++-
 1 file changed, 11 insertions(+), 21 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvpp2.c 
b/drivers/net/ethernet/marvell/mvpp2.c
index a197607..7f42d90 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -865,7 +865,7 @@ struct mvpp2 {
 
/* List of pointers to port structures */
int port_count;
-   struct mvpp2_port **port_list;
+   struct mvpp2_port *port_list[MVPP2_MAX_PORTS];
 
/* Aggregated TXQs */
struct mvpp2_tx_queue *aggr_txqs;
@@ -7741,7 +7741,7 @@ static void mvpp2_port_copy_mac_addr(struct net_device 
*dev, struct mvpp2 *priv,
 /* Ports initialization */
 static int mvpp2_port_probe(struct platform_device *pdev,
struct device_node *port_node,
-   struct mvpp2 *priv, int index)
+   struct mvpp2 *priv)
 {
struct device_node *phy_node;
struct phy *comphy;
@@ -7934,7 +7934,8 @@ static int mvpp2_port_probe(struct platform_device *pdev,
}
netdev_info(dev, "Using %s mac address %pM\n", mac_from, dev->dev_addr);
 
-   priv->port_list[index] = port;
+   priv->port_list[priv->port_count++] = port;
+
return 0;
 
 err_free_port_pcpu:
@@ -8313,28 +8314,17 @@ static int mvpp2_probe(struct platform_device *pdev)
goto err_mg_clk;
}
 
-   priv->port_count = of_get_available_child_count(dn);
-   if (priv->port_count == 0) {
-   dev_err(>dev, "no ports enabled\n");
-   err = -ENODEV;
-   goto err_mg_clk;
-   }
-
-   priv->port_list = devm_kcalloc(>dev, priv->port_count,
-  sizeof(*priv->port_list),
-  GFP_KERNEL);
-   if (!priv->port_list) {
-   err = -ENOMEM;
-   goto err_mg_clk;
-   }
-
/* Initialize ports */
-   i = 0;
for_each_available_child_of_node(dn, port_node) {
-   err = mvpp2_port_probe(pdev, port_node, priv, i);
+   err = mvpp2_port_probe(pdev, port_node, priv);
if (err < 0)
goto err_port_probe;
-   i++;
+   }
+
+   if (priv->port_count == 0) {
+   dev_err(>dev, "no ports enabled\n");
+   err = -ENODEV;
+   goto err_mg_clk;
}
 
/* Statistics must be gathered regularly because some of them (like
-- 
2.7.4



[net-next: PATCH v2 4/5] net: mvpp2: use device_*/fwnode_* APIs instead of of_*

2017-12-31 Thread Marcin Wojtas
OF functions can be used only for the driver using DT.
As a preparation for introducing ACPI support in mvpp2
driver, use struct fwnode_handle in order to obtain
properties from the hardware description.

Because there is no equivalent for for_each_available_child_of_node(),
use device_for_each_child_node() and check the port availability
inside the mvpp2_port_probe() routine.

This patch replaces of_* function with device_*/fwnode_*
where possible in the mvpp2.

Signed-off-by: Marcin Wojtas <m...@semihalf.com>
---
 drivers/net/ethernet/marvell/mvpp2.c | 47 +++-
 1 file changed, 26 insertions(+), 21 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvpp2.c 
b/drivers/net/ethernet/marvell/mvpp2.c
index 7f42d90..537474f 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -932,6 +932,9 @@ struct mvpp2_port {
 
struct mvpp2 *priv;
 
+   /* Firmware node associated to the port */
+   struct fwnode_handle *fwnode;
+
/* Per-port registers' base address */
void __iomem *base;
void __iomem *stats_base;
@@ -7711,17 +7714,16 @@ static bool mvpp2_port_has_tx_irqs(struct mvpp2 *priv,
 }
 
 static void mvpp2_port_copy_mac_addr(struct net_device *dev, struct mvpp2 
*priv,
-struct device_node *port_node,
+struct fwnode_handle *fwnode,
 char **mac_from)
 {
struct mvpp2_port *port = netdev_priv(dev);
char hw_mac_addr[ETH_ALEN] = {0};
-   const char *dt_mac_addr;
+   char fw_mac_addr[ETH_ALEN];
 
-   dt_mac_addr = of_get_mac_address(port_node);
-   if (dt_mac_addr && is_valid_ether_addr(dt_mac_addr)) {
-   *mac_from = "device tree";
-   ether_addr_copy(dev->dev_addr, dt_mac_addr);
+   if (fwnode_get_mac_address(fwnode, fw_mac_addr, ETH_ALEN)) {
+   *mac_from = "firmware node";
+   ether_addr_copy(dev->dev_addr, fw_mac_addr);
return;
}
 
@@ -7740,13 +7742,14 @@ static void mvpp2_port_copy_mac_addr(struct net_device 
*dev, struct mvpp2 *priv,
 
 /* Ports initialization */
 static int mvpp2_port_probe(struct platform_device *pdev,
-   struct device_node *port_node,
+   struct fwnode_handle *port_fwnode,
struct mvpp2 *priv)
 {
struct device_node *phy_node;
struct phy *comphy;
struct mvpp2_port *port;
struct mvpp2_port_pcpu *port_pcpu;
+   struct device_node *port_node = to_of_node(port_fwnode);
struct net_device *dev;
struct resource *res;
char *mac_from = "";
@@ -7757,6 +7760,10 @@ static int mvpp2_port_probe(struct platform_device *pdev,
int phy_mode;
int err, i, cpu;
 
+   /* Silently exit, if the port node turns out to be disabled. */
+   if (!fwnode_device_is_available(port_fwnode))
+   return 0;
+
has_tx_irqs = mvpp2_port_has_tx_irqs(priv, port_node);
 
if (!has_tx_irqs)
@@ -7773,7 +7780,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
return -ENOMEM;
 
phy_node = of_parse_phandle(port_node, "phy", 0);
-   phy_mode = of_get_phy_mode(port_node);
+   phy_mode = fwnode_get_phy_mode(port_fwnode);
if (phy_mode < 0) {
dev_err(>dev, "incorrect phy mode\n");
err = phy_mode;
@@ -7789,7 +7796,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
comphy = NULL;
}
 
-   if (of_property_read_u32(port_node, "port-id", )) {
+   if (fwnode_property_read_u32(port_fwnode, "port-id", )) {
err = -EINVAL;
dev_err(>dev, "missing port-id value\n");
goto err_free_netdev;
@@ -7820,7 +7827,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
/* the link irq is optional */
port->link_irq = 0;
 
-   if (of_property_read_bool(port_node, "marvell,loopback"))
+   if (fwnode_property_read_bool(port_fwnode, "marvell,loopback"))
port->flags |= MVPP2_F_LOOPBACK;
 
port->id = id;
@@ -7845,8 +7852,8 @@ static int mvpp2_port_probe(struct platform_device *pdev,
   MVPP21_MIB_COUNTERS_OFFSET +
   port->gop_id * MVPP21_MIB_COUNTERS_PORT_SZ;
} else {
-   if (of_property_read_u32(port_node, "gop-port-id",
->gop_id)) {
+   if (fwnode_property_read_u32(port_fwnode, "gop-port-id",
+>gop_id)) {
err = -EINVAL;
dev_err(>dev, "m

[net-next: PATCH v2 2/5] device property: Introduce fwnode_get_phy_mode()

2017-12-31 Thread Marcin Wojtas
Until now there were two almost identical functions for
obtaining network PHY mode - of_get_phy_mode() and,
more generic, device_get_phy_mode(). However it is not uncommon,
that the network interface is represented as a child
of the actual controller, hence it is not associated
directly to any struct device, required by the latter
routine.

This commit allows for getting the PHY mode for
children nodes in the ACPI world by introducing a new function -
fwnode_get_phy_mode(). This commit also changes
device_get_phy_mode() routine to be its wrapper, in order
to prevent unnecessary duplication.

Signed-off-by: Marcin Wojtas <m...@semihalf.com>
---
 drivers/base/property.c  | 24 
 include/linux/property.h |  1 +
 2 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/drivers/base/property.c b/drivers/base/property.c
index f261d1a..7c4a53d 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -1126,21 +1126,21 @@ enum dev_dma_attr device_get_dma_attr(struct device 
*dev)
 EXPORT_SYMBOL_GPL(device_get_dma_attr);
 
 /**
- * device_get_phy_mode - Get phy mode for given device
- * @dev:   Pointer to the given device
+ * fwnode_get_phy_mode - Get phy mode for given firmware node
+ * @fwnode:Pointer to the given node
  *
  * The function gets phy interface string from property 'phy-mode' or
  * 'phy-connection-type', and return its index in phy_modes table, or errno in
  * error case.
  */
-int device_get_phy_mode(struct device *dev)
+int fwnode_get_phy_mode(struct fwnode_handle *fwnode)
 {
const char *pm;
int err, i;
 
-   err = device_property_read_string(dev, "phy-mode", );
+   err = fwnode_property_read_string(fwnode, "phy-mode", );
if (err < 0)
-   err = device_property_read_string(dev,
+   err = fwnode_property_read_string(fwnode,
  "phy-connection-type", );
if (err < 0)
return err;
@@ -1151,6 +1151,20 @@ int device_get_phy_mode(struct device *dev)
 
return -ENODEV;
 }
+EXPORT_SYMBOL_GPL(fwnode_get_phy_mode);
+
+/**
+ * device_get_phy_mode - Get phy mode for given device
+ * @dev:   Pointer to the given device
+ *
+ * The function gets phy interface string from property 'phy-mode' or
+ * 'phy-connection-type', and return its index in phy_modes table, or errno in
+ * error case.
+ */
+int device_get_phy_mode(struct device *dev)
+{
+   return fwnode_get_phy_mode(dev_fwnode(dev));
+}
 EXPORT_SYMBOL_GPL(device_get_phy_mode);
 
 static void *fwnode_get_mac_addr(struct fwnode_handle *fwnode,
diff --git a/include/linux/property.h b/include/linux/property.h
index 35620e0..9b13332 100644
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -279,6 +279,7 @@ int device_get_phy_mode(struct device *dev);
 
 void *device_get_mac_address(struct device *dev, char *addr, int alen);
 
+int fwnode_get_phy_mode(struct fwnode_handle *fwnode);
 void *fwnode_get_mac_address(struct fwnode_handle *fwnode,
 char *addr, int alen);
 struct fwnode_handle *fwnode_graph_get_next_endpoint(
-- 
2.7.4



[net-next: PATCH v2 1/5] device property: Introduce fwnode_get_mac_address()

2017-12-31 Thread Marcin Wojtas
Until now there were two almost identical functions for
obtaining MAC address - of_get_mac_address() and, more generic,
device_get_mac_address(). However it is not uncommon,
that the network interface is represented as a child
of the actual controller, hence it is not associated
directly to any struct device, required by the latter
routine.

This commit allows for getting the MAC address for
children nodes in the ACPI world by introducing a new function -
fwnode_get_mac_address(). This commit also changes
device_get_mac_address() routine to be its wrapper, in order
to prevent unnecessary duplication.

Signed-off-by: Marcin Wojtas <m...@semihalf.com>
---
 drivers/base/property.c  | 28 ++--
 include/linux/property.h |  2 ++
 2 files changed, 22 insertions(+), 8 deletions(-)

diff --git a/drivers/base/property.c b/drivers/base/property.c
index 851b1b6..f261d1a 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -1153,11 +1153,11 @@ int device_get_phy_mode(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(device_get_phy_mode);
 
-static void *device_get_mac_addr(struct device *dev,
+static void *fwnode_get_mac_addr(struct fwnode_handle *fwnode,
 const char *name, char *addr,
 int alen)
 {
-   int ret = device_property_read_u8_array(dev, name, addr, alen);
+   int ret = fwnode_property_read_u8_array(fwnode, name, addr, alen);
 
if (ret == 0 && alen == ETH_ALEN && is_valid_ether_addr(addr))
return addr;
@@ -1165,8 +1165,8 @@ static void *device_get_mac_addr(struct device *dev,
 }
 
 /**
- * device_get_mac_address - Get the MAC for a given device
- * @dev:   Pointer to the device
+ * fwnode_get_mac_address - Get the MAC from the firmware node
+ * @fwnode:Pointer to the firmware node
  * @addr:  Address of buffer to store the MAC in
  * @alen:  Length of the buffer pointed to by addr, should be ETH_ALEN
  *
@@ -1187,19 +1187,31 @@ static void *device_get_mac_addr(struct device *dev,
  * In this case, the real MAC is in 'local-mac-address', and 'mac-address'
  * exists but is all zeros.
 */
-void *device_get_mac_address(struct device *dev, char *addr, int alen)
+void *fwnode_get_mac_address(struct fwnode_handle *fwnode, char *addr, int 
alen)
 {
char *res;
 
-   res = device_get_mac_addr(dev, "mac-address", addr, alen);
+   res = fwnode_get_mac_addr(fwnode, "mac-address", addr, alen);
if (res)
return res;
 
-   res = device_get_mac_addr(dev, "local-mac-address", addr, alen);
+   res = fwnode_get_mac_addr(fwnode, "local-mac-address", addr, alen);
if (res)
return res;
 
-   return device_get_mac_addr(dev, "address", addr, alen);
+   return fwnode_get_mac_addr(fwnode, "address", addr, alen);
+}
+EXPORT_SYMBOL(fwnode_get_mac_address);
+
+/**
+ * device_get_mac_address - Get the MAC for a given device
+ * @dev:   Pointer to the device
+ * @addr:  Address of buffer to store the MAC in
+ * @alen:  Length of the buffer pointed to by addr, should be ETH_ALEN
+ */
+void *device_get_mac_address(struct device *dev, char *addr, int alen)
+{
+   return fwnode_get_mac_address(dev_fwnode(dev), addr, alen);
 }
 EXPORT_SYMBOL(device_get_mac_address);
 
diff --git a/include/linux/property.h b/include/linux/property.h
index f6189a3..35620e0 100644
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -279,6 +279,8 @@ int device_get_phy_mode(struct device *dev);
 
 void *device_get_mac_address(struct device *dev, char *addr, int alen);
 
+void *fwnode_get_mac_address(struct fwnode_handle *fwnode,
+char *addr, int alen);
 struct fwnode_handle *fwnode_graph_get_next_endpoint(
const struct fwnode_handle *fwnode, struct fwnode_handle *prev);
 struct fwnode_handle *
-- 
2.7.4



Re: [PATCH net-next 5/6] arm64: dts: marvell: mcbin: enable the fourth network interface

2017-12-30 Thread Marcin Wojtas
Hi Russell and Stefan,

2017-12-29 12:38 GMT+01:00 Russell King - ARM Linux <li...@armlinux.org.uk>:
> On Fri, Dec 29, 2017 at 12:12:15PM +0100, Marcin Wojtas wrote:
>> Hi Russell,
>>
>> I see that I misspelled your email address, hence the series remained 
>> unnoticed:
>> https://lkml.org/lkml/2017/12/18/216
>>
>> In terms of the phylink support, I think the most important are:
>> * 3/8
>> https://lkml.org/lkml/2017/12/18/211
>> * 7/8
>> https://lkml.org/lkml/2017/12/18/207
>>
>> I think the way of obtaining PHY fwnode and connecting it from the
>> latter patch could be incorporated to the phylink code. Although I
>> didn't get much feedback, the whole ACPI-handling of MDIO bus and the
>> PHYs touch ACPI specification and I expect it a slower to get merged.
>> Hence my idea is following:
>> * Send v2 with ACPI supporting link-irq only in mvpp2.c
>> * Extract MDIO bus handling for ACPI and propose PHY handling
>> modifications in phylink.
>>
>> This way we may push the two things forwards in more efficient way.
>> I'm looking forward to your opinion.
>
> Agreed - as we have very few users of phylink at the moment (they're
> mostly all in external trees) we can easily change the phylink
> interfaces.  The first step is solving the ACPI representation of the
> MDIO bus and attached devices, and until that is settled, not much can
> be done.
>
> However, it seems to me that the issues of adding ACPI to mvpp2 vs
> adding phylink to mvpp2 are two entirely separate problems that don't
> really conflict with each other - since the "phy" problem afflicts
> both.
>

Yes, I already split the series and will send first one right away. I
will be followed by MDIO bus / PHY handling proposal, including the
bits related to phylink. I'm looking forward to your opinion on that
once sent.

> However, I'm not sure what this "link-irq" thing is that you talk
> about (and I suspect it's one of the things that I've been trying for
> months to find out about from Antoine when he says that there's stuff
> that mvpp2 supports that phylink doesn't.)  So, I'm left to guess, and
> I guess it's the mvpp2-variant of mvneta's in-band autonegotiation.
> Continuing to guess from the mvpp2 phylink conversion patch, this mvpp2
> variant is selected by not providing a phy handle in DT, whereas
> mvneta's variant is selected using the ethernet-standard property
> 'managed = "in-band-status"'.

This my understanding of how the PP2 HW works in terms of signalling
the link interrupt:

The full in-band management, similar to mvneta is supported only in
the SGMII mode (1G, not sure how it looks like in 2.5G mode). Such
handling is not yet implemented in the mvpp2.c

10G:
The XGMII MAC (XLG) is capable of generating link status change
interrupt upon information provided from the reconciliation layer (RS)
of the interface.

2.5G/1G SGMII:
Apart from the in-band management, the MAC is also capable of
generating IRQ during link-status change.

1G RGMII:
I was a bit surprised, but checked on my own - the link change IRQ can
be generated here as well.

In addition to above the clause 22 PHYs can be automatically polled
via SMI bus and provide complete information about link status, speed,
etc., reflecting it directly in GMAC status registers. However, this
feature had to be disabled, in order not to conflict with SW PHY
management of the phylib.

Stefan, is above correct?

>
> If my guessing is correct, I have to wonder why mvpp2 invented a
> different way to represent this from mvneta?  This makes it much more
> difficult to convert mvpp2 to phylink, and it also makes it difficult
> to add SFP support ignoring the phylink issue (since there is no phy
> handle there either.)

Doesn't SFP require the fwnode handle to the sfp node? This is what I
understand at least from the phylink_register_sfp.

Anyway, once the phylink is introduced in mvpp2.c, its presence will
simply be detected by port->phylink pointer. In such case the link IRQ
will no be used. In longer perspective, link IRQ should be used only
by ACPI and once MDIO bus is supported in generic way in this world,
it could remain as the 'last resort' option.

Best regards,
Marcin


Re: [PATCH net-next 5/6] arm64: dts: marvell: mcbin: enable the fourth network interface

2017-12-29 Thread Marcin Wojtas
Hi Russell,

2017-12-28 19:46 GMT+01:00 Russell King - ARM Linux :
> On Thu, Dec 28, 2017 at 07:27:39PM +0100, Antoine Tenart wrote:
>> Hi Florian,
>>
>> On Thu, Dec 28, 2017 at 07:02:09AM -0800, Florian Fainelli wrote:
>> > On 12/28/2017 02:05 AM, Antoine Tenart wrote:
>> > > On Thu, Dec 28, 2017 at 08:46:23AM +0100, Andrew Lunn wrote:
>> > >> On Wed, Dec 27, 2017 at 10:24:01PM +, Russell King - ARM Linux 
>> > >> wrote:
>> > >>> On Wed, Dec 27, 2017 at 11:14:45PM +0100, Antoine Tenart wrote:
>> > 
>> >  +_eth2 {
>> >  +  /* CPS Lane 5 */
>> >  +  status = "okay";
>> >  +  phy-mode = "2500base-x";
>> >  +  /* Generic PHY, providing serdes lanes */
>> >  +  phys = <_comphy5 2>;
>> >  +};
>> >  +
>> > >>>
>> > >>> This is wrong.  This lane is connected to a SFP cage which can support
>> > >>> more than just 2500base-X.  Tying it in this way to 2500base-X means
>> > >>> that this port does not support conenctions at 1000base-X, despite
>> > >>> that's one of the most popular and more standardised speeds.
>> > >>>
>> > >>
>> > >> I agree with Russell here. SFP modules are hot pluggable, and support
>> > >> a range of interface modes. You need to query what the SFP module is
>> > >> in order to know how to configure the SERDES interface. The phylink
>> > >> infrastructure does that for you.
>> > >
>> > > Sure, I understand. We'll be able to support such interfaces only when
>> > > the phylink PPv2 support lands in.
>> >
>> > Should we expect PHYLINK support to make it as the first patch in your
>> > v2 of this patch series, or is someone else doing that?
>>
>> No, the phylink patch conflicts with Marcin's ACPI series and we agreed
>> to let him get his series merged first. And I will probably work on a
>> few other topics before having the chance to work on it. So it'll
>> probably be me doing that, but not right now.
>
> ACPI is going to be a problem with phylink for a while.  There's patches
> queued in net-next which convert phylink and SFP mostly to the fwnode
> and property based systems, but phylib and i2c do not seem to have the
> necessary bits to be able to deal with those.
>
> Specifically, in DT we have "of_find_i2c_adapter_by_node()" but afaics
> there is no equivalent in ACPI - which means in an ACPI based system
> we have no way to determine the I2C bus associated with a SFP socket,
> which is a rather fundamental issue for SFP modules.
>
> For phylib side, there's "of_phy_attach()" but again there is no
> equivalent in ACPI. This should not be that much of a problem, because
> network drivers using the DT phylib calls (eg, "of_phy_connect()") are
> already restricted by this. That may have been solved by Marcin's
> series, but I've not seen it to know.
>

I see that I misspelled your email address, hence the series remained unnoticed:
https://lkml.org/lkml/2017/12/18/216

In terms of the phylink support, I think the most important are:
* 3/8
https://lkml.org/lkml/2017/12/18/211
* 7/8
https://lkml.org/lkml/2017/12/18/207

I think the way of obtaining PHY fwnode and connecting it from the
latter patch could be incorporated to the phylink code. Although I
didn't get much feedback, the whole ACPI-handling of MDIO bus and the
PHYs touch ACPI specification and I expect it a slower to get merged.
Hence my idea is following:
* Send v2 with ACPI supporting link-irq only in mvpp2.c
* Extract MDIO bus handling for ACPI and propose PHY handling
modifications in phylink.

This way we may push the two things forwards in more efficient way.
I'm looking forward to your opinion.

Best regards,
Marcin


Re: [net-next: PATCH 0/8] Armada 7k/8k PP2 ACPI support

2017-12-19 Thread Marcin Wojtas
Hi Andrew,

2017-12-19 21:46 GMT+01:00 Andrew Lunn :
>> Of course! v2 will not have such problem, I've been waiting however
>> for the feedback about the ACPI representation. Anyway, I'm strongly
>> leaning towards using _ADR/_CID objects in PHY's nodes for ACPI, so
>> maybe I'll just issue the v2 in order to push the discussion a bit
>> forward.
>
> Hi Marcin
>
> I know ~0 about ACPI. But what seems to be missing for me is
> documentation. You are defining a ABI here, which all future MDIO
> busses, PHYs, and to some extent Ethernet switches need to follow. So
> i would expect this to be documented somewhere.

As the code derives straight from of_mdio.c, there is absolutely no
deviation from Documentation/devicetree/bindings/net/mdio.txt.

>
> How does documentation work in the ACPI world?
>

ACPI has its own specification, the newest one is 6.2
http://www.uefi.org/sites/default/files/resources/ACPI_6_2.pdf

It is pretty likely, that if we establish a generic solution for the
MDIO bus, a short section about it may probably require adding to
above - for now I see none.

Best regards,
Marcin


Re: [net-next: PATCH 0/8] Armada 7k/8k PP2 ACPI support

2017-12-19 Thread Marcin Wojtas
Hi David,

2017-12-19 19:48 GMT+01:00 David Miller <da...@davemloft.net>:
> From: Marcin Wojtas <m...@semihalf.com>
> Date: Mon, 18 Dec 2017 10:17:56 +0100
>
>> Above support configures 1G to use its PHY normally. 10G can work now
>> only with the link interrupt mode. Somehow reading of the
>> string property in fwnode_mdiobus_child_is_phy works only with
>> DT and cannot cope with 10G PHY nodes as in:
>> https://pastebin.com/3JnYpU0A
>>
>> Above root cause will be further checked. In the meantime I will
>> appreciate any comments or remarks for the kernel patches.
>
> I would like you to figure this out before these changes go in.
>

Of course! v2 will not have such problem, I've been waiting however
for the feedback about the ACPI representation. Anyway, I'm strongly
leaning towards using _ADR/_CID objects in PHY's nodes for ACPI, so
maybe I'll just issue the v2 in order to push the discussion a bit
forward.

Thanks,
Marcin


Re: [net-next: PATCH 0/8] Armada 7k/8k PP2 ACPI support

2017-12-18 Thread Marcin Wojtas
Hi Ard

2017-12-18 10:40 GMT+01:00 Ard Biesheuvel <ard.biesheu...@linaro.org>:
> On 18 December 2017 at 10:17, Marcin Wojtas <m...@semihalf.com> wrote:
>> Hi,
>>
>> This patchset introduces ACPI support in mvpp2 and mvmdio drivers.
>> First three patches introduce fwnode helpers for obtaining PHY
>> information from nodes and also MDIO fwnode API for registering
>> the bus with its PHY/devices.
>>
>> Following patches update code of the mvmdio and mvpp2 drivers
>> to support ACPI tables handling. The latter is done in 4 steps,
>> as can be seen in the commits. For the details, please
>> refer to the commit messages.
>>
>> Drivers operation was tested on top of the net-next branch
>> with both DT and ACPI. Although for compatibility reasons
>> with older platforms, the mvmdio driver keeps using
>> of_ MDIO registering, new fwnode_ one proved to fully work
>> with DT as well (tested on MacchiatoBin board).
>>
>> mvpp2/mvmdio driver can work with the ACPI representation, as exposed
>> on a public branch:
>> https://github.com/MarvellEmbeddedProcessors/edk2-open-platform/commits/marvell-armada-wip
>> It was compiled together with the most recent Tianocore EDK2 revision.
>> Please refer to the firmware build instruction on MacchiatoBin board:
>> http://wiki.macchiatobin.net/tiki-index.php?page=Build+from+source+-+UEFI+EDK+II
>>
>> Above support configures 1G to use its PHY normally. 10G can work now
>> only with the link interrupt mode. Somehow reading of the
>> string property in fwnode_mdiobus_child_is_phy works only with
>> DT and cannot cope with 10G PHY nodes as in:
>> https://pastebin.com/3JnYpU0A
>>
>> Above root cause will be further checked. In the meantime I will
>> appreciate any comments or remarks for the kernel patches.
>>
>
> Hi Marcin,
>
> I have added linux-acpi and Graeme to cc. I think it makes sense to
> discuss the way you describe the device topology before looking at the
> patches in more detail.
>

Thanks. Tomasz Nowicki immediately pointed this to me off the lists.

> In particular, I would like to request feedback on the use of
> [redundant] 'reg' properties and the use of _DSD + compatible to
> describe PHYs. Usually, we try to avoid this, given that it is
> essentially a ACPI encapsulated DT dialect that is difficult to
> support in drivers unless they are based on DT to begin with. Also,
> non-standard _DSD properties require a vendor prefix, it is not
> freeform.
>

Already a lot of drivers use both DT + ACPI. Some have IMO very
fanciful bindings in both, mostly handled within the drivers with
custom functions. OF_ - only drivers can use of_mdio_ helper routines,
that assume a certain hierarchy:
MDIO device node with PHYs as children, which are referenced in the
ports node. I believe such approach could fit ACPI description too.
I'm aware however that my code is pretty much DT transposed into ACPI
environment and I'm of course open to discussion, how to do it in the
most proper way.

My main goal is to provide an fwnode-based glue code, that can be used
among the NIC/MDIO drivers  (+ phylink) without multiple ifs
differentiating between ACPI/OF. What I sent has single calls in
mvpp2/mvmdio with a common bottom layers, but I don't see a problem,
that, e.g. when iterating over PHY subnodes, in case of OF
'reg'/'compatible' are used, whereas with ACPI some specific _ADR/_CID
objects.

I'd appreaciate any feedback.

Best regards,
Marcin

> For reference, the ACPI description is here (starting at line 175)
> https://github.com/MarvellEmbeddedProcessors/edk2-open-platform/blob/72d5ac23b20dd74d479daa5e40ba443264b31261/Platforms/Marvell/Armada/AcpiTables/Armada80x0McBin/Dsdt.asl


[net-next: PATCH 0/8] Armada 7k/8k PP2 ACPI support

2017-12-18 Thread Marcin Wojtas
Hi,

This patchset introduces ACPI support in mvpp2 and mvmdio drivers.
First three patches introduce fwnode helpers for obtaining PHY
information from nodes and also MDIO fwnode API for registering
the bus with its PHY/devices.

Following patches update code of the mvmdio and mvpp2 drivers
to support ACPI tables handling. The latter is done in 4 steps,
as can be seen in the commits. For the details, please
refer to the commit messages.

Drivers operation was tested on top of the net-next branch
with both DT and ACPI. Although for compatibility reasons
with older platforms, the mvmdio driver keeps using
of_ MDIO registering, new fwnode_ one proved to fully work
with DT as well (tested on MacchiatoBin board).

mvpp2/mvmdio driver can work with the ACPI representation, as exposed
on a public branch:
https://github.com/MarvellEmbeddedProcessors/edk2-open-platform/commits/marvell-armada-wip
It was compiled together with the most recent Tianocore EDK2 revision.
Please refer to the firmware build instruction on MacchiatoBin board:
http://wiki.macchiatobin.net/tiki-index.php?page=Build+from+source+-+UEFI+EDK+II

Above support configures 1G to use its PHY normally. 10G can work now
only with the link interrupt mode. Somehow reading of the
string property in fwnode_mdiobus_child_is_phy works only with
DT and cannot cope with 10G PHY nodes as in:
https://pastebin.com/3JnYpU0A

Above root cause will be further checked. In the meantime I will
appreciate any comments or remarks for the kernel patches.

Best regards,
Marcin

Marcin Wojtas (8):
  device property: Introduce fwnode_get_mac_address()
  device property: Introduce fwnode_get_phy_mode()
  mdio_bus: Introduce fwnode MDIO helpers
  net: mvmdio: add ACPI support
  net: mvpp2: simplify maintaining enabled ports' list
  net: mvpp2: use device_*/fwnode_* APIs instead of of_*
  net: mvpp2: handle PHY with its fwnode
  net: mvpp2: enable ACPI support in the driver

 drivers/base/property.c   |  52 +++--
 drivers/net/ethernet/marvell/mvmdio.c |  42 +++-
 drivers/net/ethernet/marvell/mvpp2.c  | 246 
 drivers/net/phy/mdio_bus.c| 218 +
 include/linux/mdio.h  |   3 +
 include/linux/property.h  |   3 +
 6 files changed, 454 insertions(+), 110 deletions(-)

-- 
2.7.4



[net-next: PATCH 1/8] device property: Introduce fwnode_get_mac_address()

2017-12-18 Thread Marcin Wojtas
Until now there were two almost identical functions for
obtaining MAC address - of_get_mac_address() and, more generic,
device_get_mac_address(). However it is not uncommon,
that the network interface is represented as a child
of the actual controller, hence it is not associated
directly to any struct device, required by the latter
routine.

This commit allows for getting the MAC address for
children nodes in the ACPI world by introducing a new function -
fwnode_get_mac_address(). This commit also changes
device_get_mac_address() routine to be its wrapper, in order
to prevent unnecessary duplication.

Signed-off-by: Marcin Wojtas <m...@semihalf.com>
---
 drivers/base/property.c  | 28 ++--
 include/linux/property.h |  2 ++
 2 files changed, 22 insertions(+), 8 deletions(-)

diff --git a/drivers/base/property.c b/drivers/base/property.c
index 851b1b6..f261d1a 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -1153,11 +1153,11 @@ int device_get_phy_mode(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(device_get_phy_mode);
 
-static void *device_get_mac_addr(struct device *dev,
+static void *fwnode_get_mac_addr(struct fwnode_handle *fwnode,
 const char *name, char *addr,
 int alen)
 {
-   int ret = device_property_read_u8_array(dev, name, addr, alen);
+   int ret = fwnode_property_read_u8_array(fwnode, name, addr, alen);
 
if (ret == 0 && alen == ETH_ALEN && is_valid_ether_addr(addr))
return addr;
@@ -1165,8 +1165,8 @@ static void *device_get_mac_addr(struct device *dev,
 }
 
 /**
- * device_get_mac_address - Get the MAC for a given device
- * @dev:   Pointer to the device
+ * fwnode_get_mac_address - Get the MAC from the firmware node
+ * @fwnode:Pointer to the firmware node
  * @addr:  Address of buffer to store the MAC in
  * @alen:  Length of the buffer pointed to by addr, should be ETH_ALEN
  *
@@ -1187,19 +1187,31 @@ static void *device_get_mac_addr(struct device *dev,
  * In this case, the real MAC is in 'local-mac-address', and 'mac-address'
  * exists but is all zeros.
 */
-void *device_get_mac_address(struct device *dev, char *addr, int alen)
+void *fwnode_get_mac_address(struct fwnode_handle *fwnode, char *addr, int 
alen)
 {
char *res;
 
-   res = device_get_mac_addr(dev, "mac-address", addr, alen);
+   res = fwnode_get_mac_addr(fwnode, "mac-address", addr, alen);
if (res)
return res;
 
-   res = device_get_mac_addr(dev, "local-mac-address", addr, alen);
+   res = fwnode_get_mac_addr(fwnode, "local-mac-address", addr, alen);
if (res)
return res;
 
-   return device_get_mac_addr(dev, "address", addr, alen);
+   return fwnode_get_mac_addr(fwnode, "address", addr, alen);
+}
+EXPORT_SYMBOL(fwnode_get_mac_address);
+
+/**
+ * device_get_mac_address - Get the MAC for a given device
+ * @dev:   Pointer to the device
+ * @addr:  Address of buffer to store the MAC in
+ * @alen:  Length of the buffer pointed to by addr, should be ETH_ALEN
+ */
+void *device_get_mac_address(struct device *dev, char *addr, int alen)
+{
+   return fwnode_get_mac_address(dev_fwnode(dev), addr, alen);
 }
 EXPORT_SYMBOL(device_get_mac_address);
 
diff --git a/include/linux/property.h b/include/linux/property.h
index f6189a3..35620e0 100644
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -279,6 +279,8 @@ int device_get_phy_mode(struct device *dev);
 
 void *device_get_mac_address(struct device *dev, char *addr, int alen);
 
+void *fwnode_get_mac_address(struct fwnode_handle *fwnode,
+char *addr, int alen);
 struct fwnode_handle *fwnode_graph_get_next_endpoint(
const struct fwnode_handle *fwnode, struct fwnode_handle *prev);
 struct fwnode_handle *
-- 
2.7.4



[net-next: PATCH 2/8] device property: Introduce fwnode_get_phy_mode()

2017-12-18 Thread Marcin Wojtas
Until now there were two almost identical functions for
obtaining network PHY mode - of_get_phy_mode() and,
more generic, device_get_phy_mode(). However it is not uncommon,
that the network interface is represented as a child
of the actual controller, hence it is not associated
directly to any struct device, required by the latter
routine.

This commit allows for getting the PHY mode for
children nodes in the ACPI world by introducing a new function -
fwnode_get_phy_mode(). This commit also changes
device_get_phy_mode() routine to be its wrapper, in order
to prevent unnecessary duplication.

Signed-off-by: Marcin Wojtas <m...@semihalf.com>
---
 drivers/base/property.c  | 24 
 include/linux/property.h |  1 +
 2 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/drivers/base/property.c b/drivers/base/property.c
index f261d1a..7c4a53d 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -1126,21 +1126,21 @@ enum dev_dma_attr device_get_dma_attr(struct device 
*dev)
 EXPORT_SYMBOL_GPL(device_get_dma_attr);
 
 /**
- * device_get_phy_mode - Get phy mode for given device
- * @dev:   Pointer to the given device
+ * fwnode_get_phy_mode - Get phy mode for given firmware node
+ * @fwnode:Pointer to the given node
  *
  * The function gets phy interface string from property 'phy-mode' or
  * 'phy-connection-type', and return its index in phy_modes table, or errno in
  * error case.
  */
-int device_get_phy_mode(struct device *dev)
+int fwnode_get_phy_mode(struct fwnode_handle *fwnode)
 {
const char *pm;
int err, i;
 
-   err = device_property_read_string(dev, "phy-mode", );
+   err = fwnode_property_read_string(fwnode, "phy-mode", );
if (err < 0)
-   err = device_property_read_string(dev,
+   err = fwnode_property_read_string(fwnode,
  "phy-connection-type", );
if (err < 0)
return err;
@@ -1151,6 +1151,20 @@ int device_get_phy_mode(struct device *dev)
 
return -ENODEV;
 }
+EXPORT_SYMBOL_GPL(fwnode_get_phy_mode);
+
+/**
+ * device_get_phy_mode - Get phy mode for given device
+ * @dev:   Pointer to the given device
+ *
+ * The function gets phy interface string from property 'phy-mode' or
+ * 'phy-connection-type', and return its index in phy_modes table, or errno in
+ * error case.
+ */
+int device_get_phy_mode(struct device *dev)
+{
+   return fwnode_get_phy_mode(dev_fwnode(dev));
+}
 EXPORT_SYMBOL_GPL(device_get_phy_mode);
 
 static void *fwnode_get_mac_addr(struct fwnode_handle *fwnode,
diff --git a/include/linux/property.h b/include/linux/property.h
index 35620e0..9b13332 100644
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -279,6 +279,7 @@ int device_get_phy_mode(struct device *dev);
 
 void *device_get_mac_address(struct device *dev, char *addr, int alen);
 
+int fwnode_get_phy_mode(struct fwnode_handle *fwnode);
 void *fwnode_get_mac_address(struct fwnode_handle *fwnode,
 char *addr, int alen);
 struct fwnode_handle *fwnode_graph_get_next_endpoint(
-- 
2.7.4



[net-next: PATCH 3/8] mdio_bus: Introduce fwnode MDIO helpers

2017-12-18 Thread Marcin Wojtas
This patch introduces fwnode helper for registering MDIO
bus, as well as one for finding the PHY, basing on its
firmware node pointer. Comparing to existing OF equivalent,
fwnode_mdiobus_register() does not support:
 * deprecated bindings (device whitelist, nor the PHY ID embedded
   in the compatible string)
 * MDIO bus auto scanning

Signed-off-by: Marcin Wojtas <m...@semihalf.com>
---
 drivers/net/phy/mdio_bus.c | 218 
 include/linux/mdio.h   |   3 +
 2 files changed, 221 insertions(+)

diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index a0f34c3..f2b2a94 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -27,6 +27,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -662,6 +663,223 @@ static int mdio_uevent(struct device *dev, struct 
kobj_uevent_env *env)
return 0;
 }
 
+static int fwnode_mdiobus_register_phy(struct mii_bus *bus,
+  struct fwnode_handle *child, u32 addr)
+{
+   struct phy_device *phy;
+   bool is_c45 = false;
+   int rc;
+
+   rc = fwnode_property_match_string(child, "compatible",
+ "ethernet-phy-ieee802.3-c45");
+   if (!rc)
+   is_c45 = true;
+
+   phy = get_phy_device(bus, addr, is_c45);
+   if (IS_ERR(phy))
+   return PTR_ERR(phy);
+
+   phy->irq = bus->irq[addr];
+
+   if (to_of_node(child)) {
+   rc = of_irq_get(to_of_node(child), 0);
+   if (rc == -EPROBE_DEFER) {
+   phy_device_free(phy);
+   return rc;
+   } else if (rc > 0) {
+   phy->irq = rc;
+   bus->irq[addr] = rc;
+   }
+   }
+
+   if (fwnode_property_read_bool(child, "broken-turn-around"))
+   bus->phy_ignore_ta_mask |= 1 << addr;
+
+   /* Associate the fwnode with the device structure so it
+* can be looked up later.
+*/
+   phy->mdio.dev.fwnode = child;
+
+   /* All data is now stored in the phy struct, so register it */
+   rc = phy_device_register(phy);
+   if (rc) {
+   phy_device_free(phy);
+   fwnode_handle_put(child);
+   return rc;
+   }
+
+   dev_dbg(>dev, "registered phy at address %i\n", addr);
+
+   return 0;
+}
+
+static int fwnode_mdiobus_register_device(struct mii_bus *bus,
+ struct fwnode_handle *child, u32 addr)
+{
+   struct mdio_device *mdiodev;
+   int rc;
+
+   mdiodev = mdio_device_create(bus, addr);
+   if (IS_ERR(mdiodev))
+   return PTR_ERR(mdiodev);
+
+   /* Associate the fwnode with the device structure so it
+* can be looked up later.
+*/
+   mdiodev->dev.fwnode = child;
+
+   /* All data is now stored in the mdiodev struct; register it. */
+   rc = mdio_device_register(mdiodev);
+   if (rc) {
+   mdio_device_free(mdiodev);
+   fwnode_handle_put(child);
+   return rc;
+   }
+
+   dev_dbg(>dev, "registered mdio device at address %i\n", addr);
+
+   return 0;
+}
+
+static int fwnode_mdio_parse_addr(struct device *dev,
+ const struct fwnode_handle *fwnode)
+{
+   u32 addr;
+   int ret;
+
+   ret = fwnode_property_read_u32(fwnode, "reg", );
+   if (ret < 0) {
+   dev_err(dev, "PHY node has no 'reg' property\n");
+   return ret;
+   }
+
+   /* A PHY must have a reg property in the range [0-31] */
+   if (addr < 0 || addr >= PHY_MAX_ADDR) {
+   dev_err(dev, "PHY address %i is invalid\n", addr);
+   return -EINVAL;
+   }
+
+   return addr;
+}
+
+/**
+ * fwnode_mdiobus_child_is_phy - Return true if the child is a PHY node.
+ * It must either:
+ * o Compatible string of "ethernet-phy-ieee802.3-c45"
+ * o Compatible string of "ethernet-phy-ieee802.3-c22"
+ * Checking "compatible" property is done, in order to follow the DT binding.
+ */
+static bool fwnode_mdiobus_child_is_phy(struct fwnode_handle *child)
+{
+   int ret;
+
+   ret = fwnode_property_match_string(child, "compatible",
+  "ethernet-phy-ieee802.3-c45");
+   if (!ret)
+   return true;
+
+   ret = fwnode_property_match_string(child, "compatible",
+  "ethernet-phy-ieee802.3-c22");
+   if (!ret)
+   return true;
+
+   if (!fwnode_property_present(child, "compatible"))
+   return true;
+
+   return false;
+}
+
+/**
+ * fwnode_mdiobus_register - Register

[net-next: PATCH 5/8] net: mvpp2: simplify maintaining enabled ports' list

2017-12-18 Thread Marcin Wojtas
'port_count' field of the mvpp2 structure holds an overall amount
of available ports, based on DT nodes status. In order to be prepared
to support other HW description, obtain the value by incrementing it
upon each successful port initialization. This allowed for simplifying
port indexing in the controller's private array, whose size is now not
dynamically allocated, but fixed to MVPP2_MAX_PORTS.

This patch simplifies creating and filling list of enabled ports and
is a part of the preparation for adding ACPI support in the mvpp2 driver.

Signed-off-by: Marcin Wojtas <m...@semihalf.com>
---
 drivers/net/ethernet/marvell/mvpp2.c | 32 +++-
 1 file changed, 11 insertions(+), 21 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvpp2.c 
b/drivers/net/ethernet/marvell/mvpp2.c
index a197607..7f42d90 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -865,7 +865,7 @@ struct mvpp2 {
 
/* List of pointers to port structures */
int port_count;
-   struct mvpp2_port **port_list;
+   struct mvpp2_port *port_list[MVPP2_MAX_PORTS];
 
/* Aggregated TXQs */
struct mvpp2_tx_queue *aggr_txqs;
@@ -7741,7 +7741,7 @@ static void mvpp2_port_copy_mac_addr(struct net_device 
*dev, struct mvpp2 *priv,
 /* Ports initialization */
 static int mvpp2_port_probe(struct platform_device *pdev,
struct device_node *port_node,
-   struct mvpp2 *priv, int index)
+   struct mvpp2 *priv)
 {
struct device_node *phy_node;
struct phy *comphy;
@@ -7934,7 +7934,8 @@ static int mvpp2_port_probe(struct platform_device *pdev,
}
netdev_info(dev, "Using %s mac address %pM\n", mac_from, dev->dev_addr);
 
-   priv->port_list[index] = port;
+   priv->port_list[priv->port_count++] = port;
+
return 0;
 
 err_free_port_pcpu:
@@ -8313,28 +8314,17 @@ static int mvpp2_probe(struct platform_device *pdev)
goto err_mg_clk;
}
 
-   priv->port_count = of_get_available_child_count(dn);
-   if (priv->port_count == 0) {
-   dev_err(>dev, "no ports enabled\n");
-   err = -ENODEV;
-   goto err_mg_clk;
-   }
-
-   priv->port_list = devm_kcalloc(>dev, priv->port_count,
-  sizeof(*priv->port_list),
-  GFP_KERNEL);
-   if (!priv->port_list) {
-   err = -ENOMEM;
-   goto err_mg_clk;
-   }
-
/* Initialize ports */
-   i = 0;
for_each_available_child_of_node(dn, port_node) {
-   err = mvpp2_port_probe(pdev, port_node, priv, i);
+   err = mvpp2_port_probe(pdev, port_node, priv);
if (err < 0)
goto err_port_probe;
-   i++;
+   }
+
+   if (priv->port_count == 0) {
+   dev_err(>dev, "no ports enabled\n");
+   err = -ENODEV;
+   goto err_mg_clk;
}
 
/* Statistics must be gathered regularly because some of them (like
-- 
2.7.4



[net-next: PATCH 4/8] net: mvmdio: add ACPI support

2017-12-18 Thread Marcin Wojtas
This patch introducing ACPI support for the mvmdio driver by adding
acpi_match_table with two entries:

* "MRVL0100" for the SMI operation
* "MRVL0101" for the XSMI mode

Also clk enabling is skipped, because the tables do not contain
such data and clock maintenance relies on the firmware. The
MDIO bus is registered using newly introduced
fwnode_mdiobus_register().

Memory region used by mvmdio driver is usually placed in the middle
of the address space of the network controller (e.g. NETA or PP2).
The MDIO base address is obtained without requesting memory region
(by devm_ioremap() call), later overlapping resources are
requested by the network driver, where care is taken to avoid
concurrent access.

This way of solving problem occurred to be not sufficient with ACPI,
because resources declared in the table and used once, appear as
'in-use' in the OS. This patch also ensures releasing resources by
mvmdio driver prior to initializing the network controller driver.

Signed-off-by: Marcin Wojtas <m...@semihalf.com>
---
 drivers/net/ethernet/marvell/mvmdio.c | 42 +++-
 1 file changed, 40 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvmdio.c 
b/drivers/net/ethernet/marvell/mvmdio.c
index 0495487..31d758a 100644
--- a/drivers/net/ethernet/marvell/mvmdio.c
+++ b/drivers/net/ethernet/marvell/mvmdio.c
@@ -17,6 +17,7 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -279,9 +280,19 @@ static int orion_mdio_probe(struct platform_device *pdev)
struct resource *r;
struct mii_bus *bus;
struct orion_mdio_dev *dev;
+   const struct acpi_device_id *acpi_id;
+   bool use_acpi = false;
int i, ret;
 
-   type = (enum orion_mdio_bus_type)of_device_get_match_data(>dev);
+   if (has_acpi_companion(>dev)) {
+   acpi_id = acpi_match_device(pdev->dev.driver->acpi_match_table,
+   >dev);
+   type = (enum orion_mdio_bus_type)acpi_id->driver_data;
+   use_acpi = true;
+   } else {
+   type =
+(enum orion_mdio_bus_type)of_device_get_match_data(>dev);
+   }
 
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!r) {
@@ -319,7 +330,7 @@ static int orion_mdio_probe(struct platform_device *pdev)
 
init_waitqueue_head(>smi_busy_wait);
 
-   for (i = 0; i < ARRAY_SIZE(dev->clk); i++) {
+   for (i = 0; !use_acpi && i < ARRAY_SIZE(dev->clk); i++) {
dev->clk[i] = of_clk_get(pdev->dev.of_node, i);
if (IS_ERR(dev->clk[i]))
break;
@@ -350,6 +361,8 @@ static int orion_mdio_probe(struct platform_device *pdev)
 
if (pdev->dev.of_node)
ret = of_mdiobus_register(bus, pdev->dev.of_node);
+   else if (use_acpi)
+   ret = fwnode_mdiobus_register(bus, pdev->dev.fwnode);
else
ret = mdiobus_register(bus);
if (ret < 0) {
@@ -357,6 +370,15 @@ static int orion_mdio_probe(struct platform_device *pdev)
goto out_mdio;
}
 
+   /* In case of ACPI resources declared in the tables and used
+* once, appear as 'in-use' in the OS. Make sure they are released,
+* before the network driver possibly requests it again during
+* its initialization. The care is taken there to avoid
+* concurrent access to this memory region.
+*/
+   if (use_acpi)
+   release_resource(r);
+
platform_set_drvdata(pdev, bus);
 
return 0;
@@ -365,6 +387,11 @@ static int orion_mdio_probe(struct platform_device *pdev)
if (dev->err_interrupt > 0)
writel(0, dev->regs + MVMDIO_ERR_INT_MASK);
 
+   if (use_acpi) {
+   release_resource(r);
+   return ret;
+   }
+
for (i = 0; i < ARRAY_SIZE(dev->clk); i++) {
if (IS_ERR(dev->clk[i]))
break;
@@ -385,6 +412,9 @@ static int orion_mdio_remove(struct platform_device *pdev)
writel(0, dev->regs + MVMDIO_ERR_INT_MASK);
mdiobus_unregister(bus);
 
+   if (has_acpi_companion(>dev))
+   return 0;
+
for (i = 0; i < ARRAY_SIZE(dev->clk); i++) {
if (IS_ERR(dev->clk[i]))
break;
@@ -402,12 +432,20 @@ static const struct of_device_id orion_mdio_match[] = {
 };
 MODULE_DEVICE_TABLE(of, orion_mdio_match);
 
+static const struct acpi_device_id orion_mdio_acpi_match[] = {
+   { "MRVL0100", BUS_TYPE_SMI },
+   { "MRVL0101", BUS_TYPE_XSMI },
+   { },
+};
+MODULE_DEVICE_TABLE(acpi, orion_mdio_acpi_match);
+
 static struct platform_driver orion_mdio_driver = {
.probe = orion_mdio_probe,
 

[net-next: PATCH 8/8] net: mvpp2: enable ACPI support in the driver

2017-12-18 Thread Marcin Wojtas
This patch introduces an alternative way of obtaining resources - via
ACPI tables provided by firmware. Enabling coexistence with the DT
support, in addition to the OF_*->device_*/fwnode_* API replacement,
required following steps to be taken:

* Add mvpp2_acpi_match table
* Omit clock configuration and obtain tclk from the property - in ACPI
  world, the firmware is responsible for clock maintenance.
* Disable comphy and syscon handling as they are not available for ACPI.
* Modify way of obtaining interrupts - with ACPI they are resources
  bound to struct platform_device and it's not possible to obtain
  them directly from the child node. Hence a formula is used, depending
  on the port_id and number of possible CPUs.

Moreover when booting with ACPI MVPP2_QDIST_MULTI_MODE is picked by
default, as there is no need to keep any kind of the backward
compatibility.

Signed-off-by: Marcin Wojtas <m...@semihalf.com>
---
 drivers/net/ethernet/marvell/mvpp2.c | 130 +---
 1 file changed, 87 insertions(+), 43 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvpp2.c 
b/drivers/net/ethernet/marvell/mvpp2.c
index 4e61ce7..762a44e 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -10,6 +10,7 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -7477,7 +7478,8 @@ static int mvpp2_simple_queue_vectors_init(struct 
mvpp2_port *port,
return 0;
 }
 
-static int mvpp2_multi_queue_vectors_init(struct mvpp2_port *port,
+static int mvpp2_multi_queue_vectors_init(struct platform_device *pdev,
+ struct mvpp2_port *port,
  struct device_node *port_node)
 {
struct mvpp2_queue_vector *v;
@@ -7510,7 +7512,11 @@ static int mvpp2_multi_queue_vectors_init(struct 
mvpp2_port *port,
strncpy(irqname, "rx-shared", sizeof(irqname));
}
 
-   v->irq = of_irq_get_byname(port_node, irqname);
+   if (port_node)
+   v->irq = of_irq_get_byname(port_node, irqname);
+   else
+   v->irq = platform_get_irq(pdev, port->id *
+ (port->nqvecs + 2) + i);
if (v->irq <= 0) {
ret = -EINVAL;
goto err;
@@ -7528,11 +7534,12 @@ static int mvpp2_multi_queue_vectors_init(struct 
mvpp2_port *port,
return ret;
 }
 
-static int mvpp2_queue_vectors_init(struct mvpp2_port *port,
+static int mvpp2_queue_vectors_init(struct platform_device *pdev,
+   struct mvpp2_port *port,
struct device_node *port_node)
 {
if (port->has_tx_irqs)
-   return mvpp2_multi_queue_vectors_init(port, port_node);
+   return mvpp2_multi_queue_vectors_init(pdev, port, port_node);
else
return mvpp2_simple_queue_vectors_init(port, port_node);
 }
@@ -7753,7 +7760,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
struct fwnode_handle *port_fwnode,
struct mvpp2 *priv)
 {
-   struct phy *comphy;
+   struct phy *comphy = NULL;
struct mvpp2_port *port;
struct mvpp2_port_pcpu *port_pcpu;
struct device_node *port_node = to_of_node(port_fwnode);
@@ -7772,7 +7779,12 @@ static int mvpp2_port_probe(struct platform_device *pdev,
if (!fwnode_device_is_available(port_fwnode))
return 0;
 
-   has_tx_irqs = mvpp2_port_has_tx_irqs(priv, port_node);
+   if (port_node) {
+   has_tx_irqs = mvpp2_port_has_tx_irqs(priv, port_node);
+   } else {
+   has_tx_irqs = true;
+   queue_mode = MVPP2_QDIST_MULTI_MODE;
+   }
 
if (!has_tx_irqs)
queue_mode = MVPP2_QDIST_SINGLE_MODE;
@@ -7794,13 +7806,15 @@ static int mvpp2_port_probe(struct platform_device 
*pdev,
goto err_free_netdev;
}
 
-   comphy = devm_of_phy_get(>dev, port_node, NULL);
-   if (IS_ERR(comphy)) {
-   if (PTR_ERR(comphy) == -EPROBE_DEFER) {
-   err = -EPROBE_DEFER;
-   goto err_free_netdev;
+   if (port_node) {
+   comphy = devm_of_phy_get(>dev, port_node, NULL);
+   if (IS_ERR(comphy)) {
+   if (PTR_ERR(comphy) == -EPROBE_DEFER) {
+   err = -EPROBE_DEFER;
+   goto err_free_netdev;
+   }
+   comphy = NULL;
}
-   comphy = NULL;
}
 
if (fwnode_property_read_u32(port_fwnode, "port-id", )) {
@@ -7820,6 +7834,7 @@ static int mvpp2_port_probe(struct platform_device *p

[net-next: PATCH 7/8] net: mvpp2: handle PHY with its fwnode

2017-12-18 Thread Marcin Wojtas
Newly introduced mvmdio driver ACPI support and also fwnode
MDIO helpers allow for switching to PHY handling with its fwnode.

This patch replaces of_* related PHY handling function with
the fwnode_* equivalent and updates mvpp2_port structure
accordingly.

Signed-off-by: Marcin Wojtas <m...@semihalf.com>
---
 drivers/net/ethernet/marvell/mvpp2.c | 41 ++--
 1 file changed, 29 insertions(+), 12 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvpp2.c 
b/drivers/net/ethernet/marvell/mvpp2.c
index 537474f..4e61ce7 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -963,7 +963,7 @@ struct mvpp2_port {
struct delayed_work stats_work;
 
phy_interface_t phy_interface;
-   struct device_node *phy_node;
+   struct fwnode_handle *phy_fwnode;
struct phy *comphy;
unsigned int link;
unsigned int duplex;
@@ -6890,14 +6890,22 @@ static void mvpp21_get_mac_address(struct mvpp2_port 
*port, unsigned char *addr)
 static int mvpp2_phy_connect(struct mvpp2_port *port)
 {
struct phy_device *phy_dev;
+   int ret;
 
/* No PHY is attached */
-   if (!port->phy_node)
+   if (!port->phy_fwnode)
return 0;
 
-   phy_dev = of_phy_connect(port->dev, port->phy_node, mvpp2_link_event, 0,
+   phy_dev = fwnode_phy_find_device(port->phy_fwnode);
+   phy_dev->dev_flags = 0;
+
+   ret = phy_connect_direct(port->dev, phy_dev, mvpp2_link_event,
 port->phy_interface);
-   if (!phy_dev) {
+
+   /* Refcount is held by phy_connect_direct() on success */
+   put_device(_dev->mdio.dev);
+
+   if (ret) {
netdev_err(port->dev, "cannot connect to phy\n");
return -ENODEV;
}
@@ -7047,7 +7055,7 @@ static int mvpp2_open(struct net_device *dev)
goto err_cleanup_txqs;
}
 
-   if (priv->hw_version == MVPP22 && !port->phy_node && port->link_irq) {
+   if (priv->hw_version == MVPP22 && !port->phy_fwnode && port->link_irq) {
err = request_irq(port->link_irq, mvpp2_link_status_isr, 0,
  dev->name, port);
if (err) {
@@ -7082,7 +7090,7 @@ static int mvpp2_open(struct net_device *dev)
return 0;
 
 err_free_link_irq:
-   if (priv->hw_version == MVPP22 && !port->phy_node && port->link_irq)
+   if (priv->hw_version == MVPP22 && !port->phy_fwnode && port->link_irq)
free_irq(port->link_irq, port);
 err_free_irq:
mvpp2_irqs_deinit(port);
@@ -7107,7 +7115,7 @@ static int mvpp2_stop(struct net_device *dev)
on_each_cpu(mvpp2_interrupts_mask, port, 1);
mvpp2_shared_interrupt_mask_unmask(port, true);
 
-   if (priv->hw_version == MVPP22 && !port->phy_node && port->link_irq)
+   if (priv->hw_version == MVPP22 && !port->phy_fwnode && port->link_irq)
free_irq(port->link_irq, port);
 
mvpp2_irqs_deinit(port);
@@ -7745,11 +7753,11 @@ static int mvpp2_port_probe(struct platform_device 
*pdev,
struct fwnode_handle *port_fwnode,
struct mvpp2 *priv)
 {
-   struct device_node *phy_node;
struct phy *comphy;
struct mvpp2_port *port;
struct mvpp2_port_pcpu *port_pcpu;
struct device_node *port_node = to_of_node(port_fwnode);
+   struct fwnode_reference_args args;
struct net_device *dev;
struct resource *res;
char *mac_from = "";
@@ -7779,7 +7787,6 @@ static int mvpp2_port_probe(struct platform_device *pdev,
if (!dev)
return -ENOMEM;
 
-   phy_node = of_parse_phandle(port_node, "phy", 0);
phy_mode = fwnode_get_phy_mode(port_fwnode);
if (phy_mode < 0) {
dev_err(>dev, "incorrect phy mode\n");
@@ -7814,6 +7821,17 @@ static int mvpp2_port_probe(struct platform_device *pdev,
port->priv = priv;
port->has_tx_irqs = has_tx_irqs;
 
+   err = fwnode_property_get_reference_args(port_fwnode, "phy", NULL,
+0, 0, );
+   if (!err) {
+   port->phy_fwnode = args.fwnode;
+   } else if (err == -ENOENT) {
+   port->phy_fwnode = NULL;
+   } else {
+   dev_err(>dev, "unable to parse \"phy\" node\n");
+   goto err_free_netdev;
+   }
+
err = mvpp2_queue_vectors_init(port, port_node);
if (err)
goto err_free_netdev;
@@ -7836,7 +7854,6 @@ static int mvpp2_port_probe(struct platform_device *pdev,
else
port->first_rxq = port-&g

[net-next: PATCH 6/8] net: mvpp2: use device_*/fwnode_* APIs instead of of_*

2017-12-18 Thread Marcin Wojtas
OF functions can be used only for the driver using DT.
As a preparation for introducing ACPI support in mvpp2
driver, use struct fwnode_handle in order to obtain
properties from the hardware description.

Because there is no equivalent for for_each_available_child_of_node(),
use device_for_each_child_node() and check the port availability
inside the mvpp2_port_probe() routine.

This patch replaces of_* function with device_*/fwnode_*
where possible in the mvpp2.

Signed-off-by: Marcin Wojtas <m...@semihalf.com>
---
 drivers/net/ethernet/marvell/mvpp2.c | 47 +++-
 1 file changed, 26 insertions(+), 21 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvpp2.c 
b/drivers/net/ethernet/marvell/mvpp2.c
index 7f42d90..537474f 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -932,6 +932,9 @@ struct mvpp2_port {
 
struct mvpp2 *priv;
 
+   /* Firmware node associated to the port */
+   struct fwnode_handle *fwnode;
+
/* Per-port registers' base address */
void __iomem *base;
void __iomem *stats_base;
@@ -7711,17 +7714,16 @@ static bool mvpp2_port_has_tx_irqs(struct mvpp2 *priv,
 }
 
 static void mvpp2_port_copy_mac_addr(struct net_device *dev, struct mvpp2 
*priv,
-struct device_node *port_node,
+struct fwnode_handle *fwnode,
 char **mac_from)
 {
struct mvpp2_port *port = netdev_priv(dev);
char hw_mac_addr[ETH_ALEN] = {0};
-   const char *dt_mac_addr;
+   char fw_mac_addr[ETH_ALEN];
 
-   dt_mac_addr = of_get_mac_address(port_node);
-   if (dt_mac_addr && is_valid_ether_addr(dt_mac_addr)) {
-   *mac_from = "device tree";
-   ether_addr_copy(dev->dev_addr, dt_mac_addr);
+   if (fwnode_get_mac_address(fwnode, fw_mac_addr, ETH_ALEN)) {
+   *mac_from = "firmware node";
+   ether_addr_copy(dev->dev_addr, fw_mac_addr);
return;
}
 
@@ -7740,13 +7742,14 @@ static void mvpp2_port_copy_mac_addr(struct net_device 
*dev, struct mvpp2 *priv,
 
 /* Ports initialization */
 static int mvpp2_port_probe(struct platform_device *pdev,
-   struct device_node *port_node,
+   struct fwnode_handle *port_fwnode,
struct mvpp2 *priv)
 {
struct device_node *phy_node;
struct phy *comphy;
struct mvpp2_port *port;
struct mvpp2_port_pcpu *port_pcpu;
+   struct device_node *port_node = to_of_node(port_fwnode);
struct net_device *dev;
struct resource *res;
char *mac_from = "";
@@ -7757,6 +7760,10 @@ static int mvpp2_port_probe(struct platform_device *pdev,
int phy_mode;
int err, i, cpu;
 
+   /* Silently exit, if the port node turns out to be disabled. */
+   if (!fwnode_device_is_available(port_fwnode))
+   return 0;
+
has_tx_irqs = mvpp2_port_has_tx_irqs(priv, port_node);
 
if (!has_tx_irqs)
@@ -7773,7 +7780,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
return -ENOMEM;
 
phy_node = of_parse_phandle(port_node, "phy", 0);
-   phy_mode = of_get_phy_mode(port_node);
+   phy_mode = fwnode_get_phy_mode(port_fwnode);
if (phy_mode < 0) {
dev_err(>dev, "incorrect phy mode\n");
err = phy_mode;
@@ -7789,7 +7796,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
comphy = NULL;
}
 
-   if (of_property_read_u32(port_node, "port-id", )) {
+   if (fwnode_property_read_u32(port_fwnode, "port-id", )) {
err = -EINVAL;
dev_err(>dev, "missing port-id value\n");
goto err_free_netdev;
@@ -7820,7 +7827,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
/* the link irq is optional */
port->link_irq = 0;
 
-   if (of_property_read_bool(port_node, "marvell,loopback"))
+   if (fwnode_property_read_bool(port_fwnode, "marvell,loopback"))
port->flags |= MVPP2_F_LOOPBACK;
 
port->id = id;
@@ -7845,8 +7852,8 @@ static int mvpp2_port_probe(struct platform_device *pdev,
   MVPP21_MIB_COUNTERS_OFFSET +
   port->gop_id * MVPP21_MIB_COUNTERS_PORT_SZ;
} else {
-   if (of_property_read_u32(port_node, "gop-port-id",
->gop_id)) {
+   if (fwnode_property_read_u32(port_fwnode, "gop-port-id",
+>gop_id)) {
err = -EINVAL;
dev_err(>dev, "m

Re: Problems with mvneta

2017-11-01 Thread Marcin Wojtas
Hi Thomas,

2017-10-31 21:23 GMT+01:00 Thomas Petazzoni
<thomas.petazz...@free-electrons.com>:
> Hello,
>
> On Tue, 31 Oct 2017 18:09:38 +0100, Simon Guinot wrote:
>
>> > On Tue, 31 Oct 2017 15:23:22 +0100, Sven Müller wrote:
>> > > After quite a long time of trying to reproduce the issue without any 
>> > > success I got 3 network crashes today. And all errors occurred with a 
>> > > kernel including the patch:
>> > >
>> > > 2a90f7e1d5d04e4f1060268e0b55a2c702bbd67a
>> > >
>> > > At least according to Andreas' and my problems we can exclude the 6ad2 
>> > > patch as the source of the errors.
>> >
>> > Simon, 2a90f7e1d5d04e4f1060268e0b55a2c702bbd67a is your commit, adding
>> > xmit_more support, and a number of people are reporting stability
>> > issues with this patch applied.
>>
>> I wrote an earlier version of this patch. But I think this commit has
>> been modified by the submitter Marcin Wojtas because I don't remember
>> anything about the maximum number of descriptors allowed to be flush.
>>
>> >
>> > Do you think you will have some time to look into this ?
>>
>> No I don't have time to look into that.
>>
>> But after a quick look, I wonder what is happening if
>> "txq->pending + frags > MVNETA_TXQ_DEC_SENT_MASK" ? Because IIUC
>> mvneta_txq_pend_desc_add() is called anyway. And according to the
>> comment inside the function, it assumes there is less than 255
>> descriptors to send... It looks suspect.
>
> Thanks for the feedback. Marcin, do you remember this xmit_more patch?
>

Yes I do. It seems pretty simple and didn't show any issues durin very
long stress tests. I will check the mvneta_tx() routine if there's
anything suspicios/missed.

Marcin


Re: [PATCH net-next] net: mvpp2: phylink support

2017-09-22 Thread Marcin Wojtas
Hi Antoine,

You can add
Tested-by: Marcin Wojtas <m...@semihalf.com>

Best regards,
Marcin

2017-09-21 15:45 GMT+02:00 Antoine Tenart <antoine.ten...@free-electrons.com>:
> Convert the PPv2 driver to use phylink, which models the MAC to PHY
> link. The phylink support is made such a way the GoP link IRQ can still
> be used: the two modes are incompatible and the GoP link IRQ will be
> used if no PHY is described in the device tree. This is the same
> behaviour as before.
>
> Signed-off-by: Antoine Tenart <antoine.ten...@free-electrons.com>
> ---
>  drivers/net/ethernet/marvell/Kconfig |   1 +
>  drivers/net/ethernet/marvell/mvpp2.c | 502 
> +--
>  2 files changed, 303 insertions(+), 200 deletions(-)
>
> diff --git a/drivers/net/ethernet/marvell/Kconfig 
> b/drivers/net/ethernet/marvell/Kconfig
> index da6fb825afea..991138b8dfba 100644
> --- a/drivers/net/ethernet/marvell/Kconfig
> +++ b/drivers/net/ethernet/marvell/Kconfig
> @@ -86,6 +86,7 @@ config MVPP2
> depends on ARCH_MVEBU || COMPILE_TEST
> depends on HAS_DMA
> select MVMDIO
> +   select PHYLINK
> ---help---
>   This driver supports the network interface units in the
>   Marvell ARMADA 375, 7K and 8K SoCs.
> diff --git a/drivers/net/ethernet/marvell/mvpp2.c 
> b/drivers/net/ethernet/marvell/mvpp2.c
> index 8041d692db3c..5fb7e76ee128 100644
> --- a/drivers/net/ethernet/marvell/mvpp2.c
> +++ b/drivers/net/ethernet/marvell/mvpp2.c
> @@ -28,6 +28,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -341,6 +342,7 @@
>  #define MVPP2_GMAC_FORCE_LINK_PASS BIT(1)
>  #define MVPP2_GMAC_IN_BAND_AUTONEG BIT(2)
>  #define MVPP2_GMAC_IN_BAND_AUTONEG_BYPASS  BIT(3)
> +#define MVPP2_GMAC_IN_BAND_RESTART_AN  BIT(4)
>  #define MVPP2_GMAC_CONFIG_MII_SPEEDBIT(5)
>  #define MVPP2_GMAC_CONFIG_GMII_SPEED   BIT(6)
>  #define MVPP2_GMAC_AN_SPEED_EN BIT(7)
> @@ -350,6 +352,12 @@
>  #define MVPP2_GMAC_AN_DUPLEX_ENBIT(13)
>  #define MVPP2_GMAC_STATUS0 0x10
>  #define MVPP2_GMAC_STATUS0_LINK_UP BIT(0)
> +#defineMVPP2_GMAC_STATUS0_GMII_SPEED   BIT(1)
> +#defineMVPP2_GMAC_STATUS0_MII_SPEEDBIT(2)
> +#defineMVPP2_GMAC_STATUS0_FULL_DUPLEX  BIT(3)
> +#define MVPP2_GMAC_STATUS0_RX_PAUSEBIT(6)
> +#define MVPP2_GMAC_STATUS0_TX_PAUSEBIT(7)
> +#define MVPP2_GMAC_STATUS0_AN_COMPLETE BIT(11)
>  #define MVPP2_GMAC_PORT_FIFO_CFG_1_REG 0x1c
>  #define MVPP2_GMAC_TX_FIFO_MIN_TH_OFFS 6
>  #define MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK 0x1fc0
> @@ -878,12 +886,11 @@ struct mvpp2_port {
> u16 rx_ring_size;
> struct mvpp2_pcpu_stats __percpu *stats;
>
> +   struct device_node *of_node;
> +
> phy_interface_t phy_interface;
> -   struct device_node *phy_node;
> +   struct phylink *phylink;
> struct phy *comphy;
> -   unsigned int link;
> -   unsigned int duplex;
> -   unsigned int speed;
>
> struct mvpp2_bm_pool *pool_long;
> struct mvpp2_bm_pool *pool_short;
> @@ -4716,13 +4723,14 @@ static void mvpp2_port_periodic_xon_disable(struct 
> mvpp2_port *port)
>  }
>
>  /* Configure loopback port */
> -static void mvpp2_port_loopback_set(struct mvpp2_port *port)
> +static void mvpp2_port_loopback_set(struct mvpp2_port *port,
> +   const struct phylink_link_state *state)
>  {
> u32 val;
>
> val = readl(port->base + MVPP2_GMAC_CTRL_1_REG);
>
> -   if (port->speed == 1000)
> +   if (state->speed == 1000)
> val |= MVPP2_GMAC_GMII_LB_EN_MASK;
> else
> val &= ~MVPP2_GMAC_GMII_LB_EN_MASK;
> @@ -4778,10 +4786,6 @@ static void mvpp2_defaults_set(struct mvpp2_port *port)
> int tx_port_num, val, queue, ptxq, lrxq;
>
> if (port->priv->hw_version == MVPP21) {
> -   /* Configure port to loopback if needed */
> -   if (port->flags & MVPP2_F_LOOPBACK)
> -   mvpp2_port_loopback_set(port);
> -
> /* Update TX FIFO MIN Threshold */
> val = readl(port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG);
> val &= ~MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK;
> @@ -5860,111 +5864,6 @@ static irqreturn_t mvpp2_link_status_isr(int irq, 
> void *dev_id)
> return IRQ_HANDLED;
>  }
>
> -static void mvpp2_gmac_set_autoneg(st

Re: [PATCH net-next v2 05/14] net: mvpp2: do not force the link mode

2017-08-28 Thread Marcin Wojtas
Hi Antoine,

2017-08-28 8:55 GMT+02:00 Antoine Tenart :
> Hi Russell,
>
> On Fri, Aug 25, 2017 at 11:43:13PM +0100, Russell King - ARM Linux wrote:
>> On Fri, Aug 25, 2017 at 04:48:12PM +0200, Antoine Tenart wrote:
>> > The link mode (speed, duplex) was forced based on what the phylib
>> > returns. This should not be the case, and only forced by ethtool
>> > functions manually. This patch removes the link mode enforcement from
>> > the phylib link_event callback.
>>
>> So how does RGMII work (which has no in-band signalling between the PHY
>> and MAC)?
>>
>> phylib expects the network driver to configure it according to the PHY
>> state at link_event time - I think you need to explain more why you
>> think that this is not necessary.
>
> Good catch, this won't work properly with RGMII. This could be done
> out-of-band according to the spec, but that would use PHY polling and we
> do not want that (the same concern was raised by Andrew on another
> patch).
>
> I'll keep this mode enforcement for RGMII then.
>

Can you be 100% sure that when using SGMII with PHY's (like Marvell
Alaska 88E1xxx series), is in-band link information always available?
I'd be very cautious with such assumption and use in-band management
only when set in the DT, like mvneta. I think phylib can properly can
do its work when MDIO connection is provided on the board.

Did you check the change also on A375?

Best regards,
Marcin


Re: [EXT] Re: [PATCH net-next 10/18] net: mvpp2: use the GoP interrupt for link status changes

2017-08-23 Thread Marcin Wojtas
Hi Antoine,

2017-08-23 18:04 GMT+02:00 Antoine Tenart :
> On Wed, Aug 23, 2017 at 03:24:55PM +, Stefan Chulski wrote:
>> > When the cable is connected (there is signal) and the serdes is in sync 
>> > and AN
>> > succeeded.
>> >
>> > > With SFF/SFP ports, you generally need a gpio line the fibre module
>> > > can use to indicate if it has link. Fixed-phy has such support, and
>> > > your link_change function will get called when the link changes.
>> >
>> > So that would work when using SFP modules but I wonder if the GoP irq isn't
>> > needed when using passive cable, in which case this patch would still be 
>> > needed
>> > (and of course we should support the new Russell phylib capabilities).
>>
>> Even if new phylib driver supports passive direct cables connection,
>> GoP IRQ required for SOHO/Peridot external switch support.
>> SOHO/Peridot external switch could be connected directly to Serdes line.
>
> So I guess the GoP link irq patches are needed. Should I resend them
> then?
>
> We'll have to discuss how to handle fixed-phy vs GoP IRQ, but I guess we
> can do this when adding the fixed-phy support later.
>

Please check mvneta.c - you can find there coexistence of normal
libphy support, fixed phy and link irq for the inband management mode.
IMO it's exactly, what you need here.

Best regards,
Marcin


Re: [PATCH 1/2] net: mvneta: remove bogus use of

2017-08-04 Thread Marcin Wojtas
Hi Gregory,

>From my side: +1 to your modification.

Thanks,
Marcin

2017-08-04 17:26 GMT+02:00 Gregory CLEMENT :
> Hi Rob,
>
>  On jeu., juil. 20 2017, Rob Herring  wrote:
>
>> On Thu, Jul 20, 2017 at 10:06 AM, Gregory CLEMENT
>>  wrote:
>>> Hi Rob,
>>>
>>>  On jeu., juil. 20 2017, Rob Herring  wrote:
>>>
>>> (Adding Marcin in CC who wrote this part of code)
>>>
 Nothing sets ever sets data, so it is always NULL. Remove it as this is
 the only user of data ptr in the whole kernel, and it is going to be
 removed from struct device_node.
>>>
>>> Actually the use of device_node.data ptr is not bogus and it is set in
>>> mvneta_bm_probe:
>>> http://elixir.free-electrons.com/linux/latest/source/drivers/net/ethernet/marvell/mvneta_bm.c#L433
>>
>> Indeed. Looks like some complicated kconfig logic, so I'd not been
>> able to trigger a build failure nor did 0-day (so far).
>>
>>> Your patch will break the BM support on this driver. So if you need to
>>> remove this data ptr, then you have to offer an alternative for it.
>>
>> How about something like this (WS damaged) patch:
>
> I finally took time to test your patch. There was some missing part
> which prevented it to be build, like including linux/of_platform.h, or
> providing tub function when CONFIG_MVNETA_BM was not enable.
>
> Also the fact that you still call mvneta_bm_port_init() even if bm_priv
> was NULL was not really nice. So I proposed the following patch, that I
> tested on a clearfog with and without CONFIG_MVNETA_BM enabled.
>
> From 03c4028bc1f52d3d214e8506d9f0f0d3985d Mon Sep 17 00:00:00 2001
> From: Gregory CLEMENT 
> Date: Fri, 4 Aug 2017 17:18:38 +0200
> Subject: [PATCH] net: mvneta: remove data pointer usage from device_node
>  structure
>
> In order to be able to remove the data pointer from the device_node
> structure. We have to modify the way the BM resources are shared between
> the mvneta port.
>
> Signed-off-by: Gregory CLEMENT 
> ---
>  drivers/net/ethernet/marvell/mvneta.c| 18 --
>  drivers/net/ethernet/marvell/mvneta_bm.c | 13 +
>  drivers/net/ethernet/marvell/mvneta_bm.h |  8 ++--
>  3 files changed, 31 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/net/ethernet/marvell/mvneta.c 
> b/drivers/net/ethernet/marvell/mvneta.c
> index 63b6147753fe..fd84447582f7 100644
> --- a/drivers/net/ethernet/marvell/mvneta.c
> +++ b/drivers/net/ethernet/marvell/mvneta.c
> @@ -4295,12 +4295,16 @@ static int mvneta_probe(struct platform_device *pdev)
>
> /* Obtain access to BM resources if enabled and already initialized */
> bm_node = of_parse_phandle(dn, "buffer-manager", 0);
> -   if (bm_node && bm_node->data) {
> -   pp->bm_priv = bm_node->data;
> -   err = mvneta_bm_port_init(pdev, pp);
> -   if (err < 0) {
> -   dev_info(>dev, "use SW buffer management\n");
> -   pp->bm_priv = NULL;
> +   if (bm_node) {
> +   pp->bm_priv = mvneta_bm_get(bm_node);
> +   if (pp->bm_priv) {
> +   err = mvneta_bm_port_init(pdev, pp);
> +   if (err < 0) {
> +   dev_info(>dev,
> +"use SW buffer management\n");
> +   mvneta_bm_put(pp->bm_priv);
> +   pp->bm_priv = NULL;
> +   }
> }
> }
> of_node_put(bm_node);
> @@ -4369,6 +4373,7 @@ static int mvneta_probe(struct platform_device *pdev)
> mvneta_bm_pool_destroy(pp->bm_priv, pp->pool_long, 1 << 
> pp->id);
> mvneta_bm_pool_destroy(pp->bm_priv, pp->pool_short,
>1 << pp->id);
> +   mvneta_bm_put(pp->bm_priv);
> }
>  err_free_stats:
> free_percpu(pp->stats);
> @@ -4410,6 +4415,7 @@ static int mvneta_remove(struct platform_device *pdev)
> mvneta_bm_pool_destroy(pp->bm_priv, pp->pool_long, 1 << 
> pp->id);
> mvneta_bm_pool_destroy(pp->bm_priv, pp->pool_short,
>1 << pp->id);
> +   mvneta_bm_put(pp->bm_priv);
> }
>
> return 0;
> diff --git a/drivers/net/ethernet/marvell/mvneta_bm.c 
> b/drivers/net/ethernet/marvell/mvneta_bm.c
> index 466939f8f0cf..01e3152e76c8 100644
> --- a/drivers/net/ethernet/marvell/mvneta_bm.c
> +++ b/drivers/net/ethernet/marvell/mvneta_bm.c
> @@ -18,6 +18,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -392,6 +393,18 @@ static void mvneta_bm_put_sram(struct mvneta_bm *priv)
>   MVNETA_BM_BPPI_SIZE);
>  }
>
> +struct mvneta_bm *mvneta_bm_get(struct device_node *node)
> 

Re: [PATCH 0/8] net: mvpp2: add TX interrupts support

2017-07-26 Thread Marcin Wojtas
Hi Thomas,

I tested patchset on A8040-DB, everything seems fine.

Best regards,
Marcin

2017-07-25 17:55 GMT+02:00 Thomas Petazzoni
:
> Hello,
>
> So far, the mvpp2 driver was using an hrtimer to handle TX
> completion. This patch series adds support for using TX interrupts
> (for each CPU) on PPv2.2, the variant of the IP used on Marvell Armada
> 7K/8K.
>
> This series has been tested on Marvell Armada 7K (PPv2.2) and Armada
> 375 (PPv2.1).
>
> Dave:
>
>  - This series depends on the previous series sent by Antoine Ténart
>"net: mvpp2: MAC/GoP configuration and optional PHYs". Functionally
>speaking there is no real dependency, but we touch in a few areas
>the same piece of code, so I based my patch series on top of
>Antoine's.
>
>  - Please do not apply the last patch of this series "arm64: dts:
>marvell: add TX interrupts for PPv2.2", it will be taken by the ARM
>mvebu maintainers.
>
> Thanks!
>
> Thomas
>
> Thomas Petazzoni (8):
>   net: mvpp2: fix MVPP21_ISR_RXQ_GROUP_REG definition
>   net: mvpp2: remove RX queue group reset code
>   net: mvpp2: introduce per-port nrxqs/ntxqs variables
>   net: mvpp2: move from cpu-centric naming to "software thread" naming
>   net: mvpp2: introduce queue_vector concept
>   net: mvpp2: add support for TX interrupts and RX queue distribution
> modes
>   dt-bindings: net: marvell-pp2: update interrupt-names with TX
> interrupts
>   arm64: dts: marvell: add TX interrupts for PPv2.2
>
>  .../devicetree/bindings/net/marvell-pp2.txt|  33 +-
>  .../boot/dts/marvell/armada-cp110-master.dtsi  |  21 +-
>  .../arm64/boot/dts/marvell/armada-cp110-slave.dtsi |  21 +-
>  drivers/net/ethernet/marvell/mvpp2.c   | 638 
> +++--
>  4 files changed, 534 insertions(+), 179 deletions(-)
>
> --
> 2.9.4
>


Re: [PATCH net-next 00/18] net: mvpp2: MAC/GoP configuration and optional PHYs

2017-07-25 Thread Marcin Wojtas
2017-07-25 10:48 GMT+02:00 Antoine Tenart <antoine.ten...@free-electrons.com>:
> Hi Marcin,
>
> On Tue, Jul 25, 2017 at 01:56:57AM +0200, Marcin Wojtas wrote:
>>
>> I stressed 10G interfaces with bidirectional traffic on A8040-DB, did
>> some up/down sequences and overall it seems stable (of course I needed
>> fix mentioned in patch 10/18). In a spare moment I'll give other
>> changes a scroll.
>
> Thanks for testing! Can I had you Tested-by tag in v2?
>

Sure.

Marcin


Re: [PATCH net-next 00/18] net: mvpp2: MAC/GoP configuration and optional PHYs

2017-07-24 Thread Marcin Wojtas
Hi Antoine,

I stressed 10G interfaces with bidirectional traffic on A8040-DB, did
some up/down sequences and overall it seems stable (of course I needed
fix mentioned in patch 10/18). In a spare moment I'll give other
changes a scroll.

Best regards,
Marcin

2017-07-24 15:48 GMT+02:00 Antoine Tenart :
> Hi all,
>
> This series aim two things: making the PPv2 driver less depending on
> the firmware/bootloader initialization[1], and making the PPv2 driver
> work when no Ethernet PHY is connected between a port and the physical
> layer[2]. A few patches cleanup some small parts of the driver, and
> newly supported interfaces are described in the device trees[3].
>
> [1] The current implementation of the PPv2 driver relies on the
> firmware/bootloader initialization to configure some parts, as the
> Group of Ports (GoP) and the MACs (GMAC and/or XLG MAC --for 10G--).
> The drawback is the kernel must be configured to match exactly what
> the bootloader configures which is not convenient and is an issue
> when using boards having an Ethernet port and an SFP port wired to
> the same GoP port, as no dynamic configuration can be done.
>
> This series adds the GoP and GMAC/XLG MAC initializations so that
> the PPV2 does not have to rely on a previous initialization. One
> part is still missing from this series, and that would be the
> 'comphy' which provides shared serdes PHYs and which must be
> configured as well for a full kernel initialization to work. This
> comphy support will be part of a following up series. (This
> series was also tested with this 'comphy' support, as it's nearly
> ready).
>
> Patches 3-7, 11 and 14-15.
>
> [2] While the documentation states the phy property in a port node is
> optional, it is not in the current driver's implementation. This is
> needed when no PHY is connected between a GoP port and the physical
> layer (as for the two SFP ports on the 8040-db). One other feature
> is missing to be able to use such ports: the port link interrupt
> which allows not to rely on the phylib link event callback.
>
> This series makes the phy optional in the PPv2 driver, and then adds
> the support for the GoP port link interrupt to handle link status
> changes on such ports.
>
> Patches 8-10, 12-14.
>
> [3] With the port link interrupt and optional PHY support, the two SFP
> ports on the Marvell Armada 8040 DB can be described and used; as
> well as the SFP port on the 7040 DB..
>
> Cosmetic changes / fixes.
>
> Patches 1, 2 and 16-18.
>
> I intentionally grouped all these patches into one series, as we would
> end up with series depending on each others (and I already did not
> include all my patches in this one). If that's an issue for this series
> to be reviewed/merged, I can easily split it into two series, with a
> dependency of one on the other.
>
> @Dave: Patches 13 to 18 should go through the mvebu tree, thanks :)
>
> Thanks!
> Antoine
>
>
> Antoine Tenart (18):
>   net: mvpp2: unify register definitions coding style
>   net: mvpp2: fix the synchronization module bypass macro name
>   net: mvpp2: set the SMI PHY address when connecting to the PHY
>   net: mvpp2: move the mii configuration in the ndo_open path
>   net: mvpp2: initialize the GMAC when using a port
>   net: mvpp2: initialize the XLG MAC when using a port
>   net: mvpp2: initialize the GoP
>   net: mvpp2: make the phy optional
>   net: mvpp2: use named interrupts
>   net: mvpp2: use the GoP interrupt for link status changes
>   Documentation/bindings: net: marvell-pp2: add the system controller
>   Documentation/bindings: net: marvell-pp2: add the interrupt-names
>   arm64: dts: marvell: cp110: use named interrupts for the Ethernet
> ports
>   arm64: dts: marvell: cp110: add PPv2 port interrupts
>   arm64: dts: marvell: add a reference to the sysctrl syscon in the ppv2
> node
>   arm64: dts: marvell: mcbin: enable more networking ports
>   arm64: dts: marvell: 7040-db: enable the SFP port
>   arm64: dts: marvell: 8040-db: enable the SFP ports
>
>  .../devicetree/bindings/net/marvell-pp2.txt|   7 +
>  arch/arm64/boot/dts/marvell/armada-7040-db.dts |   5 +
>  arch/arm64/boot/dts/marvell/armada-8040-db.dts |  10 +
>  arch/arm64/boot/dts/marvell/armada-8040-mcbin.dts  |  30 ++
>  .../boot/dts/marvell/armada-cp110-master.dtsi  |  13 +-
>  .../arm64/boot/dts/marvell/armada-cp110-slave.dtsi |  13 +-
>  drivers/net/ethernet/marvell/mvpp2.c   | 587 
> ++---
>  7 files changed, 575 insertions(+), 90 deletions(-)
>
> --
> 2.13.3
>


Re: [PATCH 1/2] net: mvneta: remove bogus use of

2017-07-20 Thread Marcin Wojtas
Hi Rob,

I somehow missed this patch.

2017-07-20 17:06 GMT+02:00 Gregory CLEMENT :
> Hi Rob,
>
>  On jeu., juil. 20 2017, Rob Herring  wrote:
>
> (Adding Marcin in CC who wrote this part of code)
>
>> Nothing sets ever sets data, so it is always NULL. Remove it as this is
>> the only user of data ptr in the whole kernel, and it is going to be
>> removed from struct device_node.
>
> Actually the use of device_node.data ptr is not bogus and it is set in
> mvneta_bm_probe:
> http://elixir.free-electrons.com/linux/latest/source/drivers/net/ethernet/marvell/mvneta_bm.c#L433
>
> Your patch will break the BM support on this driver. So if you need to
> remove this data ptr, then you have to offer an alternative for it.

Exactly, this breaks NETA operation with BM block. The data is set in:

dn->data = priv;
platform_set_drvdata(pdev, priv);

At the time I couldn't have found out a nicer solution to make work
two different HW blocks (network controller and buffer manager). There
was once a patchset enabling calling another driver's probe basing on
the phandle and of_node information, but after it reached ~v7 it
eventually didn't make it to the tree. Do you any way for solving such
dependencies, if you really want to get rid of this field?

Best regards,
Marcin

>
> Thanks,
>
> Gregory
>
>>
>> Cc: Thomas Petazzoni 
>> Signed-off-by: Rob Herring 
>> ---
>> Probably there's a better fix here to actually enable the h/w buffer
>> manager.
>>
>> I intend to take this thru the DT tree as patch 2 is dependent on this.
>>
>> Rob
>>
>>  drivers/net/ethernet/marvell/mvneta.c | 4 ++--
>>  1 file changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/marvell/mvneta.c 
>> b/drivers/net/ethernet/marvell/mvneta.c
>> index 0aab74c2a209..5624f4b49f9d 100644
>> --- a/drivers/net/ethernet/marvell/mvneta.c
>> +++ b/drivers/net/ethernet/marvell/mvneta.c
>> @@ -4296,8 +4296,8 @@ static int mvneta_probe(struct platform_device *pdev)
>>
>>   /* Obtain access to BM resources if enabled and already initialized */
>>   bm_node = of_parse_phandle(dn, "buffer-manager", 0);
>> - if (bm_node && bm_node->data) {
>> - pp->bm_priv = bm_node->data;
>> + if (bm_node) {
>> + pp->bm_priv = NULL;
>>   err = mvneta_bm_port_init(pdev, pp);
>>   if (err < 0) {
>>   dev_info(>dev, "use SW buffer management\n");
>> --
>> 2.11.0
>>
>
> --
> Gregory Clement, Free Electrons
> Kernel, drivers, real-time and embedded Linux
> development, consulting, training and support.
> http://free-electrons.com


Re: [PATCH 0/6] mvmdio updates

2017-04-10 Thread Marcin Wojtas
Hi Russel,

2017-04-10 17:27 GMT+02:00 Russell King - ARM Linux :
> This series of patches update mvmdio for Armada 8k CP110.  A number of
> issues were found:
>
> 1. The driver fails to disable an interrupt when something goes wrong
>in the probe function.
>
> 2. The interrupt is specified in DT to be optional, but the driver
>unconditionally writes to the interrupt mask register, which may
>not exist.
>
> 3. The DT binding specifies
> "reg: address and length of the SMI register"
>however, when supporting the interrupt, the size must cover the
>interrupt register as well.  Update the binding documentation
>with this information that was previously omitted.
>
> 4. If the register size is too small, have the driver print an error
>and disable use of the interrupt.
>
> 5. Armada 8k needs three clocks for the MDIO interface, otherwise the
>SoC hangs (since it is part of one of the ethernet interfaces.)
>GOP clock, MG core clock and MG clock are needed on 8k. Augment the
>binding and driver to allow three clocks to be specified.
>

Actually most of the interfaces on a7k/a8k require multiple clocks to
be enabled, however all those twisted dependencies are handled within:
drivers/clk/mvebu/cp110-system-controller.c
With the latest patch of Thomas Petazzoni, MG clock is already
specified as a child of MG_CORE, so I believe a just minor change will
resolve remaining GOP clock dependency. This way we will leave
orion-mdio driver untouched around clocks.

Thomas, what is your opinion?

Regards,
Marcin


Re: [PATCH net-next v3 0/4] net: mvneta: improve rx/tx performance

2017-02-21 Thread Marcin Wojtas
Hi Jisheng,

2017-02-21 17:16 GMT+01:00 David Miller :
> From: Jisheng Zhang 
> Date: Tue, 21 Feb 2017 12:37:40 +0800
>
>> Thanks for your review.
>>
>> The measurement is simple: record how much time we spent in mvneta_rx_swbm()
>> for receiving 1GB data, something as below:
>
> Please use a standard tool for measuring performance, rather than profiling
> the driver and trying to derive numbers that way.

If possible in your setup, I suggest pushing 64B (and other sizes)
packets uni or bidirectionally via 2 ports in L2 bridge mode. It's a
good stress test, you'd get some meaningful numbers (also check cpu
consumption with mpstat in the meantime).

Best regards,
Marcin


Re: [PATCHv3 net-next 11/12] net: mvpp2: switch to build_skb() in the RX path

2017-02-05 Thread Marcin Wojtas
Hi Thomas,

How about switching to napi_alloc_frag() in mvpp2_rx_refill(), which
is called in hotpath? In easy way, it may give some performance gain.

Best regards,
Marcin

2017-02-02 16:51 GMT+01:00 Thomas Petazzoni
:
> This commit adapts the mvpp2 RX path to use the build_skb() method. Not
> only build_skb() is now the recommended mechanism, but it also
> simplifies the addition of support for the PPv2.2 variant.
>
> Indeed, without build_skb(), we have to keep track for each RX
> descriptor of the physical address of the packet buffer, and the virtual
> address of the SKB. However, in PPv2.2 running on 64 bits platform,
> there is not enough space in the descriptor to store the virtual address
> of the SKB. So having to take care only of the address of the packet
> buffer, and building the SKB upon reception helps in supporting PPv2.2.
>
> The implementation is fairly straightforward:
>
>  - mvpp2_skb_alloc() is renamed to mvpp2_buf_alloc() and no longer
>allocates a SKB. Instead, it allocates a buffer using the new
>mvpp2_frag_alloc() function, with enough space for the data and SKB.
>
>  - The initialization of the RX buffers in mvpp2_bm_bufs_add() as well
>as the refill of the RX buffers in mvpp2_rx_refill() is adjusted
>accordingly.
>
>  - Finally, the mvpp2_rx() is modified to use build_skb().
>
> Signed-off-by: Thomas Petazzoni 
> ---
>  drivers/net/ethernet/marvell/mvpp2.c | 77 
> +---
>  1 file changed, 55 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/net/ethernet/marvell/mvpp2.c 
> b/drivers/net/ethernet/marvell/mvpp2.c
> index ec8f452..4132dc8 100644
> --- a/drivers/net/ethernet/marvell/mvpp2.c
> +++ b/drivers/net/ethernet/marvell/mvpp2.c
> @@ -918,6 +918,7 @@ struct mvpp2_bm_pool {
> int buf_size;
> /* Packet size */
> int pkt_size;
> +   int frag_size;
>
> /* BPPE virtual base address */
> u32 *virt_addr;
> @@ -3354,6 +3355,22 @@ static void mvpp2_cls_oversize_rxq_set(struct 
> mvpp2_port *port)
> mvpp2_write(port->priv, MVPP2_CLS_SWFWD_PCTRL_REG, val);
>  }
>
> +static void *mvpp2_frag_alloc(const struct mvpp2_bm_pool *pool)
> +{
> +   if (likely(pool->frag_size <= PAGE_SIZE))
> +   return netdev_alloc_frag(pool->frag_size);
> +   else
> +   return kmalloc(pool->frag_size, GFP_ATOMIC);
> +}
> +
> +static void mvpp2_frag_free(const struct mvpp2_bm_pool *pool, void *data)
> +{
> +   if (likely(pool->frag_size <= PAGE_SIZE))
> +   skb_free_frag(data);
> +   else
> +   kfree(data);
> +}
> +
>  /* Buffer Manager configuration routines */
>
>  /* Create pool */
> @@ -3428,7 +3445,8 @@ static void mvpp2_bm_bufs_free(struct device *dev, 
> struct mvpp2 *priv,
>
> if (!vaddr)
> break;
> -   dev_kfree_skb_any((struct sk_buff *)vaddr);
> +
> +   mvpp2_frag_free(bm_pool, (void *)vaddr);
> }
>
> /* Update BM driver with number of buffers removed from pool */
> @@ -3542,29 +3560,28 @@ static void mvpp2_rxq_short_pool_set(struct 
> mvpp2_port *port,
> mvpp2_write(port->priv, MVPP2_RXQ_CONFIG_REG(prxq), val);
>  }
>
> -/* Allocate skb for BM pool */
> -static struct sk_buff *mvpp2_skb_alloc(struct mvpp2_port *port,
> -  struct mvpp2_bm_pool *bm_pool,
> -  dma_addr_t *buf_phys_addr,
> -  gfp_t gfp_mask)
> +static void *mvpp2_buf_alloc(struct mvpp2_port *port,
> +struct mvpp2_bm_pool *bm_pool,
> +dma_addr_t *buf_phys_addr,
> +gfp_t gfp_mask)
>  {
> -   struct sk_buff *skb;
> dma_addr_t phys_addr;
> +   void *data;
>
> -   skb = __dev_alloc_skb(bm_pool->pkt_size, gfp_mask);
> -   if (!skb)
> +   data = mvpp2_frag_alloc(bm_pool);
> +   if (!data)
> return NULL;
>
> -   phys_addr = dma_map_single(port->dev->dev.parent, skb->head,
> +   phys_addr = dma_map_single(port->dev->dev.parent, data,
>MVPP2_RX_BUF_SIZE(bm_pool->pkt_size),
> DMA_FROM_DEVICE);
> if (unlikely(dma_mapping_error(port->dev->dev.parent, phys_addr))) {
> -   dev_kfree_skb_any(skb);
> +   mvpp2_frag_free(bm_pool, data);
> return NULL;
> }
> *buf_phys_addr = phys_addr;
>
> -   return skb;
> +   return data;
>  }
>
>  /* Set pool number in a BM cookie */
> @@ -3620,9 +3637,9 @@ static void mvpp2_pool_refill(struct mvpp2_port *port, 
> u32 bm,
>  static int mvpp2_bm_bufs_add(struct mvpp2_port *port,
>  struct mvpp2_bm_pool *bm_pool, int buf_num)
>  {
> -   struct sk_buff *skb;
> int i, 

[PATCH v2 net-next 2/2] net: mvneta: add BQL support

2017-01-16 Thread Marcin Wojtas
Tests showed that when whole bandwidth is consumed, the latency for
various kind of traffic can reach high values. With saturated
link (e.g. with iperf from target to host) simple ping could take
significant amount of time. BQL proved to improve this situation
when implemented in mvneta driver. Measurements of ping latency
for 3 link speeds:
Speed | Latency w/o BQL | Latency with BQL
10|  7-14 ms| 3.5 ms
100   |  2-12 ms| 0.6 ms
1000  |   often timeout |   up to 2ms

Decreasing latency as above result in sligt performance cost - 4kpps
(-1.4%) when pushing 64B packets via two bridged interfaces of Armada 38x.
For 1500B packets in the same setup, the mpstat tool showed +8% of
CPU occupation (default affinity, second CPU idle). Even though this
cost seems reasonable to take, considering other improvements.

This commit adds byte queue limit mechanism for the mvneta driver.

Signed-off-by: Marcin Wojtas <m...@semihalf.com>
---
 drivers/net/ethernet/marvell/mvneta.c | 22 +++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvneta.c 
b/drivers/net/ethernet/marvell/mvneta.c
index 9624537..6dcc951 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -1759,8 +1759,10 @@ static struct mvneta_tx_queue 
*mvneta_tx_done_policy(struct mvneta_port *pp,
 
 /* Free tx queue skbuffs */
 static void mvneta_txq_bufs_free(struct mvneta_port *pp,
-struct mvneta_tx_queue *txq, int num)
+struct mvneta_tx_queue *txq, int num,
+struct netdev_queue *nq)
 {
+   unsigned int bytes_compl = 0, pkts_compl = 0;
int i;
 
for (i = 0; i < num; i++) {
@@ -1768,6 +1770,11 @@ static void mvneta_txq_bufs_free(struct mvneta_port *pp,
txq->txq_get_index;
struct sk_buff *skb = txq->tx_skb[txq->txq_get_index];
 
+   if (skb) {
+   bytes_compl += skb->len;
+   pkts_compl++;
+   }
+
mvneta_txq_inc_get(txq);
 
if (!IS_TSO_HEADER(txq, tx_desc->buf_phys_addr))
@@ -1778,6 +1785,8 @@ static void mvneta_txq_bufs_free(struct mvneta_port *pp,
continue;
dev_kfree_skb_any(skb);
}
+
+   netdev_tx_completed_queue(nq, pkts_compl, bytes_compl);
 }
 
 /* Handle end of transmission */
@@ -1791,7 +1800,7 @@ static void mvneta_txq_done(struct mvneta_port *pp,
if (!tx_done)
return;
 
-   mvneta_txq_bufs_free(pp, txq, tx_done);
+   mvneta_txq_bufs_free(pp, txq, tx_done, nq);
 
txq->count -= tx_done;
 
@@ -2401,6 +2410,8 @@ static int mvneta_tx(struct sk_buff *skb, struct 
net_device *dev)
struct mvneta_pcpu_stats *stats = this_cpu_ptr(pp->stats);
struct netdev_queue *nq = netdev_get_tx_queue(dev, txq_id);
 
+   netdev_tx_sent_queue(nq, len);
+
txq->count += frags;
if (txq->count >= txq->tx_stop_threshold)
netif_tx_stop_queue(nq);
@@ -2429,9 +2440,10 @@ static void mvneta_txq_done_force(struct mvneta_port *pp,
  struct mvneta_tx_queue *txq)
 
 {
+   struct netdev_queue *nq = netdev_get_tx_queue(pp->dev, txq->id);
int tx_done = txq->count;
 
-   mvneta_txq_bufs_free(pp, txq, tx_done);
+   mvneta_txq_bufs_free(pp, txq, tx_done, nq);
 
/* reset txq */
txq->count = 0;
@@ -2957,6 +2969,8 @@ static int mvneta_txq_init(struct mvneta_port *pp,
 static void mvneta_txq_deinit(struct mvneta_port *pp,
  struct mvneta_tx_queue *txq)
 {
+   struct netdev_queue *nq = netdev_get_tx_queue(pp->dev, txq->id);
+
kfree(txq->tx_skb);
 
if (txq->tso_hdrs)
@@ -2968,6 +2982,8 @@ static void mvneta_txq_deinit(struct mvneta_port *pp,
  txq->size * MVNETA_DESC_ALIGNED_SIZE,
  txq->descs, txq->descs_phys);
 
+   netdev_tx_reset_queue(nq);
+
txq->descs = NULL;
txq->last_desc = 0;
txq->next_desc_to_proc = 0;
-- 
1.8.3.1



[PATCH v2 net-next 1/2] net: mvneta: add xmit_more support

2017-01-16 Thread Marcin Wojtas
From: Simon Guinot <simon.gui...@sequanux.org>

Basing on xmit_more flag of the skb, TX descriptors can be concatenated
before flushing. This commit delay Tx descriptor flush if the queue is
running and if there is more skb's to send.

A maximum allowed number of descriptors for flushing at once due to
MVNETA_TXQ_UPDATE_REG(q) reqisters limitation, is 255. Because of that
a new macro was added (MVNETA_TXQ_DEC_SENT_MASK) in order to ensure that
concatenated amount of descriptor does not exceed that value.

Signed-off-by: Simon Guinot <simon.gui...@sequanux.org>
Signed-off-by: Marcin Wojtas <m...@semihalf.com>
---
 drivers/net/ethernet/marvell/mvneta.c | 13 ++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvneta.c 
b/drivers/net/ethernet/marvell/mvneta.c
index 3607d8f..9624537 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -224,6 +224,7 @@
 #define  MVNETA_TXQ_SENT_THRESH_MASK(coal)   ((coal) << 16)
 #define MVNETA_TXQ_UPDATE_REG(q) (0x3c60 + ((q) << 2))
 #define  MVNETA_TXQ_DEC_SENT_SHIFT   16
+#define  MVNETA_TXQ_DEC_SENT_MASK0xff
 #define MVNETA_TXQ_STATUS_REG(q) (0x3c40 + ((q) << 2))
 #define  MVNETA_TXQ_SENT_DESC_SHIFT  16
 #define  MVNETA_TXQ_SENT_DESC_MASK   0x3fff
@@ -525,6 +526,7 @@ struct mvneta_tx_queue {
 * descriptor ring
 */
int count;
+   int pending;
int tx_stop_threshold;
int tx_wake_threshold;
 
@@ -818,8 +820,9 @@ static void mvneta_txq_pend_desc_add(struct mvneta_port *pp,
/* Only 255 descriptors can be added at once ; Assume caller
 * process TX desriptors in quanta less than 256
 */
-   val = pend_desc;
+   val = pend_desc + txq->pending;
mvreg_write(pp, MVNETA_TXQ_UPDATE_REG(txq->id), val);
+   txq->pending = 0;
 }
 
 /* Get pointer to next TX descriptor to be processed (send) by HW */
@@ -2399,11 +2402,15 @@ static int mvneta_tx(struct sk_buff *skb, struct 
net_device *dev)
struct netdev_queue *nq = netdev_get_tx_queue(dev, txq_id);
 
txq->count += frags;
-   mvneta_txq_pend_desc_add(pp, txq, frags);
-
if (txq->count >= txq->tx_stop_threshold)
netif_tx_stop_queue(nq);
 
+   if (!skb->xmit_more || netif_xmit_stopped(nq) ||
+   txq->pending + frags > MVNETA_TXQ_DEC_SENT_MASK)
+   mvneta_txq_pend_desc_add(pp, txq, frags);
+   else
+   txq->pending += frags;
+
u64_stats_update_begin(>syncp);
stats->tx_packets++;
stats->tx_bytes  += len;
-- 
1.8.3.1



[PATCH v2 net-next 0/2] mvneta xmit_more and bql support

2017-01-16 Thread Marcin Wojtas
Hi,

This is a delayed v2 of short patchset, which introduces xmit_more and BQL
to mvneta driver. The only one change was added in xmit_more support -
condition check preventing excessive descriptors concatenation before
flushing in HW.

Any comments or feedback would be welcome.

Best regards,
Marcin

Changelog:
v1 -> v2:

* Add checking condition that ensures too much descriptors are not
  concatenated before flushing in HW.

Marcin Wojtas (1):
  net: mvneta: add BQL support

Simon Guinot (1):
  net: mvneta: add xmit_more support

 drivers/net/ethernet/marvell/mvneta.c | 35 +--
 1 file changed, 29 insertions(+), 6 deletions(-)

-- 
1.8.3.1



Re: [PATCHv2 net-next 11/16] net: mvpp2: handle misc PPv2.1/PPv2.2 differences

2017-01-07 Thread Marcin Wojtas
Hi Russel,

2017-01-07 12:03 GMT+01:00 Russell King - ARM Linux :
> On Wed, Dec 28, 2016 at 05:46:27PM +0100, Thomas Petazzoni wrote:
>> +#define MVPP22_SMI_MISC_CFG_REG  0x2a204
>> +#define  MVPP22_SMI_POLLING_EN   BIT(10)
>> +
> ...
>> + if (priv->hw_version == MVPP21) {
>> + val = readl(priv->lms_base + MVPP2_PHY_AN_CFG0_REG);
>> + val |= MVPP2_PHY_AN_STOP_SMI0_MASK;
>> + writel(val, priv->lms_base + MVPP2_PHY_AN_CFG0_REG);
>> + } else {
>> + val = readl(priv->iface_base + MVPP22_SMI_MISC_CFG_REG);
>> + val &= ~MVPP22_SMI_POLLING_EN;
>> + writel(val, priv->iface_base + MVPP22_SMI_MISC_CFG_REG);
>> + }
>
> The MVPP22_SMI_MISC_CFG_REG register is within the MDIO driver's
> register set, although the mvmdio driver does not access this register.
> Shouldn't this be taken care of by the mvmdio driver?
>
> Also, a point that I've noticed while reviewing this is the mvmdio
> driver also accesses these registers:
>
> #define MVMDIO_ERR_INT_CAUSE   0x007C
> #define MVMDIO_ERR_INT_MASK0x0080
>
> in addition to the un-named register at offset 0.  The driver writes
> to these registers unconditionally when unbinding:
>
> writel(0, dev->regs + MVMDIO_ERR_INT_MASK);
>
> However, the various bindings for the driver have:
>
> arch/arm/boot/dts/armada-370-xp.dtsi:  compatible = "marvell,orion-mdio";
> arch/arm/boot/dts/armada-370-xp.dtsi-  reg = <0x72004 0x4>;
> arch/arm/boot/dts/armada-375.dtsi: compatible = "marvell,orion-mdio";
> arch/arm/boot/dts/armada-375.dtsi- reg = <0xc0054 0x4>;
> arch/arm/boot/dts/dove.dtsi:   compatible = "marvell,orion-mdio";
> arch/arm/boot/dts/dove.dtsi-   #address-cells = <1>;
> arch/arm/boot/dts/dove.dtsi-   #size-cells = <0>;
> arch/arm/boot/dts/dove.dtsi-   reg = <0x72004 0x84>;
> arch/arm/boot/dts/orion5x.dtsi:compatible = "marvell,orion-mdio";
> arch/arm/boot/dts/orion5x.dtsi-#address-cells = <1>;
> arch/arm/boot/dts/orion5x.dtsi-#size-cells = <0>;
> arch/arm/boot/dts/orion5x.dtsi-reg = <0x72004 0x84>;
> arch/arm/boot/dts/kirkwood.dtsi:   compatible = "marvell,orion-mdio";
> arch/arm/boot/dts/kirkwood.dtsi-   #address-cells = <1>;
> arch/arm/boot/dts/kirkwood.dtsi-   #size-cells = <0>;
> arch/arm/boot/dts/kirkwood.dtsi-   reg = <0x72004 0x84>;
> arch/arm/boot/dts/armada-38x.dtsi: compatible = "marvell,orion-mdio";
> arch/arm/boot/dts/armada-38x.dtsi- reg = <0x72004 0x4>;
>
> So, for many of these, we're accessing registers outside of the given
> binding, which sounds incorrect.  I guess that write should be
> conditional upon an interrupt being present.
>
> The binding document says:
>
> - reg: address and length of the SMI register
>
> which is clearly wrong for those cases where the interrupt is used.
>
> I also notice that the binding for CP110 uses a register size of 0x10
> (even in your tree) - but I guess this should be 4.
>
> I'm starting to wonder whether the orion-mdio driver really is a
> separate chunk of hardware that warrants a separate description in
> DT from the ethernet controller - it appears in all cases to be
> embedded with an ethernet controller, sharing its register space
> and at least some of the ethernet controllers clocks.  That says
> to me that it isn't an independent functional unit of hardware.
>

In fact there is common SMI bus, but each port has its own register
set to control it (it's true at least for Neta and PP2). There is also
an option to use HW polling - every 1s hardware checks PHY over SMI
and updates MAC registers of each port independently. I was able to
use those successfully in other implementations.

However we are supposed to use libphy in Linux and I'm afraid we have
to use single instance that controls single SMI bus - I think current
implementation is a compromise between HW and libphy demands.

Best regards,
Marcin


Re: [PATCH] net: mvpp2: fix dma unmapping of TX buffers for fragments

2016-12-13 Thread Marcin Wojtas
Hi Thomas,

Reviewed-by: Marcin Wojtas <m...@semihalf.com>

Best regards,
Marcin

2016-12-13 17:53 GMT+01:00 Thomas Petazzoni
<thomas.petazz...@free-electrons.com>:
> Since commit 71ce391dfb784 ("net: mvpp2: enable proper per-CPU TX
> buffers unmapping"), we are not correctly DMA unmapping TX buffers for
> fragments.
>
> Indeed, the mvpp2_txq_inc_put() function only stores in the
> txq_cpu->tx_buffs[] array the physical address of the buffer to be
> DMA-unmapped when skb != NULL. In addition, when DMA-unmapping, we use
> skb_headlen(skb) to get the size to be unmapped. Both of this works fine
> for TX descriptors that are associated directly to a SKB, but not the
> ones that are used for fragments, with a NULL pointer as skb:
>
>  - We have a NULL physical address when calling DMA unmap
>  - skb_headlen(skb) crashes because skb is NULL
>
> This causes random crashes when fragments are used.
>
> To solve this problem, this commit:
>
>  - Stores the physical address of the buffer to be unmapped
>unconditionally, regardless of whether it is tied to a SKB or not.
>
>  - Adds a txq_cpu->tx_data_size[] array to store the size of the DMA
>buffer to be unmapped upon TX completion.
>
> Fixes: 71ce391dfb784 ("net: mvpp2: enable proper per-CPU TX buffers 
> unmapping")
> Reported-by: Raphael G <raphael.g...@corp.ovh.com>
> Cc: Raphael G <raphael.g...@corp.ovh.com>
> Cc: sta...@vger.kernel.org
> Signed-off-by: Thomas Petazzoni <thomas.petazz...@free-electrons.com>
> ---
>  drivers/net/ethernet/marvell/mvpp2.c | 20 
>  1 file changed, 16 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/net/ethernet/marvell/mvpp2.c 
> b/drivers/net/ethernet/marvell/mvpp2.c
> index 1026c45..d168b13 100644
> --- a/drivers/net/ethernet/marvell/mvpp2.c
> +++ b/drivers/net/ethernet/marvell/mvpp2.c
> @@ -791,6 +791,8 @@ struct mvpp2_txq_pcpu {
> /* Array of transmitted buffers' physical addresses */
> dma_addr_t *tx_buffs;
>
> +   size_t *tx_data_size;
> +
> /* Index of last TX DMA descriptor that was inserted */
> int txq_put_index;
>
> @@ -980,9 +982,10 @@ static void mvpp2_txq_inc_put(struct mvpp2_txq_pcpu 
> *txq_pcpu,
>   struct mvpp2_tx_desc *tx_desc)
>  {
> txq_pcpu->tx_skb[txq_pcpu->txq_put_index] = skb;
> -   if (skb)
> -   txq_pcpu->tx_buffs[txq_pcpu->txq_put_index] =
> -
> tx_desc->buf_phys_addr;
> +   txq_pcpu->tx_data_size[txq_pcpu->txq_put_index] =
> +   tx_desc->data_size;
> +   txq_pcpu->tx_buffs[txq_pcpu->txq_put_index] =
> +   tx_desc->buf_phys_addr;
> txq_pcpu->txq_put_index++;
> if (txq_pcpu->txq_put_index == txq_pcpu->size)
> txq_pcpu->txq_put_index = 0;
> @@ -4404,11 +4407,13 @@ static void mvpp2_txq_bufs_free(struct mvpp2_port 
> *port,
> dma_addr_t buf_phys_addr =
> 
> txq_pcpu->tx_buffs[txq_pcpu->txq_get_index];
> struct sk_buff *skb = 
> txq_pcpu->tx_skb[txq_pcpu->txq_get_index];
> +   size_t data_size =
> +   txq_pcpu->tx_data_size[txq_pcpu->txq_get_index];
>
> mvpp2_txq_inc_get(txq_pcpu);
>
> dma_unmap_single(port->dev->dev.parent, buf_phys_addr,
> -skb_headlen(skb), DMA_TO_DEVICE);
> +data_size, DMA_TO_DEVICE);
> if (!skb)
> continue;
> dev_kfree_skb_any(skb);
> @@ -4662,6 +4667,11 @@ static int mvpp2_txq_init(struct mvpp2_port *port,
> if (!txq_pcpu->tx_buffs)
> goto error;
>
> +   txq_pcpu->tx_data_size = kmalloc(txq_pcpu->size *
> +sizeof(size_t), GFP_KERNEL);
> +   if (!txq_pcpu->tx_data_size)
> +   goto error;
> +
> txq_pcpu->count = 0;
> txq_pcpu->reserved_num = 0;
> txq_pcpu->txq_put_index = 0;
> @@ -4675,6 +4685,7 @@ static int mvpp2_txq_init(struct mvpp2_port *port,
> txq_pcpu = per_cpu_ptr(txq->pcpu, cpu);
> kfree(txq_pcpu->tx_skb);
> kfree(txq_pcpu->tx_buffs);
> +   kfree(txq_pcpu->tx_data_size);
> }
>
> dma_free_coherent(port->dev->dev.parent,
> @@ -4695,6 +4706,7 @@ static void mvpp2_txq_deinit(struct mvpp2_port *port,
> txq_pcpu = per_cpu_ptr(txq->pcpu, cpu);
> kfree(txq_pcpu->tx_skb);
> kfree(txq_pcpu->tx_buffs);
> +   kfree(txq_pcpu->tx_data_size);
> }
>
> if (txq->descs)
> --
> 2.7.4
>


Re: [PATCH v5 net-next 0/7] Support Armada 37xx SoC (ARMv8 64-bits) in mvneta driver

2016-12-01 Thread Marcin Wojtas
Hi Gregory,

Checked on a388-gp with and without HWBM, also both ports work on
a3700 (second one after changing to sgmii).

Tested-by: Marcin Wojtas <m...@semihalf.com>

Best regards,
Marcin

2016-11-30 22:42 GMT+01:00 Gregory CLEMENT <gregory.clem...@free-electrons.com>:
> Hi,
>
> The Armada 37xx is a new ARMv8 SoC from Marvell using same network
> controller as the older Armada 370/38x/XP SoCs. This series adapts the
> driver in order to be able to use it on this new SoC. The main changes
> are:
>
> - 64-bits support: the first patches allow using the driver on a 64-bit
>   architecture.
>
> - MBUS support: the mbus configuration is different on Armada 37xx
>   from the older SoCs.
>
> - per cpu interrupt: Armada 37xx do not support per cpu interrupt for
>   the NETA IP, the non-per-CPU behavior was added back.
>
> The first patch is an optimization in the rx path in swbm mode.
> The second patch remove unnecessary allocation for HWBM.
> The first item is solved by patches 4 and 5.
> The 2 last items are solved by patch 6.
> In patch 7 the dt support is added.
>
> Beside Armada 37xx, this series have been again tested on Armada XP
> and Armada 38x (with Hardware Buffer Management and with Software
> Buffer Management).
>
> This is the 5th version of the series:
> - 1st version:
> http://lists.infradead.org/pipermail/linux-arm-kernel/2016-November/469588.html
>
> - 2nd version:
> http://lists.infradead.org/pipermail/linux-arm-kernel/2016-November/470476.html
>
> - 3rd version:
> http://lists.infradead.org/pipermail/linux-arm-kernel/2016-November/470901.html
>
> - 4th version:
> http://lists.infradead.org/pipermail/linux-arm-kernel/2016-November/471039.html
>
> Changelog:
> v4 -> v5:
>  - remove unnecessary cast in patch 3
>
> v3 -> v4:
>  - Adding new patch: "net: mvneta: do not allocate buffer in rxq init
>with HWBM"
>
>  - Simplify the HWBM case in patch 3 as suggested by Marcin
>
> v2 -> v3:
>  - Adding patch 1 "Optimize rx path for small frame"
>
>  - Fix the kbuild error by moving the "phys_addr += pp->rx_offset_correction;"
>   line from patch 2 to patch 3 where rx_offset_correction is introduced.
>
>  - Move the memory allocation of the buf_virt_addr of the rxq to be
>called by the probe function in order to avoid a memory leak.
>
> Thanks,
>
> Gregory
>
> Gregory CLEMENT (5):
>   net: mvneta: Optimize rx path for small frame
>   net: mvneta: Do not allocate buffer in rxq init with HWBM
>   net: mvneta: Use cacheable memory to store the rx buffer virtual address
>   net: mvneta: Only disable mvneta_bm for 64-bits
>   ARM64: dts: marvell: Add network support for Armada 3700
>
> Marcin Wojtas (2):
>   net: mvneta: Convert to be 64 bits compatible
>   net: mvneta: Add network support for Armada 3700 SoC
>
>  Documentation/devicetree/bindings/net/marvell-armada-370-neta.txt |   7 +-
>  arch/arm64/boot/dts/marvell/armada-3720-db.dts|  23 
> +-
>  arch/arm64/boot/dts/marvell/armada-37xx.dtsi  |  23 
> +-
>  drivers/net/ethernet/marvell/Kconfig  |  10 +-
>  drivers/net/ethernet/marvell/mvneta.c | 344 
> +++-
>  5 files changed, 305 insertions(+), 102 deletions(-)
>
> base-commit: 436accebb53021ef7c63535f60bda410aa87c136
> --
> git-series 0.8.10


Re: [PATCH v5 net-next 7/7] ARM64: dts: marvell: Add network support for Armada 3700

2016-12-01 Thread Marcin Wojtas
Hi Gregory,

2016-11-30 22:42 GMT+01:00 Gregory CLEMENT :
> Add neta nodes for network support both in device tree for the SoC and
> the board.
>
> Signed-off-by: Gregory CLEMENT 
> ---
>  arch/arm64/boot/dts/marvell/armada-3720-db.dts | 23 +++-
>  arch/arm64/boot/dts/marvell/armada-37xx.dtsi   | 23 +++-
>  2 files changed, 46 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm64/boot/dts/marvell/armada-3720-db.dts 
> b/arch/arm64/boot/dts/marvell/armada-3720-db.dts
> index 1372e9a6aaa4..c8b82e4145de 100644
> --- a/arch/arm64/boot/dts/marvell/armada-3720-db.dts
> +++ b/arch/arm64/boot/dts/marvell/armada-3720-db.dts
> @@ -81,3 +81,26 @@
>   {
> status = "okay";
>  };
> +
> + {
> +   status = "okay";
> +   phy0: ethernet-phy@0 {
> +   reg = <0>;
> +   };
> +
> +   phy1: ethernet-phy@1 {
> +   reg = <1>;
> +   };
> +};
> +
> + {
> +   phy-mode = "rgmii-id";
> +   phy = <>;
> +   status = "okay";
> +};
> +
> + {
> +   phy-mode = "rgmii-id";

Should be "sgmii".

Best regards,
Marcin


Re: [PATCH v5 net-next 4/7] net: mvneta: Convert to be 64 bits compatible

2016-12-01 Thread Marcin Wojtas
Hi Jisheng,

2016-12-01 13:16 GMT+01:00 Jisheng Zhang <jszh...@marvell.com>:
> On Thu, 1 Dec 2016 20:02:05 +0800 Jisheng Zhang wrote:
>
>> Hi Marcin,
>>
>> On Thu, 1 Dec 2016 12:48:39 +0100 Marcin Wojtas wrote:
>>
>> > Hi Jisheng,
>> >
>> > Which baseline do you use?
>> >
>> > It took me really lot of time to catch why RX broke after rebase from
>> > LKv4.1 to LKv4.4. Between those two, in commit:
>> > 97303480753e ("arm64: Increase the max granular size")
>> > L1_CACHE_BYTES for all ARMv8 platforms was increased to 128B and so
>> > did NET_SKB_PAD.
>> >
>> > And 128 is more than the maximum that can fit into packet offset
>> > [11:8]@0x1400. In such case this correction is needed. Did it answer
>> > your doubts?
>>
>> That's key! Thanks a lot. In my repo, we don't have commit 97303480753e
>> ("arm64: Increase the max granular size")
>>
>> I think it would be great if this information can be added into the commit
>> msg.
>>
>> IIRC, arm64 maintainers considered to let L1_CACHE_BYTES the _minimum_ of
>> cache line sizes of arm64. If that's implemented and merged, then we can
>
> I just searched and found the email.
>
> "We may have to revisit this logic and consider L1_CACHE_BYTES the
> _minimum_ of cache line sizes in arm64 systems supported by the kernel.
> Do you have any benchmarks on Cavium boards that would show significant
> degradation with 64-byte L1_CACHE_BYTES vs 128?"
>
> https://patchwork.kernel.org/patch/8634481/
>
>

Thank you for the information. I debugged it before the discussion. In
future we would be able to revert it, however afair packet offset may
be needed by A3700 Buffer Management.

Best regards,
Marcin


Re: [PATCH v5 net-next 4/7] net: mvneta: Convert to be 64 bits compatible

2016-12-01 Thread Marcin Wojtas
Hi Jisheng,

Which baseline do you use?

It took me really lot of time to catch why RX broke after rebase from
LKv4.1 to LKv4.4. Between those two, in commit:
97303480753e ("arm64: Increase the max granular size")
L1_CACHE_BYTES for all ARMv8 platforms was increased to 128B and so
did NET_SKB_PAD.

And 128 is more than the maximum that can fit into packet offset
[11:8]@0x1400. In such case this correction is needed. Did it answer
your doubts?

Best regards,
Marcin



2016-12-01 12:26 GMT+01:00 Jisheng Zhang <jszh...@marvell.com>:
> Hi Gregory, Marcin,
>
> On Wed, 30 Nov 2016 22:42:49 +0100 Gregory CLEMENT wrote:
>
>> From: Marcin Wojtas <m...@semihalf.com>
>>
>> Prepare the mvneta driver in order to be usable on the 64 bits platform
>> such as the Armada 3700.
>>
>> [gregory.clem...@free-electrons.com]: this patch was extract from a larger
>> one to ease review and maintenance.
>>
>> Signed-off-by: Marcin Wojtas <m...@semihalf.com>
>> Signed-off-by: Gregory CLEMENT <gregory.clem...@free-electrons.com>
>> ---
>>  drivers/net/ethernet/marvell/mvneta.c | 17 -
>>  1 file changed, 16 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/net/ethernet/marvell/mvneta.c 
>> b/drivers/net/ethernet/marvell/mvneta.c
>> index 92b9af14c352..8ef03fb69bcd 100644
>> --- a/drivers/net/ethernet/marvell/mvneta.c
>> +++ b/drivers/net/ethernet/marvell/mvneta.c
>> @@ -296,6 +296,12 @@
>>  /* descriptor aligned size */
>>  #define MVNETA_DESC_ALIGNED_SIZE 32
>>
>> +/* Number of bytes to be taken into account by HW when putting incoming data
>> + * to the buffers. It is needed in case NET_SKB_PAD exceeds maximum packet
>> + * offset supported in MVNETA_RXQ_CONFIG_REG(q) registers.
>
> We also brought up this driver on 64bit platforms, we doesn't have this
> patch. Maybe I'm wrong, I'm trying to understand why we need this
> modification. Let's assume the NET_SKB_PAD is 64B, we call
> mvneta_rxq_offset_set(pp, rxq, 64),
>
> {
> u32 val;
>
> val = mvreg_read(pp, MVNETA_RXQ_CONFIG_REG(rxq->id));
> val &= ~MVNETA_RXQ_PKT_OFFSET_ALL_MASK;
>
> /* Offset is in */
> val |= MVNETA_RXQ_PKT_OFFSET_MASK(offset >> 3);
> // then this will be "val |= 8;" it doesn't exceeds the max offset of
> MVNETA_RXQ_CONFIG_REG(q) register.
>
> Could you please kindly point out where I am wrong?
>
>> + */
>> +#define MVNETA_RX_PKT_OFFSET_CORRECTION  64
>> +
>>  #define MVNETA_RX_PKT_SIZE(mtu) \
>>   ALIGN((mtu) + MVNETA_MH_SIZE + MVNETA_VLAN_TAG_LEN + \
>> ETH_HLEN + ETH_FCS_LEN,\
>> @@ -416,6 +422,7 @@ struct mvneta_port {
>>   u64 ethtool_stats[ARRAY_SIZE(mvneta_statistics)];
>>
>>   u32 indir[MVNETA_RSS_LU_TABLE_SIZE];
>> + u16 rx_offset_correction;
>>  };
>>
>>  /* The mvneta_tx_desc and mvneta_rx_desc structures describe the
>> @@ -1807,6 +1814,7 @@ static int mvneta_rx_refill(struct mvneta_port *pp,
>>   return -ENOMEM;
>>   }
>>
>> + phys_addr += pp->rx_offset_correction;
>>   mvneta_rx_desc_fill(rx_desc, phys_addr, data, rxq);
>>   return 0;
>>  }
>> @@ -2782,7 +2790,7 @@ static int mvneta_rxq_init(struct mvneta_port *pp,
>>   mvreg_write(pp, MVNETA_RXQ_SIZE_REG(rxq->id), rxq->size);
>>
>>   /* Set Offset */
>> - mvneta_rxq_offset_set(pp, rxq, NET_SKB_PAD);
>> + mvneta_rxq_offset_set(pp, rxq, NET_SKB_PAD - pp->rx_offset_correction);
>>
>>   /* Set coalescing pkts and time */
>>   mvneta_rx_pkts_coal_set(pp, rxq, rxq->pkts_coal);
>> @@ -4033,6 +4041,13 @@ static int mvneta_probe(struct platform_device *pdev)
>>
>>   pp->rxq_def = rxq_def;
>>
>> + /* Set RX packet offset correction for platforms, whose
>> +  * NET_SKB_PAD, exceeds 64B. It should be 64B for 64-bit
>> +  * platforms and 0B for 32-bit ones.
>
> Even we need this patch, I'm not sure this last comment is correct or not.
> NET_SKB_PAD is defined as:
>
> #define NET_SKB_PAD max(32, L1_CACHE_BYTES)
>
> we have 64B cacheline 32bit platforms, on this platforms, the NET_SKB_PAD
> should be 64B as well.
>
> Thanks,
> Jisheng


Re: [PATCH v3 net-next 2/6] net: mvneta: Use cacheable memory to store the rx buffer virtual address

2016-11-29 Thread Marcin Wojtas
Gregory,

2016-11-29 11:19 GMT+01:00 Gregory CLEMENT <gregory.clem...@free-electrons.com>:
> Hi Marcin,
>
>  On mar., nov. 29 2016, Marcin Wojtas <m...@semihalf.com> wrote:
>
>> Hi Gregory,
>>
>> Another remark below, sorry for noise.
>>
>> 2016-11-29 10:37 GMT+01:00 Gregory CLEMENT 
>> <gregory.clem...@free-electrons.com>:
>>> Until now the virtual address of the received buffer were stored in the
>>> cookie field of the rx descriptor. However, this field is 32-bits only
>>> which prevents to use the driver on a 64-bits architecture.
>>>
>>> With this patch the virtual address is stored in an array not shared with
>>> the hardware (no more need to use the DMA API). Thanks to this, it is
>>> possible to use cache contrary to the access of the rx descriptor member.
>>>
>>> The change is done in the swbm path only because the hwbm uses the cookie
>>> field, this also means that currently the hwbm is not usable in 64-bits.
>>>
>>> Signed-off-by: Gregory CLEMENT <gregory.clem...@free-electrons.com>
>>> ---
>>>  drivers/net/ethernet/marvell/mvneta.c | 93 
>>>  1 file changed, 81 insertions(+), 12 deletions(-)
>>>
>>> diff --git a/drivers/net/ethernet/marvell/mvneta.c 
>>> b/drivers/net/ethernet/marvell/mvneta.c
>>> index 1b84f746d748..32b142d0e44e 100644
>>> --- a/drivers/net/ethernet/marvell/mvneta.c
>>> +++ b/drivers/net/ethernet/marvell/mvneta.c
>>> @@ -561,6 +561,9 @@ struct mvneta_rx_queue {
>>> u32 pkts_coal;
>>> u32 time_coal;
>>>
>>> +   /* Virtual address of the RX buffer */
>>> +   void  **buf_virt_addr;
>>> +
>>> /* Virtual address of the RX DMA descriptors array */
>>> struct mvneta_rx_desc *descs;
>>>
>>> @@ -1573,10 +1576,14 @@ static void mvneta_tx_done_pkts_coal_set(struct 
>>> mvneta_port *pp,
>>>
>>>  /* Handle rx descriptor fill by setting buf_cookie and buf_phys_addr */
>>>  static void mvneta_rx_desc_fill(struct mvneta_rx_desc *rx_desc,
>>> -   u32 phys_addr, u32 cookie)
>>> +   u32 phys_addr, void *virt_addr,
>>> +   struct mvneta_rx_queue *rxq)
>>>  {
>>> -   rx_desc->buf_cookie = cookie;
>>> +   int i;
>>> +
>>> rx_desc->buf_phys_addr = phys_addr;
>>> +   i = rx_desc - rxq->descs;
>>> +   rxq->buf_virt_addr[i] = virt_addr;
>>>  }
>>>
>>>  /* Decrement sent descriptors counter */
>>> @@ -1781,7 +1788,8 @@ EXPORT_SYMBOL_GPL(mvneta_frag_free);
>>>
>>>  /* Refill processing for SW buffer management */
>>>  static int mvneta_rx_refill(struct mvneta_port *pp,
>>> -   struct mvneta_rx_desc *rx_desc)
>>> +   struct mvneta_rx_desc *rx_desc,
>>> +   struct mvneta_rx_queue *rxq)
>>>
>>>  {
>>> dma_addr_t phys_addr;
>>> @@ -1799,7 +1807,7 @@ static int mvneta_rx_refill(struct mvneta_port *pp,
>>> return -ENOMEM;
>>> }
>>>
>>> -   mvneta_rx_desc_fill(rx_desc, phys_addr, (u32)data);
>>> +   mvneta_rx_desc_fill(rx_desc, phys_addr, data, rxq);
>>> return 0;
>>>  }
>>>
>>> @@ -1861,7 +1869,12 @@ static void mvneta_rxq_drop_pkts(struct mvneta_port 
>>> *pp,
>>>
>>> for (i = 0; i < rxq->size; i++) {
>>> struct mvneta_rx_desc *rx_desc = rxq->descs + i;
>>> -   void *data = (void *)rx_desc->buf_cookie;
>>> +   void *data;
>>> +
>>> +   if (!pp->bm_priv)
>>> +   data = rxq->buf_virt_addr[i];
>>> +   else
>>> +   data = (void *)(uintptr_t)rx_desc->buf_cookie;
>>
>> Dropping packets for HWBM (in fact returning dropped buffers to the
>> pool) is done a couple of lines above. This point will never be
>
> indeed I changed the code at every place the buf_cookie was used and
> missed the fact that for HWBM this code was never reached.
>
>> reached with HWBM enabled (and it's also incorrect).
>
> What is incorrect?
>

Possible dma_unmapping + mvneta_frag_free for buffers in HWBM, when
dropping packets.

Thanks,
Marcin


Re: [PATCH v3 net-next 2/6] net: mvneta: Use cacheable memory to store the rx buffer virtual address

2016-11-29 Thread Marcin Wojtas
Hi Gregory,

Another remark below, sorry for noise.

2016-11-29 10:37 GMT+01:00 Gregory CLEMENT :
> Until now the virtual address of the received buffer were stored in the
> cookie field of the rx descriptor. However, this field is 32-bits only
> which prevents to use the driver on a 64-bits architecture.
>
> With this patch the virtual address is stored in an array not shared with
> the hardware (no more need to use the DMA API). Thanks to this, it is
> possible to use cache contrary to the access of the rx descriptor member.
>
> The change is done in the swbm path only because the hwbm uses the cookie
> field, this also means that currently the hwbm is not usable in 64-bits.
>
> Signed-off-by: Gregory CLEMENT 
> ---
>  drivers/net/ethernet/marvell/mvneta.c | 93 
>  1 file changed, 81 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/net/ethernet/marvell/mvneta.c 
> b/drivers/net/ethernet/marvell/mvneta.c
> index 1b84f746d748..32b142d0e44e 100644
> --- a/drivers/net/ethernet/marvell/mvneta.c
> +++ b/drivers/net/ethernet/marvell/mvneta.c
> @@ -561,6 +561,9 @@ struct mvneta_rx_queue {
> u32 pkts_coal;
> u32 time_coal;
>
> +   /* Virtual address of the RX buffer */
> +   void  **buf_virt_addr;
> +
> /* Virtual address of the RX DMA descriptors array */
> struct mvneta_rx_desc *descs;
>
> @@ -1573,10 +1576,14 @@ static void mvneta_tx_done_pkts_coal_set(struct 
> mvneta_port *pp,
>
>  /* Handle rx descriptor fill by setting buf_cookie and buf_phys_addr */
>  static void mvneta_rx_desc_fill(struct mvneta_rx_desc *rx_desc,
> -   u32 phys_addr, u32 cookie)
> +   u32 phys_addr, void *virt_addr,
> +   struct mvneta_rx_queue *rxq)
>  {
> -   rx_desc->buf_cookie = cookie;
> +   int i;
> +
> rx_desc->buf_phys_addr = phys_addr;
> +   i = rx_desc - rxq->descs;
> +   rxq->buf_virt_addr[i] = virt_addr;
>  }
>
>  /* Decrement sent descriptors counter */
> @@ -1781,7 +1788,8 @@ EXPORT_SYMBOL_GPL(mvneta_frag_free);
>
>  /* Refill processing for SW buffer management */
>  static int mvneta_rx_refill(struct mvneta_port *pp,
> -   struct mvneta_rx_desc *rx_desc)
> +   struct mvneta_rx_desc *rx_desc,
> +   struct mvneta_rx_queue *rxq)
>
>  {
> dma_addr_t phys_addr;
> @@ -1799,7 +1807,7 @@ static int mvneta_rx_refill(struct mvneta_port *pp,
> return -ENOMEM;
> }
>
> -   mvneta_rx_desc_fill(rx_desc, phys_addr, (u32)data);
> +   mvneta_rx_desc_fill(rx_desc, phys_addr, data, rxq);
> return 0;
>  }
>
> @@ -1861,7 +1869,12 @@ static void mvneta_rxq_drop_pkts(struct mvneta_port 
> *pp,
>
> for (i = 0; i < rxq->size; i++) {
> struct mvneta_rx_desc *rx_desc = rxq->descs + i;
> -   void *data = (void *)rx_desc->buf_cookie;
> +   void *data;
> +
> +   if (!pp->bm_priv)
> +   data = rxq->buf_virt_addr[i];
> +   else
> +   data = (void *)(uintptr_t)rx_desc->buf_cookie;

Dropping packets for HWBM (in fact returning dropped buffers to the
pool) is done a couple of lines above. This point will never be
reached with HWBM enabled (and it's also incorrect).

Best regards,
Marcin


Re: [PATCH v3 net-next 2/6] net: mvneta: Use cacheable memory to store the rx buffer virtual address

2016-11-29 Thread Marcin Wojtas
Hi Gregory,

Apparently HWBM had a mistake in implementation, please see below.

2016-11-29 10:37 GMT+01:00 Gregory CLEMENT :
> Until now the virtual address of the received buffer were stored in the
> cookie field of the rx descriptor. However, this field is 32-bits only
> which prevents to use the driver on a 64-bits architecture.
>
> With this patch the virtual address is stored in an array not shared with
> the hardware (no more need to use the DMA API). Thanks to this, it is
> possible to use cache contrary to the access of the rx descriptor member.
>
> The change is done in the swbm path only because the hwbm uses the cookie
> field, this also means that currently the hwbm is not usable in 64-bits.
>
> Signed-off-by: Gregory CLEMENT 
> ---
>  drivers/net/ethernet/marvell/mvneta.c | 93 
>  1 file changed, 81 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/net/ethernet/marvell/mvneta.c 
> b/drivers/net/ethernet/marvell/mvneta.c
> index 1b84f746d748..32b142d0e44e 100644
> --- a/drivers/net/ethernet/marvell/mvneta.c
> +++ b/drivers/net/ethernet/marvell/mvneta.c
> @@ -561,6 +561,9 @@ struct mvneta_rx_queue {
> u32 pkts_coal;
> u32 time_coal;
>
> +   /* Virtual address of the RX buffer */
> +   void  **buf_virt_addr;
> +
> /* Virtual address of the RX DMA descriptors array */
> struct mvneta_rx_desc *descs;
>
> @@ -1573,10 +1576,14 @@ static void mvneta_tx_done_pkts_coal_set(struct 
> mvneta_port *pp,
>
>  /* Handle rx descriptor fill by setting buf_cookie and buf_phys_addr */
>  static void mvneta_rx_desc_fill(struct mvneta_rx_desc *rx_desc,
> -   u32 phys_addr, u32 cookie)
> +   u32 phys_addr, void *virt_addr,
> +   struct mvneta_rx_queue *rxq)
>  {
> -   rx_desc->buf_cookie = cookie;
> +   int i;
> +
> rx_desc->buf_phys_addr = phys_addr;
> +   i = rx_desc - rxq->descs;
> +   rxq->buf_virt_addr[i] = virt_addr;
>  }
>
>  /* Decrement sent descriptors counter */
> @@ -1781,7 +1788,8 @@ EXPORT_SYMBOL_GPL(mvneta_frag_free);
>
>  /* Refill processing for SW buffer management */
>  static int mvneta_rx_refill(struct mvneta_port *pp,
> -   struct mvneta_rx_desc *rx_desc)
> +   struct mvneta_rx_desc *rx_desc,
> +   struct mvneta_rx_queue *rxq)
>
>  {
> dma_addr_t phys_addr;
> @@ -1799,7 +1807,7 @@ static int mvneta_rx_refill(struct mvneta_port *pp,
> return -ENOMEM;
> }
>
> -   mvneta_rx_desc_fill(rx_desc, phys_addr, (u32)data);
> +   mvneta_rx_desc_fill(rx_desc, phys_addr, data, rxq);
> return 0;
>  }
>
> @@ -1861,7 +1869,12 @@ static void mvneta_rxq_drop_pkts(struct mvneta_port 
> *pp,
>
> for (i = 0; i < rxq->size; i++) {
> struct mvneta_rx_desc *rx_desc = rxq->descs + i;
> -   void *data = (void *)rx_desc->buf_cookie;
> +   void *data;
> +
> +   if (!pp->bm_priv)
> +   data = rxq->buf_virt_addr[i];
> +   else
> +   data = (void *)(uintptr_t)rx_desc->buf_cookie;
>
> dma_unmap_single(pp->dev->dev.parent, rx_desc->buf_phys_addr,
>  MVNETA_RX_BUF_SIZE(pp->pkt_size), 
> DMA_FROM_DEVICE);
> @@ -1894,12 +1907,13 @@ static int mvneta_rx_swbm(struct mvneta_port *pp, int 
> rx_todo,
> unsigned char *data;
> dma_addr_t phys_addr;
> u32 rx_status, frag_size;
> -   int rx_bytes, err;
> +   int rx_bytes, err, index;
>
> rx_done++;
> rx_status = rx_desc->status;
> rx_bytes = rx_desc->data_size - (ETH_FCS_LEN + 
> MVNETA_MH_SIZE);
> -   data = (unsigned char *)rx_desc->buf_cookie;
> +   index = rx_desc - rxq->descs;
> +   data = (unsigned char *)rxq->buf_virt_addr[index];
> phys_addr = rx_desc->buf_phys_addr;
>
> if (!mvneta_rxq_desc_is_first_last(rx_status) ||
> @@ -1938,7 +1952,7 @@ static int mvneta_rx_swbm(struct mvneta_port *pp, int 
> rx_todo,
> }
>
> /* Refill processing */
> -   err = mvneta_rx_refill(pp, rx_desc);
> +   err = mvneta_rx_refill(pp, rx_desc, rxq);
> if (err) {
> netdev_err(dev, "Linux processing - Can't refill\n");
> rxq->missed++;
> @@ -2020,7 +2034,7 @@ static int mvneta_rx_hwbm(struct mvneta_port *pp, int 
> rx_todo,
> rx_done++;
> rx_status = rx_desc->status;
> rx_bytes = rx_desc->data_size - (ETH_FCS_LEN + 
> MVNETA_MH_SIZE);
> -   data = (unsigned char *)rx_desc->buf_cookie;
> +   data = (u8 

Re: [PATCH net-next 1/4] net: mvneta: Convert to be 64 bits compatible

2016-11-24 Thread Marcin Wojtas
Hi Gregory,

2016-11-24 16:01 GMT+01:00 Gregory CLEMENT :
> Hi Arnd,
>
>  On jeu., nov. 24 2016, Arnd Bergmann  wrote:
>
>> On Thursday, November 24, 2016 4:37:36 PM CET Jisheng Zhang wrote:
>>> solB (a SW shadow cookie) perhaps gives a better performance: in hot path,
>>> such as mvneta_rx(), the driver accesses buf_cookie and buf_phys_addr of
>>> rx_desc which is allocated by dma_alloc_coherent, it's noncacheable if the
>>> device isn't cache-coherent. I didn't measure the performance difference,
>>> because in fact we take solA as well internally. From your experience,
>>> can the performance gain deserve the complex code?
>>
>> Yes, a read from uncached memory is fairly slow, so if you have a chance
>> to avoid that it will probably help. When adding complexity to the code,
>> it probably makes sense to take a runtime profile anyway quantify how
>> much it gains.
>>
>> On machines that have cache-coherent DMA, accessing the descriptor
>> should be fine, as you already have to load the entire cache line
>> to read the status field.
>>
>> Looking at this snippet:
>>
>> rx_status = rx_desc->status;
>> rx_bytes = rx_desc->data_size - (ETH_FCS_LEN + 
>> MVNETA_MH_SIZE);
>> data = (unsigned char *)rx_desc->buf_cookie;
>> phys_addr = rx_desc->buf_phys_addr;
>> pool_id = MVNETA_RX_GET_BM_POOL_ID(rx_desc);
>> bm_pool = >bm_priv->bm_pools[pool_id];
>>
>> if (!mvneta_rxq_desc_is_first_last(rx_status) ||
>> (rx_status & MVNETA_RXD_ERR_SUMMARY)) {
>> err_drop_frame_ret_pool:
>> /* Return the buffer to the pool */
>> mvneta_bm_pool_put_bp(pp->bm_priv, bm_pool,
>>   rx_desc->buf_phys_addr);
>> err_drop_frame:
>>
>>
>> I think there is more room for optimizing if you start: you read
>> the status field twice (the second one in MVNETA_RX_GET_BM_POOL_ID)
>> and you can cache the buf_phys_addr along with the virtual address
>> once you add that.
>
> I agree we can optimize this code but it is not related to the 64 bits
> conversion. Indeed this part is running when we use the HW buffer
> management, however currently this part is not ready at all for 64
> bits. The virtual address is directly handled by the hardware but it has
> only 32 bits to store it in the cookie. So if we want to use the HWBM in
> 64 bits we need to redesign the code, (maybe by storing the virtual
> address in a array and pass the index in the cookie).
>

How about storing data (virt address and maybe other stuff) as a part
of data buffer and using rx_packet_offset? It has to be used for a3700
anyway. No need of additional rings whatsoever.

Best regards,
Marcin


Re: [PATCH net-next 1/4] net: mvneta: Convert to be 64 bits compatible

2016-11-23 Thread Marcin Wojtas
Hi Gregory,

2016-11-23 14:07 GMT+01:00 Gregory CLEMENT :
> Hi Jisheng, Arnd,
>
>
> Thanks for your feedback.
>
>
>  On mer., nov. 23 2016, Arnd Bergmann  wrote:
>
>> On Wednesday, November 23, 2016 5:53:41 PM CET Jisheng Zhang wrote:
>>> On Tue, 22 Nov 2016 22:04:12 +0100 Arnd Bergmann wrote:
>>>
>>> > On Tuesday, November 22, 2016 5:48:41 PM CET Gregory CLEMENT wrote:
>>> > > +#ifdef CONFIG_64BIT
>>> > > +   void *data_tmp;
>>> > > +
>>> > > +   /* In Neta HW only 32 bits data is supported, so in order to
>>> > > +* obtain whole 64 bits address from RX descriptor, we store
>>> > > +* the upper 32 bits when allocating buffer, and put it back
>>> > > +* when using buffer cookie for accessing packet in memory.
>>> > > +* Frags should be allocated from single 'memory' region,
>>> > > +* hence common upper address half should be sufficient.
>>> > > +*/
>>> > > +   data_tmp = mvneta_frag_alloc(pp->frag_size);
>>> > > +   if (data_tmp) {
>>> > > +   pp->data_high = (u64)upper_32_bits((u64)data_tmp) << 32;
>>> > > +   mvneta_frag_free(pp->frag_size, data_tmp);
>>> > > +   }
>>> > >
>>> >
>>> > How does this work when the region spans a n*4GB address boundary?
>>>
>>> indeed. We also make use of this driver on 64bit platforms. We use
>>> different solution to make the driver 64bit safe.
>>>
>>> solA: make use of the reserved field in the mvneta_rx_desc, such
>>> as reserved2 etc. Yes, the field is marked as "for future use, PnC", but
>>> now it's not used at all. This is one possible solution however.
>>
>> Right, this sounds like the most straightforward choice.
>
> The PnC (which stands for Parsing and Classification) is not used yet
> indeed but this field will be needed when we will enable it. It is
> something we want to do but it is not planned in a near future. However
> from the datasheets I have it seems only present on the Armada XP. It is
> not mentioned on datasheets for the Armada 38x or the Armada 3700.
>

It is not mentioned in A38x spec, but this SoC has exactly the same
PnC as Armada XP (they differ only with used SRAM details). I wouldn't
be surprised if it was supported on A3700 as well.

> That would mean it was safe to use on of this field in 64-bits mode on
> the Armada 3700.
>
> So I am going to take this approach.
>

I think for now it's safe and is much easier than handling extra
software ring for virtual addresses.

Best regards,
Marcin


[PATCH net-next 0/2] mvneta xmit_more and bql support

2016-09-13 Thread Marcin Wojtas
Hi,

This short patchset introduces two enhancements to mvneta driver
TX packets concatenation support using xmit_more mechanism and also
byte queue limit in order to decrease latency on saturated links.

Any comments or feedback would be welcome.

Best regards,
Marcin

Marcin Wojtas (1):
  net: mvneta: add BQL support

Simon Guinot (1):
  net: mvneta: add xmit_more support

 drivers/net/ethernet/marvell/mvneta.c | 33 +++--
 1 file changed, 27 insertions(+), 6 deletions(-)

-- 
1.8.3.1



[PATCH net-next 1/2] net: mvneta: add xmit_more support

2016-09-13 Thread Marcin Wojtas
From: Simon Guinot 

Basing on xmit_more flag of the skb, TX descriptors can be concatenated
before flushing. This commit delay Tx descriptor flush if the queue is
running and if there is more skb's to send.

Signed-off-by: Simon Guinot 
---
 drivers/net/ethernet/marvell/mvneta.c | 11 ---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvneta.c 
b/drivers/net/ethernet/marvell/mvneta.c
index d41c28d..b9dccea 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -512,6 +512,7 @@ struct mvneta_tx_queue {
 * descriptor ring
 */
int count;
+   int pending;
int tx_stop_threshold;
int tx_wake_threshold;
 
@@ -802,8 +803,9 @@ static void mvneta_txq_pend_desc_add(struct mvneta_port *pp,
/* Only 255 descriptors can be added at once ; Assume caller
 * process TX desriptors in quanta less than 256
 */
-   val = pend_desc;
+   val = pend_desc + txq->pending;
mvreg_write(pp, MVNETA_TXQ_UPDATE_REG(txq->id), val);
+   txq->pending = 0;
 }
 
 /* Get pointer to next TX descriptor to be processed (send) by HW */
@@ -2357,11 +2359,14 @@ out:
struct netdev_queue *nq = netdev_get_tx_queue(dev, txq_id);
 
txq->count += frags;
-   mvneta_txq_pend_desc_add(pp, txq, frags);
-
if (txq->count >= txq->tx_stop_threshold)
netif_tx_stop_queue(nq);
 
+   if (!skb->xmit_more || netif_xmit_stopped(nq))
+   mvneta_txq_pend_desc_add(pp, txq, frags);
+   else
+   txq->pending += frags;
+
u64_stats_update_begin(>syncp);
stats->tx_packets++;
stats->tx_bytes  += len;
-- 
1.8.3.1



[PATCH net-next 2/2] net: mvneta: add BQL support

2016-09-13 Thread Marcin Wojtas
Tests showed that when whole bandwidth is consumed, the latency for
various kind of traffic can reach high values. With saturated
link (e.g. with iperf from target to host) simple ping could take
significant amount of time. BQL proved to improve this situation
when implemented in mvneta driver. Measurements of ping latency
for 3 link speeds:
Speed | Latency w/o BQL | Latency with BQL
10|  7-14 ms| 3.5 ms
100   |  2-12 ms| 0.6 ms
1000  |   often timeout |   up to 2ms

Decreasing latency as above result in sligt performance cost - 4kpps
(-1.4%) when pushing 64B packets via two bridged interfaces of Armada 38x.
For 1500B packets in the same setup, the mpstat tool showed +8% of
CPU occupation (default affinity, second CPU idle). Even though this
cost seems reasonable to take, considering other improvements.

This commit adds byte queue limit mechanism for the mvneta driver.

Signed-off-by: Marcin Wojtas <m...@semihalf.com>
---
 drivers/net/ethernet/marvell/mvneta.c | 22 +++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvneta.c 
b/drivers/net/ethernet/marvell/mvneta.c
index b9dccea..bb5df35 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -1719,8 +1719,10 @@ static struct mvneta_tx_queue 
*mvneta_tx_done_policy(struct mvneta_port *pp,
 
 /* Free tx queue skbuffs */
 static void mvneta_txq_bufs_free(struct mvneta_port *pp,
-struct mvneta_tx_queue *txq, int num)
+struct mvneta_tx_queue *txq, int num,
+struct netdev_queue *nq)
 {
+   unsigned int bytes_compl = 0, pkts_compl = 0;
int i;
 
for (i = 0; i < num; i++) {
@@ -1728,6 +1730,11 @@ static void mvneta_txq_bufs_free(struct mvneta_port *pp,
txq->txq_get_index;
struct sk_buff *skb = txq->tx_skb[txq->txq_get_index];
 
+   if (skb) {
+   bytes_compl += skb->len;
+   pkts_compl++;
+   }
+
mvneta_txq_inc_get(txq);
 
if (!IS_TSO_HEADER(txq, tx_desc->buf_phys_addr))
@@ -1738,6 +1745,8 @@ static void mvneta_txq_bufs_free(struct mvneta_port *pp,
continue;
dev_kfree_skb_any(skb);
}
+
+   netdev_tx_completed_queue(nq, pkts_compl, bytes_compl);
 }
 
 /* Handle end of transmission */
@@ -1751,7 +1760,7 @@ static void mvneta_txq_done(struct mvneta_port *pp,
if (!tx_done)
return;
 
-   mvneta_txq_bufs_free(pp, txq, tx_done);
+   mvneta_txq_bufs_free(pp, txq, tx_done, nq);
 
txq->count -= tx_done;
 
@@ -2358,6 +2367,8 @@ out:
struct mvneta_pcpu_stats *stats = this_cpu_ptr(pp->stats);
struct netdev_queue *nq = netdev_get_tx_queue(dev, txq_id);
 
+   netdev_tx_sent_queue(nq, len);
+
txq->count += frags;
if (txq->count >= txq->tx_stop_threshold)
netif_tx_stop_queue(nq);
@@ -2385,9 +2396,10 @@ static void mvneta_txq_done_force(struct mvneta_port *pp,
  struct mvneta_tx_queue *txq)
 
 {
+   struct netdev_queue *nq = netdev_get_tx_queue(pp->dev, txq->id);
int tx_done = txq->count;
 
-   mvneta_txq_bufs_free(pp, txq, tx_done);
+   mvneta_txq_bufs_free(pp, txq, tx_done, nq);
 
/* reset txq */
txq->count = 0;
@@ -2884,6 +2896,8 @@ static int mvneta_txq_init(struct mvneta_port *pp,
 static void mvneta_txq_deinit(struct mvneta_port *pp,
  struct mvneta_tx_queue *txq)
 {
+   struct netdev_queue *nq = netdev_get_tx_queue(pp->dev, txq->id);
+
kfree(txq->tx_skb);
 
if (txq->tso_hdrs)
@@ -2895,6 +2909,8 @@ static void mvneta_txq_deinit(struct mvneta_port *pp,
  txq->size * MVNETA_DESC_ALIGNED_SIZE,
  txq->descs, txq->descs_phys);
 
+   netdev_tx_reset_queue(nq);
+
txq->descs = NULL;
txq->last_desc = 0;
txq->next_desc_to_proc = 0;
-- 
1.8.3.1



[PATCH net] net: mvneta: set real interrupt per packet for tx_done

2016-07-05 Thread Marcin Wojtas
From: Dmitri Epshtein <d...@marvell.com>

Commit aebea2ba0f74 ("net: mvneta: fix Tx interrupt delay") intended to
set coalescing threshold to a value guaranteeing interrupt generation
per each sent packet, so that buffers can be released with no delay.

In fact setting threshold to '1' was wrong, because it causes interrupt
every two packets. According to the documentation a reason behind it is
following - interrupt occurs once sent buffers counter reaches a value,
which is higher than one specified in MVNETA_TXQ_SIZE_REG(q). This
behavior was confirmed during tests. Also when testing the SoC working
as a NAS device, better performance was observed with int-per-packet,
as it strongly depends on the fact that all transmitted packets are
released immediately.

This commit enables NETA controller work in interrupt per sent packet mode
by setting coalescing threshold to 0.

Signed-off-by: Dmitri Epshtein <d...@marvell.com>
Signed-off-by: Marcin Wojtas <m...@semihalf.com>
Cc: <sta...@vger.kernel.org> # v3.10+
Fixes aebea2ba0f74 ("net: mvneta: fix Tx interrupt delay")
---
 drivers/net/ethernet/marvell/mvneta.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/marvell/mvneta.c 
b/drivers/net/ethernet/marvell/mvneta.c
index cf04c97..0ad2fa3 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -244,7 +244,7 @@
 /* Various constants */
 
 /* Coalescing */
-#define MVNETA_TXDONE_COAL_PKTS1
+#define MVNETA_TXDONE_COAL_PKTS0   /* interrupt per packet 
*/
 #define MVNETA_RX_COAL_PKTS32
 #define MVNETA_RX_COAL_USEC100
 
-- 
1.8.3.1



Re: [PATCH] net: mvneta: fix changing MTU when using per-cpu processing

2016-04-01 Thread Marcin Wojtas
Hi David,

I've just realized I forgot to add an information, that this patch is
intended for 'net' tree.

Best regards,
Marcin

2016-04-01 15:21 GMT+02:00 Marcin Wojtas <m...@semihalf.com>:
> After enabling per-cpu processing it appeared that under heavy load
> changing MTU can result in blocking all port's interrupts and transmitting
> data is not possible after the change.
>
> This commit fixes above issue by disabling percpu interrupts for the
> time, when TXQs and RXQs are reconfigured.
>
> Signed-off-by: Marcin Wojtas <m...@semihalf.com>
> ---
>  drivers/net/ethernet/marvell/mvneta.c | 30 --
>  1 file changed, 16 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/net/ethernet/marvell/mvneta.c 
> b/drivers/net/ethernet/marvell/mvneta.c
> index fee6a91..a433de9 100644
> --- a/drivers/net/ethernet/marvell/mvneta.c
> +++ b/drivers/net/ethernet/marvell/mvneta.c
> @@ -3083,6 +3083,20 @@ static int mvneta_check_mtu_valid(struct net_device 
> *dev, int mtu)
> return mtu;
>  }
>
> +static void mvneta_percpu_enable(void *arg)
> +{
> +   struct mvneta_port *pp = arg;
> +
> +   enable_percpu_irq(pp->dev->irq, IRQ_TYPE_NONE);
> +}
> +
> +static void mvneta_percpu_disable(void *arg)
> +{
> +   struct mvneta_port *pp = arg;
> +
> +   disable_percpu_irq(pp->dev->irq);
> +}
> +
>  /* Change the device mtu */
>  static int mvneta_change_mtu(struct net_device *dev, int mtu)
>  {
> @@ -3107,6 +3121,7 @@ static int mvneta_change_mtu(struct net_device *dev, 
> int mtu)
>  * reallocation of the queues
>  */
> mvneta_stop_dev(pp);
> +   on_each_cpu(mvneta_percpu_disable, pp, true);
>
> mvneta_cleanup_txqs(pp);
> mvneta_cleanup_rxqs(pp);
> @@ -3130,6 +3145,7 @@ static int mvneta_change_mtu(struct net_device *dev, 
> int mtu)
> return ret;
> }
>
> +   on_each_cpu(mvneta_percpu_enable, pp, true);
> mvneta_start_dev(pp);
> mvneta_port_up(pp);
>
> @@ -3283,20 +3299,6 @@ static void mvneta_mdio_remove(struct mvneta_port *pp)
> pp->phy_dev = NULL;
>  }
>
> -static void mvneta_percpu_enable(void *arg)
> -{
> -   struct mvneta_port *pp = arg;
> -
> -   enable_percpu_irq(pp->dev->irq, IRQ_TYPE_NONE);
> -}
> -
> -static void mvneta_percpu_disable(void *arg)
> -{
> -   struct mvneta_port *pp = arg;
> -
> -   disable_percpu_irq(pp->dev->irq);
> -}
> -
>  /* Electing a CPU must be done in an atomic way: it should be done
>   * after or before the removal/insertion of a CPU and this function is
>   * not reentrant.
> --
> 1.8.3.1
>


[PATCH] net: mvneta: fix changing MTU when using per-cpu processing

2016-04-01 Thread Marcin Wojtas
After enabling per-cpu processing it appeared that under heavy load
changing MTU can result in blocking all port's interrupts and transmitting
data is not possible after the change.

This commit fixes above issue by disabling percpu interrupts for the
time, when TXQs and RXQs are reconfigured.

Signed-off-by: Marcin Wojtas <m...@semihalf.com>
---
 drivers/net/ethernet/marvell/mvneta.c | 30 --
 1 file changed, 16 insertions(+), 14 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvneta.c 
b/drivers/net/ethernet/marvell/mvneta.c
index fee6a91..a433de9 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -3083,6 +3083,20 @@ static int mvneta_check_mtu_valid(struct net_device 
*dev, int mtu)
return mtu;
 }
 
+static void mvneta_percpu_enable(void *arg)
+{
+   struct mvneta_port *pp = arg;
+
+   enable_percpu_irq(pp->dev->irq, IRQ_TYPE_NONE);
+}
+
+static void mvneta_percpu_disable(void *arg)
+{
+   struct mvneta_port *pp = arg;
+
+   disable_percpu_irq(pp->dev->irq);
+}
+
 /* Change the device mtu */
 static int mvneta_change_mtu(struct net_device *dev, int mtu)
 {
@@ -3107,6 +3121,7 @@ static int mvneta_change_mtu(struct net_device *dev, int 
mtu)
 * reallocation of the queues
 */
mvneta_stop_dev(pp);
+   on_each_cpu(mvneta_percpu_disable, pp, true);
 
mvneta_cleanup_txqs(pp);
mvneta_cleanup_rxqs(pp);
@@ -3130,6 +3145,7 @@ static int mvneta_change_mtu(struct net_device *dev, int 
mtu)
return ret;
}
 
+   on_each_cpu(mvneta_percpu_enable, pp, true);
mvneta_start_dev(pp);
mvneta_port_up(pp);
 
@@ -3283,20 +3299,6 @@ static void mvneta_mdio_remove(struct mvneta_port *pp)
pp->phy_dev = NULL;
 }
 
-static void mvneta_percpu_enable(void *arg)
-{
-   struct mvneta_port *pp = arg;
-
-   enable_percpu_irq(pp->dev->irq, IRQ_TYPE_NONE);
-}
-
-static void mvneta_percpu_disable(void *arg)
-{
-   struct mvneta_port *pp = arg;
-
-   disable_percpu_irq(pp->dev->irq);
-}
-
 /* Electing a CPU must be done in an atomic way: it should be done
  * after or before the removal/insertion of a CPU and this function is
  * not reentrant.
-- 
1.8.3.1



Re: [PATCH] net: mvneta: explicitly disable BM on 64bit platform

2016-03-31 Thread Marcin Wojtas
Hi Jisheng,

2016-03-31 7:53 GMT+02:00 Jisheng Zhang :
> Hi Gregory,
>
> On Wed, 30 Mar 2016 17:11:41 +0200 Gregory CLEMENT wrote:
>
>> Hi Jisheng,
>>
>>  On mer., mars 30 2016, Jisheng Zhang  wrote:
>>
>> > The mvneta BM can't work on 64bit platform, as the BM hardware expects
>> > buf virtual address to be placed in the first four bytes of mapped
>> > buffer, but obviously the virtual address on 64bit platform can't be
>> > stored in 4 bytes. So we have to explicitly disable BM on 64bit
>> > platform.
>>
>> Actually mvneta is used on Armada 3700 which is a 64bits platform.
>> Is it true that the driver needs some change to use BM in 64 bits, but
>> we don't have to disable it.
>>
>> Here is the 64 bits part of the patch we have currently on the hardware
>> prototype. We have more things which are really related to the way the
>> mvneta is connected to the Armada 3700 SoC. This code was not ready for
>
> Thanks for the sharing.
>
> I think we could commit easy parts firstly, for example: the cacheline size
> hardcoding, either piece of your diff or my version:
>
> http://lists.infradead.org/pipermail/linux-arm-kernel/2016-March/418513.html

Since the commit:
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/arch/arm64/include/asm/cache.h?id=97303480753e48fb313dc0e15daaf11b0451cdb8
detached L1_CACHE_BYTES from real cache size, I suggest, the macro should be:
#define MVNETA_CPU_D_CACHE_LINE_SIZE cache_line_size()

Regarding check after dma_alloc_coherent, I agree it's not necessary.

>
>> mainline but I prefer share it now instead of having the HWBM blindly
>
> I have looked through the diff, it is for the driver itself on 64bit 
> platforms,
> and it doesn't touch BM. The BM itself need to be disabled for 64bit, I'm not
> sure the BM could work on 64bit even with your diff. Per my understanding, 
> the BM
> can't work on 64 bit, let's have a look at some piece of the 
> mvneta_bm_construct()
>
> *(u32 *)buf = (u32)buf;

Indeed this particular part is different and unclear, I tried
different options - with no success. I'm checking with design team
now. Anyway, I managed to enable operation for HWBM on A3700 with one
work-around in mvneta_hwbm_rx():
data = phys_to_virt(rx_desc->buf_phys_addr);

Of course mvneta_bm, due to some silicone differences needed also a rework.

Actually I'd wait with updating 64-bit parts of mvneta, until real
support for such machine's controller is introduced. Basing on my
experience with enabling neta on A3700, it turns out to be more
changes.

Best regards,
Marcin


Re: [PATCH v4 net-next 8/9] net: add a hardware buffer management helper API

2016-03-06 Thread Marcin Wojtas
Hi Gregory,


> +int hwbm_pool_add(struct hwbm_pool *bm_pool, unsigned int buf_num, gfp_t gfp)
> +{
> +   int err, i;
> +   unsigned long flags;
> +
> +   spin_lock_irqsave(_pool->lock, flags);
> +   if (bm_pool->buf_num == bm_pool->size) {

'size' field is used as a 'frag_size' but here it means pool capacity.
I think it's better to keep 'size' for pool capacity and add
'buf_size' field to struct hwbm_pool.

> +   pr_warn("pool already filled\n");
> +   return bm_pool->buf_num;
> +   }
> +
> +   if (buf_num + bm_pool->buf_num > bm_pool->size) {
> +   pr_warn("cannot allocate %d buffers for pool\n",
> +   buf_num);
> +   return 0;
> +   }
> +
> +   if ((buf_num + bm_pool->buf_num) < bm_pool->buf_num) {

What is a point of this condition? How possibly after checking if
capacity of pool is not exceeded, this one would ever be true?

> +   pr_warn("Adding %d buffers to the %d current buffers will 
> overflow\n",
> +   buf_num,  bm_pool->buf_num);
> +   return 0;
> +   }
> +

Best regards,
Marcin


Re: [PATCH v2 net-next 6/8] net: mvneta: bm: add support for hardware buffer management

2016-02-18 Thread Marcin Wojtas
Hi David,


2016-02-18 5:43 GMT+01:00 David Miller :
> From: Gregory CLEMENT 
> Date: Tue, 16 Feb 2016 16:33:41 +0100
>
>>   pp->dev = dev;
>>   SET_NETDEV_DEV(dev, >dev);
>>
>> + dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO;
>> + dev->hw_features |= dev->features;
>> + dev->vlan_features |= dev->features;
>> + dev->priv_flags |= IFF_UNICAST_FLT;
>> + dev->gso_max_segs = MVNETA_MAX_TSO_SEGS;
>> +
>> + err = register_netdev(dev);
>> + if (err < 0) {
>> + dev_err(>dev, "failed to register\n");
>> + goto err_free_stats;
>> + }
>> +
>> + pp->id = dev->ifindex;
>> +
>> + /* Obtain access to BM resources if enabled and already initialized */
>> + bm_node = of_parse_phandle(dn, "buffer-manager", 0);
>> + if (bm_node && bm_node->data) {
>
> This set of changes has a lot of problems.
>
> First, the exact moment you call register_netdev() your device must be
> fully initialized because ->open() can be invoked immediately.  This
> means you must take care of all of this buffer manager stuff before
> calling register_netdev().
>
> It must precisely be the last thing you invoke in your probe function
> for this reason.

Ok. I shifted register_netdev in order to obtain port id dynamically
from netdev's ifindex (needed to control port <-> pool mapping). If
this order of registration is problematic, I will add an ID property
to DT.

>
> Also you are now adding conditionalized code to every fastpath in your
> driver, that is rediculous and is going to hurt performance.
>
> Add seperate code paths for the HWBM vs SWBM, and register a unique
> set of netdev_ops as appropriate.

TX is untouched and BM support affects only open, stop and change_mtu
- whose execution is not problematic in terms of performance. However
there are a couple new conditions in mvneta_rx(). It can be reduced to
a single condition check, moved to NAPI callback. I'll try to refactor
code in a way to avoid code duplication. Please bear in mind I don't
want to register to different NAPI functions (exactly the same apart
from one line), as the driver can fall back to SWBM after e.g.
unsuccessful mtu change.

Best regards,
Marcin


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

2015-12-08 Thread Marcin Wojtas
Hi David,

2015-12-04 21:15 GMT+01:00 Florian Fainelli <f.faine...@gmail.com>:
> (no top posting please)
>
> On 02/12/15 00:26, Marcin Wojtas wrote:
>> Hi Florian,
>>
>> Can you please describe in more details, what would you expect from
>> such special abstraction layer regarding buffer managers? I'd like to
>> understand more of your expectations and evaluate possible work.
>
> Well, something along these lines:
>
> - have the ability to register a particular pool (location + number of
> buffers) in a way that is relatively device agnostic (initialization
> would of course be device specific)
>
> - provide a set of buffer management APIs like those you proposed below,
> and have some generic code that leverages what
> drivers/net/ethernet/sun/niu.c does for instance
>
> - introduce a netdev_alloc_skb_from_pool() or something like that which
> would limit the amount of code to change in your network driver to
> benefit from that feature so based
>
> I am sure David would be able to suggest more detailed API.
>

As we're getting closer to what a generic BM part, could you please
share your thoughts on the possible API?


>>>
>>>> What kind of abstraction and helpers do you mean? Some kind of API
>>>> (e.g. bm_alloc_buffer, bm_initialize_ring bm_put_buffer,
>>>> bm_get_buffer), which would be used by platform drivers (and specific
>>>> aplications if one wants to develop on top of the kernel)?
>>>>
>>>> In general, what is your top-view of such solution and its cooperation
>>>> with the drivers?
>>>
>>> The tricky parts involved have to do with allocating pages for the
>>> buffer pools and minimizing the number of atomic refcounting
>>> operations on those pages for for the puts and gets, particularly
>>> around buffer replenish runs.
>>>
>>> For example, if you're allocating a page for a buffer pool the device
>>> will chop into N (for any N < PAGE_SIZE) byte pieces, you can
>>> eliminate many atomic operations.
>

Do you think you can point to anything similar that could be a sort of
reference for such solution?

Best regards,
Marcin
--
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 v2 4/4] net: mvneta: Spread out the TX queues management on all CPUs

2015-12-05 Thread Marcin Wojtas
Hi Gregory,

> @@ -1824,13 +1835,16 @@ error:
>  static int mvneta_tx(struct sk_buff *skb, struct net_device *dev)
>  {
> struct mvneta_port *pp = netdev_priv(dev);
> -   u16 txq_id = skb_get_queue_mapping(skb);
> +   u16 txq_id = smp_processor_id() % txq_number;

I think it may be ok to bind TXQs to different CPUs, but I don't think
that replacing skb_get_queue_mapping by in fact smp_processor_id() is
the best idea. This way you use only 2 TXQs on A385 and 4 TXQs on AXP.
There are HW mechanisms like WRR or EJP that provide balancing for
egress, so let's better keep all 8.

As a compromise I think it's enough to do the mapping and we would
achieve some offload by TX processing done on different CPU's and let
BQL do the balance on higher level. FYI, I've already implemented BQL
and will submit it asap, however I still have some weird problems
after enabling it.

Best regards,
Marcin
--
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 0/3] Marvell Armada 375 mvpp2 fixes

2015-12-03 Thread Marcin Wojtas
Hi,

During my work on mvneta driver I revised mvpp2, and it occurred that the
initial version of Marvell Armada 375 SoC comprised bugs around
DMA-unmapping in both ingress and egress paths - not all buffers were
umapped in TX path and none(!) in RX. Three patches that I send fix
this situation.

Any feedback would be welcome.

Best regards,
Marcin Wojtas

Marcin Wojtas (3):
  net: mvpp2: fix missing DMA region unmap in egress processing
  net: mvpp2: fix buffers' DMA handling on RX path
  net: mvpp2: fix refilling BM pools in RX path

 drivers/net/ethernet/marvell/mvpp2.c | 52 +++-
 1 file changed, 33 insertions(+), 19 deletions(-)

-- 
1.8.3.1

--
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 3/3] net: mvpp2: fix refilling BM pools in RX path

2015-12-03 Thread Marcin Wojtas
In hitherto code in case of RX buffer allocation error during refill,
original buffer is pushed to the network stack, but the amount of
available buffer pointers in BM pool is decreased.

This commit fixes the situation by moving refill call before skb_put(),
and returning original buffer pointer to the pool in case of an error.

Signed-off-by: Marcin Wojtas <m...@semihalf.com>

Fixes: 3f518509dedc ("ethernet: Add new driver for Marvell Armada 375
network unit")

Cc: <sta...@vger.kernel.org> # v3.18+
---
 drivers/net/ethernet/marvell/mvpp2.c | 28 
 1 file changed, 16 insertions(+), 12 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvpp2.c 
b/drivers/net/ethernet/marvell/mvpp2.c
index eaef461..a4beccf 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -5099,7 +5099,8 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo,
struct mvpp2_rx_queue *rxq)
 {
struct net_device *dev = port->dev;
-   int rx_received, rx_filled, i;
+   int rx_received;
+   int rx_done = 0;
u32 rcvd_pkts = 0;
u32 rcvd_bytes = 0;
 
@@ -5108,17 +5109,18 @@ static int mvpp2_rx(struct mvpp2_port *port, int 
rx_todo,
if (rx_todo > rx_received)
rx_todo = rx_received;
 
-   rx_filled = 0;
-   for (i = 0; i < rx_todo; i++) {
+   while (rx_done < rx_todo) {
struct mvpp2_rx_desc *rx_desc = mvpp2_rxq_next_desc_get(rxq);
struct mvpp2_bm_pool *bm_pool;
struct sk_buff *skb;
+   dma_addr_t phys_addr;
u32 bm, rx_status;
int pool, rx_bytes, err;
 
-   rx_filled++;
+   rx_done++;
rx_status = rx_desc->status;
rx_bytes = rx_desc->data_size - MVPP2_MH_SIZE;
+   phys_addr = rx_desc->buf_phys_addr;
 
bm = mvpp2_bm_cookie_build(rx_desc);
pool = mvpp2_bm_cookie_pool_get(bm);
@@ -5135,8 +5137,10 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo,
 * comprised by the RX descriptor.
 */
if (rx_status & MVPP2_RXD_ERR_SUMMARY) {
+   err_drop_frame:
dev->stats.rx_errors++;
mvpp2_rx_error(port, rx_desc);
+   /* Return the buffer to the pool */
mvpp2_pool_refill(port, bm, rx_desc->buf_phys_addr,
  rx_desc->buf_cookie);
continue;
@@ -5144,7 +5148,13 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo,
 
skb = (struct sk_buff *)rx_desc->buf_cookie;
 
-   dma_unmap_single(dev->dev.parent, rx_desc->buf_phys_addr,
+   err = mvpp2_rx_refill(port, bm_pool, bm, 0);
+   if (err) {
+   netdev_err(port->dev, "failed to refill BM pools\n");
+   goto err_drop_frame;
+   }
+
+   dma_unmap_single(dev->dev.parent, phys_addr,
 bm_pool->buf_size, DMA_FROM_DEVICE);
 
rcvd_pkts++;
@@ -5157,12 +5167,6 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo,
mvpp2_rx_csum(port, rx_status, skb);
 
napi_gro_receive(>napi, skb);
-
-   err = mvpp2_rx_refill(port, bm_pool, bm, 0);
-   if (err) {
-   netdev_err(port->dev, "failed to refill BM pools\n");
-   rx_filled--;
-   }
}
 
if (rcvd_pkts) {
@@ -5176,7 +5180,7 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo,
 
/* Update Rx queue management counters */
wmb();
-   mvpp2_rxq_status_update(port, rxq->id, rx_todo, rx_filled);
+   mvpp2_rxq_status_update(port, rxq->id, rx_done, rx_done);
 
return rx_todo;
 }
-- 
1.8.3.1

--
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 1/3] net: mvpp2: fix missing DMA region unmap in egress processing

2015-12-03 Thread Marcin Wojtas
The Tx descriptor release code currently calls dma_unmap_single() and
dev_kfree_skb_any() if the descriptor is associated with a non-NULL skb.
This condition is true only for the last fragment of the packet.

Since every descriptor's buffer is DMA-mapped it has to be properly
unmapped.

Signed-off-by: Marcin Wojtas <m...@semihalf.com>

Fixes: 3f518509dedc ("ethernet: Add new driver for Marvell Armada 375
network unit")

Cc: <sta...@vger.kernel.org> # v3.18+
---
 drivers/net/ethernet/marvell/mvpp2.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvpp2.c 
b/drivers/net/ethernet/marvell/mvpp2.c
index d9884fd..95db519 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -4401,11 +4401,10 @@ static void mvpp2_txq_bufs_free(struct mvpp2_port *port,
 
mvpp2_txq_inc_get(txq_pcpu);
 
-   if (!skb)
-   continue;
-
dma_unmap_single(port->dev->dev.parent, buf_phys_addr,
 skb_headlen(skb), DMA_TO_DEVICE);
+   if (!skb)
+   continue;
dev_kfree_skb_any(skb);
}
 }
-- 
1.8.3.1

--
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 2/3] net: mvpp2: fix buffers' DMA handling on RX path

2015-12-03 Thread Marcin Wojtas
Each allocated buffer, whose pointer is put into BM pool is DMA-mapped.
Hence it should be properly unmapped after usage or when removing buffers
from pool.

This commit fixes DMA handling on RX path by adding dma_unmap_single() in
mvpp2_rx() and in mvpp2_bufs_free(). The latter function's argument number
had to be increased for this purpose.

Signed-off-by: Marcin Wojtas <m...@semihalf.com>

Fixes: 3f518509dedc ("ethernet: Add new driver for Marvell Armada 375
network unit")

Cc: <sta...@vger.kernel.org> # v3.18+
---
 drivers/net/ethernet/marvell/mvpp2.c | 21 -
 1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvpp2.c 
b/drivers/net/ethernet/marvell/mvpp2.c
index 95db519..eaef461 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -3413,16 +3413,23 @@ static void mvpp2_bm_pool_bufsize_set(struct mvpp2 
*priv,
 }
 
 /* Free all buffers from the pool */
-static void mvpp2_bm_bufs_free(struct mvpp2 *priv, struct mvpp2_bm_pool 
*bm_pool)
+static void mvpp2_bm_bufs_free(struct device *dev, struct mvpp2 *priv,
+  struct mvpp2_bm_pool *bm_pool)
 {
int i;
 
for (i = 0; i < bm_pool->buf_num; i++) {
+   dma_addr_t buf_phys_addr;
u32 vaddr;
 
/* Get buffer virtual address (indirect access) */
-   mvpp2_read(priv, MVPP2_BM_PHY_ALLOC_REG(bm_pool->id));
+   buf_phys_addr = mvpp2_read(priv,
+  MVPP2_BM_PHY_ALLOC_REG(bm_pool->id));
vaddr = mvpp2_read(priv, MVPP2_BM_VIRT_ALLOC_REG);
+
+   dma_unmap_single(dev, buf_phys_addr,
+bm_pool->buf_size, DMA_FROM_DEVICE);
+
if (!vaddr)
break;
dev_kfree_skb_any((struct sk_buff *)vaddr);
@@ -3439,7 +3446,7 @@ static int mvpp2_bm_pool_destroy(struct platform_device 
*pdev,
 {
u32 val;
 
-   mvpp2_bm_bufs_free(priv, bm_pool);
+   mvpp2_bm_bufs_free(>dev, priv, bm_pool);
if (bm_pool->buf_num) {
WARN(1, "cannot free all buffers in pool %d\n", bm_pool->id);
return 0;
@@ -3692,7 +3699,8 @@ mvpp2_bm_pool_use(struct mvpp2_port *port, int pool, enum 
mvpp2_bm_type type,
   MVPP2_BM_LONG_BUF_NUM :
   MVPP2_BM_SHORT_BUF_NUM;
else
-   mvpp2_bm_bufs_free(port->priv, new_pool);
+   mvpp2_bm_bufs_free(port->dev->dev.parent,
+  port->priv, new_pool);
 
new_pool->pkt_size = pkt_size;
 
@@ -3756,7 +3764,7 @@ static int mvpp2_bm_update_mtu(struct net_device *dev, 
int mtu)
int pkt_size = MVPP2_RX_PKT_SIZE(mtu);
 
/* Update BM pool with new buffer size */
-   mvpp2_bm_bufs_free(port->priv, port_pool);
+   mvpp2_bm_bufs_free(dev->dev.parent, port->priv, port_pool);
if (port_pool->buf_num) {
WARN(1, "cannot free all buffers in pool %d\n", port_pool->id);
return -EIO;
@@ -5136,6 +5144,9 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo,
 
skb = (struct sk_buff *)rx_desc->buf_cookie;
 
+   dma_unmap_single(dev->dev.parent, rx_desc->buf_phys_addr,
+bm_pool->buf_size, DMA_FROM_DEVICE);
+
rcvd_pkts++;
rcvd_bytes += rx_bytes;
atomic_inc(_pool->in_use);
-- 
1.8.3.1

--
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-12-02 Thread Marcin Wojtas
Hi Florian,

Can you please describe in more details, what would you expect from
such special abstraction layer regarding buffer managers? I'd like to
understand more of your expectations and evaluate possible work.

Best regards,
Marcin

2015-11-30 17:25 GMT+01:00 David Miller <da...@redhat.com>:
> From: Marcin Wojtas <m...@semihalf.com>
> Date: Mon, 30 Nov 2015 15:13:22 +0100
>
>> What kind of abstraction and helpers do you mean? Some kind of API
>> (e.g. bm_alloc_buffer, bm_initialize_ring bm_put_buffer,
>> bm_get_buffer), which would be used by platform drivers (and specific
>> aplications if one wants to develop on top of the kernel)?
>>
>> In general, what is your top-view of such solution and its cooperation
>> with the drivers?
>
> The tricky parts involved have to do with allocating pages for the
> buffer pools and minimizing the number of atomic refcounting
> operations on those pages for for the puts and gets, particularly
> around buffer replenish runs.
>
> For example, if you're allocating a page for a buffer pool the device
> will chop into N (for any N < PAGE_SIZE) byte pieces, you can
> eliminate many atomic operations.
--
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-12-02 Thread Marcin Wojtas
Hi Gregory,

2015-12-02 17:21 GMT+01:00 Gregory CLEMENT :
> Hi,
>
>  On mer., déc. 02 2015, Gregory CLEMENT  
> wrote:
>
>>>
>>> So far the issue may have been not noticed, because in every IO driver
>>> using mvebu_mbus_dram_info for configuring MBUS windows, there's
>>> following substraction:
>>> (cs->size - 1) & 0xf000
>>>
>>> I think there are two options:
>>> 1. Change size type to u64.
>>
>> If we switch to u64 we really must pay attention to be sure that it
>> won't be used to be written in a register, but the regsiter remains
>> 32bits.
>>
>>> 2. Change condition in mvebu_mbus_get_dram_win_info to:
>>> if (cs->base <= phyaddr && phyaddr <= (cs->base + cs->size -1))
>>
>> I think it would be the best solution.
>
> So I applied the following patch:
> --- a/drivers/bus/mvebu-mbus.c
> +++ b/drivers/bus/mvebu-mbus.c
> @@ -964,7 +964,7 @@ int mvebu_mbus_get_dram_win_info(phys_addr_t phyaddr, u8 
> *target, u8 *attr)
> for (i = 0; i < dram->num_cs; i++) {
> const struct mbus_dram_window *cs = dram->cs + i;
>
> -   if (cs->base <= phyaddr && phyaddr <= (cs->base + cs->size)) {
> +   if (cs->base <= phyaddr && phyaddr <= (cs->base + cs->size - 
> 1)) {
> *target = dram->mbus_dram_target_id;
> *attr = cs->mbus_attr;
> return 0;
>
> I didn't get any errors during boot related to the BM. However I did not
> manage to use an ethernet interface. The udhcpc never managed to get an
> IP and if I set the IP manually I could not ping.
>
> But on Armada 388 GP I didn't have any issue.
>
> Do you have some idea about waht I could check?
>

I replaced 2GB with 8GB DIMM and after that, on the same kernel/board,
I can't ping either. Very strange, but as I can reproduce the issue,
don't debug it, I will.

Best regards,
Marcin
--
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 06/13] net: mvneta: enable mixed egress processing using HR timer

2015-12-02 Thread Marcin Wojtas
Hi Simon,

I checked using hrtimer_is_queued instead of a custom flag and it
resulted in ~20kpps drop in my setup. timer_scheduled flag is cleared
in the tasklet, so no timer can be scheduled until the tasklet is
executed. hr_timer flags do not cover this situation, so much more
timers are enqueued. I added a counter and with maximal throughput
during 30s test and 9 times less timers were enqueued with
timer_scheduled flag (~31k vs ~281k), so it's much more efficient and
I'll leave it as is.

Best regards,
Marcin

2015-11-30 16:57 GMT+01:00 Marcin Wojtas <m...@semihalf.com>:
> Hi Simon,
>
> 2015-11-26 17:45 GMT+01:00 Simon Guinot <simon.gui...@sequanux.org>:
>> Hi Marcin,
>>
>> On Sun, Nov 22, 2015 at 08:53:52AM +0100, Marcin Wojtas wrote:
>>> Mixed approach allows using higher interrupt threshold (increased back to
>>> 15 packets), useful in high throughput. In case of small amount of data
>>> or very short TX queues HR timer ensures releasing buffers with small
>>> latency.
>>>
>>> Along with existing tx_done processing by coalescing interrupts this
>>> commit enables triggering HR timer each time the packets are sent.
>>> Time threshold can also be configured, using ethtool.
>>>
>>> Signed-off-by: Marcin Wojtas <m...@semihalf.com>
>>> Signed-off-by: Simon Guinot <simon.gui...@sequanux.org>
>>> ---
>>>  drivers/net/ethernet/marvell/mvneta.c | 89 
>>> +--
>>>  1 file changed, 85 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/drivers/net/ethernet/marvell/mvneta.c 
>>> b/drivers/net/ethernet/marvell/mvneta.c
>>> index 9c9e858..f5acaf6 100644
>>> --- a/drivers/net/ethernet/marvell/mvneta.c
>>> +++ b/drivers/net/ethernet/marvell/mvneta.c
>>> @@ -21,6 +21,8 @@
>>>  #include 
>>>  #include 
>>>  #include 
>>> +#include 
>>> +#include 
>>
>> ktime.h is already included by hrtimer.h.
>>
>>>  #include 
>>>  #include 
>>>  #include 
>>> @@ -226,7 +228,8 @@
>>>  /* Various constants */
>>>
>>>  /* Coalescing */
>>> -#define MVNETA_TXDONE_COAL_PKTS  1
>>> +#define MVNETA_TXDONE_COAL_PKTS  15
>>> +#define MVNETA_TXDONE_COAL_USEC  100
>>
>> Maybe we should keep the default configuration and let the user choose
>> to enable (or not) this feature ?
>
> I think that this feature should be enabled by default, same as in RX
> (which is enabled by HW in ingress). It satisfies all kinds of traffic
> or queues sizes. I'd prefer a situation that if someone really wants
> to disable it (even if I don't know the possible justification), then
> let him use ethtool for this purpose.
>
>>
>>>  #define MVNETA_RX_COAL_PKTS  32
>>>  #define MVNETA_RX_COAL_USEC  100
>>>
>>> @@ -356,6 +359,11 @@ struct mvneta_port {
>>>   struct net_device *dev;
>>>   struct notifier_block cpu_notifier;
>>>
>>> + /* Egress finalization */
>>> + struct tasklet_struct tx_done_tasklet;
>>> + struct hrtimer tx_done_timer;
>>> + bool timer_scheduled;
>>
>> I think we could use hrtimer_is_queued() instead of introducing a new
>> variable.
>>
>
> Good point, i'll try that.
>
> Best regards,
> Marcin
--
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


  1   2   >