Netdev List
 help / color / mirror / Atom feed
* Re: [Potential Spoof] Re: [PATCH net-next v6 3/3] net: phy: broadcom: add 1000Base-X support for BCM54616S
From: Heiner Kallweit @ 2019-08-09 21:59 UTC (permalink / raw)
  To: Tao Ren, Andrew Lunn, Florian Fainelli, David S . Miller,
	Arun Parameswaran, Justin Chen, Vladimir Oltean,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
	openbmc@lists.ozlabs.org
In-Reply-To: <8f0e172b-575c-dab8-b695-c33dfc78fa8f@fb.com>

On 09.08.2019 23:13, Tao Ren wrote:
> On 8/9/19 1:54 PM, Tao Ren wrote:
>> Hi Heiner,
>>
>> On 8/9/19 1:21 PM, Heiner Kallweit wrote:
>>> On 09.08.2019 07:44, Tao Ren wrote:
>>>> The BCM54616S PHY cannot work properly in RGMII->1000Base-KX mode (for
>>>> example, on Facebook CMM BMC platform), mainly because genphy functions
>>>> are designed for copper links, and 1000Base-X (clause 37) auto negotiation
>>>> needs to be handled differently.
>>>>
>>>> This patch enables 1000Base-X support for BCM54616S by customizing 3
>>>> driver callbacks:
>>>>
>>>>   - probe: probe callback detects PHY's operation mode based on
>>>>     INTERF_SEL[1:0] pins and 1000X/100FX selection bit in SerDES 100-FX
>>>>     Control register.
>>>>
>>>>   - config_aneg: calls genphy_c37_config_aneg when the PHY is running in
>>>>     1000Base-X mode; otherwise, genphy_config_aneg will be called.
>>>>
>>>>   - read_status: calls genphy_c37_read_status when the PHY is running in
>>>>     1000Base-X mode; otherwise, genphy_read_status will be called.
>>>>
>>>> Signed-off-by: Tao Ren <taoren@fb.com>
>>>> ---
>>>>  Changes in v6:
>>>>   - nothing changed.
>>>>  Changes in v5:
>>>>   - include Heiner's patch "net: phy: add support for clause 37
>>>>     auto-negotiation" into the series.
>>>>   - use genphy_c37_config_aneg and genphy_c37_read_status in BCM54616S
>>>>     PHY driver's callback when the PHY is running in 1000Base-X mode.
>>>>  Changes in v4:
>>>>   - add bcm54616s_config_aneg_1000bx() to deal with auto negotiation in
>>>>     1000Base-X mode.
>>>>  Changes in v3:
>>>>   - rename bcm5482_read_status to bcm54xx_read_status so the callback can
>>>>     be shared by BCM5482 and BCM54616S.
>>>>  Changes in v2:
>>>>   - Auto-detect PHY operation mode instead of passing DT node.
>>>>   - move PHY mode auto-detect logic from config_init to probe callback.
>>>>   - only set speed (not including duplex) in read_status callback.
>>>>   - update patch description with more background to avoid confusion.
>>>>   - patch #1 in the series ("net: phy: broadcom: set features explicitly
>>>>     for BCM54616") is dropped: the fix should go to get_features callback
>>>>     which may potentially depend on this patch.
>>>>
>>>>  drivers/net/phy/broadcom.c | 54 +++++++++++++++++++++++++++++++++++---
>>>>  include/linux/brcmphy.h    | 10 +++++--
>>>>  2 files changed, 58 insertions(+), 6 deletions(-)
>>>>
>>>> diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
>>>> index 937d0059e8ac..fbd76a31c142 100644
>>>> --- a/drivers/net/phy/broadcom.c
>>>> +++ b/drivers/net/phy/broadcom.c
>>>> @@ -383,9 +383,9 @@ static int bcm5482_config_init(struct phy_device *phydev)
>>>>  		/*
>>>>  		 * Select 1000BASE-X register set (primary SerDes)
>>>>  		 */
>>>> -		reg = bcm_phy_read_shadow(phydev, BCM5482_SHD_MODE);
>>>> -		bcm_phy_write_shadow(phydev, BCM5482_SHD_MODE,
>>>> -				     reg | BCM5482_SHD_MODE_1000BX);
>>>> +		reg = bcm_phy_read_shadow(phydev, BCM54XX_SHD_MODE);
>>>> +		bcm_phy_write_shadow(phydev, BCM54XX_SHD_MODE,
>>>> +				     reg | BCM54XX_SHD_MODE_1000BX);
>>>>  
>>>>  		/*
>>>>  		 * LED1=ACTIVITYLED, LED3=LINKSPD[2]
>>>> @@ -451,12 +451,44 @@ static int bcm5481_config_aneg(struct phy_device *phydev)
>>>>  	return ret;
>>>>  }
>>>>  
>>>> +static int bcm54616s_probe(struct phy_device *phydev)
>>>> +{
>>>> +	int val, intf_sel;
>>>> +
>>>> +	val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_MODE);
>>>> +	if (val < 0)
>>>> +		return val;
>>>> +
>>>> +	/* The PHY is strapped in RGMII to fiber mode when INTERF_SEL[1:0]
>>>> +	 * is 01b.
>>>> +	 */
>>>> +	intf_sel = (val & BCM54XX_SHD_INTF_SEL_MASK) >> 1;
>>>> +	if (intf_sel == 1) {
>>>> +		val = bcm_phy_read_shadow(phydev, BCM54616S_SHD_100FX_CTRL);
>>>> +		if (val < 0)
>>>> +			return val;
>>>> +
>>>> +		/* Bit 0 of the SerDes 100-FX Control register, when set
>>>> +		 * to 1, sets the MII/RGMII -> 100BASE-FX configuration.
>>>> +		 * When this bit is set to 0, it sets the GMII/RGMII ->
>>>> +		 * 1000BASE-X configuration.
>>>> +		 */
>>>> +		if (!(val & BCM54616S_100FX_MODE))
>>>> +			phydev->dev_flags |= PHY_BCM_FLAGS_MODE_1000BX;
>>>> +	}
>>>> +
>>>> +	return 0;
>>>> +}
>>>> +
>>>>  static int bcm54616s_config_aneg(struct phy_device *phydev)
>>>>  {
>>>>  	int ret;
>>>>  
>>>>  	/* Aneg firsly. */
>>>> -	ret = genphy_config_aneg(phydev);
>>>> +	if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX)
>>>> +		ret = genphy_c37_config_aneg(phydev);
>>>> +	else
>>>> +		ret = genphy_config_aneg(phydev);
>>>>  
>>>
>>> I'm just wondering whether it needs to be considered that 100base-FX
>>> doesn't support auto-negotiation. I suppose BMSR reports aneg as
>>> supported, therefore phylib will use aneg per default.
>>> Not sure who could set 100Base-FX mode when, but maybe at that place
>>> also phydev->autoneg needs to be cleared. Did you test 100Base-FX mode?
>>
>> I'm doubting if 100Base-FX works. Besides auto-negotiation, 100Base-FX Control/Status registers are defined in shadow register instead of MII_BMCR and MII_BMSR.
>>
>> Unfortunately I don't have environment to test 100Base-FX and that's why I only make changes when the PHY is working in 1000X mode.
> 
> I can prepare a patch for 100Base-FX based on my understanding of bcm54616s datasheet, but the patch would be just compile-tested 
> 
Support for 1000Base-X should be sufficient. Best mention the missing support for
100Base-FX in the commit message and at a suited place in the driver code.

> 
> Thanks,
> 
> Tao
> 
Heiner

^ permalink raw reply

* Re: [PATCH v3] tools: bpftool: fix reading from /proc/config.gz
From: Jakub Kicinski @ 2019-08-09 21:57 UTC (permalink / raw)
  To: Stanislav Fomichev
  Cc: Peter Wu, Alexei Starovoitov, Daniel Borkmann, netdev,
	Stanislav Fomichev, Quentin Monnet
In-Reply-To: <20190809214831.GE2820@mini-arch>

On Fri, 9 Aug 2019 14:48:31 -0700, Stanislav Fomichev wrote:
> I'm just being nit picky :-)
> Because changelog says we already depend on -lz, but then in the patch
> we explicitly add it.
> 
> I think you were right in pointing out that we already implicitly depend
> on -lz via -lelf and/or -lbfd. And it works for non-static builds.
> We don't need an explicit -lz unless somebody puts '-static' in
> EXTRA_CFLAGS. So maybe we should just submit the patch as is because
> it fixes make EXTRA_CFLAGS=-static.

Mm. Sounds reasonable. Fixing EXTRA_CFLAGS=-static would be really cool,
too, I always struggle to get a statically linked build.

> RE $(error): we don't do it for -lelf, right? So probably not worth
> the hassle for zlib.

Right, OTOH bpftool doesn't really care about -lelf, it's libbpf that
needs it, and libbpf does test.

^ permalink raw reply

* Re: [PATCH v3] tools: bpftool: fix reading from /proc/config.gz
From: Stanislav Fomichev @ 2019-08-09 21:48 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Peter Wu, Alexei Starovoitov, Daniel Borkmann, netdev,
	Stanislav Fomichev, Quentin Monnet
In-Reply-To: <20190809140956.24369b00@cakuba.netronome.com>

On 08/09, Jakub Kicinski wrote:
> On Fri, 9 Aug 2019 08:32:10 -0700, Stanislav Fomichev wrote:
> > On 08/09, Peter Wu wrote:
> > > /proc/config has never existed as far as I can see, but /proc/config.gz
> > > is present on Arch Linux. Add support for decompressing config.gz using
> > > zlib which is a mandatory dependency of libelf. Replace existing stdio
> > > functions with gzFile operations since the latter transparently handles
> > > uncompressed and gzip-compressed files.
> > > 
> > > Cc: Quentin Monnet <quentin.monnet@netronome.com>
> > > Signed-off-by: Peter Wu <peter@lekensteyn.nl>
> 
> Thanks for the patch, looks good to me now!
> 
> > >  tools/bpf/bpftool/Makefile  |   2 +-
> > >  tools/bpf/bpftool/feature.c | 105 ++++++++++++++++++------------------
> > >  2 files changed, 54 insertions(+), 53 deletions(-)
> > > 
> > > diff --git a/tools/bpf/bpftool/Makefile b/tools/bpf/bpftool/Makefile
> > > index a7afea4dec47..078bd0dcfba5 100644
> > > --- a/tools/bpf/bpftool/Makefile
> > > +++ b/tools/bpf/bpftool/Makefile
> > > @@ -52,7 +52,7 @@ ifneq ($(EXTRA_LDFLAGS),)
> > >  LDFLAGS += $(EXTRA_LDFLAGS)
> > >  endif
> > >  
> > > -LIBS = -lelf $(LIBBPF)
> > > +LIBS = -lelf -lz $(LIBBPF)  
> > You're saying in the commit description that bpftool already links
> > against -lz (via -lelf), but then explicitly add -lz here, why?
> 
> It probably won't hurt to enable the zlib test:
> 
> diff --git a/tools/bpf/bpftool/Makefile b/tools/bpf/bpftool/Makefile
> index 078bd0dcfba5..8176632e519c 100644
> --- a/tools/bpf/bpftool/Makefile
> +++ b/tools/bpf/bpftool/Makefile
> @@ -58,8 +58,8 @@ INSTALL ?= install
>  RM ?= rm -f
>  
>  FEATURE_USER = .bpftool
> -FEATURE_TESTS = libbfd disassembler-four-args reallocarray
> -FEATURE_DISPLAY = libbfd disassembler-four-args
> +FEATURE_TESTS = libbfd disassembler-four-args reallocarray zlib
> +FEATURE_DISPLAY = libbfd disassembler-four-args zlib
>  
>  check_feat := 1
>  NON_CHECK_FEAT_TARGETS := clean uninstall doc doc-clean doc-install doc-uninstall
> 
> And then we can test for it the way libbpf tests for elf:
> 
> all: zdep $(OUTPUT)bpftool
> 
> PHONY += zdep
> 
> zdep:
> 	@if [ "$(feature-zlib)" != "1" ]; then echo "No zlib found"; exit 1 ; fi
> 
> Or maybe just $(error ...), Stan what's your preference here? 
> We don't have a precedent for hard tests of features in bpftool.
I'm just being nit picky :-)
Because changelog says we already depend on -lz, but then in the patch
we explicitly add it.

I think you were right in pointing out that we already implicitly depend
on -lz via -lelf and/or -lbfd. And it works for non-static builds.
We don't need an explicit -lz unless somebody puts '-static' in
EXTRA_CFLAGS. So maybe we should just submit the patch as is because
it fixes make EXTRA_CFLAGS=-static.

RE $(error): we don't do it for -lelf, right? So probably not worth
the hassle for zlib.

^ permalink raw reply

* [PATCH net] rxrpc: Fix local refcounting
From: David Howells @ 2019-08-09 21:47 UTC (permalink / raw)
  To: netdev; +Cc: dhowells, jaltman, linux-afs, linux-kernel

Fix rxrpc_unuse_local() to handle a NULL local pointer as it can be called
on an unbound socket on which rx->local is not yet set.

The following reproduced (includes omitted):

	int main(void)
	{
		socket(AF_RXRPC, SOCK_DGRAM, AF_INET);
		return 0;
	}

causes the following oops to occur:

	BUG: kernel NULL pointer dereference, address: 0000000000000010
	...
	RIP: 0010:rxrpc_unuse_local+0x8/0x1b
	...
	Call Trace:
	 rxrpc_release+0x2b5/0x338
	 __sock_release+0x37/0xa1
	 sock_close+0x14/0x17
	 __fput+0x115/0x1e9
	 task_work_run+0x72/0x98
	 do_exit+0x51b/0xa7a
	 ? __context_tracking_exit+0x4e/0x10e
	 do_group_exit+0xab/0xab
	 __x64_sys_exit_group+0x14/0x17
	 do_syscall_64+0x89/0x1d4
	 entry_SYSCALL_64_after_hwframe+0x49/0xbe

Reported-by: syzbot+20dee719a2e090427b5f@syzkaller.appspotmail.com
Fixes: 730c5fd42c1e ("rxrpc: Fix local endpoint refcounting")
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Jeffrey Altman <jaltman@auristor.com>
---

 net/rxrpc/local_object.c |   12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/net/rxrpc/local_object.c b/net/rxrpc/local_object.c
index 9798159ee65f..c9db3e762d8d 100644
--- a/net/rxrpc/local_object.c
+++ b/net/rxrpc/local_object.c
@@ -402,11 +402,13 @@ void rxrpc_unuse_local(struct rxrpc_local *local)
 {
 	unsigned int au;
 
-	au = atomic_dec_return(&local->active_users);
-	if (au == 0)
-		rxrpc_queue_local(local);
-	else
-		rxrpc_put_local(local);
+	if (local) {
+		au = atomic_dec_return(&local->active_users);
+		if (au == 0)
+			rxrpc_queue_local(local);
+		else
+			rxrpc_put_local(local);
+	}
 }
 
 /*


^ permalink raw reply related

* Re: [v4,0/4] tools: bpftool: add net attach/detach command to attach XDP prog
From: Jakub Kicinski @ 2019-08-09 21:45 UTC (permalink / raw)
  To: Daniel T. Lee; +Cc: Daniel Borkmann, Alexei Starovoitov, netdev
In-Reply-To: <20190809133248.19788-1-danieltimlee@gmail.com>

On Fri,  9 Aug 2019 22:32:44 +0900, Daniel T. Lee wrote:
> Currently, bpftool net only supports dumping progs attached on the
> interface. To attach XDP prog on interface, user must use other tool
> (eg. iproute2). By this patch, with `bpftool net attach/detach`, user
> can attach/detach XDP prog on interface.
> 
>     # bpftool prog
>         16: xdp  name xdp_prog1  tag 539ec6ce11b52f98  gpl
>         loaded_at 2019-08-07T08:30:17+0900  uid 0
>         ...
>         20: xdp  name xdp_fwd_prog  tag b9cb69f121e4a274  gpl
>         loaded_at 2019-08-07T08:30:17+0900  uid 0
> 
>     # bpftool net attach xdpdrv id 16 dev enp6s0np0
>     # bpftool net
>     xdp:
>         enp6s0np0(4) driver id 16
> 
>     # bpftool net attach xdpdrv id 20 dev enp6s0np0 overwrite
>     # bpftool net
>     xdp:
>         enp6s0np0(4) driver id 20
> 
>     # bpftool net detach xdpdrv dev enp6s0np0
>     # bpftool net
>     xdp:
> 
> 
> While this patch only contains support for XDP, through `net
> attach/detach`, bpftool can further support other prog attach types.
> 
> XDP attach/detach tested on Mellanox ConnectX-4 and Netronome Agilio.

Looks good to me now*, thanks!

Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>

* apart from the entire duplication thing.

^ permalink raw reply

* Re: [patch net-next] netdevsim: register couple of devlink params
From: Jakub Kicinski @ 2019-08-09 21:26 UTC (permalink / raw)
  To: Jiri Pirko; +Cc: netdev, davem, mlxsw
In-Reply-To: <20190809110512.31779-1-jiri@resnulli.us>

On Fri,  9 Aug 2019 13:05:12 +0200, Jiri Pirko wrote:
> From: Jiri Pirko <jiri@mellanox.com>
> 
> Register couple of devlink params, one generic, one driver-specific.
> Make the values available over debugfs.
> 
> Example:
> $ echo "111" > /sys/bus/netdevsim/new_device
> $ devlink dev param
> netdevsim/netdevsim111:
>   name max_macs type generic
>     values:
>       cmode driverinit value 32
>   name test1 type driver-specific
>     values:
>       cmode driverinit value true
> $ cat /sys/kernel/debug/netdevsim/netdevsim111/max_macs
> 32
> $ cat /sys/kernel/debug/netdevsim/netdevsim111/test1
> Y
> $ devlink dev param set netdevsim/netdevsim111 name max_macs cmode driverinit value 16
> $ devlink dev param set netdevsim/netdevsim111 name test1 cmode driverinit value false
> $ devlink dev reload netdevsim/netdevsim111
> $ cat /sys/kernel/debug/netdevsim/netdevsim111/max_macs
> 16
> $ cat /sys/kernel/debug/netdevsim/netdevsim111/test1
> 
> Signed-off-by: Jiri Pirko <jiri@mellanox.com>

The netdevsim patch looks good, what's the plan for tests?

We don't need much perhaps what you have in the commit message 
as a script which can be run by automated bots would be sufficient?

^ permalink raw reply

* Re: [PATCH v4 7/9] mfd: ioc3: Add driver for SGI IOC3 chip
From: Jakub Kicinski @ 2019-08-09 21:22 UTC (permalink / raw)
  To: Thomas Bogendoerfer
  Cc: Ralf Baechle, Paul Burton, James Hogan, Dmitry Torokhov,
	Lee Jones, David S. Miller, Srinivas Kandagatla, Alessandro Zummo,
	Alexandre Belloni, Greg Kroah-Hartman, Jiri Slaby,
	Evgeniy Polyakov, linux-mips, linux-kernel, linux-input, netdev,
	linux-rtc, linux-serial
In-Reply-To: <20190809103235.16338-8-tbogendoerfer@suse.de>

On Fri,  9 Aug 2019 12:32:29 +0200, Thomas Bogendoerfer wrote:
> SGI IOC3 chip has integrated ethernet, keyboard and mouse interface.
> It also supports connecting a SuperIO chip for serial and parallel
> interfaces. IOC3 is used inside various SGI systemboards and add-on
> cards with different equipped external interfaces.
> 
> Support for ethernet and serial interfaces were implemented inside
> the network driver. This patchset moves out the not network related
> parts to a new MFD driver, which takes care of card detection,
> setup of platform devices and interrupt distribution for the subdevices.
> 
> Serial portion: Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> 
> Signed-off-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>

There are a lot of changes in the ethernet part which are not easy to
explain by the introduction of the other MFD parts.. Could you possibly
break this change up into smaller chunks?

Also please don't use stdint types in the kernel, please try checkpatch
to catch coding style issues.

^ permalink raw reply

* Re: [net-next 01/15] ice: Implement ethtool ops for channels
From: Jakub Kicinski @ 2019-08-09 21:15 UTC (permalink / raw)
  To: Jeff Kirsher
  Cc: davem, Henry Tieman, netdev, nhorman, sassmann, Tony Nguyen,
	Andrew Bowers
In-Reply-To: <20190809183139.30871-2-jeffrey.t.kirsher@intel.com>

On Fri,  9 Aug 2019 11:31:25 -0700, Jeff Kirsher wrote:
> From: Henry Tieman <henry.w.tieman@intel.com>
> 
> Add code to query and set the number of queues on the primary
> VSI for a PF. This is accessed from the 'ethtool -l' and 'ethtool -L'
> commands, respectively.
> 
> Signed-off-by: Henry Tieman <henry.w.tieman@intel.com>
> Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
> Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>

If you're using the same IRQ vector for RX and TX queue the channel
counts as combined. Looks like you are counting RX and TX separately
here. That's incorrect.

^ permalink raw reply

* Re: [Potential Spoof] Re: [PATCH net-next v6 3/3] net: phy: broadcom: add 1000Base-X support for BCM54616S
From: Tao Ren @ 2019-08-09 21:13 UTC (permalink / raw)
  To: Heiner Kallweit, Andrew Lunn, Florian Fainelli, David S . Miller,
	Arun Parameswaran, Justin Chen, Vladimir Oltean,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
	openbmc@lists.ozlabs.org
In-Reply-To: <e556dd17-ef85-3c61-bc08-17db02d9a5dc@fb.com>

On 8/9/19 1:54 PM, Tao Ren wrote:
> Hi Heiner,
> 
> On 8/9/19 1:21 PM, Heiner Kallweit wrote:
>> On 09.08.2019 07:44, Tao Ren wrote:
>>> The BCM54616S PHY cannot work properly in RGMII->1000Base-KX mode (for
>>> example, on Facebook CMM BMC platform), mainly because genphy functions
>>> are designed for copper links, and 1000Base-X (clause 37) auto negotiation
>>> needs to be handled differently.
>>>
>>> This patch enables 1000Base-X support for BCM54616S by customizing 3
>>> driver callbacks:
>>>
>>>   - probe: probe callback detects PHY's operation mode based on
>>>     INTERF_SEL[1:0] pins and 1000X/100FX selection bit in SerDES 100-FX
>>>     Control register.
>>>
>>>   - config_aneg: calls genphy_c37_config_aneg when the PHY is running in
>>>     1000Base-X mode; otherwise, genphy_config_aneg will be called.
>>>
>>>   - read_status: calls genphy_c37_read_status when the PHY is running in
>>>     1000Base-X mode; otherwise, genphy_read_status will be called.
>>>
>>> Signed-off-by: Tao Ren <taoren@fb.com>
>>> ---
>>>  Changes in v6:
>>>   - nothing changed.
>>>  Changes in v5:
>>>   - include Heiner's patch "net: phy: add support for clause 37
>>>     auto-negotiation" into the series.
>>>   - use genphy_c37_config_aneg and genphy_c37_read_status in BCM54616S
>>>     PHY driver's callback when the PHY is running in 1000Base-X mode.
>>>  Changes in v4:
>>>   - add bcm54616s_config_aneg_1000bx() to deal with auto negotiation in
>>>     1000Base-X mode.
>>>  Changes in v3:
>>>   - rename bcm5482_read_status to bcm54xx_read_status so the callback can
>>>     be shared by BCM5482 and BCM54616S.
>>>  Changes in v2:
>>>   - Auto-detect PHY operation mode instead of passing DT node.
>>>   - move PHY mode auto-detect logic from config_init to probe callback.
>>>   - only set speed (not including duplex) in read_status callback.
>>>   - update patch description with more background to avoid confusion.
>>>   - patch #1 in the series ("net: phy: broadcom: set features explicitly
>>>     for BCM54616") is dropped: the fix should go to get_features callback
>>>     which may potentially depend on this patch.
>>>
>>>  drivers/net/phy/broadcom.c | 54 +++++++++++++++++++++++++++++++++++---
>>>  include/linux/brcmphy.h    | 10 +++++--
>>>  2 files changed, 58 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
>>> index 937d0059e8ac..fbd76a31c142 100644
>>> --- a/drivers/net/phy/broadcom.c
>>> +++ b/drivers/net/phy/broadcom.c
>>> @@ -383,9 +383,9 @@ static int bcm5482_config_init(struct phy_device *phydev)
>>>  		/*
>>>  		 * Select 1000BASE-X register set (primary SerDes)
>>>  		 */
>>> -		reg = bcm_phy_read_shadow(phydev, BCM5482_SHD_MODE);
>>> -		bcm_phy_write_shadow(phydev, BCM5482_SHD_MODE,
>>> -				     reg | BCM5482_SHD_MODE_1000BX);
>>> +		reg = bcm_phy_read_shadow(phydev, BCM54XX_SHD_MODE);
>>> +		bcm_phy_write_shadow(phydev, BCM54XX_SHD_MODE,
>>> +				     reg | BCM54XX_SHD_MODE_1000BX);
>>>  
>>>  		/*
>>>  		 * LED1=ACTIVITYLED, LED3=LINKSPD[2]
>>> @@ -451,12 +451,44 @@ static int bcm5481_config_aneg(struct phy_device *phydev)
>>>  	return ret;
>>>  }
>>>  
>>> +static int bcm54616s_probe(struct phy_device *phydev)
>>> +{
>>> +	int val, intf_sel;
>>> +
>>> +	val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_MODE);
>>> +	if (val < 0)
>>> +		return val;
>>> +
>>> +	/* The PHY is strapped in RGMII to fiber mode when INTERF_SEL[1:0]
>>> +	 * is 01b.
>>> +	 */
>>> +	intf_sel = (val & BCM54XX_SHD_INTF_SEL_MASK) >> 1;
>>> +	if (intf_sel == 1) {
>>> +		val = bcm_phy_read_shadow(phydev, BCM54616S_SHD_100FX_CTRL);
>>> +		if (val < 0)
>>> +			return val;
>>> +
>>> +		/* Bit 0 of the SerDes 100-FX Control register, when set
>>> +		 * to 1, sets the MII/RGMII -> 100BASE-FX configuration.
>>> +		 * When this bit is set to 0, it sets the GMII/RGMII ->
>>> +		 * 1000BASE-X configuration.
>>> +		 */
>>> +		if (!(val & BCM54616S_100FX_MODE))
>>> +			phydev->dev_flags |= PHY_BCM_FLAGS_MODE_1000BX;
>>> +	}
>>> +
>>> +	return 0;
>>> +}
>>> +
>>>  static int bcm54616s_config_aneg(struct phy_device *phydev)
>>>  {
>>>  	int ret;
>>>  
>>>  	/* Aneg firsly. */
>>> -	ret = genphy_config_aneg(phydev);
>>> +	if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX)
>>> +		ret = genphy_c37_config_aneg(phydev);
>>> +	else
>>> +		ret = genphy_config_aneg(phydev);
>>>  
>>
>> I'm just wondering whether it needs to be considered that 100base-FX
>> doesn't support auto-negotiation. I suppose BMSR reports aneg as
>> supported, therefore phylib will use aneg per default.
>> Not sure who could set 100Base-FX mode when, but maybe at that place
>> also phydev->autoneg needs to be cleared. Did you test 100Base-FX mode?
> 
> I'm doubting if 100Base-FX works. Besides auto-negotiation, 100Base-FX Control/Status registers are defined in shadow register instead of MII_BMCR and MII_BMSR.
> 
> Unfortunately I don't have environment to test 100Base-FX and that's why I only make changes when the PHY is working in 1000X mode.

I can prepare a patch for 100Base-FX based on my understanding of bcm54616s datasheet, but the patch would be just compile-tested 


Thanks,

Tao

^ permalink raw reply

* Re: [PATCH v3] tools: bpftool: fix reading from /proc/config.gz
From: Jakub Kicinski @ 2019-08-09 21:09 UTC (permalink / raw)
  To: Stanislav Fomichev
  Cc: Peter Wu, Alexei Starovoitov, Daniel Borkmann, netdev,
	Stanislav Fomichev, Quentin Monnet
In-Reply-To: <20190809153210.GD2820@mini-arch>

On Fri, 9 Aug 2019 08:32:10 -0700, Stanislav Fomichev wrote:
> On 08/09, Peter Wu wrote:
> > /proc/config has never existed as far as I can see, but /proc/config.gz
> > is present on Arch Linux. Add support for decompressing config.gz using
> > zlib which is a mandatory dependency of libelf. Replace existing stdio
> > functions with gzFile operations since the latter transparently handles
> > uncompressed and gzip-compressed files.
> > 
> > Cc: Quentin Monnet <quentin.monnet@netronome.com>
> > Signed-off-by: Peter Wu <peter@lekensteyn.nl>

Thanks for the patch, looks good to me now!

> >  tools/bpf/bpftool/Makefile  |   2 +-
> >  tools/bpf/bpftool/feature.c | 105 ++++++++++++++++++------------------
> >  2 files changed, 54 insertions(+), 53 deletions(-)
> > 
> > diff --git a/tools/bpf/bpftool/Makefile b/tools/bpf/bpftool/Makefile
> > index a7afea4dec47..078bd0dcfba5 100644
> > --- a/tools/bpf/bpftool/Makefile
> > +++ b/tools/bpf/bpftool/Makefile
> > @@ -52,7 +52,7 @@ ifneq ($(EXTRA_LDFLAGS),)
> >  LDFLAGS += $(EXTRA_LDFLAGS)
> >  endif
> >  
> > -LIBS = -lelf $(LIBBPF)
> > +LIBS = -lelf -lz $(LIBBPF)  
> You're saying in the commit description that bpftool already links
> against -lz (via -lelf), but then explicitly add -lz here, why?

It probably won't hurt to enable the zlib test:

diff --git a/tools/bpf/bpftool/Makefile b/tools/bpf/bpftool/Makefile
index 078bd0dcfba5..8176632e519c 100644
--- a/tools/bpf/bpftool/Makefile
+++ b/tools/bpf/bpftool/Makefile
@@ -58,8 +58,8 @@ INSTALL ?= install
 RM ?= rm -f
 
 FEATURE_USER = .bpftool
-FEATURE_TESTS = libbfd disassembler-four-args reallocarray
-FEATURE_DISPLAY = libbfd disassembler-four-args
+FEATURE_TESTS = libbfd disassembler-four-args reallocarray zlib
+FEATURE_DISPLAY = libbfd disassembler-four-args zlib
 
 check_feat := 1
 NON_CHECK_FEAT_TARGETS := clean uninstall doc doc-clean doc-install doc-uninstall

And then we can test for it the way libbpf tests for elf:

all: zdep $(OUTPUT)bpftool

PHONY += zdep

zdep:
	@if [ "$(feature-zlib)" != "1" ]; then echo "No zlib found"; exit 1 ; fi

Or maybe just $(error ...), Stan what's your preference here? 
We don't have a precedent for hard tests of features in bpftool.

^ permalink raw reply related

* Re: [PATCH v5 bpf-next] BPF: helpers: New helper to obtain namespacedata from current task
From: Carlos Antonio Neira Bustos @ 2019-08-09 21:03 UTC (permalink / raw)
  To: Yonghong Song
  Cc: Y Song, netdev@vger.kernel.org, ebiederm@xmission.com,
	brouer@redhat.com, bpf, quentin.monnet@netronome.com
In-Reply-To: <20190808211714.taet5fjr6q43na5i@dev00>

Yonghong,

I have splitted the patch in 2 :

- bpf_helper introduction :
 

From 40ec0781525b82d5235c45f5066a7a79dea71065 Mon Sep 17 00:00:00 2001
From: Carlos <cneirabustos@gmail.com>
Date: Fri, 9 Aug 2019 12:20:52 -0700
Subject: [PATCH 1/2] [PATCH v8 bpf-next 1/2] BPF: New helper to obtain
 namespace data  from current task

This helper obtains the active namespace from current and returns pid, tgid,
device and namespace id as seen from that namespace, allowing to instrument
a process inside a container.
Device is read from /proc/self/ns/pid, as in the future it's possible that
different pid_ns files may belong to different devices, according
to the discussion between Eric Biederman and Yonghong in 2017 linux plumbers
conference.
Currently bpf_get_current_pid_tgid(), is used to do pid filtering in bcc's
scripts but this helper returns the pid as seen by the root namespace which is
fine when a bcc script is not executed inside a container.
When the process of interest is inside a container, pid filtering will not work
if bpf_get_current_pid_tgid() is used. This helper addresses this limitation
returning the pid as it's seen by the current namespace where the script is
executing.

This helper has the same use cases as bpf_get_current_pid_tgid() as it can be
used to do pid filtering even inside a container.

For example a bcc script using bpf_get_current_pid_tgid() (tools/funccount.py):

        u32 pid = bpf_get_current_pid_tgid() >> 32;
        if (pid != <pid_arg_passed_in>)
                return 0;
Could be modified to use bpf_get_current_pidns_info() as follows:

        struct bpf_pidns pidns;
        bpf_get_current_pidns_info(&pidns, sizeof(struct bpf_pidns));
        u32 pid = pidns.tgid;
        u32 nsid = pidns.nsid;
        if ((pid != <pid_arg_passed_in>) && (nsid != <nsid_arg_passed_in>))
                return 0;

To find out the name PID namespace id of a process, you could use this command:

$ ps -h -o pidns -p <pid_of_interest>

Or this other command:

$ ls -Li /proc/<pid_of_interest>/ns/pid

Signed-off-by: Carlos Neira <cneirabustos@gmail.com>
---
 fs/internal.h                  |  2 --
 fs/namei.c                     |  1 -
 include/linux/bpf.h            |  1 +
 include/linux/namei.h          |  4 +++
 include/uapi/linux/bpf.h       | 31 +++++++++++++++++++-
 kernel/bpf/core.c              |  1 +
 kernel/bpf/helpers.c           | 64 ++++++++++++++++++++++++++++++++++++++++++
 kernel/trace/bpf_trace.c       |  2 ++
 tools/include/uapi/linux/bpf.h | 31 +++++++++++++++++++-
 9 files changed, 132 insertions(+), 5 deletions(-)

diff --git a/fs/internal.h b/fs/internal.h
index 315fcd8d237c..6647e15dd419 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -59,8 +59,6 @@ extern int finish_clean_context(struct fs_context *fc);
 /*
  * namei.c
  */
-extern int filename_lookup(int dfd, struct filename *name, unsigned flags,
-			   struct path *path, struct path *root);
 extern int user_path_mountpoint_at(int, const char __user *, unsigned int, struct path *);
 extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
 			   const char *, unsigned int, struct path *);
diff --git a/fs/namei.c b/fs/namei.c
index 209c51a5226c..a89fc72a4a10 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -19,7 +19,6 @@
 #include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/fs.h>
 #include <linux/namei.h>
 #include <linux/pagemap.h>
 #include <linux/fsnotify.h>
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index f9a506147c8a..e4adf5e05afd 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -1050,6 +1050,7 @@ extern const struct bpf_func_proto bpf_get_local_storage_proto;
 extern const struct bpf_func_proto bpf_strtol_proto;
 extern const struct bpf_func_proto bpf_strtoul_proto;
 extern const struct bpf_func_proto bpf_tcp_sock_proto;
+extern const struct bpf_func_proto bpf_get_current_pidns_info_proto;
 
 /* Shared helpers among cBPF and eBPF. */
 void bpf_user_rnd_init_once(void);
diff --git a/include/linux/namei.h b/include/linux/namei.h
index 9138b4471dbf..b45c8b6f7cb4 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -6,6 +6,7 @@
 #include <linux/path.h>
 #include <linux/fcntl.h>
 #include <linux/errno.h>
+#include <linux/fs.h>
 
 enum { MAX_NESTED_LINKS = 8 };
 
@@ -97,6 +98,9 @@ extern void unlock_rename(struct dentry *, struct dentry *);
 
 extern void nd_jump_link(struct path *path);
 
+extern int filename_lookup(int dfd, struct filename *name, unsigned flags,
+			   struct path *path, struct path *root);
+
 static inline void nd_terminate_link(void *name, size_t len, size_t maxlen)
 {
 	((char *) name)[min(len, maxlen)] = '\0';
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 4393bd4b2419..db241857ec15 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -2741,6 +2741,28 @@ union bpf_attr {
  *		**-EOPNOTSUPP** kernel configuration does not enable SYN cookies
  *
  *		**-EPROTONOSUPPORT** IP packet version is not 4 or 6
+ *
+ * int bpf_get_current_pidns_info(struct bpf_pidns_info *pidns, u32 size_of_pidns)
+ *	Description
+ *		Copies into *pidns* pid, namespace id and tgid as seen by the
+ *		current namespace and also device from /proc/self/ns/pid.
+ *		*size_of_pidns* must be the size of *pidns*
+ *
+ *		This helper is used when pid filtering is needed inside a
+ *		container as bpf_get_current_tgid() helper returns always the
+ *		pid id as seen by the root namespace.
+ *	Return
+ *		0 on success
+ *
+ *		**-EINVAL** if *size_of_pidns* is not valid or unable to get ns, pid
+ *		or tgid of the current task.
+ *
+ *		**-ECHILD** if /proc/self/ns/pid does not exists.
+ *
+ *		**-ENOTDIR** if /proc/self/ns does not exists.
+ *
+ *		**-ENOMEM**  if allocation fails.
+ *
  */
 #define __BPF_FUNC_MAPPER(FN)		\
 	FN(unspec),			\
@@ -2853,7 +2875,8 @@ union bpf_attr {
 	FN(sk_storage_get),		\
 	FN(sk_storage_delete),		\
 	FN(send_signal),		\
-	FN(tcp_gen_syncookie),
+	FN(tcp_gen_syncookie),		\
+	FN(get_current_pidns_info),
 
 /* integer value in 'imm' field of BPF_CALL instruction selects which helper
  * function eBPF program intends to call
@@ -3604,4 +3627,10 @@ struct bpf_sockopt {
 	__s32	retval;
 };
 
+struct bpf_pidns_info {
+	__u32 dev;
+	__u32 nsid;
+	__u32 tgid;
+	__u32 pid;
+};
 #endif /* _UAPI__LINUX_BPF_H__ */
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 8191a7db2777..3159f2a0188c 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -2038,6 +2038,7 @@ const struct bpf_func_proto bpf_get_current_uid_gid_proto __weak;
 const struct bpf_func_proto bpf_get_current_comm_proto __weak;
 const struct bpf_func_proto bpf_get_current_cgroup_id_proto __weak;
 const struct bpf_func_proto bpf_get_local_storage_proto __weak;
+const struct bpf_func_proto bpf_get_current_pidns_info __weak;
 
 const struct bpf_func_proto * __weak bpf_get_trace_printk_proto(void)
 {
diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
index 5e28718928ca..41fbf1f28a48 100644
--- a/kernel/bpf/helpers.c
+++ b/kernel/bpf/helpers.c
@@ -11,6 +11,12 @@
 #include <linux/uidgid.h>
 #include <linux/filter.h>
 #include <linux/ctype.h>
+#include <linux/pid_namespace.h>
+#include <linux/major.h>
+#include <linux/stat.h>
+#include <linux/namei.h>
+#include <linux/version.h>
+
 
 #include "../../lib/kstrtox.h"
 
@@ -312,6 +318,64 @@ void copy_map_value_locked(struct bpf_map *map, void *dst, void *src,
 	preempt_enable();
 }
 
+BPF_CALL_2(bpf_get_current_pidns_info, struct bpf_pidns_info *, pidns_info, u32,
+	 size)
+{
+	const char *pidns_path = "/proc/self/ns/pid";
+	struct pid_namespace *pidns = NULL;
+	struct filename *tmp = NULL;
+	struct inode *inode;
+	struct path kp;
+	pid_t tgid = 0;
+	pid_t pid = 0;
+	int ret;
+	int len;
+
+	if (unlikely(size != sizeof(struct bpf_pidns_info)))
+		return -EINVAL;
+	pidns = task_active_pid_ns(current);
+	if (unlikely(!pidns))
+		goto clear;
+	pidns_info->nsid =  pidns->ns.inum;
+	pid = task_pid_nr_ns(current, pidns);
+	if (unlikely(!pid))
+		goto clear;
+	tgid = task_tgid_nr_ns(current, pidns);
+	if (unlikely(!tgid))
+		goto clear;
+	pidns_info->tgid = (u32) tgid;
+	pidns_info->pid = (u32) pid;
+	tmp = kmem_cache_alloc(names_cachep, GFP_ATOMIC);
+	if (unlikely(!tmp)) {
+		memset((void *)pidns_info, 0, (size_t) size);
+		return -ENOMEM;
+	}
+	len = strlen(pidns_path) + 1;
+	memcpy((char *)tmp->name, pidns_path, len);
+	tmp->uptr = NULL;
+	tmp->aname = NULL;
+	tmp->refcnt = 1;
+	ret = filename_lookup(AT_FDCWD, tmp, 0, &kp, NULL);
+	if (ret) {
+		memset((void *)pidns_info, 0, (size_t) size);
+		return ret;
+	}
+	inode = d_backing_inode(kp.dentry);
+	pidns_info->dev = inode->i_sb->s_dev;
+	return 0;
+clear:
+	memset((void *)pidns_info, 0, (size_t) size);
+	return -EINVAL;
+}
+
+const struct bpf_func_proto bpf_get_current_pidns_info_proto = {
+	.func		= bpf_get_current_pidns_info,
+	.gpl_only	= false,
+	.ret_type	= RET_INTEGER,
+	.arg1_type	= ARG_PTR_TO_UNINIT_MEM,
+	.arg2_type	= ARG_CONST_SIZE,
+};
+
 #ifdef CONFIG_CGROUPS
 BPF_CALL_0(bpf_get_current_cgroup_id)
 {
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index ca1255d14576..5e1dc22765a5 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -709,6 +709,8 @@ tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
 #endif
 	case BPF_FUNC_send_signal:
 		return &bpf_send_signal_proto;
+	case BPF_FUNC_get_current_pidns_info:
+		return &bpf_get_current_pidns_info_proto;
 	default:
 		return NULL;
 	}
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 4393bd4b2419..db241857ec15 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -2741,6 +2741,28 @@ union bpf_attr {
  *		**-EOPNOTSUPP** kernel configuration does not enable SYN cookies
  *
  *		**-EPROTONOSUPPORT** IP packet version is not 4 or 6
+ *
+ * int bpf_get_current_pidns_info(struct bpf_pidns_info *pidns, u32 size_of_pidns)
+ *	Description
+ *		Copies into *pidns* pid, namespace id and tgid as seen by the
+ *		current namespace and also device from /proc/self/ns/pid.
+ *		*size_of_pidns* must be the size of *pidns*
+ *
+ *		This helper is used when pid filtering is needed inside a
+ *		container as bpf_get_current_tgid() helper returns always the
+ *		pid id as seen by the root namespace.
+ *	Return
+ *		0 on success
+ *
+ *		**-EINVAL** if *size_of_pidns* is not valid or unable to get ns, pid
+ *		or tgid of the current task.
+ *
+ *		**-ECHILD** if /proc/self/ns/pid does not exists.
+ *
+ *		**-ENOTDIR** if /proc/self/ns does not exists.
+ *
+ *		**-ENOMEM**  if allocation fails.
+ *
  */
 #define __BPF_FUNC_MAPPER(FN)		\
 	FN(unspec),			\
@@ -2853,7 +2875,8 @@ union bpf_attr {
 	FN(sk_storage_get),		\
 	FN(sk_storage_delete),		\
 	FN(send_signal),		\
-	FN(tcp_gen_syncookie),
+	FN(tcp_gen_syncookie),		\
+	FN(get_current_pidns_info),
 
 /* integer value in 'imm' field of BPF_CALL instruction selects which helper
  * function eBPF program intends to call
@@ -3604,4 +3627,10 @@ struct bpf_sockopt {
 	__s32	retval;
 };
 
+struct bpf_pidns_info {
+	__u32 dev;
+	__u32 nsid;
+	__u32 tgid;
+	__u32 pid;
+};
 #endif /* _UAPI__LINUX_BPF_H__ */
-- 
2.11.0


- BPF helper samples and selftests 

From a87df8b026c6374c21b2af03d83471c258ff6038 Mon Sep 17 00:00:00 2001
From: Carlos <cneirabustos@gmail.com>
Date: Fri, 9 Aug 2019 12:23:27 -0700
Subject: [PATCH 2/2] [PATCH v8 bpf-next 2/2] BPF: New helper to obtain
 namespace data  from current task

Samples and selftests for new helper.

Signed-off-by: Carlos Neira <cneirabustos@gmail.com>
---
 samples/bpf/Makefile                               |   3 +
 samples/bpf/trace_ns_info_user.c                   |  35 ++++++
 samples/bpf/trace_ns_info_user_kern.c              |  44 +++++++
 tools/testing/selftests/bpf/Makefile               |   2 +-
 tools/testing/selftests/bpf/bpf_helpers.h          |   3 +
 .../testing/selftests/bpf/progs/test_pidns_kern.c  |  51 ++++++++
 tools/testing/selftests/bpf/test_pidns.c           | 138 +++++++++++++++++++++
 7 files changed, 275 insertions(+), 1 deletion(-)
 create mode 100644 samples/bpf/trace_ns_info_user.c
 create mode 100644 samples/bpf/trace_ns_info_user_kern.c
 create mode 100644 tools/testing/selftests/bpf/progs/test_pidns_kern.c
 create mode 100644 tools/testing/selftests/bpf/test_pidns.c

diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
index 1d9be26b4edd..238453ff27d2 100644
--- a/samples/bpf/Makefile
+++ b/samples/bpf/Makefile
@@ -53,6 +53,7 @@ hostprogs-y += task_fd_query
 hostprogs-y += xdp_sample_pkts
 hostprogs-y += ibumad
 hostprogs-y += hbm
+hostprogs-y += trace_ns_info
 
 # Libbpf dependencies
 LIBBPF = $(TOOLS_PATH)/lib/bpf/libbpf.a
@@ -109,6 +110,7 @@ task_fd_query-objs := bpf_load.o task_fd_query_user.o $(TRACE_HELPERS)
 xdp_sample_pkts-objs := xdp_sample_pkts_user.o $(TRACE_HELPERS)
 ibumad-objs := bpf_load.o ibumad_user.o $(TRACE_HELPERS)
 hbm-objs := bpf_load.o hbm.o $(CGROUP_HELPERS)
+trace_ns_info-objs := bpf_load.o trace_ns_info_user.o
 
 # Tell kbuild to always build the programs
 always := $(hostprogs-y)
@@ -170,6 +172,7 @@ always += xdp_sample_pkts_kern.o
 always += ibumad_kern.o
 always += hbm_out_kern.o
 always += hbm_edt_kern.o
+always += trace_ns_info_user_kern.o
 
 KBUILD_HOSTCFLAGS += -I$(objtree)/usr/include
 KBUILD_HOSTCFLAGS += -I$(srctree)/tools/lib/bpf/
diff --git a/samples/bpf/trace_ns_info_user.c b/samples/bpf/trace_ns_info_user.c
new file mode 100644
index 000000000000..e06d08db6f30
--- /dev/null
+++ b/samples/bpf/trace_ns_info_user.c
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2018 Carlos Neira cneirabustos@gmail.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ */
+
+#include <stdio.h>
+#include <linux/bpf.h>
+#include <unistd.h>
+#include "bpf/libbpf.h"
+#include "bpf_load.h"
+
+/* This code was taken verbatim from tracex1_user.c, it's used
+ * to exercize bpf_get_current_pidns_info() helper call.
+ */
+int main(int ac, char **argv)
+{
+	FILE *f;
+	char filename[256];
+
+	snprintf(filename, sizeof(filename), "%s_user_kern.o", argv[0]);
+	printf("loading %s\n", filename);
+
+	if (load_bpf_file(filename)) {
+		printf("%s", bpf_log_buf);
+		return 1;
+	}
+
+	f = popen("taskset 1 ping  localhost", "r");
+	(void) f;
+	read_trace_pipe();
+	return 0;
+}
diff --git a/samples/bpf/trace_ns_info_user_kern.c b/samples/bpf/trace_ns_info_user_kern.c
new file mode 100644
index 000000000000..96675e02b707
--- /dev/null
+++ b/samples/bpf/trace_ns_info_user_kern.c
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2018 Carlos Neira cneirabustos@gmail.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ */
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/version.h>
+#include <uapi/linux/bpf.h>
+#include "bpf_helpers.h"
+
+typedef __u64 u64;
+typedef __u32 u32;
+
+
+/* kprobe is NOT a stable ABI
+ * kernel functions can be removed, renamed or completely change semantics.
+ * Number of arguments and their positions can change, etc.
+ * In such case this bpf+kprobe example will no longer be meaningful
+ */
+
+/* This will call bpf_get_current_pidns_info() to display pid and ns values
+ * as seen by the current namespace, on the far left you will see the pid as
+ * seen as by the root namespace.
+ */
+
+SEC("kprobe/__netif_receive_skb_core")
+int bpf_prog1(struct pt_regs *ctx)
+{
+	char fmt[] = "nsid:%u, dev: %u,  pid:%u\n";
+	struct bpf_pidns_info nsinfo;
+	int ok = 0;
+
+	ok = bpf_get_current_pidns_info(&nsinfo, sizeof(nsinfo));
+	if (ok == 0)
+		bpf_trace_printk(fmt, sizeof(fmt), (u32)nsinfo.nsid,
+				 (u32) nsinfo.dev, (u32)nsinfo.pid);
+
+	return 0;
+}
+char _license[] SEC("license") = "GPL";
+u32 _version SEC("version") = LINUX_VERSION_CODE;
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index 3bd0f4a0336a..1f97b571b581 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -29,7 +29,7 @@ TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test
 	test_cgroup_storage test_select_reuseport test_section_names \
 	test_netcnt test_tcpnotify_user test_sock_fields test_sysctl test_hashmap \
 	test_btf_dump test_cgroup_attach xdping test_sockopt test_sockopt_sk \
-	test_sockopt_multi test_tcp_rtt
+	test_sockopt_multi test_tcp_rtt test_pidns
 
 BPF_OBJ_FILES = $(patsubst %.c,%.o, $(notdir $(wildcard progs/*.c)))
 TEST_GEN_FILES = $(BPF_OBJ_FILES)
diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h
index 8b503ea142f0..3fae3b9fcd2c 100644
--- a/tools/testing/selftests/bpf/bpf_helpers.h
+++ b/tools/testing/selftests/bpf/bpf_helpers.h
@@ -231,6 +231,9 @@ static int (*bpf_send_signal)(unsigned sig) = (void *)BPF_FUNC_send_signal;
 static long long (*bpf_tcp_gen_syncookie)(struct bpf_sock *sk, void *ip,
 					  int ip_len, void *tcp, int tcp_len) =
 	(void *) BPF_FUNC_tcp_gen_syncookie;
+static int (*bpf_get_current_pidns_info)(struct bpf_pidns_info *buf,
+					 unsigned int buf_size) =
+	(void *) BPF_FUNC_get_current_pidns_info;
 
 /* llvm builtin functions that eBPF C program may use to
  * emit BPF_LD_ABS and BPF_LD_IND instructions
diff --git a/tools/testing/selftests/bpf/progs/test_pidns_kern.c b/tools/testing/selftests/bpf/progs/test_pidns_kern.c
new file mode 100644
index 000000000000..e1d2facfa762
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/test_pidns_kern.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2018 Carlos Neira cneirabustos@gmail.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ */
+
+#include <linux/bpf.h>
+#include <errno.h>
+#include "bpf_helpers.h"
+
+struct bpf_map_def SEC("maps") nsidmap = {
+	.type = BPF_MAP_TYPE_ARRAY,
+	.key_size = sizeof(__u32),
+	.value_size = sizeof(__u32),
+	.max_entries = 1,
+};
+
+struct bpf_map_def SEC("maps") pidmap = {
+	.type = BPF_MAP_TYPE_ARRAY,
+	.key_size = sizeof(__u32),
+	.value_size = sizeof(__u32),
+	.max_entries = 1,
+};
+
+SEC("tracepoint/syscalls/sys_enter_nanosleep")
+int trace(void *ctx)
+{
+	struct bpf_pidns_info nsinfo;
+	__u32 key = 0, *expected_pid, *val;
+	char fmt[] = "ERROR nspid:%d\n";
+
+	if (bpf_get_current_pidns_info(&nsinfo, sizeof(nsinfo)))
+		return -EINVAL;
+
+	expected_pid = bpf_map_lookup_elem(&pidmap, &key);
+
+
+	if (!expected_pid || *expected_pid != nsinfo.pid)
+		return 0;
+
+	val = bpf_map_lookup_elem(&nsidmap, &key);
+	if (val)
+		*val = nsinfo.nsid;
+
+	return 0;
+}
+
+char _license[] SEC("license") = "GPL";
+__u32 _version SEC("version") = 1;
diff --git a/tools/testing/selftests/bpf/test_pidns.c b/tools/testing/selftests/bpf/test_pidns.c
new file mode 100644
index 000000000000..a7254055f294
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_pidns.c
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2018 Carlos Neira cneirabustos@gmail.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <syscall.h>
+#include <unistd.h>
+#include <linux/perf_event.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <linux/bpf.h>
+#include <bpf/bpf.h>
+#include <bpf/libbpf.h>
+
+#include "cgroup_helpers.h"
+#include "bpf_rlimit.h"
+
+#define CHECK(condition, tag, format...) ({		\
+	int __ret = !!(condition);			\
+	if (__ret) {					\
+		printf("%s:FAIL:%s ", __func__, tag);	\
+		printf(format);				\
+	} else {					\
+		printf("%s:PASS:%s\n", __func__, tag);	\
+	}						\
+	__ret;						\
+})
+
+static int bpf_find_map(const char *test, struct bpf_object *obj,
+			const char *name)
+{
+	struct bpf_map *map;
+
+	map = bpf_object__find_map_by_name(obj, name);
+	if (!map)
+		return -1;
+	return bpf_map__fd(map);
+}
+
+
+int main(int argc, char **argv)
+{
+	const char *probe_name = "syscalls/sys_enter_nanosleep";
+	const char *file = "test_pidns_kern.o";
+	int err, bytes, efd, prog_fd, pmu_fd;
+	int pidmap_fd, nsidmap_fd;
+	struct perf_event_attr attr = {};
+	struct bpf_object *obj;
+	__u32 knsid = 0;
+	__u32 key = 0, pid;
+	int exit_code = 1;
+	struct stat st;
+	char buf[256];
+
+	err = bpf_prog_load(file, BPF_PROG_TYPE_TRACEPOINT, &obj, &prog_fd);
+	if (CHECK(err, "bpf_prog_load", "err %d errno %d\n", err, errno))
+		goto cleanup_cgroup_env;
+
+	nsidmap_fd = bpf_find_map(__func__, obj, "nsidmap");
+	if (CHECK(nsidmap_fd < 0, "bpf_find_map", "err %d errno %d\n",
+		  nsidmap_fd, errno))
+		goto close_prog;
+
+	pidmap_fd = bpf_find_map(__func__, obj, "pidmap");
+	if (CHECK(pidmap_fd < 0, "bpf_find_map", "err %d errno %d\n",
+		  pidmap_fd, errno))
+		goto close_prog;
+
+	pid = getpid();
+	bpf_map_update_elem(pidmap_fd, &key, &pid, 0);
+
+	snprintf(buf, sizeof(buf),
+		 "/sys/kernel/debug/tracing/events/%s/id", probe_name);
+	efd = open(buf, O_RDONLY, 0);
+	if (CHECK(efd < 0, "open", "err %d errno %d\n", efd, errno))
+		goto close_prog;
+	bytes = read(efd, buf, sizeof(buf));
+	close(efd);
+	if (CHECK(bytes <= 0 || bytes >= sizeof(buf), "read",
+		  "bytes %d errno %d\n", bytes, errno))
+		goto close_prog;
+
+	attr.config = strtol(buf, NULL, 0);
+	attr.type = PERF_TYPE_TRACEPOINT;
+	attr.sample_type = PERF_SAMPLE_RAW;
+	attr.sample_period = 1;
+	attr.wakeup_events = 1;
+
+	pmu_fd = syscall(__NR_perf_event_open, &attr, getpid(), -1, -1, 0);
+	if (CHECK(pmu_fd < 0, "perf_event_open", "err %d errno %d\n", pmu_fd,
+		  errno))
+		goto close_prog;
+
+	err = ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0);
+	if (CHECK(err, "perf_event_ioc_enable", "err %d errno %d\n", err,
+		  errno))
+		goto close_pmu;
+
+	err = ioctl(pmu_fd, PERF_EVENT_IOC_SET_BPF, prog_fd);
+	if (CHECK(err, "perf_event_ioc_set_bpf", "err %d errno %d\n", err,
+		  errno))
+		goto close_pmu;
+
+	/* trigger some syscalls */
+	sleep(1);
+
+	err = bpf_map_lookup_elem(nsidmap_fd, &key, &knsid);
+	if (CHECK(err, "bpf_map_lookup_elem", "err %d errno %d\n", err, errno))
+		goto close_pmu;
+
+	if (stat("/proc/self/ns/pid", &st))
+		goto close_pmu;
+
+	if (CHECK(knsid != (__u32) st.st_ino, "compare_namespace_id",
+		  "kern knsid %u user unsid %u\n", knsid, (__u32) st.st_ino))
+		goto close_pmu;
+
+	exit_code = 0;
+	printf("%s:PASS\n", argv[0]);
+
+close_pmu:
+	close(pmu_fd);
+close_prog:
+	bpf_object__close(obj);
+cleanup_cgroup_env:
+	return exit_code;
+}
-- 
2.11.0

Thanks for your help.

Bests


On Thu, Aug 08, 2019 at 05:17:16PM -0400, Carlos Antonio Neira Bustos wrote:
> Thanks a lot, Yonghong. I'll fix and split up the patch.
> Thanks again for your help.
> 
> Bests
> 
> On Thu, Aug 08, 2019 at 08:47:14PM +0000, Yonghong Song wrote:
> > 
> > 
> > On 8/8/19 1:26 PM, carlos antonio neira bustos wrote:
> > > Hi Yonghong,
> > > 
> > > I’m sorry, just to be sure, I’m just missing the error codes from 
> > > filename_lookup() right ?.
> > 
> >  From kernel functionality point of view. Yes, I am talking about
> > error codes returned by filename_lookup().
> > For example, if CONFIG_PID_NS or CONFIG_NAMESPACES is not
> > defined in the config, the path "/proc/self/ns/pid" will not exist,
> > the error code will return. It may be -ENOTDIR
> > if CONFIG_NAMESPACES not defined or -ECHILD if CONFIG_PID_NS
> > is not defined. Please double check.
> > 
> > Please do follow the advice in
> >  > https://lore.kernel.org/netdev/20190808174848.poybtaagg5ctle7t@dev00/T/#t
> > to break the single patch to multiple patches.
> > 
> > I only reviewed the kernel code. Will review tools/ code
> > in the next properly-formatted (broken-up) commits.
> > 
> > Also, please also cc commits to bpf mailing list at
> > bpf@vger.kernel.org
> > 
> > > 
> > > Bests
> > > 
> > > Maybe some other error codes in filename_lookup() function?
> > > 
> > >  > + *
> > > 
> > >  > + *                      If unable to get the inode from 
> > > /proc/self/ns/pid an error code
> > > 
> > >  > + *                      will be returned.
> > > 
> > > *From: *Y Song <mailto:ys114321@gmail.com>
> > > *Sent: *08 August 2019 15:44
> > > *To: *Carlos Antonio Neira Bustos <mailto:cneirabustos@gmail.com>
> > > *Cc: *Yonghong Song <mailto:yhs@fb.com>; netdev@vger.kernel.org 
> > > <mailto:netdev@vger.kernel.org>; ebiederm@xmission.com 
> > > <mailto:ebiederm@xmission.com>; brouer@redhat.com 
> > > <mailto:brouer@redhat.com>; quentin.monnet@netronome.com 
> > > <mailto:quentin.monnet@netronome.com>
> > > *Subject: *Re: [PATCH v5 bpf-next] BPF: helpers: New helper to obtain 
> > > namespacedata from current task
> > > 
> > > On Thu, Aug 8, 2019 at 10:52 AM Carlos Antonio Neira Bustos
> > > 
> > > <cneirabustos@gmail.com> wrote:
> > > 
> > >  >
> > > 
> > >  > Yonghong,
> > > 
> > >  >
> > > 
> > >  > I have modified the patch following your feedback.
> > > 
> > >  > Let me know if I'm missing something.
> > > 
> > > Yes, I have some other requests about formating.
> > > 
> > > https://lore.kernel.org/netdev/20190808174848.poybtaagg5ctle7t@dev00/T/#t
> > > 
> > > Could you address it as well?
> > > 
> > >  >
> > > 
> > >  > Bests
> > > 
> > >  >
> > > 
> > >  > From 70f8d5584700c9cfc82c006901d8ee9595c53f15 Mon Sep 17 00:00:00 2001
> > > 
> > >  > From: Carlos <cneirabustos@gmail.com>
> > > 
> > >  > Date: Wed, 7 Aug 2019 20:04:30 -0400
> > > 
> > >  > Subject: [PATCH] [PATCH v6 bpf-next] BPF: New helper to obtain 
> > > namespace data
> > > 
> > >  >  from current task
> > > 
> > >  >
> > > 
> > >  > This helper obtains the active namespace from current and returns 
> > > pid, tgid,
> > > 
> > >  > device and namespace id as seen from that namespace, allowing to 
> > > instrument
> > > 
> > >  > a process inside a container.
> > > 
> > >  > Device is read from /proc/self/ns/pid, as in the future it's possible 
> > > that
> > > 
> > >  > different pid_ns files may belong to different devices, according
> > > 
> > >  > to the discussion between Eric Biederman and Yonghong in 2017 linux 
> > > plumbers
> > > 
> > >  > conference.
> > > 
> > >  > Currently bpf_get_current_pid_tgid(), is used to do pid filtering in 
> > > bcc's
> > > 
> > >  > scripts but this helper returns the pid as seen by the root namespace 
> > > which is
> > > 
> > >  > fine when a bcc script is not executed inside a container.
> > > 
> > >  > When the process of interest is inside a container, pid filtering 
> > > will not work
> > > 
> > >  > if bpf_get_current_pid_tgid() is used. This helper addresses this 
> > > limitation
> > > 
> > >  > returning the pid as it's seen by the current namespace where the 
> > > script is
> > > 
> > >  > executing.
> > > 
> > >  >
> > > 
> > >  > This helper has the same use cases as bpf_get_current_pid_tgid() as 
> > > it can be
> > > 
> > >  > used to do pid filtering even inside a container.
> > > 
> > >  >
> > > 
> > >  > For example a bcc script using bpf_get_current_pid_tgid() 
> > > (tools/funccount.py):
> > > 
> > >  >
> > > 
> > >  >         u32 pid = bpf_get_current_pid_tgid() >> 32;
> > > 
> > >  >         if (pid != <pid_arg_passed_in>)
> > > 
> > >  >                 return 0;
> > > 
> > >  > Could be modified to use bpf_get_current_pidns_info() as follows:
> > > 
> > >  >
> > > 
> > >  >         struct bpf_pidns pidns;
> > > 
> > >  >         bpf_get_current_pidns_info(&pidns, sizeof(struct bpf_pidns));
> > > 
> > >  >         u32 pid = pidns.tgid;
> > > 
> > >  >         u32 nsid = pidns.nsid;
> > > 
> > >  >         if ((pid != <pid_arg_passed_in>) && (nsid != 
> > > <nsid_arg_passed_in>))
> > > 
> > >  >                 return 0;
> > > 
> > >  >
> > > 
> > >  > To find out the name PID namespace id of a process, you could use 
> > > this command:
> > > 
> > >  >
> > > 
> > >  > $ ps -h -o pidns -p <pid_of_interest>
> > > 
> > >  >
> > > 
> > >  > Or this other command:
> > > 
> > >  >
> > > 
> > >  > $ ls -Li /proc/<pid_of_interest>/ns/pid
> > > 
> > >  >
> > > 
> > >  > Signed-off-by: Carlos Neira <cneirabustos@gmail.com>
> > > 
> > >  > ---
> > > 
> > >  >  fs/internal.h                                      |   2 -
> > > 
> > >  >  fs/namei.c                                         |   1 -
> > > 
> > >  >  include/linux/bpf.h                                |   1 +
> > > 
> > >  >  include/linux/namei.h                              |   4 +
> > > 
> > >  >  include/uapi/linux/bpf.h                           |  27 +++-
> > > 
> > >  >  kernel/bpf/core.c                                  |   1 +
> > > 
> > >  >  kernel/bpf/helpers.c                               |  64 ++++++++++
> > > 
> > >  >  kernel/trace/bpf_trace.c                           |   2 +
> > > 
> > >  >  samples/bpf/Makefile                               |   3 +
> > > 
> > >  >  samples/bpf/trace_ns_info_user.c                   |  35 ++++++
> > > 
> > >  >  samples/bpf/trace_ns_info_user_kern.c              |  44 +++++++
> > > 
> > >  >  tools/include/uapi/linux/bpf.h                     |  27 +++-
> > > 
> > >  >  tools/testing/selftests/bpf/Makefile               |   2 +-
> > > 
> > >  >  tools/testing/selftests/bpf/bpf_helpers.h          |   3 +
> > > 
> > >  >  .../testing/selftests/bpf/progs/test_pidns_kern.c  |  51 ++++++++
> > > 
> > >  >  tools/testing/selftests/bpf/test_pidns.c           | 138 
> > > +++++++++++++++++++++
> > > 
> > >  >  16 files changed, 399 insertions(+), 6 deletions(-)
> > > 
> > >  >  create mode 100644 samples/bpf/trace_ns_info_user.c
> > > 
> > >  >  create mode 100644 samples/bpf/trace_ns_info_user_kern.c
> > > 
> > >  >  create mode 100644 tools/testing/selftests/bpf/progs/test_pidns_kern.c
> > > 
> > >  >  create mode 100644 tools/testing/selftests/bpf/test_pidns.c
> > > 
> > >  >
> > > 
> > >  > diff --git a/fs/internal.h b/fs/internal.h
> > > 
> > >  > index 315fcd8d237c..6647e15dd419 100644
> > > 
> > >  > --- a/fs/internal.h
> > > 
> > >  > +++ b/fs/internal.h
> > > 
> > >  > @@ -59,8 +59,6 @@ extern int finish_clean_context(struct fs_context *fc);
> > > 
> > >  >  /*
> > > 
> > >  >   * namei.c
> > > 
> > >  >   */
> > > 
> > >  > -extern int filename_lookup(int dfd, struct filename *name, unsigned 
> > > flags,
> > > 
> > >  > -                          struct path *path, struct path *root);
> > > 
> > >  >  extern int user_path_mountpoint_at(int, const char __user *, 
> > > unsigned int, struct path *);
> > > 
> > >  >  extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
> > > 
> > >  >                            const char *, unsigned int, struct path *);
> > > 
> > >  > diff --git a/fs/namei.c b/fs/namei.c
> > > 
> > >  > index 209c51a5226c..a89fc72a4a10 100644
> > > 
> > >  > --- a/fs/namei.c
> > > 
> > >  > +++ b/fs/namei.c
> > > 
> > >  > @@ -19,7 +19,6 @@
> > > 
> > >  >  #include <linux/export.h>
> > > 
> > >  >  #include <linux/kernel.h>
> > > 
> > >  >  #include <linux/slab.h>
> > > 
> > >  > -#include <linux/fs.h>
> > > 
> > >  >  #include <linux/namei.h>
> > > 
> > >  >  #include <linux/pagemap.h>
> > > 
> > >  >  #include <linux/fsnotify.h>
> > > 
> > >  > diff --git a/include/linux/bpf.h b/include/linux/bpf.h
> > > 
> > >  > index f9a506147c8a..e4adf5e05afd 100644
> > > 
> > >  > --- a/include/linux/bpf.h
> > > 
> > >  > +++ b/include/linux/bpf.h
> > > 
> > >  > @@ -1050,6 +1050,7 @@ extern const struct bpf_func_proto 
> > > bpf_get_local_storage_proto;
> > > 
> > >  >  extern const struct bpf_func_proto bpf_strtol_proto;
> > > 
> > >  >  extern const struct bpf_func_proto bpf_strtoul_proto;
> > > 
> > >  >  extern const struct bpf_func_proto bpf_tcp_sock_proto;
> > > 
> > >  > +extern const struct bpf_func_proto bpf_get_current_pidns_info_proto;
> > > 
> > >  >
> > > 
> > >  >  /* Shared helpers among cBPF and eBPF. */
> > > 
> > >  >  void bpf_user_rnd_init_once(void);
> > > 
> > >  > diff --git a/include/linux/namei.h b/include/linux/namei.h
> > > 
> > >  > index 9138b4471dbf..b45c8b6f7cb4 100644
> > > 
> > >  > --- a/include/linux/namei.h
> > > 
> > >  > +++ b/include/linux/namei.h
> > > 
> > >  > @@ -6,6 +6,7 @@
> > > 
> > >  >  #include <linux/path.h>
> > > 
> > >  >  #include <linux/fcntl.h>
> > > 
> > >  >  #include <linux/errno.h>
> > > 
> > >  > +#include <linux/fs.h>
> > > 
> > >  >
> > > 
> > >  >  enum { MAX_NESTED_LINKS = 8 };
> > > 
> > >  >
> > > 
> > >  > @@ -97,6 +98,9 @@ extern void unlock_rename(struct dentry *, struct 
> > > dentry *);
> > > 
> > >  >
> > > 
> > >  >  extern void nd_jump_link(struct path *path);
> > > 
> > >  >
> > > 
> > >  > +extern int filename_lookup(int dfd, struct filename *name, unsigned 
> > > flags,
> > > 
> > >  > +                          struct path *path, struct path *root);
> > > 
> > >  > +
> > > 
> > >  >  static inline void nd_terminate_link(void *name, size_t len, size_t 
> > > maxlen)
> > > 
> > >  >  {
> > > 
> > >  >         ((char *) name)[min(len, maxlen)] = '\0';
> > > 
> > >  > diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> > > 
> > >  > index 4393bd4b2419..b0d4869fb860 100644
> > > 
> > >  > --- a/include/uapi/linux/bpf.h
> > > 
> > >  > +++ b/include/uapi/linux/bpf.h
> > > 
> > >  > @@ -2741,6 +2741,24 @@ union bpf_attr {
> > > 
> > >  >   *             **-EOPNOTSUPP** kernel configuration does not enable 
> > > SYN cookies
> > > 
> > >  >   *
> > > 
> > >  >   *             **-EPROTONOSUPPORT** IP packet version is not 4 or 6
> > > 
> > >  > + *
> > > 
> > >  > + * int bpf_get_current_pidns_info(struct bpf_pidns_info *pidns, u32 
> > > size_of_pidns)
> > > 
> > >  > + *     Description
> > > 
> > >  > + *             Copies into *pidns* pid, namespace id and tgid as 
> > > seen by the
> > > 
> > >  > + *             current namespace and also device from /proc/self/ns/pid.
> > > 
> > >  > + *             *size_of_pidns* must be the size of *pidns*
> > > 
> > >  > + *
> > > 
> > >  > + *             This helper is used when pid filtering is needed inside a
> > > 
> > >  > + *             container as bpf_get_current_tgid() helper returns 
> > > always the
> > > 
> > >  > + *             pid id as seen by the root namespace.
> > > 
> > >  > + *     Return
> > > 
> > >  > + *             0 on success
> > > 
> > >  > + *
> > > 
> > >  > + *             **-EINVAL** if *size_of_pidns* is not valid or unable 
> > > to get ns, pid
> > > 
> > >  > + *             or tgid of the current task.
> > > 
> > >  > + *
> > > 
> > >  > + *             **-ENOMEM**  if allocation fails.
> > > 
> > >  > + *
> > > 
> > >  >   */
> > > 
> > >  >  #define __BPF_FUNC_MAPPER(FN)          \
> > > 
> > >  >         FN(unspec),                     \
> > > 
> > >  > @@ -2853,7 +2871,8 @@ union bpf_attr {
> > > 
> > >  >         FN(sk_storage_get),             \
> > > 
> > >  >         FN(sk_storage_delete),          \
> > > 
> > >  >         FN(send_signal),                \
> > > 
> > >  > -       FN(tcp_gen_syncookie),
> > > 
> > >  > +       FN(tcp_gen_syncookie),          \
> > > 
> > >  > +       FN(get_current_pidns_info),
> > > 
> > >  >
> > > 
> > >  >  /* integer value in 'imm' field of BPF_CALL instruction selects 
> > > which helper
> > > 
> > >  >   * function eBPF program intends to call
> > > 
> > >  > @@ -3604,4 +3623,10 @@ struct bpf_sockopt {
> > > 
> > >  >         __s32   retval;
> > > 
> > >  >  };
> > > 
> > >  >
> > > 
> > >  > +struct bpf_pidns_info {
> > > 
> > >  > +       __u32 dev;
> > > 
> > >  > +       __u32 nsid;
> > > 
> > >  > +       __u32 tgid;
> > > 
> > >  > +       __u32 pid;
> > > 
> > >  > +};
> > > 
> > >  >  #endif /* _UAPI__LINUX_BPF_H__ */
> > > 
> > >  > diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
> > > 
> > >  > index 8191a7db2777..3159f2a0188c 100644
> > > 
> > >  > --- a/kernel/bpf/core.c
> > > 
> > >  > +++ b/kernel/bpf/core.c
> > > 
> > >  > @@ -2038,6 +2038,7 @@ const struct bpf_func_proto 
> > > bpf_get_current_uid_gid_proto __weak;
> > > 
> > >  >  const struct bpf_func_proto bpf_get_current_comm_proto __weak;
> > > 
> > >  >  const struct bpf_func_proto bpf_get_current_cgroup_id_proto __weak;
> > > 
> > >  >  const struct bpf_func_proto bpf_get_local_storage_proto __weak;
> > > 
> > >  > +const struct bpf_func_proto bpf_get_current_pidns_info __weak;
> > > 
> > >  >
> > > 
> > >  >  const struct bpf_func_proto * __weak bpf_get_trace_printk_proto(void)
> > > 
> > >  >  {
> > > 
> > >  > diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
> > > 
> > >  > index 5e28718928ca..41fbf1f28a48 100644
> > > 
> > >  > --- a/kernel/bpf/helpers.c
> > > 
> > >  > +++ b/kernel/bpf/helpers.c
> > > 
> > >  > @@ -11,6 +11,12 @@
> > > 
> > >  >  #include <linux/uidgid.h>
> > > 
> > >  >  #include <linux/filter.h>
> > > 
> > >  >  #include <linux/ctype.h>
> > > 
> > >  > +#include <linux/pid_namespace.h>
> > > 
> > >  > +#include <linux/major.h>
> > > 
> > >  > +#include <linux/stat.h>
> > > 
> > >  > +#include <linux/namei.h>
> > > 
> > >  > +#include <linux/version.h>
> > > 
> > >  > +
> > > 
> > >  >
> > > 
> > >  >  #include "../../lib/kstrtox.h"
> > > 
> > >  >
> > > 
> > >  > @@ -312,6 +318,64 @@ void copy_map_value_locked(struct bpf_map *map, 
> > > void *dst, void *src,
> > > 
> > >  >         preempt_enable();
> > > 
> > >  >  }
> > > 
> > >  >
> > > 
> > >  > +BPF_CALL_2(bpf_get_current_pidns_info, struct bpf_pidns_info *, 
> > > pidns_info, u32,
> > > 
> > >  > +        size)
> > > 
> > >  > +{
> > > 
> > >  > +       const char *pidns_path = "/proc/self/ns/pid";
> > > 
> > >  > +       struct pid_namespace *pidns = NULL;
> > > 
> > >  > +       struct filename *tmp = NULL;
> > > 
> > >  > +       struct inode *inode;
> > > 
> > >  > +       struct path kp;
> > > 
> > >  > +       pid_t tgid = 0;
> > > 
> > >  > +       pid_t pid = 0;
> > > 
> > >  > +       int ret;
> > > 
> > >  > +       int len;
> > > 
> > >  > +
> > > 
> > >  > +       if (unlikely(size != sizeof(struct bpf_pidns_info)))
> > > 
> > >  > +               return -EINVAL;
> > > 
> > >  > +       pidns = task_active_pid_ns(current);
> > > 
> > >  > +       if (unlikely(!pidns))
> > > 
> > >  > +               goto clear;
> > > 
> > >  > +       pidns_info->nsid =  pidns->ns.inum;
> > > 
> > >  > +       pid = task_pid_nr_ns(current, pidns);
> > > 
> > >  > +       if (unlikely(!pid))
> > > 
> > >  > +               goto clear;
> > > 
> > >  > +       tgid = task_tgid_nr_ns(current, pidns);
> > > 
> > >  > +       if (unlikely(!tgid))
> > > 
> > >  > +               goto clear;
> > > 
> > >  > +       pidns_info->tgid = (u32) tgid;
> > > 
> > >  > +       pidns_info->pid = (u32) pid;
> > > 
> > >  > +       tmp = kmem_cache_alloc(names_cachep, GFP_ATOMIC);
> > > 
> > >  > +       if (unlikely(!tmp)) {
> > > 
> > >  > +               memset((void *)pidns_info, 0, (size_t) size);
> > > 
> > >  > +               return -ENOMEM;
> > > 
> > >  > +       }
> > > 
> > >  > +       len = strlen(pidns_path) + 1;
> > > 
> > >  > +       memcpy((char *)tmp->name, pidns_path, len);
> > > 
> > >  > +       tmp->uptr = NULL;
> > > 
> > >  > +       tmp->aname = NULL;
> > > 
> > >  > +       tmp->refcnt = 1;
> > > 
> > >  > +       ret = filename_lookup(AT_FDCWD, tmp, 0, &kp, NULL);
> > > 
> > >  > +       if (ret) {
> > > 
> > >  > +               memset((void *)pidns_info, 0, (size_t) size);
> > > 
> > >  > +               return ret;
> > > 
> > >  > +       }
> > > 
> > >  > +       inode = d_backing_inode(kp.dentry);
> > > 
> > >  > +       pidns_info->dev = inode->i_sb->s_dev;
> > > 
> > >  > +       return 0;
> > > 
> > >  > +clear:
> > > 
> > >  > +       memset((void *)pidns_info, 0, (size_t) size);
> > > 
> > >  > +       return -EINVAL;
> > > 
> > >  > +}
> > > 
> > >  > +
> > > 
> > >  > +const struct bpf_func_proto bpf_get_current_pidns_info_proto = {
> > > 
> > >  > +       .func           = bpf_get_current_pidns_info,
> > > 
> > >  > +       .gpl_only       = false,
> > > 
> > >  > +       .ret_type       = RET_INTEGER,
> > > 
> > >  > +       .arg1_type      = ARG_PTR_TO_UNINIT_MEM,
> > > 
> > >  > +       .arg2_type      = ARG_CONST_SIZE,
> > > 
> > >  > +};
> > > 
> > >  > +
> > > 
> > >  >  #ifdef CONFIG_CGROUPS
> > > 
> > >  >  BPF_CALL_0(bpf_get_current_cgroup_id)
> > > 
> > >  >  {
> > > 
> > >  > diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
> > > 
> > >  > index ca1255d14576..5e1dc22765a5 100644
> > > 
> > >  > --- a/kernel/trace/bpf_trace.c
> > > 
> > >  > +++ b/kernel/trace/bpf_trace.c
> > > 
> > >  > @@ -709,6 +709,8 @@ tracing_func_proto(enum bpf_func_id func_id, 
> > > const struct bpf_prog *prog)
> > > 
> > >  >  #endif
> > > 
> > >  >         case BPF_FUNC_send_signal:
> > > 
> > >  >                 return &bpf_send_signal_proto;
> > > 
> > >  > +       case BPF_FUNC_get_current_pidns_info:
> > > 
> > >  > +               return &bpf_get_current_pidns_info_proto;
> > > 
> > >  >         default:
> > > 
> > >  >                 return NULL;
> > > 
> > >  >         }
> > > 
> > >  > diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
> > > 
> > >  > index 1d9be26b4edd..238453ff27d2 100644
> > > 
> > >  > --- a/samples/bpf/Makefile
> > > 
> > >  > +++ b/samples/bpf/Makefile
> > > 
> > >  > @@ -53,6 +53,7 @@ hostprogs-y += task_fd_query
> > > 
> > >  >  hostprogs-y += xdp_sample_pkts
> > > 
> > >  >  hostprogs-y += ibumad
> > > 
> > >  >  hostprogs-y += hbm
> > > 
> > >  > +hostprogs-y += trace_ns_info
> > > 
> > >  >
> > > 
> > >  >  # Libbpf dependencies
> > > 
> > >  >  LIBBPF = $(TOOLS_PATH)/lib/bpf/libbpf.a
> > > 
> > >  > @@ -109,6 +110,7 @@ task_fd_query-objs := bpf_load.o 
> > > task_fd_query_user.o $(TRACE_HELPERS)
> > > 
> > >  >  xdp_sample_pkts-objs := xdp_sample_pkts_user.o $(TRACE_HELPERS)
> > > 
> > >  >  ibumad-objs := bpf_load.o ibumad_user.o $(TRACE_HELPERS)
> > > 
> > >  >  hbm-objs := bpf_load.o hbm.o $(CGROUP_HELPERS)
> > > 
> > >  > +trace_ns_info-objs := bpf_load.o trace_ns_info_user.o
> > > 
> > >  >
> > > 
> > >  >  # Tell kbuild to always build the programs
> > > 
> > >  >  always := $(hostprogs-y)
> > > 
> > >  > @@ -170,6 +172,7 @@ always += xdp_sample_pkts_kern.o
> > > 
> > >  >  always += ibumad_kern.o
> > > 
> > >  >  always += hbm_out_kern.o
> > > 
> > >  >  always += hbm_edt_kern.o
> > > 
> > >  > +always += trace_ns_info_user_kern.o
> > > 
> > >  >
> > > 
> > >  >  KBUILD_HOSTCFLAGS += -I$(objtree)/usr/include
> > > 
> > >  >  KBUILD_HOSTCFLAGS += -I$(srctree)/tools/lib/bpf/
> > > 
> > >  > diff --git a/samples/bpf/trace_ns_info_user.c 
> > > b/samples/bpf/trace_ns_info_user.c
> > > 
> > >  > new file mode 100644
> > > 
> > >  > index 000000000000..e06d08db6f30
> > > 
> > >  > --- /dev/null
> > > 
> > >  > +++ b/samples/bpf/trace_ns_info_user.c
> > > 
> > >  > @@ -0,0 +1,35 @@
> > > 
> > >  > +// SPDX-License-Identifier: GPL-2.0
> > > 
> > >  > +/* Copyright (c) 2018 Carlos Neira cneirabustos@gmail.com
> > > 
> > >  > + *
> > > 
> > >  > + * This program is free software; you can redistribute it and/or
> > > 
> > >  > + * modify it under the terms of version 2 of the GNU General Public
> > > 
> > >  > + * License as published by the Free Software Foundation.
> > > 
> > >  > + */
> > > 
> > >  > +
> > > 
> > >  > +#include <stdio.h>
> > > 
> > >  > +#include <linux/bpf.h>
> > > 
> > >  > +#include <unistd.h>
> > > 
> > >  > +#include "bpf/libbpf.h"
> > > 
> > >  > +#include "bpf_load.h"
> > > 
> > >  > +
> > > 
> > >  > +/* This code was taken verbatim from tracex1_user.c, it's used
> > > 
> > >  > + * to exercize bpf_get_current_pidns_info() helper call.
> > > 
> > >  > + */
> > > 
> > >  > +int main(int ac, char **argv)
> > > 
> > >  > +{
> > > 
> > >  > +       FILE *f;
> > > 
> > >  > +       char filename[256];
> > > 
> > >  > +
> > > 
> > >  > +       snprintf(filename, sizeof(filename), "%s_user_kern.o", argv[0]);
> > > 
> > >  > +       printf("loading %s\n", filename);
> > > 
> > >  > +
> > > 
> > >  > +       if (load_bpf_file(filename)) {
> > > 
> > >  > +               printf("%s", bpf_log_buf);
> > > 
> > >  > +               return 1;
> > > 
> > >  > +       }
> > > 
> > >  > +
> > > 
> > >  > +       f = popen("taskset 1 ping  localhost", "r");
> > > 
> > >  > +       (void) f;
> > > 
> > >  > +       read_trace_pipe();
> > > 
> > >  > +       return 0;
> > > 
> > >  > +}
> > > 
> > >  > diff --git a/samples/bpf/trace_ns_info_user_kern.c 
> > > b/samples/bpf/trace_ns_info_user_kern.c
> > > 
> > >  > new file mode 100644
> > > 
> > >  > index 000000000000..96675e02b707
> > > 
> > >  > --- /dev/null
> > > 
> > >  > +++ b/samples/bpf/trace_ns_info_user_kern.c
> > > 
> > >  > @@ -0,0 +1,44 @@
> > > 
> > >  > +// SPDX-License-Identifier: GPL-2.0
> > > 
> > >  > +/* Copyright (c) 2018 Carlos Neira cneirabustos@gmail.com
> > > 
> > >  > + *
> > > 
> > >  > + * This program is free software; you can redistribute it and/or
> > > 
> > >  > + * modify it under the terms of version 2 of the GNU General Public
> > > 
> > >  > + * License as published by the Free Software Foundation.
> > > 
> > >  > + */
> > > 
> > >  > +#include <linux/skbuff.h>
> > > 
> > >  > +#include <linux/netdevice.h>
> > > 
> > >  > +#include <linux/version.h>
> > > 
> > >  > +#include <uapi/linux/bpf.h>
> > > 
> > >  > +#include "bpf_helpers.h"
> > > 
> > >  > +
> > > 
> > >  > +typedef __u64 u64;
> > > 
> > >  > +typedef __u32 u32;
> > > 
> > >  > +
> > > 
> > >  > +
> > > 
> > >  > +/* kprobe is NOT a stable ABI
> > > 
> > >  > + * kernel functions can be removed, renamed or completely change 
> > > semantics.
> > > 
> > >  > + * Number of arguments and their positions can change, etc.
> > > 
> > >  > + * In such case this bpf+kprobe example will no longer be meaningful
> > > 
> > >  > + */
> > > 
> > >  > +
> > > 
> > >  > +/* This will call bpf_get_current_pidns_info() to display pid and ns 
> > > values
> > > 
> > >  > + * as seen by the current namespace, on the far left you will see 
> > > the pid as
> > > 
> > >  > + * seen as by the root namespace.
> > > 
> > >  > + */
> > > 
> > >  > +
> > > 
> > >  > +SEC("kprobe/__netif_receive_skb_core")
> > > 
> > >  > +int bpf_prog1(struct pt_regs *ctx)
> > > 
> > >  > +{
> > > 
> > >  > +       char fmt[] = "nsid:%u, dev: %u,  pid:%u\n";
> > > 
> > >  > +       struct bpf_pidns_info nsinfo;
> > > 
> > >  > +       int ok = 0;
> > > 
> > >  > +
> > > 
> > >  > +       ok = bpf_get_current_pidns_info(&nsinfo, sizeof(nsinfo));
> > > 
> > >  > +       if (ok == 0)
> > > 
> > >  > +               bpf_trace_printk(fmt, sizeof(fmt), (u32)nsinfo.nsid,
> > > 
> > >  > +                                (u32) nsinfo.dev, (u32)nsinfo.pid);
> > > 
> > >  > +
> > > 
> > >  > +       return 0;
> > > 
> > >  > +}
> > > 
> > >  > +char _license[] SEC("license") = "GPL";
> > > 
> > >  > +u32 _version SEC("version") = LINUX_VERSION_CODE;
> > > 
> > >  > diff --git a/tools/include/uapi/linux/bpf.h 
> > > b/tools/include/uapi/linux/bpf.h
> > > 
> > >  > index 4393bd4b2419..b0d4869fb860 100644
> > > 
> > >  > --- a/tools/include/uapi/linux/bpf.h
> > > 
> > >  > +++ b/tools/include/uapi/linux/bpf.h
> > > 
> > >  > @@ -2741,6 +2741,24 @@ union bpf_attr {
> > > 
> > >  >   *             **-EOPNOTSUPP** kernel configuration does not enable 
> > > SYN cookies
> > > 
> > >  >   *
> > > 
> > >  >   *             **-EPROTONOSUPPORT** IP packet version is not 4 or 6
> > > 
> > >  > + *
> > > 
> > >  > + * int bpf_get_current_pidns_info(struct bpf_pidns_info *pidns, u32 
> > > size_of_pidns)
> > > 
> > >  > + *     Description
> > > 
> > >  > + *             Copies into *pidns* pid, namespace id and tgid as 
> > > seen by the
> > > 
> > >  > + *             current namespace and also device from /proc/self/ns/pid.
> > > 
> > >  > + *             *size_of_pidns* must be the size of *pidns*
> > > 
> > >  > + *
> > > 
> > >  > + *             This helper is used when pid filtering is needed inside a
> > > 
> > >  > + *             container as bpf_get_current_tgid() helper returns 
> > > always the
> > > 
> > >  > + *             pid id as seen by the root namespace.
> > > 
> > >  > + *     Return
> > > 
> > >  > + *             0 on success
> > > 
> > >  > + *
> > > 
> > >  > + *             **-EINVAL** if *size_of_pidns* is not valid or unable 
> > > to get ns, pid
> > > 
> > >  > + *             or tgid of the current task.
> > > 
> > >  > + *
> > > 
> > >  > + *             **-ENOMEM**  if allocation fails.
> > > 
> > >  > + *
> > > 
> > >  >   */
> > > 
> > >  >  #define __BPF_FUNC_MAPPER(FN)          \
> > > 
> > >  >         FN(unspec),                     \
> > > 
> > >  > @@ -2853,7 +2871,8 @@ union bpf_attr {
> > > 
> > >  >         FN(sk_storage_get),             \
> > > 
> > >  >         FN(sk_storage_delete),          \
> > > 
> > >  >         FN(send_signal),                \
> > > 
> > >  > -       FN(tcp_gen_syncookie),
> > > 
> > >  > +       FN(tcp_gen_syncookie),          \
> > > 
> > >  > +       FN(get_current_pidns_info),
> > > 
> > >  >
> > > 
> > >  >  /* integer value in 'imm' field of BPF_CALL instruction selects 
> > > which helper
> > > 
> > >  >   * function eBPF program intends to call
> > > 
> > >  > @@ -3604,4 +3623,10 @@ struct bpf_sockopt {
> > > 
> > >  >         __s32   retval;
> > > 
> > >  >  };
> > > 
> > >  >
> > > 
> > >  > +struct bpf_pidns_info {
> > > 
> > >  > +       __u32 dev;
> > > 
> > >  > +       __u32 nsid;
> > > 
> > >  > +       __u32 tgid;
> > > 
> > >  > +       __u32 pid;
> > > 
> > >  > +};
> > > 
> > >  >  #endif /* _UAPI__LINUX_BPF_H__ */
> > > 
> > >  > diff --git a/tools/testing/selftests/bpf/Makefile 
> > > b/tools/testing/selftests/bpf/Makefile
> > > 
> > >  > index 3bd0f4a0336a..1f97b571b581 100644
> > > 
> > >  > --- a/tools/testing/selftests/bpf/Makefile
> > > 
> > >  > +++ b/tools/testing/selftests/bpf/Makefile
> > > 
> > >  > @@ -29,7 +29,7 @@ TEST_GEN_PROGS = test_verifier test_tag test_maps 
> > > test_lru_map test_lpm_map test
> > > 
> > >  >         test_cgroup_storage test_select_reuseport test_section_names \
> > > 
> > >  >         test_netcnt test_tcpnotify_user test_sock_fields test_sysctl 
> > > test_hashmap \
> > > 
> > >  >         test_btf_dump test_cgroup_attach xdping test_sockopt 
> > > test_sockopt_sk \
> > > 
> > >  > -       test_sockopt_multi test_tcp_rtt
> > > 
> > >  > +       test_sockopt_multi test_tcp_rtt test_pidns
> > > 
> > >  >
> > > 
> > >  >  BPF_OBJ_FILES = $(patsubst %.c,%.o, $(notdir $(wildcard progs/*.c)))
> > > 
> > >  >  TEST_GEN_FILES = $(BPF_OBJ_FILES)
> > > 
> > >  > diff --git a/tools/testing/selftests/bpf/bpf_helpers.h 
> > > b/tools/testing/selftests/bpf/bpf_helpers.h
> > > 
> > >  > index 120aa86c58d3..c96795a9d983 100644
> > > 
> > >  > --- a/tools/testing/selftests/bpf/bpf_helpers.h
> > > 
> > >  > +++ b/tools/testing/selftests/bpf/bpf_helpers.h
> > > 
> > >  > @@ -231,6 +231,9 @@ static int (*bpf_send_signal)(unsigned sig) = 
> > > (void *)BPF_FUNC_send_signal;
> > > 
> > >  >  static long long (*bpf_tcp_gen_syncookie)(struct bpf_sock *sk, void *ip,
> > > 
> > >  >                                           int ip_len, void *tcp, int 
> > > tcp_len) =
> > > 
> > >  >         (void *) BPF_FUNC_tcp_gen_syncookie;
> > > 
> > >  > +static int (*bpf_get_current_pidns_info)(struct bpf_pidns_info *buf,
> > > 
> > >  > +                                        unsigned int buf_size) =
> > > 
> > >  > +       (void *) BPF_FUNC_get_current_pidns_info;
> > > 
> > >  >
> > > 
> > >  >  /* llvm builtin functions that eBPF C program may use to
> > > 
> > >  >   * emit BPF_LD_ABS and BPF_LD_IND instructions
> > > 
> > >  > diff --git a/tools/testing/selftests/bpf/progs/test_pidns_kern.c 
> > > b/tools/testing/selftests/bpf/progs/test_pidns_kern.c
> > > 
> > >  > new file mode 100644
> > > 
> > >  > index 000000000000..e1d2facfa762
> > > 
> > >  > --- /dev/null
> > > 
> > >  > +++ b/tools/testing/selftests/bpf/progs/test_pidns_kern.c
> > > 
> > >  > @@ -0,0 +1,51 @@
> > > 
> > >  > +// SPDX-License-Identifier: GPL-2.0
> > > 
> > >  > +/* Copyright (c) 2018 Carlos Neira cneirabustos@gmail.com
> > > 
> > >  > + *
> > > 
> > >  > + * This program is free software; you can redistribute it and/or
> > > 
> > >  > + * modify it under the terms of version 2 of the GNU General Public
> > > 
> > >  > + * License as published by the Free Software Foundation.
> > > 
> > >  > + */
> > > 
> > >  > +
> > > 
> > >  > +#include <linux/bpf.h>
> > > 
> > >  > +#include <errno.h>
> > > 
> > >  > +#include "bpf_helpers.h"
> > > 
> > >  > +
> > > 
> > >  > +struct bpf_map_def SEC("maps") nsidmap = {
> > > 
> > >  > +       .type = BPF_MAP_TYPE_ARRAY,
> > > 
> > >  > +       .key_size = sizeof(__u32),
> > > 
> > >  > +       .value_size = sizeof(__u32),
> > > 
> > >  > +       .max_entries = 1,
> > > 
> > >  > +};
> > > 
> > >  > +
> > > 
> > >  > +struct bpf_map_def SEC("maps") pidmap = {
> > > 
> > >  > +       .type = BPF_MAP_TYPE_ARRAY,
> > > 
> > >  > +       .key_size = sizeof(__u32),
> > > 
> > >  > +       .value_size = sizeof(__u32),
> > > 
> > >  > +       .max_entries = 1,
> > > 
> > >  > +};
> > > 
> > >  > +
> > > 
> > >  > +SEC("tracepoint/syscalls/sys_enter_nanosleep")
> > > 
> > >  > +int trace(void *ctx)
> > > 
> > >  > +{
> > > 
> > >  > +       struct bpf_pidns_info nsinfo;
> > > 
> > >  > +       __u32 key = 0, *expected_pid, *val;
> > > 
> > >  > +       char fmt[] = "ERROR nspid:%d\n";
> > > 
> > >  > +
> > > 
> > >  > +       if (bpf_get_current_pidns_info(&nsinfo, sizeof(nsinfo)))
> > > 
> > >  > +               return -EINVAL;
> > > 
> > >  > +
> > > 
> > >  > +       expected_pid = bpf_map_lookup_elem(&pidmap, &key);
> > > 
> > >  > +
> > > 
> > >  > +
> > > 
> > >  > +       if (!expected_pid || *expected_pid != nsinfo.pid)
> > > 
> > >  > +               return 0;
> > > 
> > >  > +
> > > 
> > >  > +       val = bpf_map_lookup_elem(&nsidmap, &key);
> > > 
> > >  > +       if (val)
> > > 
> > >  > +               *val = nsinfo.nsid;
> > > 
> > >  > +
> > > 
> > >  > +       return 0;
> > > 
> > >  > +}
> > > 
> > >  > +
> > > 
> > >  > +char _license[] SEC("license") = "GPL";
> > > 
> > >  > +__u32 _version SEC("version") = 1;
> > > 
> > >  > diff --git a/tools/testing/selftests/bpf/test_pidns.c 
> > > b/tools/testing/selftests/bpf/test_pidns.c
> > > 
> > >  > new file mode 100644
> > > 
> > >  > index 000000000000..a7254055f294
> > > 
> > >  > --- /dev/null
> > > 
> > >  > +++ b/tools/testing/selftests/bpf/test_pidns.c
> > > 
> > >  > @@ -0,0 +1,138 @@
> > > 
> > >  > +// SPDX-License-Identifier: GPL-2.0
> > > 
> > >  > +/* Copyright (c) 2018 Carlos Neira cneirabustos@gmail.com
> > > 
> > >  > + *
> > > 
> > >  > + * This program is free software; you can redistribute it and/or
> > > 
> > >  > + * modify it under the terms of version 2 of the GNU General Public
> > > 
> > >  > + * License as published by the Free Software Foundation.
> > > 
> > >  > + */
> > > 
> > >  > +
> > > 
> > >  > +#include <stdio.h>
> > > 
> > >  > +#include <stdlib.h>
> > > 
> > >  > +#include <string.h>
> > > 
> > >  > +#include <errno.h>
> > > 
> > >  > +#include <fcntl.h>
> > > 
> > >  > +#include <syscall.h>
> > > 
> > >  > +#include <unistd.h>
> > > 
> > >  > +#include <linux/perf_event.h>
> > > 
> > >  > +#include <sys/ioctl.h>
> > > 
> > >  > +#include <sys/time.h>
> > > 
> > >  > +#include <sys/types.h>
> > > 
> > >  > +#include <sys/stat.h>
> > > 
> > >  > +
> > > 
> > >  > +#include <linux/bpf.h>
> > > 
> > >  > +#include <bpf/bpf.h>
> > > 
> > >  > +#include <bpf/libbpf.h>
> > > 
> > >  > +
> > > 
> > >  > +#include "cgroup_helpers.h"
> > > 
> > >  > +#include "bpf_rlimit.h"
> > > 
> > >  > +
> > > 
> > >  > +#define CHECK(condition, tag, format...) ({            \
> > > 
> > >  > +       int __ret = !!(condition);                      \
> > > 
> > >  > +       if (__ret) {                                    \
> > > 
> > >  > +               printf("%s:FAIL:%s ", __func__, tag);   \
> > > 
> > >  > +               printf(format);                         \
> > > 
> > >  > +       } else {                                        \
> > > 
> > >  > +               printf("%s:PASS:%s\n", __func__, tag);  \
> > > 
> > >  > +       }                                               \
> > > 
> > >  > +       __ret;                                          \
> > > 
> > >  > +})
> > > 
> > >  > +
> > > 
> > >  > +static int bpf_find_map(const char *test, struct bpf_object *obj,
> > > 
> > >  > +                       const char *name)
> > > 
> > >  > +{
> > > 
> > >  > +       struct bpf_map *map;
> > > 
> > >  > +
> > > 
> > >  > +       map = bpf_object__find_map_by_name(obj, name);
> > > 
> > >  > +       if (!map)
> > > 
> > >  > +               return -1;
> > > 
> > >  > +       return bpf_map__fd(map);
> > > 
> > >  > +}
> > > 
> > >  > +
> > > 
> > >  > +
> > > 
> > >  > +int main(int argc, char **argv)
> > > 
> > >  > +{
> > > 
> > >  > +       const char *probe_name = "syscalls/sys_enter_nanosleep";
> > > 
> > >  > +       const char *file = "test_pidns_kern.o";
> > > 
> > >  > +       int err, bytes, efd, prog_fd, pmu_fd;
> > > 
> > >  > +       int pidmap_fd, nsidmap_fd;
> > > 
> > >  > +       struct perf_event_attr attr = {};
> > > 
> > >  > +       struct bpf_object *obj;
> > > 
> > >  > +       __u32 knsid = 0;
> > > 
> > >  > +       __u32 key = 0, pid;
> > > 
> > >  > +       int exit_code = 1;
> > > 
> > >  > +       struct stat st;
> > > 
> > >  > +       char buf[256];
> > > 
> > >  > +
> > > 
> > >  > +       err = bpf_prog_load(file, BPF_PROG_TYPE_TRACEPOINT, &obj, 
> > > &prog_fd);
> > > 
> > >  > +       if (CHECK(err, "bpf_prog_load", "err %d errno %d\n", err, errno))
> > > 
> > >  > +               goto cleanup_cgroup_env;
> > > 
> > >  > +
> > > 
> > >  > +       nsidmap_fd = bpf_find_map(__func__, obj, "nsidmap");
> > > 
> > >  > +       if (CHECK(nsidmap_fd < 0, "bpf_find_map", "err %d errno %d\n",
> > > 
> > >  > +                 nsidmap_fd, errno))
> > > 
> > >  > +               goto close_prog;
> > > 
> > >  > +
> > > 
> > >  > +       pidmap_fd = bpf_find_map(__func__, obj, "pidmap");
> > > 
> > >  > +       if (CHECK(pidmap_fd < 0, "bpf_find_map", "err %d errno %d\n",
> > > 
> > >  > +                 pidmap_fd, errno))
> > > 
> > >  > +               goto close_prog;
> > > 
> > >  > +
> > > 
> > >  > +       pid = getpid();
> > > 
> > >  > +       bpf_map_update_elem(pidmap_fd, &key, &pid, 0);
> > > 
> > >  > +
> > > 
> > >  > +       snprintf(buf, sizeof(buf),
> > > 
> > >  > +                "/sys/kernel/debug/tracing/events/%s/id", probe_name);
> > > 
> > >  > +       efd = open(buf, O_RDONLY, 0);
> > > 
> > >  > +       if (CHECK(efd < 0, "open", "err %d errno %d\n", efd, errno))
> > > 
> > >  > +               goto close_prog;
> > > 
> > >  > +       bytes = read(efd, buf, sizeof(buf));
> > > 
> > >  > +       close(efd);
> > > 
> > >  > +       if (CHECK(bytes <= 0 || bytes >= sizeof(buf), "read",
> > > 
> > >  > +                 "bytes %d errno %d\n", bytes, errno))
> > > 
> > >  > +               goto close_prog;
> > > 
> > >  > +
> > > 
> > >  > +       attr.config = strtol(buf, NULL, 0);
> > > 
> > >  > +       attr.type = PERF_TYPE_TRACEPOINT;
> > > 
> > >  > +       attr.sample_type = PERF_SAMPLE_RAW;
> > > 
> > >  > +       attr.sample_period = 1;
> > > 
> > >  > +       attr.wakeup_events = 1;
> > > 
> > >  > +
> > > 
> > >  > +       pmu_fd = syscall(__NR_perf_event_open, &attr, getpid(), -1, 
> > > -1, 0);
> > > 
> > >  > +       if (CHECK(pmu_fd < 0, "perf_event_open", "err %d errno %d\n", 
> > > pmu_fd,
> > > 
> > >  > +                 errno))
> > > 
> > >  > +               goto close_prog;
> > > 
> > >  > +
> > > 
> > >  > +       err = ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0);
> > > 
> > >  > +       if (CHECK(err, "perf_event_ioc_enable", "err %d errno %d\n", err,
> > > 
> > >  > +                 errno))
> > > 
> > >  > +               goto close_pmu;
> > > 
> > >  > +
> > > 
> > >  > +       err = ioctl(pmu_fd, PERF_EVENT_IOC_SET_BPF, prog_fd);
> > > 
> > >  > +       if (CHECK(err, "perf_event_ioc_set_bpf", "err %d errno %d\n", 
> > > err,
> > > 
> > >  > +                 errno))
> > > 
> > >  > +               goto close_pmu;
> > > 
> > >  > +
> > > 
> > >  > +       /* trigger some syscalls */
> > > 
> > >  > +       sleep(1);
> > > 
> > >  > +
> > > 
> > >  > +       err = bpf_map_lookup_elem(nsidmap_fd, &key, &knsid);
> > > 
> > >  > +       if (CHECK(err, "bpf_map_lookup_elem", "err %d errno %d\n", 
> > > err, errno))
> > > 
> > >  > +               goto close_pmu;
> > > 
> > >  > +
> > > 
> > >  > +       if (stat("/proc/self/ns/pid", &st))
> > > 
> > >  > +               goto close_pmu;
> > > 
> > >  > +
> > > 
> > >  > +       if (CHECK(knsid != (__u32) st.st_ino, "compare_namespace_id",
> > > 
> > >  > +                 "kern knsid %u user unsid %u\n", knsid, (__u32) 
> > > st.st_ino))
> > > 
> > >  > +               goto close_pmu;
> > > 
> > >  > +
> > > 
> > >  > +       exit_code = 0;
> > > 
> > >  > +       printf("%s:PASS\n", argv[0]);
> > > 
> > >  > +
> > > 
> > >  > +close_pmu:
> > > 
> > >  > +       close(pmu_fd);
> > > 
> > >  > +close_prog:
> > > 
> > >  > +       bpf_object__close(obj);
> > > 
> > >  > +cleanup_cgroup_env:
> > > 
> > >  > +       return exit_code;
> > > 
> > >  > +}
> > > 
> > >  > --
> > > 
> > >  > 2.11.0
> > > 
> > >  >
> > > 
> > >  >
> > > 
> > >  >
> > > 
> > >  >
> > > 
> > >  >
> > > 
> > >  >
> > > 
> > >  > On Thu, Aug 08, 2019 at 05:09:51AM +0000, Yonghong Song wrote:
> > > 
> > >  > >
> > > 
> > >  > >
> > > 
> > >  > > On 8/7/19 6:22 PM, Carlos Antonio Neira Bustos wrote:
> > > 
> > >  > > > The code has been modified to avoid syscalls that could sleep.
> > > 
> > >  > > > Please let me know if any other modification is needed.
> > > 
> > >  > > >
> > > 
> > >  > > >  From be0384c0fa209a78c1567936e8db4e35b9a7c0f8 Mon Sep 17 
> > > 00:00:00 2001
> > > 
> > >  > > > From: Carlos <cneirabustos@gmail.com>
> > > 
> > >  > > > Date: Wed, 7 Aug 2019 20:04:30 -0400
> > > 
> > >  > > > Subject: [PATCH] [PATCH v5 bpf-next] BPF: New helper to obtain 
> > > namespace data
> > > 
> > >  > > >   from current task
> > > 
> > >  > > >
> > > 
> > >  > > > This helper obtains the active namespace from current and returns 
> > > pid, tgid,
> > > 
> > >  > > > device and namespace id as seen from that namespace, allowing to 
> > > instrument
> > > 
> > >  > > > a process inside a container.
> > > 
> > >  > > > Device is read from /proc/self/ns/pid, as in the future it's 
> > > possible that
> > > 
> > >  > > > different pid_ns files may belong to different devices, according
> > > 
> > >  > > > to the discussion between Eric Biederman and Yonghong in 2017 
> > > linux plumbers
> > > 
> > >  > > > conference.
> > > 
> > >  > > > Currently bpf_get_current_pid_tgid(), is used to do pid filtering 
> > > in bcc's
> > > 
> > >  > > > scripts but this helper returns the pid as seen by the root 
> > > namespace which is
> > > 
> > >  > > > fine when a bcc script is not executed inside a container.
> > > 
> > >  > > > When the process of interest is inside a container, pid filtering 
> > > will not work
> > > 
> > >  > > > if bpf_get_current_pid_tgid() is used. This helper addresses this 
> > > limitation
> > > 
> > >  > > > returning the pid as it's seen by the current namespace where the 
> > > script is
> > > 
> > >  > > > executing.
> > > 
> > >  > > >
> > > 
> > >  > > > This helper has the same use cases as bpf_get_current_pid_tgid() 
> > > as it can be
> > > 
> > >  > > > used to do pid filtering even inside a container.
> > > 
> > >  > > >
> > > 
> > >  > > > For example a bcc script using bpf_get_current_pid_tgid() 
> > > (tools/funccount.py):
> > > 
> > >  > > >
> > > 
> > >  > > >          u32 pid = bpf_get_current_pid_tgid() >> 32;
> > > 
> > >  > > >          if (pid != <pid_arg_passed_in>)
> > > 
> > >  > > >                  return 0;
> > > 
> > >  > > > Could be modified to use bpf_get_current_pidns_info() as follows:
> > > 
> > >  > > >
> > > 
> > >  > > >          struct bpf_pidns pidns;
> > > 
> > >  > > >          bpf_get_current_pidns_info(&pidns, sizeof(struct 
> > > bpf_pidns));
> > > 
> > >  > > >          u32 pid = pidns.tgid;
> > > 
> > >  > > >          u32 nsid = pidns.nsid;
> > > 
> > >  > > >          if ((pid != <pid_arg_passed_in>) && (nsid != 
> > > <nsid_arg_passed_in>))
> > > 
> > >  > > >                  return 0;
> > > 
> > >  > > >
> > > 
> > >  > > > To find out the name PID namespace id of a process, you could use 
> > > this command:
> > > 
> > >  > > >
> > > 
> > >  > > > $ ps -h -o pidns -p <pid_of_interest>
> > > 
> > >  > > >
> > > 
> > >  > > > Or this other command:
> > > 
> > >  > > >
> > > 
> > >  > > > $ ls -Li /proc/<pid_of_interest>/ns/pid
> > > 
> > >  > > >
> > > 
> > >  > > > Signed-off-by: Carlos Neira <cneirabustos@gmail.com>
> > > 
> > >  > > > ---
> > > 
> > >  > > >   fs/namei.c                                         |   2 +-
> > > 
> > >  > > >   include/linux/bpf.h                                |   1 +
> > > 
> > >  > > >   include/linux/namei.h                              |   4 +
> > > 
> > >  > > >   include/uapi/linux/bpf.h                           |  29 ++++-
> > > 
> > >  > > >   kernel/bpf/core.c                                  |   1 +
> > > 
> > >  > > >   kernel/bpf/helpers.c                               |  78 
> > > ++++++++++++
> > > 
> > >  > > >   kernel/trace/bpf_trace.c                           |   2 +
> > > 
> > >  > > >   samples/bpf/Makefile                               |   3 +
> > > 
> > >  > > >   samples/bpf/trace_ns_info_user.c                   |  35 ++++++
> > > 
> > >  > > >   samples/bpf/trace_ns_info_user_kern.c              |  44 +++++++
> > > 
> > >  > > >   tools/include/uapi/linux/bpf.h                     |  29 ++++-
> > > 
> > >  > > >   tools/testing/selftests/bpf/Makefile               |   2 +-
> > > 
> > >  > > >   tools/testing/selftests/bpf/bpf_helpers.h          |   3 +
> > > 
> > >  > > >   .../testing/selftests/bpf/progs/test_pidns_kern.c  |  51 ++++++++
> > > 
> > >  > > >   tools/testing/selftests/bpf/test_pidns.c           | 138 
> > > +++++++++++++++++++++
> > > 
> > >  > > >   15 files changed, 418 insertions(+), 4 deletions(-)
> > > 
> > >  > > >   create mode 100644 samples/bpf/trace_ns_info_user.c
> > > 
> > >  > > >   create mode 100644 samples/bpf/trace_ns_info_user_kern.c
> > > 
> > >  > > >   create mode 100644 
> > > tools/testing/selftests/bpf/progs/test_pidns_kern.c
> > > 
> > >  > > >   create mode 100644 tools/testing/selftests/bpf/test_pidns.c
> > > 
> > >  > > >
> > > 
> > >  > > > diff --git a/fs/namei.c b/fs/namei.c
> > > 
> > >  > > > index 209c51a5226c..d1eca36972d2 100644
> > > 
> > >  > > > --- a/fs/namei.c
> > > 
> > >  > > > +++ b/fs/namei.c
> > > 
> > >  > > > @@ -19,7 +19,6 @@
> > > 
> > >  > > >   #include <linux/export.h>
> > > 
> > >  > > >   #include <linux/kernel.h>
> > > 
> > >  > > >   #include <linux/slab.h>
> > > 
> > >  > > > -#include <linux/fs.h>
> > > 
> > >  > > >   #include <linux/namei.h>
> > > 
> > >  > > >   #include <linux/pagemap.h>
> > > 
> > >  > > >   #include <linux/fsnotify.h>
> > > 
> > >  > > > @@ -2355,6 +2354,7 @@ int filename_lookup(int dfd, struct 
> > > filename *name, unsigned flags,
> > > 
> > >  > > >     putname(name);
> > > 
> > >  > > >     return retval;
> > > 
> > >  > > >   }
> > > 
> > >  > > > +EXPORT_SYMBOL(filename_lookup);
> > > 
> > >  > >
> > > 
> > >  > > No need to export symbols. bpf uses it and bpf is in the core, not in
> > > 
> > >  > > modules.
> > > 
> > >  > >
> > > 
> > >  > > >
> > > 
> > >  > > >   /* Returns 0 and nd will be valid on success; Retuns error, 
> > > otherwise. */
> > > 
> > >  > > >   static int path_parentat(struct nameidata *nd, unsigned flags,
> > > 
> > >  > > > diff --git a/include/linux/bpf.h b/include/linux/bpf.h
> > > 
> > >  > > > index f9a506147c8a..e4adf5e05afd 100644
> > > 
> > >  > > > --- a/include/linux/bpf.h
> > > 
> > >  > > > +++ b/include/linux/bpf.h
> > > 
> > >  > > > @@ -1050,6 +1050,7 @@ extern const struct bpf_func_proto 
> > > bpf_get_local_storage_proto;
> > > 
> > >  > > >   extern const struct bpf_func_proto bpf_strtol_proto;
> > > 
> > >  > > >   extern const struct bpf_func_proto bpf_strtoul_proto;
> > > 
> > >  > > >   extern const struct bpf_func_proto bpf_tcp_sock_proto;
> > > 
> > >  > > > +extern const struct bpf_func_proto bpf_get_current_pidns_info_proto;
> > > 
> > >  > > >
> > > 
> > >  > > >   /* Shared helpers among cBPF and eBPF. */
> > > 
> > >  > > >   void bpf_user_rnd_init_once(void);
> > > 
> > >  > > > diff --git a/include/linux/namei.h b/include/linux/namei.h
> > > 
> > >  > > > index 9138b4471dbf..2c24e8c71d46 100644
> > > 
> > >  > > > --- a/include/linux/namei.h
> > > 
> > >  > > > +++ b/include/linux/namei.h
> > > 
> > >  > > > @@ -6,6 +6,7 @@
> > > 
> > >  > > >   #include <linux/path.h>
> > > 
> > >  > > >   #include <linux/fcntl.h>
> > > 
> > >  > > >   #include <linux/errno.h>
> > > 
> > >  > > > +#include <linux/fs.h>
> > > 
> > >  > > >
> > > 
> > >  > > >   enum { MAX_NESTED_LINKS = 8 };
> > > 
> > >  > > >
> > > 
> > >  > > > @@ -97,6 +98,9 @@ extern void unlock_rename(struct dentry *, 
> > > struct dentry *);
> > > 
> > >  > > >
> > > 
> > >  > > >   extern void nd_jump_link(struct path *path);
> > > 
> > >  > > >
> > > 
> > >  > > > +extern int filename_lookup(int dfd, struct filename *name, 
> > > unsigned int flags,
> > > 
> > >  > > > +               struct path *path, struct path *root);
> > > 
> > >  > >
> > > 
> > >  > > The previous definition in fs/internal.h should be removed.
> > > 
> > >  > >
> > > 
> > >  > > > +
> > > 
> > >  > > >   static inline void nd_terminate_link(void *name, size_t len, 
> > > size_t maxlen)
> > > 
> > >  > > >   {
> > > 
> > >  > > >     ((char *) name)[min(len, maxlen)] = '\0';
> > > 
> > >  > > > diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> > > 
> > >  > > > index 4393bd4b2419..6f601f7106e2 100644
> > > 
> > >  > > > --- a/include/uapi/linux/bpf.h
> > > 
> > >  > > > +++ b/include/uapi/linux/bpf.h
> > > 
> > >  > > > @@ -2741,6 +2741,26 @@ union bpf_attr {
> > > 
> > >  > > >    *                **-EOPNOTSUPP** kernel configuration does not 
> > > enable SYN cookies
> > > 
> > >  > > >    *
> > > 
> > >  > > >    *                **-EPROTONOSUPPORT** IP packet version is not 
> > > 4 or 6
> > > 
> > >  > > > + *
> > > 
> > >  > > > + * int bpf_get_current_pidns_info(struct bpf_pidns_info *pidns, 
> > > u32 size_of_pidns)
> > > 
> > >  > > > + * Description
> > > 
> > >  > > > + *         Copies into *pidns* pid, namespace id and tgid as 
> > > seen by the
> > > 
> > >  > > > + *         current namespace and also device from /proc/self/ns/pid.
> > > 
> > >  > > > + *         *size_of_pidns* must be the size of *pidns*
> > > 
> > >  > > > + *
> > > 
> > >  > > > + *         This helper is used when pid filtering is needed inside a
> > > 
> > >  > > > + *         container as bpf_get_current_tgid() helper returns 
> > > always the
> > > 
> > >  > > > + *         pid id as seen by the root namespace.
> > > 
> > >  > > > + * Return
> > > 
> > >  > > > + *         0 on success
> > > 
> > >  > > > + *
> > > 
> > >  > > > + *         **-EINVAL**  if unable to get ns, pid or tgid of 
> > > current task.
> > > 
> > >  > > > + *         Or if size_of_pidns is not valid.
> > > 
> > >  > >
> > > 
> > >  > > Maybe reword by following the code sequence.
> > > 
> > >  > >     if *size_of_pidns* is not valid or unable to get ns, pid or tgid of
> > > 
> > >  > >     the current task.
> > > 
> > >  > >
> > > 
> > >  > > > + *
> > > 
> > >  > > > + *         **-ENOMEM**  if allocation fails.
> > > 
> > >  > >
> > > 
> > >  > > Maybe some other error codes in filename_lookup() function?
> > > 
> > >  > >
> > > 
> > >  > > > + *
> > > 
> > >  > > > + *         If unable to get the inode from /proc/self/ns/pid an 
> > > error code
> > > 
> > >  > > > + *         will be returned.
> > > 
> > >  > >
> > > 
> > >  > > You do not need this. The description of error code cases should 
> > > cover this.
> > > 
> > >  > >
> > > 
> > >  > > >    */
> > > 
> > >  > > >   #define __BPF_FUNC_MAPPER(FN)             \
> > > 
> > >  > > >     FN(unspec),                     \
> > > 
> > >  > > > @@ -2853,7 +2873,8 @@ union bpf_attr {
> > > 
> > >  > > >     FN(sk_storage_get),             \
> > > 
> > >  > > >     FN(sk_storage_delete),          \
> > > 
> > >  > > >     FN(send_signal),                \
> > > 
> > >  > > > -   FN(tcp_gen_syncookie),
> > > 
> > >  > > > +   FN(tcp_gen_syncookie),          \
> > > 
> > >  > > > +   FN(get_current_pidns_info),
> > > 
> > >  > > >
> > > 
> > >  > > >   /* integer value in 'imm' field of BPF_CALL instruction selects 
> > > which helper
> > > 
> > >  > > >    * function eBPF program intends to call
> > > 
> > >  > > > @@ -3604,4 +3625,10 @@ struct bpf_sockopt {
> > > 
> > >  > > >     __s32   retval;
> > > 
> > >  > > >   };
> > > 
> > >  > > >
> > > 
> > >  > > > +struct bpf_pidns_info {
> > > 
> > >  > > > +   __u32 dev;
> > > 
> > >  > > > +   __u32 nsid;
> > > 
> > >  > > > +   __u32 tgid;
> > > 
> > >  > > > +   __u32 pid;
> > > 
> > >  > > > +};
> > > 
> > >  > > >   #endif /* _UAPI__LINUX_BPF_H__ */
> > > 
> > >  > > > diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
> > > 
> > >  > > > index 8191a7db2777..3159f2a0188c 100644
> > > 
> > >  > > > --- a/kernel/bpf/core.c
> > > 
> > >  > > > +++ b/kernel/bpf/core.c
> > > 
> > >  > > > @@ -2038,6 +2038,7 @@ const struct bpf_func_proto 
> > > bpf_get_current_uid_gid_proto __weak;
> > > 
> > >  > > >   const struct bpf_func_proto bpf_get_current_comm_proto __weak;
> > > 
> > >  > > >   const struct bpf_func_proto bpf_get_current_cgroup_id_proto __weak;
> > > 
> > >  > > >   const struct bpf_func_proto bpf_get_local_storage_proto __weak;
> > > 
> > >  > > > +const struct bpf_func_proto bpf_get_current_pidns_info __weak;
> > > 
> > >  > > >
> > > 
> > >  > > >   const struct bpf_func_proto * __weak 
> > > bpf_get_trace_printk_proto(void)
> > > 
> > >  > > >   {
> > > 
> > >  > > > diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
> > > 
> > >  > > > index 5e28718928ca..571f24077db2 100644
> > > 
> > >  > > > --- a/kernel/bpf/helpers.c
> > > 
> > >  > > > +++ b/kernel/bpf/helpers.c
> > > 
> > >  > > > @@ -11,6 +11,12 @@
> > > 
> > >  > > >   #include <linux/uidgid.h>
> > > 
> > >  > > >   #include <linux/filter.h>
> > > 
> > >  > > >   #include <linux/ctype.h>
> > > 
> > >  > > > +#include <linux/pid_namespace.h>
> > > 
> > >  > > > +#include <linux/major.h>
> > > 
> > >  > > > +#include <linux/stat.h>
> > > 
> > >  > > > +#include <linux/namei.h>
> > > 
> > >  > > > +#include <linux/version.h>
> > > 
> > >  > > > +
> > > 
> > >  > > >
> > > 
> > >  > > >   #include "../../lib/kstrtox.h"
> > > 
> > >  > > >
> > > 
> > >  > > > @@ -312,6 +318,78 @@ void copy_map_value_locked(struct bpf_map 
> > > *map, void *dst, void *src,
> > > 
> > >  > > >     preempt_enable();
> > > 
> > >  > > >   }
> > > 
> > >  > > >
> > > 
> > >  > > > +BPF_CALL_2(bpf_get_current_pidns_info, struct bpf_pidns_info *, 
> > > pidns_info, u32,
> > > 
> > >  > > > +    size)
> > > 
> > >  > > > +{
> > > 
> > >  > > > +   const char *name = "/proc/self/ns/pid";
> > > 
> > >  > >
> > > 
> > >  > > maybe rename this variable to pidns_path?
> > > 
> > >  > >
> > > 
> > >  > > > +   struct pid_namespace *pidns = NULL;
> > > 
> > >  > > > +   struct filename *tmp = NULL;
> > > 
> > >  > >
> > > 
> > >  > > Maybe rename this variable to name?
> > > 
> > >  > >
> > > 
> > >  > > > +   int len = strlen(name) + 1;
> > > 
> > >  > >
> > > 
> > >  > > We can delay this assignment later until it is needed.
> > > 
> > >  > >
> > > 
> > >  > > > +   struct inode *inode;
> > > 
> > >  > > > +   struct path kp;
> > > 
> > >  > > > +   pid_t tgid = 0;
> > > 
> > >  > > > +   pid_t pid = 0;
> > > 
> > >  > > > +   int ret;
> > > 
> > >  > > > +
> > > 
> > >  > > > +   if (unlikely(size != sizeof(struct bpf_pidns_info)))
> > > 
> > >  > > > +           return -EINVAL;
> > > 
> > >  > > > +
> > > 
> > >  > > > +   pidns = task_active_pid_ns(current);
> > > 
> > >  > > > +
> > > 
> > >  > >
> > > 
> > >  > > we can save an empty line here.
> > > 
> > >  > >
> > > 
> > >  > > > +   if (unlikely(!pidns))
> > > 
> > >  > > > +           goto clear;
> > > 
> > >  > > > +
> > > 
> > >  > > > +   pidns_info->nsid =  pidns->ns.inum;
> > > 
> > >  > > > +   pid = task_pid_nr_ns(current, pidns);
> > > 
> > >  > > > +
> > > 
> > >  > >
> > > 
> > >  > > We can save an empty line here.
> > > 
> > >  > >
> > > 
> > >  > > > +   if (unlikely(!pid))
> > > 
> > >  > > > +           goto clear;
> > > 
> > >  > > > +
> > > 
> > >  > > > +   tgid = task_tgid_nr_ns(current, pidns);
> > > 
> > >  > > > +
> > > 
> > >  > > ditto. save an empty line.
> > > 
> > >  > > > +   if (unlikely(!tgid))
> > > 
> > >  > > > +           goto clear;
> > > 
> > >  > > > +
> > > 
> > >  > > > +   pidns_info->tgid = (u32) tgid;
> > > 
> > >  > > > +   pidns_info->pid = (u32) pid;
> > > 
> > >  > > > +
> > > 
> > >  > > > +   tmp = kmem_cache_alloc(names_cachep, GFP_ATOMIC);
> > > 
> > >  > > > +   if (unlikely(!tmp)) {
> > > 
> > >  > > > +           memset((void *)pidns_info, 0, (size_t) size);
> > > 
> > >  > > > +           return -ENOMEM;
> > > 
> > >  > > > +   }
> > > 
> > >  > > > +
> > > 
> > >  > > > +   memcpy((char *)tmp->name, name, len);
> > > 
> > >  > > > +   tmp->uptr = NULL;
> > > 
> > >  > > > +   tmp->aname = NULL;
> > > 
> > >  > > > +   tmp->refcnt = 1;
> > > 
> > >  > > > +
> > > 
> > >  > > ditto. save an empty line.
> > > 
> > >  > > > +   ret = filename_lookup(AT_FDCWD, tmp, 0, &kp, NULL);
> > > 
> > >  > > > +
> > > 
> > >  > > ditto. save an empty line.
> > > 
> > >  > > > +   if (ret) {
> > > 
> > >  > > > +           memset((void *)pidns_info, 0, (size_t) size);
> > > 
> > >  > > > +           return ret;
> > > 
> > >  > > > +   }
> > > 
> > >  > > > +
> > > 
> > >  > > > +   inode = d_backing_inode(kp.dentry);
> > > 
> > >  > > > +   pidns_info->dev = inode->i_sb->s_dev;
> > > 
> > >  > > > +
> > > 
> > >  > > > +   return 0;
> > > 
> > >  > > > +
> > > 
> > >  > > > +clear:
> > > 
> > >  > > > +   memset((void *)pidns_info, 0, (size_t) size);
> > > 
> > >  > > > +
> > > 
> > >  > > save an empty line.
> > > 
> > >  > > > +   return -EINVAL;
> > > 
> > >  > > > +}
> > > 
> > >  > > > +
> > > 
> > >  > > > +const struct bpf_func_proto bpf_get_current_pidns_info_proto = {
> > > 
> > >  > > > +   .func   = bpf_get_current_pidns_info,
> > > 
> > >  > > make the "= " aligned with others?
> > > 
> > >  > > > +   .gpl_only       = false,
> > > 
> > >  > > > +   .ret_type       = RET_INTEGER,
> > > 
> > >  > > > +   .arg1_type      = ARG_PTR_TO_UNINIT_MEM,
> > > 
> > >  > > > +   .arg2_type      = ARG_CONST_SIZE,
> > > 
> > >  > > > +};
> > > 
> > >  > > > +
> > > 
> > >  > > >   #ifdef CONFIG_CGROUPS
> > > 
> > >  > > >   BPF_CALL_0(bpf_get_current_cgroup_id)
> > > 
> > >  > > >   {
> > > 
> > >  > > > diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
> > > 
> > >  > > > index ca1255d14576..5e1dc22765a5 100644
> > > 
> > >  > > > --- a/kernel/trace/bpf_trace.c
> > > 
> > >  > > > +++ b/kernel/trace/bpf_trace.c
> > > 
> > >  > > > @@ -709,6 +709,8 @@ tracing_func_proto(enum bpf_func_id func_id, 
> > > const struct bpf_prog *prog)
> > > 
> > >  > > >   #endif
> > > 
> > >  > > >     case BPF_FUNC_send_signal:
> > > 
> > >  > > >             return &bpf_send_signal_proto;
> > > 
> > >  > > > +   case BPF_FUNC_get_current_pidns_info:
> > > 
> > >  > > > +           return &bpf_get_current_pidns_info_proto;
> > > 
> > >  > > >     default:
> > > 
> > >  > > >             return NULL;
> > > 
> > >  > > >     }
> > > 
> > >  > > > diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
> > > 
> > >  > > > index 1d9be26b4edd..238453ff27d2 100644
> > > 
> > >  > > > --- a/samples/bpf/Makefile
> > > 
> > >  > > > +++ b/samples/bpf/Makefile
> > > 
> > >  > > > @@ -53,6 +53,7 @@ hostprogs-y += task_fd_query
> > > 
> > >  > > >   hostprogs-y += xdp_sample_pkts
> > > 
> > >  > > >   hostprogs-y += ibumad
> > > 
> > >  > > >   hostprogs-y += hbm
> > > 
> > >  > > > +hostprogs-y += trace_ns_info
> > > 
> > >  > > [...]
> > > 

^ permalink raw reply related

* [PATCH net-next] r8169: inline rtl8169_free_rx_databuff
From: Heiner Kallweit @ 2019-08-09 20:59 UTC (permalink / raw)
  To: Realtek linux nic maintainers, David Miller; +Cc: netdev@vger.kernel.org

rtl8169_free_rx_databuff is used in only one place, so let's inline it.
We can improve the loop because rtl8169_init_ring zero's RX_databuff
before calling rtl8169_rx_fill, and rtl8169_rx_fill fills
Rx_databuff starting from index 0.

Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
---
 drivers/net/ethernet/realtek/r8169_main.c | 24 +++++++----------------
 1 file changed, 7 insertions(+), 17 deletions(-)

diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
index b2a275d85..641a34942 100644
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -5260,18 +5260,6 @@ static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc)
 	desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask);
 }
 
-static void rtl8169_free_rx_databuff(struct rtl8169_private *tp,
-				     struct page **data_buff,
-				     struct RxDesc *desc)
-{
-	dma_unmap_page(tp_to_dev(tp), le64_to_cpu(desc->addr),
-		       R8169_RX_BUF_SIZE, DMA_FROM_DEVICE);
-
-	__free_pages(*data_buff, get_order(R8169_RX_BUF_SIZE));
-	*data_buff = NULL;
-	rtl8169_make_unusable_by_asic(desc);
-}
-
 static inline void rtl8169_mark_to_asic(struct RxDesc *desc)
 {
 	u32 eor = le32_to_cpu(desc->opts1) & RingEnd;
@@ -5312,11 +5300,13 @@ static void rtl8169_rx_clear(struct rtl8169_private *tp)
 {
 	unsigned int i;
 
-	for (i = 0; i < NUM_RX_DESC; i++) {
-		if (tp->Rx_databuff[i]) {
-			rtl8169_free_rx_databuff(tp, tp->Rx_databuff + i,
-					    tp->RxDescArray + i);
-		}
+	for (i = 0; i < NUM_RX_DESC && tp->Rx_databuff[i]; i++) {
+		dma_unmap_page(tp_to_dev(tp),
+			       le64_to_cpu(tp->RxDescArray[i].addr),
+			       R8169_RX_BUF_SIZE, DMA_FROM_DEVICE);
+		__free_pages(tp->Rx_databuff[i], get_order(R8169_RX_BUF_SIZE));
+		tp->Rx_databuff[i] = NULL;
+		rtl8169_make_unusable_by_asic(tp->RxDescArray + i);
 	}
 }
 
-- 
2.22.0


^ permalink raw reply related

* Re: [PATCH net-next v6 3/3] net: phy: broadcom: add 1000Base-X support for BCM54616S
From: Tao Ren @ 2019-08-09 20:54 UTC (permalink / raw)
  To: Heiner Kallweit, Andrew Lunn, Florian Fainelli, David S . Miller,
	Arun Parameswaran, Justin Chen, Vladimir Oltean,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
	openbmc@lists.ozlabs.org
In-Reply-To: <97cd059c-d98e-1392-c814-f3bd628e6366@gmail.com>

Hi Heiner,

On 8/9/19 1:21 PM, Heiner Kallweit wrote:
> On 09.08.2019 07:44, Tao Ren wrote:
>> The BCM54616S PHY cannot work properly in RGMII->1000Base-KX mode (for
>> example, on Facebook CMM BMC platform), mainly because genphy functions
>> are designed for copper links, and 1000Base-X (clause 37) auto negotiation
>> needs to be handled differently.
>>
>> This patch enables 1000Base-X support for BCM54616S by customizing 3
>> driver callbacks:
>>
>>   - probe: probe callback detects PHY's operation mode based on
>>     INTERF_SEL[1:0] pins and 1000X/100FX selection bit in SerDES 100-FX
>>     Control register.
>>
>>   - config_aneg: calls genphy_c37_config_aneg when the PHY is running in
>>     1000Base-X mode; otherwise, genphy_config_aneg will be called.
>>
>>   - read_status: calls genphy_c37_read_status when the PHY is running in
>>     1000Base-X mode; otherwise, genphy_read_status will be called.
>>
>> Signed-off-by: Tao Ren <taoren@fb.com>
>> ---
>>  Changes in v6:
>>   - nothing changed.
>>  Changes in v5:
>>   - include Heiner's patch "net: phy: add support for clause 37
>>     auto-negotiation" into the series.
>>   - use genphy_c37_config_aneg and genphy_c37_read_status in BCM54616S
>>     PHY driver's callback when the PHY is running in 1000Base-X mode.
>>  Changes in v4:
>>   - add bcm54616s_config_aneg_1000bx() to deal with auto negotiation in
>>     1000Base-X mode.
>>  Changes in v3:
>>   - rename bcm5482_read_status to bcm54xx_read_status so the callback can
>>     be shared by BCM5482 and BCM54616S.
>>  Changes in v2:
>>   - Auto-detect PHY operation mode instead of passing DT node.
>>   - move PHY mode auto-detect logic from config_init to probe callback.
>>   - only set speed (not including duplex) in read_status callback.
>>   - update patch description with more background to avoid confusion.
>>   - patch #1 in the series ("net: phy: broadcom: set features explicitly
>>     for BCM54616") is dropped: the fix should go to get_features callback
>>     which may potentially depend on this patch.
>>
>>  drivers/net/phy/broadcom.c | 54 +++++++++++++++++++++++++++++++++++---
>>  include/linux/brcmphy.h    | 10 +++++--
>>  2 files changed, 58 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
>> index 937d0059e8ac..fbd76a31c142 100644
>> --- a/drivers/net/phy/broadcom.c
>> +++ b/drivers/net/phy/broadcom.c
>> @@ -383,9 +383,9 @@ static int bcm5482_config_init(struct phy_device *phydev)
>>  		/*
>>  		 * Select 1000BASE-X register set (primary SerDes)
>>  		 */
>> -		reg = bcm_phy_read_shadow(phydev, BCM5482_SHD_MODE);
>> -		bcm_phy_write_shadow(phydev, BCM5482_SHD_MODE,
>> -				     reg | BCM5482_SHD_MODE_1000BX);
>> +		reg = bcm_phy_read_shadow(phydev, BCM54XX_SHD_MODE);
>> +		bcm_phy_write_shadow(phydev, BCM54XX_SHD_MODE,
>> +				     reg | BCM54XX_SHD_MODE_1000BX);
>>  
>>  		/*
>>  		 * LED1=ACTIVITYLED, LED3=LINKSPD[2]
>> @@ -451,12 +451,44 @@ static int bcm5481_config_aneg(struct phy_device *phydev)
>>  	return ret;
>>  }
>>  
>> +static int bcm54616s_probe(struct phy_device *phydev)
>> +{
>> +	int val, intf_sel;
>> +
>> +	val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_MODE);
>> +	if (val < 0)
>> +		return val;
>> +
>> +	/* The PHY is strapped in RGMII to fiber mode when INTERF_SEL[1:0]
>> +	 * is 01b.
>> +	 */
>> +	intf_sel = (val & BCM54XX_SHD_INTF_SEL_MASK) >> 1;
>> +	if (intf_sel == 1) {
>> +		val = bcm_phy_read_shadow(phydev, BCM54616S_SHD_100FX_CTRL);
>> +		if (val < 0)
>> +			return val;
>> +
>> +		/* Bit 0 of the SerDes 100-FX Control register, when set
>> +		 * to 1, sets the MII/RGMII -> 100BASE-FX configuration.
>> +		 * When this bit is set to 0, it sets the GMII/RGMII ->
>> +		 * 1000BASE-X configuration.
>> +		 */
>> +		if (!(val & BCM54616S_100FX_MODE))
>> +			phydev->dev_flags |= PHY_BCM_FLAGS_MODE_1000BX;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>>  static int bcm54616s_config_aneg(struct phy_device *phydev)
>>  {
>>  	int ret;
>>  
>>  	/* Aneg firsly. */
>> -	ret = genphy_config_aneg(phydev);
>> +	if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX)
>> +		ret = genphy_c37_config_aneg(phydev);
>> +	else
>> +		ret = genphy_config_aneg(phydev);
>>  
> 
> I'm just wondering whether it needs to be considered that 100base-FX
> doesn't support auto-negotiation. I suppose BMSR reports aneg as
> supported, therefore phylib will use aneg per default.
> Not sure who could set 100Base-FX mode when, but maybe at that place
> also phydev->autoneg needs to be cleared. Did you test 100Base-FX mode?

I'm doubting if 100Base-FX works. Besides auto-negotiation, 100Base-FX Control/Status registers are defined in shadow register instead of MII_BMCR and MII_BMSR.

Unfortunately I don't have environment to test 100Base-FX and that's why I only make changes when the PHY is working in 1000X mode.


Thanks,

Tao

^ permalink raw reply

* Re: [PATCH net-next 00/12] net: hns3: add some bugfixes & optimizations & cleanups for HNS3 driver
From: David Miller @ 2019-08-09 20:44 UTC (permalink / raw)
  To: tanhuazhong; +Cc: netdev, linux-kernel, salil.mehta, yisen.zhuang, linuxarm
In-Reply-To: <1565317878-31806-1-git-send-email-tanhuazhong@huawei.com>

From: Huazhong Tan <tanhuazhong@huawei.com>
Date: Fri, 9 Aug 2019 10:31:06 +0800

> This patch-set includes code optimizations, bugfixes and cleanups for
> the HNS3 ethernet controller driver.

Series applied.

^ permalink raw reply

* Re: [PATCH net v2] hv_netvsc: Fix a warning of suspicious RCU usage
From: David Miller @ 2019-08-09 20:42 UTC (permalink / raw)
  To: decui
  Cc: netdev, haiyangz, sthemmin, jakub.kicinski, sashal, kys, mikelley,
	linux-hyperv, linux-kernel, olaf, apw, jasowang, vkuznets,
	marcelo.cerri
In-Reply-To: <PU1P153MB0169A6492DCBB490FE7FE52CBFD60@PU1P153MB0169.APCP153.PROD.OUTLOOK.COM>

From: Dexuan Cui <decui@microsoft.com>
Date: Fri, 9 Aug 2019 01:58:08 +0000

> This fixes a warning of "suspicious rcu_dereference_check() usage"
> when nload runs.
> 
> Fixes: 776e726bfb34 ("netvsc: fix RCU warning in get_stats")
> Signed-off-by: Dexuan Cui <decui@microsoft.com>

Applied.

^ permalink raw reply

* Re: [PATCH v2 net-next] taprio: remove unused variable 'entry_list_policy'
From: David Miller @ 2019-08-09 20:41 UTC (permalink / raw)
  To: yuehaibing
  Cc: jhs, xiyou.wangcong, jiri, vinicius.gomes, linux-kernel, netdev
In-Reply-To: <20190809014923.69328-1-yuehaibing@huawei.com>

From: YueHaibing <yuehaibing@huawei.com>
Date: Fri, 9 Aug 2019 09:49:23 +0800

> net/sched/sch_taprio.c:680:32: warning:
>  entry_list_policy defined but not used [-Wunused-const-variable=]
> 
> One of the points of commit a3d43c0d56f1 ("taprio: Add support adding
> an admin schedule") is that it removes support (it now returns "not
> supported") for schedules using the TCA_TAPRIO_ATTR_SCHED_SINGLE_ENTRY
> attribute (which were never used), the parsing of those types of schedules
> was the only user of this policy. So removing this policy should be fine.
> 
> Reported-by: Hulk Robot <hulkci@huawei.com>
> Suggested-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>
> Signed-off-by: YueHaibing <yuehaibing@huawei.com>
> ---
> v2: respin commit log using Vinicius's explanation.

Applied.

^ permalink raw reply

* Re: [PATCH net-next] r8169: fix performance issue on RTL8168evl
From: David Miller @ 2019-08-09 20:37 UTC (permalink / raw)
  To: hkallweit1; +Cc: nic_swsd, holger, netdev
In-Reply-To: <596f91ee-d5bf-52e9-94b6-011c707a15fb@gmail.com>

From: Heiner Kallweit <hkallweit1@gmail.com>
Date: Fri, 9 Aug 2019 00:02:40 +0200

> From: Holger Hoffstätte <holger@applied-asynchrony.com>
> Disabling TSO but leaving SG active results is a significant
> performance drop. Therefore disable also SG on RTL8168evl.
> This restores the original performance.
> 
> Fixes: 93681cd7d94f ("r8169: enable HW csum and TSO")
> Signed-off-by: Holger Hoffstätte <holger@applied-asynchrony.com>
> Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>

Applied.

^ permalink raw reply

* Re: [pull request][net 00/12] Mellanox, mlx5 fixes 2019-08-08
From: David Miller @ 2019-08-09 20:37 UTC (permalink / raw)
  To: saeedm; +Cc: netdev
In-Reply-To: <20190808202025.11303-1-saeedm@mellanox.com>

From: Saeed Mahameed <saeedm@mellanox.com>
Date: Thu, 8 Aug 2019 20:21:58 +0000

> This series introduces some fixes to mlx5 driver.
> 
> Highlights:
> 1) From Tariq, Critical mlx5 kTLS fixes to better align with hw specs.
> 2) From Aya, Fixes to mlx5 tx devlink health reporter.
> 3) From Maxim, aRFs parsing to use flow dissector to avoid relying on
> invalid skb fields.
> 
> Please pull and let me know if there is any problem.

Pulled.

> For -stable v4.3
>  ('net/mlx5e: Only support tx/rx pause setting for port owner')
> For -stable v4.9
>  ('net/mlx5e: Use flow keys dissector to parse packets for ARFS')
> For -stable v5.1
>  ('net/mlx5e: Fix false negative indication on tx reporter CQE recovery')
>  ('net/mlx5e: Remove redundant check in CQE recovery flow of tx reporter')
>  ('net/mlx5e: ethtool, Avoid setting speed to 56GBASE when autoneg off')

Queued up.

> Note: when merged with net-next this minor conflict will pop up:
> ++<<<<<<< (net-next)
>  +      if (is_eswitch_flow) {
>  +              flow->esw_attr->match_level = match_level;
>  +              flow->esw_attr->tunnel_match_level = tunnel_match_level;
> ++=======
> +       if (flow->flags & MLX5E_TC_FLOW_ESWITCH) {
> +               flow->esw_attr->inner_match_level = inner_match_level;
> +               flow->esw_attr->outer_match_level = outer_match_level;
> ++>>>>>>> (net)
> 
> To resolve, use hunks from net (2nd) and replace:
> if (flow->flags & MLX5E_TC_FLOW_ESWITCH) 
> with
> if (is_eswitch_flow)

Thanks for this.

^ permalink raw reply

* Re: [PATCH net-next v2 4/9] net: introduce MACsec ops and add a reference in net_device
From: Jakub Kicinski @ 2019-08-09 20:35 UTC (permalink / raw)
  To: Antoine Tenart
  Cc: davem, sd, andrew, f.fainelli, hkallweit1, netdev, linux-kernel,
	thomas.petazzoni, alexandre.belloni, allan.nielsen, camelia.groza,
	Simon.Edelhaus
In-Reply-To: <20190808140600.21477-5-antoine.tenart@bootlin.com>

On Thu,  8 Aug 2019 16:05:55 +0200, Antoine Tenart wrote:
> This patch introduces MACsec ops for drivers to support offloading
> MACsec operations. A reference to those ops is added in net_device.
> 
> Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
> ---
>  include/linux/netdevice.h | 31 +++++++++++++++++++++++++++++++
>  1 file changed, 31 insertions(+)
> 
> diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
> index 88292953aa6f..59ff123d62e3 100644
> --- a/include/linux/netdevice.h
> +++ b/include/linux/netdevice.h
> @@ -53,6 +53,7 @@ struct netpoll_info;
>  struct device;
>  struct phy_device;
>  struct dsa_port;
> +struct macsec_context;
>  
>  struct sfp_bus;
>  /* 802.11 specific */
> @@ -910,6 +911,29 @@ struct xfrmdev_ops {
>  };
>  #endif
>  
> +#if defined(CONFIG_MACSEC)
> +struct macsec_ops {

I think it'd be cleaner to have macsec_ops declared in macsec.h
and forward declare macsec_ops rather than macsec_context.

> +	/* Device wide */
> +	int (*mdo_dev_open)(struct macsec_context *ctx);
> +	int (*mdo_dev_stop)(struct macsec_context *ctx);
> +	/* SecY */
> +	int (*mdo_add_secy)(struct macsec_context *ctx);
> +	int (*mdo_upd_secy)(struct macsec_context *ctx);
> +	int (*mdo_del_secy)(struct macsec_context *ctx);
> +	/* Security channels */
> +	int (*mdo_add_rxsc)(struct macsec_context *ctx);
> +	int (*mdo_upd_rxsc)(struct macsec_context *ctx);
> +	int (*mdo_del_rxsc)(struct macsec_context *ctx);
> +	/* Security associations */
> +	int (*mdo_add_rxsa)(struct macsec_context *ctx);
> +	int (*mdo_upd_rxsa)(struct macsec_context *ctx);
> +	int (*mdo_del_rxsa)(struct macsec_context *ctx);
> +	int (*mdo_add_txsa)(struct macsec_context *ctx);
> +	int (*mdo_upd_txsa)(struct macsec_context *ctx);
> +	int (*mdo_del_txsa)(struct macsec_context *ctx);
> +};
> +#endif
> +
>  struct dev_ifalias {
>  	struct rcu_head rcuhead;
>  	char ifalias[];
> @@ -1755,6 +1779,8 @@ enum netdev_priv_flags {
>   *
>   *	@wol_enabled:	Wake-on-LAN is enabled
>   *
> + *	@macsec_ops:    MACsec offloading ops
> + *
>   *	FIXME: cleanup struct net_device such that network protocol info
>   *	moves out.
>   */
> @@ -2036,6 +2062,11 @@ struct net_device {
>  	struct lock_class_key	*qdisc_running_key;
>  	bool			proto_down;
>  	unsigned		wol_enabled:1;
> +
> +#if IS_ENABLED(CONFIG_MACSEC)
> +	/* MACsec management functions */
> +	const struct macsec_ops *macsec_ops;
> +#endif
>  };
>  #define to_net_dev(d) container_of(d, struct net_device, dev)
>  


^ permalink raw reply

* [PATCH 00/16] ARM: remove ks8695 and w90x900 platforms
From: Arnd Bergmann @ 2019-08-09 20:27 UTC (permalink / raw)
  To: soc
  Cc: Arnd Bergmann, Wanzongshun (Vincent), Greg Ungerer,
	Greg Kroah-Hartman, linux-serial, Dmitry Torokhov, linux-input,
	Linus Walleij, linux-gpio, David S. Miller, netdev, Guenter Roeck,
	Mark Brown, alsa-devel, linux-spi, Bartlomiej Zolnierkiewicz,
	linux-fbdev, Miquel Raynal, linux-mtd, linux-arm-kernel,
	linux-kernel

As discussed previously, these two ARM platforms have no
known remaining users, let's remove them completely.

Subsystem maintainers: feel free to take the driver removals
through your respective trees, they are all independent of
one another. We can merge any remaining patches through the
soc tree.

      Arnd

Arnd Bergmann (16):
  ARM: remove ks8695 platform
  serial: remove ks8695 driver
  gpio: remove ks8695 driver
  watchdog: remove ks8695 driver
  net: remove ks8695 driver
  watchdog: remove w90x900 driver
  spi: remove w90x900 driver
  ASoC: remove w90x900/nuc900 platform drivers
  fbdev: remove w90x900/nuc900 platform drivers
  Input: remove w90x900 keyboard driver
  Input: remove w90x900 touchscreen driver
  mtd: rawnand: remove w90x900 driver
  net: remove w90p910-ether driver
  rtc: remove w90x900/nuc900 driver
  usb: remove ehci-w90x900 driver
  ARM: remove w90x900 platform

Cc: "Wanzongshun (Vincent)" <wanzongshun@huawei.com>
Cc: Greg Ungerer <gerg@kernel.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: linux-serial@vger.kernel.org
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: linux-input@vger.kernel.org
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: linux-gpio@vger.kernel.org
Cc: "David S. Miller" <davem@davemloft.net>
Cc: netdev@vger.kernel.org
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Mark Brown <broonie@kernel.org>
Cc: alsa-devel@alsa-project.org
Cc: linux-spi@vger.kernel.org
Cc: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Cc: linux-fbdev@vger.kernel.org
Cc: Miquel Raynal <miquel.raynal@bootlin.com>
Cc: linux-mtd@lists.infradead.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org

 .../watchdog/watchdog-parameters.rst          |   19 -
 MAINTAINERS                                   |   22 -
 arch/arm/Kconfig                              |   34 +-
 arch/arm/Kconfig.debug                        |    8 -
 arch/arm/Makefile                             |    2 -
 arch/arm/configs/acs5k_defconfig              |   77 -
 arch/arm/configs/acs5k_tiny_defconfig         |   69 -
 arch/arm/configs/ks8695_defconfig             |   67 -
 arch/arm/configs/nuc910_defconfig             |   51 -
 arch/arm/configs/nuc950_defconfig             |   67 -
 arch/arm/configs/nuc960_defconfig             |   57 -
 arch/arm/include/debug/ks8695.S               |   37 -
 arch/arm/mach-ks8695/Kconfig                  |   88 -
 arch/arm/mach-ks8695/Makefile                 |   23 -
 arch/arm/mach-ks8695/Makefile.boot            |    9 -
 arch/arm/mach-ks8695/board-acs5k.c            |  238 ---
 arch/arm/mach-ks8695/board-dsm320.c           |  127 --
 arch/arm/mach-ks8695/board-micrel.c           |   59 -
 arch/arm/mach-ks8695/board-og.c               |  197 --
 arch/arm/mach-ks8695/board-sg.c               |  118 --
 arch/arm/mach-ks8695/cpu.c                    |   60 -
 arch/arm/mach-ks8695/devices.c                |  197 --
 arch/arm/mach-ks8695/devices.h                |   29 -
 arch/arm/mach-ks8695/generic.h                |   12 -
 .../mach-ks8695/include/mach/entry-macro.S    |   47 -
 .../mach-ks8695/include/mach/gpio-ks8695.h    |   36 -
 arch/arm/mach-ks8695/include/mach/hardware.h  |   42 -
 arch/arm/mach-ks8695/include/mach/irqs.h      |   51 -
 arch/arm/mach-ks8695/include/mach/memory.h    |   51 -
 arch/arm/mach-ks8695/include/mach/regs-gpio.h |   55 -
 arch/arm/mach-ks8695/include/mach/regs-irq.h  |   41 -
 arch/arm/mach-ks8695/include/mach/regs-misc.h |   97 -
 .../mach-ks8695/include/mach/regs-switch.h    |   66 -
 arch/arm/mach-ks8695/include/mach/regs-uart.h |   89 -
 .../arm/mach-ks8695/include/mach/uncompress.h |   33 -
 arch/arm/mach-ks8695/irq.c                    |  164 --
 arch/arm/mach-ks8695/pci.c                    |  247 ---
 arch/arm/mach-ks8695/regs-hpna.h              |   25 -
 arch/arm/mach-ks8695/regs-lan.h               |   65 -
 arch/arm/mach-ks8695/regs-mem.h               |   89 -
 arch/arm/mach-ks8695/regs-pci.h               |   53 -
 arch/arm/mach-ks8695/regs-sys.h               |   34 -
 arch/arm/mach-ks8695/regs-wan.h               |   65 -
 arch/arm/mach-ks8695/time.c                   |  159 --
 arch/arm/mach-w90x900/Kconfig                 |   50 -
 arch/arm/mach-w90x900/Makefile                |   20 -
 arch/arm/mach-w90x900/Makefile.boot           |    4 -
 arch/arm/mach-w90x900/clksel.c                |   88 -
 arch/arm/mach-w90x900/clock.c                 |  121 --
 arch/arm/mach-w90x900/clock.h                 |   40 -
 arch/arm/mach-w90x900/cpu.c                   |  238 ---
 arch/arm/mach-w90x900/cpu.h                   |   56 -
 arch/arm/mach-w90x900/dev.c                   |  537 ------
 arch/arm/mach-w90x900/gpio.c                  |  150 --
 .../mach-w90x900/include/mach/entry-macro.S   |   26 -
 arch/arm/mach-w90x900/include/mach/hardware.h |   19 -
 arch/arm/mach-w90x900/include/mach/irqs.h     |   82 -
 arch/arm/mach-w90x900/include/mach/map.h      |  153 --
 arch/arm/mach-w90x900/include/mach/mfp.h      |   21 -
 .../mach-w90x900/include/mach/regs-clock.h    |   49 -
 arch/arm/mach-w90x900/include/mach/regs-irq.h |   46 -
 arch/arm/mach-w90x900/include/mach/regs-ldm.h |  248 ---
 .../mach-w90x900/include/mach/regs-serial.h   |   54 -
 .../mach-w90x900/include/mach/uncompress.h    |   43 -
 arch/arm/mach-w90x900/irq.c                   |  212 ---
 arch/arm/mach-w90x900/mach-nuc910evb.c        |   38 -
 arch/arm/mach-w90x900/mach-nuc950evb.c        |   42 -
 arch/arm/mach-w90x900/mach-nuc960evb.c        |   38 -
 arch/arm/mach-w90x900/mfp.c                   |  197 --
 arch/arm/mach-w90x900/nuc910.c                |   58 -
 arch/arm/mach-w90x900/nuc910.h                |   17 -
 arch/arm/mach-w90x900/nuc950.c                |   52 -
 arch/arm/mach-w90x900/nuc950.h                |   17 -
 arch/arm/mach-w90x900/nuc960.c                |   50 -
 arch/arm/mach-w90x900/nuc960.h                |   17 -
 arch/arm/mach-w90x900/nuc9xx.h                |   22 -
 arch/arm/mach-w90x900/regs-ebi.h              |   29 -
 arch/arm/mach-w90x900/regs-gcr.h              |   34 -
 arch/arm/mach-w90x900/regs-timer.h            |   37 -
 arch/arm/mach-w90x900/regs-usb.h              |   31 -
 arch/arm/mach-w90x900/time.c                  |  168 --
 arch/arm/mm/Kconfig                           |    2 +-
 drivers/gpio/Makefile                         |    1 -
 drivers/gpio/gpio-ks8695.c                    |  284 ---
 drivers/input/keyboard/Kconfig                |   11 -
 drivers/input/keyboard/Makefile               |    1 -
 drivers/input/keyboard/w90p910_keypad.c       |  264 ---
 drivers/input/touchscreen/Kconfig             |    9 -
 drivers/input/touchscreen/Makefile            |    1 -
 drivers/input/touchscreen/w90p910_ts.c        |  331 ----
 drivers/mtd/nand/raw/Kconfig                  |    8 -
 drivers/mtd/nand/raw/Makefile                 |    1 -
 drivers/mtd/nand/raw/nuc900_nand.c            |  304 ---
 drivers/net/ethernet/Kconfig                  |    1 -
 drivers/net/ethernet/Makefile                 |    1 -
 drivers/net/ethernet/micrel/Kconfig           |   11 +-
 drivers/net/ethernet/micrel/Makefile          |    1 -
 drivers/net/ethernet/micrel/ks8695net.c       | 1632 -----------------
 drivers/net/ethernet/micrel/ks8695net.h       |  108 --
 drivers/net/ethernet/nuvoton/Kconfig          |   29 -
 drivers/net/ethernet/nuvoton/Makefile         |    6 -
 drivers/net/ethernet/nuvoton/w90p910_ether.c  | 1082 -----------
 drivers/rtc/Kconfig                           |    7 -
 drivers/rtc/Makefile                          |    1 -
 drivers/rtc/rtc-nuc900.c                      |  271 ---
 drivers/spi/Kconfig                           |    7 -
 drivers/spi/Makefile                          |    1 -
 drivers/spi/spi-nuc900.c                      |  429 -----
 drivers/tty/serial/Kconfig                    |   17 -
 drivers/tty/serial/Makefile                   |    1 -
 drivers/tty/serial/serial_ks8695.c            |  698 -------
 drivers/usb/host/Kconfig                      |    6 -
 drivers/usb/host/Makefile                     |    1 -
 drivers/usb/host/ehci-w90x900.c               |  130 --
 drivers/video/fbdev/Kconfig                   |   14 -
 drivers/video/fbdev/Makefile                  |    1 -
 drivers/video/fbdev/nuc900fb.c                |  760 --------
 drivers/video/fbdev/nuc900fb.h                |   51 -
 drivers/watchdog/Kconfig                      |   16 -
 drivers/watchdog/Makefile                     |    2 -
 drivers/watchdog/ks8695_wdt.c                 |  319 ----
 drivers/watchdog/nuc900_wdt.c                 |  302 ---
 include/Kbuild                                |    2 -
 include/linux/platform_data/keypad-w90p910.h  |   16 -
 include/linux/platform_data/spi-nuc900.h      |   29 -
 include/linux/platform_data/video-nuc900fb.h  |   79 -
 include/uapi/linux/serial_core.h              |    3 -
 sound/soc/Kconfig                             |    1 -
 sound/soc/Makefile                            |    1 -
 sound/soc/nuc900/Kconfig                      |   29 -
 sound/soc/nuc900/Makefile                     |   12 -
 sound/soc/nuc900/nuc900-ac97.c                |  391 ----
 sound/soc/nuc900/nuc900-audio.c               |   73 -
 sound/soc/nuc900/nuc900-audio.h               |  108 --
 sound/soc/nuc900/nuc900-pcm.c                 |  321 ----
 135 files changed, 6 insertions(+), 14461 deletions(-)
 delete mode 100644 arch/arm/configs/acs5k_defconfig
 delete mode 100644 arch/arm/configs/acs5k_tiny_defconfig
 delete mode 100644 arch/arm/configs/ks8695_defconfig
 delete mode 100644 arch/arm/configs/nuc910_defconfig
 delete mode 100644 arch/arm/configs/nuc950_defconfig
 delete mode 100644 arch/arm/configs/nuc960_defconfig
 delete mode 100644 arch/arm/include/debug/ks8695.S
 delete mode 100644 arch/arm/mach-ks8695/Kconfig
 delete mode 100644 arch/arm/mach-ks8695/Makefile
 delete mode 100644 arch/arm/mach-ks8695/Makefile.boot
 delete mode 100644 arch/arm/mach-ks8695/board-acs5k.c
 delete mode 100644 arch/arm/mach-ks8695/board-dsm320.c
 delete mode 100644 arch/arm/mach-ks8695/board-micrel.c
 delete mode 100644 arch/arm/mach-ks8695/board-og.c
 delete mode 100644 arch/arm/mach-ks8695/board-sg.c
 delete mode 100644 arch/arm/mach-ks8695/cpu.c
 delete mode 100644 arch/arm/mach-ks8695/devices.c
 delete mode 100644 arch/arm/mach-ks8695/devices.h
 delete mode 100644 arch/arm/mach-ks8695/generic.h
 delete mode 100644 arch/arm/mach-ks8695/include/mach/entry-macro.S
 delete mode 100644 arch/arm/mach-ks8695/include/mach/gpio-ks8695.h
 delete mode 100644 arch/arm/mach-ks8695/include/mach/hardware.h
 delete mode 100644 arch/arm/mach-ks8695/include/mach/irqs.h
 delete mode 100644 arch/arm/mach-ks8695/include/mach/memory.h
 delete mode 100644 arch/arm/mach-ks8695/include/mach/regs-gpio.h
 delete mode 100644 arch/arm/mach-ks8695/include/mach/regs-irq.h
 delete mode 100644 arch/arm/mach-ks8695/include/mach/regs-misc.h
 delete mode 100644 arch/arm/mach-ks8695/include/mach/regs-switch.h
 delete mode 100644 arch/arm/mach-ks8695/include/mach/regs-uart.h
 delete mode 100644 arch/arm/mach-ks8695/include/mach/uncompress.h
 delete mode 100644 arch/arm/mach-ks8695/irq.c
 delete mode 100644 arch/arm/mach-ks8695/pci.c
 delete mode 100644 arch/arm/mach-ks8695/regs-hpna.h
 delete mode 100644 arch/arm/mach-ks8695/regs-lan.h
 delete mode 100644 arch/arm/mach-ks8695/regs-mem.h
 delete mode 100644 arch/arm/mach-ks8695/regs-pci.h
 delete mode 100644 arch/arm/mach-ks8695/regs-sys.h
 delete mode 100644 arch/arm/mach-ks8695/regs-wan.h
 delete mode 100644 arch/arm/mach-ks8695/time.c
 delete mode 100644 arch/arm/mach-w90x900/Kconfig
 delete mode 100644 arch/arm/mach-w90x900/Makefile
 delete mode 100644 arch/arm/mach-w90x900/Makefile.boot
 delete mode 100644 arch/arm/mach-w90x900/clksel.c
 delete mode 100644 arch/arm/mach-w90x900/clock.c
 delete mode 100644 arch/arm/mach-w90x900/clock.h
 delete mode 100644 arch/arm/mach-w90x900/cpu.c
 delete mode 100644 arch/arm/mach-w90x900/cpu.h
 delete mode 100644 arch/arm/mach-w90x900/dev.c
 delete mode 100644 arch/arm/mach-w90x900/gpio.c
 delete mode 100644 arch/arm/mach-w90x900/include/mach/entry-macro.S
 delete mode 100644 arch/arm/mach-w90x900/include/mach/hardware.h
 delete mode 100644 arch/arm/mach-w90x900/include/mach/irqs.h
 delete mode 100644 arch/arm/mach-w90x900/include/mach/map.h
 delete mode 100644 arch/arm/mach-w90x900/include/mach/mfp.h
 delete mode 100644 arch/arm/mach-w90x900/include/mach/regs-clock.h
 delete mode 100644 arch/arm/mach-w90x900/include/mach/regs-irq.h
 delete mode 100644 arch/arm/mach-w90x900/include/mach/regs-ldm.h
 delete mode 100644 arch/arm/mach-w90x900/include/mach/regs-serial.h
 delete mode 100644 arch/arm/mach-w90x900/include/mach/uncompress.h
 delete mode 100644 arch/arm/mach-w90x900/irq.c
 delete mode 100644 arch/arm/mach-w90x900/mach-nuc910evb.c
 delete mode 100644 arch/arm/mach-w90x900/mach-nuc950evb.c
 delete mode 100644 arch/arm/mach-w90x900/mach-nuc960evb.c
 delete mode 100644 arch/arm/mach-w90x900/mfp.c
 delete mode 100644 arch/arm/mach-w90x900/nuc910.c
 delete mode 100644 arch/arm/mach-w90x900/nuc910.h
 delete mode 100644 arch/arm/mach-w90x900/nuc950.c
 delete mode 100644 arch/arm/mach-w90x900/nuc950.h
 delete mode 100644 arch/arm/mach-w90x900/nuc960.c
 delete mode 100644 arch/arm/mach-w90x900/nuc960.h
 delete mode 100644 arch/arm/mach-w90x900/nuc9xx.h
 delete mode 100644 arch/arm/mach-w90x900/regs-ebi.h
 delete mode 100644 arch/arm/mach-w90x900/regs-gcr.h
 delete mode 100644 arch/arm/mach-w90x900/regs-timer.h
 delete mode 100644 arch/arm/mach-w90x900/regs-usb.h
 delete mode 100644 arch/arm/mach-w90x900/time.c
 delete mode 100644 drivers/gpio/gpio-ks8695.c
 delete mode 100644 drivers/input/keyboard/w90p910_keypad.c
 delete mode 100644 drivers/input/touchscreen/w90p910_ts.c
 delete mode 100644 drivers/mtd/nand/raw/nuc900_nand.c
 delete mode 100644 drivers/net/ethernet/micrel/ks8695net.c
 delete mode 100644 drivers/net/ethernet/micrel/ks8695net.h
 delete mode 100644 drivers/net/ethernet/nuvoton/Kconfig
 delete mode 100644 drivers/net/ethernet/nuvoton/Makefile
 delete mode 100644 drivers/net/ethernet/nuvoton/w90p910_ether.c
 delete mode 100644 drivers/rtc/rtc-nuc900.c
 delete mode 100644 drivers/spi/spi-nuc900.c
 delete mode 100644 drivers/tty/serial/serial_ks8695.c
 delete mode 100644 drivers/usb/host/ehci-w90x900.c
 delete mode 100644 drivers/video/fbdev/nuc900fb.c
 delete mode 100644 drivers/video/fbdev/nuc900fb.h
 delete mode 100644 drivers/watchdog/ks8695_wdt.c
 delete mode 100644 drivers/watchdog/nuc900_wdt.c
 delete mode 100644 include/linux/platform_data/keypad-w90p910.h
 delete mode 100644 include/linux/platform_data/spi-nuc900.h
 delete mode 100644 include/linux/platform_data/video-nuc900fb.h
 delete mode 100644 sound/soc/nuc900/Kconfig
 delete mode 100644 sound/soc/nuc900/Makefile
 delete mode 100644 sound/soc/nuc900/nuc900-ac97.c
 delete mode 100644 sound/soc/nuc900/nuc900-audio.c
 delete mode 100644 sound/soc/nuc900/nuc900-audio.h
 delete mode 100644 sound/soc/nuc900/nuc900-pcm.c

-- 
2.20.0


^ permalink raw reply

* [PATCH 13/16] net: remove w90p910-ether driver
From: Arnd Bergmann @ 2019-08-09 20:27 UTC (permalink / raw)
  To: soc; +Cc: Arnd Bergmann, David S. Miller, linux-kernel, netdev
In-Reply-To: <20190809202749.742267-1-arnd@arndb.de>

The ARM w90x900 platform is getting removed, so this driver is obsolete.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 drivers/net/ethernet/Kconfig                 |    1 -
 drivers/net/ethernet/Makefile                |    1 -
 drivers/net/ethernet/nuvoton/Kconfig         |   29 -
 drivers/net/ethernet/nuvoton/Makefile        |    6 -
 drivers/net/ethernet/nuvoton/w90p910_ether.c | 1082 ------------------
 5 files changed, 1119 deletions(-)
 delete mode 100644 drivers/net/ethernet/nuvoton/Kconfig
 delete mode 100644 drivers/net/ethernet/nuvoton/Makefile
 delete mode 100644 drivers/net/ethernet/nuvoton/w90p910_ether.c

diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig
index 93a2d4deb27c..dc9dee55976b 100644
--- a/drivers/net/ethernet/Kconfig
+++ b/drivers/net/ethernet/Kconfig
@@ -151,7 +151,6 @@ config NET_NETX
 	  To compile this driver as a module, choose M here. The module
 	  will be called netx-eth.
 
-source "drivers/net/ethernet/nuvoton/Kconfig"
 source "drivers/net/ethernet/nvidia/Kconfig"
 source "drivers/net/ethernet/nxp/Kconfig"
 source "drivers/net/ethernet/oki-semi/Kconfig"
diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile
index fb9155cffcff..4bc3c95562bf 100644
--- a/drivers/net/ethernet/Makefile
+++ b/drivers/net/ethernet/Makefile
@@ -65,7 +65,6 @@ obj-$(CONFIG_NET_VENDOR_NETERION) += neterion/
 obj-$(CONFIG_NET_VENDOR_NETRONOME) += netronome/
 obj-$(CONFIG_NET_VENDOR_NI) += ni/
 obj-$(CONFIG_NET_NETX) += netx-eth.o
-obj-$(CONFIG_NET_VENDOR_NUVOTON) += nuvoton/
 obj-$(CONFIG_NET_VENDOR_NVIDIA) += nvidia/
 obj-$(CONFIG_LPC_ENET) += nxp/
 obj-$(CONFIG_NET_VENDOR_OKI) += oki-semi/
diff --git a/drivers/net/ethernet/nuvoton/Kconfig b/drivers/net/ethernet/nuvoton/Kconfig
deleted file mode 100644
index 325e26c549f8..000000000000
--- a/drivers/net/ethernet/nuvoton/Kconfig
+++ /dev/null
@@ -1,29 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-#
-# Nuvoton network device configuration
-#
-
-config NET_VENDOR_NUVOTON
-	bool "Nuvoton devices"
-	default y
-	depends on ARM && ARCH_W90X900
-	---help---
-	  If you have a network (Ethernet) card belonging to this class, say Y.
-
-	  Note that the answer to this question doesn't directly affect the
-	  kernel: saying N will just cause the configurator to skip all
-	  the questions about Nuvoton cards. If you say Y, you will be asked
-	  for your specific card in the following questions.
-
-if NET_VENDOR_NUVOTON
-
-config W90P910_ETH
-	tristate "Nuvoton w90p910 Ethernet support"
-	depends on ARM && ARCH_W90X900
-	select PHYLIB
-	select MII
-	---help---
-	  Say Y here if you want to use built-in Ethernet ports
-	  on w90p910 processor.
-
-endif # NET_VENDOR_NUVOTON
diff --git a/drivers/net/ethernet/nuvoton/Makefile b/drivers/net/ethernet/nuvoton/Makefile
deleted file mode 100644
index 66f6e728d54b..000000000000
--- a/drivers/net/ethernet/nuvoton/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-#
-# Makefile for the Nuvoton network device drivers.
-#
-
-obj-$(CONFIG_W90P910_ETH) += w90p910_ether.o
diff --git a/drivers/net/ethernet/nuvoton/w90p910_ether.c b/drivers/net/ethernet/nuvoton/w90p910_ether.c
deleted file mode 100644
index 3d73970b3a2e..000000000000
--- a/drivers/net/ethernet/nuvoton/w90p910_ether.c
+++ /dev/null
@@ -1,1082 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (c) 2008-2009 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/mii.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/ethtool.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/gfp.h>
-
-#define DRV_MODULE_NAME		"w90p910-emc"
-#define DRV_MODULE_VERSION	"0.1"
-
-/* Ethernet MAC Registers */
-#define REG_CAMCMR		0x00
-#define REG_CAMEN		0x04
-#define REG_CAMM_BASE		0x08
-#define REG_CAML_BASE		0x0c
-#define REG_TXDLSA		0x88
-#define REG_RXDLSA		0x8C
-#define REG_MCMDR		0x90
-#define REG_MIID		0x94
-#define REG_MIIDA		0x98
-#define REG_FFTCR		0x9C
-#define REG_TSDR		0xa0
-#define REG_RSDR		0xa4
-#define REG_DMARFC		0xa8
-#define REG_MIEN		0xac
-#define REG_MISTA		0xb0
-#define REG_CTXDSA		0xcc
-#define REG_CTXBSA		0xd0
-#define REG_CRXDSA		0xd4
-#define REG_CRXBSA		0xd8
-
-/* mac controller bit */
-#define MCMDR_RXON		0x01
-#define MCMDR_ACP		(0x01 << 3)
-#define MCMDR_SPCRC		(0x01 << 5)
-#define MCMDR_TXON		(0x01 << 8)
-#define MCMDR_FDUP		(0x01 << 18)
-#define MCMDR_ENMDC		(0x01 << 19)
-#define MCMDR_OPMOD		(0x01 << 20)
-#define SWR			(0x01 << 24)
-
-/* cam command regiser */
-#define CAMCMR_AUP		0x01
-#define CAMCMR_AMP		(0x01 << 1)
-#define CAMCMR_ABP		(0x01 << 2)
-#define CAMCMR_CCAM		(0x01 << 3)
-#define CAMCMR_ECMP		(0x01 << 4)
-#define CAM0EN			0x01
-
-/* mac mii controller bit */
-#define MDCCR			(0x0a << 20)
-#define PHYAD			(0x01 << 8)
-#define PHYWR			(0x01 << 16)
-#define PHYBUSY			(0x01 << 17)
-#define PHYPRESP		(0x01 << 18)
-#define CAM_ENTRY_SIZE		0x08
-
-/* rx and tx status */
-#define TXDS_TXCP		(0x01 << 19)
-#define RXDS_CRCE		(0x01 << 17)
-#define RXDS_PTLE		(0x01 << 19)
-#define RXDS_RXGD		(0x01 << 20)
-#define RXDS_ALIE		(0x01 << 21)
-#define RXDS_RP			(0x01 << 22)
-
-/* mac interrupt status*/
-#define MISTA_EXDEF		(0x01 << 19)
-#define MISTA_TXBERR		(0x01 << 24)
-#define MISTA_TDU		(0x01 << 23)
-#define MISTA_RDU		(0x01 << 10)
-#define MISTA_RXBERR		(0x01 << 11)
-
-#define ENSTART			0x01
-#define ENRXINTR		0x01
-#define ENRXGD			(0x01 << 4)
-#define ENRXBERR		(0x01 << 11)
-#define ENTXINTR		(0x01 << 16)
-#define ENTXCP			(0x01 << 18)
-#define ENTXABT			(0x01 << 21)
-#define ENTXBERR		(0x01 << 24)
-#define ENMDC			(0x01 << 19)
-#define PHYBUSY			(0x01 << 17)
-#define MDCCR_VAL		0xa00000
-
-/* rx and tx owner bit */
-#define RX_OWEN_DMA		(0x01 << 31)
-#define RX_OWEN_CPU		(~(0x03 << 30))
-#define TX_OWEN_DMA		(0x01 << 31)
-#define TX_OWEN_CPU		(~(0x01 << 31))
-
-/* tx frame desc controller bit */
-#define MACTXINTEN		0x04
-#define CRCMODE			0x02
-#define PADDINGMODE		0x01
-
-/* fftcr controller bit */
-#define TXTHD 			(0x03 << 8)
-#define BLENGTH			(0x01 << 20)
-
-/* global setting for driver */
-#define RX_DESC_SIZE		50
-#define TX_DESC_SIZE		10
-#define MAX_RBUFF_SZ		0x600
-#define MAX_TBUFF_SZ		0x600
-#define TX_TIMEOUT		(HZ/2)
-#define DELAY			1000
-#define CAM0			0x0
-
-static int w90p910_mdio_read(struct net_device *dev, int phy_id, int reg);
-
-struct w90p910_rxbd {
-	unsigned int sl;
-	unsigned int buffer;
-	unsigned int reserved;
-	unsigned int next;
-};
-
-struct w90p910_txbd {
-	unsigned int mode;
-	unsigned int buffer;
-	unsigned int sl;
-	unsigned int next;
-};
-
-struct recv_pdesc {
-	struct w90p910_rxbd desclist[RX_DESC_SIZE];
-	char recv_buf[RX_DESC_SIZE][MAX_RBUFF_SZ];
-};
-
-struct tran_pdesc {
-	struct w90p910_txbd desclist[TX_DESC_SIZE];
-	char tran_buf[TX_DESC_SIZE][MAX_TBUFF_SZ];
-};
-
-struct  w90p910_ether {
-	struct recv_pdesc *rdesc;
-	struct tran_pdesc *tdesc;
-	dma_addr_t rdesc_phys;
-	dma_addr_t tdesc_phys;
-	struct platform_device *pdev;
-	struct resource *res;
-	struct sk_buff *skb;
-	struct clk *clk;
-	struct clk *rmiiclk;
-	struct mii_if_info mii;
-	struct timer_list check_timer;
-	void __iomem *reg;
-	int rxirq;
-	int txirq;
-	unsigned int cur_tx;
-	unsigned int cur_rx;
-	unsigned int finish_tx;
-	unsigned int rx_packets;
-	unsigned int rx_bytes;
-	unsigned int start_tx_ptr;
-	unsigned int start_rx_ptr;
-	unsigned int linkflag;
-};
-
-static void update_linkspeed_register(struct net_device *dev,
-				unsigned int speed, unsigned int duplex)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	unsigned int val;
-
-	val = __raw_readl(ether->reg + REG_MCMDR);
-
-	if (speed == SPEED_100) {
-		/* 100 full/half duplex */
-		if (duplex == DUPLEX_FULL) {
-			val |= (MCMDR_OPMOD | MCMDR_FDUP);
-		} else {
-			val |= MCMDR_OPMOD;
-			val &= ~MCMDR_FDUP;
-		}
-	} else {
-		/* 10 full/half duplex */
-		if (duplex == DUPLEX_FULL) {
-			val |= MCMDR_FDUP;
-			val &= ~MCMDR_OPMOD;
-		} else {
-			val &= ~(MCMDR_FDUP | MCMDR_OPMOD);
-		}
-	}
-
-	__raw_writel(val, ether->reg + REG_MCMDR);
-}
-
-static void update_linkspeed(struct net_device *dev)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	struct platform_device *pdev;
-	unsigned int bmsr, bmcr, lpa, speed, duplex;
-
-	pdev = ether->pdev;
-
-	if (!mii_link_ok(&ether->mii)) {
-		ether->linkflag = 0x0;
-		netif_carrier_off(dev);
-		dev_warn(&pdev->dev, "%s: Link down.\n", dev->name);
-		return;
-	}
-
-	if (ether->linkflag == 1)
-		return;
-
-	bmsr = w90p910_mdio_read(dev, ether->mii.phy_id, MII_BMSR);
-	bmcr = w90p910_mdio_read(dev, ether->mii.phy_id, MII_BMCR);
-
-	if (bmcr & BMCR_ANENABLE) {
-		if (!(bmsr & BMSR_ANEGCOMPLETE))
-			return;
-
-		lpa = w90p910_mdio_read(dev, ether->mii.phy_id, MII_LPA);
-
-		if ((lpa & LPA_100FULL) || (lpa & LPA_100HALF))
-			speed = SPEED_100;
-		else
-			speed = SPEED_10;
-
-		if ((lpa & LPA_100FULL) || (lpa & LPA_10FULL))
-			duplex = DUPLEX_FULL;
-		else
-			duplex = DUPLEX_HALF;
-
-	} else {
-		speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10;
-		duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
-	}
-
-	update_linkspeed_register(dev, speed, duplex);
-
-	dev_info(&pdev->dev, "%s: Link now %i-%s\n", dev->name, speed,
-			(duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex");
-	ether->linkflag = 0x01;
-
-	netif_carrier_on(dev);
-}
-
-static void w90p910_check_link(struct timer_list *t)
-{
-	struct w90p910_ether *ether = from_timer(ether, t, check_timer);
-	struct net_device *dev = ether->mii.dev;
-
-	update_linkspeed(dev);
-	mod_timer(&ether->check_timer, jiffies + msecs_to_jiffies(1000));
-}
-
-static void w90p910_write_cam(struct net_device *dev,
-				unsigned int x, unsigned char *pval)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	unsigned int msw, lsw;
-
-	msw = (pval[0] << 24) | (pval[1] << 16) | (pval[2] << 8) | pval[3];
-
-	lsw = (pval[4] << 24) | (pval[5] << 16);
-
-	__raw_writel(lsw, ether->reg + REG_CAML_BASE + x * CAM_ENTRY_SIZE);
-	__raw_writel(msw, ether->reg + REG_CAMM_BASE + x * CAM_ENTRY_SIZE);
-}
-
-static int w90p910_init_desc(struct net_device *dev)
-{
-	struct w90p910_ether *ether;
-	struct w90p910_txbd  *tdesc;
-	struct w90p910_rxbd  *rdesc;
-	struct platform_device *pdev;
-	unsigned int i;
-
-	ether = netdev_priv(dev);
-	pdev = ether->pdev;
-
-	ether->tdesc = dma_alloc_coherent(&pdev->dev, sizeof(struct tran_pdesc),
-					  &ether->tdesc_phys, GFP_KERNEL);
-	if (!ether->tdesc)
-		return -ENOMEM;
-
-	ether->rdesc = dma_alloc_coherent(&pdev->dev, sizeof(struct recv_pdesc),
-					  &ether->rdesc_phys, GFP_KERNEL);
-	if (!ether->rdesc) {
-		dma_free_coherent(&pdev->dev, sizeof(struct tran_pdesc),
-				  ether->tdesc, ether->tdesc_phys);
-		return -ENOMEM;
-	}
-
-	for (i = 0; i < TX_DESC_SIZE; i++) {
-		unsigned int offset;
-
-		tdesc = &(ether->tdesc->desclist[i]);
-
-		if (i == TX_DESC_SIZE - 1)
-			offset = offsetof(struct tran_pdesc, desclist[0]);
-		else
-			offset = offsetof(struct tran_pdesc, desclist[i + 1]);
-
-		tdesc->next = ether->tdesc_phys + offset;
-		tdesc->buffer = ether->tdesc_phys +
-			offsetof(struct tran_pdesc, tran_buf[i]);
-		tdesc->sl = 0;
-		tdesc->mode = 0;
-	}
-
-	ether->start_tx_ptr = ether->tdesc_phys;
-
-	for (i = 0; i < RX_DESC_SIZE; i++) {
-		unsigned int offset;
-
-		rdesc = &(ether->rdesc->desclist[i]);
-
-		if (i == RX_DESC_SIZE - 1)
-			offset = offsetof(struct recv_pdesc, desclist[0]);
-		else
-			offset = offsetof(struct recv_pdesc, desclist[i + 1]);
-
-		rdesc->next = ether->rdesc_phys + offset;
-		rdesc->sl = RX_OWEN_DMA;
-		rdesc->buffer = ether->rdesc_phys +
-			offsetof(struct recv_pdesc, recv_buf[i]);
-	  }
-
-	ether->start_rx_ptr = ether->rdesc_phys;
-
-	return 0;
-}
-
-static void w90p910_set_fifo_threshold(struct net_device *dev)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	unsigned int val;
-
-	val = TXTHD | BLENGTH;
-	__raw_writel(val, ether->reg + REG_FFTCR);
-}
-
-static void w90p910_return_default_idle(struct net_device *dev)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	unsigned int val;
-
-	val = __raw_readl(ether->reg + REG_MCMDR);
-	val |= SWR;
-	__raw_writel(val, ether->reg + REG_MCMDR);
-}
-
-static void w90p910_trigger_rx(struct net_device *dev)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-
-	__raw_writel(ENSTART, ether->reg + REG_RSDR);
-}
-
-static void w90p910_trigger_tx(struct net_device *dev)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-
-	__raw_writel(ENSTART, ether->reg + REG_TSDR);
-}
-
-static void w90p910_enable_mac_interrupt(struct net_device *dev)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	unsigned int val;
-
-	val = ENTXINTR | ENRXINTR | ENRXGD | ENTXCP;
-	val |= ENTXBERR | ENRXBERR | ENTXABT;
-
-	__raw_writel(val, ether->reg + REG_MIEN);
-}
-
-static void w90p910_get_and_clear_int(struct net_device *dev,
-							unsigned int *val)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-
-	*val = __raw_readl(ether->reg + REG_MISTA);
-	__raw_writel(*val, ether->reg + REG_MISTA);
-}
-
-static void w90p910_set_global_maccmd(struct net_device *dev)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	unsigned int val;
-
-	val = __raw_readl(ether->reg + REG_MCMDR);
-	val |= MCMDR_SPCRC | MCMDR_ENMDC | MCMDR_ACP | ENMDC;
-	__raw_writel(val, ether->reg + REG_MCMDR);
-}
-
-static void w90p910_enable_cam(struct net_device *dev)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	unsigned int val;
-
-	w90p910_write_cam(dev, CAM0, dev->dev_addr);
-
-	val = __raw_readl(ether->reg + REG_CAMEN);
-	val |= CAM0EN;
-	__raw_writel(val, ether->reg + REG_CAMEN);
-}
-
-static void w90p910_enable_cam_command(struct net_device *dev)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	unsigned int val;
-
-	val = CAMCMR_ECMP | CAMCMR_ABP | CAMCMR_AMP;
-	__raw_writel(val, ether->reg + REG_CAMCMR);
-}
-
-static void w90p910_enable_tx(struct net_device *dev, unsigned int enable)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	unsigned int val;
-
-	val = __raw_readl(ether->reg + REG_MCMDR);
-
-	if (enable)
-		val |= MCMDR_TXON;
-	else
-		val &= ~MCMDR_TXON;
-
-	__raw_writel(val, ether->reg + REG_MCMDR);
-}
-
-static void w90p910_enable_rx(struct net_device *dev, unsigned int enable)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	unsigned int val;
-
-	val = __raw_readl(ether->reg + REG_MCMDR);
-
-	if (enable)
-		val |= MCMDR_RXON;
-	else
-		val &= ~MCMDR_RXON;
-
-	__raw_writel(val, ether->reg + REG_MCMDR);
-}
-
-static void w90p910_set_curdest(struct net_device *dev)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-
-	__raw_writel(ether->start_rx_ptr, ether->reg + REG_RXDLSA);
-	__raw_writel(ether->start_tx_ptr, ether->reg + REG_TXDLSA);
-}
-
-static void w90p910_reset_mac(struct net_device *dev)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-
-	w90p910_enable_tx(dev, 0);
-	w90p910_enable_rx(dev, 0);
-	w90p910_set_fifo_threshold(dev);
-	w90p910_return_default_idle(dev);
-
-	if (!netif_queue_stopped(dev))
-		netif_stop_queue(dev);
-
-	w90p910_init_desc(dev);
-
-	netif_trans_update(dev); /* prevent tx timeout */
-	ether->cur_tx = 0x0;
-	ether->finish_tx = 0x0;
-	ether->cur_rx = 0x0;
-
-	w90p910_set_curdest(dev);
-	w90p910_enable_cam(dev);
-	w90p910_enable_cam_command(dev);
-	w90p910_enable_mac_interrupt(dev);
-	w90p910_enable_tx(dev, 1);
-	w90p910_enable_rx(dev, 1);
-	w90p910_trigger_tx(dev);
-	w90p910_trigger_rx(dev);
-
-	netif_trans_update(dev); /* prevent tx timeout */
-
-	if (netif_queue_stopped(dev))
-		netif_wake_queue(dev);
-}
-
-static void w90p910_mdio_write(struct net_device *dev,
-					int phy_id, int reg, int data)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	struct platform_device *pdev;
-	unsigned int val, i;
-
-	pdev = ether->pdev;
-
-	__raw_writel(data, ether->reg + REG_MIID);
-
-	val = (phy_id << 0x08) | reg;
-	val |= PHYBUSY | PHYWR | MDCCR_VAL;
-	__raw_writel(val, ether->reg + REG_MIIDA);
-
-	for (i = 0; i < DELAY; i++) {
-		if ((__raw_readl(ether->reg + REG_MIIDA) & PHYBUSY) == 0)
-			break;
-	}
-
-	if (i == DELAY)
-		dev_warn(&pdev->dev, "mdio write timed out\n");
-}
-
-static int w90p910_mdio_read(struct net_device *dev, int phy_id, int reg)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	struct platform_device *pdev;
-	unsigned int val, i, data;
-
-	pdev = ether->pdev;
-
-	val = (phy_id << 0x08) | reg;
-	val |= PHYBUSY | MDCCR_VAL;
-	__raw_writel(val, ether->reg + REG_MIIDA);
-
-	for (i = 0; i < DELAY; i++) {
-		if ((__raw_readl(ether->reg + REG_MIIDA) & PHYBUSY) == 0)
-			break;
-	}
-
-	if (i == DELAY) {
-		dev_warn(&pdev->dev, "mdio read timed out\n");
-		data = 0xffff;
-	} else {
-		data = __raw_readl(ether->reg + REG_MIID);
-	}
-
-	return data;
-}
-
-static int w90p910_set_mac_address(struct net_device *dev, void *addr)
-{
-	struct sockaddr *address = addr;
-
-	if (!is_valid_ether_addr(address->sa_data))
-		return -EADDRNOTAVAIL;
-
-	memcpy(dev->dev_addr, address->sa_data, dev->addr_len);
-	w90p910_write_cam(dev, CAM0, dev->dev_addr);
-
-	return 0;
-}
-
-static int w90p910_ether_close(struct net_device *dev)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	struct platform_device *pdev;
-
-	pdev = ether->pdev;
-
-	dma_free_coherent(&pdev->dev, sizeof(struct recv_pdesc),
-					ether->rdesc, ether->rdesc_phys);
-	dma_free_coherent(&pdev->dev, sizeof(struct tran_pdesc),
-					ether->tdesc, ether->tdesc_phys);
-
-	netif_stop_queue(dev);
-
-	del_timer_sync(&ether->check_timer);
-	clk_disable(ether->rmiiclk);
-	clk_disable(ether->clk);
-
-	free_irq(ether->txirq, dev);
-	free_irq(ether->rxirq, dev);
-
-	return 0;
-}
-
-static int w90p910_send_frame(struct net_device *dev,
-					unsigned char *data, int length)
-{
-	struct w90p910_ether *ether;
-	struct w90p910_txbd *txbd;
-	struct platform_device *pdev;
-	unsigned char *buffer;
-
-	ether = netdev_priv(dev);
-	pdev = ether->pdev;
-
-	txbd = &ether->tdesc->desclist[ether->cur_tx];
-	buffer = ether->tdesc->tran_buf[ether->cur_tx];
-
-	if (length > 1514) {
-		dev_err(&pdev->dev, "send data %d bytes, check it\n", length);
-		length = 1514;
-	}
-
-	txbd->sl = length & 0xFFFF;
-
-	memcpy(buffer, data, length);
-
-	txbd->mode = TX_OWEN_DMA | PADDINGMODE | CRCMODE | MACTXINTEN;
-
-	w90p910_enable_tx(dev, 1);
-
-	w90p910_trigger_tx(dev);
-
-	if (++ether->cur_tx >= TX_DESC_SIZE)
-		ether->cur_tx = 0;
-
-	txbd = &ether->tdesc->desclist[ether->cur_tx];
-
-	if (txbd->mode & TX_OWEN_DMA)
-		netif_stop_queue(dev);
-
-	return 0;
-}
-
-static int w90p910_ether_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-
-	if (!(w90p910_send_frame(dev, skb->data, skb->len))) {
-		ether->skb = skb;
-		dev_consume_skb_irq(skb);
-		return 0;
-	}
-	return -EAGAIN;
-}
-
-static irqreturn_t w90p910_tx_interrupt(int irq, void *dev_id)
-{
-	struct w90p910_ether *ether;
-	struct w90p910_txbd  *txbd;
-	struct platform_device *pdev;
-	struct net_device *dev;
-	unsigned int cur_entry, entry, status;
-
-	dev = dev_id;
-	ether = netdev_priv(dev);
-	pdev = ether->pdev;
-
-	w90p910_get_and_clear_int(dev, &status);
-
-	cur_entry = __raw_readl(ether->reg + REG_CTXDSA);
-
-	entry = ether->tdesc_phys +
-		offsetof(struct tran_pdesc, desclist[ether->finish_tx]);
-
-	while (entry != cur_entry) {
-		txbd = &ether->tdesc->desclist[ether->finish_tx];
-
-		if (++ether->finish_tx >= TX_DESC_SIZE)
-			ether->finish_tx = 0;
-
-		if (txbd->sl & TXDS_TXCP) {
-			dev->stats.tx_packets++;
-			dev->stats.tx_bytes += txbd->sl & 0xFFFF;
-		} else {
-			dev->stats.tx_errors++;
-		}
-
-		txbd->sl = 0x0;
-		txbd->mode = 0x0;
-
-		if (netif_queue_stopped(dev))
-			netif_wake_queue(dev);
-
-		entry = ether->tdesc_phys +
-			offsetof(struct tran_pdesc, desclist[ether->finish_tx]);
-	}
-
-	if (status & MISTA_EXDEF) {
-		dev_err(&pdev->dev, "emc defer exceed interrupt\n");
-	} else if (status & MISTA_TXBERR) {
-		dev_err(&pdev->dev, "emc bus error interrupt\n");
-		w90p910_reset_mac(dev);
-	} else if (status & MISTA_TDU) {
-		if (netif_queue_stopped(dev))
-			netif_wake_queue(dev);
-	}
-
-	return IRQ_HANDLED;
-}
-
-static void netdev_rx(struct net_device *dev)
-{
-	struct w90p910_ether *ether;
-	struct w90p910_rxbd *rxbd;
-	struct platform_device *pdev;
-	struct sk_buff *skb;
-	unsigned char *data;
-	unsigned int length, status, val, entry;
-
-	ether = netdev_priv(dev);
-	pdev = ether->pdev;
-
-	rxbd = &ether->rdesc->desclist[ether->cur_rx];
-
-	do {
-		val = __raw_readl(ether->reg + REG_CRXDSA);
-
-		entry = ether->rdesc_phys +
-			offsetof(struct recv_pdesc, desclist[ether->cur_rx]);
-
-		if (val == entry)
-			break;
-
-		status = rxbd->sl;
-		length = status & 0xFFFF;
-
-		if (status & RXDS_RXGD) {
-			data = ether->rdesc->recv_buf[ether->cur_rx];
-			skb = netdev_alloc_skb(dev, length + 2);
-			if (!skb) {
-				dev->stats.rx_dropped++;
-				return;
-			}
-
-			skb_reserve(skb, 2);
-			skb_put(skb, length);
-			skb_copy_to_linear_data(skb, data, length);
-			skb->protocol = eth_type_trans(skb, dev);
-			dev->stats.rx_packets++;
-			dev->stats.rx_bytes += length;
-			netif_rx(skb);
-		} else {
-			dev->stats.rx_errors++;
-
-			if (status & RXDS_RP) {
-				dev_err(&pdev->dev, "rx runt err\n");
-				dev->stats.rx_length_errors++;
-			} else if (status & RXDS_CRCE) {
-				dev_err(&pdev->dev, "rx crc err\n");
-				dev->stats.rx_crc_errors++;
-			} else if (status & RXDS_ALIE) {
-				dev_err(&pdev->dev, "rx alignment err\n");
-				dev->stats.rx_frame_errors++;
-			} else if (status & RXDS_PTLE) {
-				dev_err(&pdev->dev, "rx longer err\n");
-				dev->stats.rx_over_errors++;
-			}
-		}
-
-		rxbd->sl = RX_OWEN_DMA;
-		rxbd->reserved = 0x0;
-
-		if (++ether->cur_rx >= RX_DESC_SIZE)
-			ether->cur_rx = 0;
-
-		rxbd = &ether->rdesc->desclist[ether->cur_rx];
-
-	} while (1);
-}
-
-static irqreturn_t w90p910_rx_interrupt(int irq, void *dev_id)
-{
-	struct net_device *dev;
-	struct w90p910_ether  *ether;
-	struct platform_device *pdev;
-	unsigned int status;
-
-	dev = dev_id;
-	ether = netdev_priv(dev);
-	pdev = ether->pdev;
-
-	w90p910_get_and_clear_int(dev, &status);
-
-	if (status & MISTA_RDU) {
-		netdev_rx(dev);
-		w90p910_trigger_rx(dev);
-
-		return IRQ_HANDLED;
-	} else if (status & MISTA_RXBERR) {
-		dev_err(&pdev->dev, "emc rx bus error\n");
-		w90p910_reset_mac(dev);
-	}
-
-	netdev_rx(dev);
-	return IRQ_HANDLED;
-}
-
-static int w90p910_ether_open(struct net_device *dev)
-{
-	struct w90p910_ether *ether;
-	struct platform_device *pdev;
-
-	ether = netdev_priv(dev);
-	pdev = ether->pdev;
-
-	w90p910_reset_mac(dev);
-	w90p910_set_fifo_threshold(dev);
-	w90p910_set_curdest(dev);
-	w90p910_enable_cam(dev);
-	w90p910_enable_cam_command(dev);
-	w90p910_enable_mac_interrupt(dev);
-	w90p910_set_global_maccmd(dev);
-	w90p910_enable_rx(dev, 1);
-
-	clk_enable(ether->rmiiclk);
-	clk_enable(ether->clk);
-
-	ether->rx_packets = 0x0;
-	ether->rx_bytes = 0x0;
-
-	if (request_irq(ether->txirq, w90p910_tx_interrupt,
-						0x0, pdev->name, dev)) {
-		dev_err(&pdev->dev, "register irq tx failed\n");
-		return -EAGAIN;
-	}
-
-	if (request_irq(ether->rxirq, w90p910_rx_interrupt,
-						0x0, pdev->name, dev)) {
-		dev_err(&pdev->dev, "register irq rx failed\n");
-		free_irq(ether->txirq, dev);
-		return -EAGAIN;
-	}
-
-	mod_timer(&ether->check_timer, jiffies + msecs_to_jiffies(1000));
-	netif_start_queue(dev);
-	w90p910_trigger_rx(dev);
-
-	dev_info(&pdev->dev, "%s is OPENED\n", dev->name);
-
-	return 0;
-}
-
-static void w90p910_ether_set_multicast_list(struct net_device *dev)
-{
-	struct w90p910_ether *ether;
-	unsigned int rx_mode;
-
-	ether = netdev_priv(dev);
-
-	if (dev->flags & IFF_PROMISC)
-		rx_mode = CAMCMR_AUP | CAMCMR_AMP | CAMCMR_ABP | CAMCMR_ECMP;
-	else if ((dev->flags & IFF_ALLMULTI) || !netdev_mc_empty(dev))
-		rx_mode = CAMCMR_AMP | CAMCMR_ABP | CAMCMR_ECMP;
-	else
-		rx_mode = CAMCMR_ECMP | CAMCMR_ABP;
-	__raw_writel(rx_mode, ether->reg + REG_CAMCMR);
-}
-
-static int w90p910_ether_ioctl(struct net_device *dev,
-						struct ifreq *ifr, int cmd)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	struct mii_ioctl_data *data = if_mii(ifr);
-
-	return generic_mii_ioctl(&ether->mii, data, cmd, NULL);
-}
-
-static void w90p910_get_drvinfo(struct net_device *dev,
-					struct ethtool_drvinfo *info)
-{
-	strlcpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
-	strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version));
-}
-
-static int w90p910_get_link_ksettings(struct net_device *dev,
-				      struct ethtool_link_ksettings *cmd)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-
-	mii_ethtool_get_link_ksettings(&ether->mii, cmd);
-
-	return 0;
-}
-
-static int w90p910_set_link_ksettings(struct net_device *dev,
-				      const struct ethtool_link_ksettings *cmd)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	return mii_ethtool_set_link_ksettings(&ether->mii, cmd);
-}
-
-static int w90p910_nway_reset(struct net_device *dev)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	return mii_nway_restart(&ether->mii);
-}
-
-static u32 w90p910_get_link(struct net_device *dev)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	return mii_link_ok(&ether->mii);
-}
-
-static const struct ethtool_ops w90p910_ether_ethtool_ops = {
-	.get_drvinfo	= w90p910_get_drvinfo,
-	.nway_reset	= w90p910_nway_reset,
-	.get_link	= w90p910_get_link,
-	.get_link_ksettings = w90p910_get_link_ksettings,
-	.set_link_ksettings = w90p910_set_link_ksettings,
-};
-
-static const struct net_device_ops w90p910_ether_netdev_ops = {
-	.ndo_open		= w90p910_ether_open,
-	.ndo_stop		= w90p910_ether_close,
-	.ndo_start_xmit		= w90p910_ether_start_xmit,
-	.ndo_set_rx_mode	= w90p910_ether_set_multicast_list,
-	.ndo_set_mac_address	= w90p910_set_mac_address,
-	.ndo_do_ioctl		= w90p910_ether_ioctl,
-	.ndo_validate_addr	= eth_validate_addr,
-};
-
-static void get_mac_address(struct net_device *dev)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	struct platform_device *pdev;
-	char addr[ETH_ALEN];
-
-	pdev = ether->pdev;
-
-	addr[0] = 0x00;
-	addr[1] = 0x02;
-	addr[2] = 0xac;
-	addr[3] = 0x55;
-	addr[4] = 0x88;
-	addr[5] = 0xa8;
-
-	if (is_valid_ether_addr(addr))
-		memcpy(dev->dev_addr, &addr, ETH_ALEN);
-	else
-		dev_err(&pdev->dev, "invalid mac address\n");
-}
-
-static int w90p910_ether_setup(struct net_device *dev)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-
-	dev->netdev_ops = &w90p910_ether_netdev_ops;
-	dev->ethtool_ops = &w90p910_ether_ethtool_ops;
-
-	dev->tx_queue_len = 16;
-	dev->dma = 0x0;
-	dev->watchdog_timeo = TX_TIMEOUT;
-
-	get_mac_address(dev);
-
-	ether->cur_tx = 0x0;
-	ether->cur_rx = 0x0;
-	ether->finish_tx = 0x0;
-	ether->linkflag = 0x0;
-	ether->mii.phy_id = 0x01;
-	ether->mii.phy_id_mask = 0x1f;
-	ether->mii.reg_num_mask = 0x1f;
-	ether->mii.dev = dev;
-	ether->mii.mdio_read = w90p910_mdio_read;
-	ether->mii.mdio_write = w90p910_mdio_write;
-
-	timer_setup(&ether->check_timer, w90p910_check_link, 0);
-
-	return 0;
-}
-
-static int w90p910_ether_probe(struct platform_device *pdev)
-{
-	struct w90p910_ether *ether;
-	struct net_device *dev;
-	int error;
-
-	dev = alloc_etherdev(sizeof(struct w90p910_ether));
-	if (!dev)
-		return -ENOMEM;
-
-	ether = netdev_priv(dev);
-
-	ether->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (ether->res == NULL) {
-		dev_err(&pdev->dev, "failed to get I/O memory\n");
-		error = -ENXIO;
-		goto failed_free;
-	}
-
-	if (!request_mem_region(ether->res->start,
-				resource_size(ether->res), pdev->name)) {
-		dev_err(&pdev->dev, "failed to request I/O memory\n");
-		error = -EBUSY;
-		goto failed_free;
-	}
-
-	ether->reg = ioremap(ether->res->start, resource_size(ether->res));
-	if (ether->reg == NULL) {
-		dev_err(&pdev->dev, "failed to remap I/O memory\n");
-		error = -ENXIO;
-		goto failed_free_mem;
-	}
-
-	ether->txirq = platform_get_irq(pdev, 0);
-	if (ether->txirq < 0) {
-		dev_err(&pdev->dev, "failed to get ether tx irq\n");
-		error = -ENXIO;
-		goto failed_free_io;
-	}
-
-	ether->rxirq = platform_get_irq(pdev, 1);
-	if (ether->rxirq < 0) {
-		dev_err(&pdev->dev, "failed to get ether rx irq\n");
-		error = -ENXIO;
-		goto failed_free_io;
-	}
-
-	platform_set_drvdata(pdev, dev);
-
-	ether->clk = clk_get(&pdev->dev, NULL);
-	if (IS_ERR(ether->clk)) {
-		dev_err(&pdev->dev, "failed to get ether clock\n");
-		error = PTR_ERR(ether->clk);
-		goto failed_free_io;
-	}
-
-	ether->rmiiclk = clk_get(&pdev->dev, "RMII");
-	if (IS_ERR(ether->rmiiclk)) {
-		dev_err(&pdev->dev, "failed to get ether clock\n");
-		error = PTR_ERR(ether->rmiiclk);
-		goto failed_put_clk;
-	}
-
-	ether->pdev = pdev;
-
-	w90p910_ether_setup(dev);
-
-	error = register_netdev(dev);
-	if (error != 0) {
-		dev_err(&pdev->dev, "Register EMC w90p910 FAILED\n");
-		error = -ENODEV;
-		goto failed_put_rmiiclk;
-	}
-
-	return 0;
-failed_put_rmiiclk:
-	clk_put(ether->rmiiclk);
-failed_put_clk:
-	clk_put(ether->clk);
-failed_free_io:
-	iounmap(ether->reg);
-failed_free_mem:
-	release_mem_region(ether->res->start, resource_size(ether->res));
-failed_free:
-	free_netdev(dev);
-	return error;
-}
-
-static int w90p910_ether_remove(struct platform_device *pdev)
-{
-	struct net_device *dev = platform_get_drvdata(pdev);
-	struct w90p910_ether *ether = netdev_priv(dev);
-
-	unregister_netdev(dev);
-
-	clk_put(ether->rmiiclk);
-	clk_put(ether->clk);
-
-	iounmap(ether->reg);
-	release_mem_region(ether->res->start, resource_size(ether->res));
-
-	del_timer_sync(&ether->check_timer);
-
-	free_netdev(dev);
-	return 0;
-}
-
-static struct platform_driver w90p910_ether_driver = {
-	.probe		= w90p910_ether_probe,
-	.remove		= w90p910_ether_remove,
-	.driver		= {
-		.name	= "nuc900-emc",
-	},
-};
-
-module_platform_driver(w90p910_ether_driver);
-
-MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>");
-MODULE_DESCRIPTION("w90p910 MAC driver!");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:nuc900-emc");
-
-- 
2.20.0


^ permalink raw reply related

* Re: [PATCH net-next] r8169: make use of xmit_more
From: Heiner Kallweit @ 2019-08-09 20:28 UTC (permalink / raw)
  To: Holger Hoffstätte, Eric Dumazet
  Cc: Realtek linux nic maintainers, David Miller,
	netdev@vger.kernel.org, Sander Eikelenboom
In-Reply-To: <72a58a6b-974c-0feb-2fa4-c8a71c7eff7e@applied-asynchrony.com>

On 09.08.2019 10:52, Holger Hoffstätte wrote:
> On 8/9/19 10:25 AM, Eric Dumazet wrote:
> (snip)
>>>
>>> So that didn't take long - got another timeout this morning during some
>>> random light usage, despite sg/tso being disabled this time.
>>> Again the only common element is the xmit_more patch. :(
>>> Not sure whether you want to revert this right away or wait for 5.4-rc1
>>> feedback. Maybe this too is chipset-specific?
>>>
>>>> Thanks a lot for the analysis and testing. Then I'll submit the disabling
>>>> of SG on RTL8168evl (on your behalf), independent of whether it fixes
>>>> the timeout issue.
>>>
>>> Got it, thanks!
>>>
>>> Holger
>>
>> I would try this fix maybe ?
>>
>> diff --git a/drivers/net/ethernet/realtek/r8169_main.c
>> b/drivers/net/ethernet/realtek/r8169_main.c
>> index b2a275d8504cf099cff738f2f7554efa9658fe32..e77628813daba493ad50dab9ac1e3703e38b560c
>> 100644
>> --- a/drivers/net/ethernet/realtek/r8169_main.c
>> +++ b/drivers/net/ethernet/realtek/r8169_main.c
>> @@ -5691,6 +5691,7 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
>>                   */
>>                  smp_wmb();
>>                  netif_stop_queue(dev);
>> +               door_bell = true;
>>          }
>>
>>          if (door_bell)
>>
> 
> Thanks Eric, I'll give that a try and see how it fares over the next few days.
> It suspiciously looks like it could help..
> 
> -h
> 
Thanks for testing this. Looking forward to your feedback regarding the change.

Heiner

^ permalink raw reply

* [PATCH 05/16] net: remove ks8695 driver
From: Arnd Bergmann @ 2019-08-09 20:27 UTC (permalink / raw)
  To: soc; +Cc: Arnd Bergmann, David S. Miller, linux-kernel, netdev
In-Reply-To: <20190809202749.742267-1-arnd@arndb.de>

The platform is getting removed, so there are no remaining
users of this driver.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 drivers/net/ethernet/micrel/Kconfig     |   11 +-
 drivers/net/ethernet/micrel/Makefile    |    1 -
 drivers/net/ethernet/micrel/ks8695net.c | 1632 -----------------------
 drivers/net/ethernet/micrel/ks8695net.h |  108 --
 4 files changed, 1 insertion(+), 1751 deletions(-)
 delete mode 100644 drivers/net/ethernet/micrel/ks8695net.c
 delete mode 100644 drivers/net/ethernet/micrel/ks8695net.h

diff --git a/drivers/net/ethernet/micrel/Kconfig b/drivers/net/ethernet/micrel/Kconfig
index 90a8c6bead56..b9c4d48e28e4 100644
--- a/drivers/net/ethernet/micrel/Kconfig
+++ b/drivers/net/ethernet/micrel/Kconfig
@@ -6,8 +6,7 @@
 config NET_VENDOR_MICREL
 	bool "Micrel devices"
 	default y
-	depends on (HAS_IOMEM && DMA_ENGINE) || SPI || PCI || HAS_IOMEM || \
-		   (ARM && ARCH_KS8695)
+	depends on (HAS_IOMEM && DMA_ENGINE) || SPI || PCI || HAS_IOMEM
 	---help---
 	  If you have a network (Ethernet) card belonging to this class, say Y.
 
@@ -18,14 +17,6 @@ config NET_VENDOR_MICREL
 
 if NET_VENDOR_MICREL
 
-config ARM_KS8695_ETHER
-	tristate "KS8695 Ethernet support"
-	depends on ARM && ARCH_KS8695
-	select MII
-	---help---
-	  If you wish to compile a kernel for the KS8695 and want to
-	  use the internal ethernet then you should answer Y to this.
-
 config KS8842
 	tristate "Micrel KSZ8841/42 with generic bus interface"
 	depends on HAS_IOMEM && DMA_ENGINE
diff --git a/drivers/net/ethernet/micrel/Makefile b/drivers/net/ethernet/micrel/Makefile
index 848fc1c5a5dc..6d8ac5527aef 100644
--- a/drivers/net/ethernet/micrel/Makefile
+++ b/drivers/net/ethernet/micrel/Makefile
@@ -3,7 +3,6 @@
 # Makefile for the Micrel network device drivers.
 #
 
-obj-$(CONFIG_ARM_KS8695_ETHER) += ks8695net.o
 obj-$(CONFIG_KS8842) += ks8842.o
 obj-$(CONFIG_KS8851) += ks8851.o
 obj-$(CONFIG_KS8851_MLL) += ks8851_mll.o
diff --git a/drivers/net/ethernet/micrel/ks8695net.c b/drivers/net/ethernet/micrel/ks8695net.c
deleted file mode 100644
index 1390ef5323a2..000000000000
--- a/drivers/net/ethernet/micrel/ks8695net.c
+++ /dev/null
@@ -1,1632 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Micrel KS8695 (Centaur) Ethernet.
- *
- * Copyright 2008 Simtec Electronics
- *		  Daniel Silverstone <dsilvers@simtec.co.uk>
- *		  Vincent Sanders <vince@simtec.co.uk>
- */
-
-#include <linux/dma-mapping.h>
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/interrupt.h>
-#include <linux/skbuff.h>
-#include <linux/spinlock.h>
-#include <linux/crc32.h>
-#include <linux/mii.h>
-#include <linux/ethtool.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#include <asm/irq.h>
-
-#include <mach/regs-switch.h>
-#include <mach/regs-misc.h>
-#include <asm/mach/irq.h>
-#include <mach/regs-irq.h>
-
-#include "ks8695net.h"
-
-#define MODULENAME	"ks8695_ether"
-#define MODULEVERSION	"1.02"
-
-/*
- * Transmit and device reset timeout, default 5 seconds.
- */
-static int watchdog = 5000;
-
-/* Hardware structures */
-
-/**
- *	struct rx_ring_desc - Receive descriptor ring element
- *	@status: The status of the descriptor element (E.g. who owns it)
- *	@length: The number of bytes in the block pointed to by data_ptr
- *	@data_ptr: The physical address of the data block to receive into
- *	@next_desc: The physical address of the next descriptor element.
- */
-struct rx_ring_desc {
-	__le32	status;
-	__le32	length;
-	__le32	data_ptr;
-	__le32	next_desc;
-};
-
-/**
- *	struct tx_ring_desc - Transmit descriptor ring element
- *	@owner: Who owns the descriptor
- *	@status: The number of bytes in the block pointed to by data_ptr
- *	@data_ptr: The physical address of the data block to receive into
- *	@next_desc: The physical address of the next descriptor element.
- */
-struct tx_ring_desc {
-	__le32	owner;
-	__le32	status;
-	__le32	data_ptr;
-	__le32	next_desc;
-};
-
-/**
- *	struct ks8695_skbuff - sk_buff wrapper for rx/tx rings.
- *	@skb: The buffer in the ring
- *	@dma_ptr: The mapped DMA pointer of the buffer
- *	@length: The number of bytes mapped to dma_ptr
- */
-struct ks8695_skbuff {
-	struct sk_buff	*skb;
-	dma_addr_t	dma_ptr;
-	u32		length;
-};
-
-/* Private device structure */
-
-#define MAX_TX_DESC 8
-#define MAX_TX_DESC_MASK 0x7
-#define MAX_RX_DESC 16
-#define MAX_RX_DESC_MASK 0xf
-
-/*napi_weight have better more than rx DMA buffers*/
-#define NAPI_WEIGHT   64
-
-#define MAX_RXBUF_SIZE 0x700
-
-#define TX_RING_DMA_SIZE (sizeof(struct tx_ring_desc) * MAX_TX_DESC)
-#define RX_RING_DMA_SIZE (sizeof(struct rx_ring_desc) * MAX_RX_DESC)
-#define RING_DMA_SIZE (TX_RING_DMA_SIZE + RX_RING_DMA_SIZE)
-
-/**
- *	enum ks8695_dtype - Device type
- *	@KS8695_DTYPE_WAN: This device is a WAN interface
- *	@KS8695_DTYPE_LAN: This device is a LAN interface
- *	@KS8695_DTYPE_HPNA: This device is an HPNA interface
- */
-enum ks8695_dtype {
-	KS8695_DTYPE_WAN,
-	KS8695_DTYPE_LAN,
-	KS8695_DTYPE_HPNA,
-};
-
-/**
- *	struct ks8695_priv - Private data for the KS8695 Ethernet
- *	@in_suspend: Flag to indicate if we're suspending/resuming
- *	@ndev: The net_device for this interface
- *	@dev: The platform device object for this interface
- *	@dtype: The type of this device
- *	@io_regs: The ioremapped registers for this interface
- *      @napi : Add support NAPI for Rx
- *	@rx_irq_name: The textual name of the RX IRQ from the platform data
- *	@tx_irq_name: The textual name of the TX IRQ from the platform data
- *	@link_irq_name: The textual name of the link IRQ from the
- *			platform data if available
- *	@rx_irq: The IRQ number for the RX IRQ
- *	@tx_irq: The IRQ number for the TX IRQ
- *	@link_irq: The IRQ number for the link IRQ if available
- *	@regs_req: The resource request for the registers region
- *	@phyiface_req: The resource request for the phy/switch region
- *		       if available
- *	@phyiface_regs: The ioremapped registers for the phy/switch if available
- *	@ring_base: The base pointer of the dma coherent memory for the rings
- *	@ring_base_dma: The DMA mapped equivalent of ring_base
- *	@tx_ring: The pointer in ring_base of the TX ring
- *	@tx_ring_used: The number of slots in the TX ring which are occupied
- *	@tx_ring_next_slot: The next slot to fill in the TX ring
- *	@tx_ring_dma: The DMA mapped equivalent of tx_ring
- *	@tx_buffers: The sk_buff mappings for the TX ring
- *	@txq_lock: A lock to protect the tx_buffers tx_ring_used etc variables
- *	@rx_ring: The pointer in ring_base of the RX ring
- *	@rx_ring_dma: The DMA mapped equivalent of rx_ring
- *	@rx_buffers: The sk_buff mappings for the RX ring
- *	@next_rx_desc_read: The next RX descriptor to read from on IRQ
- *      @rx_lock: A lock to protect Rx irq function
- *	@msg_enable: The flags for which messages to emit
- */
-struct ks8695_priv {
-	int in_suspend;
-	struct net_device *ndev;
-	struct device *dev;
-	enum ks8695_dtype dtype;
-	void __iomem *io_regs;
-
-	struct napi_struct	napi;
-
-	const char *rx_irq_name, *tx_irq_name, *link_irq_name;
-	int rx_irq, tx_irq, link_irq;
-
-	struct resource *regs_req, *phyiface_req;
-	void __iomem *phyiface_regs;
-
-	void *ring_base;
-	dma_addr_t ring_base_dma;
-
-	struct tx_ring_desc *tx_ring;
-	int tx_ring_used;
-	int tx_ring_next_slot;
-	dma_addr_t tx_ring_dma;
-	struct ks8695_skbuff tx_buffers[MAX_TX_DESC];
-	spinlock_t txq_lock;
-
-	struct rx_ring_desc *rx_ring;
-	dma_addr_t rx_ring_dma;
-	struct ks8695_skbuff rx_buffers[MAX_RX_DESC];
-	int next_rx_desc_read;
-	spinlock_t rx_lock;
-
-	int msg_enable;
-};
-
-/* Register access */
-
-/**
- *	ks8695_readreg - Read from a KS8695 ethernet register
- *	@ksp: The device to read from
- *	@reg: The register to read
- */
-static inline u32
-ks8695_readreg(struct ks8695_priv *ksp, int reg)
-{
-	return readl(ksp->io_regs + reg);
-}
-
-/**
- *	ks8695_writereg - Write to a KS8695 ethernet register
- *	@ksp: The device to write to
- *	@reg: The register to write
- *	@value: The value to write to the register
- */
-static inline void
-ks8695_writereg(struct ks8695_priv *ksp, int reg, u32 value)
-{
-	writel(value, ksp->io_regs + reg);
-}
-
-/* Utility functions */
-
-/**
- *	ks8695_port_type - Retrieve port-type as user-friendly string
- *	@ksp: The device to return the type for
- *
- *	Returns a string indicating which of the WAN, LAN or HPNA
- *	ports this device is likely to represent.
- */
-static const char *
-ks8695_port_type(struct ks8695_priv *ksp)
-{
-	switch (ksp->dtype) {
-	case KS8695_DTYPE_LAN:
-		return "LAN";
-	case KS8695_DTYPE_WAN:
-		return "WAN";
-	case KS8695_DTYPE_HPNA:
-		return "HPNA";
-	}
-
-	return "UNKNOWN";
-}
-
-/**
- *	ks8695_update_mac - Update the MAC registers in the device
- *	@ksp: The device to update
- *
- *	Updates the MAC registers in the KS8695 device from the address in the
- *	net_device structure associated with this interface.
- */
-static void
-ks8695_update_mac(struct ks8695_priv *ksp)
-{
-	/* Update the HW with the MAC from the net_device */
-	struct net_device *ndev = ksp->ndev;
-	u32 machigh, maclow;
-
-	maclow	= ((ndev->dev_addr[2] << 24) | (ndev->dev_addr[3] << 16) |
-		   (ndev->dev_addr[4] <<  8) | (ndev->dev_addr[5] <<  0));
-	machigh = ((ndev->dev_addr[0] <<  8) | (ndev->dev_addr[1] <<  0));
-
-	ks8695_writereg(ksp, KS8695_MAL, maclow);
-	ks8695_writereg(ksp, KS8695_MAH, machigh);
-
-}
-
-/**
- *	ks8695_refill_rxbuffers - Re-fill the RX buffer ring
- *	@ksp: The device to refill
- *
- *	Iterates the RX ring of the device looking for empty slots.
- *	For each empty slot, we allocate and map a new SKB and give it
- *	to the hardware.
- *	This can be called from interrupt context safely.
- */
-static void
-ks8695_refill_rxbuffers(struct ks8695_priv *ksp)
-{
-	/* Run around the RX ring, filling in any missing sk_buff's */
-	int buff_n;
-
-	for (buff_n = 0; buff_n < MAX_RX_DESC; ++buff_n) {
-		if (!ksp->rx_buffers[buff_n].skb) {
-			struct sk_buff *skb =
-				netdev_alloc_skb(ksp->ndev, MAX_RXBUF_SIZE);
-			dma_addr_t mapping;
-
-			ksp->rx_buffers[buff_n].skb = skb;
-			if (skb == NULL) {
-				/* Failed to allocate one, perhaps
-				 * we'll try again later.
-				 */
-				break;
-			}
-
-			mapping = dma_map_single(ksp->dev, skb->data,
-						 MAX_RXBUF_SIZE,
-						 DMA_FROM_DEVICE);
-			if (unlikely(dma_mapping_error(ksp->dev, mapping))) {
-				/* Failed to DMA map this SKB, try later */
-				dev_kfree_skb_irq(skb);
-				ksp->rx_buffers[buff_n].skb = NULL;
-				break;
-			}
-			ksp->rx_buffers[buff_n].dma_ptr = mapping;
-			ksp->rx_buffers[buff_n].length = MAX_RXBUF_SIZE;
-
-			/* Record this into the DMA ring */
-			ksp->rx_ring[buff_n].data_ptr = cpu_to_le32(mapping);
-			ksp->rx_ring[buff_n].length =
-				cpu_to_le32(MAX_RXBUF_SIZE);
-
-			wmb();
-
-			/* And give ownership over to the hardware */
-			ksp->rx_ring[buff_n].status = cpu_to_le32(RDES_OWN);
-		}
-	}
-}
-
-/* Maximum number of multicast addresses which the KS8695 HW supports */
-#define KS8695_NR_ADDRESSES	16
-
-/**
- *	ks8695_init_partial_multicast - Init the mcast addr registers
- *	@ksp: The device to initialise
- *	@addr: The multicast address list to use
- *	@nr_addr: The number of addresses in the list
- *
- *	This routine is a helper for ks8695_set_multicast - it writes
- *	the additional-address registers in the KS8695 ethernet device
- *	and cleans up any others left behind.
- */
-static void
-ks8695_init_partial_multicast(struct ks8695_priv *ksp,
-			      struct net_device *ndev)
-{
-	u32 low, high;
-	int i;
-	struct netdev_hw_addr *ha;
-
-	i = 0;
-	netdev_for_each_mc_addr(ha, ndev) {
-		/* Ran out of space in chip? */
-		BUG_ON(i == KS8695_NR_ADDRESSES);
-
-		low = (ha->addr[2] << 24) | (ha->addr[3] << 16) |
-		      (ha->addr[4] << 8) | (ha->addr[5]);
-		high = (ha->addr[0] << 8) | (ha->addr[1]);
-
-		ks8695_writereg(ksp, KS8695_AAL_(i), low);
-		ks8695_writereg(ksp, KS8695_AAH_(i), AAH_E | high);
-		i++;
-	}
-
-	/* Clear the remaining Additional Station Addresses */
-	for (; i < KS8695_NR_ADDRESSES; i++) {
-		ks8695_writereg(ksp, KS8695_AAL_(i), 0);
-		ks8695_writereg(ksp, KS8695_AAH_(i), 0);
-	}
-}
-
-/* Interrupt handling */
-
-/**
- *	ks8695_tx_irq - Transmit IRQ handler
- *	@irq: The IRQ which went off (ignored)
- *	@dev_id: The net_device for the interrupt
- *
- *	Process the TX ring, clearing out any transmitted slots.
- *	Allows the net_device to pass us new packets once slots are
- *	freed.
- */
-static irqreturn_t
-ks8695_tx_irq(int irq, void *dev_id)
-{
-	struct net_device *ndev = (struct net_device *)dev_id;
-	struct ks8695_priv *ksp = netdev_priv(ndev);
-	int buff_n;
-
-	for (buff_n = 0; buff_n < MAX_TX_DESC; ++buff_n) {
-		if (ksp->tx_buffers[buff_n].skb &&
-		    !(ksp->tx_ring[buff_n].owner & cpu_to_le32(TDES_OWN))) {
-			rmb();
-			/* An SKB which is not owned by HW is present */
-			/* Update the stats for the net_device */
-			ndev->stats.tx_packets++;
-			ndev->stats.tx_bytes += ksp->tx_buffers[buff_n].length;
-
-			/* Free the packet from the ring */
-			ksp->tx_ring[buff_n].data_ptr = 0;
-
-			/* Free the sk_buff */
-			dma_unmap_single(ksp->dev,
-					 ksp->tx_buffers[buff_n].dma_ptr,
-					 ksp->tx_buffers[buff_n].length,
-					 DMA_TO_DEVICE);
-			dev_consume_skb_irq(ksp->tx_buffers[buff_n].skb);
-			ksp->tx_buffers[buff_n].skb = NULL;
-			ksp->tx_ring_used--;
-		}
-	}
-
-	netif_wake_queue(ndev);
-
-	return IRQ_HANDLED;
-}
-
-/**
- *	ks8695_get_rx_enable_bit - Get rx interrupt enable/status bit
- *	@ksp: Private data for the KS8695 Ethernet
- *
- *    For KS8695 document:
- *    Interrupt Enable Register (offset 0xE204)
- *        Bit29 : WAN MAC Receive Interrupt Enable
- *        Bit16 : LAN MAC Receive Interrupt Enable
- *    Interrupt Status Register (Offset 0xF208)
- *        Bit29: WAN MAC Receive Status
- *        Bit16: LAN MAC Receive Status
- *    So, this Rx interrupt enable/status bit number is equal
- *    as Rx IRQ number.
- */
-static inline u32 ks8695_get_rx_enable_bit(struct ks8695_priv *ksp)
-{
-	return ksp->rx_irq;
-}
-
-/**
- *	ks8695_rx_irq - Receive IRQ handler
- *	@irq: The IRQ which went off (ignored)
- *	@dev_id: The net_device for the interrupt
- *
- *	Inform NAPI that packet reception needs to be scheduled
- */
-
-static irqreturn_t
-ks8695_rx_irq(int irq, void *dev_id)
-{
-	struct net_device *ndev = (struct net_device *)dev_id;
-	struct ks8695_priv *ksp = netdev_priv(ndev);
-
-	spin_lock(&ksp->rx_lock);
-
-	if (napi_schedule_prep(&ksp->napi)) {
-		unsigned long status = readl(KS8695_IRQ_VA + KS8695_INTEN);
-		unsigned long mask_bit = 1 << ks8695_get_rx_enable_bit(ksp);
-		/*disable rx interrupt*/
-		status &= ~mask_bit;
-		writel(status , KS8695_IRQ_VA + KS8695_INTEN);
-		__napi_schedule(&ksp->napi);
-	}
-
-	spin_unlock(&ksp->rx_lock);
-	return IRQ_HANDLED;
-}
-
-/**
- *	ks8695_rx - Receive packets called by NAPI poll method
- *	@ksp: Private data for the KS8695 Ethernet
- *	@budget: Number of packets allowed to process
- */
-static int ks8695_rx(struct ks8695_priv *ksp, int budget)
-{
-	struct net_device *ndev = ksp->ndev;
-	struct sk_buff *skb;
-	int buff_n;
-	u32 flags;
-	int pktlen;
-	int received = 0;
-
-	buff_n = ksp->next_rx_desc_read;
-	while (received < budget
-			&& ksp->rx_buffers[buff_n].skb
-			&& (!(ksp->rx_ring[buff_n].status &
-					cpu_to_le32(RDES_OWN)))) {
-			rmb();
-			flags = le32_to_cpu(ksp->rx_ring[buff_n].status);
-
-			/* Found an SKB which we own, this means we
-			 * received a packet
-			 */
-			if ((flags & (RDES_FS | RDES_LS)) !=
-			    (RDES_FS | RDES_LS)) {
-				/* This packet is not the first and
-				 * the last segment.  Therefore it is
-				 * a "spanning" packet and we can't
-				 * handle it
-				 */
-				goto rx_failure;
-			}
-
-			if (flags & (RDES_ES | RDES_RE)) {
-				/* It's an error packet */
-				ndev->stats.rx_errors++;
-				if (flags & RDES_TL)
-					ndev->stats.rx_length_errors++;
-				if (flags & RDES_RF)
-					ndev->stats.rx_length_errors++;
-				if (flags & RDES_CE)
-					ndev->stats.rx_crc_errors++;
-				if (flags & RDES_RE)
-					ndev->stats.rx_missed_errors++;
-
-				goto rx_failure;
-			}
-
-			pktlen = flags & RDES_FLEN;
-			pktlen -= 4; /* Drop the CRC */
-
-			/* Retrieve the sk_buff */
-			skb = ksp->rx_buffers[buff_n].skb;
-
-			/* Clear it from the ring */
-			ksp->rx_buffers[buff_n].skb = NULL;
-			ksp->rx_ring[buff_n].data_ptr = 0;
-
-			/* Unmap the SKB */
-			dma_unmap_single(ksp->dev,
-					 ksp->rx_buffers[buff_n].dma_ptr,
-					 ksp->rx_buffers[buff_n].length,
-					 DMA_FROM_DEVICE);
-
-			/* Relinquish the SKB to the network layer */
-			skb_put(skb, pktlen);
-			skb->protocol = eth_type_trans(skb, ndev);
-			napi_gro_receive(&ksp->napi, skb);
-
-			/* Record stats */
-			ndev->stats.rx_packets++;
-			ndev->stats.rx_bytes += pktlen;
-			goto rx_finished;
-
-rx_failure:
-			/* This ring entry is an error, but we can
-			 * re-use the skb
-			 */
-			/* Give the ring entry back to the hardware */
-			ksp->rx_ring[buff_n].status = cpu_to_le32(RDES_OWN);
-rx_finished:
-			received++;
-			buff_n = (buff_n + 1) & MAX_RX_DESC_MASK;
-	}
-
-	/* And note which RX descriptor we last did */
-	ksp->next_rx_desc_read = buff_n;
-
-	/* And refill the buffers */
-	ks8695_refill_rxbuffers(ksp);
-
-	/* Kick the RX DMA engine, in case it became suspended */
-	ks8695_writereg(ksp, KS8695_DRSC, 0);
-
-	return received;
-}
-
-
-/**
- *	ks8695_poll - Receive packet by NAPI poll method
- *	@ksp: Private data for the KS8695 Ethernet
- *	@budget: The remaining number packets for network subsystem
- *
- *     Invoked by the network core when it requests for new
- *     packets from the driver
- */
-static int ks8695_poll(struct napi_struct *napi, int budget)
-{
-	struct ks8695_priv *ksp = container_of(napi, struct ks8695_priv, napi);
-	unsigned long isr = readl(KS8695_IRQ_VA + KS8695_INTEN);
-	unsigned long mask_bit = 1 << ks8695_get_rx_enable_bit(ksp);
-	int work_done;
-
-	work_done = ks8695_rx(ksp, budget);
-
-	if (work_done < budget && napi_complete_done(napi, work_done)) {
-		unsigned long flags;
-
-		spin_lock_irqsave(&ksp->rx_lock, flags);
-		/* enable rx interrupt */
-		writel(isr | mask_bit, KS8695_IRQ_VA + KS8695_INTEN);
-		spin_unlock_irqrestore(&ksp->rx_lock, flags);
-	}
-	return work_done;
-}
-
-/**
- *	ks8695_link_irq - Link change IRQ handler
- *	@irq: The IRQ which went off (ignored)
- *	@dev_id: The net_device for the interrupt
- *
- *	The WAN interface can generate an IRQ when the link changes,
- *	report this to the net layer and the user.
- */
-static irqreturn_t
-ks8695_link_irq(int irq, void *dev_id)
-{
-	struct net_device *ndev = (struct net_device *)dev_id;
-	struct ks8695_priv *ksp = netdev_priv(ndev);
-	u32 ctrl;
-
-	ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
-	if (ctrl & WMC_WLS) {
-		netif_carrier_on(ndev);
-		if (netif_msg_link(ksp))
-			dev_info(ksp->dev,
-				 "%s: Link is now up (10%sMbps/%s-duplex)\n",
-				 ndev->name,
-				 (ctrl & WMC_WSS) ? "0" : "",
-				 (ctrl & WMC_WDS) ? "Full" : "Half");
-	} else {
-		netif_carrier_off(ndev);
-		if (netif_msg_link(ksp))
-			dev_info(ksp->dev, "%s: Link is now down.\n",
-				 ndev->name);
-	}
-
-	return IRQ_HANDLED;
-}
-
-
-/* KS8695 Device functions */
-
-/**
- *	ks8695_reset - Reset a KS8695 ethernet interface
- *	@ksp: The interface to reset
- *
- *	Perform an engine reset of the interface and re-program it
- *	with sensible defaults.
- */
-static void
-ks8695_reset(struct ks8695_priv *ksp)
-{
-	int reset_timeout = watchdog;
-	/* Issue the reset via the TX DMA control register */
-	ks8695_writereg(ksp, KS8695_DTXC, DTXC_TRST);
-	while (reset_timeout--) {
-		if (!(ks8695_readreg(ksp, KS8695_DTXC) & DTXC_TRST))
-			break;
-		msleep(1);
-	}
-
-	if (reset_timeout < 0) {
-		dev_crit(ksp->dev,
-			 "Timeout waiting for DMA engines to reset\n");
-		/* And blithely carry on */
-	}
-
-	/* Definitely wait long enough before attempting to program
-	 * the engines
-	 */
-	msleep(10);
-
-	/* RX: unicast and broadcast */
-	ks8695_writereg(ksp, KS8695_DRXC, DRXC_RU | DRXC_RB);
-	/* TX: pad and add CRC */
-	ks8695_writereg(ksp, KS8695_DTXC, DTXC_TEP | DTXC_TAC);
-}
-
-/**
- *	ks8695_shutdown - Shut down a KS8695 ethernet interface
- *	@ksp: The interface to shut down
- *
- *	This disables packet RX/TX, cleans up IRQs, drains the rings,
- *	and basically places the interface into a clean shutdown
- *	state.
- */
-static void
-ks8695_shutdown(struct ks8695_priv *ksp)
-{
-	u32 ctrl;
-	int buff_n;
-
-	/* Disable packet transmission */
-	ctrl = ks8695_readreg(ksp, KS8695_DTXC);
-	ks8695_writereg(ksp, KS8695_DTXC, ctrl & ~DTXC_TE);
-
-	/* Disable packet reception */
-	ctrl = ks8695_readreg(ksp, KS8695_DRXC);
-	ks8695_writereg(ksp, KS8695_DRXC, ctrl & ~DRXC_RE);
-
-	/* Release the IRQs */
-	free_irq(ksp->rx_irq, ksp->ndev);
-	free_irq(ksp->tx_irq, ksp->ndev);
-	if (ksp->link_irq != -1)
-		free_irq(ksp->link_irq, ksp->ndev);
-
-	/* Throw away any pending TX packets */
-	for (buff_n = 0; buff_n < MAX_TX_DESC; ++buff_n) {
-		if (ksp->tx_buffers[buff_n].skb) {
-			/* Remove this SKB from the TX ring */
-			ksp->tx_ring[buff_n].owner = 0;
-			ksp->tx_ring[buff_n].status = 0;
-			ksp->tx_ring[buff_n].data_ptr = 0;
-
-			/* Unmap and bin this SKB */
-			dma_unmap_single(ksp->dev,
-					 ksp->tx_buffers[buff_n].dma_ptr,
-					 ksp->tx_buffers[buff_n].length,
-					 DMA_TO_DEVICE);
-			dev_kfree_skb_irq(ksp->tx_buffers[buff_n].skb);
-			ksp->tx_buffers[buff_n].skb = NULL;
-		}
-	}
-
-	/* Purge the RX buffers */
-	for (buff_n = 0; buff_n < MAX_RX_DESC; ++buff_n) {
-		if (ksp->rx_buffers[buff_n].skb) {
-			/* Remove the SKB from the RX ring */
-			ksp->rx_ring[buff_n].status = 0;
-			ksp->rx_ring[buff_n].data_ptr = 0;
-
-			/* Unmap and bin the SKB */
-			dma_unmap_single(ksp->dev,
-					 ksp->rx_buffers[buff_n].dma_ptr,
-					 ksp->rx_buffers[buff_n].length,
-					 DMA_FROM_DEVICE);
-			dev_kfree_skb_irq(ksp->rx_buffers[buff_n].skb);
-			ksp->rx_buffers[buff_n].skb = NULL;
-		}
-	}
-}
-
-
-/**
- *	ks8695_setup_irq - IRQ setup helper function
- *	@irq: The IRQ number to claim
- *	@irq_name: The name to give the IRQ claimant
- *	@handler: The function to call to handle the IRQ
- *	@ndev: The net_device to pass in as the dev_id argument to the handler
- *
- *	Return 0 on success.
- */
-static int
-ks8695_setup_irq(int irq, const char *irq_name,
-		 irq_handler_t handler, struct net_device *ndev)
-{
-	int ret;
-
-	ret = request_irq(irq, handler, IRQF_SHARED, irq_name, ndev);
-
-	if (ret) {
-		dev_err(&ndev->dev, "failure to request IRQ %d\n", irq);
-		return ret;
-	}
-
-	return 0;
-}
-
-/**
- *	ks8695_init_net - Initialise a KS8695 ethernet interface
- *	@ksp: The interface to initialise
- *
- *	This routine fills the RX ring, initialises the DMA engines,
- *	allocates the IRQs and then starts the packet TX and RX
- *	engines.
- */
-static int
-ks8695_init_net(struct ks8695_priv *ksp)
-{
-	int ret;
-	u32 ctrl;
-
-	ks8695_refill_rxbuffers(ksp);
-
-	/* Initialise the DMA engines */
-	ks8695_writereg(ksp, KS8695_RDLB, (u32) ksp->rx_ring_dma);
-	ks8695_writereg(ksp, KS8695_TDLB, (u32) ksp->tx_ring_dma);
-
-	/* Request the IRQs */
-	ret = ks8695_setup_irq(ksp->rx_irq, ksp->rx_irq_name,
-			       ks8695_rx_irq, ksp->ndev);
-	if (ret)
-		return ret;
-	ret = ks8695_setup_irq(ksp->tx_irq, ksp->tx_irq_name,
-			       ks8695_tx_irq, ksp->ndev);
-	if (ret)
-		return ret;
-	if (ksp->link_irq != -1) {
-		ret = ks8695_setup_irq(ksp->link_irq, ksp->link_irq_name,
-				       ks8695_link_irq, ksp->ndev);
-		if (ret)
-			return ret;
-	}
-
-	/* Set up the ring indices */
-	ksp->next_rx_desc_read = 0;
-	ksp->tx_ring_next_slot = 0;
-	ksp->tx_ring_used = 0;
-
-	/* Bring up transmission */
-	ctrl = ks8695_readreg(ksp, KS8695_DTXC);
-	/* Enable packet transmission */
-	ks8695_writereg(ksp, KS8695_DTXC, ctrl | DTXC_TE);
-
-	/* Bring up the reception */
-	ctrl = ks8695_readreg(ksp, KS8695_DRXC);
-	/* Enable packet reception */
-	ks8695_writereg(ksp, KS8695_DRXC, ctrl | DRXC_RE);
-	/* And start the DMA engine */
-	ks8695_writereg(ksp, KS8695_DRSC, 0);
-
-	/* All done */
-	return 0;
-}
-
-/**
- *	ks8695_release_device - HW resource release for KS8695 e-net
- *	@ksp: The device to be freed
- *
- *	This unallocates io memory regions, dma-coherent regions etc
- *	which were allocated in ks8695_probe.
- */
-static void
-ks8695_release_device(struct ks8695_priv *ksp)
-{
-	/* Unmap the registers */
-	iounmap(ksp->io_regs);
-	if (ksp->phyiface_regs)
-		iounmap(ksp->phyiface_regs);
-
-	/* And release the request */
-	release_resource(ksp->regs_req);
-	kfree(ksp->regs_req);
-	if (ksp->phyiface_req) {
-		release_resource(ksp->phyiface_req);
-		kfree(ksp->phyiface_req);
-	}
-
-	/* Free the ring buffers */
-	dma_free_coherent(ksp->dev, RING_DMA_SIZE,
-			  ksp->ring_base, ksp->ring_base_dma);
-}
-
-/* Ethtool support */
-
-/**
- *	ks8695_get_msglevel - Get the messages enabled for emission
- *	@ndev: The network device to read from
- */
-static u32
-ks8695_get_msglevel(struct net_device *ndev)
-{
-	struct ks8695_priv *ksp = netdev_priv(ndev);
-
-	return ksp->msg_enable;
-}
-
-/**
- *	ks8695_set_msglevel - Set the messages enabled for emission
- *	@ndev: The network device to configure
- *	@value: The messages to set for emission
- */
-static void
-ks8695_set_msglevel(struct net_device *ndev, u32 value)
-{
-	struct ks8695_priv *ksp = netdev_priv(ndev);
-
-	ksp->msg_enable = value;
-}
-
-/**
- *	ks8695_wan_get_link_ksettings - Get device-specific settings.
- *	@ndev: The network device to read settings from
- *	@cmd: The ethtool structure to read into
- */
-static int
-ks8695_wan_get_link_ksettings(struct net_device *ndev,
-			      struct ethtool_link_ksettings *cmd)
-{
-	struct ks8695_priv *ksp = netdev_priv(ndev);
-	u32 ctrl;
-	u32 supported, advertising;
-
-	/* All ports on the KS8695 support these... */
-	supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
-			  SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
-			  SUPPORTED_TP | SUPPORTED_MII);
-
-	advertising = ADVERTISED_TP | ADVERTISED_MII;
-	cmd->base.port = PORT_MII;
-	supported |= (SUPPORTED_Autoneg | SUPPORTED_Pause);
-	cmd->base.phy_address = 0;
-
-	ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
-	if ((ctrl & WMC_WAND) == 0) {
-		/* auto-negotiation is enabled */
-		advertising |= ADVERTISED_Autoneg;
-		if (ctrl & WMC_WANA100F)
-			advertising |= ADVERTISED_100baseT_Full;
-		if (ctrl & WMC_WANA100H)
-			advertising |= ADVERTISED_100baseT_Half;
-		if (ctrl & WMC_WANA10F)
-			advertising |= ADVERTISED_10baseT_Full;
-		if (ctrl & WMC_WANA10H)
-			advertising |= ADVERTISED_10baseT_Half;
-		if (ctrl & WMC_WANAP)
-			advertising |= ADVERTISED_Pause;
-		cmd->base.autoneg = AUTONEG_ENABLE;
-
-		cmd->base.speed = (ctrl & WMC_WSS) ? SPEED_100 : SPEED_10;
-		cmd->base.duplex = (ctrl & WMC_WDS) ?
-			DUPLEX_FULL : DUPLEX_HALF;
-	} else {
-		/* auto-negotiation is disabled */
-		cmd->base.autoneg = AUTONEG_DISABLE;
-
-		cmd->base.speed = (ctrl & WMC_WANF100) ?
-					    SPEED_100 : SPEED_10;
-		cmd->base.duplex = (ctrl & WMC_WANFF) ?
-			DUPLEX_FULL : DUPLEX_HALF;
-	}
-
-	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
-						supported);
-	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
-						advertising);
-
-	return 0;
-}
-
-/**
- *	ks8695_wan_set_link_ksettings - Set device-specific settings.
- *	@ndev: The network device to configure
- *	@cmd: The settings to configure
- */
-static int
-ks8695_wan_set_link_ksettings(struct net_device *ndev,
-			      const struct ethtool_link_ksettings *cmd)
-{
-	struct ks8695_priv *ksp = netdev_priv(ndev);
-	u32 ctrl;
-	u32 advertising;
-
-	ethtool_convert_link_mode_to_legacy_u32(&advertising,
-						cmd->link_modes.advertising);
-
-	if ((cmd->base.speed != SPEED_10) && (cmd->base.speed != SPEED_100))
-		return -EINVAL;
-	if ((cmd->base.duplex != DUPLEX_HALF) &&
-	    (cmd->base.duplex != DUPLEX_FULL))
-		return -EINVAL;
-	if (cmd->base.port != PORT_MII)
-		return -EINVAL;
-	if ((cmd->base.autoneg != AUTONEG_DISABLE) &&
-	    (cmd->base.autoneg != AUTONEG_ENABLE))
-		return -EINVAL;
-
-	if (cmd->base.autoneg == AUTONEG_ENABLE) {
-		if ((advertising & (ADVERTISED_10baseT_Half |
-				ADVERTISED_10baseT_Full |
-				ADVERTISED_100baseT_Half |
-				ADVERTISED_100baseT_Full)) == 0)
-			return -EINVAL;
-
-		ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
-
-		ctrl &= ~(WMC_WAND | WMC_WANA100F | WMC_WANA100H |
-			  WMC_WANA10F | WMC_WANA10H);
-		if (advertising & ADVERTISED_100baseT_Full)
-			ctrl |= WMC_WANA100F;
-		if (advertising & ADVERTISED_100baseT_Half)
-			ctrl |= WMC_WANA100H;
-		if (advertising & ADVERTISED_10baseT_Full)
-			ctrl |= WMC_WANA10F;
-		if (advertising & ADVERTISED_10baseT_Half)
-			ctrl |= WMC_WANA10H;
-
-		/* force a re-negotiation */
-		ctrl |= WMC_WANR;
-		writel(ctrl, ksp->phyiface_regs + KS8695_WMC);
-	} else {
-		ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
-
-		/* disable auto-negotiation */
-		ctrl |= WMC_WAND;
-		ctrl &= ~(WMC_WANF100 | WMC_WANFF);
-
-		if (cmd->base.speed == SPEED_100)
-			ctrl |= WMC_WANF100;
-		if (cmd->base.duplex == DUPLEX_FULL)
-			ctrl |= WMC_WANFF;
-
-		writel(ctrl, ksp->phyiface_regs + KS8695_WMC);
-	}
-
-	return 0;
-}
-
-/**
- *	ks8695_wan_nwayreset - Restart the autonegotiation on the port.
- *	@ndev: The network device to restart autoneotiation on
- */
-static int
-ks8695_wan_nwayreset(struct net_device *ndev)
-{
-	struct ks8695_priv *ksp = netdev_priv(ndev);
-	u32 ctrl;
-
-	ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
-
-	if ((ctrl & WMC_WAND) == 0)
-		writel(ctrl | WMC_WANR,
-		       ksp->phyiface_regs + KS8695_WMC);
-	else
-		/* auto-negotiation not enabled */
-		return -EINVAL;
-
-	return 0;
-}
-
-/**
- *	ks8695_wan_get_pause - Retrieve network pause/flow-control advertising
- *	@ndev: The device to retrieve settings from
- *	@param: The structure to fill out with the information
- */
-static void
-ks8695_wan_get_pause(struct net_device *ndev, struct ethtool_pauseparam *param)
-{
-	struct ks8695_priv *ksp = netdev_priv(ndev);
-	u32 ctrl;
-
-	ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
-
-	/* advertise Pause */
-	param->autoneg = (ctrl & WMC_WANAP);
-
-	/* current Rx Flow-control */
-	ctrl = ks8695_readreg(ksp, KS8695_DRXC);
-	param->rx_pause = (ctrl & DRXC_RFCE);
-
-	/* current Tx Flow-control */
-	ctrl = ks8695_readreg(ksp, KS8695_DTXC);
-	param->tx_pause = (ctrl & DTXC_TFCE);
-}
-
-/**
- *	ks8695_get_drvinfo - Retrieve driver information
- *	@ndev: The network device to retrieve info about
- *	@info: The info structure to fill out.
- */
-static void
-ks8695_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo *info)
-{
-	strlcpy(info->driver, MODULENAME, sizeof(info->driver));
-	strlcpy(info->version, MODULEVERSION, sizeof(info->version));
-	strlcpy(info->bus_info, dev_name(ndev->dev.parent),
-		sizeof(info->bus_info));
-}
-
-static const struct ethtool_ops ks8695_ethtool_ops = {
-	.get_msglevel	= ks8695_get_msglevel,
-	.set_msglevel	= ks8695_set_msglevel,
-	.get_drvinfo	= ks8695_get_drvinfo,
-};
-
-static const struct ethtool_ops ks8695_wan_ethtool_ops = {
-	.get_msglevel	= ks8695_get_msglevel,
-	.set_msglevel	= ks8695_set_msglevel,
-	.nway_reset	= ks8695_wan_nwayreset,
-	.get_link	= ethtool_op_get_link,
-	.get_pauseparam = ks8695_wan_get_pause,
-	.get_drvinfo	= ks8695_get_drvinfo,
-	.get_link_ksettings = ks8695_wan_get_link_ksettings,
-	.set_link_ksettings = ks8695_wan_set_link_ksettings,
-};
-
-/* Network device interface functions */
-
-/**
- *	ks8695_set_mac - Update MAC in net dev and HW
- *	@ndev: The network device to update
- *	@addr: The new MAC address to set
- */
-static int
-ks8695_set_mac(struct net_device *ndev, void *addr)
-{
-	struct ks8695_priv *ksp = netdev_priv(ndev);
-	struct sockaddr *address = addr;
-
-	if (!is_valid_ether_addr(address->sa_data))
-		return -EADDRNOTAVAIL;
-
-	memcpy(ndev->dev_addr, address->sa_data, ndev->addr_len);
-
-	ks8695_update_mac(ksp);
-
-	dev_dbg(ksp->dev, "%s: Updated MAC address to %pM\n",
-		ndev->name, ndev->dev_addr);
-
-	return 0;
-}
-
-/**
- *	ks8695_set_multicast - Set up the multicast behaviour of the interface
- *	@ndev: The net_device to configure
- *
- *	This routine, called by the net layer, configures promiscuity
- *	and multicast reception behaviour for the interface.
- */
-static void
-ks8695_set_multicast(struct net_device *ndev)
-{
-	struct ks8695_priv *ksp = netdev_priv(ndev);
-	u32 ctrl;
-
-	ctrl = ks8695_readreg(ksp, KS8695_DRXC);
-
-	if (ndev->flags & IFF_PROMISC) {
-		/* enable promiscuous mode */
-		ctrl |= DRXC_RA;
-	} else if (ndev->flags & ~IFF_PROMISC) {
-		/* disable promiscuous mode */
-		ctrl &= ~DRXC_RA;
-	}
-
-	if (ndev->flags & IFF_ALLMULTI) {
-		/* enable all multicast mode */
-		ctrl |= DRXC_RM;
-	} else if (netdev_mc_count(ndev) > KS8695_NR_ADDRESSES) {
-		/* more specific multicast addresses than can be
-		 * handled in hardware
-		 */
-		ctrl |= DRXC_RM;
-	} else {
-		/* enable specific multicasts */
-		ctrl &= ~DRXC_RM;
-		ks8695_init_partial_multicast(ksp, ndev);
-	}
-
-	ks8695_writereg(ksp, KS8695_DRXC, ctrl);
-}
-
-/**
- *	ks8695_timeout - Handle a network tx/rx timeout.
- *	@ndev: The net_device which timed out.
- *
- *	A network transaction timed out, reset the device.
- */
-static void
-ks8695_timeout(struct net_device *ndev)
-{
-	struct ks8695_priv *ksp = netdev_priv(ndev);
-
-	netif_stop_queue(ndev);
-	ks8695_shutdown(ksp);
-
-	ks8695_reset(ksp);
-
-	ks8695_update_mac(ksp);
-
-	/* We ignore the return from this since it managed to init
-	 * before it probably will be okay to init again.
-	 */
-	ks8695_init_net(ksp);
-
-	/* Reconfigure promiscuity etc */
-	ks8695_set_multicast(ndev);
-
-	/* And start the TX queue once more */
-	netif_start_queue(ndev);
-}
-
-/**
- *	ks8695_start_xmit - Start a packet transmission
- *	@skb: The packet to transmit
- *	@ndev: The network device to send the packet on
- *
- *	This routine, called by the net layer, takes ownership of the
- *	sk_buff and adds it to the TX ring. It then kicks the TX DMA
- *	engine to ensure transmission begins.
- */
-static netdev_tx_t
-ks8695_start_xmit(struct sk_buff *skb, struct net_device *ndev)
-{
-	struct ks8695_priv *ksp = netdev_priv(ndev);
-	int buff_n;
-	dma_addr_t dmap;
-
-	spin_lock_irq(&ksp->txq_lock);
-
-	if (ksp->tx_ring_used == MAX_TX_DESC) {
-		/* Somehow we got entered when we have no room */
-		spin_unlock_irq(&ksp->txq_lock);
-		return NETDEV_TX_BUSY;
-	}
-
-	buff_n = ksp->tx_ring_next_slot;
-
-	BUG_ON(ksp->tx_buffers[buff_n].skb);
-
-	dmap = dma_map_single(ksp->dev, skb->data, skb->len, DMA_TO_DEVICE);
-	if (unlikely(dma_mapping_error(ksp->dev, dmap))) {
-		/* Failed to DMA map this SKB, give it back for now */
-		spin_unlock_irq(&ksp->txq_lock);
-		dev_dbg(ksp->dev, "%s: Could not map DMA memory for "\
-			"transmission, trying later\n", ndev->name);
-		return NETDEV_TX_BUSY;
-	}
-
-	ksp->tx_buffers[buff_n].dma_ptr = dmap;
-	/* Mapped okay, store the buffer pointer and length for later */
-	ksp->tx_buffers[buff_n].skb = skb;
-	ksp->tx_buffers[buff_n].length = skb->len;
-
-	/* Fill out the TX descriptor */
-	ksp->tx_ring[buff_n].data_ptr =
-		cpu_to_le32(ksp->tx_buffers[buff_n].dma_ptr);
-	ksp->tx_ring[buff_n].status =
-		cpu_to_le32(TDES_IC | TDES_FS | TDES_LS |
-			    (skb->len & TDES_TBS));
-
-	wmb();
-
-	/* Hand it over to the hardware */
-	ksp->tx_ring[buff_n].owner = cpu_to_le32(TDES_OWN);
-
-	if (++ksp->tx_ring_used == MAX_TX_DESC)
-		netif_stop_queue(ndev);
-
-	/* Kick the TX DMA in case it decided to go IDLE */
-	ks8695_writereg(ksp, KS8695_DTSC, 0);
-
-	/* And update the next ring slot */
-	ksp->tx_ring_next_slot = (buff_n + 1) & MAX_TX_DESC_MASK;
-
-	spin_unlock_irq(&ksp->txq_lock);
-	return NETDEV_TX_OK;
-}
-
-/**
- *	ks8695_stop - Stop (shutdown) a KS8695 ethernet interface
- *	@ndev: The net_device to stop
- *
- *	This disables the TX queue and cleans up a KS8695 ethernet
- *	device.
- */
-static int
-ks8695_stop(struct net_device *ndev)
-{
-	struct ks8695_priv *ksp = netdev_priv(ndev);
-
-	netif_stop_queue(ndev);
-	napi_disable(&ksp->napi);
-
-	ks8695_shutdown(ksp);
-
-	return 0;
-}
-
-/**
- *	ks8695_open - Open (bring up) a KS8695 ethernet interface
- *	@ndev: The net_device to open
- *
- *	This resets, configures the MAC, initialises the RX ring and
- *	DMA engines and starts the TX queue for a KS8695 ethernet
- *	device.
- */
-static int
-ks8695_open(struct net_device *ndev)
-{
-	struct ks8695_priv *ksp = netdev_priv(ndev);
-	int ret;
-
-	ks8695_reset(ksp);
-
-	ks8695_update_mac(ksp);
-
-	ret = ks8695_init_net(ksp);
-	if (ret) {
-		ks8695_shutdown(ksp);
-		return ret;
-	}
-
-	napi_enable(&ksp->napi);
-	netif_start_queue(ndev);
-
-	return 0;
-}
-
-/* Platform device driver */
-
-/**
- *	ks8695_init_switch - Init LAN switch to known good defaults.
- *	@ksp: The device to initialise
- *
- *	This initialises the LAN switch in the KS8695 to a known-good
- *	set of defaults.
- */
-static void
-ks8695_init_switch(struct ks8695_priv *ksp)
-{
-	u32 ctrl;
-
-	/* Default value for SEC0 according to datasheet */
-	ctrl = 0x40819e00;
-
-	/* LED0 = Speed	 LED1 = Link/Activity */
-	ctrl &= ~(SEC0_LLED1S | SEC0_LLED0S);
-	ctrl |= (LLED0S_LINK | LLED1S_LINK_ACTIVITY);
-
-	/* Enable Switch */
-	ctrl |= SEC0_ENABLE;
-
-	writel(ctrl, ksp->phyiface_regs + KS8695_SEC0);
-
-	/* Defaults for SEC1 */
-	writel(0x9400100, ksp->phyiface_regs + KS8695_SEC1);
-}
-
-/**
- *	ks8695_init_wan_phy - Initialise the WAN PHY to sensible defaults
- *	@ksp: The device to initialise
- *
- *	This initialises a KS8695's WAN phy to sensible values for
- *	autonegotiation etc.
- */
-static void
-ks8695_init_wan_phy(struct ks8695_priv *ksp)
-{
-	u32 ctrl;
-
-	/* Support auto-negotiation */
-	ctrl = (WMC_WANAP | WMC_WANA100F | WMC_WANA100H |
-		WMC_WANA10F | WMC_WANA10H);
-
-	/* LED0 = Activity , LED1 = Link */
-	ctrl |= (WLED0S_ACTIVITY | WLED1S_LINK);
-
-	/* Restart Auto-negotiation */
-	ctrl |= WMC_WANR;
-
-	writel(ctrl, ksp->phyiface_regs + KS8695_WMC);
-
-	writel(0, ksp->phyiface_regs + KS8695_WPPM);
-	writel(0, ksp->phyiface_regs + KS8695_PPS);
-}
-
-static const struct net_device_ops ks8695_netdev_ops = {
-	.ndo_open		= ks8695_open,
-	.ndo_stop		= ks8695_stop,
-	.ndo_start_xmit		= ks8695_start_xmit,
-	.ndo_tx_timeout		= ks8695_timeout,
-	.ndo_set_mac_address	= ks8695_set_mac,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_rx_mode	= ks8695_set_multicast,
-};
-
-/**
- *	ks8695_probe - Probe and initialise a KS8695 ethernet interface
- *	@pdev: The platform device to probe
- *
- *	Initialise a KS8695 ethernet device from platform data.
- *
- *	This driver requires at least one IORESOURCE_MEM for the
- *	registers and two IORESOURCE_IRQ for the RX and TX IRQs
- *	respectively. It can optionally take an additional
- *	IORESOURCE_MEM for the switch or phy in the case of the lan or
- *	wan ports, and an IORESOURCE_IRQ for the link IRQ for the wan
- *	port.
- */
-static int
-ks8695_probe(struct platform_device *pdev)
-{
-	struct ks8695_priv *ksp;
-	struct net_device *ndev;
-	struct resource *regs_res, *phyiface_res;
-	struct resource *rxirq_res, *txirq_res, *linkirq_res;
-	int ret = 0;
-	int buff_n;
-	bool inv_mac_addr = false;
-	u32 machigh, maclow;
-
-	/* Initialise a net_device */
-	ndev = alloc_etherdev(sizeof(struct ks8695_priv));
-	if (!ndev)
-		return -ENOMEM;
-
-	SET_NETDEV_DEV(ndev, &pdev->dev);
-
-	dev_dbg(&pdev->dev, "ks8695_probe() called\n");
-
-	/* Configure our private structure a little */
-	ksp = netdev_priv(ndev);
-
-	ksp->dev = &pdev->dev;
-	ksp->ndev = ndev;
-	ksp->msg_enable = NETIF_MSG_LINK;
-
-	/* Retrieve resources */
-	regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	phyiface_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-
-	rxirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	txirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
-	linkirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 2);
-
-	if (!(regs_res && rxirq_res && txirq_res)) {
-		dev_err(ksp->dev, "insufficient resources\n");
-		ret = -ENOENT;
-		goto failure;
-	}
-
-	ksp->regs_req = request_mem_region(regs_res->start,
-					   resource_size(regs_res),
-					   pdev->name);
-
-	if (!ksp->regs_req) {
-		dev_err(ksp->dev, "cannot claim register space\n");
-		ret = -EIO;
-		goto failure;
-	}
-
-	ksp->io_regs = ioremap(regs_res->start, resource_size(regs_res));
-
-	if (!ksp->io_regs) {
-		dev_err(ksp->dev, "failed to ioremap registers\n");
-		ret = -EINVAL;
-		goto failure;
-	}
-
-	if (phyiface_res) {
-		ksp->phyiface_req =
-			request_mem_region(phyiface_res->start,
-					   resource_size(phyiface_res),
-					   phyiface_res->name);
-
-		if (!ksp->phyiface_req) {
-			dev_err(ksp->dev,
-				"cannot claim switch register space\n");
-			ret = -EIO;
-			goto failure;
-		}
-
-		ksp->phyiface_regs = ioremap(phyiface_res->start,
-					     resource_size(phyiface_res));
-
-		if (!ksp->phyiface_regs) {
-			dev_err(ksp->dev,
-				"failed to ioremap switch registers\n");
-			ret = -EINVAL;
-			goto failure;
-		}
-	}
-
-	ksp->rx_irq = rxirq_res->start;
-	ksp->rx_irq_name = rxirq_res->name ? rxirq_res->name : "Ethernet RX";
-	ksp->tx_irq = txirq_res->start;
-	ksp->tx_irq_name = txirq_res->name ? txirq_res->name : "Ethernet TX";
-	ksp->link_irq = (linkirq_res ? linkirq_res->start : -1);
-	ksp->link_irq_name = (linkirq_res && linkirq_res->name) ?
-		linkirq_res->name : "Ethernet Link";
-
-	/* driver system setup */
-	ndev->netdev_ops = &ks8695_netdev_ops;
-	ndev->watchdog_timeo	 = msecs_to_jiffies(watchdog);
-
-	netif_napi_add(ndev, &ksp->napi, ks8695_poll, NAPI_WEIGHT);
-
-	/* Retrieve the default MAC addr from the chip. */
-	/* The bootloader should have left it in there for us. */
-
-	machigh = ks8695_readreg(ksp, KS8695_MAH);
-	maclow = ks8695_readreg(ksp, KS8695_MAL);
-
-	ndev->dev_addr[0] = (machigh >> 8) & 0xFF;
-	ndev->dev_addr[1] = machigh & 0xFF;
-	ndev->dev_addr[2] = (maclow >> 24) & 0xFF;
-	ndev->dev_addr[3] = (maclow >> 16) & 0xFF;
-	ndev->dev_addr[4] = (maclow >> 8) & 0xFF;
-	ndev->dev_addr[5] = maclow & 0xFF;
-
-	if (!is_valid_ether_addr(ndev->dev_addr))
-		inv_mac_addr = true;
-
-	/* In order to be efficient memory-wise, we allocate both
-	 * rings in one go.
-	 */
-	ksp->ring_base = dma_alloc_coherent(&pdev->dev, RING_DMA_SIZE,
-					    &ksp->ring_base_dma, GFP_KERNEL);
-	if (!ksp->ring_base) {
-		ret = -ENOMEM;
-		goto failure;
-	}
-
-	/* Specify the TX DMA ring buffer */
-	ksp->tx_ring = ksp->ring_base;
-	ksp->tx_ring_dma = ksp->ring_base_dma;
-
-	/* And initialise the queue's lock */
-	spin_lock_init(&ksp->txq_lock);
-	spin_lock_init(&ksp->rx_lock);
-
-	/* Specify the RX DMA ring buffer */
-	ksp->rx_ring = ksp->ring_base + TX_RING_DMA_SIZE;
-	ksp->rx_ring_dma = ksp->ring_base_dma + TX_RING_DMA_SIZE;
-
-	/* Zero the descriptor rings */
-	memset(ksp->tx_ring, 0, TX_RING_DMA_SIZE);
-	memset(ksp->rx_ring, 0, RX_RING_DMA_SIZE);
-
-	/* Build the rings */
-	for (buff_n = 0; buff_n < MAX_TX_DESC; ++buff_n) {
-		ksp->tx_ring[buff_n].next_desc =
-			cpu_to_le32(ksp->tx_ring_dma +
-				    (sizeof(struct tx_ring_desc) *
-				     ((buff_n + 1) & MAX_TX_DESC_MASK)));
-	}
-
-	for (buff_n = 0; buff_n < MAX_RX_DESC; ++buff_n) {
-		ksp->rx_ring[buff_n].next_desc =
-			cpu_to_le32(ksp->rx_ring_dma +
-				    (sizeof(struct rx_ring_desc) *
-				     ((buff_n + 1) & MAX_RX_DESC_MASK)));
-	}
-
-	/* Initialise the port (physically) */
-	if (ksp->phyiface_regs && ksp->link_irq == -1) {
-		ks8695_init_switch(ksp);
-		ksp->dtype = KS8695_DTYPE_LAN;
-		ndev->ethtool_ops = &ks8695_ethtool_ops;
-	} else if (ksp->phyiface_regs && ksp->link_irq != -1) {
-		ks8695_init_wan_phy(ksp);
-		ksp->dtype = KS8695_DTYPE_WAN;
-		ndev->ethtool_ops = &ks8695_wan_ethtool_ops;
-	} else {
-		/* No initialisation since HPNA does not have a PHY */
-		ksp->dtype = KS8695_DTYPE_HPNA;
-		ndev->ethtool_ops = &ks8695_ethtool_ops;
-	}
-
-	/* And bring up the net_device with the net core */
-	platform_set_drvdata(pdev, ndev);
-	ret = register_netdev(ndev);
-
-	if (ret == 0) {
-		if (inv_mac_addr)
-			dev_warn(ksp->dev, "%s: Invalid ethernet MAC address. Please set using ip\n",
-				 ndev->name);
-		dev_info(ksp->dev, "ks8695 ethernet (%s) MAC: %pM\n",
-			 ks8695_port_type(ksp), ndev->dev_addr);
-	} else {
-		/* Report the failure to register the net_device */
-		dev_err(ksp->dev, "ks8695net: failed to register netdev.\n");
-		goto failure;
-	}
-
-	/* All is well */
-	return 0;
-
-	/* Error exit path */
-failure:
-	ks8695_release_device(ksp);
-	free_netdev(ndev);
-
-	return ret;
-}
-
-/**
- *	ks8695_drv_suspend - Suspend a KS8695 ethernet platform device.
- *	@pdev: The device to suspend
- *	@state: The suspend state
- *
- *	This routine detaches and shuts down a KS8695 ethernet device.
- */
-static int
-ks8695_drv_suspend(struct platform_device *pdev, pm_message_t state)
-{
-	struct net_device *ndev = platform_get_drvdata(pdev);
-	struct ks8695_priv *ksp = netdev_priv(ndev);
-
-	ksp->in_suspend = 1;
-
-	if (netif_running(ndev)) {
-		netif_device_detach(ndev);
-		ks8695_shutdown(ksp);
-	}
-
-	return 0;
-}
-
-/**
- *	ks8695_drv_resume - Resume a KS8695 ethernet platform device.
- *	@pdev: The device to resume
- *
- *	This routine re-initialises and re-attaches a KS8695 ethernet
- *	device.
- */
-static int
-ks8695_drv_resume(struct platform_device *pdev)
-{
-	struct net_device *ndev = platform_get_drvdata(pdev);
-	struct ks8695_priv *ksp = netdev_priv(ndev);
-
-	if (netif_running(ndev)) {
-		ks8695_reset(ksp);
-		ks8695_init_net(ksp);
-		ks8695_set_multicast(ndev);
-		netif_device_attach(ndev);
-	}
-
-	ksp->in_suspend = 0;
-
-	return 0;
-}
-
-/**
- *	ks8695_drv_remove - Remove a KS8695 net device on driver unload.
- *	@pdev: The platform device to remove
- *
- *	This unregisters and releases a KS8695 ethernet device.
- */
-static int
-ks8695_drv_remove(struct platform_device *pdev)
-{
-	struct net_device *ndev = platform_get_drvdata(pdev);
-	struct ks8695_priv *ksp = netdev_priv(ndev);
-
-	netif_napi_del(&ksp->napi);
-
-	unregister_netdev(ndev);
-	ks8695_release_device(ksp);
-	free_netdev(ndev);
-
-	dev_dbg(&pdev->dev, "released and freed device\n");
-	return 0;
-}
-
-static struct platform_driver ks8695_driver = {
-	.driver = {
-		.name	= MODULENAME,
-	},
-	.probe		= ks8695_probe,
-	.remove		= ks8695_drv_remove,
-	.suspend	= ks8695_drv_suspend,
-	.resume		= ks8695_drv_resume,
-};
-
-module_platform_driver(ks8695_driver);
-
-MODULE_AUTHOR("Simtec Electronics");
-MODULE_DESCRIPTION("Micrel KS8695 (Centaur) Ethernet driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:" MODULENAME);
-
-module_param(watchdog, int, 0400);
-MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");
diff --git a/drivers/net/ethernet/micrel/ks8695net.h b/drivers/net/ethernet/micrel/ks8695net.h
deleted file mode 100644
index b18fad4ad5fd..000000000000
--- a/drivers/net/ethernet/micrel/ks8695net.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Micrel KS8695 (Centaur) Ethernet.
- *
- * Copyright 2008 Simtec Electronics
- *		  Daniel Silverstone <dsilvers@simtec.co.uk>
- *		  Vincent Sanders <vince@simtec.co.uk>
- */
-
-#ifndef KS8695NET_H
-#define KS8695NET_H
-
-/* Receive descriptor flags */
-#define RDES_OWN	(1 << 31)	/* Ownership */
-#define RDES_FS		(1 << 30)	/* First Descriptor */
-#define RDES_LS		(1 << 29)	/* Last Descriptor */
-#define RDES_IPE	(1 << 28)	/* IP Checksum error */
-#define RDES_TCPE	(1 << 27)	/* TCP Checksum error */
-#define RDES_UDPE	(1 << 26)	/* UDP Checksum error */
-#define RDES_ES		(1 << 25)	/* Error summary */
-#define RDES_MF		(1 << 24)	/* Multicast Frame */
-#define RDES_RE		(1 << 19)	/* MII Error reported */
-#define RDES_TL		(1 << 18)	/* Frame too Long */
-#define RDES_RF		(1 << 17)	/* Runt Frame */
-#define RDES_CE		(1 << 16)	/* CRC error */
-#define RDES_FT		(1 << 15)	/* Frame Type */
-#define RDES_FLEN	(0x7ff)		/* Frame Length */
-
-#define RDES_RER	(1 << 25)	/* Receive End of Ring */
-#define RDES_RBS	(0x7ff)		/* Receive Buffer Size */
-
-/* Transmit descriptor flags */
-
-#define TDES_OWN	(1 << 31)	/* Ownership */
-
-#define TDES_IC		(1 << 31)	/* Interrupt on Completion */
-#define TDES_FS		(1 << 30)	/* First Segment */
-#define TDES_LS		(1 << 29)	/* Last Segment */
-#define TDES_IPCKG	(1 << 28)	/* IP Checksum generate */
-#define TDES_TCPCKG	(1 << 27)	/* TCP Checksum generate */
-#define TDES_UDPCKG	(1 << 26)	/* UDP Checksum generate */
-#define TDES_TER	(1 << 25)	/* Transmit End of Ring */
-#define TDES_TBS	(0x7ff)		/* Transmit Buffer Size */
-
-/*
- * Network controller register offsets
- */
-#define KS8695_DTXC		(0x00)		/* DMA Transmit Control */
-#define KS8695_DRXC		(0x04)		/* DMA Receive Control */
-#define KS8695_DTSC		(0x08)		/* DMA Transmit Start Command */
-#define KS8695_DRSC		(0x0c)		/* DMA Receive Start Command */
-#define KS8695_TDLB		(0x10)		/* Transmit Descriptor List
-						 * Base Address
-						 */
-#define KS8695_RDLB		(0x14)		/* Receive Descriptor List
-						 * Base Address
-						 */
-#define KS8695_MAL		(0x18)		/* MAC Station Address Low */
-#define KS8695_MAH		(0x1c)		/* MAC Station Address High */
-#define KS8695_AAL_(n)		(0x80 + ((n)*8))	/* MAC Additional
-							 * Station Address
-							 * (0..15) Low
-							 */
-#define KS8695_AAH_(n)		(0x84 + ((n)*8))	/* MAC Additional
-							 * Station Address
-							 * (0..15) High
-							 */
-
-
-/* DMA Transmit Control Register */
-#define DTXC_TRST		(1    << 31)	/* Soft Reset */
-#define DTXC_TBS		(0x3f << 24)	/* Transmit Burst Size */
-#define DTXC_TUCG		(1    << 18)	/* Transmit UDP
-						 * Checksum Generate
-						 */
-#define DTXC_TTCG		(1    << 17)	/* Transmit TCP
-						 * Checksum Generate
-						 */
-#define DTXC_TICG		(1    << 16)	/* Transmit IP
-						 * Checksum Generate
-						 */
-#define DTXC_TFCE		(1    <<  9)	/* Transmit Flow
-						 * Control Enable
-						 */
-#define DTXC_TLB		(1    <<  8)	/* Loopback mode */
-#define DTXC_TEP		(1    <<  2)	/* Transmit Enable Padding */
-#define DTXC_TAC		(1    <<  1)	/* Transmit Add CRC */
-#define DTXC_TE			(1    <<  0)	/* TX Enable */
-
-/* DMA Receive Control Register */
-#define DRXC_RBS		(0x3f << 24)	/* Receive Burst Size */
-#define DRXC_RUCC		(1    << 18)	/* Receive UDP Checksum check */
-#define DRXC_RTCG		(1    << 17)	/* Receive TCP Checksum check */
-#define DRXC_RICG		(1    << 16)	/* Receive IP Checksum check */
-#define DRXC_RFCE		(1    <<  9)	/* Receive Flow Control
-						 * Enable
-						 */
-#define DRXC_RB			(1    <<  6)	/* Receive Broadcast */
-#define DRXC_RM			(1    <<  5)	/* Receive Multicast */
-#define DRXC_RU			(1    <<  4)	/* Receive Unicast */
-#define DRXC_RERR		(1    <<  3)	/* Receive Error Frame */
-#define DRXC_RA			(1    <<  2)	/* Receive All */
-#define DRXC_RE			(1    <<  0)	/* RX Enable */
-
-/* Additional Station Address High */
-#define AAH_E			(1    << 31)	/* Address Enabled */
-
-#endif /* KS8695NET_H */
-- 
2.20.0


^ permalink raw reply related

* Re: [PATCH net-next v6 3/3] net: phy: broadcom: add 1000Base-X support for BCM54616S
From: Heiner Kallweit @ 2019-08-09 20:21 UTC (permalink / raw)
  To: Tao Ren, Andrew Lunn, Florian Fainelli, David S . Miller,
	Arun Parameswaran, Justin Chen, Vladimir Oltean, netdev,
	linux-kernel, openbmc
In-Reply-To: <20190809054411.1015962-1-taoren@fb.com>

On 09.08.2019 07:44, Tao Ren wrote:
> The BCM54616S PHY cannot work properly in RGMII->1000Base-KX mode (for
> example, on Facebook CMM BMC platform), mainly because genphy functions
> are designed for copper links, and 1000Base-X (clause 37) auto negotiation
> needs to be handled differently.
> 
> This patch enables 1000Base-X support for BCM54616S by customizing 3
> driver callbacks:
> 
>   - probe: probe callback detects PHY's operation mode based on
>     INTERF_SEL[1:0] pins and 1000X/100FX selection bit in SerDES 100-FX
>     Control register.
> 
>   - config_aneg: calls genphy_c37_config_aneg when the PHY is running in
>     1000Base-X mode; otherwise, genphy_config_aneg will be called.
> 
>   - read_status: calls genphy_c37_read_status when the PHY is running in
>     1000Base-X mode; otherwise, genphy_read_status will be called.
> 
> Signed-off-by: Tao Ren <taoren@fb.com>
> ---
>  Changes in v6:
>   - nothing changed.
>  Changes in v5:
>   - include Heiner's patch "net: phy: add support for clause 37
>     auto-negotiation" into the series.
>   - use genphy_c37_config_aneg and genphy_c37_read_status in BCM54616S
>     PHY driver's callback when the PHY is running in 1000Base-X mode.
>  Changes in v4:
>   - add bcm54616s_config_aneg_1000bx() to deal with auto negotiation in
>     1000Base-X mode.
>  Changes in v3:
>   - rename bcm5482_read_status to bcm54xx_read_status so the callback can
>     be shared by BCM5482 and BCM54616S.
>  Changes in v2:
>   - Auto-detect PHY operation mode instead of passing DT node.
>   - move PHY mode auto-detect logic from config_init to probe callback.
>   - only set speed (not including duplex) in read_status callback.
>   - update patch description with more background to avoid confusion.
>   - patch #1 in the series ("net: phy: broadcom: set features explicitly
>     for BCM54616") is dropped: the fix should go to get_features callback
>     which may potentially depend on this patch.
> 
>  drivers/net/phy/broadcom.c | 54 +++++++++++++++++++++++++++++++++++---
>  include/linux/brcmphy.h    | 10 +++++--
>  2 files changed, 58 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
> index 937d0059e8ac..fbd76a31c142 100644
> --- a/drivers/net/phy/broadcom.c
> +++ b/drivers/net/phy/broadcom.c
> @@ -383,9 +383,9 @@ static int bcm5482_config_init(struct phy_device *phydev)
>  		/*
>  		 * Select 1000BASE-X register set (primary SerDes)
>  		 */
> -		reg = bcm_phy_read_shadow(phydev, BCM5482_SHD_MODE);
> -		bcm_phy_write_shadow(phydev, BCM5482_SHD_MODE,
> -				     reg | BCM5482_SHD_MODE_1000BX);
> +		reg = bcm_phy_read_shadow(phydev, BCM54XX_SHD_MODE);
> +		bcm_phy_write_shadow(phydev, BCM54XX_SHD_MODE,
> +				     reg | BCM54XX_SHD_MODE_1000BX);
>  
>  		/*
>  		 * LED1=ACTIVITYLED, LED3=LINKSPD[2]
> @@ -451,12 +451,44 @@ static int bcm5481_config_aneg(struct phy_device *phydev)
>  	return ret;
>  }
>  
> +static int bcm54616s_probe(struct phy_device *phydev)
> +{
> +	int val, intf_sel;
> +
> +	val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_MODE);
> +	if (val < 0)
> +		return val;
> +
> +	/* The PHY is strapped in RGMII to fiber mode when INTERF_SEL[1:0]
> +	 * is 01b.
> +	 */
> +	intf_sel = (val & BCM54XX_SHD_INTF_SEL_MASK) >> 1;
> +	if (intf_sel == 1) {
> +		val = bcm_phy_read_shadow(phydev, BCM54616S_SHD_100FX_CTRL);
> +		if (val < 0)
> +			return val;
> +
> +		/* Bit 0 of the SerDes 100-FX Control register, when set
> +		 * to 1, sets the MII/RGMII -> 100BASE-FX configuration.
> +		 * When this bit is set to 0, it sets the GMII/RGMII ->
> +		 * 1000BASE-X configuration.
> +		 */
> +		if (!(val & BCM54616S_100FX_MODE))
> +			phydev->dev_flags |= PHY_BCM_FLAGS_MODE_1000BX;
> +	}
> +
> +	return 0;
> +}
> +
>  static int bcm54616s_config_aneg(struct phy_device *phydev)
>  {
>  	int ret;
>  
>  	/* Aneg firsly. */
> -	ret = genphy_config_aneg(phydev);
> +	if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX)
> +		ret = genphy_c37_config_aneg(phydev);
> +	else
> +		ret = genphy_config_aneg(phydev);
>  

I'm just wondering whether it needs to be considered that 100base-FX
doesn't support auto-negotiation. I suppose BMSR reports aneg as
supported, therefore phylib will use aneg per default.
Not sure who could set 100Base-FX mode when, but maybe at that place
also phydev->autoneg needs to be cleared. Did you test 100Base-FX mode?

Heiner

^ permalink raw reply

* Re: [net v2] ixgbe: fix possible deadlock in ixgbe_service_task()
From: David Miller @ 2019-08-09 20:17 UTC (permalink / raw)
  To: jeffrey.t.kirsher; +Cc: ap420073, netdev, nhorman, sassmann, andrewx.bowers
In-Reply-To: <20190808163756.8753-1-jeffrey.t.kirsher@intel.com>

From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Date: Thu,  8 Aug 2019 09:37:56 -0700

> From: Taehee Yoo <ap420073@gmail.com>
> 
> ixgbe_service_task() calls unregister_netdev() under rtnl_lock().
> But unregister_netdev() internally calls rtnl_lock().
> So deadlock would occur.
> 
> Fixes: 59dd45d550c5 ("ixgbe: firmware recovery mode")
> Signed-off-by: Taehee Yoo <ap420073@gmail.com>
> Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
> ---
> v2: removed unnecessary curly brackets

Applied, thanks everyone.

^ permalink raw reply


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