* Re: [PATCH] netem: Segment GSO packets on enqueue.
From: Neil Horman @ 2016-04-26 19:00 UTC (permalink / raw)
To: Eric Dumazet; +Cc: netdev, Jamal Hadi Salim, David S. Miller, netem
In-Reply-To: <1461696598.5535.35.camel@edumazet-glaptop3.roam.corp.google.com>
On Tue, Apr 26, 2016 at 11:49:58AM -0700, Eric Dumazet wrote:
> On Tue, 2016-04-26 at 13:43 -0400, Neil Horman wrote:
> > This was recently reported to me, and reproduced on the latest net kernel, when
> > attempting to run netperf from a host that had a netem qdisc attached to the
> > egress interface:
>
> ..
>
> > The problem occurs because netem is not prepared to handle GSO packets (as it
> > uses skb_checksum_help in its enqueue path, which cannot manipulate these
> > frames).
> >
> > The solution I think is to simply segment the skb in a simmilar fashion to the
> > way we do in __dev_queue_xmit (via validate_xmit_skb), except here we always
> > segment, instead of only when the interface needs us to do it. This allows
> > netem to properly drop/mangle/pass/etc the correct percentages of frames as per
> > its qdisc configuration, and avoid failing its checksum operations
> >
> > tested successfully by myself on the latest net kernel, to whcih this applies
> >
> > Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
> > CC: Jamal Hadi Salim <jhs@mojatatu.com>
> > CC: "David S. Miller" <davem@davemloft.net>
> > CC: netem@lists.linux-foundation.org
> > ---
> > net/sched/sch_netem.c | 34 +++++++++++++++++++++++++++++++++-
> > 1 file changed, 33 insertions(+), 1 deletion(-)
>
>
> This is not correct.
>
> I want my TSO packets being still TSO after netem traversal.
>
> Some of us use netem at 40Gbit speed ;)
>
I can understand that, but that raises two questions in my mind:
1) Doesn't that make all the statistical manipulation for netem wrong? That is
to say, if netem drops 5% of packets, and it happens to drop a GSO packet, its
actually dropping several, instead of the single one required.
2) How are you getting netem to work with GSO at all? The warning is triggered
for me on every GSO packet, which I think would impact throughput :)
Neil
^ permalink raw reply
* Re: [PATCH net-next] macvlan: fix failure during registration v3
From: Francesco Ruggeri @ 2016-04-26 19:07 UTC (permalink / raw)
To: Mahesh Bandewar; +Cc: linux-netdev, Eric W. Biederman, David S. Miller
In-Reply-To: <CAF2d9jh98MGYorJ=btvx04==EsjP5_ivUEimf0TJ1NUPDzG4nw@mail.gmail.com>
On Tue, Apr 26, 2016 at 11:54 AM, Mahesh Bandewar <maheshb@google.com> wrote:
>
> On Sat, Apr 23, 2016 at 3:03 PM, Francesco Ruggeri <fruggeri@arista.com> wrote:
> > If macvlan_common_newlink fails in register_netdevice after macvlan_init
> > then it decrements port->count twice, first in macvlan_uninit (from
> > register_netdevice or rollback_registered) and then again in
> > macvlan_common_newlink.
> > A similar problem may exist in the ipvlan driver.
> That is correct! The problem exists in ipvlan driver also. I'll cook a
> patch to fix this in ipvlan driver.
>
> > This patch consolidates modifications to port->count into macvlan_init
> > and macvlan_uninit (thanks to Eric Biederman for suggesting this approach).
> >
> > v3: remove macvtap specific bits.
> >
> > Signed-off-by: Francesco Ruggeri <fruggeri@arista.com>
> > ---
> > drivers/net/macvlan.c | 10 ++++------
> > 1 file changed, 4 insertions(+), 6 deletions(-)
> >
> > diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
> > index 2bcf1f3..cb01023 100644
> > --- a/drivers/net/macvlan.c
> > +++ b/drivers/net/macvlan.c
> > @@ -795,6 +795,7 @@ static int macvlan_init(struct net_device *dev)
> > {
> > struct macvlan_dev *vlan = netdev_priv(dev);
> > const struct net_device *lowerdev = vlan->lowerdev;
> > + struct macvlan_port *port = vlan->port;
> >
> > dev->state = (dev->state & ~MACVLAN_STATE_MASK) |
> > (lowerdev->state & MACVLAN_STATE_MASK);
> > @@ -812,6 +813,8 @@ static int macvlan_init(struct net_device *dev)
> > if (!vlan->pcpu_stats)
> > return -ENOMEM;
> >
> > + port->count += 1;
> > +
> > return 0;
> > }
> >
> > @@ -1312,10 +1315,9 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
> > return err;
> > }
> >
> > - port->count += 1;
> > err = register_netdevice(dev);
> > if (err < 0)
> > - goto destroy_port;
> > + return err;
> >
> > dev->priv_flags |= IFF_MACVLAN;
> > err = netdev_upper_dev_link(lowerdev, dev);
> > @@ -1330,10 +1332,6 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
> >
> > unregister_netdev:
> > unregister_netdevice(dev);
> > -destroy_port:
> > - port->count -= 1;
> > - if (!port->count)
> > - macvlan_port_destroy(lowerdev);
> I think you still need this when it fails netdev_upper_dev_link(). The
> only thing you should remove is the label.
I don't think so. I think the double decrement also occurred in this case.
unregister_netdevice invokes rollback_registered/macvlan_uninit
which does the decrement.
Thanks,
Francesco
> >
> > return err;
> > }
> > --
> > 1.8.1.4
> >
^ permalink raw reply
* Re: [PATCH] can: m_can: fix bitrate setup on latest silicon
From: Oliver Hartkopp @ 2016-04-26 19:11 UTC (permalink / raw)
To: Florian Vallee, Wolfgang Grandegger, Marc Kleine-Budde
Cc: linux-can, netdev, linux-kernel, ebenard
In-Reply-To: <1461678379-28257-1-git-send-email-fvallee@eukrea.fr>
On 04/26/2016 03:46 PM, Florian Vallee wrote:
> According to the m_can user manual changelog the BTP register layout was
> updated with core revision 3.1.0
Hello Florian,
nice to see a real v3.1.0 user emerging on the mailing list :-)
I wonder whether this small change covers the updates made between
v3.0.1 and v3.1.0.
IIRC
v3.0.1:
NON_ISO operation / general CAN/CANFD and BRS switch in register CCCR
v3.1.0:
ISO operation / per frame CAN/CANFD switch (FDF/BRS bit in TX/RX buffer)
v3.2.x:
Ability to switch ISO/NON_ISO operation (NISO bit on register CCCR)
updated range of NBTP.NTSEG2
The current v3.0.1 driver is fixed to tell to be a NON_ISO controller:
https://git.kernel.org/cgit/linux/kernel/git/mkl/linux-can-next.git/diff/drivers/net/can/m_can/m_can.c?h=testing
The v3.1.0 is a fixed ISO controller and additional it does not make
sense anymore to configure the CCCR register each time, before sending a
frame:
https://git.kernel.org/cgit/linux/kernel/git/mkl/linux-can-next.git/tree/drivers/net/can/m_can/m_can.c?h=testing&id=885cc17abad6c3064f266099a6ded2d357012380#n1075
Just as the new TX/RX buffer layout contains a FDF and BRS bits for this
reason.
> +static inline int m_can_read_core_rev(const struct m_can_priv *priv)
> +{
> + u32 reg = m_can_read(priv, M_CAN_CREL);
> +
> + return ((reg >> CRR_REL_SHIFT) & CRR_REL_MASK);
> +}
> +
> static void m_can_read_fifo(struct net_device *dev, u32 rxfs)
> {
> struct net_device_stats *stats = &dev->stats;
> @@ -814,8 +838,16 @@ static int m_can_set_bittiming(struct net_device *dev)
> sjw = bt->sjw - 1;
> tseg1 = bt->prop_seg + bt->phase_seg1 - 1;
> tseg2 = bt->phase_seg2 - 1;
> - reg_btp = (brp << BTR_BRP_SHIFT) | (sjw << BTR_SJW_SHIFT) |
> - (tseg1 << BTR_TSEG1_SHIFT) | (tseg2 << BTR_TSEG2_SHIFT);
> +
> + if (m_can_read_core_rev(priv) < M_CAN_COREREL_3_1_0)
Your patch looks very good so far. I would appreciate if you could
update the other register changes too as I don't have a hardware to
test. I can provide the ISO/NON_ISO config for the netlink interface
updates then :-)
Best regards,
Oliver
^ permalink raw reply
* Re: [PATCH net-next] ravb: Remove rx buffer ALIGN
From: Sergei Shtylyov @ 2016-04-26 19:14 UTC (permalink / raw)
To: Yoshihiro Kaneko, netdev
Cc: David S. Miller, Simon Horman, Magnus Damm, linux-renesas-soc
In-Reply-To: <1461514567-23444-1-git-send-email-ykaneko0929@gmail.com>
Hello.
On 04/24/2016 07:16 PM, Yoshihiro Kaneko wrote:
> From: Kazuya Mizuguchi <kazuya.mizuguchi.ks@renesas.com>
>
> Aligning the reception data size is not required.
OK, the gen 2/3 manuals indeed don't require this. I assume the patch has
been tested...
> Signed-off-by: Kazuya Mizuguchi <kazuya.mizuguchi.ks@renesas.com>
> Signed-off-by: Yoshihiro Kaneko <ykaneko0929@gmail.com>
I have a few comments though...
> diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
> index 238b56f..66ed80c 100644
> --- a/drivers/net/ethernet/renesas/ravb_main.c
> +++ b/drivers/net/ethernet/renesas/ravb_main.c
> @@ -246,10 +246,10 @@ static void ravb_ring_format(struct net_device *ndev, int q)
> for (i = 0; i < priv->num_rx_ring[q]; i++) {
> /* RX descriptor */
> rx_desc = &priv->rx_ring[q][i];
> - /* The size of the buffer should be on 16-byte boundary. */
> - rx_desc->ds_cc = cpu_to_le16(ALIGN(PKT_BUF_SZ, 16));
> - dma_addr = dma_map_single(ndev->dev.parent, priv->rx_skb[q][i]->data,
> - ALIGN(PKT_BUF_SZ, 16),
> + rx_desc->ds_cc = cpu_to_le16(PKT_BUF_SZ);
> + dma_addr = dma_map_single(ndev->dev.parent,
> + priv->rx_skb[q][i]->data,
Please don't reformat the lines above.
> + PKT_BUF_SZ,
> DMA_FROM_DEVICE);
> /* We just set the data size to 0 for a failed mapping which
> * should prevent DMA from happening...
> @@ -557,8 +557,9 @@ static bool ravb_rx(struct net_device *ndev, int *quota, int q)
>
> skb = priv->rx_skb[q][entry];
> priv->rx_skb[q][entry] = NULL;
> - dma_unmap_single(ndev->dev.parent, le32_to_cpu(desc->dptr),
> - ALIGN(PKT_BUF_SZ, 16),
> + dma_unmap_single(ndev->dev.parent,
> + le32_to_cpu(desc->dptr),
Same here.
[...]
MBR, Sergei
^ permalink raw reply
* Re: [PATCH net-next] macvlan: fix failure during registration v3
From: David Miller @ 2016-04-26 19:19 UTC (permalink / raw)
To: fruggeri; +Cc: netdev, ebiederm, maheshb
In-Reply-To: <1461449012-7401-1-git-send-email-fruggeri@arista.com>
From: Francesco Ruggeri <fruggeri@arista.com>
Date: Sat, 23 Apr 2016 15:03:32 -0700
> If macvlan_common_newlink fails in register_netdevice after macvlan_init
> then it decrements port->count twice, first in macvlan_uninit (from
> register_netdevice or rollback_registered) and then again in
> macvlan_common_newlink.
> A similar problem may exist in the ipvlan driver.
> This patch consolidates modifications to port->count into macvlan_init
> and macvlan_uninit (thanks to Eric Biederman for suggesting this approach).
>
> v3: remove macvtap specific bits.
>
> Signed-off-by: Francesco Ruggeri <fruggeri@arista.com>
Applied.
^ permalink raw reply
* Re: [PATCH net-next] macvtap: check minor when unregistering
From: David Miller @ 2016-04-26 19:19 UTC (permalink / raw)
To: fruggeri; +Cc: netdev, ebiederm
In-Reply-To: <1461449071-7499-1-git-send-email-fruggeri@arista.com>
From: Francesco Ruggeri <fruggeri@arista.com>
Date: Sat, 23 Apr 2016 15:04:31 -0700
> macvtap_device_event(NETDEV_UNREGISTER) should check vlan->minor to
> determine if it is being invoked in the context of a macvtap_newlink
> that failed, for example in this code sequence:
>
> macvtap_newlink
> macvlan_common_newlink
> register_netdevice
> call_netdevice_notifiers(NETDEV_REGISTER, dev)
> macvtap_device_event(NETDEV_REGISTER)
> <fail here, vlan->minor = 0>
> rollback_registered(dev);
> rollback_registered_many
> call_netdevice_notifiers(NETDEV_UNREGISTER, dev);
> macvtap_device_event(NETDEV_UNREGISTER)
> <nothing to clean up here>
>
> Signed-off-by: Francesco Ruggeri <fruggeri@arista.com>
Applied.
^ permalink raw reply
* Re: [PATCH net-next] sctp: sctp_diag should fill RMEM_ALLOC with asoc->rmem_alloc when rcvbuf_policy is set
From: David Miller @ 2016-04-26 19:19 UTC (permalink / raw)
To: lucien.xin
Cc: netdev, linux-sctp, marcelo.leitner, vyasevich, daniel,
eric.dumazet
In-Reply-To: <f21861d502b04cf3752dce4cde8cd3f5f1806571.1461511282.git.lucien.xin@gmail.com>
From: Xin Long <lucien.xin@gmail.com>
Date: Sun, 24 Apr 2016 23:21:22 +0800
> For sctp assoc, when rcvbuf_policy is set, it will has it's own
> rmem_alloc, when we dump asoc info in sctp_diag, we should use that
> value on RMEM_ALLOC as well, just like WMEM_ALLOC.
>
> Signed-off-by: Xin Long <lucien.xin@gmail.com>
Applied.
^ permalink raw reply
* Re: [PATCH] sh_eth: get rid of the 2nd parameter to sh_eth_dev_init()
From: David Miller @ 2016-04-26 19:22 UTC (permalink / raw)
To: sergei.shtylyov; +Cc: netdev, linux-renesas-soc
In-Reply-To: <1615196.r6Bb3HFTJZ@wasted.cogentembedded.com>
From: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Date: Sun, 24 Apr 2016 19:11:07 +0300
> sh_eth_dev_init() is now always called with 'true' as the 2nd argument,
> so that there's no more sense in having 2 parameters to this function...
>
> Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Applied.
^ permalink raw reply
* Re: [PATCH 1/6] bus: Add shared MDIO bus framework
From: Arnd Bergmann @ 2016-04-26 19:24 UTC (permalink / raw)
To: Andrew Lunn
Cc: Florian Fainelli, Pramod Kumar, Rob Herring, Catalin Marinas,
Will Deacon, Masahiro Yamada, Chen-Yu Tsai, Mark Rutland,
devicetree, Pawel Moll, Suzuki K Poulose, netdev, Punit Agrawal,
linux-kernel, BCM Kernel Feedback, linux-arm-kernel, Anup Patel,
Kishon Vijay Abraham I
In-Reply-To: <20160426182335.GE30107@lunn.ch>
On Tuesday 26 April 2016 20:23:35 Andrew Lunn wrote:
> > A more complex problem would be having a PHY driver for a device
> > that can be either an ethernet phy or some other phy.
>
> I doubt that ever happens. You can have up to 32 different devices on
> an MDIO bus. Since an Ethernet PHY and a "some other sort of PHY" are
> completely different things, why would a hardware engineer place them
> on the same address? It is like saying your ATA controller and VGA
> controller share the same slot on the PCI bus...
To clarify: what I meant is a device that is designed as a PHY for
similar hardware (e.g. SATA, USB3 and PCIe) and that has a common
register set and a single driver, but that driver can operate
in multiple modes. You typically have multiple instances of
such hardware, with each instance linked to exactly one host
device, but one driver for all of them.
See Documentation/devicetree/bindings/phy/apm-xgene-phy.txt
and drivers/phy/phy-xgene.c for one such example.
Arnd
^ permalink raw reply
* Re: [PATCH 1/6] bus: Add shared MDIO bus framework
From: Andrew Lunn @ 2016-04-26 19:41 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Florian Fainelli, Pramod Kumar, Rob Herring, Catalin Marinas,
Will Deacon, Masahiro Yamada, Chen-Yu Tsai, Mark Rutland,
devicetree, Pawel Moll, Suzuki K Poulose, netdev, Punit Agrawal,
linux-kernel, BCM Kernel Feedback, linux-arm-kernel, Anup Patel,
Kishon Vijay Abraham I
In-Reply-To: <9424602.Vqb0FY56gH@wuerfel>
On Tue, Apr 26, 2016 at 09:24:34PM +0200, Arnd Bergmann wrote:
> On Tuesday 26 April 2016 20:23:35 Andrew Lunn wrote:
> > > A more complex problem would be having a PHY driver for a device
> > > that can be either an ethernet phy or some other phy.
> >
> > I doubt that ever happens. You can have up to 32 different devices on
> > an MDIO bus. Since an Ethernet PHY and a "some other sort of PHY" are
> > completely different things, why would a hardware engineer place them
> > on the same address? It is like saying your ATA controller and VGA
> > controller share the same slot on the PCI bus...
>
> To clarify: what I meant is a device that is designed as a PHY for
> similar hardware (e.g. SATA, USB3 and PCIe) and that has a common
> register set and a single driver, but that driver can operate
> in multiple modes. You typically have multiple instances of
> such hardware, with each instance linked to exactly one host
> device, but one driver for all of them.
>
> See Documentation/devicetree/bindings/phy/apm-xgene-phy.txt
> and drivers/phy/phy-xgene.c for one such example.
Interesting. Also, that this lists SGMII. I assume this is a phy in
the MAC in order to talk to the Ethernet PHY.
I still don't see it being a big problem if a phy driver implements an
Ethernet PHY. It just needs to call phy_device_create() and
phy_device_register().
Andrew
^ permalink raw reply
* Re: [PATCH 0/5] Don't return NULL from get_phy_device() anymore
From: David Miller @ 2016-04-26 19:41 UTC (permalink / raw)
To: sergei.shtylyov; +Cc: f.fainelli, netdev, arnd
In-Reply-To: <56219623.1S7UfcqQqc@wasted.cogentembedded.com>
From: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Date: Sun, 24 Apr 2016 20:23:03 +0300
> Here's the set of 5 patches against DaveM's 'net-next.git' repo. The first
> patch makes get_phy_device() return only error values on error, the rest of
> the patches clean up the callers of that function...
Series applied, thanks.
^ permalink raw reply
* Re: [PATCH] Fixes buffer allocation size and the actual packet length;
From: David Miller @ 2016-04-26 19:45 UTC (permalink / raw)
To: petkan; +Cc: netdev
In-Reply-To: <1461696624-5373-1-git-send-email-petkan@mip-labs.com>
Submitting a cover letter and the patch itself with identical Subject lines
is not correct.
You must also use proper "[PATCH $(TREE) X/Y] " prefixes in your Subject
lines as well.
Please format your Subject lines correctly and resubmit, thank you.
^ permalink raw reply
* Re: [PATCH RFC net-next] net: dsa: Provide CPU port statistics to master netdev
From: Florian Fainelli @ 2016-04-26 19:44 UTC (permalink / raw)
To: Andrew Lunn; +Cc: netdev, davem, vivien.didelot
In-Reply-To: <20160425214342.GB5538@lunn.ch>
On 25/04/16 14:43, Andrew Lunn wrote:
> On Wed, Apr 20, 2016 at 10:58:21AM -0700, Florian Fainelli wrote:
>> This patch overloads the DSA master netdev, aka CPU Ethernet MAC to also
>> include switch-side statistics, which is useful for debugging purposes,
>> when the switch is not properly connected to the Ethernet MAC (duplex
>> mismatch, (RG)MII electrical issues etc.).
>>
>> We accomplish this by retaining the original copy of the master netdev's
>> ethtool_ops, and just overload the 3 operations we care about:
>> get_sset_count, get_strings and get_ethtool_stats so as to intercept
>> these calls and call into the original master_netdev ethtool_ops, plus
>> our own.
>
> Hi Florian
>
> Interesting concept. My one concern is that by concatenating the two
> sets of statistics, we get a name clash. I'm not sure the Marvell
> switch statistics counters have different names to the Marvell
> Ethernet driver statistics counters. ethtool does not care, but maybe
> an SNMP agent using these statistics might not be too happy seeing the
> same name twice?
That's a very good point, would you agree if we were prefixing the DSA
CPU port statistics with some kind of name, e.g: cpu_port_<name> or
something more compact?
--
Florian
^ permalink raw reply
* Re: [PATCH net-next 0/6] net: core: remove TX_LOCKED support
From: David Miller @ 2016-04-26 19:53 UTC (permalink / raw)
To: fw; +Cc: netdev, linux-kernel
In-Reply-To: <1461526694-11367-1-git-send-email-fw@strlen.de>
From: Florian Westphal <fw@strlen.de>
Date: Sun, 24 Apr 2016 21:38:08 +0200
> Not that many users left, lets kill it.
>
> TX_LOCKED was meant to be used by LLTX drivers when spin_trylock()
> failed. Stack then re-queued if collisions happened on different
> cpus or free'd the skb to prevent deadlocks.
>
> Most of the driver removal patches fall into one of three categories:
> 1. remove the driver-private tx lock (and LLTX flag), or...
> 2. convert spin_trylock to plain spin_lock, or...
> 3. convert TX_LOCKED to free+TX_OK
>
> Patches are grouped by these categories, last patch is the actual removal.
> All driver changes were compile tested only with exception of atl1e.
This looks good to me, series applied, thanks Florian.
^ permalink raw reply
* Re: [PATCH net-next V1 00/11] Mellanox 100G extending mlx5 ethtool support
From: David Miller @ 2016-04-26 20:03 UTC (permalink / raw)
To: saeedm; +Cc: netdev, ogerlitz, talal, eranbe
In-Reply-To: <1461527516-29290-1-git-send-email-saeedm@mellanox.com>
From: Saeed Mahameed <saeedm@mellanox.com>
Date: Sun, 24 Apr 2016 22:51:45 +0300
> Changes from V0:
> - Dropped: net/mlx5e: Disable link up on INIT HCA command
> Due to Ido's and Or's requests we will submit this patch to net and will need it for -stable.
> - Rebased to: 11afbff86168 ("Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next")
>
> This series is centralized around extending and improving mlx5 ethernet driver ethtool
> support. We've done some code refactoring for ethtool statistics reporting, making it
> more scalable and robust, now each reported ethtool counter belongs to a group and has
> its own descriptor within that group, the descriptor holds the counter name and offset
> in memory in that group memory block.
>
> Added new counters:
> - Reporting more error and drop counter in ifconig/ip tool.
> - Per priority pause and traffic counter in ethtool.
> - link down events counter in ethtool.
>
> Set features handling was also refactored a little bit to be more resilient and generic,
> now setting more than one feature will not stop on the first failed one, but instead
> it will try to continue setting others. We made it generic to make it simpler for adding
> more features support, it is now done easily by only introducing a handler function of
> the new supported netdev feature, and let the generic handler do the job.
>
> New netdev features and ethtool support:
> - Netdev feature RXALL, set on/off FCS check offload.
> - Netdev feature HW_VLAN_CTAG_RX, set on/off rx-vlan stripping offload.
> - Ethtool interface identify.
> - Ethtool dump module EEPROM.
Series applied.
Be careful about what feature update semantics you implement. If you get a request
to change multiple feature bits, and even one of them cannot be done, the entire
update operation should fail and the bits should revert to what they were before
the request.
Is that how the code behaves now?
^ permalink raw reply
* [PATCH v6 03/25] io-mapping: Specify mapping size for io_mapping_map_wc()
From: Chris Wilson @ 2016-04-26 20:05 UTC (permalink / raw)
To: intel-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
Cc: Chris Wilson, Tvrtko Ursulin, Daniel Vetter, Jani Nikula,
David Airlie, Yishai Hadas, Dan Williams, Ingo Molnar,
Peter Zijlstra (Intel), David Hildenbrand, Luis R . Rodriguez,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
netdev-u79uwXL29TY76Z2rM5mHXA, linux-rdma-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1461701180-895-1-git-send-email-chris-Y6uKTt2uX1cEflXRtASbqLVCufUGDwFn@public.gmane.org>
The ioremap() hidden behind the io_mapping_map_wc() convenience helper
can be used for remapping multiple pages. Extend the helper so that
future callers can use it for larger ranges.
Signed-off-by: Chris Wilson <chris-Y6uKTt2uX1cEflXRtASbqLVCufUGDwFn@public.gmane.org>
Cc: Tvrtko Ursulin <tvrtko.ursulin-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Cc: Daniel Vetter <daniel.vetter-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Cc: Jani Nikula <jani.nikula-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Cc: David Airlie <airlied-cv59FeDIM0c@public.gmane.org>
Cc: Yishai Hadas <yishaih-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
Cc: Dan Williams <dan.j.williams-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Cc: Ingo Molnar <mingo-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Cc: "Peter Zijlstra (Intel)" <peterz-wEGCiKHe2LqWVfeAwA7xHQ@public.gmane.org>
Cc: David Hildenbrand <dahi-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
Cc: Luis R. Rodriguez <mcgrof-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Cc: intel-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org
Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org
Cc: netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Cc: linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Reviewed-by: Luis R. Rodriguez <mcgrof-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
drivers/gpu/drm/i915/intel_overlay.c | 3 ++-
drivers/net/ethernet/mellanox/mlx4/pd.c | 4 +++-
include/linux/io-mapping.h | 10 +++++++---
3 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
index 06bcd6aee64f..8d5293644d05 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -198,7 +198,8 @@ intel_overlay_map_regs(struct intel_overlay *overlay)
regs = (struct overlay_registers __iomem *)overlay->reg_bo->phys_handle->vaddr;
else
regs = io_mapping_map_wc(ggtt->mappable,
- overlay->flip_addr);
+ overlay->flip_addr,
+ PAGE_SIZE);
return regs;
}
diff --git a/drivers/net/ethernet/mellanox/mlx4/pd.c b/drivers/net/ethernet/mellanox/mlx4/pd.c
index b3cc3ab63799..6fc156a3918d 100644
--- a/drivers/net/ethernet/mellanox/mlx4/pd.c
+++ b/drivers/net/ethernet/mellanox/mlx4/pd.c
@@ -205,7 +205,9 @@ int mlx4_bf_alloc(struct mlx4_dev *dev, struct mlx4_bf *bf, int node)
goto free_uar;
}
- uar->bf_map = io_mapping_map_wc(priv->bf_mapping, uar->index << PAGE_SHIFT);
+ uar->bf_map = io_mapping_map_wc(priv->bf_mapping,
+ uar->index << PAGE_SHIFT,
+ PAGE_SIZE);
if (!uar->bf_map) {
err = -ENOMEM;
goto unamp_uar;
diff --git a/include/linux/io-mapping.h b/include/linux/io-mapping.h
index e399029b68c5..645ad06b5d52 100644
--- a/include/linux/io-mapping.h
+++ b/include/linux/io-mapping.h
@@ -100,14 +100,16 @@ io_mapping_unmap_atomic(void __iomem *vaddr)
}
static inline void __iomem *
-io_mapping_map_wc(struct io_mapping *mapping, unsigned long offset)
+io_mapping_map_wc(struct io_mapping *mapping,
+ unsigned long offset,
+ unsigned long size)
{
resource_size_t phys_addr;
BUG_ON(offset >= mapping->size);
phys_addr = mapping->base + offset;
- return ioremap_wc(phys_addr, PAGE_SIZE);
+ return ioremap_wc(phys_addr, size);
}
static inline void
@@ -155,7 +157,9 @@ io_mapping_unmap_atomic(void __iomem *vaddr)
/* Non-atomic map/unmap */
static inline void __iomem *
-io_mapping_map_wc(struct io_mapping *mapping, unsigned long offset)
+io_mapping_map_wc(struct io_mapping *mapping,
+ unsigned long offset,
+ unsigned long size)
{
return ((char __force __iomem *) mapping) + offset;
}
--
2.8.1
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* Re: [PATCH 0/2] sh_eth: couple of software reset bit cleanups
From: David Miller @ 2016-04-26 20:07 UTC (permalink / raw)
To: sergei.shtylyov; +Cc: netdev, linux-renesas-soc
In-Reply-To: <16246598.T4zYgEztZA@wasted.cogentembedded.com>
From: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Date: Sun, 24 Apr 2016 23:42:48 +0300
> Here's a set of 2 patches against DaveM's 'net-next.git' repo. We clean up
> the use of the software reset bits...
>
> [1/2] sh_eth: use EDMR_SRST_GETHER in sh_eth_check_reset()
> [2/2] sh_eth: rename ARSTR register bit
Series applied, thanks.
^ permalink raw reply
* Re: [PATCH RFC net-next] net: dsa: Provide CPU port statistics to master netdev
From: Andrew Lunn @ 2016-04-26 20:13 UTC (permalink / raw)
To: Florian Fainelli; +Cc: netdev, davem, vivien.didelot
In-Reply-To: <571FC532.4060402@gmail.com>
> > Hi Florian
> >
> > Interesting concept. My one concern is that by concatenating the two
> > sets of statistics, we get a name clash. I'm not sure the Marvell
> > switch statistics counters have different names to the Marvell
> > Ethernet driver statistics counters. ethtool does not care, but maybe
> > an SNMP agent using these statistics might not be too happy seeing the
> > same name twice?
>
> That's a very good point, would you agree if we were prefixing the DSA
> CPU port statistics with some kind of name, e.g: cpu_port_<name> or
> something more compact?
Yes, that would be O.K.
It cannot be too long a prefix. The maximum length of the name is
32. The header file is unclear if there must be a NULL at the end. It
looks like the longest switch statistic we have is
RxPkts1024toMaxPktsOctets, i.e. 25 characters. So we only have 6 or 7
characters for the prefix.
Andrew
^ permalink raw reply
* Re: [PATCH] netem: Segment GSO packets on enqueue.
From: Eric Dumazet @ 2016-04-26 20:19 UTC (permalink / raw)
To: Neil Horman; +Cc: netdev, Jamal Hadi Salim, David S. Miller, netem
In-Reply-To: <20160426190026.GB12788@hmsreliant.think-freely.org>
On Tue, 2016-04-26 at 15:00 -0400, Neil Horman wrote:
> I can understand that, but that raises two questions in my mind:
>
> 1) Doesn't that make all the statistical manipulation for netem wrong? That is
> to say, if netem drops 5% of packets, and it happens to drop a GSO packet, its
> actually dropping several, instead of the single one required.
Please take a look at tbf_segment(), where you can find a proper way to
handle this.
Note that for the case q->corrupt is 0, we definitely do not want to
segment TSO packets.
> 2) How are you getting netem to work with GSO at all? The warning is triggered
> for me on every GSO packet, which I think would impact throughput :)
I mostly use netem to add delays and drops.
I never had this bug, since q->corrupt = 0
^ permalink raw reply
* Re: [net-next PATCH 6/8] mlx4: Add support for inner IPv6 checksum offloads and TSO
From: Saeed Mahameed @ 2016-04-26 20:23 UTC (permalink / raw)
To: Alex Duyck
Cc: Tal Alon, Linux Kernel Network Developers, David Miller,
Gal Pressman, Or Gerlitz, Eran Ben Elisha
In-Reply-To: <CAMt9YRqrk51Rx28FiBiR2RM-fern-UuUq7_A+FeZV+mfm_q+zg@mail.gmail.com>
On Tue, Apr 26, 2016 at 6:50 PM, Alex Duyck <aduyck@mirantis.com> wrote:
>
> The setup is pretty straight forward. Basically I left the first port
> in the default namespace and moved the second int a secondary
> namespace referred to below as $netns. I then assigned the IPv6
> addresses fec0::10:1 and fec0::10:2. After that I ran the following:
>
> VXLAN=vx$net
> echo $VXLAN ${test_options[$i]}
> ip link add $VXLAN type vxlan id $net \
> local fec0::10:1 remote $addr6 dev $PF0 \
> ${test_options[$i]} dstport `expr 8800 + $net`
> ip netns exec $netns ip link add $VXLAN type vxlan id $net \
> local $addr6 remote fec0::10:1 dev $port \
> ${test_options[$i]} dstport `expr 8800 + $net`
> ifconfig $VXLAN 192.168.${net}.1/24
> ip netns exec $netns ifconfig $VXLAN 192.168.${net}.2/24
>
Thanks, indeed i see that GSO is not working with vxlan over IPv6 over
mlx5 device.
We will test out those patches on both mlx4 and mlx5, and debug mlx4
IPv6 issue you see.
>
>> Anyway, I suspect it might be related to a driver bug most likely in
>> get_real_size function @en_tx.c
>> specifically in : *lso_header_size = (skb_inner_transport_header(skb) -
>> skb->data) + inner_tcp_hdrlen(skb);
>>
>> will check this and get back to you.
>
> I'm not entirely convinced. What I was seeing is t hat the hardware
> itself was performing Rx checksum offload only on tunnels with an
> outer IPv4 header and ignoring tunnels with an outer IPv6 header.
I don't get it, are you trying to say that the issue is in the RX side ?
what do you mean by ignoring ? Dropping ? or just not validating checksum ?
if so why would you disable GSO and IPv6 checksumming on TX ?
>>> @@ -2431,7 +2435,18 @@ static netdev_features_t
>>> mlx4_en_features_check(struct sk_buff *skb,
>>> netdev_features_t
>>> features)
>>> {
>>> features = vlan_features_check(skb, features);
>>> - return vxlan_features_check(skb, features);
>>> + features = vxlan_features_check(skb, features);
>>> +
>>> + /* The ConnectX-3 doesn't support outer IPv6 checksums but it does
>>> + * support inner IPv6 checksums and segmentation so we need to
>>> + * strip that feature if this is an IPv6 encapsulated frame.
>>> + */
>>> + if (skb->encapsulation &&
>>> + (skb->ip_summed == CHECKSUM_PARTIAL) &&
>>> + (ip_hdr(skb)->version != 4))
>>> + features &= ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
>>
>> Dejavu, didn't you fix this already in harmonize_features, in
>> i.e, it is enough to do here:
>>
>> if (skb->encapsulation && (skb->ip_summed == CHECKSUM_PARTIAL))
>> features &= ~NETIF_F_IPV6_CSUM;
>>
>
> So what this patch is doing is enabling an inner IPv6 header offloads.
> Up above we set the NETIF_F_IPV6_CSUM bit and we want it to stay set
> unless we have an outer IPv6 header because the inner headers may
> still need that bit set. If I did what you suggest it strips IPv6
> checksum support for inner headers and if we have to use GSO partial I
> ended up encountering some of the other bugs that I have fixed for GSO
> partial where either sg or csum are not defined.
>
I see, you mean that you want to disable checksumming and GSO only for
packets with Outer(IPv6):Inner(X) and keep it in case for
Outer(IPv4):Inner(IPv6)
but i think it is weird that the driver decides to disable features it
didn't declare in first place (NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK)
Retry:
if (skb->encapsulation && (skb->ip_summed == CHECKSUM_PARTIAL) &&
(ip_hdr(skb)->version != 4))
features &= ~NETIF_F_IPV6_CSUM;
will this work ?
Anyway i prefer to debug the mlx4 issue first before we discuss the
best approach to disable checksumming & GSO for outer IPv6 in mlx4.
>>
>>> +
>>> + return features;
>>> }
>>> #endif
>>> diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c
>>> b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
>>> index c0d7b7296236..c9f5388ea22a 100644
>>> --- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c
>>> +++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
>>> @@ -41,6 +41,7 @@
>>> #include <linux/vmalloc.h>
>>> #include <linux/tcp.h>
>>> #include <linux/ip.h>
>>> +#include <linux/ipv6.h>
>>> #include <linux/moduleparam.h>
>>> #include "mlx4_en.h"
>>> @@ -918,8 +919,18 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct
>>> net_device *dev)
>>> tx_ind, fragptr);
>>> if (skb->encapsulation) {
>>> - struct iphdr *ipv4 = (struct iphdr
>>> *)skb_inner_network_header(skb);
>>> - if (ipv4->protocol == IPPROTO_TCP || ipv4->protocol ==
>>> IPPROTO_UDP)
>>> + union {
>>> + struct iphdr *v4;
>>> + struct ipv6hdr *v6;
>>> + unsigned char *hdr;
>>> + } ip;
>>> + u8 proto;
>>> +
>>> + ip.hdr = skb_inner_network_header(skb);
>>> + proto = (ip.v4->version == 4) ? ip.v4->protocol :
>>> + ip.v6->nexthdr;
>>> +
>>> + if (proto == IPPROTO_TCP || proto == IPPROTO_UDP)
>>> op_own |= cpu_to_be32(MLX4_WQE_CTRL_IIP |
>>> MLX4_WQE_CTRL_ILP);
>>> else
>>> op_own |= cpu_to_be32(MLX4_WQE_CTRL_IIP);
>>
>>
>> basically this is a bug fix, I don't know why the original author assumed it
>> will be ipv4 !
>
> Because the feature flags didn't allow it any other way. I am adding
> the NETIF_F_TSO6 and NETIF_F_IPV6_CSUM flags in hw_enc_features and so
> situations such as this couldn't be encountered until you start adding
> those flags.
>
True.
Thanks,
- Saeed
^ permalink raw reply
* [PATCH] bpf: fix double-fdput in replace_map_fd_with_map_ptr()
From: Jann Horn @ 2016-04-26 20:26 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Jann Horn
When bpf(BPF_PROG_LOAD, ...) was invoked with a BPF program whose bytecode
references a non-map file descriptor as a map file descriptor, the error
handling code called fdput() twice instead of once (in __bpf_map_get() and
in replace_map_fd_with_map_ptr()). If the file descriptor table of the
current task is shared, this causes f_count to be decremented too much,
allowing the struct file to be freed while it is still in use
(use-after-free). This can be exploited to gain root privileges by an
unprivileged user.
This bug was introduced in
commit 0246e64d9a5f ("bpf: handle pseudo BPF_LD_IMM64 insn"), but is only
exploitable since
commit 1be7f75d1668 ("bpf: enable non-root eBPF programs") because
previously, CAP_SYS_ADMIN was required to reach the vulnerable code.
(posted publicly according to request by maintainer)
Signed-off-by: Jann Horn <jannh@google.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
---
kernel/bpf/verifier.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 2e08f8e..8291251 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -2029,7 +2029,6 @@ static int replace_map_fd_with_map_ptr(struct verifier_env *env)
if (IS_ERR(map)) {
verbose("fd %d is not pointing to valid bpf_map\n",
insn->imm);
- fdput(f);
return PTR_ERR(map);
}
--
2.8.0.rc3.226.g39d4020
^ permalink raw reply related
* [PATCH -next] net: w5100: support W5500
From: Akinobu Mita @ 2016-04-26 20:43 UTC (permalink / raw)
To: netdev; +Cc: Akinobu Mita, Mike Sinkovsky, David S. Miller
This adds support for W5500 chip.
W5500 has similar register and memory organization with W5100 and W5200.
There are a few important differences listed below but it is still
possible to share common code with W5100 and W5200.
* W5500 register and memory are organized by multiple blocks. Each one
is selected by 16bits offset address and 5bits block select bits.
But the existing register access operations take u16 address. This change
extends the addess by u32 address and put offset address to lower 16bits
and block select bits to upper 16bits.
This change also adds the offset addresses for socket register and TX/RX
memory blocks to the driver private data structure in order to reduce
conditional switches for each chip.
* W5500 has the different register offset for socket interrupt mask
register. Newly added internal functions w5100_enable_intr() and
w5100_disable_intr() take care of the diffrence.
* W5500 has the different register offset for retry time-value register.
But this register is only used to verify that the reset value is correctly
read at initialization. So move the verification to w5100_hw_reset()
which already does different things for different chips.
Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
Cc: Mike Sinkovsky <msink@permonline.ru>
Cc: David S. Miller <davem@davemloft.net>
---
drivers/net/ethernet/wiznet/Kconfig | 2 +-
drivers/net/ethernet/wiznet/w5100-spi.c | 192 +++++++++++++++++++++++--
drivers/net/ethernet/wiznet/w5100.c | 243 +++++++++++++++++++++++---------
drivers/net/ethernet/wiznet/w5100.h | 13 +-
4 files changed, 365 insertions(+), 85 deletions(-)
diff --git a/drivers/net/ethernet/wiznet/Kconfig b/drivers/net/ethernet/wiznet/Kconfig
index f3385a1..1981e88c 100644
--- a/drivers/net/ethernet/wiznet/Kconfig
+++ b/drivers/net/ethernet/wiznet/Kconfig
@@ -70,7 +70,7 @@ config WIZNET_BUS_ANY
endchoice
config WIZNET_W5100_SPI
- tristate "WIZnet W5100/W5200 Ethernet support for SPI mode"
+ tristate "WIZnet W5100/W5200/W5500 Ethernet support for SPI mode"
depends on WIZNET_BUS_ANY && WIZNET_W5100
depends on SPI
---help---
diff --git a/drivers/net/ethernet/wiznet/w5100-spi.c b/drivers/net/ethernet/wiznet/w5100-spi.c
index 598a7b0..b868e45 100644
--- a/drivers/net/ethernet/wiznet/w5100-spi.c
+++ b/drivers/net/ethernet/wiznet/w5100-spi.c
@@ -1,5 +1,5 @@
/*
- * Ethernet driver for the WIZnet W5100/W5200 chip.
+ * Ethernet driver for the WIZnet W5100/W5200/W5500 chip.
*
* Copyright (C) 2016 Akinobu Mita <akinobu.mita@gmail.com>
*
@@ -8,6 +8,7 @@
* Datasheet:
* http://www.wiznet.co.kr/wp-content/uploads/wiznethome/Chip/W5100/Document/W5100_Datasheet_v1.2.6.pdf
* http://wiznethome.cafe24.com/wp-content/uploads/wiznethome/Chip/W5200/Documents/W5200_DS_V140E.pdf
+ * http://wizwiki.net/wiki/lib/exe/fetch.php?media=products:w5500:w5500_ds_v106e_141230.pdf
*/
#include <linux/kernel.h>
@@ -21,7 +22,7 @@
#define W5100_SPI_WRITE_OPCODE 0xf0
#define W5100_SPI_READ_OPCODE 0x0f
-static int w5100_spi_read(struct net_device *ndev, u16 addr)
+static int w5100_spi_read(struct net_device *ndev, u32 addr)
{
struct spi_device *spi = to_spi_device(ndev->dev.parent);
u8 cmd[3] = { W5100_SPI_READ_OPCODE, addr >> 8, addr & 0xff };
@@ -33,7 +34,7 @@ static int w5100_spi_read(struct net_device *ndev, u16 addr)
return ret ? ret : data;
}
-static int w5100_spi_write(struct net_device *ndev, u16 addr, u8 data)
+static int w5100_spi_write(struct net_device *ndev, u32 addr, u8 data)
{
struct spi_device *spi = to_spi_device(ndev->dev.parent);
u8 cmd[4] = { W5100_SPI_WRITE_OPCODE, addr >> 8, addr & 0xff, data};
@@ -41,7 +42,7 @@ static int w5100_spi_write(struct net_device *ndev, u16 addr, u8 data)
return spi_write_then_read(spi, cmd, sizeof(cmd), NULL, 0);
}
-static int w5100_spi_read16(struct net_device *ndev, u16 addr)
+static int w5100_spi_read16(struct net_device *ndev, u32 addr)
{
u16 data;
int ret;
@@ -55,7 +56,7 @@ static int w5100_spi_read16(struct net_device *ndev, u16 addr)
return ret < 0 ? ret : data | ret;
}
-static int w5100_spi_write16(struct net_device *ndev, u16 addr, u16 data)
+static int w5100_spi_write16(struct net_device *ndev, u32 addr, u16 data)
{
int ret;
@@ -66,7 +67,7 @@ static int w5100_spi_write16(struct net_device *ndev, u16 addr, u16 data)
return w5100_spi_write(ndev, addr + 1, data & 0xff);
}
-static int w5100_spi_readbulk(struct net_device *ndev, u16 addr, u8 *buf,
+static int w5100_spi_readbulk(struct net_device *ndev, u32 addr, u8 *buf,
int len)
{
int i;
@@ -82,7 +83,7 @@ static int w5100_spi_readbulk(struct net_device *ndev, u16 addr, u8 *buf,
return 0;
}
-static int w5100_spi_writebulk(struct net_device *ndev, u16 addr, const u8 *buf,
+static int w5100_spi_writebulk(struct net_device *ndev, u32 addr, const u8 *buf,
int len)
{
int i;
@@ -134,7 +135,7 @@ static int w5200_spi_init(struct net_device *ndev)
return 0;
}
-static int w5200_spi_read(struct net_device *ndev, u16 addr)
+static int w5200_spi_read(struct net_device *ndev, u32 addr)
{
struct spi_device *spi = to_spi_device(ndev->dev.parent);
u8 cmd[4] = { addr >> 8, addr & 0xff, 0, 1 };
@@ -146,7 +147,7 @@ static int w5200_spi_read(struct net_device *ndev, u16 addr)
return ret ? ret : data;
}
-static int w5200_spi_write(struct net_device *ndev, u16 addr, u8 data)
+static int w5200_spi_write(struct net_device *ndev, u32 addr, u8 data)
{
struct spi_device *spi = to_spi_device(ndev->dev.parent);
u8 cmd[5] = { addr >> 8, addr & 0xff, W5200_SPI_WRITE_OPCODE, 1, data };
@@ -154,7 +155,7 @@ static int w5200_spi_write(struct net_device *ndev, u16 addr, u8 data)
return spi_write_then_read(spi, cmd, sizeof(cmd), NULL, 0);
}
-static int w5200_spi_read16(struct net_device *ndev, u16 addr)
+static int w5200_spi_read16(struct net_device *ndev, u32 addr)
{
struct spi_device *spi = to_spi_device(ndev->dev.parent);
u8 cmd[4] = { addr >> 8, addr & 0xff, 0, 2 };
@@ -166,7 +167,7 @@ static int w5200_spi_read16(struct net_device *ndev, u16 addr)
return ret ? ret : be16_to_cpu(data);
}
-static int w5200_spi_write16(struct net_device *ndev, u16 addr, u16 data)
+static int w5200_spi_write16(struct net_device *ndev, u32 addr, u16 data)
{
struct spi_device *spi = to_spi_device(ndev->dev.parent);
u8 cmd[6] = {
@@ -178,7 +179,7 @@ static int w5200_spi_write16(struct net_device *ndev, u16 addr, u16 data)
return spi_write_then_read(spi, cmd, sizeof(cmd), NULL, 0);
}
-static int w5200_spi_readbulk(struct net_device *ndev, u16 addr, u8 *buf,
+static int w5200_spi_readbulk(struct net_device *ndev, u32 addr, u8 *buf,
int len)
{
struct spi_device *spi = to_spi_device(ndev->dev.parent);
@@ -208,7 +209,7 @@ static int w5200_spi_readbulk(struct net_device *ndev, u16 addr, u8 *buf,
return ret;
}
-static int w5200_spi_writebulk(struct net_device *ndev, u16 addr, const u8 *buf,
+static int w5200_spi_writebulk(struct net_device *ndev, u32 addr, const u8 *buf,
int len)
{
struct spi_device *spi = to_spi_device(ndev->dev.parent);
@@ -250,6 +251,164 @@ static const struct w5100_ops w5200_ops = {
.init = w5200_spi_init,
};
+#define W5500_SPI_BLOCK_SELECT(addr) (((addr) >> 16) & 0x1f)
+#define W5500_SPI_READ_CONTROL(addr) (W5500_SPI_BLOCK_SELECT(addr) << 3)
+#define W5500_SPI_WRITE_CONTROL(addr) \
+ ((W5500_SPI_BLOCK_SELECT(addr) << 3) | BIT(2))
+
+struct w5500_spi_priv {
+ /* Serialize access to cmd_buf */
+ struct mutex cmd_lock;
+
+ /* DMA (thus cache coherency maintenance) requires the
+ * transfer buffers to live in their own cache lines.
+ */
+ u8 cmd_buf[3] ____cacheline_aligned;
+};
+
+static struct w5500_spi_priv *w5500_spi_priv(struct net_device *ndev)
+{
+ return w5100_ops_priv(ndev);
+}
+
+static int w5500_spi_init(struct net_device *ndev)
+{
+ struct w5500_spi_priv *spi_priv = w5500_spi_priv(ndev);
+
+ mutex_init(&spi_priv->cmd_lock);
+
+ return 0;
+}
+
+static int w5500_spi_read(struct net_device *ndev, u32 addr)
+{
+ struct spi_device *spi = to_spi_device(ndev->dev.parent);
+ u8 cmd[3] = {
+ addr >> 8,
+ addr,
+ W5500_SPI_READ_CONTROL(addr)
+ };
+ u8 data;
+ int ret;
+
+ ret = spi_write_then_read(spi, cmd, sizeof(cmd), &data, 1);
+
+ return ret ? ret : data;
+}
+
+static int w5500_spi_write(struct net_device *ndev, u32 addr, u8 data)
+{
+ struct spi_device *spi = to_spi_device(ndev->dev.parent);
+ u8 cmd[4] = {
+ addr >> 8,
+ addr,
+ W5500_SPI_WRITE_CONTROL(addr),
+ data
+ };
+
+ return spi_write_then_read(spi, cmd, sizeof(cmd), NULL, 0);
+}
+
+static int w5500_spi_read16(struct net_device *ndev, u32 addr)
+{
+ struct spi_device *spi = to_spi_device(ndev->dev.parent);
+ u8 cmd[3] = {
+ addr >> 8,
+ addr,
+ W5500_SPI_READ_CONTROL(addr)
+ };
+ __be16 data;
+ int ret;
+
+ ret = spi_write_then_read(spi, cmd, sizeof(cmd), &data, sizeof(data));
+
+ return ret ? ret : be16_to_cpu(data);
+}
+
+static int w5500_spi_write16(struct net_device *ndev, u32 addr, u16 data)
+{
+ struct spi_device *spi = to_spi_device(ndev->dev.parent);
+ u8 cmd[5] = {
+ addr >> 8,
+ addr,
+ W5500_SPI_WRITE_CONTROL(addr),
+ data >> 8,
+ data
+ };
+
+ return spi_write_then_read(spi, cmd, sizeof(cmd), NULL, 0);
+}
+
+static int w5500_spi_readbulk(struct net_device *ndev, u32 addr, u8 *buf,
+ int len)
+{
+ struct spi_device *spi = to_spi_device(ndev->dev.parent);
+ struct w5500_spi_priv *spi_priv = w5500_spi_priv(ndev);
+ struct spi_transfer xfer[] = {
+ {
+ .tx_buf = spi_priv->cmd_buf,
+ .len = sizeof(spi_priv->cmd_buf),
+ },
+ {
+ .rx_buf = buf,
+ .len = len,
+ },
+ };
+ int ret;
+
+ mutex_lock(&spi_priv->cmd_lock);
+
+ spi_priv->cmd_buf[0] = addr >> 8;
+ spi_priv->cmd_buf[1] = addr;
+ spi_priv->cmd_buf[2] = W5500_SPI_READ_CONTROL(addr);
+ ret = spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer));
+
+ mutex_unlock(&spi_priv->cmd_lock);
+
+ return ret;
+}
+
+static int w5500_spi_writebulk(struct net_device *ndev, u32 addr, const u8 *buf,
+ int len)
+{
+ struct spi_device *spi = to_spi_device(ndev->dev.parent);
+ struct w5500_spi_priv *spi_priv = w5500_spi_priv(ndev);
+ struct spi_transfer xfer[] = {
+ {
+ .tx_buf = spi_priv->cmd_buf,
+ .len = sizeof(spi_priv->cmd_buf),
+ },
+ {
+ .tx_buf = buf,
+ .len = len,
+ },
+ };
+ int ret;
+
+ mutex_lock(&spi_priv->cmd_lock);
+
+ spi_priv->cmd_buf[0] = addr >> 8;
+ spi_priv->cmd_buf[1] = addr;
+ spi_priv->cmd_buf[2] = W5500_SPI_WRITE_CONTROL(addr);
+ ret = spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer));
+
+ mutex_unlock(&spi_priv->cmd_lock);
+
+ return ret;
+}
+
+static const struct w5100_ops w5500_ops = {
+ .may_sleep = true,
+ .chip_id = W5500,
+ .read = w5500_spi_read,
+ .write = w5500_spi_write,
+ .read16 = w5500_spi_read16,
+ .write16 = w5500_spi_write16,
+ .readbulk = w5500_spi_readbulk,
+ .writebulk = w5500_spi_writebulk,
+ .init = w5500_spi_init,
+};
+
static int w5100_spi_probe(struct spi_device *spi)
{
const struct spi_device_id *id = spi_get_device_id(spi);
@@ -265,6 +424,10 @@ static int w5100_spi_probe(struct spi_device *spi)
ops = &w5200_ops;
priv_size = sizeof(struct w5200_spi_priv);
break;
+ case W5500:
+ ops = &w5500_ops;
+ priv_size = sizeof(struct w5500_spi_priv);
+ break;
default:
return -EINVAL;
}
@@ -280,6 +443,7 @@ static int w5100_spi_remove(struct spi_device *spi)
static const struct spi_device_id w5100_spi_ids[] = {
{ "w5100", W5100 },
{ "w5200", W5200 },
+ { "w5500", W5500 },
{}
};
MODULE_DEVICE_TABLE(spi, w5100_spi_ids);
@@ -295,6 +459,6 @@ static struct spi_driver w5100_spi_driver = {
};
module_spi_driver(w5100_spi_driver);
-MODULE_DESCRIPTION("WIZnet W5100/W5200 Ethernet driver for SPI mode");
+MODULE_DESCRIPTION("WIZnet W5100/W5200/W5500 Ethernet driver for SPI mode");
MODULE_AUTHOR("Akinobu Mita <akinobu.mita@gmail.com>");
MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/wiznet/w5100.c b/drivers/net/ethernet/wiznet/w5100.c
index 09149c9..8ed0c77 100644
--- a/drivers/net/ethernet/wiznet/w5100.c
+++ b/drivers/net/ethernet/wiznet/w5100.c
@@ -38,7 +38,7 @@ MODULE_ALIAS("platform:"DRV_NAME);
MODULE_LICENSE("GPL");
/*
- * W5100 and W5100 common registers
+ * W5100/W5200/W5500 common registers
*/
#define W5100_COMMON_REGS 0x0000
#define W5100_MR 0x0000 /* Mode Register */
@@ -48,10 +48,6 @@ MODULE_LICENSE("GPL");
#define MR_IND 0x01 /* Indirect mode */
#define W5100_SHAR 0x0009 /* Source MAC address */
#define W5100_IR 0x0015 /* Interrupt Register */
-#define W5100_IMR 0x0016 /* Interrupt Mask Register */
-#define IR_S0 0x01 /* S0 interrupt */
-#define W5100_RTR 0x0017 /* Retry Time-value Register */
-#define RTR_DEFAULT 2000 /* =0x07d0 (2000) */
#define W5100_COMMON_REGS_LEN 0x0040
#define W5100_Sn_MR 0x0000 /* Sn Mode Register */
@@ -64,7 +60,7 @@ MODULE_LICENSE("GPL");
#define W5100_Sn_RX_RSR 0x0026 /* Sn Receive free memory size */
#define W5100_Sn_RX_RD 0x0028 /* Sn Receive memory read pointer */
-#define S0_REGS(priv) (is_w5200(priv) ? W5200_S0_REGS : W5100_S0_REGS)
+#define S0_REGS(priv) ((priv)->s0_regs)
#define W5100_S0_MR(priv) (S0_REGS(priv) + W5100_Sn_MR)
#define S0_MR_MACRAW 0x04 /* MAC RAW mode (promiscuous) */
@@ -88,7 +84,15 @@ MODULE_LICENSE("GPL");
#define W5100_S0_REGS_LEN 0x0040
/*
- * W5100 specific registers
+ * W5100 and W5200 common registers
+ */
+#define W5100_IMR 0x0016 /* Interrupt Mask Register */
+#define IR_S0 0x01 /* S0 interrupt */
+#define W5100_RTR 0x0017 /* Retry Time-value Register */
+#define RTR_DEFAULT 2000 /* =0x07d0 (2000) */
+
+/*
+ * W5100 specific register and memory
*/
#define W5100_RMSR 0x001a /* Receive Memory Size */
#define W5100_TMSR 0x001b /* Transmit Memory Size */
@@ -101,13 +105,12 @@ MODULE_LICENSE("GPL");
#define W5100_RX_MEM_SIZE 0x2000
/*
- * W5200 specific registers
+ * W5200 specific register and memory
*/
#define W5200_S0_REGS 0x4000
#define W5200_Sn_RXMEM_SIZE(n) (0x401e + (n) * 0x0100) /* Sn RX Memory Size */
#define W5200_Sn_TXMEM_SIZE(n) (0x401f + (n) * 0x0100) /* Sn TX Memory Size */
-#define W5200_S0_IMR 0x402c /* S0 Interrupt Mask Register */
#define W5200_TX_MEM_START 0x8000
#define W5200_TX_MEM_SIZE 0x4000
@@ -115,11 +118,44 @@ MODULE_LICENSE("GPL");
#define W5200_RX_MEM_SIZE 0x4000
/*
+ * W5500 specific register and memory
+ *
+ * W5500 register and memory are organized by multiple blocks. Each one is
+ * selected by 16bits offset address and 5bits block select bits. So we
+ * encode it into 32bits address. (lower 16bits is offset address and
+ * upper 16bits is block select bits)
+ */
+#define W5500_SIMR 0x0018 /* Socket Interrupt Mask Register */
+#define W5500_RTR 0x0019 /* Retry Time-value Register */
+
+#define W5500_S0_REGS 0x10000
+
+#define W5500_Sn_RXMEM_SIZE(n) \
+ (0x1001e + (n) * 0x40000) /* Sn RX Memory Size */
+#define W5500_Sn_TXMEM_SIZE(n) \
+ (0x1001f + (n) * 0x40000) /* Sn TX Memory Size */
+
+#define W5500_TX_MEM_START 0x20000
+#define W5500_TX_MEM_SIZE 0x04000
+#define W5500_RX_MEM_START 0x30000
+#define W5500_RX_MEM_SIZE 0x04000
+
+/*
* Device driver private data structure
*/
struct w5100_priv {
const struct w5100_ops *ops;
+
+ /* Socket 0 register offset address */
+ u32 s0_regs;
+ /* Socket 0 TX buffer offset address and size */
+ u32 s0_tx_buf;
+ u16 s0_tx_buf_size;
+ /* Socket 0 RX buffer offset address and size */
+ u32 s0_rx_buf;
+ u16 s0_rx_buf_size;
+
int irq;
int link_irq;
int link_gpio;
@@ -172,12 +208,12 @@ static inline void __iomem *w5100_mmio(struct net_device *ndev)
*
* 0x8000 bytes are required for memory space.
*/
-static inline int w5100_read_direct(struct net_device *ndev, u16 addr)
+static inline int w5100_read_direct(struct net_device *ndev, u32 addr)
{
return ioread8(w5100_mmio(ndev) + (addr << CONFIG_WIZNET_BUS_SHIFT));
}
-static inline int __w5100_write_direct(struct net_device *ndev, u16 addr,
+static inline int __w5100_write_direct(struct net_device *ndev, u32 addr,
u8 data)
{
iowrite8(data, w5100_mmio(ndev) + (addr << CONFIG_WIZNET_BUS_SHIFT));
@@ -185,7 +221,7 @@ static inline int __w5100_write_direct(struct net_device *ndev, u16 addr,
return 0;
}
-static inline int w5100_write_direct(struct net_device *ndev, u16 addr, u8 data)
+static inline int w5100_write_direct(struct net_device *ndev, u32 addr, u8 data)
{
__w5100_write_direct(ndev, addr, data);
mmiowb();
@@ -193,7 +229,7 @@ static inline int w5100_write_direct(struct net_device *ndev, u16 addr, u8 data)
return 0;
}
-static int w5100_read16_direct(struct net_device *ndev, u16 addr)
+static int w5100_read16_direct(struct net_device *ndev, u32 addr)
{
u16 data;
data = w5100_read_direct(ndev, addr) << 8;
@@ -201,7 +237,7 @@ static int w5100_read16_direct(struct net_device *ndev, u16 addr)
return data;
}
-static int w5100_write16_direct(struct net_device *ndev, u16 addr, u16 data)
+static int w5100_write16_direct(struct net_device *ndev, u32 addr, u16 data)
{
__w5100_write_direct(ndev, addr, data >> 8);
__w5100_write_direct(ndev, addr + 1, data);
@@ -210,7 +246,7 @@ static int w5100_write16_direct(struct net_device *ndev, u16 addr, u16 data)
return 0;
}
-static int w5100_readbulk_direct(struct net_device *ndev, u16 addr, u8 *buf,
+static int w5100_readbulk_direct(struct net_device *ndev, u32 addr, u8 *buf,
int len)
{
int i;
@@ -221,7 +257,7 @@ static int w5100_readbulk_direct(struct net_device *ndev, u16 addr, u8 *buf,
return 0;
}
-static int w5100_writebulk_direct(struct net_device *ndev, u16 addr,
+static int w5100_writebulk_direct(struct net_device *ndev, u32 addr,
const u8 *buf, int len)
{
int i;
@@ -275,7 +311,7 @@ static const struct w5100_ops w5100_mmio_direct_ops = {
#define W5100_IDM_AR 0x01 /* Indirect Mode Address Register */
#define W5100_IDM_DR 0x03 /* Indirect Mode Data Register */
-static int w5100_read_indirect(struct net_device *ndev, u16 addr)
+static int w5100_read_indirect(struct net_device *ndev, u32 addr)
{
struct w5100_mmio_priv *mmio_priv = w5100_mmio_priv(ndev);
unsigned long flags;
@@ -289,7 +325,7 @@ static int w5100_read_indirect(struct net_device *ndev, u16 addr)
return data;
}
-static int w5100_write_indirect(struct net_device *ndev, u16 addr, u8 data)
+static int w5100_write_indirect(struct net_device *ndev, u32 addr, u8 data)
{
struct w5100_mmio_priv *mmio_priv = w5100_mmio_priv(ndev);
unsigned long flags;
@@ -302,7 +338,7 @@ static int w5100_write_indirect(struct net_device *ndev, u16 addr, u8 data)
return 0;
}
-static int w5100_read16_indirect(struct net_device *ndev, u16 addr)
+static int w5100_read16_indirect(struct net_device *ndev, u32 addr)
{
struct w5100_mmio_priv *mmio_priv = w5100_mmio_priv(ndev);
unsigned long flags;
@@ -317,7 +353,7 @@ static int w5100_read16_indirect(struct net_device *ndev, u16 addr)
return data;
}
-static int w5100_write16_indirect(struct net_device *ndev, u16 addr, u16 data)
+static int w5100_write16_indirect(struct net_device *ndev, u32 addr, u16 data)
{
struct w5100_mmio_priv *mmio_priv = w5100_mmio_priv(ndev);
unsigned long flags;
@@ -331,7 +367,7 @@ static int w5100_write16_indirect(struct net_device *ndev, u16 addr, u16 data)
return 0;
}
-static int w5100_readbulk_indirect(struct net_device *ndev, u16 addr, u8 *buf,
+static int w5100_readbulk_indirect(struct net_device *ndev, u32 addr, u8 *buf,
int len)
{
struct w5100_mmio_priv *mmio_priv = w5100_mmio_priv(ndev);
@@ -350,7 +386,7 @@ static int w5100_readbulk_indirect(struct net_device *ndev, u16 addr, u8 *buf,
return 0;
}
-static int w5100_writebulk_indirect(struct net_device *ndev, u16 addr,
+static int w5100_writebulk_indirect(struct net_device *ndev, u32 addr,
const u8 *buf, int len)
{
struct w5100_mmio_priv *mmio_priv = w5100_mmio_priv(ndev);
@@ -392,32 +428,32 @@ static const struct w5100_ops w5100_mmio_indirect_ops = {
#if defined(CONFIG_WIZNET_BUS_DIRECT)
-static int w5100_read(struct w5100_priv *priv, u16 addr)
+static int w5100_read(struct w5100_priv *priv, u32 addr)
{
return w5100_read_direct(priv->ndev, addr);
}
-static int w5100_write(struct w5100_priv *priv, u16 addr, u8 data)
+static int w5100_write(struct w5100_priv *priv, u32 addr, u8 data)
{
return w5100_write_direct(priv->ndev, addr, data);
}
-static int w5100_read16(struct w5100_priv *priv, u16 addr)
+static int w5100_read16(struct w5100_priv *priv, u32 addr)
{
return w5100_read16_direct(priv->ndev, addr);
}
-static int w5100_write16(struct w5100_priv *priv, u16 addr, u16 data)
+static int w5100_write16(struct w5100_priv *priv, u32 addr, u16 data)
{
return w5100_write16_direct(priv->ndev, addr, data);
}
-static int w5100_readbulk(struct w5100_priv *priv, u16 addr, u8 *buf, int len)
+static int w5100_readbulk(struct w5100_priv *priv, u32 addr, u8 *buf, int len)
{
return w5100_readbulk_direct(priv->ndev, addr, buf, len);
}
-static int w5100_writebulk(struct w5100_priv *priv, u16 addr, const u8 *buf,
+static int w5100_writebulk(struct w5100_priv *priv, u32 addr, const u8 *buf,
int len)
{
return w5100_writebulk_direct(priv->ndev, addr, buf, len);
@@ -425,32 +461,32 @@ static int w5100_writebulk(struct w5100_priv *priv, u16 addr, const u8 *buf,
#elif defined(CONFIG_WIZNET_BUS_INDIRECT)
-static int w5100_read(struct w5100_priv *priv, u16 addr)
+static int w5100_read(struct w5100_priv *priv, u32 addr)
{
return w5100_read_indirect(priv->ndev, addr);
}
-static int w5100_write(struct w5100_priv *priv, u16 addr, u8 data)
+static int w5100_write(struct w5100_priv *priv, u32 addr, u8 data)
{
return w5100_write_indirect(priv->ndev, addr, data);
}
-static int w5100_read16(struct w5100_priv *priv, u16 addr)
+static int w5100_read16(struct w5100_priv *priv, u32 addr)
{
return w5100_read16_indirect(priv->ndev, addr);
}
-static int w5100_write16(struct w5100_priv *priv, u16 addr, u16 data)
+static int w5100_write16(struct w5100_priv *priv, u32 addr, u16 data)
{
return w5100_write16_indirect(priv->ndev, addr, data);
}
-static int w5100_readbulk(struct w5100_priv *priv, u16 addr, u8 *buf, int len)
+static int w5100_readbulk(struct w5100_priv *priv, u32 addr, u8 *buf, int len)
{
return w5100_readbulk_indirect(priv->ndev, addr, buf, len);
}
-static int w5100_writebulk(struct w5100_priv *priv, u16 addr, const u8 *buf,
+static int w5100_writebulk(struct w5100_priv *priv, u32 addr, const u8 *buf,
int len)
{
return w5100_writebulk_indirect(priv->ndev, addr, buf, len);
@@ -458,32 +494,32 @@ static int w5100_writebulk(struct w5100_priv *priv, u16 addr, const u8 *buf,
#else /* CONFIG_WIZNET_BUS_ANY */
-static int w5100_read(struct w5100_priv *priv, u16 addr)
+static int w5100_read(struct w5100_priv *priv, u32 addr)
{
return priv->ops->read(priv->ndev, addr);
}
-static int w5100_write(struct w5100_priv *priv, u16 addr, u8 data)
+static int w5100_write(struct w5100_priv *priv, u32 addr, u8 data)
{
return priv->ops->write(priv->ndev, addr, data);
}
-static int w5100_read16(struct w5100_priv *priv, u16 addr)
+static int w5100_read16(struct w5100_priv *priv, u32 addr)
{
return priv->ops->read16(priv->ndev, addr);
}
-static int w5100_write16(struct w5100_priv *priv, u16 addr, u16 data)
+static int w5100_write16(struct w5100_priv *priv, u32 addr, u16 data)
{
return priv->ops->write16(priv->ndev, addr, data);
}
-static int w5100_readbulk(struct w5100_priv *priv, u16 addr, u8 *buf, int len)
+static int w5100_readbulk(struct w5100_priv *priv, u32 addr, u8 *buf, int len)
{
return priv->ops->readbulk(priv->ndev, addr, buf, len);
}
-static int w5100_writebulk(struct w5100_priv *priv, u16 addr, const u8 *buf,
+static int w5100_writebulk(struct w5100_priv *priv, u32 addr, const u8 *buf,
int len)
{
return priv->ops->writebulk(priv->ndev, addr, buf, len);
@@ -493,13 +529,11 @@ static int w5100_writebulk(struct w5100_priv *priv, u16 addr, const u8 *buf,
static int w5100_readbuf(struct w5100_priv *priv, u16 offset, u8 *buf, int len)
{
- u16 addr;
+ u32 addr;
int remain = 0;
int ret;
- const u16 mem_start =
- is_w5200(priv) ? W5200_RX_MEM_START : W5100_RX_MEM_START;
- const u16 mem_size =
- is_w5200(priv) ? W5200_RX_MEM_SIZE : W5100_RX_MEM_SIZE;
+ const u32 mem_start = priv->s0_rx_buf;
+ const u16 mem_size = priv->s0_rx_buf_size;
offset %= mem_size;
addr = mem_start + offset;
@@ -519,13 +553,11 @@ static int w5100_readbuf(struct w5100_priv *priv, u16 offset, u8 *buf, int len)
static int w5100_writebuf(struct w5100_priv *priv, u16 offset, const u8 *buf,
int len)
{
- u16 addr;
+ u32 addr;
int ret;
int remain = 0;
- const u16 mem_start =
- is_w5200(priv) ? W5200_TX_MEM_START : W5100_TX_MEM_START;
- const u16 mem_size =
- is_w5200(priv) ? W5200_TX_MEM_SIZE : W5100_TX_MEM_SIZE;
+ const u32 mem_start = priv->s0_tx_buf;
+ const u16 mem_size = priv->s0_tx_buf_size;
offset %= mem_size;
addr = mem_start + offset;
@@ -578,6 +610,28 @@ static void w5100_write_macaddr(struct w5100_priv *priv)
w5100_writebulk(priv, W5100_SHAR, ndev->dev_addr, ETH_ALEN);
}
+static void w5100_socket_intr_mask(struct w5100_priv *priv, u8 mask)
+{
+ u32 imr;
+
+ if (priv->ops->chip_id == W5500)
+ imr = W5500_SIMR;
+ else
+ imr = W5100_IMR;
+
+ w5100_write(priv, imr, mask);
+}
+
+static void w5100_enable_intr(struct w5100_priv *priv)
+{
+ w5100_socket_intr_mask(priv, IR_S0);
+}
+
+static void w5100_disable_intr(struct w5100_priv *priv)
+{
+ w5100_socket_intr_mask(priv, 0);
+}
+
static void w5100_memory_configure(struct w5100_priv *priv)
{
/* Configure 16K of internal memory
@@ -603,17 +657,52 @@ static void w5200_memory_configure(struct w5100_priv *priv)
}
}
-static void w5100_hw_reset(struct w5100_priv *priv)
+static void w5500_memory_configure(struct w5100_priv *priv)
{
+ int i;
+
+ /* Configure internal RX memory as 16K RX buffer and
+ * internal TX memory as 16K TX buffer
+ */
+ w5100_write(priv, W5500_Sn_RXMEM_SIZE(0), 0x10);
+ w5100_write(priv, W5500_Sn_TXMEM_SIZE(0), 0x10);
+
+ for (i = 1; i < 8; i++) {
+ w5100_write(priv, W5500_Sn_RXMEM_SIZE(i), 0);
+ w5100_write(priv, W5500_Sn_TXMEM_SIZE(i), 0);
+ }
+}
+
+static int w5100_hw_reset(struct w5100_priv *priv)
+{
+ u32 rtr;
+
w5100_reset(priv);
- w5100_write(priv, W5100_IMR, 0);
+ w5100_disable_intr(priv);
w5100_write_macaddr(priv);
- if (is_w5200(priv))
- w5200_memory_configure(priv);
- else
+ switch (priv->ops->chip_id) {
+ case W5100:
w5100_memory_configure(priv);
+ rtr = W5100_RTR;
+ break;
+ case W5200:
+ w5200_memory_configure(priv);
+ rtr = W5100_RTR;
+ break;
+ case W5500:
+ w5500_memory_configure(priv);
+ rtr = W5500_RTR;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (w5100_read16(priv, rtr) != RTR_DEFAULT)
+ return -ENODEV;
+
+ return 0;
}
static void w5100_hw_start(struct w5100_priv *priv)
@@ -621,12 +710,12 @@ static void w5100_hw_start(struct w5100_priv *priv)
w5100_write(priv, W5100_S0_MR(priv), priv->promisc ?
S0_MR_MACRAW : S0_MR_MACRAW_MF);
w5100_command(priv, S0_CR_OPEN);
- w5100_write(priv, W5100_IMR, IR_S0);
+ w5100_enable_intr(priv);
}
static void w5100_hw_close(struct w5100_priv *priv)
{
- w5100_write(priv, W5100_IMR, 0);
+ w5100_disable_intr(priv);
w5100_command(priv, S0_CR_CLOSE);
}
@@ -805,7 +894,7 @@ static void w5100_rx_work(struct work_struct *work)
while ((skb = w5100_rx_skb(priv->ndev)))
netif_rx_ni(skb);
- w5100_write(priv, W5100_IMR, IR_S0);
+ w5100_enable_intr(priv);
}
static int w5100_napi_poll(struct napi_struct *napi, int budget)
@@ -824,7 +913,7 @@ static int w5100_napi_poll(struct napi_struct *napi, int budget)
if (rx_count < budget) {
napi_complete(napi);
- w5100_write(priv, W5100_IMR, IR_S0);
+ w5100_enable_intr(priv);
}
return rx_count;
@@ -846,7 +935,7 @@ static irqreturn_t w5100_interrupt(int irq, void *ndev_instance)
}
if (ir & S0_IR_RECV) {
- w5100_write(priv, W5100_IMR, 0);
+ w5100_disable_intr(priv);
if (priv->ops->may_sleep)
queue_work(priv->xfer_wq, &priv->rx_work);
@@ -1014,6 +1103,34 @@ int w5100_probe(struct device *dev, const struct w5100_ops *ops,
SET_NETDEV_DEV(ndev, dev);
dev_set_drvdata(dev, ndev);
priv = netdev_priv(ndev);
+
+ switch (ops->chip_id) {
+ case W5100:
+ priv->s0_regs = W5100_S0_REGS;
+ priv->s0_tx_buf = W5100_TX_MEM_START;
+ priv->s0_tx_buf_size = W5100_TX_MEM_SIZE;
+ priv->s0_rx_buf = W5100_RX_MEM_START;
+ priv->s0_rx_buf_size = W5100_RX_MEM_SIZE;
+ break;
+ case W5200:
+ priv->s0_regs = W5200_S0_REGS;
+ priv->s0_tx_buf = W5200_TX_MEM_START;
+ priv->s0_tx_buf_size = W5200_TX_MEM_SIZE;
+ priv->s0_rx_buf = W5200_RX_MEM_START;
+ priv->s0_rx_buf_size = W5200_RX_MEM_SIZE;
+ break;
+ case W5500:
+ priv->s0_regs = W5500_S0_REGS;
+ priv->s0_tx_buf = W5500_TX_MEM_START;
+ priv->s0_tx_buf_size = W5500_TX_MEM_SIZE;
+ priv->s0_rx_buf = W5500_RX_MEM_START;
+ priv->s0_rx_buf_size = W5500_RX_MEM_SIZE;
+ break;
+ default:
+ err = -EINVAL;
+ goto err_register;
+ }
+
priv->ndev = ndev;
priv->ops = ops;
priv->irq = irq;
@@ -1055,11 +1172,9 @@ int w5100_probe(struct device *dev, const struct w5100_ops *ops,
goto err_hw;
}
- w5100_hw_reset(priv);
- if (w5100_read16(priv, W5100_RTR) != RTR_DEFAULT) {
- err = -ENODEV;
+ err = w5100_hw_reset(priv);
+ if (err)
goto err_hw;
- }
if (ops->may_sleep) {
err = request_threaded_irq(priv->irq, NULL, w5100_interrupt,
diff --git a/drivers/net/ethernet/wiznet/w5100.h b/drivers/net/ethernet/wiznet/w5100.h
index 9b1fa23..f8a16fa 100644
--- a/drivers/net/ethernet/wiznet/w5100.h
+++ b/drivers/net/ethernet/wiznet/w5100.h
@@ -10,17 +10,18 @@
enum {
W5100,
W5200,
+ W5500,
};
struct w5100_ops {
bool may_sleep;
int chip_id;
- int (*read)(struct net_device *ndev, u16 addr);
- int (*write)(struct net_device *ndev, u16 addr, u8 data);
- int (*read16)(struct net_device *ndev, u16 addr);
- int (*write16)(struct net_device *ndev, u16 addr, u16 data);
- int (*readbulk)(struct net_device *ndev, u16 addr, u8 *buf, int len);
- int (*writebulk)(struct net_device *ndev, u16 addr, const u8 *buf,
+ int (*read)(struct net_device *ndev, u32 addr);
+ int (*write)(struct net_device *ndev, u32 addr, u8 data);
+ int (*read16)(struct net_device *ndev, u32 addr);
+ int (*write16)(struct net_device *ndev, u32 addr, u16 data);
+ int (*readbulk)(struct net_device *ndev, u32 addr, u8 *buf, int len);
+ int (*writebulk)(struct net_device *ndev, u32 addr, const u8 *buf,
int len);
int (*reset)(struct net_device *ndev);
int (*init)(struct net_device *ndev);
--
2.5.0
^ permalink raw reply related
* Re: [PATCH] bpf: fix double-fdput in replace_map_fd_with_map_ptr()
From: Alexei Starovoitov @ 2016-04-26 20:44 UTC (permalink / raw)
To: Jann Horn; +Cc: David Miller, netdev
In-Reply-To: <1461702386-17490-1-git-send-email-jannh@google.com>
On Tue, Apr 26, 2016 at 10:26:26PM +0200, Jann Horn wrote:
> When bpf(BPF_PROG_LOAD, ...) was invoked with a BPF program whose bytecode
> references a non-map file descriptor as a map file descriptor, the error
> handling code called fdput() twice instead of once (in __bpf_map_get() and
> in replace_map_fd_with_map_ptr()). If the file descriptor table of the
> current task is shared, this causes f_count to be decremented too much,
> allowing the struct file to be freed while it is still in use
> (use-after-free). This can be exploited to gain root privileges by an
> unprivileged user.
>
> This bug was introduced in
> commit 0246e64d9a5f ("bpf: handle pseudo BPF_LD_IMM64 insn"), but is only
> exploitable since
> commit 1be7f75d1668 ("bpf: enable non-root eBPF programs") because
> previously, CAP_SYS_ADMIN was required to reach the vulnerable code.
>
> (posted publicly according to request by maintainer)
>
> Signed-off-by: Jann Horn <jannh@google.com>
> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Acked-by: Alexei Starovoitov <ast@kernel.org>
^ permalink raw reply
* Re: [PATCH] bpf: fix double-fdput in replace_map_fd_with_map_ptr()
From: Daniel Borkmann @ 2016-04-26 20:48 UTC (permalink / raw)
To: Jann Horn, David Miller; +Cc: netdev, alexei.starovoitov
In-Reply-To: <1461702386-17490-1-git-send-email-jannh@google.com>
On 04/26/2016 10:26 PM, Jann Horn wrote:
> When bpf(BPF_PROG_LOAD, ...) was invoked with a BPF program whose bytecode
> references a non-map file descriptor as a map file descriptor, the error
> handling code called fdput() twice instead of once (in __bpf_map_get() and
> in replace_map_fd_with_map_ptr()). If the file descriptor table of the
> current task is shared, this causes f_count to be decremented too much,
> allowing the struct file to be freed while it is still in use
> (use-after-free). This can be exploited to gain root privileges by an
> unprivileged user.
>
> This bug was introduced in
> commit 0246e64d9a5f ("bpf: handle pseudo BPF_LD_IMM64 insn"), but is only
> exploitable since
> commit 1be7f75d1668 ("bpf: enable non-root eBPF programs") because
> previously, CAP_SYS_ADMIN was required to reach the vulnerable code.
>
> (posted publicly according to request by maintainer)
>
> Signed-off-by: Jann Horn <jannh@google.com>
> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
Thanks!
^ permalink raw reply
* Re: [PATCH net-next V1 00/11] Mellanox 100G extending mlx5 ethtool support
From: Saeed Mahameed @ 2016-04-26 20:55 UTC (permalink / raw)
To: David Miller
Cc: Saeed Mahameed, Linux Netdev List, Or Gerlitz, Tal Alon,
Eran Ben Elisha
In-Reply-To: <20160426.160301.938979848864279754.davem@davemloft.net>
On Tue, Apr 26, 2016 at 11:03 PM, David Miller <davem@davemloft.net> wrote:
>
> Series applied.
>
> Be careful about what feature update semantics you implement. If you get a request
> to change multiple feature bits, and even one of them cannot be done, the entire
> update operation should fail and the bits should revert to what they were before
> the request.
It will be a nightmare to rollback in such case. What if the rollback failed ?
>
> Is that how the code behaves now?
>
Not exactly. If the set/clear of Bit(I) is performed successfully we
set/clear that feature in dev->features ourselves,
and if one fails we return a negative error code so
__netdev_update_features will notify on the failure, but we will be
left with the features that we did success to modify.
__netdev_update_features@net/core/dev.c
if (unlikely(err < 0)) {
netdev_err(dev,
"set_features() failed (%d); wanted %pNF, left %pNF\n",
err, &features, &dev->features);
/* return non-0 since some features might have changed and
* it's better to fire a spurious notification than miss it
*/
return -1;
}
>From this I understand it is ok to update the dev->features inside the
device's set_features NDO and return a negative value in case of
failure,
and a notification on changed features will be fired in anycase.
Is this a correct assumption ?
Anyhow if you think this behavior should be fixed, we will fix it.
Failures at set_features should be rare and should be debugged rather
than ignored.
Saeed.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox