* Re: [PATCH v4 net-next 13/19] ionic: Add initial ethtool support
From: Andrew Lunn @ 2019-07-25 13:28 UTC (permalink / raw)
To: Shannon Nelson; +Cc: netdev, davem
In-Reply-To: <20190722214023.9513-14-snelson@pensando.io>
On Mon, Jul 22, 2019 at 02:40:17PM -0700, Shannon Nelson wrote:
> +static void ionic_get_pauseparam(struct net_device *netdev,
> + struct ethtool_pauseparam *pause)
> +{
> + struct lif *lif = netdev_priv(netdev);
> + struct ionic_dev *idev = &lif->ionic->idev;
> + uint8_t pause_type = idev->port_info->config.pause_type;
> +
> + pause->autoneg = 0;
> +
> + if (pause_type) {
> + pause->rx_pause = pause_type & IONIC_PAUSE_F_RX ? 1 : 0;
> + pause->tx_pause = pause_type & IONIC_PAUSE_F_TX ? 1 : 0;
> + }
> +}
> +
> +static int ionic_set_pauseparam(struct net_device *netdev,
> + struct ethtool_pauseparam *pause)
> +{
> + struct lif *lif = netdev_priv(netdev);
> + struct ionic *ionic = lif->ionic;
> + struct ionic_dev *idev = &lif->ionic->idev;
> + u32 requested_pause;
> + int err;
> +
> + if (pause->autoneg == AUTONEG_ENABLE) {
> + netdev_info(netdev, "Please use 'ethtool -s ...' to change autoneg\n");
> + return -EOPNOTSUPP;
> + }
> +
> + /* change both at the same time */
> + requested_pause = PORT_PAUSE_TYPE_LINK;
> + if (pause->rx_pause)
> + requested_pause |= IONIC_PAUSE_F_RX;
> + if (pause->tx_pause)
> + requested_pause |= IONIC_PAUSE_F_TX;
Hi Shannon
This not what i was expecting, and i'm guessing what you have here is
not right.
So you don't support the case of pause->autoneg ==
AUTONEG_ENABLE. That implies that setting pause values directly
configures the MAC. The values from auto-neg are always ignored. Then
why did you set PAUSE in the get ksettings function?
If you always ignore the values from auto-neg, then your info message
also makes no sense.
What really does the firmware do?
Andrew
^ permalink raw reply
* RE: [PATCH v6 0/5] net: macb: cover letter
From: Parshuram Raju Thombare @ 2019-07-25 13:27 UTC (permalink / raw)
To: Andrew Lunn
Cc: nicolas.ferre@microchip.com, davem@davemloft.net,
f.fainelli@gmail.com, linux@armlinux.org.uk,
netdev@vger.kernel.org, hkallweit1@gmail.com,
linux-kernel@vger.kernel.org, Rafal Ciepiela, Piotr Sroka,
Anil Joy Varughese, Arthur Marris, Steven Ho, Milind Parab
In-Reply-To: <20190718151310.GE25635@lunn.ch>
Hi Andrew,
>One thing which was never clear is how you are testing the features you are
>adding. Please could you describe your test setup and how each new feature
>is tested using that hardware. I'm particularly interested in what C45 device
>are you using? But i expect Russell would like to know more about SFP
>modules you are using. Do you have any which require 1000BaseX,
>2500BaseX, or provide copper 1G?
Sorry for late reply.
Here is a little more information on our setup used for testing C45 patch with a view to
try clarify a few points.
Regarding the MDIO communication channel that our controller supports - We have tested
MDIO transfers through Clause 22, but none of our local PHY's support Clause 45 so our hardware
team have created an example Clause 45 slave device for us to add support to the driver.
Note our hardware has been in silicon for 20 years, with customers using their own software to support
MDIO (both clause 22 and clause 45 functionality) and so this has been in Cadence's hardware controller
many times.
The programming interface is not hugely different between the two clauses and therefore we feel the risk is low.
For other features like SGMII, USXGMII we are using kc705 and vcu118 FPGA boards.
10G SFP+ module from Tyco electronics is used for testing 10G USXGMII in fixed AN mode.
Regards,
Parshuram Thombare
^ permalink raw reply
* RE: [PATCH net-next 3/3] net: stmmac: Introducing support for Page Pool
From: Jose Abreu @ 2019-07-25 13:26 UTC (permalink / raw)
To: Jon Hunter, Jose Abreu, linux-kernel@vger.kernel.org,
netdev@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com,
linux-arm-kernel@lists.infradead.org
Cc: Joao Pinto, David S . Miller, Giuseppe Cavallaro,
Alexandre Torgue, Maxime Coquelin, Maxime Ripard, Chen-Yu Tsai,
Robin Murphy, wens@csie.org, linux-tegra, peppe.cavallaro@st.com
In-Reply-To: <7a79be5d-7ba2-c457-36d3-1ccef6572181@nvidia.com>
From: Jon Hunter <jonathanh@nvidia.com>
Date: Jul/25/2019, 14:20:07 (UTC+00:00)
>
> On 03/07/2019 11:37, Jose Abreu wrote:
> > Mapping and unmapping DMA region is an high bottleneck in stmmac driver,
> > specially in the RX path.
> >
> > This commit introduces support for Page Pool API and uses it in all RX
> > queues. With this change, we get more stable troughput and some increase
> > of banwidth with iperf:
> > - MAC1000 - 950 Mbps
> > - XGMAC: 9.22 Gbps
> >
> > Signed-off-by: Jose Abreu <joabreu@synopsys.com>
> > Cc: Joao Pinto <jpinto@synopsys.com>
> > Cc: David S. Miller <davem@davemloft.net>
> > Cc: Giuseppe Cavallaro <peppe.cavallaro@st.com>
> > Cc: Alexandre Torgue <alexandre.torgue@st.com>
> > Cc: Maxime Coquelin <mcoquelin.stm32@gmail.com>
> > Cc: Maxime Ripard <maxime.ripard@bootlin.com>
> > Cc: Chen-Yu Tsai <wens@csie.org>
> > ---
> > drivers/net/ethernet/stmicro/stmmac/Kconfig | 1 +
> > drivers/net/ethernet/stmicro/stmmac/stmmac.h | 10 +-
> > drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 196 ++++++----------------
> > 3 files changed, 63 insertions(+), 144 deletions(-)
>
> ...
>
> > @@ -3306,49 +3295,22 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue)
> > else
> > p = rx_q->dma_rx + entry;
> >
> > - if (likely(!rx_q->rx_skbuff[entry])) {
> > - struct sk_buff *skb;
> > -
> > - skb = netdev_alloc_skb_ip_align(priv->dev, bfsize);
> > - if (unlikely(!skb)) {
> > - /* so for a while no zero-copy! */
> > - rx_q->rx_zeroc_thresh = STMMAC_RX_THRESH;
> > - if (unlikely(net_ratelimit()))
> > - dev_err(priv->device,
> > - "fail to alloc skb entry %d\n",
> > - entry);
> > - break;
> > - }
> > -
> > - rx_q->rx_skbuff[entry] = skb;
> > - rx_q->rx_skbuff_dma[entry] =
> > - dma_map_single(priv->device, skb->data, bfsize,
> > - DMA_FROM_DEVICE);
> > - if (dma_mapping_error(priv->device,
> > - rx_q->rx_skbuff_dma[entry])) {
> > - netdev_err(priv->dev, "Rx DMA map failed\n");
> > - dev_kfree_skb(skb);
> > + if (!buf->page) {
> > + buf->page = page_pool_dev_alloc_pages(rx_q->page_pool);
> > + if (!buf->page)
> > break;
> > - }
> > -
> > - stmmac_set_desc_addr(priv, p, rx_q->rx_skbuff_dma[entry]);
> > - stmmac_refill_desc3(priv, rx_q, p);
> > -
> > - if (rx_q->rx_zeroc_thresh > 0)
> > - rx_q->rx_zeroc_thresh--;
> > -
> > - netif_dbg(priv, rx_status, priv->dev,
> > - "refill entry #%d\n", entry);
> > }
> > - dma_wmb();
> > +
> > + buf->addr = buf->page->dma_addr;
> > + stmmac_set_desc_addr(priv, p, buf->addr);
> > + stmmac_refill_desc3(priv, rx_q, p);
> >
> > rx_q->rx_count_frames++;
> > rx_q->rx_count_frames %= priv->rx_coal_frames;
> > use_rx_wd = priv->use_riwt && rx_q->rx_count_frames;
> >
> > - stmmac_set_rx_owner(priv, p, use_rx_wd);
> > -
> > dma_wmb();
> > + stmmac_set_rx_owner(priv, p, use_rx_wd);
> >
> > entry = STMMAC_GET_ENTRY(entry, DMA_RX_SIZE);
> > }
>
> I was looking at this change in a bit closer detail and one thing that
> stuck out to me was the above where the barrier had been moved from
> after the stmmac_set_rx_owner() call to before.
>
> So I moved this back and I no longer saw the crash. However, then I
> recalled I had the patch to enable the debug prints for the buffer
> address applied but after reverting that, the crash occurred again.
>
> In other words, what works for me is moving the above barrier and adding
> the debug print, which appears to suggest that there is some
> timing/coherency issue here. Anyway, maybe this is clue to what is going
> on?
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index a7486c2f3221..2f016397231b 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -3303,8 +3303,8 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue)
> rx_q->rx_count_frames %= priv->rx_coal_frames;
> use_rx_wd = priv->use_riwt && rx_q->rx_count_frames;
>
> - dma_wmb();
> stmmac_set_rx_owner(priv, p, use_rx_wd);
> + dma_wmb();
>
> entry = STMMAC_GET_ENTRY(entry, DMA_RX_SIZE);
> }
> @@ -3438,6 +3438,10 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
> dma_sync_single_for_device(priv->device, buf->addr,
> frame_len, DMA_FROM_DEVICE);
>
> + pr_info("%s: paddr=0x%llx, vaddr=0x%llx, len=%d", __func__,
> + buf->addr, page_address(buf->page),
> + frame_len);
> +
> if (netif_msg_pktdata(priv)) {
> netdev_dbg(priv->dev, "frame received (%dbytes)",
> frame_len);
>
> Cheers
> Jon
>
> --
> nvpublic
Well, I wasn't expecting that :/
Per documentation of barriers I think we should set descriptor fields
and then barrier and finally ownership to HW so that remaining fields
are coherent before owner is set.
Anyway, can you also add a dma_rmb() after the call to
stmmac_rx_status() ?
---
Thanks,
Jose Miguel Abreu
^ permalink raw reply
* Re: [PATCH] net: bridge: Allow bridge to joing multicast groups
From: Nikolay Aleksandrov @ 2019-07-25 13:21 UTC (permalink / raw)
To: Horatiu Vultur, roopa, davem, bridge, netdev, linux-kernel,
allan.nielsen
In-Reply-To: <7e7a7015-6072-d884-b2ba-0a51177245ab@cumulusnetworks.com>
On 25/07/2019 16:06, Nikolay Aleksandrov wrote:
> On 25/07/2019 14:44, Horatiu Vultur wrote:
>> There is no way to configure the bridge, to receive only specific link
>> layer multicast addresses. From the description of the command 'bridge
>> fdb append' is supposed to do that, but there was no way to notify the
>> network driver that the bridge joined a group, because LLADDR was added
>> to the unicast netdev_hw_addr_list.
>>
>> Therefore update fdb_add_entry to check if the NLM_F_APPEND flag is set
>> and if the source is NULL, which represent the bridge itself. Then add
>> address to multicast netdev_hw_addr_list for each bridge interfaces.
>> And then the .ndo_set_rx_mode function on the driver is called. To notify
>> the driver that the list of multicast mac addresses changed.
>>
>> Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com>
>> ---
>> net/bridge/br_fdb.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++---
>> 1 file changed, 46 insertions(+), 3 deletions(-)
>>
>
> Hi,
> I'm sorry but this patch is wrong on many levels, some notes below. In general
> NLM_F_APPEND is only used in vxlan, the bridge does not handle that flag at all.
> FDB is only for *unicast*, nothing is joined and no multicast should be used with fdbs.
> MDB is used for multicast handling, but both of these are used for forwarding.
> The reason the static fdbs are added to the filter is for non-promisc ports, so they can
> receive traffic destined for these FDBs for forwarding.
> If you'd like to join any multicast group please use the standard way, if you'd like to join
> it only on a specific port - join it only on that port (or ports) and the bridge and you'll
And obviously this is for the case where you're not enabling port promisc mode (non-default).
In general you'll only need to join the group on the bridge to receive traffic for it
or add it as an mdb entry to forward it.
> have the effect that you're describing. What do you mean there's no way ?
>
> In addition you're allowing a mix of mcast functions to be called with unicast addresses
> and vice versa, it is not that big of a deal because the kernel will simply return an error
> but still makes no sense.
>
> Nacked-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
>
>> diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
>> index b1d3248..d93746d 100644
>> --- a/net/bridge/br_fdb.c
>> +++ b/net/bridge/br_fdb.c
>> @@ -175,6 +175,29 @@ static void fdb_add_hw_addr(struct net_bridge *br, const unsigned char *addr)
>> }
>> }
>>
>> +static void fdb_add_hw_maddr(struct net_bridge *br, const unsigned char *addr)
>> +{
>> + int err;
>> + struct net_bridge_port *p;
>> +
>> + ASSERT_RTNL();
>> +
>> + list_for_each_entry(p, &br->port_list, list) {
>> + if (!br_promisc_port(p)) {
>> + err = dev_mc_add(p->dev, addr);
>> + if (err)
>> + goto undo;
>> + }
>> + }
>> +
>> + return;
>> +undo:
>> + list_for_each_entry_continue_reverse(p, &br->port_list, list) {
>> + if (!br_promisc_port(p))
>> + dev_mc_del(p->dev, addr);
>> + }
>> +}
>> +
>> /* When a static FDB entry is deleted, the HW address from that entry is
>> * also removed from the bridge private HW address list and updates all
>> * the ports with needed information.
>> @@ -192,13 +215,27 @@ static void fdb_del_hw_addr(struct net_bridge *br, const unsigned char *addr)
>> }
>> }
>>
>> +static void fdb_del_hw_maddr(struct net_bridge *br, const unsigned char *addr)
>> +{
>> + struct net_bridge_port *p;
>> +
>> + ASSERT_RTNL();
>> +
>> + list_for_each_entry(p, &br->port_list, list) {
>> + if (!br_promisc_port(p))
>> + dev_mc_del(p->dev, addr);
>> + }
>> +}
>> +
>> static void fdb_delete(struct net_bridge *br, struct net_bridge_fdb_entry *f,
>> bool swdev_notify)
>> {
>> trace_fdb_delete(br, f);
>>
>> - if (f->is_static)
>> + if (f->is_static) {
>> fdb_del_hw_addr(br, f->key.addr.addr);
>> + fdb_del_hw_maddr(br, f->key.addr.addr);
>
> Walking over all ports again for each static delete is a no-go.
>
>> + }
>>
>> hlist_del_init_rcu(&f->fdb_node);
>> rhashtable_remove_fast(&br->fdb_hash_tbl, &f->rhnode,
>> @@ -843,13 +880,19 @@ static int fdb_add_entry(struct net_bridge *br, struct net_bridge_port *source,
>> fdb->is_local = 1;
>> if (!fdb->is_static) {
>> fdb->is_static = 1;
>> - fdb_add_hw_addr(br, addr);
>> + if (flags & NLM_F_APPEND && !source)
>> + fdb_add_hw_maddr(br, addr);
>> + else
>> + fdb_add_hw_addr(br, addr);
>> }
>> } else if (state & NUD_NOARP) {
>> fdb->is_local = 0;
>> if (!fdb->is_static) {
>> fdb->is_static = 1;
>> - fdb_add_hw_addr(br, addr);
>> + if (flags & NLM_F_APPEND && !source)
>> + fdb_add_hw_maddr(br, addr);
>> + else
>> + fdb_add_hw_addr(br, addr);
>> }
>> } else {
>> fdb->is_local = 0;
>>
>
^ permalink raw reply
* Re: [PATCH net-next 3/3] net: stmmac: Introducing support for Page Pool
From: Jon Hunter @ 2019-07-25 13:20 UTC (permalink / raw)
To: Jose Abreu, linux-kernel, netdev, linux-stm32, linux-arm-kernel
Cc: Joao Pinto, David S . Miller, Giuseppe Cavallaro,
Alexandre Torgue, Maxime Coquelin, Maxime Ripard, Chen-Yu Tsai,
Robin Murphy, wens@csie.org, linux-tegra, peppe.cavallaro@st.com
In-Reply-To: <1b254bb7fc6044c5e6e2fdd9e00088d1d13a808b.1562149883.git.joabreu@synopsys.com>
On 03/07/2019 11:37, Jose Abreu wrote:
> Mapping and unmapping DMA region is an high bottleneck in stmmac driver,
> specially in the RX path.
>
> This commit introduces support for Page Pool API and uses it in all RX
> queues. With this change, we get more stable troughput and some increase
> of banwidth with iperf:
> - MAC1000 - 950 Mbps
> - XGMAC: 9.22 Gbps
>
> Signed-off-by: Jose Abreu <joabreu@synopsys.com>
> Cc: Joao Pinto <jpinto@synopsys.com>
> Cc: David S. Miller <davem@davemloft.net>
> Cc: Giuseppe Cavallaro <peppe.cavallaro@st.com>
> Cc: Alexandre Torgue <alexandre.torgue@st.com>
> Cc: Maxime Coquelin <mcoquelin.stm32@gmail.com>
> Cc: Maxime Ripard <maxime.ripard@bootlin.com>
> Cc: Chen-Yu Tsai <wens@csie.org>
> ---
> drivers/net/ethernet/stmicro/stmmac/Kconfig | 1 +
> drivers/net/ethernet/stmicro/stmmac/stmmac.h | 10 +-
> drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 196 ++++++----------------
> 3 files changed, 63 insertions(+), 144 deletions(-)
...
> @@ -3306,49 +3295,22 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue)
> else
> p = rx_q->dma_rx + entry;
>
> - if (likely(!rx_q->rx_skbuff[entry])) {
> - struct sk_buff *skb;
> -
> - skb = netdev_alloc_skb_ip_align(priv->dev, bfsize);
> - if (unlikely(!skb)) {
> - /* so for a while no zero-copy! */
> - rx_q->rx_zeroc_thresh = STMMAC_RX_THRESH;
> - if (unlikely(net_ratelimit()))
> - dev_err(priv->device,
> - "fail to alloc skb entry %d\n",
> - entry);
> - break;
> - }
> -
> - rx_q->rx_skbuff[entry] = skb;
> - rx_q->rx_skbuff_dma[entry] =
> - dma_map_single(priv->device, skb->data, bfsize,
> - DMA_FROM_DEVICE);
> - if (dma_mapping_error(priv->device,
> - rx_q->rx_skbuff_dma[entry])) {
> - netdev_err(priv->dev, "Rx DMA map failed\n");
> - dev_kfree_skb(skb);
> + if (!buf->page) {
> + buf->page = page_pool_dev_alloc_pages(rx_q->page_pool);
> + if (!buf->page)
> break;
> - }
> -
> - stmmac_set_desc_addr(priv, p, rx_q->rx_skbuff_dma[entry]);
> - stmmac_refill_desc3(priv, rx_q, p);
> -
> - if (rx_q->rx_zeroc_thresh > 0)
> - rx_q->rx_zeroc_thresh--;
> -
> - netif_dbg(priv, rx_status, priv->dev,
> - "refill entry #%d\n", entry);
> }
> - dma_wmb();
> +
> + buf->addr = buf->page->dma_addr;
> + stmmac_set_desc_addr(priv, p, buf->addr);
> + stmmac_refill_desc3(priv, rx_q, p);
>
> rx_q->rx_count_frames++;
> rx_q->rx_count_frames %= priv->rx_coal_frames;
> use_rx_wd = priv->use_riwt && rx_q->rx_count_frames;
>
> - stmmac_set_rx_owner(priv, p, use_rx_wd);
> -
> dma_wmb();
> + stmmac_set_rx_owner(priv, p, use_rx_wd);
>
> entry = STMMAC_GET_ENTRY(entry, DMA_RX_SIZE);
> }
I was looking at this change in a bit closer detail and one thing that
stuck out to me was the above where the barrier had been moved from
after the stmmac_set_rx_owner() call to before.
So I moved this back and I no longer saw the crash. However, then I
recalled I had the patch to enable the debug prints for the buffer
address applied but after reverting that, the crash occurred again.
In other words, what works for me is moving the above barrier and adding
the debug print, which appears to suggest that there is some
timing/coherency issue here. Anyway, maybe this is clue to what is going
on?
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index a7486c2f3221..2f016397231b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -3303,8 +3303,8 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue)
rx_q->rx_count_frames %= priv->rx_coal_frames;
use_rx_wd = priv->use_riwt && rx_q->rx_count_frames;
- dma_wmb();
stmmac_set_rx_owner(priv, p, use_rx_wd);
+ dma_wmb();
entry = STMMAC_GET_ENTRY(entry, DMA_RX_SIZE);
}
@@ -3438,6 +3438,10 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
dma_sync_single_for_device(priv->device, buf->addr,
frame_len, DMA_FROM_DEVICE);
+ pr_info("%s: paddr=0x%llx, vaddr=0x%llx, len=%d", __func__,
+ buf->addr, page_address(buf->page),
+ frame_len);
+
if (netif_msg_pktdata(priv)) {
netdev_dbg(priv->dev, "frame received (%dbytes)",
frame_len);
Cheers
Jon
--
nvpublic
^ permalink raw reply related
* Re: [PATCH net] net: hns: fix LED configuration for marvell phy
From: Andrew Lunn @ 2019-07-25 13:08 UTC (permalink / raw)
To: liuyonglong
Cc: David Miller, netdev, linux-kernel, linuxarm, salil.mehta,
yisen.zhuang, shiju.jose
In-Reply-To: <8017d9ff-2991-f94f-e611-4d1bac12e93b@huawei.com>
> You are discussing about the DT configuration, is Matthias Kaehlcke's work
> also provide a generic way to configure PHY LEDS using ACPI?
In general, you should be able to use the same properties in ACPI as
DT. If the device_property_read_X() API is used, it will try both ACPI
and OF to get the property.
Andrew
^ permalink raw reply
* Re: [PATCH][next] can: kvaser_pciefd: remove redundant negative check on trigger
From: Colin Ian King @ 2019-07-25 12:41 UTC (permalink / raw)
To: wharms
Cc: Wolfgang Grandegger, Marc Kleine-Budde, David S . Miller,
linux-can, netdev, kernel-janitors, linux-kernel
In-Reply-To: <5D39A274.1000800@bfs.de>
On 25/07/2019 13:37, walter harms wrote:
>
>
> Am 25.07.2019 13:25, schrieb Colin King:
>> From: Colin Ian King <colin.king@canonical.com>
>>
>> The check to see if trigger is less than zero is always false, trigger
>> is always in the range 0..255. Hence the check is redundant and can
>> be removed.
>>
>> Addresses-Coverity: ("Logically dead code")
>> Signed-off-by: Colin Ian King <colin.king@canonical.com>
>> ---
>> drivers/net/can/kvaser_pciefd.c | 3 ---
>> 1 file changed, 3 deletions(-)
>>
>> diff --git a/drivers/net/can/kvaser_pciefd.c b/drivers/net/can/kvaser_pciefd.c
>> index 3af747cbbde4..68e00aad0810 100644
>> --- a/drivers/net/can/kvaser_pciefd.c
>> +++ b/drivers/net/can/kvaser_pciefd.c
>> @@ -652,9 +652,6 @@ static void kvaser_pciefd_pwm_stop(struct kvaser_pciefd_can *can)
>> top = (pwm_ctrl >> KVASER_PCIEFD_KCAN_PWM_TOP_SHIFT) & 0xff;
>>
>> trigger = (100 * top + 50) / 100;
>> - if (trigger < 0)
>> - trigger = 0;
>> -
> to be fair i do not understand the calculation here here.
> (100*top+50)/100 = top+50/100
>
> but seems to be int so it should be =top
Indeed it does not do anything, that does look like an unintentional
bug. Good catch.
>
> did i missunderstand something here ?
>
> re,
> wh
>
>
>> pwm_ctrl = trigger & 0xff;
>> pwm_ctrl |= (top & 0xff) << KVASER_PCIEFD_KCAN_PWM_TOP_SHIFT;
>> iowrite32(pwm_ctrl, can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG);
^ permalink raw reply
* Re: [PATCH] net: sfc: falcon: convert to i2c_new_dummy_device
From: Edward Cree @ 2019-07-25 12:37 UTC (permalink / raw)
To: David Miller, wsa+renesas
Cc: linux-i2c, linux-net-drivers, mhabets, netdev, linux-kernel
In-Reply-To: <20190724.154739.72147269285837223.davem@davemloft.net>
On 24/07/2019 23:47, David Miller wrote:
> From: Wolfram Sang <wsa+renesas@sang-engineering.com>
> Date: Mon, 22 Jul 2019 19:26:35 +0200
>
>> Move from i2c_new_dummy() to i2c_new_dummy_device(). So, we now get an
>> ERRPTR which we use in error handling.
>>
>> Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Subject & description are incomplete, you're also changing i2c_new_device()
to i2c_new_client_device().
Other than that,
Acked-by: Edward Cree <ecree@solarflare.com>
> Solarflare folks, please review/test.
>
> Thank you.
Falcon isn't likely to get tested by us, I think we only have about three
of them left in the building, two of which are in display cabinets ;-)
We end-of-lifed this hardware a couple of years ago, maybe it should be
downgraded from 'supported' to 'odd fixes'. Or even moved to staging,
like that qlogic driver recently was.
^ permalink raw reply
* Re: [PATCH][next] can: kvaser_pciefd: remove redundant negative check on trigger
From: walter harms @ 2019-07-25 12:37 UTC (permalink / raw)
To: Colin King
Cc: Wolfgang Grandegger, Marc Kleine-Budde, David S . Miller,
linux-can, netdev, kernel-janitors, linux-kernel
In-Reply-To: <20190725112509.1075-1-colin.king@canonical.com>
Am 25.07.2019 13:25, schrieb Colin King:
> From: Colin Ian King <colin.king@canonical.com>
>
> The check to see if trigger is less than zero is always false, trigger
> is always in the range 0..255. Hence the check is redundant and can
> be removed.
>
> Addresses-Coverity: ("Logically dead code")
> Signed-off-by: Colin Ian King <colin.king@canonical.com>
> ---
> drivers/net/can/kvaser_pciefd.c | 3 ---
> 1 file changed, 3 deletions(-)
>
> diff --git a/drivers/net/can/kvaser_pciefd.c b/drivers/net/can/kvaser_pciefd.c
> index 3af747cbbde4..68e00aad0810 100644
> --- a/drivers/net/can/kvaser_pciefd.c
> +++ b/drivers/net/can/kvaser_pciefd.c
> @@ -652,9 +652,6 @@ static void kvaser_pciefd_pwm_stop(struct kvaser_pciefd_can *can)
> top = (pwm_ctrl >> KVASER_PCIEFD_KCAN_PWM_TOP_SHIFT) & 0xff;
>
> trigger = (100 * top + 50) / 100;
> - if (trigger < 0)
> - trigger = 0;
> -
to be fair i do not understand the calculation here here.
(100*top+50)/100 = top+50/100
but seems to be int so it should be =top
did i missunderstand something here ?
re,
wh
> pwm_ctrl = trigger & 0xff;
> pwm_ctrl |= (top & 0xff) << KVASER_PCIEFD_KCAN_PWM_TOP_SHIFT;
> iowrite32(pwm_ctrl, can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG);
^ permalink raw reply
* Re: [PATCH net-next 07/11] net: hns3: adds debug messages to identify eth down cause
From: liuyonglong @ 2019-07-25 12:28 UTC (permalink / raw)
To: Saeed Mahameed, tanhuazhong@huawei.com, davem@davemloft.net
Cc: lipeng321@huawei.com, yisen.zhuang@huawei.com,
salil.mehta@huawei.com, linuxarm@huawei.com,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <ffd942e7d7442549a3a6d469709b7f7405928afe.camel@mellanox.com>
On 2019/7/25 3:12, Saeed Mahameed wrote:
> On Wed, 2019-07-24 at 11:18 +0800, Huazhong Tan wrote:
>> From: Yonglong Liu <liuyonglong@huawei.com>
>>
>> Some times just see the eth interface have been down/up via
>> dmesg, but can not know why the eth down. So adds some debug
>> messages to identify the cause for this.
>>
>
> I really don't like this. your default msg lvl has NETIF_MSG_IFDOWN
> turned on .. dumping every single operation that happens on your device
> by default to kernel log is too much !
>
> We should really consider using trace buffers with well defined
> structures for vendor specific events. so we can use bpf filters and
> state of the art tools for netdev debugging.
>
We do this because we can just see a link down message in dmesg, and had
take a long time to found the cause of link down, just because another
user changed the settings.
We can change the net_open/net_stop/dcbnl_ops to msg_drv (not default
turned on), and want to keep the others default print to kernel log,
is it acceptable?
>> @@ -1593,6 +1603,11 @@ static int hns3_ndo_set_vf_vlan(struct
>> net_device *netdev, int vf, u16 vlan,
>> struct hnae3_handle *h = hns3_get_handle(netdev);
>> int ret = -EIO;
>>
>> + if (netif_msg_ifdown(h))
>
> why msg_ifdown ? looks like netif_msg_drv is more appropriate, for many
> of the cases in this patch.
>
This operation may cause link down, so we use msg_ifdown.
>> + netdev_info(netdev,
>> + "set vf vlan: vf=%d, vlan=%d, qos=%d,
>> vlan_proto=%d\n",
>> + vf, vlan, qos, vlan_proto);
>> +
>> if (h->ae_algo->ops->set_vf_vlan_filter)
>> ret = h->ae_algo->ops->set_vf_vlan_filter(h, vf, vlan,
>> qos,
>> vlan_proto);
>> @@ -1611,6 +1626,10 @@ static int hns3_nic_change_mtu(struct
>> net_device *netdev, int new_mtu)
>> if (!h->ae_algo->ops->set_mtu)
>> return -EOPNOTSUPP;
>>
>> + if (netif_msg_ifdown(h))
>> + netdev_info(netdev, "change mtu from %d to %d\n",
>> + netdev->mtu, new_mtu);
>> +
>> ret = h->ae_algo->ops->set_mtu(h, new_mtu);
>> if (ret)
>> netdev_err(netdev, "failed to change MTU in hardware
>> %d\n",
>> @@ -4395,6 +4414,11 @@ int hns3_set_channels(struct net_device
>> *netdev,
>> if (kinfo->rss_size == new_tqp_num)
>> return 0;
>>
>> + if (netif_msg_ifdown(h))
>> + netdev_info(netdev,
>> + "set channels: tqp_num=%d, rxfh=%d\n",
>> + new_tqp_num, rxfh_configured);
>> +
>> ret = hns3_reset_notify(h, HNAE3_DOWN_CLIENT);
>> if (ret)
>> return ret;
>> diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
>> b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
>> index e71c92b..edb9845 100644
>> --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
>> +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
>> @@ -311,6 +311,9 @@ static void hns3_self_test(struct net_device
>> *ndev,
>> if (eth_test->flags != ETH_TEST_FL_OFFLINE)
>> return;
>>
>> + if (netif_msg_ifdown(h))
>> + netdev_info(ndev, "self test start\n");
>> +
>> st_param[HNAE3_LOOP_APP][0] = HNAE3_LOOP_APP;
>> st_param[HNAE3_LOOP_APP][1] =
>> h->flags & HNAE3_SUPPORT_APP_LOOPBACK;
>> @@ -374,6 +377,9 @@ static void hns3_self_test(struct net_device
>> *ndev,
>>
>> if (if_running)
>> ndev->netdev_ops->ndo_open(ndev);
>> +
>> + if (netif_msg_ifdown(h))
>> + netdev_info(ndev, "self test end\n");
>> }
>>
>> static int hns3_get_sset_count(struct net_device *netdev, int
>> stringset)
>> @@ -604,6 +610,11 @@ static int hns3_set_pauseparam(struct net_device
>> *netdev,
>> {
>> struct hnae3_handle *h = hns3_get_handle(netdev);
>>
>> + if (netif_msg_ifdown(h))
>> + netdev_info(netdev,
>> + "set pauseparam: autoneg=%d, rx:%d,
>> tx:%d\n",
>> + param->autoneg, param->rx_pause, param-
>>> tx_pause);
>> +
>> if (h->ae_algo->ops->set_pauseparam)
>> return h->ae_algo->ops->set_pauseparam(h, param-
>>> autoneg,
>> param->rx_pause,
>> @@ -743,6 +754,13 @@ static int hns3_set_link_ksettings(struct
>> net_device *netdev,
>> if (cmd->base.speed == SPEED_1000 && cmd->base.duplex ==
>> DUPLEX_HALF)
>> return -EINVAL;
>>
>> + if (netif_msg_ifdown(handle))
>> + netdev_info(netdev,
>> + "set link(%s): autoneg=%d, speed=%d,
>> duplex=%d\n",
>> + netdev->phydev ? "phy" : "mac",
>> + cmd->base.autoneg, cmd->base.speed,
>> + cmd->base.duplex);
>> +
>> /* Only support ksettings_set for netdev with phy attached for
>> now */
>> if (netdev->phydev)
>> return phy_ethtool_ksettings_set(netdev->phydev, cmd);
>> @@ -984,6 +1002,10 @@ static int hns3_nway_reset(struct net_device
>> *netdev)
>> return -EINVAL;
>> }
>>
>> + if (netif_msg_ifdown(handle))
>> + netdev_info(netdev, "nway reset (using %s)\n",
>> + phy ? "phy" : "mac");
>> +
>> if (phy)
>> return genphy_restart_aneg(phy);
>>
>> @@ -1308,6 +1330,10 @@ static int hns3_set_fecparam(struct net_device
>> *netdev,
>> if (!ops->set_fec)
>> return -EOPNOTSUPP;
>> fec_mode = eth_to_loc_fec(fec->fec);
>> +
>> + if (netif_msg_ifdown(handle))
>> + netdev_info(netdev, "set fecparam: mode=%d\n",
>> fec_mode);
>> +
>> return ops->set_fec(handle, fec_mode);
>> }
>>
>> diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c
>> b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c
>> index bac4ce1..133e7c6 100644
>> --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c
>> +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c
>> @@ -201,6 +201,7 @@ static int hclge_client_setup_tc(struct hclge_dev
>> *hdev)
>> static int hclge_ieee_setets(struct hnae3_handle *h, struct ieee_ets
>> *ets)
>> {
>> struct hclge_vport *vport = hclge_get_vport(h);
>> + struct net_device *netdev = h->kinfo.netdev;
>> struct hclge_dev *hdev = vport->back;
>> bool map_changed = false;
>> u8 num_tc = 0;
>> @@ -215,6 +216,9 @@ static int hclge_ieee_setets(struct hnae3_handle
>> *h, struct ieee_ets *ets)
>> return ret;
>>
>> if (map_changed) {
>> + if (netif_msg_ifdown(h))
>> + netdev_info(netdev, "set ets\n");
>> +
>> ret = hclge_notify_client(hdev, HNAE3_DOWN_CLIENT);
>> if (ret)
>> return ret;
>> @@ -300,6 +304,7 @@ static int hclge_ieee_getpfc(struct hnae3_handle
>> *h, struct ieee_pfc *pfc)
>> static int hclge_ieee_setpfc(struct hnae3_handle *h, struct ieee_pfc
>> *pfc)
>> {
>> struct hclge_vport *vport = hclge_get_vport(h);
>> + struct net_device *netdev = h->kinfo.netdev;
>> struct hclge_dev *hdev = vport->back;
>> u8 i, j, pfc_map, *prio_tc;
>>
>> @@ -325,6 +330,11 @@ static int hclge_ieee_setpfc(struct hnae3_handle
>> *h, struct ieee_pfc *pfc)
>> hdev->tm_info.hw_pfc_map = pfc_map;
>> hdev->tm_info.pfc_en = pfc->pfc_en;
>>
>> + if (netif_msg_ifdown(h))
>> + netdev_info(netdev,
>> + "set pfc: pfc_en=%d, pfc_map=%d,
>> num_tc=%d\n",
>> + pfc->pfc_en, pfc_map, hdev-
>>> tm_info.num_tc);
>> +
>> hclge_tm_pfc_info_update(hdev);
>>
>> return hclge_pause_setup_hw(hdev, false);
>> @@ -345,8 +355,12 @@ static u8 hclge_getdcbx(struct hnae3_handle *h)
>> static u8 hclge_setdcbx(struct hnae3_handle *h, u8 mode)
>> {
>> struct hclge_vport *vport = hclge_get_vport(h);
>> + struct net_device *netdev = h->kinfo.netdev;
>> struct hclge_dev *hdev = vport->back;
>>
>> + if (netif_msg_drv(h))
>> + netdev_info(netdev, "set dcbx: mode=%d\n", mode);
>> +
>> /* No support for LLD_MANAGED modes or CEE */
>> if ((mode & DCB_CAP_DCBX_LLD_MANAGED) ||
>> (mode & DCB_CAP_DCBX_VER_CEE) ||
^ permalink raw reply
* Re: [PATCH net-next 2/2] mlx4/en_netdev: call notifiers when hw_enc_features change
From: Davide Caratti @ 2019-07-25 12:25 UTC (permalink / raw)
To: Saeed Mahameed, davem@davemloft.net, Tariq Toukan,
netdev@vger.kernel.org
Cc: Eran Ben Elisha
In-Reply-To: <e007bac4c951486294d4e69d20f7c9ed7040172d.camel@mellanox.com>
On Wed, 2019-07-24 at 20:47 +0000, Saeed Mahameed wrote:
> On Wed, 2019-07-24 at 16:02 +0200, Davide Caratti wrote:
> > ensure to call netdev_features_change() when the driver flips its
> > hw_enc_features bits.
> >
> > Signed-off-by: Davide Caratti <dcaratti@redhat.com>
>
> The patch is correct,
hello Saeed, and thanks for looking at this!
> but can you explain how did you come to this ?
> did you encounter any issue with the current code ?
>
> I am asking just because i think the whole dynamic changing of dev-
> > hw_enc_features is redundant since mlx4 has the featutres_check
> callback.
we need it to ensure that vlan_transfer_features() updates
the (new) value of hw_enc_features in the overlying vlan: otherwise,
segmentation will happen anyway when skb passes from vxlan to vlan, if the
vxlan is added after the vlan device has been created (see: 7dad9937e064
("net: vlan: add support for tunnel offload") ).
thanks!
--
davide
^ permalink raw reply
* Re: [PATCH v3 5/7] mfd: ioc3: Add driver for SGI IOC3 chip
From: Lee Jones @ 2019-07-25 11:47 UTC (permalink / raw)
To: Thomas Bogendoerfer
Cc: Ralf Baechle, Paul Burton, James Hogan, Dmitry Torokhov,
David S. Miller, Srinivas Kandagatla, Alessandro Zummo,
Alexandre Belloni, Greg Kroah-Hartman, Jiri Slaby, linux-mips,
linux-kernel, linux-input, netdev, linux-rtc, linux-serial
In-Reply-To: <20190613170636.6647-6-tbogendoerfer@suse.de>
On Thu, 13 Jun 2019, Thomas Bogendoerfer wrote:
> SGI IOC3 chip has integrated ethernet, keyboard and mouse interface.
> It also supports connecting a SuperIO chip for serial and parallel
> interfaces. IOC3 is used inside various SGI systemboards and add-on
> cards with different equipped external interfaces.
>
> Support for ethernet and serial interfaces were implemented inside
> the network driver. This patchset moves out the not network related
> parts to a new MFD driver, which takes care of card detection,
> setup of platform devices and interrupt distribution for the subdevices.
>
> Serial portion: Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
>
> Signed-off-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
> ---
> arch/mips/include/asm/sn/ioc3.h | 345 +++----
> arch/mips/sgi-ip27/ip27-timer.c | 20 -
> drivers/mfd/Kconfig | 13 +
> drivers/mfd/Makefile | 1 +
> drivers/mfd/ioc3.c | 683 +++++++++++++
A vast improvement, but still a little work to do.
> drivers/net/ethernet/sgi/Kconfig | 4 +-
> drivers/net/ethernet/sgi/ioc3-eth.c | 1932 ++++++++++++++---------------------
> drivers/tty/serial/8250/8250_ioc3.c | 98 ++
> drivers/tty/serial/8250/Kconfig | 11 +
> drivers/tty/serial/8250/Makefile | 1 +
> 10 files changed, 1693 insertions(+), 1415 deletions(-)
> create mode 100644 drivers/mfd/ioc3.c
> create mode 100644 drivers/tty/serial/8250/8250_ioc3.c
[...]
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index a17d275bf1d4..5c9f1bd9bd0a 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -1989,5 +1989,18 @@ config RAVE_SP_CORE
> Select this to get support for the Supervisory Processor
> device found on several devices in RAVE line of hardware.
>
> +config SGI_MFD_IOC3
> + tristate "SGI IOC3 core driver"
> + depends on PCI && MIPS
> + select MFD_CORE
> + help
> + This option enables basic support for the SGI IOC3-based
> + controller cards. This option does not enable any specific
> + functions on such a card, but provides necessary infrastructure
> + for other drivers to utilize.
> +
> + If you have an SGI Origin, Octane, or a PCI IOC3 card,
> + then say Y. Otherwise say N.
> +
> endmenu
> endif
> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> index 52b1a90ff515..bba0d9eb0b18 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -249,3 +249,4 @@ obj-$(CONFIG_MFD_SC27XX_PMIC) += sprd-sc27xx-spi.o
> obj-$(CONFIG_RAVE_SP_CORE) += rave-sp.o
> obj-$(CONFIG_MFD_ROHM_BD718XX) += rohm-bd718x7.o
> obj-$(CONFIG_MFD_STMFX) += stmfx.o
> +obj-$(CONFIG_SGI_MFD_IOC3) += ioc3.o
> diff --git a/drivers/mfd/ioc3.c b/drivers/mfd/ioc3.c
> new file mode 100644
> index 000000000000..0c0d1b3475d0
> --- /dev/null
> +++ b/drivers/mfd/ioc3.c
> @@ -0,0 +1,683 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * SGI IOC3 multifunction device driver
> + *
> + * Copyright (C) 2018, 2019 Thomas Bogendoerfer <tbogendoerfer@suse.de>
> + *
> + * Based on work by:
> + * Stanislaw Skowronek <skylark@unaligned.org>
> + * Joshua Kinard <kumba@gentoo.org>
> + * Brent Casavant <bcasavan@sgi.com> - IOC4 master driver
> + * Pat Gefre <pfg@sgi.com> - IOC3 serial port IRQ demuxer
> + */
> +
> +#include <linux/delay.h>
> +#include <linux/errno.h>
> +#include <linux/interrupt.h>
> +#include <linux/mfd/core.h>
> +#include <linux/module.h>
> +#include <linux/pci.h>
> +#include <linux/platform_device.h>
> +#include <linux/platform_data/sgi-w1.h>
> +#include <linux/rtc/ds1685.h>
> +
> +#include <asm/pci/bridge.h>
> +#include <asm/sn/ioc3.h>
> +
> +#define IOC3_IRQ_SERIAL_A 6
> +#define IOC3_IRQ_SERIAL_B 15
> +#define IOC3_IRQ_KBD 22
> +#define IOC3_IRQ_ETH_DOMAIN 23
> +
> +static int ioc3_serial_id;
> +static int ioc3_eth_id;
> +static int ioc3_kbd_id;
> +
> +struct ioc3_priv_data {
> + struct irq_domain *domain;
> + struct ioc3 __iomem *regs;
> + struct pci_dev *pdev;
> + int domain_irq;
> +};
> +
> +static void ioc3_irq_ack(struct irq_data *d)
> +{
> + struct ioc3_priv_data *ipd = irq_data_get_irq_chip_data(d);
> + unsigned int hwirq = irqd_to_hwirq(d);
> +
> + writel(BIT(hwirq), &ipd->regs->sio_ir);
> +}
> +
> +static void ioc3_irq_mask(struct irq_data *d)
> +{
> + struct ioc3_priv_data *ipd = irq_data_get_irq_chip_data(d);
> + unsigned int hwirq = irqd_to_hwirq(d);
> +
> + writel(BIT(hwirq), &ipd->regs->sio_iec);
> +}
> +
> +static void ioc3_irq_unmask(struct irq_data *d)
> +{
> + struct ioc3_priv_data *ipd = irq_data_get_irq_chip_data(d);
> + unsigned int hwirq = irqd_to_hwirq(d);
> +
> + writel(BIT(hwirq), &ipd->regs->sio_ies);
> +}
> +
> +static struct irq_chip ioc3_irq_chip = {
> + .name = "IOC3",
> + .irq_ack = ioc3_irq_ack,
> + .irq_mask = ioc3_irq_mask,
> + .irq_unmask = ioc3_irq_unmask,
> +};
> +
> +#define IOC3_LVL_MASK (BIT(IOC3_IRQ_SERIAL_A) | BIT(IOC3_IRQ_SERIAL_B))
> +
> +static int ioc3_irq_domain_map(struct irq_domain *d, unsigned int irq,
> + irq_hw_number_t hwirq)
> +{
> + /* use level irqs for every interrupt contained in IOC3_LVL_MASK */
Nit: Could you use proper grammar (less the full stops) in the
comments please? Start with an uppercase character and things like
"irq" should be "IRQ", etc.
> + if (BIT(hwirq) & IOC3_LVL_MASK)
> + irq_set_chip_and_handler(irq, &ioc3_irq_chip, handle_level_irq);
> + else
> + irq_set_chip_and_handler(irq, &ioc3_irq_chip, handle_edge_irq);
> +
> + irq_set_chip_data(irq, d->host_data);
> + return 0;
> +}
> +
> +static const struct irq_domain_ops ioc3_irq_domain_ops = {
> + .map = ioc3_irq_domain_map,
> +};
> +
> +static void ioc3_irq_handler(struct irq_desc *desc)
> +{
> + struct irq_domain *domain = irq_desc_get_handler_data(desc);
> + struct ioc3_priv_data *ipd = domain->host_data;
> + struct ioc3 __iomem *regs = ipd->regs;
> + u32 pending, mask;
> + unsigned int irq;
> +
> + pending = readl(®s->sio_ir);
> + mask = readl(®s->sio_ies);
> + pending &= mask; /* mask off not enabled but pending irqs */
> +
> + if (mask & BIT(IOC3_IRQ_ETH_DOMAIN))
> + /* if eth irq is enabled we need to check in eth irq regs */
> + if (readl(®s->eth.eisr) & readl(®s->eth.eier))
> + pending |= IOC3_IRQ_ETH_DOMAIN;
> +
> + if (pending) {
> + irq = irq_find_mapping(domain, __ffs(pending));
> + if (irq)
> + generic_handle_irq(irq);
> + } else {
> + spurious_interrupt();
> + }
> +}
> +
> +/*
> + * System boards/BaseIOs use more interrupt pins of the bridge asic
"ASIC"
> + * to which the IOC3 is connected. Since the IOC3 MFD driver
> + * knows wiring of these extra pins, we use the map_irq function
> + * to get interrupts activated
> + */
> +static int ioc3_map_irq(struct pci_dev *pdev, int pin)
> +{
> + struct pci_host_bridge *hbrg = pci_find_host_bridge(pdev->bus);
> +
> + return hbrg->map_irq(pdev, pin, 0);
> +}
> +
> +static int ioc3_irq_domain_setup(struct ioc3_priv_data *ipd, int irq)
> +{
> + struct irq_domain *domain;
> + struct fwnode_handle *fn;
> +
> + fn = irq_domain_alloc_named_fwnode("IOC3");
> + if (!fn)
> + goto err;
> +
> + domain = irq_domain_create_linear(fn, 24, &ioc3_irq_domain_ops, ipd);
> + if (!domain)
> + goto err;
> +
> + irq_domain_free_fwnode(fn);
> + ipd->domain = domain;
> +
> + irq_set_chained_handler_and_data(irq, ioc3_irq_handler, domain);
> + ipd->domain_irq = irq;
> + return 0;
> +err:
> + dev_err(&ipd->pdev->dev, "irq domain setup failed\n");
> + return -ENOMEM;
> +}
> +
> +static struct resource ioc3_uarta_resources[] = {
> + DEFINE_RES_MEM(offsetof(struct ioc3, sregs.uarta),
> + sizeof_field(struct ioc3, sregs.uarta)),
> + DEFINE_RES_IRQ(IOC3_IRQ_SERIAL_A)
> +};
> +
> +static struct resource ioc3_uartb_resources[] = {
> + DEFINE_RES_MEM(offsetof(struct ioc3, sregs.uartb),
> + sizeof_field(struct ioc3, sregs.uartb)),
> + DEFINE_RES_IRQ(IOC3_IRQ_SERIAL_B)
> +};
> +
> +static struct mfd_cell ioc3_serial_cells[] = {
> + {
> + .name = "ioc3-serial8250",
> + .resources = ioc3_uarta_resources,
> + .num_resources = ARRAY_SIZE(ioc3_uarta_resources),
> + .id = 0,
> + },
> + {
> + .name = "ioc3-serial8250",
> + .resources = ioc3_uartb_resources,
> + .num_resources = ARRAY_SIZE(ioc3_uartb_resources),
> + .id = 1,
Any reason for not using PLATFORM_DEVID_AUTO.
> + }
> +};
> +
> +static int ioc3_serial_setup(struct ioc3_priv_data *ipd)
> +{
> + int ret;
> +
> + /* set gpio pins for RS232/RS422 mode selection */
> + writel(GPCR_UARTA_MODESEL | GPCR_UARTB_MODESEL,
> + &ipd->regs->gpcr_s);
> + /* select RS232 mode for uart a */
> + writel(0, &ipd->regs->gppr[6]);
> + /* select RS232 mode for uart b */
> + writel(0, &ipd->regs->gppr[7]);
> +
> + /* switch both ports to 16650 mode */
> + writel(readl(&ipd->regs->port_a.sscr) & ~SSCR_DMA_EN,
> + &ipd->regs->port_a.sscr);
> + writel(readl(&ipd->regs->port_b.sscr) & ~SSCR_DMA_EN,
> + &ipd->regs->port_b.sscr);
> + udelay(1000); /* wait until mode switch is done */
> +
> + ret = mfd_add_devices(&ipd->pdev->dev, ioc3_serial_id,
Any reason for not using PLATFORM_DEVID_AUTO.
> + ioc3_serial_cells, ARRAY_SIZE(ioc3_serial_cells),
> + &ipd->pdev->resource[0], 0, ipd->domain);
> + if (ret) {
> + dev_err(&ipd->pdev->dev, "Failed to add 16550 subdevs\n");
> + return ret;
> + }
> + ioc3_serial_id += 2;
When is this likely to be re-read?
> + return 0;
> +}
> +
> +static struct resource ioc3_kbd_resources[] = {
> + DEFINE_RES_MEM(offsetof(struct ioc3, serio),
> + sizeof_field(struct ioc3, serio)),
> + DEFINE_RES_IRQ(IOC3_IRQ_KBD)
> +};
> +
> +static struct mfd_cell ioc3_kbd_cells[] = {
> + {
> + .name = "ioc3-kbd",
> + .resources = ioc3_kbd_resources,
> + .num_resources = ARRAY_SIZE(ioc3_kbd_resources),
> + }
> +};
> +
> +static int ioc3_kbd_setup(struct ioc3_priv_data *ipd)
> +{
> + int ret;
> +
> + ret = mfd_add_devices(&ipd->pdev->dev, ioc3_kbd_id, ioc3_kbd_cells,
> + ARRAY_SIZE(ioc3_kbd_cells),
> + &ipd->pdev->resource[0], 0, ipd->domain);
> + if (ret) {
> + dev_err(&ipd->pdev->dev, "Failed to add 16550 subdevs\n");
> + return ret;
> + }
> + ioc3_kbd_id++;
Nit: '\n' here
> + return 0;
> +}
> +
> +static struct resource ioc3_eth_resources[] = {
> + DEFINE_RES_MEM(offsetof(struct ioc3, eth),
> + sizeof_field(struct ioc3, eth)),
> + DEFINE_RES_MEM(offsetof(struct ioc3, ssram),
> + sizeof_field(struct ioc3, ssram)),
> + DEFINE_RES_IRQ(0)
> +};
> +
> +static struct resource ioc3_w1_resources[] = {
> + DEFINE_RES_MEM(offsetof(struct ioc3, mcr),
> + sizeof_field(struct ioc3, mcr)),
> +};
> +static struct sgi_w1_platform_data ioc3_w1_platform_data;
> +
> +static struct mfd_cell ioc3_eth_cells[] = {
> + {
> + .name = "ioc3-eth",
> + .resources = ioc3_eth_resources,
> + .num_resources = ARRAY_SIZE(ioc3_eth_resources),
> + },
> + {
> + .name = "sgi_w1",
> + .resources = ioc3_w1_resources,
> + .num_resources = ARRAY_SIZE(ioc3_w1_resources),
> + .platform_data = &ioc3_w1_platform_data,
> + .pdata_size = sizeof(ioc3_w1_platform_data),
> + }
> +};
> +
> +static int ioc3_eth_setup(struct ioc3_priv_data *ipd, bool use_domain)
> +{
> + int irq = ipd->pdev->irq;
> + int ret;
> +
> + /* enable One-Wire bus */
> + writel(GPCR_MLAN_EN, &ipd->regs->gpcr_s);
> +
> + /* generate unique identifier */
> + snprintf(ioc3_w1_platform_data.dev_id,
> + sizeof(ioc3_w1_platform_data.dev_id), "ioc3-%012llx",
> + ipd->pdev->resource->start);
> +
> + if (use_domain)
> + irq = irq_create_mapping(ipd->domain, IOC3_IRQ_ETH_DOMAIN);
> +
> + ret = mfd_add_devices(&ipd->pdev->dev, ioc3_eth_id, ioc3_eth_cells,
> + ARRAY_SIZE(ioc3_eth_cells),
> + &ipd->pdev->resource[0], irq, NULL);
> + if (ret) {
> + dev_err(&ipd->pdev->dev, "Failed to add ETH/W1 subdev\n");
> + return ret;
> + }
> +
Nit: Remove this line and place it below:
> + ioc3_eth_id++;
Nit: '\n' here
> + return 0;
> +}
> +
> +#define M48T35_REG_SIZE 32768 /* size of m48t35 registers */
> +
> +static struct resource ioc3_m48t35_resources[] = {
> + DEFINE_RES_MEM(IOC3_BYTEBUS_DEV0, M48T35_REG_SIZE)
> +};
> +
> +static struct mfd_cell ioc3_m48t35_cells[] = {
> + {
> + .name = "rtc-m48t35",
> + .resources = ioc3_m48t35_resources,
> + .num_resources = ARRAY_SIZE(ioc3_m48t35_resources),
> + }
> +};
> +
> +static int ioc3_m48t35_setup(struct ioc3_priv_data *ipd)
> +{
> + int ret;
> +
> + ret = mfd_add_devices(&ipd->pdev->dev, PLATFORM_DEVID_AUTO,
> + ioc3_m48t35_cells, ARRAY_SIZE(ioc3_m48t35_cells),
> + &ipd->pdev->resource[0], 0, ipd->domain);
> + if (ret)
> + dev_err(&ipd->pdev->dev, "Failed to add M48T35 subdev\n");
> +
> + return ret;
> +}
> +
> +/*
> + * On IP30 the RTC (a DS1687) is behind the IOC3 on the generic
> + * ByteBus regions. We have to write the RTC address of interest to
> + * IOC3_BYTEBUS_DEV1, then read the data from IOC3_BYTEBUS_DEV2.
> + * rtc->regs already points to IOC3_BYTEBUS_DEV1.
> + */
> +#define IP30_RTC_ADDR(rtc) (rtc->regs)
> +#define IP30_RTC_DATA(rtc) ((rtc->regs) + IOC3_BYTEBUS_DEV2 - IOC3_BYTEBUS_DEV1)
> +
> +static u8 ip30_rtc_read(struct ds1685_priv *rtc, int reg)
> +{
> + writeb((reg & 0x7f), IP30_RTC_ADDR(rtc));
> + return readb(IP30_RTC_DATA(rtc));
> +}
> +
> +static void ip30_rtc_write(struct ds1685_priv *rtc, int reg, u8 value)
> +{
> + writeb((reg & 0x7f), IP30_RTC_ADDR(rtc));
> + writeb(value, IP30_RTC_DATA(rtc));
> +}
Why is this not in the RTC driver?
> +static struct ds1685_rtc_platform_data ip30_rtc_platform_data = {
> + .bcd_mode = false,
> + .no_irq = false,
> + .uie_unsupported = true,
> + .alloc_io_resources = true,
> + .plat_read = ip30_rtc_read,
> + .plat_write = ip30_rtc_write,
Call-backs in a non-subsystem API is pretty ugly IMHO.
Where are these called from?
> +};
> +
> +static struct resource ioc3_rtc_ds1685_resources[] = {
> + DEFINE_RES_MEM(IOC3_BYTEBUS_DEV1,
> + IOC3_BYTEBUS_DEV2 - IOC3_BYTEBUS_DEV1 + 1),
> + DEFINE_RES_IRQ(0)
> +};
> +
> +static struct mfd_cell ioc3_ds1685_cells[] = {
> + {
> + .name = "rtc-ds1685",
> + .resources = ioc3_rtc_ds1685_resources,
> + .num_resources = ARRAY_SIZE(ioc3_rtc_ds1685_resources),
> + .platform_data = &ip30_rtc_platform_data,
> + .pdata_size = sizeof(ip30_rtc_platform_data),
> + .id = -1,
Use the #define. Same goes for below.
> + }
> +};
> +
> +static int ioc3_ds1685_setup(struct ioc3_priv_data *ipd)
> +{
> + int ret, irq;
> +
> + irq = ioc3_map_irq(ipd->pdev, 6);
Nit: '\n' here
> + ret = mfd_add_devices(&ipd->pdev->dev, 0, ioc3_ds1685_cells,
> + ARRAY_SIZE(ioc3_ds1685_cells),
> + &ipd->pdev->resource[0], irq, NULL);
> + if (ret)
> + dev_err(&ipd->pdev->dev, "Failed to add DS1685 subdev\n");
> +
> + return ret;
> +};
> +
> +
> +static struct resource ioc3_leds_resources[] = {
> + DEFINE_RES_MEM(offsetof(struct ioc3, gppr[0]),
> + sizeof_field(struct ioc3, gppr[0])),
> + DEFINE_RES_MEM(offsetof(struct ioc3, gppr[1]),
> + sizeof_field(struct ioc3, gppr[1])),
> +};
> +
> +static struct mfd_cell ioc3_led_cells[] = {
> + {
> + .name = "ip30-leds",
> + .resources = ioc3_leds_resources,
> + .num_resources = ARRAY_SIZE(ioc3_leds_resources),
> + .id = -1,
> + }
> +};
> +
> +static int ioc3_led_setup(struct ioc3_priv_data *ipd)
> +{
> + int ret;
> +
> + ret = mfd_add_devices(&ipd->pdev->dev, 0, ioc3_led_cells,
> + ARRAY_SIZE(ioc3_led_cells),
> + &ipd->pdev->resource[0], 0, ipd->domain);
> + if (ret)
> + dev_err(&ipd->pdev->dev, "Failed to add LED subdev\n");
Nit: '\n' here
> + return ret;
> +}
> +
> +static int ip27_baseio_setup(struct ioc3_priv_data *ipd)
> +{
> + int ret, io_irq;
> +
> + io_irq = ioc3_map_irq(ipd->pdev, PCI_SLOT(ipd->pdev->devfn) + 2);
> + ret = ioc3_irq_domain_setup(ipd, io_irq);
> + if (ret)
> + return ret;
Nit: '\n' here
> + ret = ioc3_eth_setup(ipd, false);
> + if (ret)
> + return ret;
Nit: '\n' here
> + ret = ioc3_serial_setup(ipd);
> + if (ret)
> + return ret;
Nit: '\n' here
Etc, etc, etc ... same for all of the instances below.
> + return ioc3_m48t35_setup(ipd);
> +}
> +
> +static int ip27_baseio6g_setup(struct ioc3_priv_data *ipd)
> +{
> + int ret, io_irq;
> +
> + io_irq = ioc3_map_irq(ipd->pdev, PCI_SLOT(ipd->pdev->devfn) + 2);
> + ret = ioc3_irq_domain_setup(ipd, io_irq);
> + if (ret)
> + return ret;
> + ret = ioc3_eth_setup(ipd, false);
> + if (ret)
> + return ret;
> + ret = ioc3_serial_setup(ipd);
> + if (ret)
> + return ret;
> + ret = ioc3_m48t35_setup(ipd);
> + if (ret)
> + return ret;
> + return ioc3_kbd_setup(ipd);
> +}
> +
> +static int ip27_mio_setup(struct ioc3_priv_data *ipd)
> +{
> + int ret;
> +
> + ret = ioc3_irq_domain_setup(ipd, ipd->pdev->irq);
> + if (ret)
> + return ret;
> + ret = ioc3_serial_setup(ipd);
> + if (ret)
> + return ret;
> + return ioc3_kbd_setup(ipd);
> +}
> +
> +static int ip29_sysboard_setup(struct ioc3_priv_data *ipd)
> +{
> + int ret, io_irq;
> +
> + io_irq = ioc3_map_irq(ipd->pdev, PCI_SLOT(ipd->pdev->devfn) + 1);
> + ret = ioc3_irq_domain_setup(ipd, io_irq);
> + if (ret)
> + return ret;
> + ret = ioc3_eth_setup(ipd, false);
> + if (ret)
> + return ret;
> + ret = ioc3_serial_setup(ipd);
> + if (ret)
> + return ret;
> + ret = ioc3_m48t35_setup(ipd);
> + if (ret)
> + return ret;
> + return ioc3_kbd_setup(ipd);
> +}
> +
> +static int ip30_sysboard_setup(struct ioc3_priv_data *ipd)
> +{
> + int ret, io_irq;
> +
> + io_irq = ioc3_map_irq(ipd->pdev, PCI_SLOT(ipd->pdev->devfn) + 2);
> + ret = ioc3_irq_domain_setup(ipd, io_irq);
> + if (ret)
> + return ret;
> + ret = ioc3_eth_setup(ipd, false);
> + if (ret)
> + return ret;
> + ret = ioc3_serial_setup(ipd);
> + if (ret)
> + return ret;
> + ret = ioc3_kbd_setup(ipd);
> + if (ret)
> + return ret;
> + ret = ioc3_ds1685_setup(ipd);
> + if (ret)
> + return ret;
> + return ioc3_led_setup(ipd);
> +}
> +
> +static int ioc3_menet_setup(struct ioc3_priv_data *ipd)
> +{
> + int ret, io_irq;
> +
> + io_irq = ioc3_map_irq(ipd->pdev, PCI_SLOT(ipd->pdev->devfn) + 4);
> + ret = ioc3_irq_domain_setup(ipd, io_irq);
> + if (ret)
> + return ret;
> + ret = ioc3_eth_setup(ipd, false);
> + if (ret)
> + return ret;
> + return ioc3_serial_setup(ipd);
> +}
> +
> +static int ioc3_menet4_setup(struct ioc3_priv_data *ipd)
> +{
> + return ioc3_eth_setup(ipd, false);
> +}
> +
> +static int ioc3_cad_duo_setup(struct ioc3_priv_data *ipd)
> +{
> + int ret;
> +
> + ret = ioc3_irq_domain_setup(ipd, ipd->pdev->irq);
> + if (ret)
> + return ret;
> + ret = ioc3_eth_setup(ipd, true);
> + if (ret)
> + return ret;
> + return ioc3_kbd_setup(ipd);
> +}
> +
> +#define IOC3_SID(_name, _sid, _setup) \
> + { \
> + .name = _name, \
> + .sid = (PCI_VENDOR_ID_SGI << 16) | IOC3_SUBSYS_ ## _sid, \
> + .setup = _setup, \
> + }
> +
> +static struct {
> + const char *name;
> + u32 sid;
> + int (*setup)(struct ioc3_priv_data *ipd);
> +} ioc3_infos[] = {
IMHO it's neater if you separate the definition and static data part.
> + IOC3_SID("IP27 BaseIO6G", IP27_BASEIO6G, &ip27_baseio6g_setup),
> + IOC3_SID("IP27 MIO", IP27_MIO, &ip27_mio_setup),
> + IOC3_SID("IP27 BaseIO", IP27_BASEIO, &ip27_baseio_setup),
> + IOC3_SID("IP29 System Board", IP29_SYSBOARD, &ip29_sysboard_setup),
> + IOC3_SID("IP30 System Board", IP30_SYSBOARD, &ip30_sysboard_setup),
> + IOC3_SID("MENET", MENET, &ioc3_menet_setup),
> + IOC3_SID("MENET4", MENET4, &ioc3_menet4_setup)
> +};
> +
> +static int ioc3_setup(struct ioc3_priv_data *ipd)
> +{
> + u32 sid;
> + int i;
> +
> + /* Clear IRQs */
> + writel(~0, &ipd->regs->sio_iec);
> + writel(~0, &ipd->regs->sio_ir);
> + writel(0, &ipd->regs->eth.eier);
> + writel(~0, &ipd->regs->eth.eisr);
> +
> + /* read subsystem vendor id and subsystem id */
> + pci_read_config_dword(ipd->pdev, PCI_SUBSYSTEM_VENDOR_ID, &sid);
> +
> + for (i = 0; i < ARRAY_SIZE(ioc3_infos); i++)
> + if (sid == ioc3_infos[i].sid) {
> + pr_info("ioc3: %s\n", ioc3_infos[i].name);
> + return ioc3_infos[i].setup(ipd);
> + }
> +
> + /* treat everything not identified by PCI subid as CAD DUO */
> + pr_info("ioc3: CAD DUO\n");
> + return ioc3_cad_duo_setup(ipd);
> +}
> +
> +static int ioc3_mfd_probe(struct pci_dev *pdev,
> + const struct pci_device_id *pci_id)
> +{
> + struct ioc3_priv_data *ipd;
> + struct ioc3 __iomem *regs;
> + int ret;
> +
> + ret = pci_enable_device(pdev);
> + if (ret)
> + return ret;
> +
> + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
What does 64 mean here? Define it perhaps?
> + pci_set_master(pdev);
> +
> + ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
> + if (ret) {
> + dev_warn(&pdev->dev, "Warning: couldn_t set 64-bit DMA mask\n");
Remove the "Warning:" part please.
"Failed to set 64-bit DMA mask - trying 32-bit" ?
> + ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
> + if (ret) {
> + dev_err(&pdev->dev, "Can't set DMA mask, aborting\n");
> + return ret;
> + }
> + }
> +
> + /* Set up per-IOC3 data */
> + ipd = devm_kzalloc(&pdev->dev, sizeof(struct ioc3_priv_data),
> + GFP_KERNEL);
> + if (!ipd) {
> + ret = -ENOMEM;
> + goto out_disable_device;
> + }
> + ipd->pdev = pdev;
> +
> + /*
> + * Map all IOC3 registers. These are shared between subdevices
> + * so the main IOC3 module manages them.
> + */
> + regs = devm_ioremap(&pdev->dev, pci_resource_start(pdev, 0),
> + pci_resource_len(pdev, 0));
> + if (!regs) {
> + pr_warn("ioc3: Unable to remap PCI BAR for %s.\n",
> + pci_name(pdev));
Why are you using pr_warn() here?
> + ret = -ENOMEM;
> + goto out_disable_device;
> + }
> + ipd->regs = regs;
> +
> + /* Track PCI-device specific data */
> + pci_set_drvdata(pdev, ipd);
> +
> + ret = ioc3_setup(ipd);
> + if (ret)
> + goto out_disable_device;
> +
> + return 0;
> +
> +out_disable_device:
> + pci_disable_device(pdev);
> + return ret;
> +}
> +
> +static void ioc3_mfd_remove(struct pci_dev *pdev)
> +{
> + struct ioc3_priv_data *ipd;
> +
> + ipd = pci_get_drvdata(pdev);
> +
> + /* Clear and disable all IRQs */
> + writel(~0, &ipd->regs->sio_iec);
> + writel(~0, &ipd->regs->sio_ir);
> +
> + /* Release resources */
> + if (ipd->domain) {
> + irq_domain_remove(ipd->domain);
> + free_irq(ipd->domain_irq, (void *)ipd);
> + }
> + pci_disable_device(pdev);
> +}
> +
> +static struct pci_device_id ioc3_mfd_id_table[] = {
> + { PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3, PCI_ANY_ID, PCI_ANY_ID },
> + { 0, },
> +};
> +MODULE_DEVICE_TABLE(pci, ioc3_mfd_id_table);
> +
> +static struct pci_driver ioc3_mfd_driver = {
> + .name = "IOC3",
> + .id_table = ioc3_mfd_id_table,
> + .probe = ioc3_mfd_probe,
> + .remove = ioc3_mfd_remove,
> +};
> +
> +module_pci_driver(ioc3_mfd_driver);
> +
> +MODULE_AUTHOR("Thomas Bogendoerfer <tbogendoerfer@suse.de>");
> +MODULE_DESCRIPTION("SGI IOC3 MFD driver");
> +MODULE_LICENSE("GPL");
GPL v2 ?
--
Lee Jones [李琼斯]
Linaro Services Technical Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply
* [PATCH] net: bridge: Allow bridge to joing multicast groups
From: Horatiu Vultur @ 2019-07-25 11:44 UTC (permalink / raw)
To: roopa, nikolay, davem, bridge, netdev, linux-kernel,
allan.nielsen
Cc: Horatiu Vultur
There is no way to configure the bridge, to receive only specific link
layer multicast addresses. From the description of the command 'bridge
fdb append' is supposed to do that, but there was no way to notify the
network driver that the bridge joined a group, because LLADDR was added
to the unicast netdev_hw_addr_list.
Therefore update fdb_add_entry to check if the NLM_F_APPEND flag is set
and if the source is NULL, which represent the bridge itself. Then add
address to multicast netdev_hw_addr_list for each bridge interfaces.
And then the .ndo_set_rx_mode function on the driver is called. To notify
the driver that the list of multicast mac addresses changed.
Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com>
---
net/bridge/br_fdb.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 46 insertions(+), 3 deletions(-)
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index b1d3248..d93746d 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -175,6 +175,29 @@ static void fdb_add_hw_addr(struct net_bridge *br, const unsigned char *addr)
}
}
+static void fdb_add_hw_maddr(struct net_bridge *br, const unsigned char *addr)
+{
+ int err;
+ struct net_bridge_port *p;
+
+ ASSERT_RTNL();
+
+ list_for_each_entry(p, &br->port_list, list) {
+ if (!br_promisc_port(p)) {
+ err = dev_mc_add(p->dev, addr);
+ if (err)
+ goto undo;
+ }
+ }
+
+ return;
+undo:
+ list_for_each_entry_continue_reverse(p, &br->port_list, list) {
+ if (!br_promisc_port(p))
+ dev_mc_del(p->dev, addr);
+ }
+}
+
/* When a static FDB entry is deleted, the HW address from that entry is
* also removed from the bridge private HW address list and updates all
* the ports with needed information.
@@ -192,13 +215,27 @@ static void fdb_del_hw_addr(struct net_bridge *br, const unsigned char *addr)
}
}
+static void fdb_del_hw_maddr(struct net_bridge *br, const unsigned char *addr)
+{
+ struct net_bridge_port *p;
+
+ ASSERT_RTNL();
+
+ list_for_each_entry(p, &br->port_list, list) {
+ if (!br_promisc_port(p))
+ dev_mc_del(p->dev, addr);
+ }
+}
+
static void fdb_delete(struct net_bridge *br, struct net_bridge_fdb_entry *f,
bool swdev_notify)
{
trace_fdb_delete(br, f);
- if (f->is_static)
+ if (f->is_static) {
fdb_del_hw_addr(br, f->key.addr.addr);
+ fdb_del_hw_maddr(br, f->key.addr.addr);
+ }
hlist_del_init_rcu(&f->fdb_node);
rhashtable_remove_fast(&br->fdb_hash_tbl, &f->rhnode,
@@ -843,13 +880,19 @@ static int fdb_add_entry(struct net_bridge *br, struct net_bridge_port *source,
fdb->is_local = 1;
if (!fdb->is_static) {
fdb->is_static = 1;
- fdb_add_hw_addr(br, addr);
+ if (flags & NLM_F_APPEND && !source)
+ fdb_add_hw_maddr(br, addr);
+ else
+ fdb_add_hw_addr(br, addr);
}
} else if (state & NUD_NOARP) {
fdb->is_local = 0;
if (!fdb->is_static) {
fdb->is_static = 1;
- fdb_add_hw_addr(br, addr);
+ if (flags & NLM_F_APPEND && !source)
+ fdb_add_hw_maddr(br, addr);
+ else
+ fdb_add_hw_addr(br, addr);
}
} else {
fdb->is_local = 0;
--
2.7.4
^ permalink raw reply related
* Re: [PATCH net-next 3/3] net: stmmac: Introducing support for Page Pool
From: Ilias Apalodimas @ 2019-07-25 11:39 UTC (permalink / raw)
To: Jon Hunter
Cc: Jose Abreu, David Miller, robin.murphy@arm.com, lists@bofh.nu,
Joao.Pinto@synopsys.com, alexandre.torgue@st.com,
maxime.ripard@bootlin.com, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org,
linux-stm32@st-md-mailman.stormreply.com, wens@csie.org,
mcoquelin.stm32@gmail.com, linux-tegra@vger.kernel.org,
peppe.cavallaro@st.com, linux-arm-kernel@lists.infradead.org
In-Reply-To: <d2658b7d-1f24-70f7-fafe-b60a0fd7d240@nvidia.com>
Hi Jon, Jose,
On Thu, Jul 25, 2019 at 10:45:46AM +0100, Jon Hunter wrote:
>
> On 25/07/2019 08:44, Jose Abreu wrote:
>
> ...
>
> > OK. Can you please test what Ilias mentioned ?
> >
> > Basically you can hard-code the order to 0 in
> > alloc_dma_rx_desc_resources():
> > - pp_params.order = DIV_ROUND_UP(priv->dma_buf_sz, PAGE_SIZE);
> > + pp_params.order = 0;
> >
> > Unless you use a MTU > PAGE_SIZE.
>
> I made the change but unfortunately the issue persists.
Yea tbh i didn't expect this to fix it, since i think the mappings are fine, but
it never hurts to verify.
@Jose: Can we add some debugging prints on the driver?
Ideally the pages the api allocates (on init), the page that the driver is
trying to use before the crash and the size of the packet (right from the device
descriptor). Maybe this will tell us where the erroneous access is
Thanks
/Ilias
^ permalink raw reply
* Re: [PATCH bpf-next v4 3/6] xdp: Add devmap_hash map type for looking up devices by hashed index
From: Jesper Dangaard Brouer @ 2019-07-25 11:37 UTC (permalink / raw)
To: Toke Høiland-Jørgensen
Cc: Daniel Borkmann, Alexei Starovoitov, netdev, David Miller,
Jakub Kicinski, Björn Töpel, Yonghong Song, brouer
In-Reply-To: <87muh2z9os.fsf@toke.dk>
On Thu, 25 Jul 2019 12:32:19 +0200
Toke Høiland-Jørgensen <toke@redhat.com> wrote:
> Jesper Dangaard Brouer <brouer@redhat.com> writes:
>
> > On Mon, 22 Jul 2019 13:52:48 +0200
> > Toke Høiland-Jørgensen <toke@redhat.com> wrote:
> >
> >> +static inline struct hlist_head *dev_map_index_hash(struct bpf_dtab *dtab,
> >> + int idx)
> >> +{
> >> + return &dtab->dev_index_head[idx & (NETDEV_HASHENTRIES - 1)];
> >> +}
> >
> > It is good for performance that our "hash" function is simply an AND
> > operation on the idx. We want to keep it this way.
> >
> > I don't like that you are using NETDEV_HASHENTRIES, because the BPF map
> > infrastructure already have a way to specify the map size (struct
> > bpf_map_def .max_entries). BUT for performance reasons, to keep the
> > AND operation, we would need to round up the hash-array size to nearest
> > power of 2 (or reject if user didn't specify a power of 2, if we want
> > to "expose" this limit to users).
>
> But do we really want the number of hash buckets to be equal to the max
> number of entries? The values are not likely to be evenly distributed,
> so we'll end up with big buckets if the number is small, meaning we'll
> blow performance on walking long lists in each bucket.
The requested change makes it user-configurable, instead of fixed 256
entries. I've seen production use-case with >5000 net_devices, thus
they need a knob to increase this (to avoid the list walking as you
mention).
> Also, if the size is dynamic the size needs to be loaded from memory
> instead of being a compile-time constant, which will presumably hurt
> performance (though not sure by how much)?
To counter this, the mask value which need to be loaded from memory,
needs to be placed next to some other struct member which is already in
use (at least on same cacheline, Intel have some 16 bytes access micro
optimizations, which I've never been able to measure, as its in 0.5
nanosec scale).
--
Best regards,
Jesper Dangaard Brouer
MSc.CS, Principal Kernel Engineer at Red Hat
LinkedIn: http://www.linkedin.com/in/brouer
^ permalink raw reply
* [PATCH][next] can: kvaser_pciefd: remove redundant negative check on trigger
From: Colin King @ 2019-07-25 11:25 UTC (permalink / raw)
To: Wolfgang Grandegger, Marc Kleine-Budde, David S . Miller,
linux-can, netdev
Cc: kernel-janitors, linux-kernel
From: Colin Ian King <colin.king@canonical.com>
The check to see if trigger is less than zero is always false, trigger
is always in the range 0..255. Hence the check is redundant and can
be removed.
Addresses-Coverity: ("Logically dead code")
Signed-off-by: Colin Ian King <colin.king@canonical.com>
---
drivers/net/can/kvaser_pciefd.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/drivers/net/can/kvaser_pciefd.c b/drivers/net/can/kvaser_pciefd.c
index 3af747cbbde4..68e00aad0810 100644
--- a/drivers/net/can/kvaser_pciefd.c
+++ b/drivers/net/can/kvaser_pciefd.c
@@ -652,9 +652,6 @@ static void kvaser_pciefd_pwm_stop(struct kvaser_pciefd_can *can)
top = (pwm_ctrl >> KVASER_PCIEFD_KCAN_PWM_TOP_SHIFT) & 0xff;
trigger = (100 * top + 50) / 100;
- if (trigger < 0)
- trigger = 0;
-
pwm_ctrl = trigger & 0xff;
pwm_ctrl |= (top & 0xff) << KVASER_PCIEFD_KCAN_PWM_TOP_SHIFT;
iowrite32(pwm_ctrl, can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG);
--
2.20.1
^ permalink raw reply related
* [PATCH] net/mlx5e: Fix zero table prio set by user.
From: wenxu @ 2019-07-25 11:24 UTC (permalink / raw)
To: saeedm; +Cc: netdev
From: wenxu <wenxu@ucloud.cn>
The flow_cls_common_offload prio is zero
It leads the invalid table prio in hw.
Error: Could not process rule: Invalid argument
kernel log:
mlx5_core 0000:81:00.0: E-Switch: Failed to create FDB Table err -22 (table prio: 65535, level: 0, size: 4194304)
table_prio = (chain * FDB_MAX_PRIO) + prio - 1;
should check (chain * FDB_MAX_PRIO) + prio is not 0
Signed-off-by: wenxu <wenxu@ucloud.cn>
---
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
index 089ae4d..64ca90f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
@@ -970,7 +970,9 @@ static int esw_add_fdb_miss_rule(struct mlx5_eswitch *esw)
flags |= (MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT |
MLX5_FLOW_TABLE_TUNNEL_EN_DECAP);
- table_prio = (chain * FDB_MAX_PRIO) + prio - 1;
+ table_prio = (chain * FDB_MAX_PRIO) + prio;
+ if (table_prio)
+ table_prio = table_prio - 1;
/* create earlier levels for correct fs_core lookup when
* connecting tables
--
1.8.3.1
^ permalink raw reply related
* [PATCH net-next v2 0/4] enetc: Add mdio bus driver for the PCIe MDIO endpoint
From: Claudiu Manoil @ 2019-07-25 11:19 UTC (permalink / raw)
To: David S . Miller
Cc: andrew, Rob Herring, Li Yang, alexandru.marginean, netdev,
devicetree, linux-arm-kernel, linux-kernel
Second patch just registers the PCIe endpoint device containing
the MDIO registers as a standalone MDIO bus driver, to allow
an alternative way to control the MDIO bus. The same code used
by the ENETC ports (eth controllers) to manage MDIO via local
registers applies and is reused.
Bindings are provided for the new MDIO node, similarly to ENETC
port nodes bindings.
Last patch enables the ENETC port 1 and its RGMII PHY on the
LS1028A QDS board, where the MDIO muxing configuration relies
on the MDIO support provided in the first patch.
Claudiu Manoil (4):
enetc: Clean up local mdio bus allocation
enetc: Add mdio bus driver for the PCIe MDIO endpoint
dt-bindings: net: fsl: enetc: Add bindings for the central MDIO PCIe
endpoint
arm64: dts: fsl: ls1028a: Enable eth port1 on the ls1028a QDS board
.../devicetree/bindings/net/fsl-enetc.txt | 42 +++-
.../boot/dts/freescale/fsl-ls1028a-qds.dts | 40 ++++
.../arm64/boot/dts/freescale/fsl-ls1028a.dtsi | 6 +
.../net/ethernet/freescale/enetc/enetc_mdio.c | 190 +++++++++++++-----
.../net/ethernet/freescale/enetc/enetc_pf.c | 5 +-
5 files changed, 232 insertions(+), 51 deletions(-)
--
2.17.1
^ permalink raw reply
* [PATCH net-next v2 4/4] arm64: dts: fsl: ls1028a: Enable eth port1 on the ls1028a QDS board
From: Claudiu Manoil @ 2019-07-25 11:19 UTC (permalink / raw)
To: David S . Miller
Cc: andrew, Rob Herring, Li Yang, alexandru.marginean, netdev,
devicetree, linux-arm-kernel, linux-kernel
In-Reply-To: <1564053568-20522-1-git-send-email-claudiu.manoil@nxp.com>
LS1028a has one Ethernet management interface. On the QDS board, the
MDIO signals are multiplexed to either on-board AR8035 PHY device or
to 4 PCIe slots allowing for SGMII cards.
To enable the Ethernet ENETC Port 1, which can only be connected to a
RGMII PHY, the multiplexer needs to be configured to route the MDIO to
the AR8035 PHY. The MDIO/MDC routing is controlled by bits 7:4 of FPGA
board config register 0x54, and value 0 selects the on-board RGMII PHY.
The FPGA board config registers are accessible on the i2c bus, at address
0x66.
The PF3 MDIO PCIe integrated endpoint device allows for centralized access
to the MDIO bus. Add the corresponding devicetree node and set it to be
the MDIO bus parent.
Signed-off-by: Alex Marginean <alexandru.marginean@nxp.com>
Signed-off-by: Claudiu Manoil <claudiu.manoil@nxp.com>
---
v1 - none
v2 - none
.../boot/dts/freescale/fsl-ls1028a-qds.dts | 40 +++++++++++++++++++
.../arm64/boot/dts/freescale/fsl-ls1028a.dtsi | 6 +++
2 files changed, 46 insertions(+)
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dts
index de6ef39f3118..663c4b728c07 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dts
@@ -85,6 +85,26 @@
system-clock-frequency = <25000000>;
};
};
+
+ mdio-mux {
+ compatible = "mdio-mux-multiplexer";
+ mux-controls = <&mux 0>;
+ mdio-parent-bus = <&enetc_mdio_pf3>;
+ #address-cells=<1>;
+ #size-cells = <0>;
+
+ /* on-board RGMII PHY */
+ mdio@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ qds_phy1: ethernet-phy@5 {
+ /* Atheros 8035 */
+ reg = <5>;
+ };
+ };
+ };
};
&duart0 {
@@ -164,6 +184,26 @@
};
};
};
+
+ fpga@66 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,ls1028aqds-fpga", "fsl,fpga-qixis-i2c",
+ "simple-mfd";
+ reg = <0x66>;
+
+ mux: mux-controller {
+ compatible = "reg-mux";
+ #mux-control-cells = <1>;
+ mux-reg-masks = <0x54 0xf0>; /* 0: reg 0x54, bits 7:4 */
+ };
+ };
+
+};
+
+&enetc_port1 {
+ phy-handle = <&qds_phy1>;
+ phy-connection-type = "rgmii-id";
};
&sai1 {
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi
index 7975519b4f56..de71153fda00 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi
@@ -536,6 +536,12 @@
compatible = "fsl,enetc";
reg = <0x000100 0 0 0 0>;
};
+ enetc_mdio_pf3: mdio@0,3 {
+ compatible = "fsl,enetc-mdio";
+ reg = <0x000300 0 0 0 0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
ethernet@0,4 {
compatible = "fsl,enetc-ptp";
reg = <0x000400 0 0 0 0>;
--
2.17.1
^ permalink raw reply related
* [PATCH net-next v2 1/4] enetc: Clean up local mdio bus allocation
From: Claudiu Manoil @ 2019-07-25 11:19 UTC (permalink / raw)
To: David S . Miller
Cc: andrew, Rob Herring, Li Yang, alexandru.marginean, netdev,
devicetree, linux-arm-kernel, linux-kernel
In-Reply-To: <1564053568-20522-1-git-send-email-claudiu.manoil@nxp.com>
What's needed is basically a pointer to the mdio registers.
This is one way to store it inside bus->priv allocated space,
without upsetting sparse.
Reworked accessor design as requested by Andrew Lunn in the
process.
Used devm_* variant to further clean up the init error /
remove paths.
Fixes following sparse warning:
warning: incorrect type in assignment (different address spaces)
expected void *priv
got struct enetc_mdio_regs [noderef] <asn:2>*[assigned] regs
Fixes: ebfcb23d62ab ("enetc: Add ENETC PF level external MDIO support")
CC: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Claudiu Manoil <claudiu.manoil@nxp.com>
---
v1 - added this patch
v2 - reworked accessors as per Andrew Lunn's request
.../net/ethernet/freescale/enetc/enetc_mdio.c | 94 +++++++++----------
1 file changed, 46 insertions(+), 48 deletions(-)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_mdio.c b/drivers/net/ethernet/freescale/enetc/enetc_mdio.c
index 77b9cd10ba2b..05094601ece8 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_mdio.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_mdio.c
@@ -8,16 +8,22 @@
#include "enetc_pf.h"
-struct enetc_mdio_regs {
- u32 mdio_cfg; /* MDIO configuration and status */
- u32 mdio_ctl; /* MDIO control */
- u32 mdio_data; /* MDIO data */
- u32 mdio_addr; /* MDIO address */
+#define ENETC_MDIO_REG_OFFSET 0x1c00
+#define ENETC_MDIO_CFG 0x0 /* MDIO configuration and status */
+#define ENETC_MDIO_CTL 0x4 /* MDIO control */
+#define ENETC_MDIO_DATA 0x8 /* MDIO data */
+#define ENETC_MDIO_ADDR 0xc /* MDIO address */
+
+#define enetc_mdio_rd(hw, off) \
+ enetc_port_rd(hw, ENETC_##off + ENETC_MDIO_REG_OFFSET)
+#define enetc_mdio_wr(hw, off, val) \
+ enetc_port_wr(hw, ENETC_##off + ENETC_MDIO_REG_OFFSET, val)
+#define enetc_mdio_rd_reg(off) enetc_mdio_rd(hw, off)
+
+struct enetc_mdio_priv {
+ struct enetc_hw *hw;
};
-#define bus_to_enetc_regs(bus) (struct enetc_mdio_regs __iomem *)((bus)->priv)
-
-#define ENETC_MDIO_REG_OFFSET 0x1c00
#define ENETC_MDC_DIV 258
#define MDIO_CFG_CLKDIV(x) ((((x) >> 1) & 0xff) << 8)
@@ -33,18 +39,19 @@ struct enetc_mdio_regs {
#define MDIO_DATA(x) ((x) & 0xffff)
#define TIMEOUT 1000
-static int enetc_mdio_wait_complete(struct enetc_mdio_regs __iomem *regs)
+static int enetc_mdio_wait_complete(struct enetc_hw *hw)
{
u32 val;
- return readx_poll_timeout(enetc_rd_reg, ®s->mdio_cfg, val,
+ return readx_poll_timeout(enetc_mdio_rd_reg, MDIO_CFG, val,
!(val & MDIO_CFG_BSY), 10, 10 * TIMEOUT);
}
static int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum,
u16 value)
{
- struct enetc_mdio_regs __iomem *regs = bus_to_enetc_regs(bus);
+ struct enetc_mdio_priv *mdio_priv = bus->priv;
+ struct enetc_hw *hw = mdio_priv->hw;
u32 mdio_ctl, mdio_cfg;
u16 dev_addr;
int ret;
@@ -59,29 +66,29 @@ static int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum,
mdio_cfg &= ~MDIO_CFG_ENC45;
}
- enetc_wr_reg(®s->mdio_cfg, mdio_cfg);
+ enetc_mdio_wr(hw, MDIO_CFG, mdio_cfg);
- ret = enetc_mdio_wait_complete(regs);
+ ret = enetc_mdio_wait_complete(hw);
if (ret)
return ret;
/* set port and dev addr */
mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr);
- enetc_wr_reg(®s->mdio_ctl, mdio_ctl);
+ enetc_mdio_wr(hw, MDIO_CTL, mdio_ctl);
/* set the register address */
if (regnum & MII_ADDR_C45) {
- enetc_wr_reg(®s->mdio_addr, regnum & 0xffff);
+ enetc_mdio_wr(hw, MDIO_ADDR, regnum & 0xffff);
- ret = enetc_mdio_wait_complete(regs);
+ ret = enetc_mdio_wait_complete(hw);
if (ret)
return ret;
}
/* write the value */
- enetc_wr_reg(®s->mdio_data, MDIO_DATA(value));
+ enetc_mdio_wr(hw, MDIO_DATA, MDIO_DATA(value));
- ret = enetc_mdio_wait_complete(regs);
+ ret = enetc_mdio_wait_complete(hw);
if (ret)
return ret;
@@ -90,7 +97,8 @@ static int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum,
static int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
{
- struct enetc_mdio_regs __iomem *regs = bus_to_enetc_regs(bus);
+ struct enetc_mdio_priv *mdio_priv = bus->priv;
+ struct enetc_hw *hw = mdio_priv->hw;
u32 mdio_ctl, mdio_cfg;
u16 dev_addr, value;
int ret;
@@ -104,41 +112,41 @@ static int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
mdio_cfg &= ~MDIO_CFG_ENC45;
}
- enetc_wr_reg(®s->mdio_cfg, mdio_cfg);
+ enetc_mdio_wr(hw, MDIO_CFG, mdio_cfg);
- ret = enetc_mdio_wait_complete(regs);
+ ret = enetc_mdio_wait_complete(hw);
if (ret)
return ret;
/* set port and device addr */
mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr);
- enetc_wr_reg(®s->mdio_ctl, mdio_ctl);
+ enetc_mdio_wr(hw, MDIO_CTL, mdio_ctl);
/* set the register address */
if (regnum & MII_ADDR_C45) {
- enetc_wr_reg(®s->mdio_addr, regnum & 0xffff);
+ enetc_mdio_wr(hw, MDIO_ADDR, regnum & 0xffff);
- ret = enetc_mdio_wait_complete(regs);
+ ret = enetc_mdio_wait_complete(hw);
if (ret)
return ret;
}
/* initiate the read */
- enetc_wr_reg(®s->mdio_ctl, mdio_ctl | MDIO_CTL_READ);
+ enetc_mdio_wr(hw, MDIO_CTL, mdio_ctl | MDIO_CTL_READ);
- ret = enetc_mdio_wait_complete(regs);
+ ret = enetc_mdio_wait_complete(hw);
if (ret)
return ret;
/* return all Fs if nothing was there */
- if (enetc_rd_reg(®s->mdio_cfg) & MDIO_CFG_RD_ER) {
+ if (enetc_mdio_rd(hw, MDIO_CFG) & MDIO_CFG_RD_ER) {
dev_dbg(&bus->dev,
"Error while reading PHY%d reg at %d.%hhu\n",
phy_id, dev_addr, regnum);
return 0xffff;
}
- value = enetc_rd_reg(®s->mdio_data) & 0xffff;
+ value = enetc_mdio_rd(hw, MDIO_DATA) & 0xffff;
return value;
}
@@ -146,12 +154,12 @@ static int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
int enetc_mdio_probe(struct enetc_pf *pf)
{
struct device *dev = &pf->si->pdev->dev;
- struct enetc_mdio_regs __iomem *regs;
+ struct enetc_mdio_priv *mdio_priv;
struct device_node *np;
struct mii_bus *bus;
- int ret;
+ int err;
- bus = mdiobus_alloc_size(sizeof(regs));
+ bus = devm_mdiobus_alloc_size(dev, sizeof(*mdio_priv));
if (!bus)
return -ENOMEM;
@@ -159,41 +167,31 @@ int enetc_mdio_probe(struct enetc_pf *pf)
bus->read = enetc_mdio_read;
bus->write = enetc_mdio_write;
bus->parent = dev;
+ mdio_priv = bus->priv;
+ mdio_priv->hw = &pf->si->hw;
snprintf(bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev));
- /* store the enetc mdio base address for this bus */
- regs = pf->si->hw.port + ENETC_MDIO_REG_OFFSET;
- bus->priv = regs;
-
np = of_get_child_by_name(dev->of_node, "mdio");
if (!np) {
dev_err(dev, "MDIO node missing\n");
- ret = -EINVAL;
- goto err_registration;
+ return -EINVAL;
}
- ret = of_mdiobus_register(bus, np);
- if (ret) {
+ err = of_mdiobus_register(bus, np);
+ if (err) {
of_node_put(np);
dev_err(dev, "cannot register MDIO bus\n");
- goto err_registration;
+ return err;
}
of_node_put(np);
pf->mdio = bus;
return 0;
-
-err_registration:
- mdiobus_free(bus);
-
- return ret;
}
void enetc_mdio_remove(struct enetc_pf *pf)
{
- if (pf->mdio) {
+ if (pf->mdio)
mdiobus_unregister(pf->mdio);
- mdiobus_free(pf->mdio);
- }
}
--
2.17.1
^ permalink raw reply related
* [PATCH net-next v2 2/4] enetc: Add mdio bus driver for the PCIe MDIO endpoint
From: Claudiu Manoil @ 2019-07-25 11:19 UTC (permalink / raw)
To: David S . Miller
Cc: andrew, Rob Herring, Li Yang, alexandru.marginean, netdev,
devicetree, linux-arm-kernel, linux-kernel
In-Reply-To: <1564053568-20522-1-git-send-email-claudiu.manoil@nxp.com>
ENETC ports can manage the MDIO bus via local register
interface. However there's also a centralized way
to manage the MDIO bus, via the MDIO PCIe endpoint
device integrated by the same root complex that also
integrates the ENETC ports (eth controllers).
Depending on board design and use case, centralized
access to MDIO may be better than using local ENETC
port registers. For instance, on the LS1028A QDS board
where MDIO muxing is requiered. Also, the LS1028A on-chip
switch doesn't have a local MDIO register interface.
The current patch registers the above PCIe enpoint as a
separate MDIO bus and provides a driver for it by re-using
the code used for local MDIO access. It also allows the
ENETC port PHYs to be managed by this driver if the local
"mdio" node is missing from the ENETC port node.
Signed-off-by: Claudiu Manoil <claudiu.manoil@nxp.com>
---
v1 - fixed mdio bus allocation
- requested only BAR0 region, as it's the only one used by the driver
v2 - reworked accessors as per Andrew Lunn's request
.../net/ethernet/freescale/enetc/enetc_mdio.c | 98 +++++++++++++++++++
.../net/ethernet/freescale/enetc/enetc_pf.c | 5 +-
2 files changed, 102 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_mdio.c b/drivers/net/ethernet/freescale/enetc/enetc_mdio.c
index 05094601ece8..56ad94a3504c 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_mdio.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_mdio.c
@@ -195,3 +195,101 @@ void enetc_mdio_remove(struct enetc_pf *pf)
if (pf->mdio)
mdiobus_unregister(pf->mdio);
}
+
+#define ENETC_MDIO_DEV_ID 0xee01
+#define ENETC_MDIO_DEV_NAME "FSL PCIe IE Central MDIO"
+#define ENETC_MDIO_BUS_NAME ENETC_MDIO_DEV_NAME " Bus"
+#define ENETC_MDIO_DRV_NAME ENETC_MDIO_DEV_NAME " driver"
+#define ENETC_MDIO_DRV_ID "fsl_enetc_mdio"
+
+static int enetc_pci_mdio_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ struct enetc_mdio_priv *mdio_priv;
+ struct device *dev = &pdev->dev;
+ struct enetc_hw *hw;
+ struct mii_bus *bus;
+ int err;
+
+ hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL);
+ if (!hw)
+ return -ENOMEM;
+
+ bus = devm_mdiobus_alloc_size(dev, sizeof(*mdio_priv));
+ if (!bus)
+ return -ENOMEM;
+
+ bus->name = ENETC_MDIO_BUS_NAME;
+ bus->read = enetc_mdio_read;
+ bus->write = enetc_mdio_write;
+ bus->parent = dev;
+ mdio_priv = bus->priv;
+ mdio_priv->hw = hw;
+ snprintf(bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev));
+
+ pcie_flr(pdev);
+ err = pci_enable_device_mem(pdev);
+ if (err) {
+ dev_err(dev, "device enable failed\n");
+ return err;
+ }
+
+ err = pci_request_region(pdev, 0, ENETC_MDIO_DRV_ID);
+ if (err) {
+ dev_err(dev, "pci_request_region failed\n");
+ goto err_pci_mem_reg;
+ }
+
+ hw->port = pci_iomap(pdev, 0, 0);
+ if (!bus->priv) {
+ err = -ENXIO;
+ dev_err(dev, "iomap failed\n");
+ goto err_ioremap;
+ }
+
+ err = of_mdiobus_register(bus, dev->of_node);
+ if (err)
+ goto err_mdiobus_reg;
+
+ pci_set_drvdata(pdev, bus);
+
+ return 0;
+
+err_mdiobus_reg:
+ iounmap(mdio_priv->hw->port);
+err_ioremap:
+ pci_release_mem_regions(pdev);
+err_pci_mem_reg:
+ pci_disable_device(pdev);
+
+ return err;
+}
+
+static void enetc_pci_mdio_remove(struct pci_dev *pdev)
+{
+ struct mii_bus *bus = pci_get_drvdata(pdev);
+ struct enetc_mdio_priv *mdio_priv;
+
+ mdiobus_unregister(bus);
+ mdio_priv = bus->priv;
+ iounmap(mdio_priv->hw->port);
+ pci_release_mem_regions(pdev);
+ pci_disable_device(pdev);
+}
+
+static const struct pci_device_id enetc_pci_mdio_id_table[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_MDIO_DEV_ID) },
+ { 0, } /* End of table. */
+};
+MODULE_DEVICE_TABLE(pci, enetc_mdio_id_table);
+
+static struct pci_driver enetc_pci_mdio_driver = {
+ .name = ENETC_MDIO_DRV_ID,
+ .id_table = enetc_pci_mdio_id_table,
+ .probe = enetc_pci_mdio_probe,
+ .remove = enetc_pci_mdio_remove,
+};
+module_pci_driver(enetc_pci_mdio_driver);
+
+MODULE_DESCRIPTION(ENETC_MDIO_DRV_NAME);
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index 258b3cb38a6f..7d6513ff8507 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -750,6 +750,7 @@ static int enetc_of_get_phy(struct enetc_ndev_priv *priv)
{
struct enetc_pf *pf = enetc_si_priv(priv->si);
struct device_node *np = priv->dev->of_node;
+ struct device_node *mdio_np;
int err;
if (!np) {
@@ -773,7 +774,9 @@ static int enetc_of_get_phy(struct enetc_ndev_priv *priv)
priv->phy_node = of_node_get(np);
}
- if (!of_phy_is_fixed_link(np)) {
+ mdio_np = of_get_child_by_name(np, "mdio");
+ if (mdio_np) {
+ of_node_put(mdio_np);
err = enetc_mdio_probe(pf);
if (err) {
of_node_put(priv->phy_node);
--
2.17.1
^ permalink raw reply related
* [PATCH net-next v2 3/4] dt-bindings: net: fsl: enetc: Add bindings for the central MDIO PCIe endpoint
From: Claudiu Manoil @ 2019-07-25 11:19 UTC (permalink / raw)
To: David S . Miller
Cc: andrew, Rob Herring, Li Yang, alexandru.marginean, netdev,
devicetree, linux-arm-kernel, linux-kernel
In-Reply-To: <1564053568-20522-1-git-send-email-claudiu.manoil@nxp.com>
The on-chip PCIe root complex that integrates the ENETC ethernet
controllers also integrates a PCIe enpoint for the MDIO controller
provinding for cetralized control of the ENETC mdio bus.
Add bindings for this "central" MDIO Integrated PCIe Endpoit.
Signed-off-by: Claudiu Manoil <claudiu.manoil@nxp.com>
---
v1 - none
v2 - none
.../devicetree/bindings/net/fsl-enetc.txt | 42 +++++++++++++++++--
1 file changed, 39 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/fsl-enetc.txt b/Documentation/devicetree/bindings/net/fsl-enetc.txt
index 25fc687419db..c090f6df7a39 100644
--- a/Documentation/devicetree/bindings/net/fsl-enetc.txt
+++ b/Documentation/devicetree/bindings/net/fsl-enetc.txt
@@ -11,7 +11,9 @@ Required properties:
to parent node bindings.
- compatible : Should be "fsl,enetc".
-1) The ENETC external port is connected to a MDIO configurable phy:
+1. The ENETC external port is connected to a MDIO configurable phy
+
+1.1. Using the local ENETC Port MDIO interface
In this case, the ENETC node should include a "mdio" sub-node
that in turn should contain the "ethernet-phy" node describing the
@@ -47,8 +49,42 @@ Example:
};
};
-2) The ENETC port is an internal port or has a fixed-link external
-connection:
+1.2. Using the central MDIO PCIe enpoint device
+
+In this case, the mdio node should be defined as another PCIe
+endpoint node, at the same level with the ENETC port nodes.
+
+Required properties:
+
+- reg : Specifies PCIe Device Number and Function
+ Number of the ENETC endpoint device, according
+ to parent node bindings.
+- compatible : Should be "fsl,enetc-mdio".
+
+The remaining required mdio bus properties are standard, their bindings
+already defined in Documentation/devicetree/bindings/net/mdio.txt.
+
+Example:
+
+ ethernet@0,0 {
+ compatible = "fsl,enetc";
+ reg = <0x000000 0 0 0 0>;
+ phy-handle = <&sgmii_phy0>;
+ phy-connection-type = "sgmii";
+ };
+
+ mdio@0,3 {
+ compatible = "fsl,enetc-mdio";
+ reg = <0x000300 0 0 0 0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ sgmii_phy0: ethernet-phy@2 {
+ reg = <0x2>;
+ };
+ };
+
+2. The ENETC port is an internal port or has a fixed-link external
+connection
In this case, the ENETC port node defines a fixed link connection,
as specified by Documentation/devicetree/bindings/net/fixed-link.txt.
--
2.17.1
^ permalink raw reply related
* Re: [PATCH] qlge: Fix build error without CONFIG_ETHERNET
From: Greg KH @ 2019-07-25 11:14 UTC (permalink / raw)
To: David Miller
Cc: yuehaibing, bpoirier, devel, GR-Linux-NIC-Dev, manishc,
linux-kernel, netdev
In-Reply-To: <20190724.141228.454330962921320879.davem@davemloft.net>
On Wed, Jul 24, 2019 at 02:12:28PM -0700, David Miller wrote:
> From: David Miller <davem@davemloft.net>
> Date: Wed, 24 Jul 2019 14:12:02 -0700 (PDT)
>
> > From: YueHaibing <yuehaibing@huawei.com>
> > Date: Wed, 24 Jul 2019 21:01:26 +0800
> >
> >> Now if CONFIG_ETHERNET is not set, QLGE driver
> >> building fails:
> >>
> >> drivers/staging/qlge/qlge_main.o: In function `qlge_remove':
> >> drivers/staging/qlge/qlge_main.c:4831: undefined reference to `unregister_netdev'
> >>
> >> Reported-by: Hulk Robot <hulkci@huawei.com>
> >> Fixes: 955315b0dc8c ("qlge: Move drivers/net/ethernet/qlogic/qlge/ to drivers/staging/qlge/")
> >> Signed-off-by: YueHaibing <yuehaibing@huawei.com>
> >
> > I'll let Greg take this.
>
> Actually, I take that back.
>
> Since the move to staging happened in my tree I will take this ;-)
Thanks. If you want to push that "move" to Linus soon, I can then take
any cleanup patches that show up for this driver, otherwise feel free to
ignore them until 5.4-rc1.
thanks,
greg k-h
^ permalink raw reply
* Re: [PATCH] Build fixes for skb_frag_size conversion
From: Arnd Bergmann @ 2019-07-25 11:08 UTC (permalink / raw)
To: Matthew Wilcox; +Cc: Networking, David Miller
In-Reply-To: <20190724113615.11961-1-willy@infradead.org>
On Wed, Jul 24, 2019 at 1:37 PM Matthew Wilcox <willy@infradead.org> wrote:
>
> From: "Matthew Wilcox (Oracle)" <willy@infradead.org>
>
> I missed a few places. One is in some ifdeffed code which will probably
> never be re-enabled; the others are in drivers which can't currently be
> compiled on x86.
>
> Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
> diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c
> index cc12c78f73f1..46a6fcf1414d 100644
> --- a/drivers/staging/octeon/ethernet-tx.c
> +++ b/drivers/staging/octeon/ethernet-tx.c
> @@ -284,7 +284,7 @@ int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev)
>
> hw_buffer.s.addr =
> XKPHYS_TO_PHYS((u64)skb_frag_address(fs));
> - hw_buffer.s.size = fs->size;
> + hw_buffer.s.size = skb_drag_size(fs);
> CVM_OCT_SKB_CB(skb)[i + 1] = hw_buffer.u64;
> }
> hw_buffer.s.addr = XKPHYS_TO_PHYS((u64)CVM_OCT_SKB_CB(skb));
Kernelci noticed a build failure from a typo here:
https://kernelci.org/build/id/5d3943f859b514103f688918/logs/
Arnd
^ permalink raw reply
* [PATCH] qed: RDMA - Fix the hw_ver returned in device attributes
From: Michal Kalderon @ 2019-07-25 10:59 UTC (permalink / raw)
To: michal.kalderon, ariel.elior, davem; +Cc: netdev
The hw_ver field was initialized to zero. Return the chip revision.
This is relevant for rdma driver.
Signed-off-by: Michal Kalderon <michal.kalderon@marvell.com>
---
drivers/net/ethernet/qlogic/qed/qed_rdma.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/qlogic/qed/qed_rdma.c b/drivers/net/ethernet/qlogic/qed/qed_rdma.c
index f900fde448db..7110cae384ee 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_rdma.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_rdma.c
@@ -442,7 +442,7 @@ static void qed_rdma_init_devinfo(struct qed_hwfn *p_hwfn,
/* Vendor specific information */
dev->vendor_id = cdev->vendor_id;
dev->vendor_part_id = cdev->device_id;
- dev->hw_ver = 0;
+ dev->hw_ver = cdev->chip_rev;
dev->fw_ver = (FW_MAJOR_VERSION << 24) | (FW_MINOR_VERSION << 16) |
(FW_REVISION_VERSION << 8) | (FW_ENGINEERING_VERSION);
--
2.14.5
^ 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