* stmmac regression on ASUS TinkerBoard
From: Katsuhiro Suzuki @ 2019-06-23 14:14 UTC (permalink / raw)
To: Giuseppe Cavallaro, Alexandre Torgue, Jose Abreu, Maxime Coquelin,
netdev
Cc: Andrew Lunn, Heiko Stuebner, linux-arm-kernel,
Linux Kernel Mailing List
Hello stmmac maintainers,
I found this commit and that has some regressions:
74371272f97f net: stmmac: Convert to phylink and remove phylib logic
My environment is:
- ASUS TinkerBoard
- SoC is RK3288
- Using STMMAC driver
drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
- Using this device-tree
arch/arm/boot/dts/rk3288.dtsi ('gmac: ethernet@ff290000' node)
Current linux-next on my environment, 'ifconfig eth0 up' does not work
correctly with following message...
-----
root@linaro-alip:~# ifconfig eth0 up
[ 105.028916] rk_gmac-dwmac ff290000.ethernet eth0: stmmac_open: Cannot
attach to PHY (error: -19)
SIOCSIFFLAGS: No such device
-----
I checked drivers/net/ethernet/stmicro/stmmac/stmmac_main.c and found
stmmac_init_phy() is going to fail if ethernet device node does not
have following property:
- phy-handle
- phy
- phy-device
This commit broke the device-trees such as TinkerBoard. The mdio
subnode creating a mdio bus is changed to required or still optional?
Best Regards,
Katsuhiro Suzuki
^ permalink raw reply
* Re: [RFC V1 net-next 1/1] net: ena: implement XDP drop support
From: Maciej Fijalkowski @ 2019-06-23 14:51 UTC (permalink / raw)
To: sameehj
Cc: davem, netdev, dwmw, zorik, matua, saeedb, msw, aliguori, nafea,
gtzalik, netanel, alisaidi, benh, akiyano
In-Reply-To: <20190623070649.18447-2-sameehj@amazon.com>
On Sun, 23 Jun 2019 10:06:49 +0300
<sameehj@amazon.com> wrote:
> From: Sameeh Jubran <sameehj@amazon.com>
>
> This commit implements the basic functionality of drop/pass logic in the
> ena driver.
>
> Signed-off-by: Sameeh Jubran <sameehj@amazon.com>
> ---
> drivers/net/ethernet/amazon/ena/ena_netdev.c | 83 +++++++++++++++++++-
> drivers/net/ethernet/amazon/ena/ena_netdev.h | 29 +++++++
> 2 files changed, 111 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c
> index 20ec8ff03..3d65c0771 100644
> --- a/drivers/net/ethernet/amazon/ena/ena_netdev.c
> +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c
> @@ -33,10 +33,10 @@
> #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
>
> #ifdef CONFIG_RFS_ACCEL
> +#include <linux/bpf_trace.h>
> #include <linux/cpu_rmap.h>
> #endif /* CONFIG_RFS_ACCEL */
> #include <linux/ethtool.h>
> -#include <linux/if_vlan.h>
> #include <linux/kernel.h>
> #include <linux/module.h>
> #include <linux/numa.h>
> @@ -105,11 +105,82 @@ static void update_rx_ring_mtu(struct ena_adapter *adapter, int mtu)
> adapter->rx_ring[i].mtu = mtu;
> }
>
> +static int ena_xdp_execute(struct ena_ring *rx_ring, struct xdp_buff *xdp)
> +{
> + struct bpf_prog *xdp_prog = rx_ring->xdp_bpf_prog;
> + u32 verdict = XDP_PASS;
> +
> + rcu_read_lock();
> +
> + if (!xdp_prog)
> + goto out;
> +
> + verdict = bpf_prog_run_xdp(xdp_prog, xdp);
> +
> + if (unlikely(verdict == XDP_ABORTED))
> + trace_xdp_exception(rx_ring->netdev, xdp_prog, verdict);
> + else if (unlikely(verdict > XDP_REDIRECT))
Shouldn't this be verdict >= XDP_TX at this point? You're not providing XDP TX
resources in this patch and you're saying that only drop/pass actions are
supported.
> + bpf_warn_invalid_xdp_action(verdict);
> +out:
> + rcu_read_unlock();
> + return verdict;
> +}
> +
> +static int ena_xdp_set(struct net_device *netdev, struct bpf_prog *prog)
> +{
> + struct ena_adapter *adapter = netdev_priv(netdev);
> + struct bpf_prog *old_bpf_prog;
> + int i;
> +
> + if (ena_xdp_allowed(adapter)) {
> + old_bpf_prog = xchg(&adapter->xdp_bpf_prog, prog);
> +
> + for (i = 0; i < adapter->num_queues; i++)
> + xchg(&adapter->rx_ring[i].xdp_bpf_prog, prog);
> +
> + if (old_bpf_prog)
> + bpf_prog_put(old_bpf_prog);
> +
> + } else {
> + netif_err(adapter, drv, adapter->netdev, "Failed to set xdp program, the current MTU (%d) is larger than the maximal allowed MTU (%lu) while xdp is on",
> + netdev->mtu, ENA_XDP_MAX_MTU);
Consider using netlink's extack mechanism. Downside of this approach is that you
can't use format specifiers, so you won't tell user about the max allowed mtu
size for XDP case, but OTOH the message is printed right in front of user's
face in console, no need to look into dmesg.
> + return -EFAULT;
> + }
> +
> + return 0;
> +}
> +
> +/* This is the main xdp callback, it's used by the kernel to set/unset the xdp
> + * program as well as to query the current xdp program id.
> + */
> +static int ena_xdp(struct net_device *netdev, struct netdev_bpf *bpf)
> +{
> + struct ena_adapter *adapter = netdev_priv(netdev);
> +
> + switch (bpf->command) {
> + case XDP_SETUP_PROG:
> + return ena_xdp_set(netdev, bpf->prog);
> + case XDP_QUERY_PROG:
> + bpf->prog_id = adapter->xdp_bpf_prog ?
> + adapter->xdp_bpf_prog->aux->id : 0;
> + break;
> + default:
Again, consider the following:
NL_SET_ERR_MSG_MOD(bpf->extack, "Unsupported XDP command");
> + return -EINVAL;
> + }
> + return 0;
> +}
> +
> static int ena_change_mtu(struct net_device *dev, int new_mtu)
> {
> struct ena_adapter *adapter = netdev_priv(dev);
> int ret;
>
> + if (new_mtu > ENA_XDP_MAX_MTU && ena_xdp_present(adapter)) {
> + netif_err(adapter, drv, dev,
> + "Requested MTU value is not valid while xdp is enabled new_mtu: %d max mtu: %lu min mtu: %d\n",
> + new_mtu, ENA_XDP_MAX_MTU, ENA_MIN_MTU);
> + return -EINVAL;
> + }
> ret = ena_com_set_dev_mtu(adapter->ena_dev, new_mtu);
> if (!ret) {
> netif_dbg(adapter, drv, dev, "set MTU to %d\n", new_mtu);
> @@ -888,6 +959,15 @@ static struct sk_buff *ena_rx_skb(struct ena_ring *rx_ring,
> va = page_address(rx_info->page) + rx_info->page_offset;
> prefetch(va + NET_IP_ALIGN);
>
> + if (ena_xdp_present_ring(rx_ring)) {
> + rx_ring->xdp.data = va;
> + rx_ring->xdp.data_meta = rx_ring->xdp.data;
> + rx_ring->xdp.data_hard_start = rx_ring->xdp.data -
> + rx_info->page_offset;
> + rx_ring->xdp.data_end = rx_ring->xdp.data + len;
> + if (ena_xdp_execute(rx_ring, &rx_ring->xdp) != XDP_PASS)
> + return NULL;
> + }
Hmm running XDP program within the function that is supposed to handle skb
seems a bit not intuitive. Couldn't you have this logic before the ena_rx_skb()
call in ena_clean_rx_irq?
Another thing, from performance perspective IMO it would be better to operate on
local struct xdp_buff, rather than accessing it from rx_ring.
> if (len <= rx_ring->rx_copybreak) {
> skb = ena_alloc_skb(rx_ring, false);
> if (unlikely(!skb))
> @@ -2549,6 +2629,7 @@ static const struct net_device_ops ena_netdev_ops = {
> .ndo_change_mtu = ena_change_mtu,
> .ndo_set_mac_address = NULL,
> .ndo_validate_addr = eth_validate_addr,
> + .ndo_bpf = ena_xdp,
> };
>
> static int ena_device_validate_params(struct ena_adapter *adapter,
> diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.h b/drivers/net/ethernet/amazon/ena/ena_netdev.h
> index f2b6e2e05..e17965f7a 100644
> --- a/drivers/net/ethernet/amazon/ena/ena_netdev.h
> +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.h
> @@ -35,6 +35,7 @@
>
> #include <linux/bitops.h>
> #include <linux/etherdevice.h>
> +#include <linux/if_vlan.h>
> #include <linux/inetdevice.h>
> #include <linux/interrupt.h>
> #include <linux/netdevice.h>
> @@ -139,6 +140,14 @@
>
> #define ENA_MMIO_DISABLE_REG_READ BIT(0)
>
> +/* The max MTU size is configured to be the ethernet frame without the overhead
> + * of the ethernet header, which can have VLAN header, and the frame check
> + * sequence (FCS).
> + * The buffer sizes we share with the device are defined to be ENA_PAGE_SIZE
> + */
> +#define ENA_XDP_MAX_MTU (ENA_PAGE_SIZE - ETH_HLEN - ETH_FCS_LEN - \
> + VLAN_HLEN)
> +
> struct ena_irq {
> irq_handler_t handler;
> void *data;
> @@ -288,6 +297,8 @@ struct ena_ring {
>
> u8 *push_buf_intermediate_buf;
> int empty_rx_queue;
> + struct bpf_prog *xdp_bpf_prog;
> + struct xdp_buff xdp;
> } ____cacheline_aligned;
>
> struct ena_stats_dev {
> @@ -380,6 +391,9 @@ struct ena_adapter {
> enum ena_regs_reset_reason_types reset_reason;
>
> u8 ena_extra_properties_count;
> +
> + /* XDP structures */
> + struct bpf_prog *xdp_bpf_prog;
> };
>
> void ena_set_ethtool_ops(struct net_device *netdev);
> @@ -394,4 +408,19 @@ int ena_update_queue_sizes(struct ena_adapter *adapter,
>
> int ena_get_sset_count(struct net_device *netdev, int sset);
>
> +static inline bool ena_xdp_present(struct ena_adapter *adapter)
> +{
> + return !!adapter->xdp_bpf_prog;
> +}
> +
> +static inline bool ena_xdp_present_ring(struct ena_ring *ring)
> +{
> + return !!ring->xdp_bpf_prog;
> +}
> +
> +static inline bool ena_xdp_allowed(struct ena_adapter *adapter)
> +{
> + return adapter->netdev->mtu <= ENA_XDP_MAX_MTU;
> +}
> +
> #endif /* !(ENA_H) */
^ permalink raw reply
* Re: [PATCH v2 net] af_packet: Block execution of tasks waiting for transmit to complete in AF_PACKET
From: Willem de Bruijn @ 2019-06-23 14:39 UTC (permalink / raw)
To: Neil Horman; +Cc: Network Development, Matteo Croce, David S. Miller
In-Reply-To: <20190623114021.GB10908@hmswarspite.think-freely.org>
On Sun, Jun 23, 2019 at 7:40 AM Neil Horman <nhorman@tuxdriver.com> wrote:
>
> On Sat, Jun 22, 2019 at 10:21:31PM -0400, Willem de Bruijn wrote:
> > > > -static void __packet_set_status(struct packet_sock *po, void *frame, int status)
> > > > +static void __packet_set_status(struct packet_sock *po, void *frame, int status,
> > > > + bool call_complete)
> > > > {
> > > > union tpacket_uhdr h;
> > > >
> > > > @@ -381,6 +382,8 @@ static void __packet_set_status(struct packet_sock *po, void *frame, int status)
> > > > BUG();
> > > > }
> > > >
> > > > + if (po->wait_on_complete && call_complete)
> > > > + complete(&po->skb_completion);
> > >
> > > This wake need not happen before the barrier. Only one caller of
> > > __packet_set_status passes call_complete (tpacket_destruct_skb).
> > > Moving this branch to the caller avoids a lot of code churn.
> > >
> > > Also, multiple packets may be released before the process is awoken.
> > > The process will block until packet_read_pending drops to zero. Can
> > > defer the wait_on_complete to that one instance.
> >
> > Eh no. The point of having this sleep in the send loop is that
> > additional slots may be released for transmission (flipped to
> > TP_STATUS_SEND_REQUEST) from another thread while this thread is
> > waiting.
> >
> Thats incorrect. The entirety of tpacket_snd is protected by a mutex. No other
> thread can alter the state of the frames in the vector from the kernel send path
> while this thread is waiting.
I meant another user thread updating the memory mapped ring contents.
> > Else, it would have been much simpler to move the wait below the send
> > loop: send as many packets as possible, then wait for all of them
> > having been released. Much clearer control flow.
> >
> Thats (almost) what happens now. The only difference is that with this
> implementation, the waiting thread has the opportunity to see if userspace has
> queued more frames for transmission during the wait period. We could
> potentially change that, but thats outside the scope of this fix.
Agreed. I think the current, more complex, behavior was intentional.
We could still restructure to move it out of the loop and jump back.
But, yes, definitely out of scope for a fix.
> > Where to set and clear the wait_on_complete boolean remains. Integer
> > assignment is fragile, as the compiler and processor may optimize or
> > move simple seemingly independent operations. As complete() takes a
> > spinlock, avoiding that in the DONTWAIT case is worthwhile. But probably
> > still preferable to set when beginning waiting and clear when calling
> > complete.
> We avoid any call to wait_for_complete or complete already, based on the gating
> of the need_wait variable in tpacket_snd. If the transmitting thread doesn't
> set MSG_DONTWAIT in the flags of the msg structure, we will never set
> wait_for_complete, and so we will never manipulate the completion queue.
But we don't know the state of this at tpacket_destruct_skb time without
wait_for_completion?
^ permalink raw reply
* Re: [RFC V1 net-next 1/1] net: ena: implement XDP drop support
From: David Ahern @ 2019-06-23 14:28 UTC (permalink / raw)
To: sameehj, davem, netdev
Cc: dwmw, zorik, matua, saeedb, msw, aliguori, nafea, gtzalik,
netanel, alisaidi, benh, akiyano
In-Reply-To: <20190623070649.18447-2-sameehj@amazon.com>
On 6/23/19 1:06 AM, sameehj@amazon.com wrote:
> +static int ena_xdp_set(struct net_device *netdev, struct bpf_prog *prog)
> +{
> + struct ena_adapter *adapter = netdev_priv(netdev);
> + struct bpf_prog *old_bpf_prog;
> + int i;
> +
> + if (ena_xdp_allowed(adapter)) {
> + old_bpf_prog = xchg(&adapter->xdp_bpf_prog, prog);
> +
> + for (i = 0; i < adapter->num_queues; i++)
> + xchg(&adapter->rx_ring[i].xdp_bpf_prog, prog);
> +
> + if (old_bpf_prog)
> + bpf_prog_put(old_bpf_prog);
> +
> + } else {
> + netif_err(adapter, drv, adapter->netdev, "Failed to set xdp program, the current MTU (%d) is larger than the maximal allowed MTU (%lu) while xdp is on",
> + netdev->mtu, ENA_XDP_MAX_MTU);
> + return -EFAULT;
unfortunate that extack has not been plumbed to ndo_bpf handler so that
message is passed to the user.
And EFAULT seems like the wrong return code.
> + }
> +
> + return 0;
> +}
> +
> +/* This is the main xdp callback, it's used by the kernel to set/unset the xdp
> + * program as well as to query the current xdp program id.
> + */
> +static int ena_xdp(struct net_device *netdev, struct netdev_bpf *bpf)
> +{
> + struct ena_adapter *adapter = netdev_priv(netdev);
> +
> + switch (bpf->command) {
> + case XDP_SETUP_PROG:
> + return ena_xdp_set(netdev, bpf->prog);
> + case XDP_QUERY_PROG:
> + bpf->prog_id = adapter->xdp_bpf_prog ?
> + adapter->xdp_bpf_prog->aux->id : 0;
> + break;
> + default:
> + return -EINVAL;
> + }
> + return 0;
> +}
> +
> static int ena_change_mtu(struct net_device *dev, int new_mtu)
> {
> struct ena_adapter *adapter = netdev_priv(dev);
> int ret;
>
> + if (new_mtu > ENA_XDP_MAX_MTU && ena_xdp_present(adapter)) {
> + netif_err(adapter, drv, dev,
> + "Requested MTU value is not valid while xdp is enabled new_mtu: %d max mtu: %lu min mtu: %d\n",
> + new_mtu, ENA_XDP_MAX_MTU, ENA_MIN_MTU);
> + return -EINVAL;
> + }
If you manage dev->max_mtu as an XDP program is installed / removed this
check is not needed. Instead it is handled by the core change_mtu logic
and has better user semanitcs: link list shows the new MTU and trying to
change it above the new max a message is sent to the user as opposed to
kernel log.
> ret = ena_com_set_dev_mtu(adapter->ena_dev, new_mtu);
> if (!ret) {
> netif_dbg(adapter, drv, dev, "set MTU to %d\n", new_mtu);
^ permalink raw reply
* Re: [RFC V1 net-next 1/1] net: ena: implement XDP drop support
From: Jesper Dangaard Brouer @ 2019-06-23 14:21 UTC (permalink / raw)
To: sameehj
Cc: brouer, davem, netdev, dwmw, Machulsky, Zorik, matua, saeedb, msw,
aliguori, nafea, gtzalik, netanel, alisaidi, benh, akiyano,
Daniel Borkmann
In-Reply-To: <20190623070649.18447-2-sameehj@amazon.com>
On Sun, 23 Jun 2019 10:06:49 +0300 <sameehj@amazon.com> wrote:
> This commit implements the basic functionality of drop/pass logic in the
> ena driver.
Usually we require a driver to implement all the XDP return codes,
before we accept it. But as Daniel and I discussed with Zorik during
NetConf[1], we are going to make an exception and accept the driver
if you also implement XDP_TX.
As we trust that Zorik/Amazon will follow and implement XDP_REDIRECT
later, given he/you wants AF_XDP support which requires XDP_REDIRECT.
[1] http://vger.kernel.org/netconf2019.html
--
Best regards,
Jesper Dangaard Brouer
MSc.CS, Principal Kernel Engineer at Red Hat
LinkedIn: http://www.linkedin.com/in/brouer
^ permalink raw reply
* Re: [RFC V1 net-next 1/1] net: ena: implement XDP drop support
From: Jesper Dangaard Brouer @ 2019-06-23 14:09 UTC (permalink / raw)
To: sameehj
Cc: brouer, davem, netdev, dwmw, Machulsky, Zorik, matua, saeedb, msw,
aliguori, nafea, gtzalik, netanel, alisaidi, benh, akiyano,
Daniel Borkmann
In-Reply-To: <20190623070649.18447-2-sameehj@amazon.com>
I'm very happy to see progress with XDP for the ENA driver.
On Sun, 23 Jun 2019 10:06:49 +0300 <sameehj@amazon.com> wrote:
> @@ -888,6 +959,15 @@ static struct sk_buff *ena_rx_skb(struct ena_ring *rx_ring,
> va = page_address(rx_info->page) + rx_info->page_offset;
> prefetch(va + NET_IP_ALIGN);
>
> + if (ena_xdp_present_ring(rx_ring)) {
> + rx_ring->xdp.data = va;
> + rx_ring->xdp.data_meta = rx_ring->xdp.data;
> + rx_ring->xdp.data_hard_start = rx_ring->xdp.data -
> + rx_info->page_offset;
> + rx_ring->xdp.data_end = rx_ring->xdp.data + len;
> + if (ena_xdp_execute(rx_ring, &rx_ring->xdp) != XDP_PASS)
> + return NULL;
> + }
Looks like you forgot to init xdp.rxq pointer.
You can use the samples/bpf/xdp_rxq_info* to access this... and this
driver will likely crash if you use it...
--
Best regards,
Jesper Dangaard Brouer
MSc.CS, Principal Kernel Engineer at Red Hat
LinkedIn: http://www.linkedin.com/in/brouer
^ permalink raw reply
* [PATCH net-next 3/3] mlxsw: core: Add support for negative temperature readout
From: Ido Schimmel @ 2019-06-23 12:56 UTC (permalink / raw)
To: netdev; +Cc: davem, jiri, mlxsw, Vadim Pasternak, Ido Schimmel
In-Reply-To: <20190623125645.2663-1-idosch@idosch.org>
From: Vadim Pasternak <vadimp@mellanox.com>
Extend macros MLXSW_REG_MTMP_TEMP_TO_MC() to allow support of negative
temperature readout, since chip and others thermal components are
capable of operating within the negative temperature.
With no such support negative temperature will be consider as very high
temperature and it will cause wrong readout and thermal shutdown.
For negative values 2`s complement is used.
Tested in chamber.
Example of chip ambient temperature readout with chamber temperature:
-10 Celsius:
temp1: -6.0C (highest = -5.0C)
-5 Celsius:
temp1: -1.0C (highest = -1.0C)
Signed-off-by: Vadim Pasternak <vadimp@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c | 12 +++++-------
drivers/net/ethernet/mellanox/mlxsw/core_thermal.c | 14 +++++++-------
drivers/net/ethernet/mellanox/mlxsw/reg.h | 12 +++++++-----
3 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c
index 056e3f55ae6c..fb1fd334a8d4 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c
@@ -52,8 +52,7 @@ static ssize_t mlxsw_hwmon_temp_show(struct device *dev,
container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
char mtmp_pl[MLXSW_REG_MTMP_LEN];
- unsigned int temp;
- int index;
+ int temp, index;
int err;
index = mlxsw_hwmon_get_attr_index(mlwsw_hwmon_attr->type_index,
@@ -65,7 +64,7 @@ static ssize_t mlxsw_hwmon_temp_show(struct device *dev,
return err;
}
mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL);
- return sprintf(buf, "%u\n", temp);
+ return sprintf(buf, "%d\n", temp);
}
static ssize_t mlxsw_hwmon_temp_max_show(struct device *dev,
@@ -76,8 +75,7 @@ static ssize_t mlxsw_hwmon_temp_max_show(struct device *dev,
container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
char mtmp_pl[MLXSW_REG_MTMP_LEN];
- unsigned int temp_max;
- int index;
+ int temp_max, index;
int err;
index = mlxsw_hwmon_get_attr_index(mlwsw_hwmon_attr->type_index,
@@ -89,7 +87,7 @@ static ssize_t mlxsw_hwmon_temp_max_show(struct device *dev,
return err;
}
mlxsw_reg_mtmp_unpack(mtmp_pl, NULL, &temp_max, NULL);
- return sprintf(buf, "%u\n", temp_max);
+ return sprintf(buf, "%d\n", temp_max);
}
static ssize_t mlxsw_hwmon_temp_rst_store(struct device *dev,
@@ -215,8 +213,8 @@ static ssize_t mlxsw_hwmon_module_temp_show(struct device *dev,
container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
char mtmp_pl[MLXSW_REG_MTMP_LEN];
- unsigned int temp;
u8 module;
+ int temp;
int err;
module = mlwsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
index 504a34d240f7..35a1dc89c28a 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
@@ -312,7 +312,7 @@ static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev,
struct mlxsw_thermal *thermal = tzdev->devdata;
struct device *dev = thermal->bus_info->dev;
char mtmp_pl[MLXSW_REG_MTMP_LEN];
- unsigned int temp;
+ int temp;
int err;
mlxsw_reg_mtmp_pack(mtmp_pl, 0, false, false);
@@ -327,7 +327,7 @@ static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev,
mlxsw_thermal_tz_score_update(thermal, tzdev, thermal->trips,
temp);
- *p_temp = (int) temp;
+ *p_temp = temp;
return 0;
}
@@ -503,7 +503,7 @@ static int mlxsw_thermal_module_temp_get(struct thermal_zone_device *tzdev,
struct mlxsw_thermal *thermal = tz->parent;
struct device *dev = thermal->bus_info->dev;
char mtmp_pl[MLXSW_REG_MTMP_LEN];
- unsigned int temp;
+ int temp;
int err;
/* Read module temperature. */
@@ -519,14 +519,14 @@ static int mlxsw_thermal_module_temp_get(struct thermal_zone_device *tzdev,
return 0;
}
mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL);
- *p_temp = (int) temp;
+ *p_temp = temp;
if (!temp)
return 0;
/* Update trip points. */
err = mlxsw_thermal_module_trips_update(dev, thermal->core, tz);
- if (!err)
+ if (!err && temp > 0)
mlxsw_thermal_tz_score_update(thermal, tzdev, tz->trips, temp);
return 0;
@@ -612,8 +612,8 @@ static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev,
struct mlxsw_thermal_module *tz = tzdev->devdata;
struct mlxsw_thermal *thermal = tz->parent;
char mtmp_pl[MLXSW_REG_MTMP_LEN];
- unsigned int temp;
u16 index;
+ int temp;
int err;
index = MLXSW_REG_MTMP_GBOX_INDEX_MIN + tz->module;
@@ -627,7 +627,7 @@ static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev,
if (temp > 0)
mlxsw_thermal_tz_score_update(thermal, tzdev, tz->trips, temp);
- *p_temp = (int) temp;
+ *p_temp = temp;
return 0;
}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h
index 452f645fa040..e5f6bfd8a35a 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h
@@ -8050,7 +8050,10 @@ MLXSW_REG_DEFINE(mtmp, MLXSW_REG_MTMP_ID, MLXSW_REG_MTMP_LEN);
MLXSW_ITEM32(reg, mtmp, sensor_index, 0x00, 0, 12);
/* Convert to milli degrees Celsius */
-#define MLXSW_REG_MTMP_TEMP_TO_MC(val) (val * 125)
+#define MLXSW_REG_MTMP_TEMP_TO_MC(val) ({ typeof(val) v_ = (val); \
+ ((v_) >= 0) ? ((v_) * 125) : \
+ ((s16)((GENMASK(15, 0) + (v_) + 1) \
+ * 125)); })
/* reg_mtmp_temperature
* Temperature reading from the sensor. Reading is in 0.125 Celsius
@@ -8121,11 +8124,10 @@ static inline void mlxsw_reg_mtmp_pack(char *payload, u16 sensor_index,
MLXSW_REG_MTMP_THRESH_HI);
}
-static inline void mlxsw_reg_mtmp_unpack(char *payload, unsigned int *p_temp,
- unsigned int *p_max_temp,
- char *sensor_name)
+static inline void mlxsw_reg_mtmp_unpack(char *payload, int *p_temp,
+ int *p_max_temp, char *sensor_name)
{
- u16 temp;
+ s16 temp;
if (p_temp) {
temp = mlxsw_reg_mtmp_temperature_get(payload);
--
2.20.1
^ permalink raw reply related
* [PATCH net-next 2/3] mlxsw: core: Add the hottest thermal zone detection
From: Ido Schimmel @ 2019-06-23 12:56 UTC (permalink / raw)
To: netdev; +Cc: davem, jiri, mlxsw, Vadim Pasternak, Ido Schimmel
In-Reply-To: <20190623125645.2663-1-idosch@idosch.org>
From: Vadim Pasternak <vadimp@mellanox.com>
When multiple sensors are mapped to the same cooling device, the
cooling device should be set according the worst sensor from the
sensors associated with this cooling device.
Provide the hottest thermal zone detection and enforce cooling device
to follow the temperature trends of the hottest zone only.
Prevent competition for the cooling device control from others zones,
by "stable trend" indication. A cooling device will not perform any
actions associated with a zone with a "stable trend".
When other thermal zone is detected as a hottest, a cooling device is
to be switched to following temperature trends of new hottest zone.
Thermal zone score is represented by 32 bits unsigned integer and
calculated according to the next formula:
For T < TZ<t><i>, where t from {normal trip = 0, high trip = 1, hot
trip = 2, critical = 3}:
TZ<i> score = (T + (TZ<t><i> - T) / 2) / (TZ<t><i> - T) * 256 ** j;
Highest thermal zone score s is set as MAX(TZ<i>score);
Following this formula, if TZ<i> is in trip point higher than TZ<k>,
the higher score is to be always assigned to TZ<i>.
For two thermal zones located at the same kind of trip point, the higher
score will be assigned to the zone which is closer to the next trip
point. Thus, the highest score will always be assigned objectively to
the hottest thermal zone.
All the thermal zones initially are to be configured with mode
"enabled" with the "step_wise" governor.
Signed-off-by: Vadim Pasternak <vadimp@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
.../ethernet/mellanox/mlxsw/core_thermal.c | 75 +++++++++++++++----
1 file changed, 62 insertions(+), 13 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
index 88f43ad2cc4f..504a34d240f7 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
@@ -23,6 +23,7 @@
#define MLXSW_THERMAL_HYSTERESIS_TEMP 5000 /* 5C */
#define MLXSW_THERMAL_MODULE_TEMP_SHIFT (MLXSW_THERMAL_HYSTERESIS_TEMP * 2)
#define MLXSW_THERMAL_ZONE_MAX_NAME 16
+#define MLXSW_THERMAL_TEMP_SCORE_MAX GENMASK(31, 0)
#define MLXSW_THERMAL_MAX_STATE 10
#define MLXSW_THERMAL_MAX_DUTY 255
/* Minimum and maximum fan allowed speed in percent: from 20% to 100%. Values
@@ -113,6 +114,8 @@ struct mlxsw_thermal {
struct mlxsw_thermal_module *tz_module_arr;
struct mlxsw_thermal_module *tz_gearbox_arr;
u8 tz_gearbox_num;
+ unsigned int tz_highest_score;
+ struct thermal_zone_device *tz_highest_dev;
};
static inline u8 mlxsw_state_to_duty(int state)
@@ -197,6 +200,34 @@ mlxsw_thermal_module_trips_update(struct device *dev, struct mlxsw_core *core,
return 0;
}
+static void mlxsw_thermal_tz_score_update(struct mlxsw_thermal *thermal,
+ struct thermal_zone_device *tzdev,
+ struct mlxsw_thermal_trip *trips,
+ int temp)
+{
+ struct mlxsw_thermal_trip *trip = trips;
+ unsigned int score, delta, i, shift = 1;
+
+ /* Calculate thermal zone score, if temperature is above the critical
+ * threshold score is set to MLXSW_THERMAL_TEMP_SCORE_MAX.
+ */
+ score = MLXSW_THERMAL_TEMP_SCORE_MAX;
+ for (i = MLXSW_THERMAL_TEMP_TRIP_NORM; i < MLXSW_THERMAL_NUM_TRIPS;
+ i++, trip++) {
+ if (temp < trip->temp) {
+ delta = DIV_ROUND_CLOSEST(temp, trip->temp - temp);
+ score = delta * shift;
+ break;
+ }
+ shift *= 256;
+ }
+
+ if (score > thermal->tz_highest_score) {
+ thermal->tz_highest_score = score;
+ thermal->tz_highest_dev = tzdev;
+ }
+}
+
static int mlxsw_thermal_bind(struct thermal_zone_device *tzdev,
struct thermal_cooling_device *cdev)
{
@@ -292,6 +323,9 @@ static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev,
return err;
}
mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL);
+ if (temp > 0)
+ mlxsw_thermal_tz_score_update(thermal, tzdev, thermal->trips,
+ temp);
*p_temp = (int) temp;
return 0;
@@ -353,6 +387,22 @@ static int mlxsw_thermal_set_trip_hyst(struct thermal_zone_device *tzdev,
return 0;
}
+static int mlxsw_thermal_trend_get(struct thermal_zone_device *tzdev,
+ int trip, enum thermal_trend *trend)
+{
+ struct mlxsw_thermal_module *tz = tzdev->devdata;
+ struct mlxsw_thermal *thermal = tz->parent;
+
+ if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
+ return -EINVAL;
+
+ if (tzdev == thermal->tz_highest_dev)
+ return 1;
+
+ *trend = THERMAL_TREND_STABLE;
+ return 0;
+}
+
static struct thermal_zone_device_ops mlxsw_thermal_ops = {
.bind = mlxsw_thermal_bind,
.unbind = mlxsw_thermal_unbind,
@@ -364,6 +414,7 @@ static struct thermal_zone_device_ops mlxsw_thermal_ops = {
.set_trip_temp = mlxsw_thermal_set_trip_temp,
.get_trip_hyst = mlxsw_thermal_get_trip_hyst,
.set_trip_hyst = mlxsw_thermal_set_trip_hyst,
+ .get_trend = mlxsw_thermal_trend_get,
};
static int mlxsw_thermal_module_bind(struct thermal_zone_device *tzdev,
@@ -474,7 +525,9 @@ static int mlxsw_thermal_module_temp_get(struct thermal_zone_device *tzdev,
return 0;
/* Update trip points. */
- mlxsw_thermal_module_trips_update(dev, thermal->core, tz);
+ err = mlxsw_thermal_module_trips_update(dev, thermal->core, tz);
+ if (!err)
+ mlxsw_thermal_tz_score_update(thermal, tzdev, tz->trips, temp);
return 0;
}
@@ -539,10 +592,6 @@ mlxsw_thermal_module_trip_hyst_set(struct thermal_zone_device *tzdev, int trip,
return 0;
}
-static struct thermal_zone_params mlxsw_thermal_module_params = {
- .governor_name = "user_space",
-};
-
static struct thermal_zone_device_ops mlxsw_thermal_module_ops = {
.bind = mlxsw_thermal_module_bind,
.unbind = mlxsw_thermal_module_unbind,
@@ -554,6 +603,7 @@ static struct thermal_zone_device_ops mlxsw_thermal_module_ops = {
.set_trip_temp = mlxsw_thermal_module_trip_temp_set,
.get_trip_hyst = mlxsw_thermal_module_trip_hyst_get,
.set_trip_hyst = mlxsw_thermal_module_trip_hyst_set,
+ .get_trend = mlxsw_thermal_trend_get,
};
static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev,
@@ -574,6 +624,8 @@ static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev,
return err;
mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL);
+ if (temp > 0)
+ mlxsw_thermal_tz_score_update(thermal, tzdev, tz->trips, temp);
*p_temp = (int) temp;
return 0;
@@ -590,10 +642,7 @@ static struct thermal_zone_device_ops mlxsw_thermal_gearbox_ops = {
.set_trip_temp = mlxsw_thermal_module_trip_temp_set,
.get_trip_hyst = mlxsw_thermal_module_trip_hyst_get,
.set_trip_hyst = mlxsw_thermal_module_trip_hyst_set,
-};
-
-static struct thermal_zone_params mlxsw_thermal_gearbox_params = {
- .governor_name = "user_space",
+ .get_trend = mlxsw_thermal_trend_get,
};
static int mlxsw_thermal_get_max_state(struct thermal_cooling_device *cdev,
@@ -709,13 +758,13 @@ mlxsw_thermal_module_tz_init(struct mlxsw_thermal_module *module_tz)
MLXSW_THERMAL_TRIP_MASK,
module_tz,
&mlxsw_thermal_module_ops,
- &mlxsw_thermal_module_params,
- 0, 0);
+ NULL, 0, 0);
if (IS_ERR(module_tz->tzdev)) {
err = PTR_ERR(module_tz->tzdev);
return err;
}
+ module_tz->mode = THERMAL_DEVICE_ENABLED;
return 0;
}
@@ -833,11 +882,11 @@ mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module *gearbox_tz)
MLXSW_THERMAL_TRIP_MASK,
gearbox_tz,
&mlxsw_thermal_gearbox_ops,
- &mlxsw_thermal_gearbox_params,
- 0, 0);
+ NULL, 0, 0);
if (IS_ERR(gearbox_tz->tzdev))
return PTR_ERR(gearbox_tz->tzdev);
+ gearbox_tz->mode = THERMAL_DEVICE_ENABLED;
return 0;
}
--
2.20.1
^ permalink raw reply related
* [PATCH net-next 1/3] mlxsw: core: Extend thermal core with per inter-connect device thermal zones
From: Ido Schimmel @ 2019-06-23 12:56 UTC (permalink / raw)
To: netdev; +Cc: davem, jiri, mlxsw, Vadim Pasternak, Ido Schimmel
In-Reply-To: <20190623125645.2663-1-idosch@idosch.org>
From: Vadim Pasternak <vadimp@mellanox.com>
Add a dedicated thermal zone for each inter-connect device. The
current temperature is obtained from inter-connect temperature sensor
and the default trip points are set to the same values as default ASIC
trip points. These settings could be changed from the user space.
A cooling device (fan) is bound to all inter-connect devices.
Signed-off-by: Vadim Pasternak <vadimp@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
.../ethernet/mellanox/mlxsw/core_thermal.c | 137 +++++++++++++++++-
1 file changed, 136 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
index cfab0e330a47..88f43ad2cc4f 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
@@ -98,7 +98,7 @@ struct mlxsw_thermal_module {
struct thermal_zone_device *tzdev;
struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];
enum thermal_device_mode mode;
- int module;
+ int module; /* Module or gearbox number */
};
struct mlxsw_thermal {
@@ -111,6 +111,8 @@ struct mlxsw_thermal {
struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];
enum thermal_device_mode mode;
struct mlxsw_thermal_module *tz_module_arr;
+ struct mlxsw_thermal_module *tz_gearbox_arr;
+ u8 tz_gearbox_num;
};
static inline u8 mlxsw_state_to_duty(int state)
@@ -554,6 +556,46 @@ static struct thermal_zone_device_ops mlxsw_thermal_module_ops = {
.set_trip_hyst = mlxsw_thermal_module_trip_hyst_set,
};
+static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev,
+ int *p_temp)
+{
+ struct mlxsw_thermal_module *tz = tzdev->devdata;
+ struct mlxsw_thermal *thermal = tz->parent;
+ char mtmp_pl[MLXSW_REG_MTMP_LEN];
+ unsigned int temp;
+ u16 index;
+ int err;
+
+ index = MLXSW_REG_MTMP_GBOX_INDEX_MIN + tz->module;
+ mlxsw_reg_mtmp_pack(mtmp_pl, index, false, false);
+
+ err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl);
+ if (err)
+ return err;
+
+ mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL);
+
+ *p_temp = (int) temp;
+ return 0;
+}
+
+static struct thermal_zone_device_ops mlxsw_thermal_gearbox_ops = {
+ .bind = mlxsw_thermal_module_bind,
+ .unbind = mlxsw_thermal_module_unbind,
+ .get_mode = mlxsw_thermal_module_mode_get,
+ .set_mode = mlxsw_thermal_module_mode_set,
+ .get_temp = mlxsw_thermal_gearbox_temp_get,
+ .get_trip_type = mlxsw_thermal_module_trip_type_get,
+ .get_trip_temp = mlxsw_thermal_module_trip_temp_get,
+ .set_trip_temp = mlxsw_thermal_module_trip_temp_set,
+ .get_trip_hyst = mlxsw_thermal_module_trip_hyst_get,
+ .set_trip_hyst = mlxsw_thermal_module_trip_hyst_set,
+};
+
+static struct thermal_zone_params mlxsw_thermal_gearbox_params = {
+ .governor_name = "user_space",
+};
+
static int mlxsw_thermal_get_max_state(struct thermal_cooling_device *cdev,
unsigned long *p_state)
{
@@ -779,6 +821,92 @@ mlxsw_thermal_modules_fini(struct mlxsw_thermal *thermal)
kfree(thermal->tz_module_arr);
}
+static int
+mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module *gearbox_tz)
+{
+ char tz_name[MLXSW_THERMAL_ZONE_MAX_NAME];
+
+ snprintf(tz_name, sizeof(tz_name), "mlxsw-gearbox%d",
+ gearbox_tz->module + 1);
+ gearbox_tz->tzdev = thermal_zone_device_register(tz_name,
+ MLXSW_THERMAL_NUM_TRIPS,
+ MLXSW_THERMAL_TRIP_MASK,
+ gearbox_tz,
+ &mlxsw_thermal_gearbox_ops,
+ &mlxsw_thermal_gearbox_params,
+ 0, 0);
+ if (IS_ERR(gearbox_tz->tzdev))
+ return PTR_ERR(gearbox_tz->tzdev);
+
+ return 0;
+}
+
+static void
+mlxsw_thermal_gearbox_tz_fini(struct mlxsw_thermal_module *gearbox_tz)
+{
+ thermal_zone_device_unregister(gearbox_tz->tzdev);
+}
+
+static int
+mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core,
+ struct mlxsw_thermal *thermal)
+{
+ struct mlxsw_thermal_module *gearbox_tz;
+ char mgpir_pl[MLXSW_REG_MGPIR_LEN];
+ int i;
+ int err;
+
+ if (!mlxsw_core_res_query_enabled(core))
+ return 0;
+
+ mlxsw_reg_mgpir_pack(mgpir_pl);
+ err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl);
+ if (err)
+ return err;
+
+ mlxsw_reg_mgpir_unpack(mgpir_pl, &thermal->tz_gearbox_num, NULL, NULL);
+ if (!thermal->tz_gearbox_num)
+ return 0;
+
+ thermal->tz_gearbox_arr = kcalloc(thermal->tz_gearbox_num,
+ sizeof(*thermal->tz_gearbox_arr),
+ GFP_KERNEL);
+ if (!thermal->tz_gearbox_arr)
+ return -ENOMEM;
+
+ for (i = 0; i < thermal->tz_gearbox_num; i++) {
+ gearbox_tz = &thermal->tz_gearbox_arr[i];
+ memcpy(gearbox_tz->trips, default_thermal_trips,
+ sizeof(thermal->trips));
+ gearbox_tz->module = i;
+ gearbox_tz->parent = thermal;
+ err = mlxsw_thermal_gearbox_tz_init(gearbox_tz);
+ if (err)
+ goto err_unreg_tz_gearbox;
+ }
+
+ return 0;
+
+err_unreg_tz_gearbox:
+ for (i--; i >= 0; i--)
+ mlxsw_thermal_gearbox_tz_fini(&thermal->tz_gearbox_arr[i]);
+ kfree(thermal->tz_gearbox_arr);
+ return err;
+}
+
+static void
+mlxsw_thermal_gearboxes_fini(struct mlxsw_thermal *thermal)
+{
+ int i;
+
+ if (!mlxsw_core_res_query_enabled(thermal->core))
+ return;
+
+ for (i = thermal->tz_gearbox_num - 1; i >= 0; i--)
+ mlxsw_thermal_gearbox_tz_fini(&thermal->tz_gearbox_arr[i]);
+ kfree(thermal->tz_gearbox_arr);
+}
+
int mlxsw_thermal_init(struct mlxsw_core *core,
const struct mlxsw_bus_info *bus_info,
struct mlxsw_thermal **p_thermal)
@@ -869,10 +997,16 @@ int mlxsw_thermal_init(struct mlxsw_core *core,
if (err)
goto err_unreg_tzdev;
+ err = mlxsw_thermal_gearboxes_init(dev, core, thermal);
+ if (err)
+ goto err_unreg_modules_tzdev;
+
thermal->mode = THERMAL_DEVICE_ENABLED;
*p_thermal = thermal;
return 0;
+err_unreg_modules_tzdev:
+ mlxsw_thermal_modules_fini(thermal);
err_unreg_tzdev:
if (thermal->tzdev) {
thermal_zone_device_unregister(thermal->tzdev);
@@ -891,6 +1025,7 @@ void mlxsw_thermal_fini(struct mlxsw_thermal *thermal)
{
int i;
+ mlxsw_thermal_gearboxes_fini(thermal);
mlxsw_thermal_modules_fini(thermal);
if (thermal->tzdev) {
thermal_zone_device_unregister(thermal->tzdev);
--
2.20.1
^ permalink raw reply related
* [PATCH net-next 0/3] mlxsw: Thermal and hwmon extensions
From: Ido Schimmel @ 2019-06-23 12:56 UTC (permalink / raw)
To: netdev; +Cc: davem, jiri, mlxsw, Ido Schimmel
From: Ido Schimmel <idosch@mellanox.com>
This patchset from Vadim includes various enhancements to thermal and
hwmon code in mlxsw.
Patch #1 adds a thermal zone for each inter-connect device (gearbox).
These devices are present in SN3800 systems and code to expose their
temperature via hwmon was added in commit 2e265a8b6c09 ("mlxsw: core:
Extend hwmon interface with inter-connect temperature attributes").
Currently, there are multiple thermal zones in mlxsw and only a few
cooling devices. Patch #2 detects the hottest thermal zone and the
cooling devices are switched to follow its trends. RFC was sent last
month [1].
Patch #3 allows to read and report negative temperature of the sensors
mlxsw exposes via hwmon and thermal subsystems.
[1] https://patchwork.ozlabs.org/patch/1107161/
Vadim Pasternak (3):
mlxsw: core: Extend thermal core with per inter-connect device thermal
zones
mlxsw: core: Add the hottest thermal zone detection
mlxsw: core: Add support for negative temperature readout
.../net/ethernet/mellanox/mlxsw/core_hwmon.c | 12 +-
.../ethernet/mellanox/mlxsw/core_thermal.c | 208 +++++++++++++++++-
drivers/net/ethernet/mellanox/mlxsw/reg.h | 12 +-
3 files changed, 208 insertions(+), 24 deletions(-)
--
2.20.1
^ permalink raw reply
* [PATCH] net: ethernet: ti: cpsw: Assign OF node to slave devices
From: Marek Vasut @ 2019-06-23 12:11 UTC (permalink / raw)
To: netdev; +Cc: Marek Vasut, David S . Miller, Ivan Khoronzhuk
Assign OF node to CPSW slave devices, otherwise it is not possible to
bind e.g. DSA switch to them. Without this patch, the DSA code tries
to find the ethernet device by OF match, but fails to do so because
the slave device has NULL OF node.
Signed-off-by: Marek Vasut <marex@denx.de>
Cc: David S. Miller <davem@davemloft.net>
Cc: Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org>
---
drivers/net/ethernet/ti/cpsw.c | 3 +++
drivers/net/ethernet/ti/cpsw_priv.h | 1 +
2 files changed, 4 insertions(+)
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 7bdd287074fc..c39790e21276 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -2179,6 +2179,7 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
return ret;
}
+ slave_data->slave_node = slave_node;
slave_data->phy_node = of_parse_phandle(slave_node,
"phy-handle", 0);
parp = of_get_property(slave_node, "phy_id", &lenp);
@@ -2329,6 +2330,7 @@ static int cpsw_probe_dual_emac(struct cpsw_priv *priv)
/* register the network device */
SET_NETDEV_DEV(ndev, cpsw->dev);
+ ndev->dev.of_node = cpsw->slaves[1].data->slave_node;
ret = register_netdev(ndev);
if (ret)
dev_err(cpsw->dev, "cpsw: error registering net device\n");
@@ -2506,6 +2508,7 @@ static int cpsw_probe(struct platform_device *pdev)
/* register the network device */
SET_NETDEV_DEV(ndev, dev);
+ ndev->dev.of_node = cpsw->slaves[0].data->slave_node;
ret = register_netdev(ndev);
if (ret) {
dev_err(dev, "error registering net device\n");
diff --git a/drivers/net/ethernet/ti/cpsw_priv.h b/drivers/net/ethernet/ti/cpsw_priv.h
index 04795b97ee71..e32f11da2dce 100644
--- a/drivers/net/ethernet/ti/cpsw_priv.h
+++ b/drivers/net/ethernet/ti/cpsw_priv.h
@@ -272,6 +272,7 @@ struct cpsw_host_regs {
};
struct cpsw_slave_data {
+ struct device_node *slave_node;
struct device_node *phy_node;
char phy_id[MII_BUS_ID_SIZE];
int phy_if;
--
2.20.1
^ permalink raw reply related
* [PATCH] net: dsa: microchip: Use gpiod_set_value_cansleep()
From: Marek Vasut @ 2019-06-23 12:10 UTC (permalink / raw)
To: netdev
Cc: Marek Vasut, Andrew Lunn, Florian Fainelli, Linus Walleij,
Tristram Ha, Woojung Huh
Replace gpiod_set_value() with gpiod_set_value_cansleep(), as the switch
reset GPIO can be connected to e.g. I2C GPIO expander and it is perfectly
fine for the kernel to sleep for a bit in ksz_switch_register().
Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: Tristram Ha <Tristram.Ha@microchip.com>
Cc: Woojung Huh <Woojung.Huh@microchip.com>
---
drivers/net/dsa/microchip/ksz_common.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index 4f6648d5ac8b..bc81806dd75e 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -436,9 +436,9 @@ int ksz_switch_register(struct ksz_device *dev,
return PTR_ERR(dev->reset_gpio);
if (dev->reset_gpio) {
- gpiod_set_value(dev->reset_gpio, 1);
+ gpiod_set_value_cansleep(dev->reset_gpio, 1);
mdelay(10);
- gpiod_set_value(dev->reset_gpio, 0);
+ gpiod_set_value_cansleep(dev->reset_gpio, 0);
}
mutex_init(&dev->dev_mutex);
--
2.20.1
^ permalink raw reply related
* Re: [PATCH bpf-next v5 00/16] AF_XDP infrastructure improvements and mlx5e support
From: Tariq Toukan @ 2019-06-23 11:53 UTC (permalink / raw)
To: Saeed Mahameed, Björn Töpel
Cc: Maxim Mikityanskiy, Alexei Starovoitov, Daniel Borkmann,
Björn Töpel, Magnus Karlsson, bpf@vger.kernel.org,
netdev@vger.kernel.org, David S. Miller, Saeed Mahameed,
Jonathan Lemon, Tariq Toukan, Martin KaFai Lau, Song Liu,
Yonghong Song, Jakub Kicinski, Maciej Fijalkowski
In-Reply-To: <CALzJLG-eCiYYshkm_op1PqkCmxTmdDdPSGbX7g2JMqTb8QXyJg@mail.gmail.com>
On 6/21/2019 10:52 PM, Saeed Mahameed wrote:
> On Thu, Jun 20, 2019 at 2:13 AM Björn Töpel <bjorn.topel@gmail.com> wrote:
>>
>> On Tue, 18 Jun 2019 at 14:00, Maxim Mikityanskiy <maximmi@mellanox.com> wrote:
>>>
>>> This series contains improvements to the AF_XDP kernel infrastructure
>>> and AF_XDP support in mlx5e. The infrastructure improvements are
>>> required for mlx5e, but also some of them benefit to all drivers, and
>>> some can be useful for other drivers that want to implement AF_XDP.
>>>
>>> The performance testing was performed on a machine with the following
>>> configuration:
>>>
>>> - 24 cores of Intel Xeon E5-2620 v3 @ 2.40 GHz
>>> - Mellanox ConnectX-5 Ex with 100 Gbit/s link
>>>
>>> The results with retpoline disabled, single stream:
>>>
>>> txonly: 33.3 Mpps (21.5 Mpps with queue and app pinned to the same CPU)
>>> rxdrop: 12.2 Mpps
>>> l2fwd: 9.4 Mpps
>>>
>>> The results with retpoline enabled, single stream:
>>>
>>> txonly: 21.3 Mpps (14.1 Mpps with queue and app pinned to the same CPU)
>>> rxdrop: 9.9 Mpps
>>> l2fwd: 6.8 Mpps
>>>
>>> v2 changes:
>>>
>>> Added patches for mlx5e and addressed the comments for v1. Rebased for
>>> bpf-next.
>>>
>>> v3 changes:
>>>
>>> Rebased for the newer bpf-next, resolved conflicts in libbpf. Addressed
>>> Björn's comments for coding style. Fixed a bug in error handling flow in
>>> mlx5e_open_xsk.
>>>
>>> v4 changes:
>>>
>>> UAPI is not changed, XSK RX queues are exposed to the kernel. The lower
>>> half of the available amount of RX queues are regular queues, and the
>>> upper half are XSK RX queues. The patch "xsk: Extend channels to support
>>> combined XSK/non-XSK traffic" was dropped. The final patch was reworked
>>> accordingly.
>>>
>>> Added "net/mlx5e: Attach/detach XDP program safely", as the changes
>>> introduced in the XSK patch base on the stuff from this one.
>>>
>>> Added "libbpf: Support drivers with non-combined channels", which aligns
>>> the condition in libbpf with the condition in the kernel.
>>>
>>> Rebased over the newer bpf-next.
>>>
>>> v5 changes:
>>>
>>> In v4, ethtool reports the number of channels as 'combined' and the
>>> number of XSK RX queues as 'rx' for mlx5e. It was changed, so that 'rx'
>>> is 0, and 'combined' reports the double amount of channels if there is
>>> an active UMEM - to make libbpf happy.
>>>
>>> The patch for libbpf was dropped. Although it's still useful and fixes
>>> things, it raises some disagreement, so I'm dropping it - it's no longer
>>> useful for mlx5e anymore after the change above.
>>>
>>
>> Just a heads-up: There are some checkpatch warnings (>80 chars/line)
>
> Thanks Bjorn for your comment, in mlx5 we allow up to 95 chars per line,
> otherwise it is going to be an ugly zigzags.
>
>> for the mlnx5 driver parts, and the series didn't apply cleanly on
>> bpf-next for me.
>>
>> I haven't been able to test the mlnx5 parts.
>>
>> Parts of the series are unrelated/orthogonal, and could be submitted
>> as separate series, e.g. patches {1,7} and patches {3,4}. No blockers
>> for me, though.
>>
>> Thanks for the hard work!
>>
>> For the series:
>> Acked-by: Björn Töpel <bjorn.topel@intel.com>
Just wanted to make sure we're on the same page, so we don't miss this
kernel.
AIU, currently no action is needed from Maxim's side, as Saeed is fine
with the mlx5 part, and series is still marked as 'New' in patchworks
with no requested changes.
Regards,
Tariq
^ permalink raw reply
* Re: [PATCH v2 net] af_packet: Block execution of tasks waiting for transmit to complete in AF_PACKET
From: Neil Horman @ 2019-06-23 11:40 UTC (permalink / raw)
To: Willem de Bruijn; +Cc: Network Development, Matteo Croce, David S. Miller
In-Reply-To: <CAF=yD-+8NDiL0dxM+eOFyiwi1ZhCW29dW--+VeEkssUaJqedWg@mail.gmail.com>
On Sat, Jun 22, 2019 at 10:21:31PM -0400, Willem de Bruijn wrote:
> > > -static void __packet_set_status(struct packet_sock *po, void *frame, int status)
> > > +static void __packet_set_status(struct packet_sock *po, void *frame, int status,
> > > + bool call_complete)
> > > {
> > > union tpacket_uhdr h;
> > >
> > > @@ -381,6 +382,8 @@ static void __packet_set_status(struct packet_sock *po, void *frame, int status)
> > > BUG();
> > > }
> > >
> > > + if (po->wait_on_complete && call_complete)
> > > + complete(&po->skb_completion);
> >
> > This wake need not happen before the barrier. Only one caller of
> > __packet_set_status passes call_complete (tpacket_destruct_skb).
> > Moving this branch to the caller avoids a lot of code churn.
> >
> > Also, multiple packets may be released before the process is awoken.
> > The process will block until packet_read_pending drops to zero. Can
> > defer the wait_on_complete to that one instance.
>
> Eh no. The point of having this sleep in the send loop is that
> additional slots may be released for transmission (flipped to
> TP_STATUS_SEND_REQUEST) from another thread while this thread is
> waiting.
>
Thats incorrect. The entirety of tpacket_snd is protected by a mutex. No other
thread can alter the state of the frames in the vector from the kernel send path
while this thread is waiting.
> Else, it would have been much simpler to move the wait below the send
> loop: send as many packets as possible, then wait for all of them
> having been released. Much clearer control flow.
>
Thats (almost) what happens now. The only difference is that with this
implementation, the waiting thread has the opportunity to see if userspace has
queued more frames for transmission during the wait period. We could
potentially change that, but thats outside the scope of this fix.
> Where to set and clear the wait_on_complete boolean remains. Integer
> assignment is fragile, as the compiler and processor may optimize or
> move simple seemingly independent operations. As complete() takes a
> spinlock, avoiding that in the DONTWAIT case is worthwhile. But probably
> still preferable to set when beginning waiting and clear when calling
> complete.
We avoid any call to wait_for_complete or complete already, based on the gating
of the need_wait variable in tpacket_snd. If the transmitting thread doesn't
set MSG_DONTWAIT in the flags of the msg structure, we will never set
wait_for_complete, and so we will never manipulate the completion queue.
Neil
>
^ permalink raw reply
* Re: [PATCH v2 net] af_packet: Block execution of tasks waiting for transmit to complete in AF_PACKET
From: Neil Horman @ 2019-06-23 11:34 UTC (permalink / raw)
To: Willem de Bruijn; +Cc: Network Development, Matteo Croce, David S. Miller
In-Reply-To: <CAF=yD-JC_r1vjitN1ccyvQ3DXiP9BNCwq9iiWU11cXznmhAY8Q@mail.gmail.com>
On Sat, Jun 22, 2019 at 10:12:46PM -0400, Willem de Bruijn wrote:
> On Sat, Jun 22, 2019 at 1:42 PM Neil Horman <nhorman@tuxdriver.com> wrote:
> >
> > When an application is run that:
> > a) Sets its scheduler to be SCHED_FIFO
> > and
> > b) Opens a memory mapped AF_PACKET socket, and sends frames with the
> > MSG_DONTWAIT flag cleared, its possible for the application to hang
> > forever in the kernel. This occurs because when waiting, the code in
> > tpacket_snd calls schedule, which under normal circumstances allows
> > other tasks to run, including ksoftirqd, which in some cases is
> > responsible for freeing the transmitted skb (which in AF_PACKET calls a
> > destructor that flips the status bit of the transmitted frame back to
> > available, allowing the transmitting task to complete).
> >
> > However, when the calling application is SCHED_FIFO, its priority is
> > such that the schedule call immediately places the task back on the cpu,
> > preventing ksoftirqd from freeing the skb, which in turn prevents the
> > transmitting task from detecting that the transmission is complete.
> >
> > We can fix this by converting the schedule call to a completion
> > mechanism. By using a completion queue, we force the calling task, when
> > it detects there are no more frames to send, to schedule itself off the
> > cpu until such time as the last transmitted skb is freed, allowing
> > forward progress to be made.
> >
> > Tested by myself and the reporter, with good results
> >
> > Appies to the net tree
> >
> > Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
> > Reported-by: Matteo Croce <mcroce@redhat.com>
> > CC: "David S. Miller" <davem@davemloft.net>
> > CC: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
> >
> > Change Notes:
> >
> > V1->V2:
> > Enhance the sleep logic to support being interruptible and
> > allowing for honoring to SK_SNDTIMEO (Willem de Bruijn)
> > ---
> > net/packet/af_packet.c | 60 ++++++++++++++++++++++++++++++++----------
> > net/packet/internal.h | 2 ++
> > 2 files changed, 48 insertions(+), 14 deletions(-)
> >
> > diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
> > index a29d66da7394..8ddb2f7aebb4 100644
> > --- a/net/packet/af_packet.c
> > +++ b/net/packet/af_packet.c
> > @@ -358,7 +358,8 @@ static inline struct page * __pure pgv_to_page(void *addr)
> > return virt_to_page(addr);
> > }
> >
> > -static void __packet_set_status(struct packet_sock *po, void *frame, int status)
> > +static void __packet_set_status(struct packet_sock *po, void *frame, int status,
> > + bool call_complete)
> > {
> > union tpacket_uhdr h;
> >
> > @@ -381,6 +382,8 @@ static void __packet_set_status(struct packet_sock *po, void *frame, int status)
> > BUG();
> > }
> >
> > + if (po->wait_on_complete && call_complete)
> > + complete(&po->skb_completion);
>
> This wake need not happen before the barrier. Only one caller of
> __packet_set_status passes call_complete (tpacket_destruct_skb).
> Moving this branch to the caller avoids a lot of code churn.
>
Yeah, thats a fair point, I'll adjust that.
> Also, multiple packets may be released before the process is awoken.
> The process will block until packet_read_pending drops to zero. Can
> defer the wait_on_complete to that one instance.
>
Also true, we can gate the complete call on wait_on_complete and
pack_read_pending(...) == 0
> > smp_wmb();
> > }
> >
> > @@ -1148,6 +1151,14 @@ static void *packet_previous_frame(struct packet_sock *po,
> > return packet_lookup_frame(po, rb, previous, status);
> > }
> >
> > +static void *packet_next_frame(struct packet_sock *po,
> > + struct packet_ring_buffer *rb,
> > + int status)
> > +{
> > + unsigned int next = rb->head != rb->frame_max ? rb->head+1 : 0;
> > + return packet_lookup_frame(po, rb, next, status);
> > +}
> > +
> > static void packet_increment_head(struct packet_ring_buffer *buff)
> > {
> > buff->head = buff->head != buff->frame_max ? buff->head+1 : 0;
> > @@ -2360,7 +2371,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
> > #endif
> >
> > if (po->tp_version <= TPACKET_V2) {
> > - __packet_set_status(po, h.raw, status);
> > + __packet_set_status(po, h.raw, status, false);
> > sk->sk_data_ready(sk);
> > } else {
> > prb_clear_blk_fill_status(&po->rx_ring);
> > @@ -2400,7 +2411,7 @@ static void tpacket_destruct_skb(struct sk_buff *skb)
> > packet_dec_pending(&po->tx_ring);
> >
> > ts = __packet_set_timestamp(po, ph, skb);
> > - __packet_set_status(po, ph, TP_STATUS_AVAILABLE | ts);
> > + __packet_set_status(po, ph, TP_STATUS_AVAILABLE | ts, true);
> > }
> >
> > sock_wfree(skb);
> > @@ -2585,13 +2596,13 @@ static int tpacket_parse_header(struct packet_sock *po, void *frame,
> >
> > static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
> > {
> > - struct sk_buff *skb;
> > + struct sk_buff *skb = NULL;
> > struct net_device *dev;
> > struct virtio_net_hdr *vnet_hdr = NULL;
> > struct sockcm_cookie sockc;
> > __be16 proto;
> > int err, reserve = 0;
> > - void *ph;
> > + void *ph = NULL;
> > DECLARE_SOCKADDR(struct sockaddr_ll *, saddr, msg->msg_name);
> > bool need_wait = !(msg->msg_flags & MSG_DONTWAIT);
> > unsigned char *addr = NULL;
> > @@ -2600,9 +2611,12 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
> > int len_sum = 0;
> > int status = TP_STATUS_AVAILABLE;
> > int hlen, tlen, copylen = 0;
> > + long timeo;
> >
> > mutex_lock(&po->pg_vec_lock);
> >
> > + timeo = sock_sndtimeo(&po->sk, msg->msg_flags & MSG_DONTWAIT);
> > +
> > if (likely(saddr == NULL)) {
> > dev = packet_cached_dev_get(po);
> > proto = po->num;
> > @@ -2647,16 +2661,29 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
> > size_max = dev->mtu + reserve + VLAN_HLEN;
> >
> > do {
> > +
> > + if (po->wait_on_complete && need_wait) {
> > + timeo = wait_for_completion_interruptible_timeout(&po->skb_completion, timeo);
>
> Why move the sleeping location from where it was with schedule()?
> Without that change, ph and skb are both guaranteed to be NULL after
> packet_current_frame, so can jump to out_put and avoid adding branches
> at out_status. And no need for packet_next_frame.
>
> Just replace schedule with a sleeping function in place (removing the
> then obsolete need_resched call).
>
> That is a much shorter patch and easier to compare for correctness
> with the current code.
>
> minor: probably preferable to first check local variable need_wait
> before reading a struct member.
>
> > + po->wait_on_complete = 0;
> > + if (!timeo) {
> > + /* We timed out, break out and notify userspace */
> > + err = -ETIMEDOUT;
> > + goto out_status;
> > + } else if (timeo == -ERESTARTSYS) {
> > + err = -ERESTARTSYS;
> > + goto out_status;
> > + }
> > + }
> > +
> > ph = packet_current_frame(po, &po->tx_ring,
> > TP_STATUS_SEND_REQUEST);
> > - if (unlikely(ph == NULL)) {
> > - if (need_wait && need_resched())
> > - schedule();
> > - continue;
> > - }
> > +
> > + if (likely(ph == NULL))
>
> why switch from unlikely to likely?
>
> > + break;
> >
> > skb = NULL;
> > tp_len = tpacket_parse_header(po, ph, size_max, &data);
> > +
>
> nit: irrelevant
>
> > if (tp_len < 0)
> > goto tpacket_error;
> >
> > @@ -2699,7 +2726,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
> > tpacket_error:
> > if (po->tp_loss) {
> > __packet_set_status(po, ph,
> > - TP_STATUS_AVAILABLE);
> > + TP_STATUS_AVAILABLE, false);
> > packet_increment_head(&po->tx_ring);
> > kfree_skb(skb);
> > continue;
> > @@ -2719,7 +2746,9 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
> > }
> >
> > skb->destructor = tpacket_destruct_skb;
> > - __packet_set_status(po, ph, TP_STATUS_SENDING);
> > + __packet_set_status(po, ph, TP_STATUS_SENDING, false);
> > + if (!packet_next_frame(po, &po->tx_ring, TP_STATUS_SEND_REQUEST))
> > + po->wait_on_complete = 1;
> > packet_inc_pending(&po->tx_ring);
> >
> > status = TP_STATUS_SEND_REQUEST;
> > @@ -2753,8 +2782,10 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
> > goto out_put;
> >
> > out_status:
> > - __packet_set_status(po, ph, status);
> > - kfree_skb(skb);
> > + if (ph)
> > + __packet_set_status(po, ph, status, false);
> > + if (skb)
> > + kfree_skb(skb);
> > out_put:
> > dev_put(dev);
> > out:
> > @@ -3207,6 +3238,7 @@ static int packet_create(struct net *net, struct socket *sock, int protocol,
> > sock_init_data(sock, sk);
> >
> > po = pkt_sk(sk);
> > + init_completion(&po->skb_completion);
> > sk->sk_family = PF_PACKET;
> > po->num = proto;
> > po->xmit = dev_queue_xmit;
> > diff --git a/net/packet/internal.h b/net/packet/internal.h
> > index 3bb7c5fb3bff..bbb4be2c18e7 100644
> > --- a/net/packet/internal.h
> > +++ b/net/packet/internal.h
> > @@ -128,6 +128,8 @@ struct packet_sock {
> > unsigned int tp_hdrlen;
> > unsigned int tp_reserve;
> > unsigned int tp_tstamp;
> > + struct completion skb_completion;
> > + unsigned int wait_on_complete;
>
> Probably belong in packet_ring_buffer. Near pending_refcnt as touched
> in the same code. And because protected by the ring buffer mutex.
>
>
>
> > struct net_device __rcu *cached_dev;
> > int (*xmit)(struct sk_buff *skb);
> > struct packet_type prot_hook ____cacheline_aligned_in_smp;
> > --
> > 2.20.1
> >
>
^ permalink raw reply
* KMSAN: uninit-value in gre_parse_header
From: syzbot @ 2019-06-23 10:37 UTC (permalink / raw)
To: davem, glider, kuznet, linux-kernel, netdev, syzkaller-bugs, xeb,
yoshfuji
Hello,
syzbot found the following crash on:
HEAD commit: 088c01ea kmsan: fix comment, NFC
git tree: kmsan
console output: https://syzkaller.appspot.com/x/log.txt?x=15efc163200000
kernel config: https://syzkaller.appspot.com/x/.config?x=68044283f8b8640d
dashboard link: https://syzkaller.appspot.com/bug?extid=f583ce3d4ddf9836b27a
compiler: clang version 8.0.0 (trunk 350509)
syz repro: https://syzkaller.appspot.com/x/repro.syz?x=10775ecd200000
C reproducer: https://syzkaller.appspot.com/x/repro.c?x=1364b30f200000
IMPORTANT: if you fix the bug, please add the following tag to the commit:
Reported-by: syzbot+f583ce3d4ddf9836b27a@syzkaller.appspotmail.com
IPv6: ADDRCONF(NETDEV_CHANGE): hsr_slave_1: link becomes ready
IPv6: ADDRCONF(NETDEV_CHANGE): hsr0: link becomes ready
8021q: adding VLAN 0 to HW filter on device batadv0
raw_sendmsg: syz-executor949 forgot to set AF_INET. Fix it!
==================================================================
BUG: KMSAN: uninit-value in __arch_swab32
arch/x86/include/uapi/asm/swab.h:10 [inline]
BUG: KMSAN: uninit-value in __fswab32 include/uapi/linux/swab.h:59 [inline]
BUG: KMSAN: uninit-value in gre_parse_header+0x1396/0x1690
net/ipv4/gre_demux.c:136
CPU: 1 PID: 10485 Comm: syz-executor949 Not tainted 5.1.0-rc2+ #21
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
Call Trace:
<IRQ>
__dump_stack lib/dump_stack.c:77 [inline]
dump_stack+0x173/0x1d0 lib/dump_stack.c:113
kmsan_report+0x131/0x2a0 mm/kmsan/kmsan.c:624
__msan_warning+0x7a/0xf0 mm/kmsan/kmsan_instr.c:310
__arch_swab32 arch/x86/include/uapi/asm/swab.h:10 [inline]
__fswab32 include/uapi/linux/swab.h:59 [inline]
gre_parse_header+0x1396/0x1690 net/ipv4/gre_demux.c:136
gre_rcv+0x1c3/0x1800 net/ipv4/ip_gre.c:409
gre_rcv+0x2dd/0x3c0 net/ipv4/gre_demux.c:160
ip_protocol_deliver_rcu+0x584/0xbb0 net/ipv4/ip_input.c:208
ip_local_deliver_finish net/ipv4/ip_input.c:234 [inline]
NF_HOOK include/linux/netfilter.h:289 [inline]
ip_local_deliver+0x624/0x7b0 net/ipv4/ip_input.c:255
dst_input include/net/dst.h:450 [inline]
ip_rcv_finish net/ipv4/ip_input.c:414 [inline]
NF_HOOK include/linux/netfilter.h:289 [inline]
ip_rcv+0x6bd/0x740 net/ipv4/ip_input.c:524
__netif_receive_skb_one_core net/core/dev.c:4973 [inline]
__netif_receive_skb net/core/dev.c:5083 [inline]
process_backlog+0x756/0x10e0 net/core/dev.c:5923
napi_poll net/core/dev.c:6346 [inline]
net_rx_action+0x78b/0x1a60 net/core/dev.c:6412
__do_softirq+0x53f/0x93a kernel/softirq.c:294
do_softirq_own_stack+0x49/0x80 arch/x86/entry/entry_64.S:1039
</IRQ>
do_softirq kernel/softirq.c:339 [inline]
__local_bh_enable_ip+0x1a3/0x1f0 kernel/softirq.c:191
local_bh_enable+0x36/0x40 include/linux/bottom_half.h:32
rcu_read_unlock_bh include/linux/rcupdate.h:684 [inline]
ip_finish_output2+0x1721/0x1930 net/ipv4/ip_output.c:231
ip_finish_output+0xd2b/0xfd0 net/ipv4/ip_output.c:317
NF_HOOK_COND include/linux/netfilter.h:278 [inline]
ip_output+0x53f/0x610 net/ipv4/ip_output.c:405
dst_output include/net/dst.h:444 [inline]
ip_local_out net/ipv4/ip_output.c:124 [inline]
ip_send_skb net/ipv4/ip_output.c:1465 [inline]
ip_push_pending_frames+0x243/0x460 net/ipv4/ip_output.c:1485
raw_sendmsg+0x2e31/0x4650 net/ipv4/raw.c:676
inet_sendmsg+0x54a/0x720 net/ipv4/af_inet.c:798
sock_sendmsg_nosec net/socket.c:622 [inline]
sock_sendmsg net/socket.c:632 [inline]
___sys_sendmsg+0xdb3/0x1220 net/socket.c:2137
__sys_sendmmsg+0x580/0xad0 net/socket.c:2232
__do_sys_sendmmsg net/socket.c:2261 [inline]
__se_sys_sendmmsg+0xbd/0xe0 net/socket.c:2258
__x64_sys_sendmmsg+0x56/0x70 net/socket.c:2258
do_syscall_64+0xbc/0xf0 arch/x86/entry/common.c:291
entry_SYSCALL_64_after_hwframe+0x63/0xe7
RIP: 0033:0x441999
Code: 18 89 d0 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 00 48 89 f8 48 89 f7
48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff
ff 0f 83 bb 10 fc ff c3 66 2e 0f 1f 84 00 00 00 00
RSP: 002b:00007ffd647de1c8 EFLAGS: 00000246 ORIG_RAX: 0000000000000133
RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 0000000000441999
RDX: 0000000000000001 RSI: 00000000200006c0 RDI: 0000000000000004
RBP: 00000000004a9030 R08: 0000000001bbbbbb R09: 0000000001bbbbbb
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000402ee0
R13: 0000000000402f70 R14: 0000000000000000 R15: 0000000000000000
Uninit was stored to memory at:
kmsan_save_stack_with_flags mm/kmsan/kmsan.c:205 [inline]
kmsan_save_stack mm/kmsan/kmsan.c:220 [inline]
kmsan_internal_chain_origin+0x134/0x230 mm/kmsan/kmsan.c:426
kmsan_memcpy_memmove_metadata+0xb5b/0xfe0 mm/kmsan/kmsan.c:304
kmsan_memcpy_metadata+0xb/0x10 mm/kmsan/kmsan.c:324
__msan_memcpy+0x58/0x70 mm/kmsan/kmsan_instr.c:139
pskb_expand_head+0x3aa/0x1a30 net/core/skbuff.c:1478
__skb_cow include/linux/skbuff.h:3029 [inline]
skb_cow_head include/linux/skbuff.h:3063 [inline]
ip_tunnel_xmit+0x2c4e/0x3310 net/ipv4/ip_tunnel.c:824
__gre_xmit net/ipv4/ip_gre.c:444 [inline]
erspan_xmit+0x1f5e/0x3640 net/ipv4/ip_gre.c:679
__netdev_start_xmit include/linux/netdevice.h:4411 [inline]
netdev_start_xmit include/linux/netdevice.h:4420 [inline]
xmit_one net/core/dev.c:3278 [inline]
dev_hard_start_xmit+0x604/0xc40 net/core/dev.c:3294
sch_direct_xmit+0x58a/0x880 net/sched/sch_generic.c:327
qdisc_restart net/sched/sch_generic.c:390 [inline]
__qdisc_run+0x1cd7/0x34b0 net/sched/sch_generic.c:398
qdisc_run include/net/pkt_sched.h:121 [inline]
__dev_xmit_skb net/core/dev.c:3473 [inline]
__dev_queue_xmit+0x1e51/0x3ce0 net/core/dev.c:3832
dev_queue_xmit+0x4b/0x60 net/core/dev.c:3897
neigh_resolve_output+0xab7/0xb40 net/core/neighbour.c:1487
neigh_output include/net/neighbour.h:508 [inline]
ip_finish_output2+0x1709/0x1930 net/ipv4/ip_output.c:229
ip_finish_output+0xd2b/0xfd0 net/ipv4/ip_output.c:317
NF_HOOK_COND include/linux/netfilter.h:278 [inline]
ip_output+0x53f/0x610 net/ipv4/ip_output.c:405
dst_output include/net/dst.h:444 [inline]
ip_local_out net/ipv4/ip_output.c:124 [inline]
ip_send_skb net/ipv4/ip_output.c:1465 [inline]
ip_push_pending_frames+0x243/0x460 net/ipv4/ip_output.c:1485
raw_sendmsg+0x2e31/0x4650 net/ipv4/raw.c:676
inet_sendmsg+0x54a/0x720 net/ipv4/af_inet.c:798
sock_sendmsg_nosec net/socket.c:622 [inline]
sock_sendmsg net/socket.c:632 [inline]
___sys_sendmsg+0xdb3/0x1220 net/socket.c:2137
__sys_sendmmsg+0x580/0xad0 net/socket.c:2232
__do_sys_sendmmsg net/socket.c:2261 [inline]
__se_sys_sendmmsg+0xbd/0xe0 net/socket.c:2258
__x64_sys_sendmmsg+0x56/0x70 net/socket.c:2258
do_syscall_64+0xbc/0xf0 arch/x86/entry/common.c:291
entry_SYSCALL_64_after_hwframe+0x63/0xe7
Uninit was created at:
kmsan_save_stack_with_flags mm/kmsan/kmsan.c:205 [inline]
kmsan_internal_poison_shadow+0x92/0x150 mm/kmsan/kmsan.c:159
kmsan_kmalloc+0xa9/0x130 mm/kmsan/kmsan_hooks.c:173
kmsan_slab_alloc+0xe/0x10 mm/kmsan/kmsan_hooks.c:182
slab_post_alloc_hook mm/slab.h:441 [inline]
slab_alloc_node mm/slub.c:2771 [inline]
__kmalloc_node_track_caller+0xead/0x1000 mm/slub.c:4396
__kmalloc_reserve net/core/skbuff.c:140 [inline]
__alloc_skb+0x309/0xa20 net/core/skbuff.c:208
alloc_skb include/linux/skbuff.h:1059 [inline]
__ip_append_data+0x3671/0x5000 net/ipv4/ip_output.c:1005
ip_append_data+0x324/0x480 net/ipv4/ip_output.c:1220
raw_sendmsg+0x2d2a/0x4650 net/ipv4/raw.c:670
inet_sendmsg+0x54a/0x720 net/ipv4/af_inet.c:798
sock_sendmsg_nosec net/socket.c:622 [inline]
sock_sendmsg net/socket.c:632 [inline]
___sys_sendmsg+0xdb3/0x1220 net/socket.c:2137
__sys_sendmmsg+0x580/0xad0 net/socket.c:2232
__do_sys_sendmmsg net/socket.c:2261 [inline]
__se_sys_sendmmsg+0xbd/0xe0 net/socket.c:2258
__x64_sys_sendmmsg+0x56/0x70 net/socket.c:2258
do_syscall_64+0xbc/0xf0 arch/x86/entry/common.c:291
entry_SYSCALL_64_after_hwframe+0x63/0xe7
==================================================================
---
This bug is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.
syzbot will keep track of this bug report. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.
syzbot can test patches for this bug, for details see:
https://goo.gl/tpsmEJ#testing-patches
^ permalink raw reply
* Re: [PATCH v4 3/5] net: macb: add support for c45 PHY
From: Russell King - ARM Linux admin @ 2019-06-23 10:12 UTC (permalink / raw)
To: Parshuram Thombare
Cc: andrew, nicolas.ferre, davem, f.fainelli, netdev, hkallweit1,
linux-kernel, rafalc, aniljoy, piotrs
In-Reply-To: <1561281797-13796-1-git-send-email-pthombar@cadence.com>
On Sun, Jun 23, 2019 at 10:23:17AM +0100, Parshuram Thombare wrote:
> This patch modify MDIO read/write functions to support
> communication with C45 PHY.
Which Clause 45 PHY are you using?
>
> Signed-off-by: Parshuram Thombare <pthombar@cadence.com>
> ---
> drivers/net/ethernet/cadence/macb.h | 15 ++++--
> drivers/net/ethernet/cadence/macb_main.c | 61 +++++++++++++++++++-----
> 2 files changed, 61 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
> index 6d268283c318..330da702b946 100644
> --- a/drivers/net/ethernet/cadence/macb.h
> +++ b/drivers/net/ethernet/cadence/macb.h
> @@ -642,10 +642,17 @@
> #define GEM_CLK_DIV96 5
>
> /* Constants for MAN register */
> -#define MACB_MAN_SOF 1
> -#define MACB_MAN_WRITE 1
> -#define MACB_MAN_READ 2
> -#define MACB_MAN_CODE 2
> +#define MACB_MAN_C22_SOF 1
> +#define MACB_MAN_C22_WRITE 1
> +#define MACB_MAN_C22_READ 2
> +#define MACB_MAN_C22_CODE 2
> +
> +#define MACB_MAN_C45_SOF 0
> +#define MACB_MAN_C45_ADDR 0
> +#define MACB_MAN_C45_WRITE 1
> +#define MACB_MAN_C45_POST_READ_INCR 2
> +#define MACB_MAN_C45_READ 3
> +#define MACB_MAN_C45_CODE 2
>
> /* Capability mask bits */
> #define MACB_CAPS_ISR_CLEAR_ON_WRITE BIT(0)
> diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
> index 10d18b2cef31..94145e460e6e 100644
> --- a/drivers/net/ethernet/cadence/macb_main.c
> +++ b/drivers/net/ethernet/cadence/macb_main.c
> @@ -341,11 +341,30 @@ static int macb_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
> if (status < 0)
> goto mdio_read_exit;
>
> - macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF)
> - | MACB_BF(RW, MACB_MAN_READ)
> - | MACB_BF(PHYA, mii_id)
> - | MACB_BF(REGA, regnum)
> - | MACB_BF(CODE, MACB_MAN_CODE)));
> + if (regnum & MII_ADDR_C45) {
> + macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_C45_SOF)
> + | MACB_BF(RW, MACB_MAN_C45_ADDR)
> + | MACB_BF(PHYA, mii_id)
> + | MACB_BF(REGA, (regnum >> 16) & 0x1F)
> + | MACB_BF(DATA, regnum & 0xFFFF)
> + | MACB_BF(CODE, MACB_MAN_C45_CODE)));
> +
> + status = macb_mdio_wait_for_idle(bp);
> + if (status < 0)
> + goto mdio_read_exit;
> +
> + macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_C45_SOF)
> + | MACB_BF(RW, MACB_MAN_C45_READ)
> + | MACB_BF(PHYA, mii_id)
> + | MACB_BF(REGA, (regnum >> 16) & 0x1F)
> + | MACB_BF(CODE, MACB_MAN_C45_CODE)));
> + } else {
> + macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_C22_SOF)
> + | MACB_BF(RW, MACB_MAN_C22_READ)
> + | MACB_BF(PHYA, mii_id)
> + | MACB_BF(REGA, regnum)
> + | MACB_BF(CODE, MACB_MAN_C22_CODE)));
> + }
>
> status = macb_mdio_wait_for_idle(bp);
> if (status < 0)
> @@ -374,12 +393,32 @@ static int macb_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
> if (status < 0)
> goto mdio_write_exit;
>
> - macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF)
> - | MACB_BF(RW, MACB_MAN_WRITE)
> - | MACB_BF(PHYA, mii_id)
> - | MACB_BF(REGA, regnum)
> - | MACB_BF(CODE, MACB_MAN_CODE)
> - | MACB_BF(DATA, value)));
> + if (regnum & MII_ADDR_C45) {
> + macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_C45_SOF)
> + | MACB_BF(RW, MACB_MAN_C45_ADDR)
> + | MACB_BF(PHYA, mii_id)
> + | MACB_BF(REGA, (regnum >> 16) & 0x1F)
> + | MACB_BF(DATA, regnum & 0xFFFF)
> + | MACB_BF(CODE, MACB_MAN_C45_CODE)));
> +
> + status = macb_mdio_wait_for_idle(bp);
> + if (status < 0)
> + goto mdio_write_exit;
> +
> + macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_C45_SOF)
> + | MACB_BF(RW, MACB_MAN_C45_WRITE)
> + | MACB_BF(PHYA, mii_id)
> + | MACB_BF(REGA, (regnum >> 16) & 0x1F)
> + | MACB_BF(CODE, MACB_MAN_C45_CODE)
> + | MACB_BF(DATA, value)));
> + } else {
> + macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_C22_SOF)
> + | MACB_BF(RW, MACB_MAN_C22_WRITE)
> + | MACB_BF(PHYA, mii_id)
> + | MACB_BF(REGA, regnum)
> + | MACB_BF(CODE, MACB_MAN_C22_CODE)
> + | MACB_BF(DATA, value)));
> + }
>
> status = macb_mdio_wait_for_idle(bp);
> if (status < 0)
> --
> 2.17.1
>
>
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 12.1Mbps down 622kbps up
According to speedtest.net: 11.9Mbps down 500kbps up
^ permalink raw reply
* Re: [PATCH v4 2/5] net: macb: add support for sgmii MAC-PHY interface
From: Russell King - ARM Linux admin @ 2019-06-23 10:12 UTC (permalink / raw)
To: Parshuram Thombare
Cc: andrew, nicolas.ferre, davem, f.fainelli, netdev, hkallweit1,
linux-kernel, rafalc, aniljoy, piotrs
In-Reply-To: <1561281781-13479-1-git-send-email-pthombar@cadence.com>
On Sun, Jun 23, 2019 at 10:23:01AM +0100, Parshuram Thombare wrote:
> This patch add support for SGMII interface) and
> 2.5Gbps MAC in Cadence ethernet controller driver.
>
> Signed-off-by: Parshuram Thombare <pthombar@cadence.com>
> ---
> drivers/net/ethernet/cadence/macb.h | 54 ++++++++++++----
> drivers/net/ethernet/cadence/macb_main.c | 80 +++++++++++++++++++++---
> 2 files changed, 112 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
> index 8629d345af31..6d268283c318 100644
> --- a/drivers/net/ethernet/cadence/macb.h
> +++ b/drivers/net/ethernet/cadence/macb.h
> @@ -77,6 +77,7 @@
> #define MACB_RBQPH 0x04D4
>
> /* GEM register offsets. */
> +#define GEM_NCR 0x0000 /* Network Control */
> #define GEM_NCFGR 0x0004 /* Network Config */
> #define GEM_USRIO 0x000c /* User IO */
> #define GEM_DMACFG 0x0010 /* DMA Configuration */
> @@ -156,6 +157,7 @@
> #define GEM_PEFTN 0x01f4 /* PTP Peer Event Frame Tx Ns */
> #define GEM_PEFRSL 0x01f8 /* PTP Peer Event Frame Rx Sec Low */
> #define GEM_PEFRN 0x01fc /* PTP Peer Event Frame Rx Ns */
> +#define GEM_PCS_CTRL 0x0200 /* PCS Control */
> #define GEM_DCFG1 0x0280 /* Design Config 1 */
> #define GEM_DCFG2 0x0284 /* Design Config 2 */
> #define GEM_DCFG3 0x0288 /* Design Config 3 */
> @@ -271,6 +273,10 @@
> #define MACB_IRXFCS_OFFSET 19
> #define MACB_IRXFCS_SIZE 1
>
> +/* GEM specific NCR bitfields. */
> +#define GEM_TWO_PT_FIVE_GIG_OFFSET 29
> +#define GEM_TWO_PT_FIVE_GIG_SIZE 1
> +
> /* GEM specific NCFGR bitfields. */
> #define GEM_GBE_OFFSET 10 /* Gigabit mode enable */
> #define GEM_GBE_SIZE 1
> @@ -323,6 +329,9 @@
> #define MACB_MDIO_SIZE 1
> #define MACB_IDLE_OFFSET 2 /* The PHY management logic is idle */
> #define MACB_IDLE_SIZE 1
> +#define MACB_DUPLEX_OFFSET 3
> +#define MACB_DUPLEX_SIZE 1
> +
>
> /* Bitfields in TSR */
> #define MACB_UBR_OFFSET 0 /* Used bit read */
> @@ -456,11 +465,17 @@
> #define MACB_REV_OFFSET 0
> #define MACB_REV_SIZE 16
>
> +/* Bitfields in PCS_CONTROL. */
> +#define GEM_PCS_CTRL_RST_OFFSET 15
> +#define GEM_PCS_CTRL_RST_SIZE 1
> +
> /* Bitfields in DCFG1. */
> #define GEM_IRQCOR_OFFSET 23
> #define GEM_IRQCOR_SIZE 1
> #define GEM_DBWDEF_OFFSET 25
> #define GEM_DBWDEF_SIZE 3
> +#define GEM_NO_PCS_OFFSET 0
> +#define GEM_NO_PCS_SIZE 1
>
> /* Bitfields in DCFG2. */
> #define GEM_RX_PKT_BUFF_OFFSET 20
> @@ -633,19 +648,32 @@
> #define MACB_MAN_CODE 2
>
> /* Capability mask bits */
> -#define MACB_CAPS_ISR_CLEAR_ON_WRITE 0x00000001
> -#define MACB_CAPS_USRIO_HAS_CLKEN 0x00000002
> -#define MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII 0x00000004
> -#define MACB_CAPS_NO_GIGABIT_HALF 0x00000008
> -#define MACB_CAPS_USRIO_DISABLED 0x00000010
> -#define MACB_CAPS_JUMBO 0x00000020
> -#define MACB_CAPS_GEM_HAS_PTP 0x00000040
> -#define MACB_CAPS_BD_RD_PREFETCH 0x00000080
> -#define MACB_CAPS_NEEDS_RSTONUBR 0x00000100
> -#define MACB_CAPS_FIFO_MODE 0x10000000
> -#define MACB_CAPS_GIGABIT_MODE_AVAILABLE 0x20000000
> -#define MACB_CAPS_SG_DISABLED 0x40000000
> -#define MACB_CAPS_MACB_IS_GEM 0x80000000
> +#define MACB_CAPS_ISR_CLEAR_ON_WRITE BIT(0)
> +#define MACB_CAPS_USRIO_HAS_CLKEN BIT(1)
> +#define MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII BIT(2)
> +#define MACB_CAPS_NO_GIGABIT_HALF BIT(3)
> +#define MACB_CAPS_USRIO_DISABLED BIT(4)
> +#define MACB_CAPS_JUMBO BIT(5)
> +#define MACB_CAPS_GEM_HAS_PTP BIT(6)
> +#define MACB_CAPS_BD_RD_PREFETCH BIT(7)
> +#define MACB_CAPS_NEEDS_RSTONUBR BIT(8)
> +#define MACB_CAPS_FIFO_MODE BIT(28)
> +#define MACB_CAPS_GIGABIT_MODE_AVAILABLE BIT(29)
> +#define MACB_CAPS_SG_DISABLED BIT(30)
> +#define MACB_CAPS_MACB_IS_GEM BIT(31)
> +#define MACB_CAPS_PCS BIT(24)
> +#define MACB_CAPS_MACB_IS_GEM_GXL BIT(25)
> +
> +#define MACB_GEM7010_IDNUM 0x009
> +#define MACB_GEM7014_IDNU 0x107
> +#define MACB_GEM7014A_IDNUM 0x207
> +#define MACB_GEM7016_IDNUM 0x10a
> +#define MACB_GEM7017_IDNUM 0x00a
> +#define MACB_GEM7017A_IDNUM 0x20a
> +#define MACB_GEM7020_IDNUM 0x003
> +#define MACB_GEM7021_IDNUM 0x00c
> +#define MACB_GEM7021A_IDNUM 0x20c
> +#define MACB_GEM7022_IDNUM 0x00b
>
> /* LSO settings */
> #define MACB_LSO_UFO_ENABLE 0x01
> diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
> index 1d6527a5313f..10d18b2cef31 100644
> --- a/drivers/net/ethernet/cadence/macb_main.c
> +++ b/drivers/net/ethernet/cadence/macb_main.c
> @@ -445,15 +445,15 @@ static void gem_phylink_validate(struct phylink_config *pl_config,
> __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
>
> switch (state->interface) {
> + case PHY_INTERFACE_MODE_NA:
> + case PHY_INTERFACE_MODE_SGMII:
> case PHY_INTERFACE_MODE_GMII:
> case PHY_INTERFACE_MODE_RGMII:
> if (bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE) {
> phylink_set(mask, 1000baseT_Full);
> phylink_set(mask, 1000baseX_Full);
> - if (!(bp->caps & MACB_CAPS_NO_GIGABIT_HALF)) {
> + if (!(bp->caps & MACB_CAPS_NO_GIGABIT_HALF))
> phylink_set(mask, 1000baseT_Half);
> - phylink_set(mask, 1000baseT_Half);
> - }
> }
> /* fallthrough */
> case PHY_INTERFACE_MODE_MII:
> @@ -469,7 +469,6 @@ static void gem_phylink_validate(struct phylink_config *pl_config,
>
> linkmode_and(supported, supported, mask);
> linkmode_and(state->advertising, state->advertising, mask);
> -
> }
>
> static int gem_phylink_mac_link_state(struct phylink_config *pl_config,
> @@ -483,19 +482,42 @@ static void gem_mac_config(struct phylink_config *pl_config, unsigned int mode,
> {
> struct net_device *netdev = to_net_dev(pl_config->dev);
> struct macb *bp = netdev_priv(netdev);
> + bool change_interface = bp->phy_interface != state->interface;
> unsigned long flags;
>
> spin_lock_irqsave(&bp->lock, flags);
>
> + if (change_interface) {
> + if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII) {
> + gem_writel(bp, NCFGR, ~GEM_BIT(SGMIIEN) &
> + ~GEM_BIT(PCSSEL) &
> + gem_readl(bp, NCFGR));
> + gem_writel(bp, NCR, ~GEM_BIT(TWO_PT_FIVE_GIG) &
> + gem_readl(bp, NCR));
> + gem_writel(bp, PCS_CTRL, gem_readl(bp, PCS_CTRL) |
> + GEM_BIT(PCS_CTRL_RST));
> + }
I still don't think this makes much sense, splitting the interface
configuration between here and below.
> + bp->phy_interface = state->interface;
> + }
> +
> if (!phylink_autoneg_inband(mode) &&
> (bp->speed != state->speed ||
> - bp->duplex != state->duplex)) {
> + bp->duplex != state->duplex ||
> + change_interface)) {
> u32 reg;
>
> reg = macb_readl(bp, NCFGR);
> reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
> if (macb_is_gem(bp))
> reg &= ~GEM_BIT(GBE);
> + macb_or_gem_writel(bp, NCFGR, reg);
> +
> + if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII)
> + gem_writel(bp, NCFGR, GEM_BIT(SGMIIEN) |
> + GEM_BIT(PCSSEL) |
> + gem_readl(bp, NCFGR));
This will only be executed when we are not using inband mode, which
basically means it's not possible to switch to SGMII in-band mode.
> +
> + reg = macb_readl(bp, NCFGR);
> if (state->duplex)
> reg |= MACB_BIT(FD);
>
> @@ -590,8 +612,8 @@ static int macb_mii_probe(struct net_device *dev)
> }
>
> bp->link = 0;
> - bp->speed = 0;
> - bp->duplex = -1;
> + bp->speed = SPEED_UNKNOWN;
> + bp->duplex = DUPLEX_UNKNOWN;
>
> return ret;
> }
> @@ -3340,6 +3362,22 @@ static void macb_configure_caps(struct macb *bp,
> dcfg = gem_readl(bp, DCFG1);
> if (GEM_BFEXT(IRQCOR, dcfg) == 0)
> bp->caps |= MACB_CAPS_ISR_CLEAR_ON_WRITE;
> + if (GEM_BFEXT(NO_PCS, dcfg) == 0)
> + bp->caps |= MACB_CAPS_PCS;
> + switch (MACB_BFEXT(IDNUM, macb_readl(bp, MID))) {
> + case MACB_GEM7016_IDNUM:
> + case MACB_GEM7017_IDNUM:
> + case MACB_GEM7017A_IDNUM:
> + case MACB_GEM7020_IDNUM:
> + case MACB_GEM7021_IDNUM:
> + case MACB_GEM7021A_IDNUM:
> + case MACB_GEM7022_IDNUM:
> + bp->caps |= MACB_CAPS_USRIO_DISABLED;
> + bp->caps |= MACB_CAPS_MACB_IS_GEM_GXL;
> + break;
> + default:
> + break;
> + }
> dcfg = gem_readl(bp, DCFG2);
> if ((dcfg & (GEM_BIT(RX_PKT_BUFF) | GEM_BIT(TX_PKT_BUFF))) == 0)
> bp->caps |= MACB_CAPS_FIFO_MODE;
> @@ -4322,11 +4360,35 @@ static int macb_probe(struct platform_device *pdev)
> }
>
> phy_mode = of_get_phy_mode(np);
> - if (phy_mode < 0)
> + if (phy_mode < 0) {
> /* not found in DT, MII by default */
> bp->phy_interface = PHY_INTERFACE_MODE_MII;
> - else
> + } else if (bp->caps & MACB_CAPS_MACB_IS_GEM_GXL) {
> + u32 interface_supported = 1;
> +
> + if (phy_mode == PHY_INTERFACE_MODE_SGMII) {
> + if (!(bp->caps & MACB_CAPS_PCS))
> + interface_supported = 0;
> + } else if (phy_mode == PHY_INTERFACE_MODE_GMII ||
> + phy_mode == PHY_INTERFACE_MODE_RGMII) {
> + if (!macb_is_gem(bp))
> + interface_supported = 0;
> + } else if (phy_mode != PHY_INTERFACE_MODE_RMII &&
> + phy_mode != PHY_INTERFACE_MODE_MII) {
> + /* Add new mode before this */
> + interface_supported = 0;
> + }
> +
> + if (!interface_supported) {
> + netdev_err(dev, "Phy mode %s not supported",
> + phy_modes(phy_mode));
> + goto err_out_free_netdev;
> + }
> +
> bp->phy_interface = phy_mode;
> + } else {
> + bp->phy_interface = phy_mode;
> + }
If bp->phy_interface is PHY_INTERFACE_MODE_SGMII here, and mac_config()
is called with state->interface = PHY_INTERFACE_MODE_SGMII, then
mac_config() won't configure the MAC for the interface type - is that
intentional?
>
> /* IP specific init */
> err = init(pdev);
> --
> 2.17.1
>
>
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 12.1Mbps down 622kbps up
According to speedtest.net: 11.9Mbps down 500kbps up
^ permalink raw reply
* Re: [PATCH v4 1/5] net: macb: add phylink support
From: Russell King - ARM Linux admin @ 2019-06-23 10:08 UTC (permalink / raw)
To: Parshuram Thombare
Cc: andrew, nicolas.ferre, davem, f.fainelli, netdev, hkallweit1,
linux-kernel, rafalc, aniljoy, piotrs
In-Reply-To: <1561281457-6886-1-git-send-email-pthombar@cadence.com>
On Sun, Jun 23, 2019 at 10:17:37AM +0100, Parshuram Thombare wrote:
> + switch (state->interface) {
> + case PHY_INTERFACE_MODE_GMII:
> + case PHY_INTERFACE_MODE_RGMII:
> + if (bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE) {
> + phylink_set(mask, 1000baseT_Full);
> + phylink_set(mask, 1000baseX_Full);
> + if (!(bp->caps & MACB_CAPS_NO_GIGABIT_HALF)) {
> + phylink_set(mask, 1000baseT_Half);
> + phylink_set(mask, 1000baseT_Half);
I think this can be cleaned up.
> + }
> + }
> + /* fallthrough */
> + case PHY_INTERFACE_MODE_MII:
> + case PHY_INTERFACE_MODE_RMII:
> + phylink_set(mask, 10baseT_Half);
> + phylink_set(mask, 10baseT_Full);
> + phylink_set(mask, 100baseT_Half);
> + phylink_set(mask, 100baseT_Full);
> + break;
> + default:
> + break;
> + }
>
> - spin_lock_irqsave(&bp->lock, flags);
> + linkmode_and(supported, supported, mask);
> + linkmode_and(state->advertising, state->advertising, mask);
>
You remove this blank line in the next patch, so given that this is a
new function, you might as well clean that up in this patch.
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 12.1Mbps down 622kbps up
According to speedtest.net: 11.9Mbps down 500kbps up
^ permalink raw reply
* Re: WARNING in debug_check_no_obj_freed
From: syzbot @ 2019-06-23 9:47 UTC (permalink / raw)
To: alexander.h.duyck, amritha.nambiar, andriy.shevchenko, ast, bpf,
daniel, davem, dmitry.torokhov, f.fainelli, idosch,
jeffrey.t.kirsher, jiri, kafai, kgraul, linux-kernel, linux-s390,
netdev, songliubraving, syzkaller-bugs, tyhicks, ubraun,
wanghai26, yhs, yuehaibing
In-Reply-To: <00000000000090ae7a058bc12946@google.com>
syzbot has bisected this bug to:
commit 99182beed858a1bde22f60046602b9b223225f73
Author: Daniel Borkmann <daniel@iogearbox.net>
Date: Tue Apr 2 21:17:19 2019 +0000
Merge branch 'bpf-selftest-clang-fixes'
bisection log: https://syzkaller.appspot.com/x/bisect.txt?x=12faf81aa00000
start commit: bed3c0d8 Merge tag 'for-5.2-rc5-tag' of git://git.kernel.o..
git tree: upstream
final crash: https://syzkaller.appspot.com/x/report.txt?x=11faf81aa00000
console output: https://syzkaller.appspot.com/x/log.txt?x=16faf81aa00000
kernel config: https://syzkaller.appspot.com/x/.config?x=28ec3437a5394ee0
dashboard link: https://syzkaller.appspot.com/bug?extid=b972214bb803a343f4fe
syz repro: https://syzkaller.appspot.com/x/repro.syz?x=12fcf0b2a00000
C reproducer: https://syzkaller.appspot.com/x/repro.c?x=17a22ad6a00000
Reported-by: syzbot+b972214bb803a343f4fe@syzkaller.appspotmail.com
Fixes: 99182beed858 ("Merge branch 'bpf-selftest-clang-fixes'")
For information about bisection process see: https://goo.gl/tpsmEJ#bisection
^ permalink raw reply
* [PATCH v4 5/5] net: macb: parameter added to cadence ethernet controller DT binding
From: Parshuram Thombare @ 2019-06-23 9:24 UTC (permalink / raw)
To: andrew, nicolas.ferre, davem, f.fainelli
Cc: linux, netdev, hkallweit1, linux-kernel, rafalc, aniljoy, piotrs,
pthombar
In-Reply-To: <1561281419-6030-1-git-send-email-pthombar@cadence.com>
New parameters added to Cadence ethernet controller DT binding
for USXGMII interface.
Signed-off-by: Parshuram Thombare <pthombar@cadence.com>
---
Documentation/devicetree/bindings/net/macb.txt | 3 +++
1 file changed, 3 insertions(+)
diff --git a/Documentation/devicetree/bindings/net/macb.txt b/Documentation/devicetree/bindings/net/macb.txt
index 63c73fafe26d..dabdf9d3b574 100644
--- a/Documentation/devicetree/bindings/net/macb.txt
+++ b/Documentation/devicetree/bindings/net/macb.txt
@@ -28,6 +28,9 @@ Required properties:
Optional elements: 'rx_clk' applies to cdns,zynqmp-gem
Optional elements: 'tsu_clk'
- clocks: Phandles to input clocks.
+- serdes-rate-gbps External serdes rate.Mandatory for USXGMII mode.
+ 5 - 5G
+ 10 - 10G
The MAC address will be determined using the optional properties
defined in ethernet.txt.
--
2.17.1
^ permalink raw reply related
* [PATCH v4 4/5] net: macb: add support for high speed interface
From: Parshuram Thombare @ 2019-06-23 9:23 UTC (permalink / raw)
To: andrew, nicolas.ferre, davem, f.fainelli
Cc: linux, netdev, hkallweit1, linux-kernel, rafalc, aniljoy, piotrs,
pthombar
In-Reply-To: <1561281419-6030-1-git-send-email-pthombar@cadence.com>
This patch add support for high speed USXGMII PCS and 10G
speed in Cadence ethernet controller driver.
Signed-off-by: Parshuram Thombare <pthombar@cadence.com>
---
drivers/net/ethernet/cadence/macb.h | 41 +++++
drivers/net/ethernet/cadence/macb_main.c | 194 +++++++++++++++++++----
2 files changed, 207 insertions(+), 28 deletions(-)
diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
index 330da702b946..809acff19be9 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -82,6 +82,7 @@
#define GEM_USRIO 0x000c /* User IO */
#define GEM_DMACFG 0x0010 /* DMA Configuration */
#define GEM_JML 0x0048 /* Jumbo Max Length */
+#define GEM_HS_MAC_CONFIG 0x0050 /* GEM high speed config */
#define GEM_HRB 0x0080 /* Hash Bottom */
#define GEM_HRT 0x0084 /* Hash Top */
#define GEM_SA1B 0x0088 /* Specific1 Bottom */
@@ -167,6 +168,9 @@
#define GEM_DCFG7 0x0298 /* Design Config 7 */
#define GEM_DCFG8 0x029C /* Design Config 8 */
#define GEM_DCFG10 0x02A4 /* Design Config 10 */
+#define GEM_DCFG12 0x02AC /* Design Config 12 */
+#define GEM_USX_CONTROL 0x0A80 /* USXGMII control register */
+#define GEM_USX_STATUS 0x0A88 /* USXGMII status register */
#define GEM_TXBDCTRL 0x04cc /* TX Buffer Descriptor control register */
#define GEM_RXBDCTRL 0x04d0 /* RX Buffer Descriptor control register */
@@ -274,6 +278,8 @@
#define MACB_IRXFCS_SIZE 1
/* GEM specific NCR bitfields. */
+#define GEM_ENABLE_HS_MAC_OFFSET 31
+#define GEM_ENABLE_HS_MAC_SIZE 1
#define GEM_TWO_PT_FIVE_GIG_OFFSET 29
#define GEM_TWO_PT_FIVE_GIG_SIZE 1
@@ -465,6 +471,10 @@
#define MACB_REV_OFFSET 0
#define MACB_REV_SIZE 16
+/* Bitfield in HS_MAC_CONFIG */
+#define GEM_HS_MAC_SPEED_OFFSET 0
+#define GEM_HS_MAC_SPEED_SIZE 3
+
/* Bitfields in PCS_CONTROL. */
#define GEM_PCS_CTRL_RST_OFFSET 15
#define GEM_PCS_CTRL_RST_SIZE 1
@@ -510,6 +520,34 @@
#define GEM_RXBD_RDBUFF_OFFSET 8
#define GEM_RXBD_RDBUFF_SIZE 4
+/* Bitfields in DCFG12. */
+#define GEM_HIGH_SPEED_OFFSET 26
+#define GEM_HIGH_SPEED_SIZE 1
+
+/* Bitfields in USX_CONTROL. */
+#define GEM_USX_CTRL_SPEED_OFFSET 14
+#define GEM_USX_CTRL_SPEED_SIZE 3
+#define GEM_SERDES_RATE_OFFSET 12
+#define GEM_SERDES_RATE_SIZE 2
+#define GEM_RX_SCR_BYPASS_OFFSET 9
+#define GEM_RX_SCR_BYPASS_SIZE 1
+#define GEM_TX_SCR_BYPASS_OFFSET 8
+#define GEM_TX_SCR_BYPASS_SIZE 1
+#define GEM_RX_SYNC_RESET_OFFSET 2
+#define GEM_RX_SYNC_RESET_SIZE 1
+#define GEM_TX_EN_OFFSET 1
+#define GEM_TX_EN_SIZE 1
+#define GEM_SIGNAL_OK_OFFSET 0
+#define GEM_SIGNAL_OK_SIZE 1
+
+/* Bitfields in USX_STATUS. */
+#define GEM_USX_TX_FAULT_OFFSET 28
+#define GEM_USX_TX_FAULT_SIZE 1
+#define GEM_USX_RX_FAULT_OFFSET 27
+#define GEM_USX_RX_FAULT_SIZE 1
+#define GEM_USX_BLOCK_LOCK_OFFSET 0
+#define GEM_USX_BLOCK_LOCK_SIZE 1
+
/* Bitfields in TISUBN */
#define GEM_SUBNSINCR_OFFSET 0
#define GEM_SUBNSINCR_SIZE 16
@@ -670,6 +708,7 @@
#define MACB_CAPS_MACB_IS_GEM BIT(31)
#define MACB_CAPS_PCS BIT(24)
#define MACB_CAPS_MACB_IS_GEM_GXL BIT(25)
+#define MACB_CAPS_HIGH_SPEED BIT(26)
#define MACB_GEM7010_IDNUM 0x009
#define MACB_GEM7014_IDNU 0x107
@@ -749,6 +788,7 @@
})
#define MACB_READ_NSR(bp) macb_readl(bp, NSR)
+#define GEM_READ_USX_STATUS(bp) gem_readl(bp, USX_STATUS)
/* struct macb_dma_desc - Hardware DMA descriptor
* @addr: DMA address of data buffer
@@ -1262,6 +1302,7 @@ struct macb {
struct macb_pm_data pm_data;
struct phylink *pl;
struct phylink_config pl_config;
+ u32 serdes_rate;
};
#ifdef CONFIG_MACB_USE_HWSTAMP
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index 94145e460e6e..65eda399aef8 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -84,6 +84,20 @@ static struct sifive_fu540_macb_mgmt *mgmt;
#define MACB_WOL_HAS_MAGIC_PACKET (0x1 << 0)
#define MACB_WOL_ENABLED (0x1 << 1)
+enum {
+ HS_MAC_SPEED_100M,
+ HS_MAC_SPEED_1000M,
+ HS_MAC_SPEED_2500M,
+ HS_MAC_SPEED_5000M,
+ HS_MAC_SPEED_10000M,
+ HS_MAC_SPEED_25000M,
+};
+
+enum {
+ MACB_SERDES_RATE_5_PT_15625Gbps = 5,
+ MACB_SERDES_RATE_10_PT_3125Gbps = 10,
+};
+
/* Graceful stop timeouts in us. We should allow up to
* 1 frame time (10 Mbits/s, full-duplex, ignoring collisions)
*/
@@ -93,6 +107,8 @@ static struct sifive_fu540_macb_mgmt *mgmt;
#define MACB_MDIO_TIMEOUT 1000000 /* in usecs */
+#define MACB_USX_BLOCK_LOCK_TIMEOUT 1000000 /* in usecs */
+
/* DMA buffer descriptor might be different size
* depends on hardware configuration:
*
@@ -439,23 +455,37 @@ static int macb_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
*/
static void macb_set_tx_clk(struct clk *clk, int speed, struct net_device *dev)
{
+ struct macb *bp = netdev_priv(dev);
long ferr, rate, rate_rounded;
if (!clk)
return;
- switch (speed) {
- case SPEED_10:
- rate = 2500000;
- break;
- case SPEED_100:
- rate = 25000000;
- break;
- case SPEED_1000:
- rate = 125000000;
- break;
- default:
- return;
+ if (bp->phy_interface == PHY_INTERFACE_MODE_USXGMII) {
+ switch (bp->serdes_rate) {
+ case MACB_SERDES_RATE_5_PT_15625Gbps:
+ rate = 78125000;
+ break;
+ case MACB_SERDES_RATE_10_PT_3125Gbps:
+ rate = 156250000;
+ break;
+ default:
+ return;
+ }
+ } else {
+ switch (speed) {
+ case SPEED_10:
+ rate = 2500000;
+ break;
+ case SPEED_100:
+ rate = 25000000;
+ break;
+ case SPEED_1000:
+ rate = 125000000;
+ break;
+ default:
+ return;
+ }
}
rate_rounded = clk_round_rate(clk, rate);
@@ -485,6 +515,21 @@ static void gem_phylink_validate(struct phylink_config *pl_config,
switch (state->interface) {
case PHY_INTERFACE_MODE_NA:
+ case PHY_INTERFACE_MODE_USXGMII:
+ case PHY_INTERFACE_MODE_10GKR:
+ if (bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE) {
+ phylink_set(mask, 10000baseCR_Full);
+ phylink_set(mask, 10000baseER_Full);
+ phylink_set(mask, 10000baseKR_Full);
+ phylink_set(mask, 10000baseLR_Full);
+ phylink_set(mask, 10000baseLRM_Full);
+ phylink_set(mask, 10000baseSR_Full);
+ phylink_set(mask, 10000baseT_Full);
+ phylink_set(mask, 5000baseT_Full);
+ phylink_set(mask, 2500baseX_Full);
+ phylink_set(mask, 1000baseX_Full);
+ }
+ /* fallthrough */
case PHY_INTERFACE_MODE_SGMII:
case PHY_INTERFACE_MODE_GMII:
case PHY_INTERFACE_MODE_RGMII:
@@ -516,6 +561,91 @@ static int gem_phylink_mac_link_state(struct phylink_config *pl_config,
return -EOPNOTSUPP;
}
+static int macb_wait_for_usx_block_lock(struct macb *bp)
+{
+ u32 val;
+
+ return readx_poll_timeout(GEM_READ_USX_STATUS, bp, val,
+ val & GEM_BIT(USX_BLOCK_LOCK),
+ 1, MACB_USX_BLOCK_LOCK_TIMEOUT);
+}
+
+static inline int gem_mac_usx_configure(struct macb *bp, int spd)
+{
+ u32 speed, config;
+
+ gem_writel(bp, NCFGR, GEM_BIT(PCSSEL) |
+ (~GEM_BIT(SGMIIEN) & gem_readl(bp, NCFGR)));
+ gem_writel(bp, NCR, gem_readl(bp, NCR) |
+ GEM_BIT(ENABLE_HS_MAC));
+ gem_writel(bp, NCFGR, gem_readl(bp, NCFGR) |
+ MACB_BIT(FD));
+ config = gem_readl(bp, USX_CONTROL);
+ config = GEM_BFINS(SERDES_RATE, bp->serdes_rate, config);
+ config &= ~GEM_BIT(TX_SCR_BYPASS);
+ config &= ~GEM_BIT(RX_SCR_BYPASS);
+ gem_writel(bp, USX_CONTROL, config |
+ GEM_BIT(TX_EN));
+ config = gem_readl(bp, USX_CONTROL);
+ gem_writel(bp, USX_CONTROL, config | GEM_BIT(SIGNAL_OK));
+ if (macb_wait_for_usx_block_lock(bp) < 0) {
+ netdev_warn(bp->dev, "USXGMII block lock failed");
+ return -ETIMEDOUT;
+ }
+
+ switch (spd) {
+ case SPEED_10000:
+ if (bp->serdes_rate >= MACB_SERDES_RATE_10_PT_3125Gbps) {
+ speed = HS_MAC_SPEED_10000M;
+ } else {
+ netdev_warn(bp->dev, "10G speed isn't supported by HW");
+ netdev_warn(bp->dev, "Setting speed to 1G");
+ speed = HS_MAC_SPEED_1000M;
+ }
+ break;
+ case SPEED_5000:
+ speed = HS_MAC_SPEED_5000M;
+ break;
+ case SPEED_2500:
+ speed = HS_MAC_SPEED_2500M;
+ break;
+ case SPEED_1000:
+ speed = HS_MAC_SPEED_1000M;
+ break;
+ default:
+ case SPEED_100:
+ speed = HS_MAC_SPEED_100M;
+ break;
+ }
+
+ gem_writel(bp, HS_MAC_CONFIG, GEM_BFINS(HS_MAC_SPEED, speed,
+ gem_readl(bp, HS_MAC_CONFIG)));
+ gem_writel(bp, USX_CONTROL, GEM_BFINS(USX_CTRL_SPEED, speed,
+ gem_readl(bp, USX_CONTROL)));
+ return 0;
+}
+
+static inline void gem_mac_configure(struct macb *bp, int speed)
+{
+ if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII)
+ gem_writel(bp, NCFGR, GEM_BIT(SGMIIEN) |
+ GEM_BIT(PCSSEL) |
+ gem_readl(bp, NCFGR));
+
+ switch (speed) {
+ case SPEED_1000:
+ gem_writel(bp, NCFGR, GEM_BIT(GBE) |
+ gem_readl(bp, NCFGR));
+ break;
+ case SPEED_100:
+ macb_writel(bp, NCFGR, MACB_BIT(SPD) |
+ macb_readl(bp, NCFGR));
+ break;
+ default:
+ break;
+ }
+}
+
static void gem_mac_config(struct phylink_config *pl_config, unsigned int mode,
const struct phylink_link_state *state)
{
@@ -551,26 +681,20 @@ static void gem_mac_config(struct phylink_config *pl_config, unsigned int mode,
reg &= ~GEM_BIT(GBE);
macb_or_gem_writel(bp, NCFGR, reg);
- if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII)
- gem_writel(bp, NCFGR, GEM_BIT(SGMIIEN) |
- GEM_BIT(PCSSEL) |
- gem_readl(bp, NCFGR));
-
reg = macb_readl(bp, NCFGR);
if (state->duplex)
reg |= MACB_BIT(FD);
+ macb_or_gem_writel(bp, NCFGR, reg);
- switch (state->speed) {
- case SPEED_1000:
- reg |= GEM_BIT(GBE);
- break;
- case SPEED_100:
- reg |= MACB_BIT(SPD);
- break;
- default:
- break;
+ if (bp->phy_interface == PHY_INTERFACE_MODE_USXGMII) {
+ if (gem_mac_usx_configure(bp, state->speed) < 0) {
+ spin_unlock_irqrestore(&bp->lock, flags);
+ phylink_mac_change(bp->pl, false);
+ return;
+ }
+ } else {
+ gem_mac_configure(bp, state->speed);
}
- macb_or_gem_writel(bp, NCFGR, reg);
bp->speed = state->speed;
bp->duplex = state->duplex;
@@ -3417,6 +3541,9 @@ static void macb_configure_caps(struct macb *bp,
default:
break;
}
+ dcfg = gem_readl(bp, DCFG12);
+ if (GEM_BFEXT(HIGH_SPEED, dcfg) == 1)
+ bp->caps |= MACB_CAPS_HIGH_SPEED;
dcfg = gem_readl(bp, DCFG2);
if ((dcfg & (GEM_BIT(RX_PKT_BUFF) | GEM_BIT(TX_PKT_BUFF))) == 0)
bp->caps |= MACB_CAPS_FIFO_MODE;
@@ -4405,7 +4532,18 @@ static int macb_probe(struct platform_device *pdev)
} else if (bp->caps & MACB_CAPS_MACB_IS_GEM_GXL) {
u32 interface_supported = 1;
- if (phy_mode == PHY_INTERFACE_MODE_SGMII) {
+ if (phy_mode == PHY_INTERFACE_MODE_USXGMII) {
+ if (!(bp->caps & MACB_CAPS_HIGH_SPEED &&
+ bp->caps & MACB_CAPS_PCS))
+ interface_supported = 0;
+
+ if (of_property_read_u32(np, "serdes-rate-gbps",
+ &bp->serdes_rate)) {
+ netdev_err(dev,
+ "GEM serdes_rate not specified");
+ interface_supported = 0;
+ }
+ } else if (phy_mode == PHY_INTERFACE_MODE_SGMII) {
if (!(bp->caps & MACB_CAPS_PCS))
interface_supported = 0;
} else if (phy_mode == PHY_INTERFACE_MODE_GMII ||
--
2.17.1
^ permalink raw reply related
* [PATCH v4 3/5] net: macb: add support for c45 PHY
From: Parshuram Thombare @ 2019-06-23 9:23 UTC (permalink / raw)
To: andrew, nicolas.ferre, davem, f.fainelli
Cc: linux, netdev, hkallweit1, linux-kernel, rafalc, aniljoy, piotrs,
pthombar
In-Reply-To: <1561281419-6030-1-git-send-email-pthombar@cadence.com>
This patch modify MDIO read/write functions to support
communication with C45 PHY.
Signed-off-by: Parshuram Thombare <pthombar@cadence.com>
---
drivers/net/ethernet/cadence/macb.h | 15 ++++--
drivers/net/ethernet/cadence/macb_main.c | 61 +++++++++++++++++++-----
2 files changed, 61 insertions(+), 15 deletions(-)
diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
index 6d268283c318..330da702b946 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -642,10 +642,17 @@
#define GEM_CLK_DIV96 5
/* Constants for MAN register */
-#define MACB_MAN_SOF 1
-#define MACB_MAN_WRITE 1
-#define MACB_MAN_READ 2
-#define MACB_MAN_CODE 2
+#define MACB_MAN_C22_SOF 1
+#define MACB_MAN_C22_WRITE 1
+#define MACB_MAN_C22_READ 2
+#define MACB_MAN_C22_CODE 2
+
+#define MACB_MAN_C45_SOF 0
+#define MACB_MAN_C45_ADDR 0
+#define MACB_MAN_C45_WRITE 1
+#define MACB_MAN_C45_POST_READ_INCR 2
+#define MACB_MAN_C45_READ 3
+#define MACB_MAN_C45_CODE 2
/* Capability mask bits */
#define MACB_CAPS_ISR_CLEAR_ON_WRITE BIT(0)
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index 10d18b2cef31..94145e460e6e 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -341,11 +341,30 @@ static int macb_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
if (status < 0)
goto mdio_read_exit;
- macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF)
- | MACB_BF(RW, MACB_MAN_READ)
- | MACB_BF(PHYA, mii_id)
- | MACB_BF(REGA, regnum)
- | MACB_BF(CODE, MACB_MAN_CODE)));
+ if (regnum & MII_ADDR_C45) {
+ macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_C45_SOF)
+ | MACB_BF(RW, MACB_MAN_C45_ADDR)
+ | MACB_BF(PHYA, mii_id)
+ | MACB_BF(REGA, (regnum >> 16) & 0x1F)
+ | MACB_BF(DATA, regnum & 0xFFFF)
+ | MACB_BF(CODE, MACB_MAN_C45_CODE)));
+
+ status = macb_mdio_wait_for_idle(bp);
+ if (status < 0)
+ goto mdio_read_exit;
+
+ macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_C45_SOF)
+ | MACB_BF(RW, MACB_MAN_C45_READ)
+ | MACB_BF(PHYA, mii_id)
+ | MACB_BF(REGA, (regnum >> 16) & 0x1F)
+ | MACB_BF(CODE, MACB_MAN_C45_CODE)));
+ } else {
+ macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_C22_SOF)
+ | MACB_BF(RW, MACB_MAN_C22_READ)
+ | MACB_BF(PHYA, mii_id)
+ | MACB_BF(REGA, regnum)
+ | MACB_BF(CODE, MACB_MAN_C22_CODE)));
+ }
status = macb_mdio_wait_for_idle(bp);
if (status < 0)
@@ -374,12 +393,32 @@ static int macb_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
if (status < 0)
goto mdio_write_exit;
- macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF)
- | MACB_BF(RW, MACB_MAN_WRITE)
- | MACB_BF(PHYA, mii_id)
- | MACB_BF(REGA, regnum)
- | MACB_BF(CODE, MACB_MAN_CODE)
- | MACB_BF(DATA, value)));
+ if (regnum & MII_ADDR_C45) {
+ macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_C45_SOF)
+ | MACB_BF(RW, MACB_MAN_C45_ADDR)
+ | MACB_BF(PHYA, mii_id)
+ | MACB_BF(REGA, (regnum >> 16) & 0x1F)
+ | MACB_BF(DATA, regnum & 0xFFFF)
+ | MACB_BF(CODE, MACB_MAN_C45_CODE)));
+
+ status = macb_mdio_wait_for_idle(bp);
+ if (status < 0)
+ goto mdio_write_exit;
+
+ macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_C45_SOF)
+ | MACB_BF(RW, MACB_MAN_C45_WRITE)
+ | MACB_BF(PHYA, mii_id)
+ | MACB_BF(REGA, (regnum >> 16) & 0x1F)
+ | MACB_BF(CODE, MACB_MAN_C45_CODE)
+ | MACB_BF(DATA, value)));
+ } else {
+ macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_C22_SOF)
+ | MACB_BF(RW, MACB_MAN_C22_WRITE)
+ | MACB_BF(PHYA, mii_id)
+ | MACB_BF(REGA, regnum)
+ | MACB_BF(CODE, MACB_MAN_C22_CODE)
+ | MACB_BF(DATA, value)));
+ }
status = macb_mdio_wait_for_idle(bp);
if (status < 0)
--
2.17.1
^ permalink raw reply related
* [PATCH v4 2/5] net: macb: add support for sgmii MAC-PHY interface
From: Parshuram Thombare @ 2019-06-23 9:23 UTC (permalink / raw)
To: andrew, nicolas.ferre, davem, f.fainelli
Cc: linux, netdev, hkallweit1, linux-kernel, rafalc, aniljoy, piotrs,
pthombar
In-Reply-To: <1561281419-6030-1-git-send-email-pthombar@cadence.com>
This patch add support for SGMII interface) and
2.5Gbps MAC in Cadence ethernet controller driver.
Signed-off-by: Parshuram Thombare <pthombar@cadence.com>
---
drivers/net/ethernet/cadence/macb.h | 54 ++++++++++++----
drivers/net/ethernet/cadence/macb_main.c | 80 +++++++++++++++++++++---
2 files changed, 112 insertions(+), 22 deletions(-)
diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
index 8629d345af31..6d268283c318 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -77,6 +77,7 @@
#define MACB_RBQPH 0x04D4
/* GEM register offsets. */
+#define GEM_NCR 0x0000 /* Network Control */
#define GEM_NCFGR 0x0004 /* Network Config */
#define GEM_USRIO 0x000c /* User IO */
#define GEM_DMACFG 0x0010 /* DMA Configuration */
@@ -156,6 +157,7 @@
#define GEM_PEFTN 0x01f4 /* PTP Peer Event Frame Tx Ns */
#define GEM_PEFRSL 0x01f8 /* PTP Peer Event Frame Rx Sec Low */
#define GEM_PEFRN 0x01fc /* PTP Peer Event Frame Rx Ns */
+#define GEM_PCS_CTRL 0x0200 /* PCS Control */
#define GEM_DCFG1 0x0280 /* Design Config 1 */
#define GEM_DCFG2 0x0284 /* Design Config 2 */
#define GEM_DCFG3 0x0288 /* Design Config 3 */
@@ -271,6 +273,10 @@
#define MACB_IRXFCS_OFFSET 19
#define MACB_IRXFCS_SIZE 1
+/* GEM specific NCR bitfields. */
+#define GEM_TWO_PT_FIVE_GIG_OFFSET 29
+#define GEM_TWO_PT_FIVE_GIG_SIZE 1
+
/* GEM specific NCFGR bitfields. */
#define GEM_GBE_OFFSET 10 /* Gigabit mode enable */
#define GEM_GBE_SIZE 1
@@ -323,6 +329,9 @@
#define MACB_MDIO_SIZE 1
#define MACB_IDLE_OFFSET 2 /* The PHY management logic is idle */
#define MACB_IDLE_SIZE 1
+#define MACB_DUPLEX_OFFSET 3
+#define MACB_DUPLEX_SIZE 1
+
/* Bitfields in TSR */
#define MACB_UBR_OFFSET 0 /* Used bit read */
@@ -456,11 +465,17 @@
#define MACB_REV_OFFSET 0
#define MACB_REV_SIZE 16
+/* Bitfields in PCS_CONTROL. */
+#define GEM_PCS_CTRL_RST_OFFSET 15
+#define GEM_PCS_CTRL_RST_SIZE 1
+
/* Bitfields in DCFG1. */
#define GEM_IRQCOR_OFFSET 23
#define GEM_IRQCOR_SIZE 1
#define GEM_DBWDEF_OFFSET 25
#define GEM_DBWDEF_SIZE 3
+#define GEM_NO_PCS_OFFSET 0
+#define GEM_NO_PCS_SIZE 1
/* Bitfields in DCFG2. */
#define GEM_RX_PKT_BUFF_OFFSET 20
@@ -633,19 +648,32 @@
#define MACB_MAN_CODE 2
/* Capability mask bits */
-#define MACB_CAPS_ISR_CLEAR_ON_WRITE 0x00000001
-#define MACB_CAPS_USRIO_HAS_CLKEN 0x00000002
-#define MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII 0x00000004
-#define MACB_CAPS_NO_GIGABIT_HALF 0x00000008
-#define MACB_CAPS_USRIO_DISABLED 0x00000010
-#define MACB_CAPS_JUMBO 0x00000020
-#define MACB_CAPS_GEM_HAS_PTP 0x00000040
-#define MACB_CAPS_BD_RD_PREFETCH 0x00000080
-#define MACB_CAPS_NEEDS_RSTONUBR 0x00000100
-#define MACB_CAPS_FIFO_MODE 0x10000000
-#define MACB_CAPS_GIGABIT_MODE_AVAILABLE 0x20000000
-#define MACB_CAPS_SG_DISABLED 0x40000000
-#define MACB_CAPS_MACB_IS_GEM 0x80000000
+#define MACB_CAPS_ISR_CLEAR_ON_WRITE BIT(0)
+#define MACB_CAPS_USRIO_HAS_CLKEN BIT(1)
+#define MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII BIT(2)
+#define MACB_CAPS_NO_GIGABIT_HALF BIT(3)
+#define MACB_CAPS_USRIO_DISABLED BIT(4)
+#define MACB_CAPS_JUMBO BIT(5)
+#define MACB_CAPS_GEM_HAS_PTP BIT(6)
+#define MACB_CAPS_BD_RD_PREFETCH BIT(7)
+#define MACB_CAPS_NEEDS_RSTONUBR BIT(8)
+#define MACB_CAPS_FIFO_MODE BIT(28)
+#define MACB_CAPS_GIGABIT_MODE_AVAILABLE BIT(29)
+#define MACB_CAPS_SG_DISABLED BIT(30)
+#define MACB_CAPS_MACB_IS_GEM BIT(31)
+#define MACB_CAPS_PCS BIT(24)
+#define MACB_CAPS_MACB_IS_GEM_GXL BIT(25)
+
+#define MACB_GEM7010_IDNUM 0x009
+#define MACB_GEM7014_IDNU 0x107
+#define MACB_GEM7014A_IDNUM 0x207
+#define MACB_GEM7016_IDNUM 0x10a
+#define MACB_GEM7017_IDNUM 0x00a
+#define MACB_GEM7017A_IDNUM 0x20a
+#define MACB_GEM7020_IDNUM 0x003
+#define MACB_GEM7021_IDNUM 0x00c
+#define MACB_GEM7021A_IDNUM 0x20c
+#define MACB_GEM7022_IDNUM 0x00b
/* LSO settings */
#define MACB_LSO_UFO_ENABLE 0x01
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index 1d6527a5313f..10d18b2cef31 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -445,15 +445,15 @@ static void gem_phylink_validate(struct phylink_config *pl_config,
__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
switch (state->interface) {
+ case PHY_INTERFACE_MODE_NA:
+ case PHY_INTERFACE_MODE_SGMII:
case PHY_INTERFACE_MODE_GMII:
case PHY_INTERFACE_MODE_RGMII:
if (bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE) {
phylink_set(mask, 1000baseT_Full);
phylink_set(mask, 1000baseX_Full);
- if (!(bp->caps & MACB_CAPS_NO_GIGABIT_HALF)) {
+ if (!(bp->caps & MACB_CAPS_NO_GIGABIT_HALF))
phylink_set(mask, 1000baseT_Half);
- phylink_set(mask, 1000baseT_Half);
- }
}
/* fallthrough */
case PHY_INTERFACE_MODE_MII:
@@ -469,7 +469,6 @@ static void gem_phylink_validate(struct phylink_config *pl_config,
linkmode_and(supported, supported, mask);
linkmode_and(state->advertising, state->advertising, mask);
-
}
static int gem_phylink_mac_link_state(struct phylink_config *pl_config,
@@ -483,19 +482,42 @@ static void gem_mac_config(struct phylink_config *pl_config, unsigned int mode,
{
struct net_device *netdev = to_net_dev(pl_config->dev);
struct macb *bp = netdev_priv(netdev);
+ bool change_interface = bp->phy_interface != state->interface;
unsigned long flags;
spin_lock_irqsave(&bp->lock, flags);
+ if (change_interface) {
+ if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII) {
+ gem_writel(bp, NCFGR, ~GEM_BIT(SGMIIEN) &
+ ~GEM_BIT(PCSSEL) &
+ gem_readl(bp, NCFGR));
+ gem_writel(bp, NCR, ~GEM_BIT(TWO_PT_FIVE_GIG) &
+ gem_readl(bp, NCR));
+ gem_writel(bp, PCS_CTRL, gem_readl(bp, PCS_CTRL) |
+ GEM_BIT(PCS_CTRL_RST));
+ }
+ bp->phy_interface = state->interface;
+ }
+
if (!phylink_autoneg_inband(mode) &&
(bp->speed != state->speed ||
- bp->duplex != state->duplex)) {
+ bp->duplex != state->duplex ||
+ change_interface)) {
u32 reg;
reg = macb_readl(bp, NCFGR);
reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
if (macb_is_gem(bp))
reg &= ~GEM_BIT(GBE);
+ macb_or_gem_writel(bp, NCFGR, reg);
+
+ if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII)
+ gem_writel(bp, NCFGR, GEM_BIT(SGMIIEN) |
+ GEM_BIT(PCSSEL) |
+ gem_readl(bp, NCFGR));
+
+ reg = macb_readl(bp, NCFGR);
if (state->duplex)
reg |= MACB_BIT(FD);
@@ -590,8 +612,8 @@ static int macb_mii_probe(struct net_device *dev)
}
bp->link = 0;
- bp->speed = 0;
- bp->duplex = -1;
+ bp->speed = SPEED_UNKNOWN;
+ bp->duplex = DUPLEX_UNKNOWN;
return ret;
}
@@ -3340,6 +3362,22 @@ static void macb_configure_caps(struct macb *bp,
dcfg = gem_readl(bp, DCFG1);
if (GEM_BFEXT(IRQCOR, dcfg) == 0)
bp->caps |= MACB_CAPS_ISR_CLEAR_ON_WRITE;
+ if (GEM_BFEXT(NO_PCS, dcfg) == 0)
+ bp->caps |= MACB_CAPS_PCS;
+ switch (MACB_BFEXT(IDNUM, macb_readl(bp, MID))) {
+ case MACB_GEM7016_IDNUM:
+ case MACB_GEM7017_IDNUM:
+ case MACB_GEM7017A_IDNUM:
+ case MACB_GEM7020_IDNUM:
+ case MACB_GEM7021_IDNUM:
+ case MACB_GEM7021A_IDNUM:
+ case MACB_GEM7022_IDNUM:
+ bp->caps |= MACB_CAPS_USRIO_DISABLED;
+ bp->caps |= MACB_CAPS_MACB_IS_GEM_GXL;
+ break;
+ default:
+ break;
+ }
dcfg = gem_readl(bp, DCFG2);
if ((dcfg & (GEM_BIT(RX_PKT_BUFF) | GEM_BIT(TX_PKT_BUFF))) == 0)
bp->caps |= MACB_CAPS_FIFO_MODE;
@@ -4322,11 +4360,35 @@ static int macb_probe(struct platform_device *pdev)
}
phy_mode = of_get_phy_mode(np);
- if (phy_mode < 0)
+ if (phy_mode < 0) {
/* not found in DT, MII by default */
bp->phy_interface = PHY_INTERFACE_MODE_MII;
- else
+ } else if (bp->caps & MACB_CAPS_MACB_IS_GEM_GXL) {
+ u32 interface_supported = 1;
+
+ if (phy_mode == PHY_INTERFACE_MODE_SGMII) {
+ if (!(bp->caps & MACB_CAPS_PCS))
+ interface_supported = 0;
+ } else if (phy_mode == PHY_INTERFACE_MODE_GMII ||
+ phy_mode == PHY_INTERFACE_MODE_RGMII) {
+ if (!macb_is_gem(bp))
+ interface_supported = 0;
+ } else if (phy_mode != PHY_INTERFACE_MODE_RMII &&
+ phy_mode != PHY_INTERFACE_MODE_MII) {
+ /* Add new mode before this */
+ interface_supported = 0;
+ }
+
+ if (!interface_supported) {
+ netdev_err(dev, "Phy mode %s not supported",
+ phy_modes(phy_mode));
+ goto err_out_free_netdev;
+ }
+
bp->phy_interface = phy_mode;
+ } else {
+ bp->phy_interface = phy_mode;
+ }
/* IP specific init */
err = init(pdev);
--
2.17.1
^ permalink raw reply related
* [PATCH v4 1/5] net: macb: add phylink support
From: Parshuram Thombare @ 2019-06-23 9:17 UTC (permalink / raw)
To: andrew, nicolas.ferre, davem, f.fainelli
Cc: linux, netdev, hkallweit1, linux-kernel, rafalc, aniljoy, piotrs,
pthombar
In-Reply-To: <1561281419-6030-1-git-send-email-pthombar@cadence.com>
This patch replace phylib API's by phylink API's.
Signed-off-by: Parshuram Thombare <pthombar@cadence.com>
---
drivers/net/ethernet/cadence/Kconfig | 2 +-
drivers/net/ethernet/cadence/macb.h | 3 +
drivers/net/ethernet/cadence/macb_main.c | 304 ++++++++++++-----------
3 files changed, 166 insertions(+), 143 deletions(-)
diff --git a/drivers/net/ethernet/cadence/Kconfig b/drivers/net/ethernet/cadence/Kconfig
index 1766697c9c5a..d71411a71587 100644
--- a/drivers/net/ethernet/cadence/Kconfig
+++ b/drivers/net/ethernet/cadence/Kconfig
@@ -22,7 +22,7 @@ if NET_VENDOR_CADENCE
config MACB
tristate "Cadence MACB/GEM support"
depends on HAS_DMA
- select PHYLIB
+ select PHYLINK
---help---
The Cadence MACB ethernet interface is found on many Atmel AT32 and
AT91 parts. This driver also supports the Cadence GEM (Gigabit
diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
index 6ff123da6a14..8629d345af31 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -11,6 +11,7 @@
#include <linux/ptp_clock_kernel.h>
#include <linux/net_tstamp.h>
#include <linux/interrupt.h>
+#include <linux/phylink.h>
#if defined(CONFIG_ARCH_DMA_ADDR_T_64BIT) || defined(CONFIG_MACB_USE_HWSTAMP)
#define MACB_EXT_DESC
@@ -1224,6 +1225,8 @@ struct macb {
u32 rx_intr_mask;
struct macb_pm_data pm_data;
+ struct phylink *pl;
+ struct phylink_config pl_config;
};
#ifdef CONFIG_MACB_USE_HWSTAMP
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index b4fa0111cd7a..1d6527a5313f 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -36,6 +36,7 @@
#include <linux/tcp.h>
#include <linux/iopoll.h>
#include <linux/pm_runtime.h>
+#include <linux/phylink.h>
#include "macb.h"
/* This structure is only used for MACB on SiFive FU540 devices */
@@ -435,115 +436,145 @@ static void macb_set_tx_clk(struct clk *clk, int speed, struct net_device *dev)
netdev_err(dev, "adjusting tx_clk failed.\n");
}
-static void macb_handle_link_change(struct net_device *dev)
+static void gem_phylink_validate(struct phylink_config *pl_config,
+ unsigned long *supported,
+ struct phylink_link_state *state)
{
- struct macb *bp = netdev_priv(dev);
- struct phy_device *phydev = dev->phydev;
- unsigned long flags;
- int status_change = 0;
+ struct net_device *netdev = to_net_dev(pl_config->dev);
+ struct macb *bp = netdev_priv(netdev);
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
+
+ switch (state->interface) {
+ case PHY_INTERFACE_MODE_GMII:
+ case PHY_INTERFACE_MODE_RGMII:
+ if (bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE) {
+ phylink_set(mask, 1000baseT_Full);
+ phylink_set(mask, 1000baseX_Full);
+ if (!(bp->caps & MACB_CAPS_NO_GIGABIT_HALF)) {
+ phylink_set(mask, 1000baseT_Half);
+ phylink_set(mask, 1000baseT_Half);
+ }
+ }
+ /* fallthrough */
+ case PHY_INTERFACE_MODE_MII:
+ case PHY_INTERFACE_MODE_RMII:
+ phylink_set(mask, 10baseT_Half);
+ phylink_set(mask, 10baseT_Full);
+ phylink_set(mask, 100baseT_Half);
+ phylink_set(mask, 100baseT_Full);
+ break;
+ default:
+ break;
+ }
- spin_lock_irqsave(&bp->lock, flags);
+ linkmode_and(supported, supported, mask);
+ linkmode_and(state->advertising, state->advertising, mask);
- if (phydev->link) {
- if ((bp->speed != phydev->speed) ||
- (bp->duplex != phydev->duplex)) {
- u32 reg;
+}
- reg = macb_readl(bp, NCFGR);
- reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
- if (macb_is_gem(bp))
- reg &= ~GEM_BIT(GBE);
+static int gem_phylink_mac_link_state(struct phylink_config *pl_config,
+ struct phylink_link_state *state)
+{
+ return -EOPNOTSUPP;
+}
- if (phydev->duplex)
- reg |= MACB_BIT(FD);
- if (phydev->speed == SPEED_100)
- reg |= MACB_BIT(SPD);
- if (phydev->speed == SPEED_1000 &&
- bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE)
- reg |= GEM_BIT(GBE);
+static void gem_mac_config(struct phylink_config *pl_config, unsigned int mode,
+ const struct phylink_link_state *state)
+{
+ struct net_device *netdev = to_net_dev(pl_config->dev);
+ struct macb *bp = netdev_priv(netdev);
+ unsigned long flags;
- macb_or_gem_writel(bp, NCFGR, reg);
+ spin_lock_irqsave(&bp->lock, flags);
- bp->speed = phydev->speed;
- bp->duplex = phydev->duplex;
- status_change = 1;
- }
- }
+ if (!phylink_autoneg_inband(mode) &&
+ (bp->speed != state->speed ||
+ bp->duplex != state->duplex)) {
+ u32 reg;
- if (phydev->link != bp->link) {
- if (!phydev->link) {
- bp->speed = 0;
- bp->duplex = -1;
+ reg = macb_readl(bp, NCFGR);
+ reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
+ if (macb_is_gem(bp))
+ reg &= ~GEM_BIT(GBE);
+ if (state->duplex)
+ reg |= MACB_BIT(FD);
+
+ switch (state->speed) {
+ case SPEED_1000:
+ reg |= GEM_BIT(GBE);
+ break;
+ case SPEED_100:
+ reg |= MACB_BIT(SPD);
+ break;
+ default:
+ break;
}
- bp->link = phydev->link;
+ macb_or_gem_writel(bp, NCFGR, reg);
+
+ bp->speed = state->speed;
+ bp->duplex = state->duplex;
- status_change = 1;
+ if (state->link)
+ macb_set_tx_clk(bp->tx_clk, state->speed, netdev);
}
spin_unlock_irqrestore(&bp->lock, flags);
+}
- if (status_change) {
- if (phydev->link) {
- /* Update the TX clock rate if and only if the link is
- * up and there has been a link change.
- */
- macb_set_tx_clk(bp->tx_clk, phydev->speed, dev);
+static void gem_mac_link_up(struct phylink_config *pl_config, unsigned int mode,
+ phy_interface_t interface, struct phy_device *phy)
+{
+ struct net_device *netdev = to_net_dev(pl_config->dev);
+ struct macb *bp = netdev_priv(netdev);
- netif_carrier_on(dev);
- netdev_info(dev, "link up (%d/%s)\n",
- phydev->speed,
- phydev->duplex == DUPLEX_FULL ?
- "Full" : "Half");
- } else {
- netif_carrier_off(dev);
- netdev_info(dev, "link down\n");
- }
- }
+ bp->link = 1;
+ /* Enable TX and RX */
+ macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(RE) | MACB_BIT(TE));
+}
+
+static void gem_mac_link_down(struct phylink_config *pl_config,
+ unsigned int mode, phy_interface_t interface)
+{
+ struct net_device *netdev = to_net_dev(pl_config->dev);
+ struct macb *bp = netdev_priv(netdev);
+
+ bp->link = 0;
+ /* Disable TX and RX */
+ macb_writel(bp, NCR,
+ macb_readl(bp, NCR) & ~(MACB_BIT(RE) | MACB_BIT(TE)));
}
+static const struct phylink_mac_ops gem_phylink_ops = {
+ .validate = gem_phylink_validate,
+ .mac_link_state = gem_phylink_mac_link_state,
+ .mac_config = gem_mac_config,
+ .mac_link_up = gem_mac_link_up,
+ .mac_link_down = gem_mac_link_down,
+};
+
/* based on au1000_eth. c*/
static int macb_mii_probe(struct net_device *dev)
{
struct macb *bp = netdev_priv(dev);
struct phy_device *phydev;
struct device_node *np;
- int ret, i;
+ int ret;
np = bp->pdev->dev.of_node;
ret = 0;
- if (np) {
- if (of_phy_is_fixed_link(np)) {
- bp->phy_node = of_node_get(np);
- } else {
- bp->phy_node = of_parse_phandle(np, "phy-handle", 0);
- /* fallback to standard phy registration if no
- * phy-handle was found nor any phy found during
- * dt phy registration
- */
- if (!bp->phy_node && !phy_find_first(bp->mii_bus)) {
- for (i = 0; i < PHY_MAX_ADDR; i++) {
- phydev = mdiobus_scan(bp->mii_bus, i);
- if (IS_ERR(phydev) &&
- PTR_ERR(phydev) != -ENODEV) {
- ret = PTR_ERR(phydev);
- break;
- }
- }
-
- if (ret)
- return -ENODEV;
- }
- }
+ bp->pl_config.dev = &dev->dev;
+ bp->pl_config.type = PHYLINK_NETDEV;
+ bp->pl = phylink_create(&bp->pl_config, of_fwnode_handle(np),
+ bp->phy_interface, &gem_phylink_ops);
+ if (IS_ERR(bp->pl)) {
+ netdev_err(dev,
+ "error creating PHYLINK: %ld\n", PTR_ERR(bp->pl));
+ return PTR_ERR(bp->pl);
}
- if (bp->phy_node) {
- phydev = of_phy_connect(dev, bp->phy_node,
- &macb_handle_link_change, 0,
- bp->phy_interface);
- if (!phydev)
- return -ENODEV;
- } else {
+ ret = phylink_of_phy_connect(bp->pl, np, 0);
+ if (ret == -ENODEV && bp->mii_bus) {
phydev = phy_find_first(bp->mii_bus);
if (!phydev) {
netdev_err(dev, "no PHY found\n");
@@ -551,29 +582,18 @@ static int macb_mii_probe(struct net_device *dev)
}
/* attach the mac to the phy */
- ret = phy_connect_direct(dev, phydev, &macb_handle_link_change,
- bp->phy_interface);
+ ret = phylink_connect_phy(bp->pl, phydev);
if (ret) {
netdev_err(dev, "Could not attach to PHY\n");
return ret;
}
}
- /* mask with MAC supported features */
- if (macb_is_gem(bp) && bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE)
- phy_set_max_speed(phydev, SPEED_1000);
- else
- phy_set_max_speed(phydev, SPEED_100);
-
- if (bp->caps & MACB_CAPS_NO_GIGABIT_HALF)
- phy_remove_link_mode(phydev,
- ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
-
bp->link = 0;
bp->speed = 0;
bp->duplex = -1;
- return 0;
+ return ret;
}
static int macb_mii_init(struct macb *bp)
@@ -601,17 +621,7 @@ static int macb_mii_init(struct macb *bp)
dev_set_drvdata(&bp->dev->dev, bp->mii_bus);
np = bp->pdev->dev.of_node;
- if (np && of_phy_is_fixed_link(np)) {
- if (of_phy_register_fixed_link(np) < 0) {
- dev_err(&bp->pdev->dev,
- "broken fixed-link specification %pOF\n", np);
- goto err_out_free_mdiobus;
- }
-
- err = mdiobus_register(bp->mii_bus);
- } else {
- err = of_mdiobus_register(bp->mii_bus, np);
- }
+ err = of_mdiobus_register(bp->mii_bus, np);
if (err)
goto err_out_free_fixed_link;
@@ -627,7 +637,6 @@ static int macb_mii_init(struct macb *bp)
err_out_free_fixed_link:
if (np && of_phy_is_fixed_link(np))
of_phy_deregister_fixed_link(np);
-err_out_free_mdiobus:
of_node_put(bp->phy_node);
mdiobus_free(bp->mii_bus);
err_out:
@@ -2418,12 +2427,6 @@ static int macb_open(struct net_device *dev)
/* carrier starts down */
netif_carrier_off(dev);
- /* if the phy is not yet register, retry later*/
- if (!dev->phydev) {
- err = -EAGAIN;
- goto pm_exit;
- }
-
/* RX buffers initialization */
macb_init_rx_buffer_size(bp, bufsz);
@@ -2441,7 +2444,7 @@ static int macb_open(struct net_device *dev)
macb_init_hw(bp);
/* schedule a link state check */
- phy_start(dev->phydev);
+ phylink_start(bp->pl);
netif_tx_start_all_queues(dev);
@@ -2468,8 +2471,7 @@ static int macb_close(struct net_device *dev)
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue)
napi_disable(&queue->napi);
- if (dev->phydev)
- phy_stop(dev->phydev);
+ phylink_stop(bp->pl);
spin_lock_irqsave(&bp->lock, flags);
macb_reset_hw(bp);
@@ -3158,6 +3160,23 @@ static int gem_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd)
return ret;
}
+static int gem_ethtool_get_link_ksettings(struct net_device *netdev,
+ struct ethtool_link_ksettings *cmd)
+{
+ struct macb *bp = netdev_priv(netdev);
+
+ return phylink_ethtool_ksettings_get(bp->pl, cmd);
+}
+
+static int
+gem_ethtool_set_link_ksettings(struct net_device *netdev,
+ const struct ethtool_link_ksettings *cmd)
+{
+ struct macb *bp = netdev_priv(netdev);
+
+ return phylink_ethtool_ksettings_set(bp->pl, cmd);
+}
+
static const struct ethtool_ops macb_ethtool_ops = {
.get_regs_len = macb_get_regs_len,
.get_regs = macb_get_regs,
@@ -3165,8 +3184,8 @@ static const struct ethtool_ops macb_ethtool_ops = {
.get_ts_info = ethtool_op_get_ts_info,
.get_wol = macb_get_wol,
.set_wol = macb_set_wol,
- .get_link_ksettings = phy_ethtool_get_link_ksettings,
- .set_link_ksettings = phy_ethtool_set_link_ksettings,
+ .get_link_ksettings = gem_ethtool_get_link_ksettings,
+ .set_link_ksettings = gem_ethtool_set_link_ksettings,
.get_ringparam = macb_get_ringparam,
.set_ringparam = macb_set_ringparam,
};
@@ -3179,8 +3198,8 @@ static const struct ethtool_ops gem_ethtool_ops = {
.get_ethtool_stats = gem_get_ethtool_stats,
.get_strings = gem_get_ethtool_strings,
.get_sset_count = gem_get_sset_count,
- .get_link_ksettings = phy_ethtool_get_link_ksettings,
- .set_link_ksettings = phy_ethtool_set_link_ksettings,
+ .get_link_ksettings = gem_ethtool_get_link_ksettings,
+ .set_link_ksettings = gem_ethtool_set_link_ksettings,
.get_ringparam = macb_get_ringparam,
.set_ringparam = macb_set_ringparam,
.get_rxnfc = gem_get_rxnfc,
@@ -3189,17 +3208,13 @@ static const struct ethtool_ops gem_ethtool_ops = {
static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
- struct phy_device *phydev = dev->phydev;
struct macb *bp = netdev_priv(dev);
if (!netif_running(dev))
return -EINVAL;
- if (!phydev)
- return -ENODEV;
-
if (!bp->ptp_info)
- return phy_mii_ioctl(phydev, rq, cmd);
+ return phylink_mii_ioctl(bp->pl, rq, cmd);
switch (cmd) {
case SIOCSHWTSTAMP:
@@ -3207,7 +3222,7 @@ static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
case SIOCGHWTSTAMP:
return bp->ptp_info->get_hwtst(dev, rq);
default:
- return phy_mii_ioctl(phydev, rq, cmd);
+ return phylink_mii_ioctl(bp->pl, rq, cmd);
}
}
@@ -3707,7 +3722,7 @@ static int at91ether_open(struct net_device *dev)
MACB_BIT(HRESP));
/* schedule a link state check */
- phy_start(dev->phydev);
+ phylink_start(lp->pl);
netif_start_queue(dev);
@@ -4180,13 +4195,12 @@ static int macb_probe(struct platform_device *pdev)
struct clk *tsu_clk = NULL;
unsigned int queue_mask, num_queues;
bool native_io;
- struct phy_device *phydev;
struct net_device *dev;
struct resource *regs;
void __iomem *mem;
const char *mac;
struct macb *bp;
- int err, val;
+ int err, val, phy_mode;
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mem = devm_ioremap_resource(&pdev->dev, regs);
@@ -4307,12 +4321,12 @@ static int macb_probe(struct platform_device *pdev)
macb_get_hwaddr(bp);
}
- err = of_get_phy_mode(np);
- if (err < 0)
+ phy_mode = of_get_phy_mode(np);
+ if (phy_mode < 0)
/* not found in DT, MII by default */
bp->phy_interface = PHY_INTERFACE_MODE_MII;
else
- bp->phy_interface = err;
+ bp->phy_interface = phy_mode;
/* IP specific init */
err = init(pdev);
@@ -4323,8 +4337,6 @@ static int macb_probe(struct platform_device *pdev)
if (err)
goto err_out_free_netdev;
- phydev = dev->phydev;
-
netif_carrier_off(dev);
err = register_netdev(dev);
@@ -4336,8 +4348,6 @@ static int macb_probe(struct platform_device *pdev)
tasklet_init(&bp->hresp_err_tasklet, macb_hresp_error_task,
(unsigned long)bp);
- phy_attached_info(phydev);
-
netdev_info(dev, "Cadence %s rev 0x%08x at 0x%08lx irq %d (%pM)\n",
macb_is_gem(bp) ? "GEM" : "MACB", macb_readl(bp, MID),
dev->base_addr, dev->irq, dev->dev_addr);
@@ -4348,7 +4358,9 @@ static int macb_probe(struct platform_device *pdev)
return 0;
err_out_unregister_mdio:
- phy_disconnect(dev->phydev);
+ rtnl_lock();
+ phylink_disconnect_phy(bp->pl);
+ rtnl_unlock();
mdiobus_unregister(bp->mii_bus);
of_node_put(bp->phy_node);
if (np && of_phy_is_fixed_link(np))
@@ -4382,13 +4394,18 @@ static int macb_remove(struct platform_device *pdev)
if (dev) {
bp = netdev_priv(dev);
- if (dev->phydev)
- phy_disconnect(dev->phydev);
+ if (bp->pl) {
+ rtnl_lock();
+ phylink_disconnect_phy(bp->pl);
+ rtnl_unlock();
+ }
mdiobus_unregister(bp->mii_bus);
if (np && of_phy_is_fixed_link(np))
of_phy_deregister_fixed_link(np);
dev->phydev = NULL;
mdiobus_free(bp->mii_bus);
+ if (bp->pl)
+ phylink_destroy(bp->pl);
unregister_netdev(dev);
pm_runtime_disable(&pdev->dev);
@@ -4431,8 +4448,9 @@ static int __maybe_unused macb_suspend(struct device *dev)
for (q = 0, queue = bp->queues; q < bp->num_queues;
++q, ++queue)
napi_disable(&queue->napi);
- phy_stop(netdev->phydev);
- phy_suspend(netdev->phydev);
+ phylink_stop(bp->pl);
+ if (netdev->phydev)
+ phy_suspend(netdev->phydev);
spin_lock_irqsave(&bp->lock, flags);
macb_reset_hw(bp);
spin_unlock_irqrestore(&bp->lock, flags);
@@ -4480,9 +4498,11 @@ static int __maybe_unused macb_resume(struct device *dev)
for (q = 0, queue = bp->queues; q < bp->num_queues;
++q, ++queue)
napi_enable(&queue->napi);
- phy_resume(netdev->phydev);
- phy_init_hw(netdev->phydev);
- phy_start(netdev->phydev);
+ if (netdev->phydev) {
+ phy_resume(netdev->phydev);
+ phy_init_hw(netdev->phydev);
+ }
+ phylink_start(bp->pl);
}
bp->macbgem_ops.mog_init_rings(bp);
--
2.17.1
^ permalink raw reply related
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