* [PATCH net] net: vrf: Add missing Rx counters
From: David Ahern @ 2017-01-03 17:37 UTC (permalink / raw)
To: netdev; +Cc: David Ahern
The move from rx-handler to L3 receive handler inadvertantly dropped the
rx counters. Restore them.
Fixes: 74b20582ac38 ("net: l3mdev: Add hook in ip and ipv6")
Reported-by: Dinesh Dutt <ddutt@cumulusnetworks.com>
Signed-off-by: David Ahern <dsa@cumulusnetworks.com>
---
drivers/net/vrf.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index 7532646c3b7b..23dfb0eac098 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -967,6 +967,7 @@ static struct sk_buff *vrf_ip6_rcv(struct net_device *vrf_dev,
*/
need_strict = rt6_need_strict(&ipv6_hdr(skb)->daddr);
if (!ipv6_ndisc_frame(skb) && !need_strict) {
+ vrf_rx_stats(vrf_dev, skb->len);
skb->dev = vrf_dev;
skb->skb_iif = vrf_dev->ifindex;
@@ -1011,6 +1012,8 @@ static struct sk_buff *vrf_ip_rcv(struct net_device *vrf_dev,
goto out;
}
+ vrf_rx_stats(vrf_dev, skb->len);
+
skb_push(skb, skb->mac_len);
dev_queue_xmit_nit(skb, vrf_dev);
skb_pull(skb, skb->mac_len);
--
2.1.4
^ permalink raw reply related
* Re: [PATCH 2/6] wl1251: Use request_firmware_prefer_user() for loading NVS calibration data
From: Luis R. Rodriguez @ 2017-01-03 17:59 UTC (permalink / raw)
To: Pavel Machek, Daniel Wagner, Tom Gundersen
Cc: Arend Van Spriel, Pali Rohár, Ming Lei, Luis R. Rodriguez,
Greg Kroah-Hartman, Kalle Valo, David Gnedt, Michal Kazior,
Daniel Wagner, Tony Lindgren, Sebastian Reichel, Ivaylo Dimitrov,
Aaro Koskinen, Takashi Iwai, David Woodhouse, Bjorn Andersson,
Grazvydas Ignotas, linux-kernel, linux-wireless
In-Reply-To: <20161226163559.GB27087@amd>
On Mon, Dec 26, 2016 at 05:35:59PM +0100, Pavel Machek wrote:
>
> Right question is "should we solve it without user-space help"?
>
> Answer is no, too. Way too complex. Yes, it would be nice if hardware
> was designed in such a way that getting calibration data from kernel
> is easy, and if you design hardware, please design it like that. But
> N900 is not designed like that and getting the calibration through
> userspace looks like only reasonable solution.
Arend seems to have a better alternative in mind possible for other
devices which *can* probably pull of doing this easily and nicely,
given the nasty history of the usermode helper crap we should not
in any way discourage such efforts.
Arend -- please look at the firmware cache, it not a hash but a hash
table for an O(1) lookups would be a welcomed change, then it could
be repurposed for what you describe, I think the only difference is
you'd perhaps want a custom driver hook to fetch the calibration data
so the driver does whatever it needs.
> Now... how exactly to do that is other question. (But this is looks
> very reasonable. Maybe I'd add request_firmware_with_flags(, ...int
> flags), but.. that's a tiny detail.). But userspace needs to be
> involved.
No, no, we keep adding yet-another-exported symbol for requesting firmware,
instead of just adding a set of parameters possible and easily extending
functionality. Please review the patches posted on my last set which adds
a flexible API with only 2 calls, sync and async, and lets us customize
our requests using a parameter:
https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linux-next.git/log/?h=20161216-drvdata-v3-try3
This also documents the "usermode helper" properly and explains some of
the issues and limitations you will need to consider if you use it, its
one reason I'd highly encourage to consider an alternative as what Arend
is considering. *Iff* you insist on using the (now using the proper term,
as per the documentation update I am providing) "custom fallback mechanism"
I welcome such a change but I ask we *really* think this through well so
we avoid the stupid issues which have historically made the custom fallback
mechanism more of a nuisance for Linux distributions, users and developers.
To this end -- I ask you check out Daniel Wagner and Tom Gundersen's firmwared
work [0] which I referred you to in December. Although the drvdata API does
not yet use a custom fallback mechanism, after and its merged the goal here
would be to *only* support a clean custom fallback mechanism which aligns
itself *well* with firmwared or solutions like it. Your patch set then could
just become a patch set to add the custom fallback mechaism support to drvdata
API with the new options/prefernce you are looking for to be specified in
the new parameters, not a new exported symbol.
One of the cruxes we should consider addressing before the drvdata API gets a
custom fallback mechanism support added is that the usermode helper lock should
be replaced with a generic solution for the races it was intended to address:
use of the API on suspend/resume and implicitly later avoid a race on init. To
this end we should consider the same race for *other* real kernel "user mode
helpers", I've documented this on a wiki [1] which documents the *real*
kernel usermode helpers users, one of which was the kobject uevent which is
one of the fallback mechanisms.
I should also note that the idea of fallback mechanism using kobject uevents
should really suffice, in review with Johannes Berg at least, he seemed
convinced just letting either the upstream firmwared, a custom firmwared or
a custom userspace solution should be able to just monitor for uevents for
drvdata and do the right thing, this whole "custom fallback mechanism"
in retrospect seems not really needed as far as I can tell.
[0] https://github.com/teg/firmwared
[1] https://kernelnewbies.org/KernelProjects/usermode-helper-enhancements
Luis
^ permalink raw reply
* [net-next PATCH v2 0/6] i40e: Add VF Port representator support for SR-IOV VFs
From: Sridhar Samudrala @ 2017-01-03 18:07 UTC (permalink / raw)
To: alexander.h.duyck, john.r.fastabend, anjali.singhai,
jakub.kicinski, davem, intel-wired-lan, netdev
- Patch 1 introduces devlink interface to get/set the mode of SRIOV switch.
- Patch 2 adds support to create VF port representor(VFPR) netdevs associated
with SR-IOV VFs that can be used to control/configure VFs from PF name space.
- Patch 3 enables syncing link state between VFs and VFPRs.
- Patch 4 adds a new type to metadata_dst to allow passing VF id to lower device.
- Patch 5 adds TX and RX support to VFPR netdevs.
- Patch 6 enables HW and SW VFPR statistics to be exposed via netlink on VFPR
netdevs.
v2:
- handle i40e_alloc_vfpr_netdev() failures.
- minor comment/commit msg updates.
Jakub Kicinski (1):
net: store port/representator id in metadata_dst
Sridhar Samudrala (5):
i40e: Introduce devlink interface.
i40e: Introduce VF Port Representator(VFPR) netdevs.
i40e: Sync link state between VFs and VFPRs
i40e: Add TX and RX support in switchdev mode.
i40e: Add support for exposing VF port statistics via VFPR netdev on
the host.
drivers/net/ethernet/intel/Kconfig | 1 +
drivers/net/ethernet/intel/i40e/i40e.h | 4 +
drivers/net/ethernet/intel/i40e/i40e_main.c | 103 ++++++-
drivers/net/ethernet/intel/i40e/i40e_txrx.c | 132 ++++++++-
drivers/net/ethernet/intel/i40e/i40e_txrx.h | 1 +
drivers/net/ethernet/intel/i40e/i40e_type.h | 3 +
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 324 ++++++++++++++++++++-
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h | 25 ++
include/net/dst_metadata.h | 35 ++-
net/core/dst.c | 15 +-
net/core/filter.c | 1 +
net/ipv4/ip_tunnel_core.c | 6 +-
net/openvswitch/flow_netlink.c | 4 +-
13 files changed, 620 insertions(+), 34 deletions(-)
--
2.5.5
^ permalink raw reply
* [net-next PATCH v2 1/6] i40e: Introduce devlink interface.
From: Sridhar Samudrala @ 2017-01-03 18:07 UTC (permalink / raw)
To: alexander.h.duyck, john.r.fastabend, anjali.singhai,
jakub.kicinski, davem, intel-wired-lan, netdev
In-Reply-To: <1483466874-2962-1-git-send-email-sridhar.samudrala@intel.com>
Add initial devlink support to get/set the mode of SRIOV switch.
This patch sets the default mode as 'legacy' and enables getting the mode
and and setting it to 'legacy'.
The switch mode can be get/set via following 'devlink' commands.
# devlink dev eswitch show pci/0000:05:00.0
pci/0000:05:00.0: mode legacy
# devlink dev eswitch set pci/0000:05:00.0 mode switchdev
devlink answers: Operation not supported
# devlink dev eswitch set pci/0000:05:00.0 mode legacy
# devlink dev eswitch show pci/0000:05:00.0
pci/0000:05:00.0: mode legacy
Signed-off-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
---
drivers/net/ethernet/intel/Kconfig | 1 +
drivers/net/ethernet/intel/i40e/i40e.h | 3 ++
drivers/net/ethernet/intel/i40e/i40e_main.c | 80 ++++++++++++++++++++++++++---
3 files changed, 76 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/intel/Kconfig b/drivers/net/ethernet/intel/Kconfig
index 1349b45..0dbb87e 100644
--- a/drivers/net/ethernet/intel/Kconfig
+++ b/drivers/net/ethernet/intel/Kconfig
@@ -215,6 +215,7 @@ config I40E
tristate "Intel(R) Ethernet Controller XL710 Family support"
imply PTP_1588_CLOCK
depends on PCI
+ depends on MAY_USE_DEVLINK
---help---
This driver supports Intel(R) Ethernet Controller XL710 Family of
devices. For more information on how to identify your adapter, go
diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h
index ba8d309..410f83d 100644
--- a/drivers/net/ethernet/intel/i40e/i40e.h
+++ b/drivers/net/ethernet/intel/i40e/i40e.h
@@ -54,6 +54,8 @@
#include <linux/clocksource.h>
#include <linux/net_tstamp.h>
#include <linux/ptp_clock_kernel.h>
+#include <net/devlink.h>
+
#include "i40e_type.h"
#include "i40e_prototype.h"
#ifdef I40E_FCOE
@@ -448,6 +450,7 @@ struct i40e_pf {
u32 ioremap_len;
u32 fd_inv;
u16 phy_led_val;
+ enum devlink_eswitch_mode eswitch_mode;
};
/**
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index ad4cf63..c01a620 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -10910,6 +10910,57 @@ static void i40e_get_platform_mac_addr(struct pci_dev *pdev, struct i40e_pf *pf)
}
/**
+ * i40e_devlink_eswitch_mode_get
+ *
+ * @devlink: pointer to devlink struct
+ * @mode: sr-iov switch mode pointer
+ *
+ * Returns the switch mode of the associated PF in the @mode pointer.
+ */
+static int i40e_devlink_eswitch_mode_get(struct devlink *devlink, u16 *mode)
+{
+ struct i40e_pf *pf = devlink_priv(devlink);
+
+ *mode = pf->eswitch_mode;
+
+ return 0;
+}
+
+/**
+ * i40e_devlink_eswitch_mode_set
+ *
+ * @devlink: pointer to devlink struct
+ * @mode: sr-iov switch mode
+ *
+ * Set the switch mode of the associated PF.
+ * Returns 0 on success and -EOPNOTSUPP on error.
+ */
+static int i40e_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode)
+{
+ struct i40e_pf *pf = devlink_priv(devlink);
+ int err = 0;
+
+ if (mode == pf->eswitch_mode)
+ goto done;
+
+ switch (mode) {
+ case DEVLINK_ESWITCH_MODE_LEGACY:
+ pf->eswitch_mode = mode;
+ break;
+ default:
+ err = -EOPNOTSUPP;
+ break;
+ }
+done:
+ return err;
+}
+
+static const struct devlink_ops i40e_devlink_ops = {
+ .eswitch_mode_get = i40e_devlink_eswitch_mode_get,
+ .eswitch_mode_set = i40e_devlink_eswitch_mode_set,
+};
+
+/**
* i40e_probe - Device initialization routine
* @pdev: PCI device information struct
* @ent: entry in i40e_pci_tbl
@@ -10926,6 +10977,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
struct i40e_pf *pf;
struct i40e_hw *hw;
static u16 pfs_found;
+ struct devlink *devlink;
u16 wol_nvm_bits;
u16 link_status;
int err;
@@ -10959,20 +11011,28 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
pci_enable_pcie_error_reporting(pdev);
pci_set_master(pdev);
+ devlink = devlink_alloc(&i40e_devlink_ops, sizeof(*pf));
+ if (!devlink) {
+ dev_err(&pdev->dev, "devlink_alloc failed\n");
+ err = -ENOMEM;
+ goto err_devlink_alloc;
+ }
+
/* Now that we have a PCI connection, we need to do the
* low level device setup. This is primarily setting up
* the Admin Queue structures and then querying for the
* device's current profile information.
*/
- pf = kzalloc(sizeof(*pf), GFP_KERNEL);
- if (!pf) {
- err = -ENOMEM;
- goto err_pf_alloc;
- }
+ pf = devlink_priv(devlink);
pf->next_vsi = 0;
pf->pdev = pdev;
set_bit(__I40E_DOWN, &pf->state);
+ pf->eswitch_mode = DEVLINK_ESWITCH_MODE_LEGACY;
+ err = devlink_register(devlink, &pdev->dev);
+ if (err)
+ goto err_devlink_register;
+
hw = &pf->hw;
hw->back = pf;
@@ -11445,8 +11505,10 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
err_pf_reset:
iounmap(hw->hw_addr);
err_ioremap:
- kfree(pf);
-err_pf_alloc:
+ devlink_unregister(devlink);
+err_devlink_register:
+ devlink_free(devlink);
+err_devlink_alloc:
pci_disable_pcie_error_reporting(pdev);
pci_release_mem_regions(pdev);
err_pci_reg:
@@ -11468,6 +11530,7 @@ static void i40e_remove(struct pci_dev *pdev)
{
struct i40e_pf *pf = pci_get_drvdata(pdev);
struct i40e_hw *hw = &pf->hw;
+ struct devlink *devlink = priv_to_devlink(pf);
i40e_status ret_code;
int i;
@@ -11554,7 +11617,8 @@ static void i40e_remove(struct pci_dev *pdev)
kfree(pf->vsi);
iounmap(hw->hw_addr);
- kfree(pf);
+ devlink_unregister(devlink);
+ devlink_free(devlink);
pci_release_mem_regions(pdev);
pci_disable_pcie_error_reporting(pdev);
--
2.5.5
^ permalink raw reply related
* [net-next PATCH v2 2/6] i40e: Introduce VF Port Representator(VFPR) netdevs.
From: Sridhar Samudrala @ 2017-01-03 18:07 UTC (permalink / raw)
To: alexander.h.duyck, john.r.fastabend, anjali.singhai,
jakub.kicinski, davem, intel-wired-lan, netdev
In-Reply-To: <1483466874-2962-1-git-send-email-sridhar.samudrala@intel.com>
VF Port Representator netdevs are created for each VF if the switch mode
is set to 'switchdev'. These netdevs can be used to control and configure
VFs from PFs namespace. They enable exposing VF statistics, configure and
monitor link state, mtu, filters, fdb/vlan entries etc. of VFs.
Broadcast filters are not enabled in switchdev mode.
Sample script to create VF port representors
# rmmod i40e; modprobe i40e
# devlink dev eswitch set pci/0000:05:00.0 mode switchdev
# echo 2 > /sys/class/net/enp5s0f0/device/sriov_numvfs
# ip l show
297: enp5s0f0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop portid 6805ca2e7268 state DOWN mode DEFAULT group default qlen 1000
link/ether 68:05:ca:2e:72:68 brd ff:ff:ff:ff:ff:ff
vf 0 MAC 00:00:00:00:00:00, spoof checking on, link-state auto, trust off
vf 1 MAC 00:00:00:00:00:00, spoof checking on, link-state auto, trust off
299: enp5s0f0-vf0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
300: enp5s0f0-vf1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
Signed-off-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
---
drivers/net/ethernet/intel/i40e/i40e_main.c | 21 ++-
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 154 ++++++++++++++++++++-
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h | 14 ++
3 files changed, 182 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index c01a620..17428f0 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -10938,15 +10938,34 @@ static int i40e_devlink_eswitch_mode_get(struct devlink *devlink, u16 *mode)
static int i40e_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode)
{
struct i40e_pf *pf = devlink_priv(devlink);
- int err = 0;
+ struct i40e_vf *vf;
+ int i, j, err = 0;
if (mode == pf->eswitch_mode)
goto done;
switch (mode) {
case DEVLINK_ESWITCH_MODE_LEGACY:
+ for (i = 0; i < pf->num_alloc_vfs; i++) {
+ vf = &(pf->vf[i]);
+ i40e_free_vfpr_netdev(vf);
+ }
pf->eswitch_mode = mode;
break;
+ case DEVLINK_ESWITCH_MODE_SWITCHDEV:
+ for (i = 0; i < pf->num_alloc_vfs; i++) {
+ vf = &(pf->vf[i]);
+ err = i40e_alloc_vfpr_netdev(vf, i);
+ if (err) {
+ for (j = 0; j < i; j++) {
+ vf = &(pf->vf[j]);
+ i40e_free_vfpr_netdev(vf);
+ }
+ goto done;
+ }
+ }
+ pf->eswitch_mode = mode;
+ break;
default:
err = -EOPNOTSUPP;
break;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
index a6198b7..63da829 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
@@ -697,12 +697,16 @@ static int i40e_alloc_vsi_res(struct i40e_vf *vf, enum i40e_vsi_type type)
"Could not add MAC filter %pM for VF %d\n",
vf->default_lan_addr.addr, vf->vf_id);
}
- eth_broadcast_addr(broadcast);
- f = i40e_add_filter(vsi, broadcast,
- vf->port_vlan_id ? vf->port_vlan_id : -1);
- if (!f)
- dev_info(&pf->pdev->dev,
- "Could not allocate VF broadcast filter\n");
+
+ /* Add VF broadcast filter only in 'legacy' mode */
+ if (vsi->back->eswitch_mode == DEVLINK_ESWITCH_MODE_LEGACY) {
+ eth_broadcast_addr(broadcast);
+ f = i40e_add_filter(vsi, broadcast,
+ vf->port_vlan_id ? vf->port_vlan_id : -1);
+ if (!f)
+ dev_info(&pf->pdev->dev,
+ "Could not allocate VF broadcast filter\n");
+ }
spin_unlock_bh(&vsi->mac_filter_hash_lock);
i40e_write_rx_ctl(&pf->hw, I40E_VFQF_HENA1(0, vf->vf_id),
(u32)hena);
@@ -1020,6 +1024,136 @@ void i40e_reset_vf(struct i40e_vf *vf, bool flr)
}
/**
+ * i40e_vfpr_netdev_open
+ * @dev: network interface device structure
+ *
+ * Called when vfpr netdevice is brought up.
+ **/
+static int i40e_vfpr_netdev_open(struct net_device *dev)
+{
+ return 0;
+}
+
+/**
+ * i40e_vfpr_netdev_stop
+ * @dev: network interface device structure
+ *
+ * Called when vfpr netdevice is brought down.
+ **/
+static int i40e_vfpr_netdev_stop(struct net_device *dev)
+{
+ return 0;
+}
+
+static const struct net_device_ops i40e_vfpr_netdev_ops = {
+ .ndo_open = i40e_vfpr_netdev_open,
+ .ndo_stop = i40e_vfpr_netdev_stop,
+};
+
+/**
+ * i40e_update_vf_broadcast_filter
+ * @vf: pointer to the VF structure
+ * @enable: boolean flag indicating add/delete
+ *
+ * add/delete VFs broadcast filter
+ **/
+void i40e_update_vf_broadcast_filter(struct i40e_vf *vf, bool enable)
+{
+ struct i40e_pf *pf = vf->pf;
+ struct i40e_vsi *vsi = pf->vsi[vf->lan_vsi_idx];
+ u8 broadcast[ETH_ALEN];
+ int err;
+
+ spin_lock_bh(&vsi->mac_filter_hash_lock);
+ eth_broadcast_addr(broadcast);
+ if (enable)
+ i40e_add_filter(vsi, broadcast, vf->port_vlan_id ? vf->port_vlan_id : -1);
+ else
+ i40e_del_filter(vsi, broadcast, vf->port_vlan_id ? vf->port_vlan_id : -1);
+ spin_unlock_bh(&vsi->mac_filter_hash_lock);
+
+ /* update broadcast filter */
+ err = i40e_sync_vsi_filters(vsi);
+ if (err)
+ dev_err(&pf->pdev->dev, "Unable to program bcast filter\n");
+}
+
+/**
+ * i40e_alloc_vfpr_netdev
+ * @vf: pointer to the VF structure
+ * @vf_num: VF number
+ *
+ * Create VF Port representor netdev
+ **/
+int i40e_alloc_vfpr_netdev(struct i40e_vf *vf, u16 vf_num)
+{
+ struct net_device *vfpr_netdev;
+ char netdev_name[IFNAMSIZ];
+ struct i40e_vfpr_netdev_priv *priv;
+ struct i40e_pf *pf = vf->pf;
+ struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi];
+ int err;
+
+ snprintf(netdev_name, IFNAMSIZ, "%s-vf%d", vsi->netdev->name, vf_num);
+ vfpr_netdev = alloc_netdev(sizeof(struct i40e_vfpr_netdev_priv),
+ netdev_name, NET_NAME_UNKNOWN, ether_setup);
+ if (!vfpr_netdev) {
+ dev_err(&pf->pdev->dev, "alloc_netdev failed for vf:%d\n",
+ vf_num);
+ return -ENOMEM;
+ }
+
+ pf->vf[vf_num].vfpr_netdev = vfpr_netdev;
+
+ priv = netdev_priv(vfpr_netdev);
+ priv->vf = &(pf->vf[vf_num]);
+
+ vfpr_netdev->netdev_ops = &i40e_vfpr_netdev_ops;
+
+ netif_carrier_off(vfpr_netdev);
+ netif_tx_disable(vfpr_netdev);
+
+ err = register_netdev(vfpr_netdev);
+ if (err) {
+ dev_err(&pf->pdev->dev, "register_netdev failed for vf: %s\n",
+ vf->vfpr_netdev->name);
+ free_netdev(vfpr_netdev);
+ return err;
+ }
+
+ dev_info(&pf->pdev->dev, "VF Port representor(%s) created for VF %d\n",
+ vf->vfpr_netdev->name, vf_num);
+
+ /* Delete broadcast filter for VF */
+ i40e_update_vf_broadcast_filter(vf, false);
+
+ return 0;
+}
+
+/**
+ * i40e_free_vfpr_netdev
+ * @vf: pointer to the VF structure
+ *
+ * Free VF Port representor netdev
+ **/
+void i40e_free_vfpr_netdev(struct i40e_vf *vf)
+{
+ struct i40e_pf *pf = vf->pf;
+
+ if (!vf->vfpr_netdev)
+ return;
+
+ dev_info(&pf->pdev->dev, "Freeing VF Port representor(%s)\n",
+ vf->vfpr_netdev->name);
+
+ unregister_netdev(vf->vfpr_netdev);
+ free_netdev(vf->vfpr_netdev);
+
+ /* Add broadcast filter to VF */
+ i40e_update_vf_broadcast_filter(vf, true);
+}
+
+/**
* i40e_free_vfs
* @pf: pointer to the PF structure
*
@@ -1060,6 +1194,9 @@ void i40e_free_vfs(struct i40e_pf *pf)
i40e_free_vf_res(&pf->vf[i]);
/* disable qp mappings */
i40e_disable_vf_mappings(&pf->vf[i]);
+
+ if (pf->eswitch_mode == DEVLINK_ESWITCH_MODE_SWITCHDEV)
+ i40e_free_vfpr_netdev(&pf->vf[i]);
}
kfree(pf->vf);
@@ -1127,6 +1264,11 @@ int i40e_alloc_vfs(struct i40e_pf *pf, u16 num_alloc_vfs)
/* VF resources get allocated during reset */
i40e_reset_vf(&vfs[i], false);
+ if (pf->eswitch_mode == DEVLINK_ESWITCH_MODE_SWITCHDEV) {
+ ret = i40e_alloc_vfpr_netdev(&vfs[i], i);
+ if (ret)
+ goto err_alloc;
+ }
}
pf->num_alloc_vfs = num_alloc_vfs;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h
index 4012d06..25ce93c 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h
@@ -72,10 +72,21 @@ enum i40e_vf_capabilities {
I40E_VIRTCHNL_VF_CAP_IWARP,
};
+/* VF Port representator netdev private structure */
+struct i40e_vfpr_netdev_priv {
+ struct i40e_vf *vf;
+};
+
/* VF information structure */
struct i40e_vf {
struct i40e_pf *pf;
+ /* VF Port representator netdev that allows control and configuration
+ * of VFs from the host. Enables returning VF stats, configuring link
+ * state, mtu, fdb/vlans etc.
+ */
+ struct net_device *vfpr_netdev;
+
/* VF id in the PF space */
s16 vf_id;
/* all VF vsis connect to the same parent */
@@ -142,4 +153,7 @@ int i40e_ndo_set_vf_spoofchk(struct net_device *netdev, int vf_id, bool enable);
void i40e_vc_notify_link_state(struct i40e_pf *pf);
void i40e_vc_notify_reset(struct i40e_pf *pf);
+int i40e_alloc_vfpr_netdev(struct i40e_vf *vf, u16 vf_num);
+void i40e_free_vfpr_netdev(struct i40e_vf *vf);
+
#endif /* _I40E_VIRTCHNL_PF_H_ */
--
2.5.5
^ permalink raw reply related
* [net-next PATCH v2 3/6] i40e: Sync link state between VFs and VFPRs
From: Sridhar Samudrala @ 2017-01-03 18:07 UTC (permalink / raw)
To: alexander.h.duyck, john.r.fastabend, anjali.singhai,
jakub.kicinski, davem, intel-wired-lan, netdev
In-Reply-To: <1483466874-2962-1-git-send-email-sridhar.samudrala@intel.com>
This patch enables
- reflecting the link state of VFPR based on VF admin state & link state
of VF based on admin state of VFPR.
- bringing up/down the VFPR sends a notification to update VF link state.
- bringing up/down the VF will cause the link state update of VFPR.
- enable/disable VF link state via ndo_set_vf_link_state will update the
admin state of associated VFPR.
PF: enp5s0f0, VFs: enp5s2,enp5s2f1 VFPRs:enp5s0f0-vf0, enp5s0f0-vf1
# rmmod i40e; modprobe i40e
# devlink dev eswitch set pci/0000:05:00.0 mode switchdev
# echo 2 > /sys/class/net/enp5s0f0/device/sriov_numvfs
# ip link set enp5s2 up
# ip link set enp5s0f0-vf0 up
# ip link set enp5s0f0-vf1 up
/* enp5s2 UP -> enp5s0f0-vf0 CARRIER ON */
# ip link show enp5s0f0-vf0
215: enp5s0f0-vf0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
/* enp5s0f0-vf0 UP -> enp5s2 CARRIER ON */
# ip link show enp5s2
218: enp5s2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
link/ether ea:4d:60:bc:6f:85 brd ff:ff:ff:ff:ff:ff
/* enp5s2f1 DOWN -> enp5s0f0-vf1 NO-CARRIER */
# ip link show enp5s0f0-vf1
216: enp5s0f0-vf1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc fq_codel state DOWN mode DEFAULT group default qlen 1000
link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
# ip link set enp5s0f0-vf0 down
# ip link set enp5s2f1 up
/* enp5s0-vf0 DOWN -> enp5s2 NO_CARRIER */
# ip link show enp5s2
218: enp5s2: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq state DOWN mode DEFAULT group default qlen 1000
link/ether ea:4d:60:bc:6f:85 brd ff:ff:ff:ff:ff:ff
# ip -d link show enp5s0f0
213: enp5s0f0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop portid 6805ca27268 state DOWN mode DEFAULT group default qlen 1000
link/ether 68:05:ca:2e:72:68 brd ff:ff:ff:ff:ff:ff promiscuity 0 addrgenmode eui64
vf 0 MAC 00:00:00:00:00:00, spoof checking on, link-state disable, trust off
vf 1 MAC 00:00:00:00:00:00, spoof checking on, link-state enable, trust off
Signed-off-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
---
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 44 ++++++++++++++++++++++
1 file changed, 44 insertions(+)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
index 63da829..0c8687d 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
@@ -1031,6 +1031,13 @@ void i40e_reset_vf(struct i40e_vf *vf, bool flr)
**/
static int i40e_vfpr_netdev_open(struct net_device *dev)
{
+ struct i40e_vfpr_netdev_priv *priv = netdev_priv(dev);
+ struct i40e_vf *vf = priv->vf;
+
+ vf->link_forced = true;
+ vf->link_up = true;
+ i40e_vc_notify_vf_link_state(vf);
+
return 0;
}
@@ -1042,6 +1049,13 @@ static int i40e_vfpr_netdev_open(struct net_device *dev)
**/
static int i40e_vfpr_netdev_stop(struct net_device *dev)
{
+ struct i40e_vfpr_netdev_priv *priv = netdev_priv(dev);
+ struct i40e_vf *vf = priv->vf;
+
+ vf->link_forced = true;
+ vf->link_up = false;
+ i40e_vc_notify_vf_link_state(vf);
+
return 0;
}
@@ -1127,6 +1141,13 @@ int i40e_alloc_vfpr_netdev(struct i40e_vf *vf, u16 vf_num)
/* Delete broadcast filter for VF */
i40e_update_vf_broadcast_filter(vf, false);
+ /* Reset VF link as we are changing the mode to 'switchdev'. VFPR netdev
+ * needs to be brought up to enable VF link.
+ */
+ vf->link_forced = true;
+ vf->link_up = false;
+ i40e_vc_notify_vf_link_state(vf);
+
return 0;
}
@@ -1151,6 +1172,10 @@ void i40e_free_vfpr_netdev(struct i40e_vf *vf)
/* Add broadcast filter to VF */
i40e_update_vf_broadcast_filter(vf, true);
+
+ /* In legacy mode, VF link is not controlled by VFPR */
+ vf->link_forced = false;
+ i40e_vc_notify_vf_link_state(vf);
}
/**
@@ -1910,6 +1935,10 @@ static int i40e_vc_enable_queues_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
if (i40e_vsi_start_rings(pf->vsi[vf->lan_vsi_idx]))
aq_ret = I40E_ERR_TIMEOUT;
+
+ if ((0 == aq_ret) && vf->vfpr_netdev)
+ netif_carrier_on(vf->vfpr_netdev);
+
error_param:
/* send the response to the VF */
return i40e_vc_send_resp_to_vf(vf, I40E_VIRTCHNL_OP_ENABLE_QUEUES,
@@ -1949,6 +1978,9 @@ static int i40e_vc_disable_queues_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
i40e_vsi_stop_rings(pf->vsi[vf->lan_vsi_idx]);
+ if ((0 == aq_ret) && vf->vfpr_netdev)
+ netif_carrier_off(vf->vfpr_netdev);
+
error_param:
/* send the response to the VF */
return i40e_vc_send_resp_to_vf(vf, I40E_VIRTCHNL_OP_DISABLE_QUEUES,
@@ -3189,6 +3221,7 @@ int i40e_ndo_set_vf_link_state(struct net_device *netdev, int vf_id, int link)
struct i40e_netdev_priv *np = netdev_priv(netdev);
struct i40e_pf *pf = np->vsi->back;
struct i40e_virtchnl_pf_event pfe;
+ struct net_device *vfpr_netdev;
struct i40e_hw *hw = &pf->hw;
struct i40e_vf *vf;
int abs_vf_id;
@@ -3231,6 +3264,17 @@ int i40e_ndo_set_vf_link_state(struct net_device *netdev, int vf_id, int link)
ret = -EINVAL;
goto error_out;
}
+
+ vfpr_netdev = vf->vfpr_netdev;
+ if (vfpr_netdev) {
+ unsigned int flags = vfpr_netdev->flags;
+
+ if (vf->link_up)
+ dev_change_flags(vfpr_netdev, flags | IFF_UP);
+ else
+ dev_change_flags(vfpr_netdev, flags & ~IFF_UP);
+ }
+
/* Notify the VF of its new link state */
i40e_aq_send_msg_to_vf(hw, abs_vf_id, I40E_VIRTCHNL_OP_EVENT,
0, (u8 *)&pfe, sizeof(pfe), NULL);
--
2.5.5
^ permalink raw reply related
* [net-next PATCH v2 5/6] i40e: Add TX and RX support in switchdev mode.
From: Sridhar Samudrala @ 2017-01-03 18:07 UTC (permalink / raw)
To: alexander.h.duyck, john.r.fastabend, anjali.singhai,
jakub.kicinski, davem, intel-wired-lan, netdev
In-Reply-To: <1483466874-2962-1-git-send-email-sridhar.samudrala@intel.com>
In switchdev mode, broadcast filter is not enabled on VFs. The broadcasts and
unknown frames from VFs are received by the PF and passed to corresponding VF
port representator netdev.
A host based switching entity like a linux bridge or OVS redirects these frames
to the right VFs via VFPR netdevs. Any frames sent via VFPR netdevs are sent as
directed transmits to the corresponding VFs. To enable directed transmit, skb
metadata dst is used to pass the VF id and the frame is requeued to call the PFs
transmit routine.
Small script to demonstrate inter VF pings in switchdev mode.
PF: enp5s0f0, VFs: enp5s2,enp5s2f1 VFPRs:enp5s0f0-vf0, enp5s0f0-vf1
# rmmod i40e; modprobe i40e
# devlink dev eswitch set pci/0000:05:00.0 mode switchdev
# echo 2 > /sys/class/net/enp5s0f0/device/sriov_numvfs
# ip link set enp5s0f0 vf 0 mac 00:11:22:33:44:55
# ip link set enp5s0f0 vf 1 mac 00:11:22:33:44:56
# rmmod i40evf; modprobe i40evf
/* Create 2 namespaces and move the VFs to the corresponding ns. */
# ip netns add ns0
# ip link set enp5s2 netns ns0
# ip netns exec ns0 ip addr add 192.168.1.10/24 dev enp5s2
# ip netns exec ns0 ip link set enp5s2 up
# ip netns add ns1
# ip link set enp5s2f1 netns ns1
# ip netns exec ns1 ip addr add 192.168.1.11/24 dev enp5s2f1
# ip netns exec ns1 ip link set enp5s2f1 up
/* bring up pf and vfpr netdevs */
# ip link set enp5s0f0 up
# ip link set enp5s0f0-vf0 up
# ip link set enp5s0f0-vf1 up
/* Create a linux bridge and add vfpr netdevs to it. */
# ip link add vfpr-br type bridge
# ip link set enp5s0f0-vf0 master vfpr-br
# ip link set enp5s0f0-vf1 master vfpr-br
# ip addr add 192.168.1.1/24 dev vfpr-br
# ip link set vfpr-br up
# ip netns exec ns0 ping -c3 192.168.1.11
# ip netns exec ns1 ping -c3 192.168.1.10
Signed-off-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
---
drivers/net/ethernet/intel/i40e/i40e.h | 1 +
drivers/net/ethernet/intel/i40e/i40e_main.c | 4 +
drivers/net/ethernet/intel/i40e/i40e_txrx.c | 92 ++++++++++++++++++++--
drivers/net/ethernet/intel/i40e/i40e_txrx.h | 1 +
drivers/net/ethernet/intel/i40e/i40e_type.h | 3 +
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 19 ++++-
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h | 1 +
7 files changed, 114 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h
index 410f83d..1c88db5 100644
--- a/drivers/net/ethernet/intel/i40e/i40e.h
+++ b/drivers/net/ethernet/intel/i40e/i40e.h
@@ -55,6 +55,7 @@
#include <linux/net_tstamp.h>
#include <linux/ptp_clock_kernel.h>
#include <net/devlink.h>
+#include <net/dst_metadata.h>
#include "i40e_type.h"
#include "i40e_prototype.h"
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 17428f0..27b2fc1 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -10938,6 +10938,7 @@ static int i40e_devlink_eswitch_mode_get(struct devlink *devlink, u16 *mode)
static int i40e_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode)
{
struct i40e_pf *pf = devlink_priv(devlink);
+ struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi];
struct i40e_vf *vf;
int i, j, err = 0;
@@ -10951,6 +10952,8 @@ static int i40e_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode)
i40e_free_vfpr_netdev(vf);
}
pf->eswitch_mode = mode;
+ vsi->netdev->priv_flags |=
+ (IFF_XMIT_DST_RELEASE | IFF_XMIT_DST_RELEASE_PERM);
break;
case DEVLINK_ESWITCH_MODE_SWITCHDEV:
for (i = 0; i < pf->num_alloc_vfs; i++) {
@@ -10965,6 +10968,7 @@ static int i40e_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode)
}
}
pf->eswitch_mode = mode;
+ netif_keep_dst(vsi->netdev);
break;
default:
err = -EOPNOTSUPP;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
index 352cf7c..b46ddaa 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
@@ -1176,16 +1176,37 @@ static bool i40e_alloc_mapped_page(struct i40e_ring *rx_ring,
* @rx_ring: rx ring in play
* @skb: packet to send up
* @vlan_tag: vlan tag for packet
+ * @lpbk: is it a loopback frame?
**/
static void i40e_receive_skb(struct i40e_ring *rx_ring,
- struct sk_buff *skb, u16 vlan_tag)
+ struct sk_buff *skb, u16 vlan_tag, bool lpbk)
{
struct i40e_q_vector *q_vector = rx_ring->q_vector;
+ struct i40e_pf *pf = rx_ring->vsi->back;
+ struct i40e_vf *vf;
+ struct ethhdr *eth;
+ int vf_id;
if ((rx_ring->netdev->features & NETIF_F_HW_VLAN_CTAG_RX) &&
(vlan_tag & VLAN_VID_MASK))
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tag);
+ if ((pf->eswitch_mode == DEVLINK_ESWITCH_MODE_LEGACY) || !lpbk)
+ goto gro_receive;
+
+ /* If a loopback packet is received from a VF in switchdev mode, pass the
+ * frame to the corresponding VFPR netdev based on the source MAC in the frame.
+ */
+ eth = (struct ethhdr *)skb_mac_header(skb);
+ for (vf_id = 0; vf_id < pf->num_alloc_vfs; vf_id++) {
+ vf = &pf->vf[vf_id];
+ if (ether_addr_equal(eth->h_source, vf->default_lan_addr.addr)) {
+ skb->dev = vf->vfpr_netdev;
+ break;
+ }
+ }
+
+gro_receive:
napi_gro_receive(&q_vector->napi, skb);
}
@@ -1394,6 +1415,7 @@ static inline void i40e_rx_hash(struct i40e_ring *ring,
* @rx_desc: pointer to the EOP Rx descriptor
* @skb: pointer to current skb being populated
* @rx_ptype: the packet type decoded by hardware
+ * @lpbk: is it a loopback frame?
*
* This function checks the ring, descriptor, and packet information in
* order to populate the hash, checksum, VLAN, protocol, and
@@ -1402,7 +1424,7 @@ static inline void i40e_rx_hash(struct i40e_ring *ring,
static inline
void i40e_process_skb_fields(struct i40e_ring *rx_ring,
union i40e_rx_desc *rx_desc, struct sk_buff *skb,
- u8 rx_ptype)
+ u8 rx_ptype, bool *lpbk)
{
u64 qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
u32 rx_status = (qword & I40E_RXD_QW1_STATUS_MASK) >>
@@ -1411,6 +1433,9 @@ void i40e_process_skb_fields(struct i40e_ring *rx_ring,
u32 tsyn = (rx_status & I40E_RXD_QW1_STATUS_TSYNINDX_MASK) >>
I40E_RXD_QW1_STATUS_TSYNINDX_SHIFT;
+ *lpbk = !!((rx_status & I40E_RXD_QW1_STATUS_LPBK_MASK) >>
+ I40E_RXD_QW1_STATUS_LPBK_SHIFT);
+
if (unlikely(tsynvalid))
i40e_ptp_rx_hwtstamp(rx_ring->vsi->back, skb, tsyn);
@@ -1736,6 +1761,7 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
while (likely(total_rx_packets < budget)) {
union i40e_rx_desc *rx_desc;
struct sk_buff *skb;
+ bool lpbk;
u16 vlan_tag;
u8 rx_ptype;
u64 qword;
@@ -1794,7 +1820,7 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
I40E_RXD_QW1_PTYPE_SHIFT;
/* populate checksum, VLAN, and protocol */
- i40e_process_skb_fields(rx_ring, rx_desc, skb, rx_ptype);
+ i40e_process_skb_fields(rx_ring, rx_desc, skb, rx_ptype, &lpbk);
#ifdef I40E_FCOE
if (unlikely(
@@ -1808,7 +1834,7 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
vlan_tag = (qword & BIT(I40E_RX_DESC_STATUS_L2TAG1P_SHIFT)) ?
le16_to_cpu(rx_desc->wb.qword0.lo_dword.l2tag1) : 0;
- i40e_receive_skb(rx_ring, skb, vlan_tag);
+ i40e_receive_skb(rx_ring, skb, vlan_tag, lpbk);
/* update budget accounting */
total_rx_packets++;
@@ -2346,6 +2372,27 @@ static int i40e_tso(struct sk_buff *skb, u8 *hdr_len, u64 *cd_type_cmd_tso_mss)
}
/**
+ * i40e_tvsi - set up the target vsi in TX context descriptor
+ * @tx_ring: ptr to the target vsi
+ * @cd_type_cmd_tso_mss: Quad Word 1
+ *
+ * Returns 0
+ **/
+static int i40e_tvsi(struct i40e_vsi *tvsi, u64 *cd_type_cmd_tso_mss)
+{
+ u64 cd_cmd, cd_tvsi;
+
+ cd_cmd = I40E_TX_CTX_DESC_SWTCH_VSI;
+ cd_tvsi = tvsi->id;
+ cd_tvsi = (cd_tvsi << I40E_TXD_CTX_QW1_VSI_SHIFT) &
+ I40E_TXD_CTX_QW1_VSI_MASK;
+ *cd_type_cmd_tso_mss |= (cd_cmd << I40E_TXD_CTX_QW1_CMD_SHIFT) |
+ cd_tvsi;
+
+ return 0;
+}
+
+/**
* i40e_tsyn - set up the tsyn context descriptor
* @tx_ring: ptr to the ring to send
* @skb: ptr to the skb we're sending
@@ -2887,8 +2934,12 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb,
struct i40e_ring *tx_ring)
{
u64 cd_type_cmd_tso_mss = I40E_TX_DESC_DTYPE_CONTEXT;
+ struct metadata_dst *md_dst = skb_metadata_dst(skb);
u32 cd_tunneling = 0, cd_l2tag2 = 0;
struct i40e_tx_buffer *first;
+ struct i40e_vsi *t_vsi = NULL;
+ struct i40e_vf *t_vf;
+ struct i40e_pf *pf;
u32 td_offset = 0;
u32 tx_flags = 0;
__be16 protocol;
@@ -2935,7 +2986,22 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb,
else if (protocol == htons(ETH_P_IPV6))
tx_flags |= I40E_TX_FLAGS_IPV6;
- tso = i40e_tso(skb, &hdr_len, &cd_type_cmd_tso_mss);
+ /* If skb metadata dst points to a VF id, do a directed transmit to
+ * that VSI. TSO is mutually exclusive with this option. So TSO is not
+ * enabled when doing a directed transmit.
+ */
+ if (md_dst && (md_dst->type == METADATA_HW_PORT_MUX)) {
+ pf = tx_ring->vsi->back;
+ if (md_dst->u.port_info.port_id < pf->num_alloc_vfs) {
+ t_vf = &pf->vf[md_dst->u.port_info.port_id];
+ t_vsi = pf->vsi[t_vf->lan_vsi_idx];
+ }
+ }
+
+ if (t_vsi)
+ tso = i40e_tvsi(t_vsi, &cd_type_cmd_tso_mss);
+ else
+ tso = i40e_tso(skb, &hdr_len, &cd_type_cmd_tso_mss);
if (tso < 0)
goto out_drop;
@@ -2998,3 +3064,19 @@ netdev_tx_t i40e_lan_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
return i40e_xmit_frame_ring(skb, tx_ring);
}
+
+netdev_tx_t i40e_vfpr_netdev_start_xmit(struct sk_buff *skb,
+ struct net_device *dev)
+{
+ struct i40e_vfpr_netdev_priv *priv = netdev_priv(dev);
+ struct i40e_vf *vf = priv->vf;
+ struct i40e_pf *pf = vf->pf;
+ struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi];
+
+ skb_dst_drop(skb);
+ dst_hold(&priv->vfpr_dst->dst);
+ skb_dst_set(skb, &priv->vfpr_dst->dst);
+ skb->dev = vsi->netdev;
+
+ return dev_queue_xmit(skb);
+}
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h
index e065321..850723f 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h
@@ -366,6 +366,7 @@ struct i40e_ring_container {
bool i40e_alloc_rx_buffers(struct i40e_ring *rxr, u16 cleaned_count);
netdev_tx_t i40e_lan_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
+netdev_tx_t i40e_vfpr_netdev_start_xmit(struct sk_buff *skb, struct net_device *netdev);
void i40e_clean_tx_ring(struct i40e_ring *tx_ring);
void i40e_clean_rx_ring(struct i40e_ring *rx_ring);
int i40e_setup_tx_descriptors(struct i40e_ring *tx_ring);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h
index edc0abd..c136cc9 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_type.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_type.h
@@ -728,6 +728,9 @@ enum i40e_rx_desc_status_bits {
#define I40E_RXD_QW1_STATUS_TSYNVALID_SHIFT I40E_RX_DESC_STATUS_TSYNVALID_SHIFT
#define I40E_RXD_QW1_STATUS_TSYNVALID_MASK \
BIT_ULL(I40E_RXD_QW1_STATUS_TSYNVALID_SHIFT)
+#define I40E_RXD_QW1_STATUS_LPBK_SHIFT I40E_RX_DESC_STATUS_LPBK_SHIFT
+#define I40E_RXD_QW1_STATUS_LPBK_MASK \
+ BIT_ULL(I40E_RXD_QW1_STATUS_LPBK_SHIFT)
enum i40e_rx_desc_fltstat_values {
I40E_RX_DESC_FLTSTAT_NO_DATA = 0,
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
index 0c8687d..f0860ef 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
@@ -1062,6 +1062,7 @@ static int i40e_vfpr_netdev_stop(struct net_device *dev)
static const struct net_device_ops i40e_vfpr_netdev_ops = {
.ndo_open = i40e_vfpr_netdev_open,
.ndo_stop = i40e_vfpr_netdev_stop,
+ .ndo_start_xmit = i40e_vfpr_netdev_start_xmit,
};
/**
@@ -1121,16 +1122,22 @@ int i40e_alloc_vfpr_netdev(struct i40e_vf *vf, u16 vf_num)
priv = netdev_priv(vfpr_netdev);
priv->vf = &(pf->vf[vf_num]);
+ priv->vfpr_dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX, GFP_KERNEL);
+ priv->vfpr_dst->u.port_info.lower_dev = vsi->netdev;
+ priv->vfpr_dst->u.port_info.port_id = vf->vf_id;
vfpr_netdev->netdev_ops = &i40e_vfpr_netdev_ops;
netif_carrier_off(vfpr_netdev);
netif_tx_disable(vfpr_netdev);
+ eth_hw_addr_inherit(vfpr_netdev, vsi->netdev);
+
err = register_netdev(vfpr_netdev);
if (err) {
dev_err(&pf->pdev->dev, "register_netdev failed for vf: %s\n",
vf->vfpr_netdev->name);
+ dst_release((struct dst_entry *)priv->vfpr_dst);
free_netdev(vfpr_netdev);
return err;
}
@@ -1159,14 +1166,18 @@ int i40e_alloc_vfpr_netdev(struct i40e_vf *vf, u16 vf_num)
**/
void i40e_free_vfpr_netdev(struct i40e_vf *vf)
{
+ struct i40e_vfpr_netdev_priv *priv;
struct i40e_pf *pf = vf->pf;
if (!vf->vfpr_netdev)
return;
+ priv = netdev_priv(vf->vfpr_netdev);
+
dev_info(&pf->pdev->dev, "Freeing VF Port representor(%s)\n",
vf->vfpr_netdev->name);
+ dst_release((struct dst_entry *)priv->vfpr_dst);
unregister_netdev(vf->vfpr_netdev);
free_netdev(vf->vfpr_netdev);
@@ -1936,8 +1947,10 @@ static int i40e_vc_enable_queues_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
if (i40e_vsi_start_rings(pf->vsi[vf->lan_vsi_idx]))
aq_ret = I40E_ERR_TIMEOUT;
- if ((0 == aq_ret) && vf->vfpr_netdev)
+ if ((0 == aq_ret) && vf->vfpr_netdev) {
+ netif_tx_start_all_queues(vf->vfpr_netdev);
netif_carrier_on(vf->vfpr_netdev);
+ }
error_param:
/* send the response to the VF */
@@ -1978,8 +1991,10 @@ static int i40e_vc_disable_queues_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
i40e_vsi_stop_rings(pf->vsi[vf->lan_vsi_idx]);
- if ((0 == aq_ret) && vf->vfpr_netdev)
+ if ((0 == aq_ret) && vf->vfpr_netdev) {
+ netif_tx_stop_all_queues(vf->vfpr_netdev);
netif_carrier_off(vf->vfpr_netdev);
+ }
error_param:
/* send the response to the VF */
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h
index 25ce93c..3dea207 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h
@@ -74,6 +74,7 @@ enum i40e_vf_capabilities {
/* VF Port representator netdev private structure */
struct i40e_vfpr_netdev_priv {
+ struct metadata_dst *vfpr_dst;
struct i40e_vf *vf;
};
--
2.5.5
^ permalink raw reply related
* [net-next PATCH v2 6/6] i40e: Add support for exposing VF port statistics via VFPR netdev on the host.
From: Sridhar Samudrala @ 2017-01-03 18:07 UTC (permalink / raw)
To: alexander.h.duyck, john.r.fastabend, anjali.singhai,
jakub.kicinski, davem, intel-wired-lan, netdev
In-Reply-To: <1483466874-2962-1-git-send-email-sridhar.samudrala@intel.com>
By default stats counted by HW are returned via the original ndo_get_stats64()
api. Stats counted in SW are returned via ndo_get_offload_stats() api.
Small script to demonstrate vfpr stats in switchdev mode.
PF: enp5s0f0, VFs: enp5s2,enp5s2f1 VFPRs:enp5s0f0-vf0, enp5s0f0-vf1
# rmmod i40e; modprobe i40e
# devlink dev eswitch set pci/0000:05:00.0 mode switchdev
# echo 2 > /sys/class/net/enp5s0f0/device/sriov_numvfs
# ip link set enp5s0f0 vf 0 mac 00:11:22:33:44:55
# ip link set enp5s0f0 vf 1 mac 00:11:22:33:44:56
# rmmod i40evf; modprobe i40evf
/* Create 2 namespaces and move the VFs to the corresponding ns */
# ip netns add ns0
# ip link set enp5s2 netns ns0
# ip netns exec ns0 ip addr add 192.168.1.10/24 dev enp5s2
# ip netns exec ns0 ip link set enp5s2 up
# ip netns add ns1
# ip link set enp5s2f1 netns ns1
# ip netns exec ns1 ip addr add 192.168.1.11/24 dev enp5s2f1
# ip netns exec ns1 ip link set enp5s2f1 up
/* bring up pf and vfpr netdevs */
# ip link set enp5s0f0 up
# ip link set enp5s0f0-vf0 up
# ip link set enp5s0f0-vf1 up
/* Create a linux bridge and add vfpr netdevs to it. */
# ip link add vfpr-br type bridge
# ip link set enp5s0f0-vf0 master vfpr-br
# ip link set enp5s0f0-vf1 master vfpr-br
# ip addr add 192.168.1.1/24 dev vfpr-br
# ip link set vfpr-br up
# ip netns exec ns0 ping -c3 192.168.1.11
# ip netns exec ns1 ping -c3 192.168.1.10
# ip netns exec ns0 ip -s l show enp5s2
56: enp5s2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
link/ether 00:11:22:33:44:55 brd ff:ff:ff:ff:ff:ff
RX: bytes packets errors dropped overrun mcast
1468 18 0 0 0 0
TX: bytes packets errors dropped carrier collsns
1398 17 0 0 0 0
# ip -s l show enp5s0f0-vf0
52: enp5s0f0-vf0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel master vfpr-br state UP mode DEFAULT group default qlen 1000
link/ether 68:05:ca:2e:72:68 brd ff:ff:ff:ff:ff:ff
RX: bytes packets errors dropped overrun mcast
1398 17 0 0 0 0
TX: bytes packets errors dropped carrier collsns
1468 18 0 0 0 0
# ip netns exec ns1 ip -s l show enp5s2f1
57: enp5s2f1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
link/ether 00:11:22:33:44:56 brd ff:ff:ff:ff:ff:ff
RX: bytes packets errors dropped overrun mcast
1486 18 0 0 0 0
TX: bytes packets errors dropped carrier collsns
1538 19 0 0 0 0
# ip -s l show enp5s0f0-vf1
53: enp5s0f0-vf1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel master vfpr-br state UP mode DEFAULT group default qlen 1000
link/ether 68:05:ca:2e:72:68 brd ff:ff:ff:ff:ff:ff
RX: bytes packets errors dropped overrun mcast
1538 19 0 0 0 0
TX: bytes packets errors dropped carrier collsns
1486 18 0 0 0 0
Signed-off-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
---
drivers/net/ethernet/intel/i40e/i40e_txrx.c | 44 +++++++-
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 111 +++++++++++++++++++++
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h | 10 ++
3 files changed, 163 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
index b46ddaa..9f04337 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
@@ -1172,6 +1172,32 @@ static bool i40e_alloc_mapped_page(struct i40e_ring *rx_ring,
}
/**
+ * i40e_vfpr_receive_skb
+ * @vf: pointer to VF
+ * @skb: packet to send up
+ *
+ * Update skb dev to vfpr netdev and rx stats.
+ **/
+static void i40e_vfpr_receive_skb(struct i40e_vf *vf, struct sk_buff *skb)
+{
+ struct i40e_vfpr_netdev_priv *priv;
+ struct vfpr_pcpu_stats *vfpr_stats;
+
+ if (!vf->vfpr_netdev)
+ return;
+
+ skb->dev = vf->vfpr_netdev;
+
+ priv = netdev_priv(vf->vfpr_netdev);
+ vfpr_stats = this_cpu_ptr(priv->vfpr_stats);
+
+ u64_stats_update_begin(&vfpr_stats->syncp);
+ vfpr_stats->rx_packets++;
+ vfpr_stats->rx_bytes += skb->len;
+ u64_stats_update_end(&vfpr_stats->syncp);
+}
+
+/**
* i40e_receive_skb - Send a completed packet up the stack
* @rx_ring: rx ring in play
* @skb: packet to send up
@@ -1201,7 +1227,7 @@ static void i40e_receive_skb(struct i40e_ring *rx_ring,
for (vf_id = 0; vf_id < pf->num_alloc_vfs; vf_id++) {
vf = &pf->vf[vf_id];
if (ether_addr_equal(eth->h_source, vf->default_lan_addr.addr)) {
- skb->dev = vf->vfpr_netdev;
+ i40e_vfpr_receive_skb(vf, skb);
break;
}
}
@@ -3072,11 +3098,25 @@ netdev_tx_t i40e_vfpr_netdev_start_xmit(struct sk_buff *skb,
struct i40e_vf *vf = priv->vf;
struct i40e_pf *pf = vf->pf;
struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi];
+ int ret;
skb_dst_drop(skb);
dst_hold(&priv->vfpr_dst->dst);
skb_dst_set(skb, &priv->vfpr_dst->dst);
skb->dev = vsi->netdev;
- return dev_queue_xmit(skb);
+ ret = dev_queue_xmit(skb);
+
+ if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) {
+ struct vfpr_pcpu_stats *vfpr_stats = this_cpu_ptr(priv->vfpr_stats);
+
+ u64_stats_update_begin(&vfpr_stats->syncp);
+ vfpr_stats->tx_packets++;
+ vfpr_stats->tx_bytes += skb->len;
+ u64_stats_update_end(&vfpr_stats->syncp);
+ } else {
+ this_cpu_inc(priv->vfpr_stats->tx_drops);
+ }
+
+ return ret;
}
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
index f0860ef..7801082 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
@@ -1059,10 +1059,113 @@ static int i40e_vfpr_netdev_stop(struct net_device *dev)
return 0;
}
+/**
+ * i40e_vfpr_netdev_get_stats64
+ * @dev: network interface device structure
+ * @stats: netlink stats structure
+ *
+ * Returns the hw statistics from the VSI corresponding to the associated VFPR
+ **/
+static struct rtnl_link_stats64 *
+i40e_vfpr_netdev_get_stats64(struct net_device *netdev,
+ struct rtnl_link_stats64 *stats)
+{
+ struct i40e_vfpr_netdev_priv *priv = netdev_priv(netdev);
+ struct i40e_vf *vf = priv->vf;
+ struct i40e_pf *pf = vf->pf;
+ struct i40e_vsi *vsi;
+ struct i40e_eth_stats *estats;
+
+ vsi = pf->vsi[vf->lan_vsi_idx];
+ i40e_update_stats(vsi);
+
+ estats = &vsi->eth_stats;
+
+ /* TX and RX stats are flipped as we are returning the stats as seen
+ * at the switch port correspoding to the VF.
+ */
+ stats->rx_packets = estats->tx_unicast + estats->tx_multicast +
+ estats->tx_broadcast;
+ stats->tx_packets = estats->rx_unicast + estats->rx_multicast +
+ estats->rx_broadcast;
+ stats->rx_bytes = estats->tx_bytes;
+ stats->tx_bytes = estats->rx_bytes;
+ stats->rx_dropped = estats->tx_discards;
+ stats->tx_dropped = estats->rx_discards;
+
+ return stats;
+}
+
+
+/**
+ * i40e_vfpr_get_cpu_hit_stats64
+ * @dev: network interface device structure
+ * @stats: netlink stats structure
+ *
+ * stats are filled from the priv structure. correspond to the packets
+ * that are seen by the cpu and sent/received via vfpr netdev.
+ **/
+static int
+i40e_vfpr_get_cpu_hit_stats64(const struct net_device *dev,
+ struct rtnl_link_stats64 *stats)
+{
+ struct i40e_vfpr_netdev_priv *priv = netdev_priv(dev);
+ int i;
+
+ for_each_possible_cpu(i) {
+ struct vfpr_pcpu_stats *vfpr_stats;
+ u64 tbytes, tpkts, tdrops, rbytes, rpkts;
+ unsigned int start;
+
+ vfpr_stats = per_cpu_ptr(priv->vfpr_stats, i);
+ do {
+ start = u64_stats_fetch_begin_irq(&vfpr_stats->syncp);
+ tbytes = vfpr_stats->tx_bytes;
+ tpkts = vfpr_stats->tx_packets;
+ tdrops = vfpr_stats->tx_drops;
+ rbytes = vfpr_stats->rx_bytes;
+ rpkts = vfpr_stats->rx_packets;
+ } while (u64_stats_fetch_retry_irq(&vfpr_stats->syncp, start));
+ stats->tx_bytes += tbytes;
+ stats->tx_packets += tpkts;
+ stats->tx_dropped += tdrops;
+ stats->rx_bytes += rbytes;
+ stats->rx_packets += rpkts;
+ }
+
+ return 0;
+}
+
+static bool
+i40e_vfpr_netdev_has_offload_stats(const struct net_device *dev, int attr_id)
+{
+ switch (attr_id) {
+ case IFLA_OFFLOAD_XSTATS_CPU_HIT:
+ return true;
+ }
+
+ return false;
+}
+
+static int
+i40e_vfpr_netdev_get_offload_stats(int attr_id, const struct net_device *dev,
+ void *sp)
+{
+ switch (attr_id) {
+ case IFLA_OFFLOAD_XSTATS_CPU_HIT:
+ return i40e_vfpr_get_cpu_hit_stats64(dev, sp);
+ }
+
+ return -EINVAL;
+}
+
static const struct net_device_ops i40e_vfpr_netdev_ops = {
.ndo_open = i40e_vfpr_netdev_open,
.ndo_stop = i40e_vfpr_netdev_stop,
.ndo_start_xmit = i40e_vfpr_netdev_start_xmit,
+ .ndo_get_stats64 = i40e_vfpr_netdev_get_stats64,
+ .ndo_has_offload_stats = i40e_vfpr_netdev_has_offload_stats,
+ .ndo_get_offload_stats = i40e_vfpr_netdev_get_offload_stats,
};
/**
@@ -1121,6 +1224,13 @@ int i40e_alloc_vfpr_netdev(struct i40e_vf *vf, u16 vf_num)
pf->vf[vf_num].vfpr_netdev = vfpr_netdev;
priv = netdev_priv(vfpr_netdev);
+ priv->vfpr_stats = netdev_alloc_pcpu_stats(struct vfpr_pcpu_stats);
+ if (!priv->vfpr_stats) {
+ dev_err(&pf->pdev->dev, "alloc_pcpu_stats failed for vf:%d\n",
+ vf_num);
+ free_netdev(vfpr_netdev);
+ return -ENOMEM;
+ }
priv->vf = &(pf->vf[vf_num]);
priv->vfpr_dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX, GFP_KERNEL);
priv->vfpr_dst->u.port_info.lower_dev = vsi->netdev;
@@ -1178,6 +1288,7 @@ void i40e_free_vfpr_netdev(struct i40e_vf *vf)
vf->vfpr_netdev->name);
dst_release((struct dst_entry *)priv->vfpr_dst);
+ free_percpu(priv->vfpr_stats);
unregister_netdev(vf->vfpr_netdev);
free_netdev(vf->vfpr_netdev);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h
index 3dea207..7025c7a 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h
@@ -72,10 +72,20 @@ enum i40e_vf_capabilities {
I40E_VIRTCHNL_VF_CAP_IWARP,
};
+struct vfpr_pcpu_stats {
+ u64 tx_packets;
+ u64 tx_bytes;
+ u64 tx_drops;
+ u64 rx_packets;
+ u64 rx_bytes;
+ struct u64_stats_sync syncp;
+};
+
/* VF Port representator netdev private structure */
struct i40e_vfpr_netdev_priv {
struct metadata_dst *vfpr_dst;
struct i40e_vf *vf;
+ struct vfpr_pcpu_stats *vfpr_stats;
};
/* VF information structure */
--
2.5.5
^ permalink raw reply related
* [PATCH net-next 0/3] net: dsa: restore HWMON support in dsa2
From: Vivien Didelot @ 2017-01-03 18:15 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
Andrew Lunn, cphealy, Vivien Didelot
The current HWMON support in DSA in embedded in the legacy code.
Extract it to its own file and register it in the newer DSA code.
Tested on ZII Rev B boards.
Vivien Didelot (3):
net: dsa: remove out label in dsa_switch_setup_one
net: dsa: move HWMON support to its own file
net: dsa: restore HWMON support in dsa2
net/dsa/Makefile | 1 +
net/dsa/dsa.c | 171 +++++------------------------------------------------
net/dsa/dsa2.c | 4 ++
net/dsa/dsa_priv.h | 9 +++
net/dsa/hwmon.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 178 insertions(+), 156 deletions(-)
create mode 100644 net/dsa/hwmon.c
--
2.11.0
^ permalink raw reply
* [PATCH net-next 1/3] net: dsa: remove out label in dsa_switch_setup_one
From: Vivien Didelot @ 2017-01-03 18:15 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
Andrew Lunn, cphealy, Vivien Didelot
In-Reply-To: <20170103181538.2593-1-vivien.didelot@savoirfairelinux.com>
The "out" label in dsa_switch_setup_one() is useless, thus remove it.
---
net/dsa/dsa.c | 40 +++++++++++++---------------------------
1 file changed, 13 insertions(+), 27 deletions(-)
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 7899919cd9f0..89e66b623d73 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -329,8 +329,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
if (dst->cpu_switch != -1) {
netdev_err(dst->master_netdev,
"multiple cpu ports?!\n");
- ret = -EINVAL;
- goto out;
+ return -EINVAL;
}
dst->cpu_switch = index;
dst->cpu_port = i;
@@ -343,10 +342,8 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
valid_name_found = true;
}
- if (!valid_name_found && i == DSA_MAX_PORTS) {
- ret = -EINVAL;
- goto out;
- }
+ if (!valid_name_found && i == DSA_MAX_PORTS)
+ return -EINVAL;
/* Make the built-in MII bus mask match the number of ports,
* switch drivers can override this later
@@ -363,10 +360,8 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
tag_protocol = ops->get_tag_protocol(ds);
dst->tag_ops = dsa_resolve_tag_protocol(tag_protocol);
- if (IS_ERR(dst->tag_ops)) {
- ret = PTR_ERR(dst->tag_ops);
- goto out;
- }
+ if (IS_ERR(dst->tag_ops))
+ return PTR_ERR(dst->tag_ops);
dst->rcv = dst->tag_ops->rcv;
}
@@ -378,25 +373,23 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
*/
ret = ops->setup(ds);
if (ret < 0)
- goto out;
+ return ret;
if (ops->set_addr) {
ret = ops->set_addr(ds, dst->master_netdev->dev_addr);
if (ret < 0)
- goto out;
+ return ret;
}
if (!ds->slave_mii_bus && ops->phy_read) {
ds->slave_mii_bus = devm_mdiobus_alloc(parent);
- if (!ds->slave_mii_bus) {
- ret = -ENOMEM;
- goto out;
- }
+ if (!ds->slave_mii_bus)
+ return -ENOMEM;
dsa_slave_mii_bus_init(ds);
ret = mdiobus_register(ds->slave_mii_bus);
if (ret < 0)
- goto out;
+ return ret;
}
/*
@@ -409,20 +402,16 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
continue;
ret = dsa_slave_create(ds, parent, i, cd->port_names[i]);
- if (ret < 0) {
+ if (ret < 0)
netdev_err(dst->master_netdev, "[%d]: can't create dsa slave device for port %d(%s): %d\n",
index, i, cd->port_names[i], ret);
- ret = 0;
- }
}
/* Perform configuration of the CPU and DSA ports */
ret = dsa_cpu_dsa_setups(ds, parent);
- if (ret < 0) {
+ if (ret < 0)
netdev_err(dst->master_netdev, "[%d] : can't configure CPU and DSA ports\n",
index);
- ret = 0;
- }
ret = dsa_cpu_port_ethtool_setup(ds);
if (ret)
@@ -453,10 +442,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
}
#endif /* CONFIG_NET_DSA_HWMON */
- return ret;
-
-out:
- return ret;
+ return 0;
}
static struct dsa_switch *
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 3/3] net: dsa: restore HWMON support in dsa2
From: Vivien Didelot @ 2017-01-03 18:15 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
Andrew Lunn, cphealy, Vivien Didelot
In-Reply-To: <20170103181538.2593-1-vivien.didelot@savoirfairelinux.com>
The HWMON support was only registered in the legacy DSA code. Register
it in the newer DSA code (dsa2) as well.
---
net/dsa/dsa2.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index 5fff951a0a49..668aa2974d01 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -348,6 +348,8 @@ static int dsa_ds_apply(struct dsa_switch_tree *dst, struct dsa_switch *ds)
continue;
}
+ dsa_hwmon_register(ds);
+
return 0;
}
@@ -356,6 +358,8 @@ static void dsa_ds_unapply(struct dsa_switch_tree *dst, struct dsa_switch *ds)
struct device_node *port;
u32 index;
+ dsa_hwmon_unregister(ds);
+
for (index = 0; index < DSA_MAX_PORTS; index++) {
port = ds->ports[index].dn;
if (!port)
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 2/3] net: dsa: move HWMON support to its own file
From: Vivien Didelot @ 2017-01-03 18:15 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
Andrew Lunn, cphealy, Vivien Didelot
In-Reply-To: <20170103181538.2593-1-vivien.didelot@savoirfairelinux.com>
The HWMON support in DSA is currently embedded in the legacy DSA code.
Move it out in its own file, so that it can be reused in newer DSA code.
---
net/dsa/Makefile | 1 +
net/dsa/dsa.c | 131 +---------------------------------------------
net/dsa/dsa_priv.h | 9 ++++
net/dsa/hwmon.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 161 insertions(+), 129 deletions(-)
create mode 100644 net/dsa/hwmon.c
diff --git a/net/dsa/Makefile b/net/dsa/Makefile
index a3380ed0e0be..560b6747c276 100644
--- a/net/dsa/Makefile
+++ b/net/dsa/Makefile
@@ -1,6 +1,7 @@
# the core
obj-$(CONFIG_NET_DSA) += dsa_core.o
dsa_core-y += dsa.o slave.o dsa2.o
+dsa_core-$(CONFIG_NET_DSA_HWMON) += hwmon.o
# tagging formats
dsa_core-$(CONFIG_NET_DSA_TAG_BRCM) += tag_brcm.o
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 89e66b623d73..aa73f923e9b5 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -9,9 +9,7 @@
* (at your option) any later version.
*/
-#include <linux/ctype.h>
#include <linux/device.h>
-#include <linux/hwmon.h>
#include <linux/list.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
@@ -110,105 +108,6 @@ dsa_switch_probe(struct device *parent, struct device *host_dev, int sw_addr,
return ret;
}
-/* hwmon support ************************************************************/
-
-#ifdef CONFIG_NET_DSA_HWMON
-
-static ssize_t temp1_input_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct dsa_switch *ds = dev_get_drvdata(dev);
- int temp, ret;
-
- ret = ds->ops->get_temp(ds, &temp);
- if (ret < 0)
- return ret;
-
- return sprintf(buf, "%d\n", temp * 1000);
-}
-static DEVICE_ATTR_RO(temp1_input);
-
-static ssize_t temp1_max_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct dsa_switch *ds = dev_get_drvdata(dev);
- int temp, ret;
-
- ret = ds->ops->get_temp_limit(ds, &temp);
- if (ret < 0)
- return ret;
-
- return sprintf(buf, "%d\n", temp * 1000);
-}
-
-static ssize_t temp1_max_store(struct device *dev,
- struct device_attribute *attr, const char *buf,
- size_t count)
-{
- struct dsa_switch *ds = dev_get_drvdata(dev);
- int temp, ret;
-
- ret = kstrtoint(buf, 0, &temp);
- if (ret < 0)
- return ret;
-
- ret = ds->ops->set_temp_limit(ds, DIV_ROUND_CLOSEST(temp, 1000));
- if (ret < 0)
- return ret;
-
- return count;
-}
-static DEVICE_ATTR_RW(temp1_max);
-
-static ssize_t temp1_max_alarm_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct dsa_switch *ds = dev_get_drvdata(dev);
- bool alarm;
- int ret;
-
- ret = ds->ops->get_temp_alarm(ds, &alarm);
- if (ret < 0)
- return ret;
-
- return sprintf(buf, "%d\n", alarm);
-}
-static DEVICE_ATTR_RO(temp1_max_alarm);
-
-static struct attribute *dsa_hwmon_attrs[] = {
- &dev_attr_temp1_input.attr, /* 0 */
- &dev_attr_temp1_max.attr, /* 1 */
- &dev_attr_temp1_max_alarm.attr, /* 2 */
- NULL
-};
-
-static umode_t dsa_hwmon_attrs_visible(struct kobject *kobj,
- struct attribute *attr, int index)
-{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct dsa_switch *ds = dev_get_drvdata(dev);
- struct dsa_switch_ops *ops = ds->ops;
- umode_t mode = attr->mode;
-
- if (index == 1) {
- if (!ops->get_temp_limit)
- mode = 0;
- else if (!ops->set_temp_limit)
- mode &= ~S_IWUSR;
- } else if (index == 2 && !ops->get_temp_alarm) {
- mode = 0;
- }
- return mode;
-}
-
-static const struct attribute_group dsa_hwmon_group = {
- .attrs = dsa_hwmon_attrs,
- .is_visible = dsa_hwmon_attrs_visible,
-};
-__ATTRIBUTE_GROUPS(dsa_hwmon);
-
-#endif /* CONFIG_NET_DSA_HWMON */
-
/* basic switch operations **************************************************/
int dsa_cpu_dsa_setup(struct dsa_switch *ds, struct device *dev,
struct device_node *port_dn, int port)
@@ -417,30 +316,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
if (ret)
return ret;
-#ifdef CONFIG_NET_DSA_HWMON
- /* If the switch provides a temperature sensor,
- * register with hardware monitoring subsystem.
- * Treat registration error as non-fatal and ignore it.
- */
- if (ops->get_temp) {
- const char *netname = netdev_name(dst->master_netdev);
- char hname[IFNAMSIZ + 1];
- int i, j;
-
- /* Create valid hwmon 'name' attribute */
- for (i = j = 0; i < IFNAMSIZ && netname[i]; i++) {
- if (isalnum(netname[i]))
- hname[j++] = netname[i];
- }
- hname[j] = '\0';
- scnprintf(ds->hwmon_name, sizeof(ds->hwmon_name), "%s_dsa%d",
- hname, index);
- ds->hwmon_dev = hwmon_device_register_with_groups(NULL,
- ds->hwmon_name, ds, dsa_hwmon_groups);
- if (IS_ERR(ds->hwmon_dev))
- ds->hwmon_dev = NULL;
- }
-#endif /* CONFIG_NET_DSA_HWMON */
+ dsa_hwmon_register(ds);
return 0;
}
@@ -500,10 +376,7 @@ static void dsa_switch_destroy(struct dsa_switch *ds)
{
int port;
-#ifdef CONFIG_NET_DSA_HWMON
- if (ds->hwmon_dev)
- hwmon_device_unregister(ds->hwmon_dev);
-#endif
+ dsa_hwmon_unregister(ds);
/* Destroy network devices for physical switch ports. */
for (port = 0; port < DSA_MAX_PORTS; port++) {
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 6cfd7388834e..8cdbc4a7b678 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -57,6 +57,15 @@ const struct dsa_device_ops *dsa_resolve_tag_protocol(int tag_protocol);
int dsa_cpu_port_ethtool_setup(struct dsa_switch *ds);
void dsa_cpu_port_ethtool_restore(struct dsa_switch *ds);
+/* hwmon.c */
+#if CONFIG_NET_DSA_HWMON
+void dsa_hwmon_register(struct dsa_switch *ds);
+void dsa_hwmon_unregister(struct dsa_switch *ds);
+#else
+static inline void dsa_hwmon_register(struct dsa_switch *ds) { }
+static inline void dsa_hwmon_unregister(struct dsa_switch *ds) { }
+#endif
+
/* slave.c */
extern const struct dsa_device_ops notag_netdev_ops;
void dsa_slave_mii_bus_init(struct dsa_switch *ds);
diff --git a/net/dsa/hwmon.c b/net/dsa/hwmon.c
new file mode 100644
index 000000000000..7b3d1a9c2be2
--- /dev/null
+++ b/net/dsa/hwmon.c
@@ -0,0 +1,149 @@
+/*
+ * net/dsa/hwmon.c - HWMON subsystem support
+ * Copyright (c) 2014 Guenter Roeck <linux@roeck-us.net>
+ * Copyright (c) 2017 Vivien Didelot <vivien.didelot@savoirfairelinux.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/ctype.h>
+#include <linux/hwmon.h>
+#include <net/dsa.h>
+
+#include "dsa_priv.h"
+
+static ssize_t temp1_input_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct dsa_switch *ds = dev_get_drvdata(dev);
+ int temp, ret;
+
+ ret = ds->ops->get_temp(ds, &temp);
+ if (ret < 0)
+ return ret;
+
+ return sprintf(buf, "%d\n", temp * 1000);
+}
+static DEVICE_ATTR_RO(temp1_input);
+
+static ssize_t temp1_max_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct dsa_switch *ds = dev_get_drvdata(dev);
+ int temp, ret;
+
+ ret = ds->ops->get_temp_limit(ds, &temp);
+ if (ret < 0)
+ return ret;
+
+ return sprintf(buf, "%d\n", temp * 1000);
+}
+
+static ssize_t temp1_max_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ struct dsa_switch *ds = dev_get_drvdata(dev);
+ int temp, ret;
+
+ ret = kstrtoint(buf, 0, &temp);
+ if (ret < 0)
+ return ret;
+
+ ret = ds->ops->set_temp_limit(ds, DIV_ROUND_CLOSEST(temp, 1000));
+ if (ret < 0)
+ return ret;
+
+ return count;
+}
+static DEVICE_ATTR_RW(temp1_max);
+
+static ssize_t temp1_max_alarm_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct dsa_switch *ds = dev_get_drvdata(dev);
+ bool alarm;
+ int ret;
+
+ ret = ds->ops->get_temp_alarm(ds, &alarm);
+ if (ret < 0)
+ return ret;
+
+ return sprintf(buf, "%d\n", alarm);
+}
+static DEVICE_ATTR_RO(temp1_max_alarm);
+
+static struct attribute *dsa_hwmon_attrs[] = {
+ &dev_attr_temp1_input.attr, /* 0 */
+ &dev_attr_temp1_max.attr, /* 1 */
+ &dev_attr_temp1_max_alarm.attr, /* 2 */
+ NULL
+};
+
+static umode_t dsa_hwmon_attrs_visible(struct kobject *kobj,
+ struct attribute *attr, int index)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct dsa_switch *ds = dev_get_drvdata(dev);
+ struct dsa_switch_ops *ops = ds->ops;
+ umode_t mode = attr->mode;
+
+ if (index == 1) {
+ if (!ops->get_temp_limit)
+ mode = 0;
+ else if (!ops->set_temp_limit)
+ mode &= ~S_IWUSR;
+ } else if (index == 2 && !ops->get_temp_alarm) {
+ mode = 0;
+ }
+ return mode;
+}
+
+static const struct attribute_group dsa_hwmon_group = {
+ .attrs = dsa_hwmon_attrs,
+ .is_visible = dsa_hwmon_attrs_visible,
+};
+__ATTRIBUTE_GROUPS(dsa_hwmon);
+
+void dsa_hwmon_register(struct dsa_switch *ds)
+{
+ const char *netname = netdev_name(ds->dst->master_netdev);
+ char hname[IFNAMSIZ + 1];
+ int i, j;
+
+ /* If the switch provides temperature accessors, register with hardware
+ * monitoring subsystem. Treat registration error as non-fatal.
+ */
+ if (!ds->ops->get_temp)
+ return;
+
+ /* Create valid hwmon 'name' attribute */
+ for (i = j = 0; i < IFNAMSIZ && netname[i]; i++) {
+ if (isalnum(netname[i]))
+ hname[j++] = netname[i];
+ }
+ hname[j] = '\0';
+ scnprintf(ds->hwmon_name, sizeof(ds->hwmon_name), "%s_dsa%d", hname,
+ ds->index);
+ ds->hwmon_dev = hwmon_device_register_with_groups(NULL, ds->hwmon_name,
+ ds, dsa_hwmon_groups);
+ if (IS_ERR(ds->hwmon_dev)) {
+ pr_warn("DSA: failed to register HWMON subsystem for switch %d\n",
+ ds->index);
+ ds->hwmon_dev = NULL;
+ } else {
+ pr_info("DSA: registered HWMON subsystem for switch %d\n",
+ ds->index);
+ }
+}
+
+void dsa_hwmon_unregister(struct dsa_switch *ds)
+{
+ if (ds->hwmon_dev) {
+ hwmon_device_unregister(ds->hwmon_dev);
+ ds->hwmon_dev = NULL;
+ }
+}
--
2.11.0
^ permalink raw reply related
* Re: [PATCH net-next 0/3] net: dsa: restore HWMON support in dsa2
From: Andrew Lunn @ 2017-01-03 18:33 UTC (permalink / raw)
To: Vivien Didelot
Cc: netdev, linux-kernel, kernel, David S. Miller, Florian Fainelli,
cphealy
In-Reply-To: <20170103181538.2593-1-vivien.didelot@savoirfairelinux.com>
On Tue, Jan 03, 2017 at 01:15:35PM -0500, Vivien Didelot wrote:
> The current HWMON support in DSA in embedded in the legacy code.
> Extract it to its own file and register it in the newer DSA code.
Hi Vivien
I would really prefer not to do this.
The temperature sensor is in the embedded PHYs of the switch. Many of
Marvell discrete PHYs also have the same temperature sensor. The
correct thing to do is move this code into drivers/net/phy/marvell.c.
Andrew
^ permalink raw reply
* Re: [PATCH v3 3/3] nfc: trf7970a: Prevent repeated polling from crashing the kernel
From: Geoff Lansberry @ 2017-01-03 18:35 UTC (permalink / raw)
To: Mark Greer
Cc: linux-wireless, Lauro Ramos Venancio, Aloisio Almeida Jr,
Samuel Ortiz, robh+dt, mark.rutland, netdev, devicetree,
linux-kernel, Justin Bronder, Jaret Cantu
In-Reply-To: <20170103163324.GA3184@animalcreek.com>
On Tue, Jan 3, 2017 at 11:33 AM, Mark Greer <mgreer@animalcreek.com> wrote:
> [Please stop top-posting. Bottom-post only to these lists.]
Sorry; gmail keeps baiting me to do it...
>
> Hi Geoff & happy new year.
>
> On Tue, Dec 27, 2016 at 09:18:32AM -0500, Geoff Lansberry wrote:
>> Mark - I will split this off soon.
>
> OK
Thanks for the reminder!
>
>> In the meantime - here is some more info about how we use it.
>>
>> We do use NFC structures. I did find an interesting clue in that
>> there are certain bottles that cause neard to segfault, I'm not sure
>> what is different about them. We write a string, like
>> "coppola_chardonnay_2015" to the bottles.
>
> Off the top of my head, it could be the length of the text.
> It would be useful to compare the data that works to the data
> that doesn't work. Can you install NXP's 'TagInfo' app on a
> smartphone and scan tags with working & non-working data?
> You can email the data from the app to yourself, edit out
> the cruft, and share here.
The data is always the same - and the tags are all the same. Only
difference is that the tag is physically different, and perhaps
orientation; distance from antenna to tag is fixed. I can't even
write the tags at all, so reading them will show blank. Also a minor
but significant detail, is that the tags are embedded in such a way
that the phone cannot get close enough to them to connect.
>
>> Come to think of it, I
>> haven't done anything special to make that an ndef record, just
>> assumed that it would happen by default, I'll look into this further.
>
> If you wrote the data using neard, it will be NDEF formatted.
> Since it is working this well, it is virtually guaranteed that
> the data is NDEF formatted.
OK, good.
>
>> Also, I've been running neard with --plugin nfctype2. Just in case
>> the problem was happening due to cycling through other tag types. It
>> didn't seem to make any difference, but I have not gone back to
>> default.
>
> Good to know, thanks.
>
> Mark
> --
^ permalink raw reply
* Re: [PATCH net-next 1/3] net: dsa: remove out label in dsa_switch_setup_one
From: Andrew Lunn @ 2017-01-03 18:39 UTC (permalink / raw)
To: Vivien Didelot
Cc: netdev, linux-kernel, kernel, David S. Miller, Florian Fainelli,
cphealy
In-Reply-To: <20170103181538.2593-2-vivien.didelot@savoirfairelinux.com>
On Tue, Jan 03, 2017 at 01:15:36PM -0500, Vivien Didelot wrote:
> The "out" label in dsa_switch_setup_one() is useless, thus remove it.
Hi Vivien
Missing a SOB.
This one patch i'm happy with. Assuming we drop the other two, please
could you submit this on its own.
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Andrew
> ---
> net/dsa/dsa.c | 40 +++++++++++++---------------------------
> 1 file changed, 13 insertions(+), 27 deletions(-)
>
> diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
> index 7899919cd9f0..89e66b623d73 100644
> --- a/net/dsa/dsa.c
> +++ b/net/dsa/dsa.c
> @@ -329,8 +329,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
> if (dst->cpu_switch != -1) {
> netdev_err(dst->master_netdev,
> "multiple cpu ports?!\n");
> - ret = -EINVAL;
> - goto out;
> + return -EINVAL;
> }
> dst->cpu_switch = index;
> dst->cpu_port = i;
> @@ -343,10 +342,8 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
> valid_name_found = true;
> }
>
> - if (!valid_name_found && i == DSA_MAX_PORTS) {
> - ret = -EINVAL;
> - goto out;
> - }
> + if (!valid_name_found && i == DSA_MAX_PORTS)
> + return -EINVAL;
>
> /* Make the built-in MII bus mask match the number of ports,
> * switch drivers can override this later
> @@ -363,10 +360,8 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
>
> tag_protocol = ops->get_tag_protocol(ds);
> dst->tag_ops = dsa_resolve_tag_protocol(tag_protocol);
> - if (IS_ERR(dst->tag_ops)) {
> - ret = PTR_ERR(dst->tag_ops);
> - goto out;
> - }
> + if (IS_ERR(dst->tag_ops))
> + return PTR_ERR(dst->tag_ops);
>
> dst->rcv = dst->tag_ops->rcv;
> }
> @@ -378,25 +373,23 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
> */
> ret = ops->setup(ds);
> if (ret < 0)
> - goto out;
> + return ret;
>
> if (ops->set_addr) {
> ret = ops->set_addr(ds, dst->master_netdev->dev_addr);
> if (ret < 0)
> - goto out;
> + return ret;
> }
>
> if (!ds->slave_mii_bus && ops->phy_read) {
> ds->slave_mii_bus = devm_mdiobus_alloc(parent);
> - if (!ds->slave_mii_bus) {
> - ret = -ENOMEM;
> - goto out;
> - }
> + if (!ds->slave_mii_bus)
> + return -ENOMEM;
> dsa_slave_mii_bus_init(ds);
>
> ret = mdiobus_register(ds->slave_mii_bus);
> if (ret < 0)
> - goto out;
> + return ret;
> }
>
> /*
> @@ -409,20 +402,16 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
> continue;
>
> ret = dsa_slave_create(ds, parent, i, cd->port_names[i]);
> - if (ret < 0) {
> + if (ret < 0)
> netdev_err(dst->master_netdev, "[%d]: can't create dsa slave device for port %d(%s): %d\n",
> index, i, cd->port_names[i], ret);
> - ret = 0;
> - }
> }
>
> /* Perform configuration of the CPU and DSA ports */
> ret = dsa_cpu_dsa_setups(ds, parent);
> - if (ret < 0) {
> + if (ret < 0)
> netdev_err(dst->master_netdev, "[%d] : can't configure CPU and DSA ports\n",
> index);
> - ret = 0;
> - }
>
> ret = dsa_cpu_port_ethtool_setup(ds);
> if (ret)
> @@ -453,10 +442,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
> }
> #endif /* CONFIG_NET_DSA_HWMON */
>
> - return ret;
> -
> -out:
> - return ret;
> + return 0;
> }
>
> static struct dsa_switch *
> --
> 2.11.0
>
^ permalink raw reply
* [PATCH] LiquidIO VF: s/select/imply/ for PTP_1588_CLOCK
From: Nicolas Pitre @ 2017-01-03 18:57 UTC (permalink / raw)
To: Richard Cochran, Raghu Vatsavayi, David S. Miller; +Cc: netdev
In-Reply-To: <20170103101105.GA24780@localhost.localdomain>
Fix a minor fallout from the merge of the timers and the networking
trees. The following error may result if the PTP_1588_CLOCK
prerequisites are not available:
drivers/built-in.o: In function `ptp_clock_unregister':
(.text+0x40e0a5): undefined reference to `pps_unregister_source'
drivers/built-in.o: In function `ptp_clock_unregister':
(.text+0x40e0cc): undefined reference to `posix_clock_unregister'
drivers/built-in.o: In function `ptp_clock_event':
(.text+0x40e249): undefined reference to `pps_event'
drivers/built-in.o: In function `ptp_clock_register':
(.text+0x40e5e1): undefined reference to `pps_register_source'
drivers/built-in.o: In function `ptp_clock_register':
(.text+0x40e62c): undefined reference to `posix_clock_register'
drivers/built-in.o: In function `ptp_clock_register':
(.text+0x40e68d): undefined reference to `pps_unregister_source'
Signed-off-by: Nicolas Pitre <nico@linaro.org>
diff --git a/drivers/net/ethernet/cavium/Kconfig b/drivers/net/ethernet/cavium/Kconfig
index bbc8bd16cb..dcbce6cac6 100644
--- a/drivers/net/ethernet/cavium/Kconfig
+++ b/drivers/net/ethernet/cavium/Kconfig
@@ -77,7 +77,7 @@ config OCTEON_MGMT_ETHERNET
config LIQUIDIO_VF
tristate "Cavium LiquidIO VF support"
depends on 64BIT && PCI_MSI
- select PTP_1588_CLOCK
+ imply PTP_1588_CLOCK
---help---
This driver supports Cavium LiquidIO Intelligent Server Adapter
based on CN23XX chips.
^ permalink raw reply related
* Re: [PATCH net-next 1/3] net: dsa: remove out label in dsa_switch_setup_one
From: Vivien Didelot @ 2017-01-03 19:18 UTC (permalink / raw)
To: Andrew Lunn
Cc: netdev, linux-kernel, kernel, David S. Miller, Florian Fainelli,
cphealy
In-Reply-To: <20170103183913.GB30638@lunn.ch>
Hi Andrew,
Andrew Lunn <andrew@lunn.ch> writes:
> On Tue, Jan 03, 2017 at 01:15:36PM -0500, Vivien Didelot wrote:
>> The "out" label in dsa_switch_setup_one() is useless, thus remove it.
>
> Hi Vivien
>
> Missing a SOB.
>
> This one patch i'm happy with. Assuming we drop the other two, please
> could you submit this on its own.
>
> Reviewed-by: Andrew Lunn <andrew@lunn.ch>
You're right, thanks, will do.
Vivien
^ permalink raw reply
* Re: [PATCH] LiquidIO VF: s/select/imply/ for PTP_1588_CLOCK
From: Richard Cochran @ 2017-01-03 19:24 UTC (permalink / raw)
To: Nicolas Pitre; +Cc: Raghu Vatsavayi, David S. Miller, netdev
In-Reply-To: <alpine.LFD.2.20.1701031331450.21662@knanqh.ubzr>
On Tue, Jan 03, 2017 at 01:57:00PM -0500, Nicolas Pitre wrote:
> Fix a minor fallout from the merge of the timers and the networking
> trees. The following error may result if the PTP_1588_CLOCK
> prerequisites are not available:
>
> drivers/built-in.o: In function `ptp_clock_unregister':
> (.text+0x40e0a5): undefined reference to `pps_unregister_source'
> drivers/built-in.o: In function `ptp_clock_unregister':
> (.text+0x40e0cc): undefined reference to `posix_clock_unregister'
> drivers/built-in.o: In function `ptp_clock_event':
> (.text+0x40e249): undefined reference to `pps_event'
> drivers/built-in.o: In function `ptp_clock_register':
> (.text+0x40e5e1): undefined reference to `pps_register_source'
> drivers/built-in.o: In function `ptp_clock_register':
> (.text+0x40e62c): undefined reference to `posix_clock_register'
> drivers/built-in.o: In function `ptp_clock_register':
> (.text+0x40e68d): undefined reference to `pps_unregister_source'
>
> Signed-off-by: Nicolas Pitre <nico@linaro.org>
Thanks for following up on this.
Acked-by: Richard Cochran <richardcochran@gmail.com>
^ permalink raw reply
* Re: [PATCH net-next 0/3] net: dsa: restore HWMON support in dsa2
From: Vivien Didelot @ 2017-01-03 19:24 UTC (permalink / raw)
To: Andrew Lunn
Cc: netdev, linux-kernel, kernel, David S. Miller, Florian Fainelli,
cphealy
In-Reply-To: <20170103183352.GA30638@lunn.ch>
Hi Andrew,
Andrew Lunn <andrew@lunn.ch> writes:
> On Tue, Jan 03, 2017 at 01:15:35PM -0500, Vivien Didelot wrote:
>> The current HWMON support in DSA in embedded in the legacy code.
>> Extract it to its own file and register it in the newer DSA code.
>
> I would really prefer not to do this.
>
> The temperature sensor is in the embedded PHYs of the switch. Many of
> Marvell discrete PHYs also have the same temperature sensor. The
> correct thing to do is move this code into drivers/net/phy/marvell.c.
I agree that the temperature code in the mv88e6xxx driver must be moved
to the Marvell PHY driver.
However I still think this patchset is still valuable because at least
it isolates the HWMON code in DSA which is good, and I think some chips
do have temperature sensors in their cores, not in their PHYs. So the
new DSA code should benefit from the HWMON support instead of
considering this a regression for its users.
Thanks,
Vivien
^ permalink raw reply
* Re: [PATCH] Ipvlan should return an error when an address is already in use.
From: Aaron Conole @ 2017-01-03 19:24 UTC (permalink / raw)
To: David Miller; +Cc: kjlx, maheshb, netdev
In-Reply-To: <20170103.105528.1616978923771083764.davem@davemloft.net>
David Miller <davem@davemloft.net> writes:
> From: Aaron Conole <aconole@redhat.com>
> Date: Tue, 03 Jan 2017 10:50:00 -0500
>
>>> @@ -489,7 +490,12 @@ static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh,
>>> Notifier will trigger FIB update, so that
>>> listeners of netlink will know about new ifaddr */
>>> rtmsg_ifa(RTM_NEWADDR, ifa, nlh, portid);
>>> - blocking_notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa);
>>> + ret = blocking_notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa);
>>
>> Why are you doing this assignment if you aren't using the result?
>>
>>> + ret = notifier_to_errno(ret);
>>> + if (ret) {
>>> + __inet_del_ifa(in_dev, ifap, 1, NULL, portid);
>>> + return ret;
>>> + }
>
> 'ret' assignment is being used, via notifier_to_errno().
d'oh! should have had more coffee - sorry for the noise.
^ permalink raw reply
* [PATCH net-next] liquidio: remove PTP support in 23XX adapters
From: Felix Manlunas @ 2017-01-03 19:27 UTC (permalink / raw)
To: davem; +Cc: netdev, raghu.vatsavayi, derek.chickles, satananda.burla
From: Prasad Kanneganti <prasad.kanneganti@cavium.com>
liquidio driver incorrectly indicates that PTP is supported in 23XX
adapters; this patch fixes that. PTP is supported in 66XX and 68XX
adapters, and the driver correctly indicates that.
Signed-off-by: Prasad Kanneganti <prasad.kanneganti@cavium.com>
Signed-off-by: Felix Manlunas <felix.manlunas@cavium.com>
Signed-off-by: Derek Chickles <derek.chickles@cavium.com>
Signed-off-by: Satanand Burla <satananda.burla@cavium.com>
---
drivers/net/ethernet/cavium/liquidio/lio_main.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c
index 39a9665..6443bc1 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c
@@ -2629,7 +2629,9 @@ static int liquidio_open(struct net_device *netdev)
oct->droq[0]->ops.poll_mode = 1;
}
- oct_ptp_open(netdev);
+ if ((oct->chip_id == OCTEON_CN66XX || oct->chip_id == OCTEON_CN68XX) &&
+ ptp_enable)
+ oct_ptp_open(netdev);
ifstate_set(lio, LIO_IFSTATE_RUNNING);
@@ -2973,9 +2975,13 @@ static int hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr)
*/
static int liquidio_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
{
+ struct lio *lio = GET_LIO(netdev);
+
switch (cmd) {
case SIOCSHWTSTAMP:
- return hwtstamp_ioctl(netdev, ifr);
+ if ((lio->oct_dev->chip_id == OCTEON_CN66XX ||
+ lio->oct_dev->chip_id == OCTEON_CN68XX) && ptp_enable)
+ return hwtstamp_ioctl(netdev, ifr);
default:
return -EOPNOTSUPP;
}
^ permalink raw reply related
* Re: [PATCH net-next 0/3] net: dsa: restore HWMON support in dsa2
From: Florian Fainelli @ 2017-01-03 19:29 UTC (permalink / raw)
To: Vivien Didelot, Andrew Lunn
Cc: netdev, linux-kernel, kernel, David S. Miller, cphealy
In-Reply-To: <87ful0eylp.fsf@weeman.i-did-not-set--mail-host-address--so-tickle-me>
On 01/03/2017 11:24 AM, Vivien Didelot wrote:
> Hi Andrew,
>
> Andrew Lunn <andrew@lunn.ch> writes:
>
>> On Tue, Jan 03, 2017 at 01:15:35PM -0500, Vivien Didelot wrote:
>>> The current HWMON support in DSA in embedded in the legacy code.
>>> Extract it to its own file and register it in the newer DSA code.
>>
>> I would really prefer not to do this.
>>
>> The temperature sensor is in the embedded PHYs of the switch. Many of
>> Marvell discrete PHYs also have the same temperature sensor. The
>> correct thing to do is move this code into drivers/net/phy/marvell.c.
>
> I agree that the temperature code in the mv88e6xxx driver must be moved
> to the Marvell PHY driver.
>
> However I still think this patchset is still valuable because at least
> it isolates the HWMON code in DSA which is good, and I think some chips
> do have temperature sensors in their cores, not in their PHYs. So the
> new DSA code should benefit from the HWMON support instead of
> considering this a regression for its users.
Well, I agree with the regression part, but an argument could
definitively be made that HWMON did not belong in the DSA layer in the
first place, unless we were able to find some commonality between
devices which AFAICT, we could not yet.
I don't have a strong preference, but it seems like the HWMON
functionality should have been part of the switch and/or PHY driver all
along.
--
Florian
^ permalink raw reply
* [PATCH net-next v2] net: dsa: remove out label in dsa_switch_setup_one
From: Vivien Didelot @ 2017-01-03 19:31 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
Andrew Lunn, Vivien Didelot
The "out" label in dsa_switch_setup_one() is useless, thus remove it.
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
net/dsa/dsa.c | 40 +++++++++++++---------------------------
1 file changed, 13 insertions(+), 27 deletions(-)
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 7899919cd9f0..89e66b623d73 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -329,8 +329,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
if (dst->cpu_switch != -1) {
netdev_err(dst->master_netdev,
"multiple cpu ports?!\n");
- ret = -EINVAL;
- goto out;
+ return -EINVAL;
}
dst->cpu_switch = index;
dst->cpu_port = i;
@@ -343,10 +342,8 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
valid_name_found = true;
}
- if (!valid_name_found && i == DSA_MAX_PORTS) {
- ret = -EINVAL;
- goto out;
- }
+ if (!valid_name_found && i == DSA_MAX_PORTS)
+ return -EINVAL;
/* Make the built-in MII bus mask match the number of ports,
* switch drivers can override this later
@@ -363,10 +360,8 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
tag_protocol = ops->get_tag_protocol(ds);
dst->tag_ops = dsa_resolve_tag_protocol(tag_protocol);
- if (IS_ERR(dst->tag_ops)) {
- ret = PTR_ERR(dst->tag_ops);
- goto out;
- }
+ if (IS_ERR(dst->tag_ops))
+ return PTR_ERR(dst->tag_ops);
dst->rcv = dst->tag_ops->rcv;
}
@@ -378,25 +373,23 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
*/
ret = ops->setup(ds);
if (ret < 0)
- goto out;
+ return ret;
if (ops->set_addr) {
ret = ops->set_addr(ds, dst->master_netdev->dev_addr);
if (ret < 0)
- goto out;
+ return ret;
}
if (!ds->slave_mii_bus && ops->phy_read) {
ds->slave_mii_bus = devm_mdiobus_alloc(parent);
- if (!ds->slave_mii_bus) {
- ret = -ENOMEM;
- goto out;
- }
+ if (!ds->slave_mii_bus)
+ return -ENOMEM;
dsa_slave_mii_bus_init(ds);
ret = mdiobus_register(ds->slave_mii_bus);
if (ret < 0)
- goto out;
+ return ret;
}
/*
@@ -409,20 +402,16 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
continue;
ret = dsa_slave_create(ds, parent, i, cd->port_names[i]);
- if (ret < 0) {
+ if (ret < 0)
netdev_err(dst->master_netdev, "[%d]: can't create dsa slave device for port %d(%s): %d\n",
index, i, cd->port_names[i], ret);
- ret = 0;
- }
}
/* Perform configuration of the CPU and DSA ports */
ret = dsa_cpu_dsa_setups(ds, parent);
- if (ret < 0) {
+ if (ret < 0)
netdev_err(dst->master_netdev, "[%d] : can't configure CPU and DSA ports\n",
index);
- ret = 0;
- }
ret = dsa_cpu_port_ethtool_setup(ds);
if (ret)
@@ -453,10 +442,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
}
#endif /* CONFIG_NET_DSA_HWMON */
- return ret;
-
-out:
- return ret;
+ return 0;
}
static struct dsa_switch *
--
2.11.0
^ permalink raw reply related
* Re: [PATCH net-next v2] net: dsa: remove out label in dsa_switch_setup_one
From: Florian Fainelli @ 2017-01-03 19:34 UTC (permalink / raw)
To: Vivien Didelot, netdev; +Cc: linux-kernel, kernel, David S. Miller, Andrew Lunn
In-Reply-To: <20170103193149.4169-1-vivien.didelot@savoirfairelinux.com>
On 01/03/2017 11:31 AM, Vivien Didelot wrote:
> The "out" label in dsa_switch_setup_one() is useless, thus remove it.
>
> Reviewed-by: Andrew Lunn <andrew@lunn.ch>
> Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
--
Florian
^ permalink raw reply
* Re: [PATCH net-next 0/3] net: dsa: restore HWMON support in dsa2
From: Vivien Didelot @ 2017-01-03 19:41 UTC (permalink / raw)
To: Florian Fainelli, Andrew Lunn
Cc: netdev, linux-kernel, kernel, David S. Miller, cphealy
In-Reply-To: <0a504cad-2f2c-fc6a-9965-5ae87be9dac4@gmail.com>
Hi Florian,
Florian Fainelli <f.fainelli@gmail.com> writes:
>>>> The current HWMON support in DSA in embedded in the legacy code.
>>>> Extract it to its own file and register it in the newer DSA code.
>>>
>>> I would really prefer not to do this.
>>>
>>> The temperature sensor is in the embedded PHYs of the switch. Many of
>>> Marvell discrete PHYs also have the same temperature sensor. The
>>> correct thing to do is move this code into drivers/net/phy/marvell.c.
>>
>> I agree that the temperature code in the mv88e6xxx driver must be moved
>> to the Marvell PHY driver.
>>
>> However I still think this patchset is still valuable because at least
>> it isolates the HWMON code in DSA which is good, and I think some chips
>> do have temperature sensors in their cores, not in their PHYs. So the
>> new DSA code should benefit from the HWMON support instead of
>> considering this a regression for its users.
>
> Well, I agree with the regression part, but an argument could
> definitively be made that HWMON did not belong in the DSA layer in the
> first place, unless we were able to find some commonality between
> devices which AFAICT, we could not yet.
>
> I don't have a strong preference, but it seems like the HWMON
> functionality should have been part of the switch and/or PHY driver all
> along.
I see what you mean. Indeed the drivers could register their own HWMON
device until we figure any many chips have an embedded temperature
sensor in their core.
What about sending the patch 2/3 on its own?
Thanks,
Vivien
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox