Commit 9e479d64 authored by Ivan Vecera's avatar Ivan Vecera Committed by David S. Miller

i40e: Add initial devlink support

Add an initial support for devlink interface to i40e driver.

Similarly to ice driver the implementation doe not enable devlink
to manage device-wide configuration and devlink instance is created
for each physical function of PCIe device.
Signed-off-by: default avatarIvan Vecera <ivecera@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b22f21f7
...@@ -225,6 +225,7 @@ config I40E ...@@ -225,6 +225,7 @@ config I40E
depends on PTP_1588_CLOCK_OPTIONAL depends on PTP_1588_CLOCK_OPTIONAL
depends on PCI depends on PCI
select AUXILIARY_BUS select AUXILIARY_BUS
select NET_DEVLINK
help help
This driver supports Intel(R) Ethernet Controller XL710 Family of This driver supports Intel(R) Ethernet Controller XL710 Family of
devices. For more information on how to identify your adapter, go devices. For more information on how to identify your adapter, go
......
...@@ -24,6 +24,7 @@ i40e-objs := i40e_main.o \ ...@@ -24,6 +24,7 @@ i40e-objs := i40e_main.o \
i40e_ddp.o \ i40e_ddp.o \
i40e_client.o \ i40e_client.o \
i40e_virtchnl_pf.o \ i40e_virtchnl_pf.o \
i40e_xsk.o i40e_xsk.o \
i40e_devlink.o
i40e-$(CONFIG_I40E_DCB) += i40e_dcb.o i40e_dcb_nl.o i40e-$(CONFIG_I40E_DCB) += i40e_dcb.o i40e_dcb_nl.o
...@@ -9,10 +9,12 @@ ...@@ -9,10 +9,12 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/avf/virtchnl.h> #include <linux/avf/virtchnl.h>
#include <linux/net/intel/i40e_client.h> #include <linux/net/intel/i40e_client.h>
#include <net/devlink.h>
#include <net/pkt_cls.h> #include <net/pkt_cls.h>
#include <net/udp_tunnel.h> #include <net/udp_tunnel.h>
#include "i40e_dcb.h" #include "i40e_dcb.h"
#include "i40e_debug.h" #include "i40e_debug.h"
#include "i40e_devlink.h"
#include "i40e_io.h" #include "i40e_io.h"
#include "i40e_prototype.h" #include "i40e_prototype.h"
#include "i40e_register.h" #include "i40e_register.h"
...@@ -411,6 +413,7 @@ static inline const u8 *i40e_channel_mac(struct i40e_channel *ch) ...@@ -411,6 +413,7 @@ static inline const u8 *i40e_channel_mac(struct i40e_channel *ch)
/* struct that defines the Ethernet device */ /* struct that defines the Ethernet device */
struct i40e_pf { struct i40e_pf {
struct pci_dev *pdev; struct pci_dev *pdev;
struct devlink_port devlink_port;
struct i40e_hw hw; struct i40e_hw hw;
DECLARE_BITMAP(state, __I40E_STATE_SIZE__); DECLARE_BITMAP(state, __I40E_STATE_SIZE__);
struct msix_entry *msix_entries; struct msix_entry *msix_entries;
......
// SPDX-License-Identifier: GPL-2.0
/* Copyright(c) 2023 Intel Corporation. */
#include <net/devlink.h>
#include "i40e.h"
#include "i40e_devlink.h"
static const struct devlink_ops i40e_devlink_ops = {
};
/**
* i40e_alloc_pf - Allocate devlink and return i40e_pf structure pointer
* @dev: the device to allocate for
*
* Allocate a devlink instance for this device and return the private
* area as the i40e_pf structure.
**/
struct i40e_pf *i40e_alloc_pf(struct device *dev)
{
struct devlink *devlink;
devlink = devlink_alloc(&i40e_devlink_ops, sizeof(struct i40e_pf), dev);
if (!devlink)
return NULL;
return devlink_priv(devlink);
}
/**
* i40e_free_pf - Free i40e_pf structure and associated devlink
* @pf: the PF structure
*
* Free i40e_pf structure and devlink allocated by devlink_alloc.
**/
void i40e_free_pf(struct i40e_pf *pf)
{
struct devlink *devlink = priv_to_devlink(pf);
devlink_free(devlink);
}
/**
* i40e_devlink_register - Register devlink interface for this PF
* @pf: the PF to register the devlink for.
*
* Register the devlink instance associated with this physical function.
**/
void i40e_devlink_register(struct i40e_pf *pf)
{
devlink_register(priv_to_devlink(pf));
}
/**
* i40e_devlink_unregister - Unregister devlink resources for this PF.
* @pf: the PF structure to cleanup
*
* Releases resources used by devlink and cleans up associated memory.
**/
void i40e_devlink_unregister(struct i40e_pf *pf)
{
devlink_unregister(priv_to_devlink(pf));
}
/**
* i40e_devlink_set_switch_id - Set unique switch id based on pci dsn
* @pf: the PF to create a devlink port for
* @ppid: struct with switch id information
*/
static void i40e_devlink_set_switch_id(struct i40e_pf *pf,
struct netdev_phys_item_id *ppid)
{
u64 id = pci_get_dsn(pf->pdev);
ppid->id_len = sizeof(id);
put_unaligned_be64(id, &ppid->id);
}
/**
* i40e_devlink_create_port - Create a devlink port for this PF
* @pf: the PF to create a port for
*
* Create and register a devlink_port for this PF. Note that although each
* physical function is connected to a separate devlink instance, the port
* will still be numbered according to the physical function id.
*
* Return: zero on success or an error code on failure.
**/
int i40e_devlink_create_port(struct i40e_pf *pf)
{
struct devlink *devlink = priv_to_devlink(pf);
struct devlink_port_attrs attrs = {};
struct device *dev = &pf->pdev->dev;
int err;
attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
attrs.phys.port_number = pf->hw.pf_id;
i40e_devlink_set_switch_id(pf, &attrs.switch_id);
devlink_port_attrs_set(&pf->devlink_port, &attrs);
err = devlink_port_register(devlink, &pf->devlink_port, pf->hw.pf_id);
if (err) {
dev_err(dev, "devlink_port_register failed: %d\n", err);
return err;
}
return 0;
}
/**
* i40e_devlink_destroy_port - Destroy the devlink_port for this PF
* @pf: the PF to cleanup
*
* Unregisters the devlink_port structure associated with this PF.
**/
void i40e_devlink_destroy_port(struct i40e_pf *pf)
{
devlink_port_type_clear(&pf->devlink_port);
devlink_port_unregister(&pf->devlink_port);
}
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2023, Intel Corporation. */
#ifndef _I40E_DEVLINK_H_
#define _I40E_DEVLINK_H_
#include <linux/device.h>
struct i40e_pf;
struct i40e_pf *i40e_alloc_pf(struct device *dev);
void i40e_free_pf(struct i40e_pf *pf);
void i40e_devlink_register(struct i40e_pf *pf);
void i40e_devlink_unregister(struct i40e_pf *pf);
int i40e_devlink_create_port(struct i40e_pf *pf);
void i40e_devlink_destroy_port(struct i40e_pf *pf);
#endif /* _I40E_DEVLINK_H_ */
...@@ -14211,6 +14211,8 @@ int i40e_vsi_release(struct i40e_vsi *vsi) ...@@ -14211,6 +14211,8 @@ int i40e_vsi_release(struct i40e_vsi *vsi)
} }
set_bit(__I40E_VSI_RELEASING, vsi->state); set_bit(__I40E_VSI_RELEASING, vsi->state);
uplink_seid = vsi->uplink_seid; uplink_seid = vsi->uplink_seid;
if (vsi->type == I40E_VSI_MAIN)
i40e_devlink_destroy_port(pf);
if (vsi->type != I40E_VSI_SRIOV) { if (vsi->type != I40E_VSI_SRIOV) {
if (vsi->netdev_registered) { if (vsi->netdev_registered) {
vsi->netdev_registered = false; vsi->netdev_registered = false;
...@@ -14398,6 +14400,8 @@ static struct i40e_vsi *i40e_vsi_reinit_setup(struct i40e_vsi *vsi) ...@@ -14398,6 +14400,8 @@ static struct i40e_vsi *i40e_vsi_reinit_setup(struct i40e_vsi *vsi)
err_rings: err_rings:
i40e_vsi_free_q_vectors(vsi); i40e_vsi_free_q_vectors(vsi);
if (vsi->type == I40E_VSI_MAIN)
i40e_devlink_destroy_port(pf);
if (vsi->netdev_registered) { if (vsi->netdev_registered) {
vsi->netdev_registered = false; vsi->netdev_registered = false;
unregister_netdev(vsi->netdev); unregister_netdev(vsi->netdev);
...@@ -14544,9 +14548,15 @@ struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type, ...@@ -14544,9 +14548,15 @@ struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type,
ret = i40e_netif_set_realnum_tx_rx_queues(vsi); ret = i40e_netif_set_realnum_tx_rx_queues(vsi);
if (ret) if (ret)
goto err_netdev; goto err_netdev;
if (vsi->type == I40E_VSI_MAIN) {
ret = i40e_devlink_create_port(pf);
if (ret)
goto err_netdev;
SET_NETDEV_DEVLINK_PORT(vsi->netdev, &pf->devlink_port);
}
ret = register_netdev(vsi->netdev); ret = register_netdev(vsi->netdev);
if (ret) if (ret)
goto err_netdev; goto err_dl_port;
vsi->netdev_registered = true; vsi->netdev_registered = true;
netif_carrier_off(vsi->netdev); netif_carrier_off(vsi->netdev);
#ifdef CONFIG_I40E_DCB #ifdef CONFIG_I40E_DCB
...@@ -14589,6 +14599,9 @@ struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type, ...@@ -14589,6 +14599,9 @@ struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type,
free_netdev(vsi->netdev); free_netdev(vsi->netdev);
vsi->netdev = NULL; vsi->netdev = NULL;
} }
err_dl_port:
if (vsi->type == I40E_VSI_MAIN)
i40e_devlink_destroy_port(pf);
err_netdev: err_netdev:
i40e_aq_delete_element(&pf->hw, vsi->seid, NULL); i40e_aq_delete_element(&pf->hw, vsi->seid, NULL);
err_vsi: err_vsi:
...@@ -15619,7 +15632,7 @@ static int i40e_init_recovery_mode(struct i40e_pf *pf, struct i40e_hw *hw) ...@@ -15619,7 +15632,7 @@ static int i40e_init_recovery_mode(struct i40e_pf *pf, struct i40e_hw *hw)
iounmap(hw->hw_addr); iounmap(hw->hw_addr);
pci_release_mem_regions(pf->pdev); pci_release_mem_regions(pf->pdev);
pci_disable_device(pf->pdev); pci_disable_device(pf->pdev);
kfree(pf); i40e_free_pf(pf);
return err; return err;
} }
...@@ -15696,7 +15709,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -15696,7 +15709,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
* the Admin Queue structures and then querying for the * the Admin Queue structures and then querying for the
* device's current profile information. * device's current profile information.
*/ */
pf = kzalloc(sizeof(*pf), GFP_KERNEL); pf = i40e_alloc_pf(&pdev->dev);
if (!pf) { if (!pf) {
err = -ENOMEM; err = -ENOMEM;
goto err_pf_alloc; goto err_pf_alloc;
...@@ -16223,6 +16236,8 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -16223,6 +16236,8 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* print a string summarizing features */ /* print a string summarizing features */
i40e_print_features(pf); i40e_print_features(pf);
i40e_devlink_register(pf);
return 0; return 0;
/* Unwind what we've done if something failed in the setup */ /* Unwind what we've done if something failed in the setup */
...@@ -16243,7 +16258,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -16243,7 +16258,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
err_pf_reset: err_pf_reset:
iounmap(hw->hw_addr); iounmap(hw->hw_addr);
err_ioremap: err_ioremap:
kfree(pf); i40e_free_pf(pf);
err_pf_alloc: err_pf_alloc:
pci_release_mem_regions(pdev); pci_release_mem_regions(pdev);
err_pci_reg: err_pci_reg:
...@@ -16268,6 +16283,8 @@ static void i40e_remove(struct pci_dev *pdev) ...@@ -16268,6 +16283,8 @@ static void i40e_remove(struct pci_dev *pdev)
int ret_code; int ret_code;
int i; int i;
i40e_devlink_unregister(pf);
i40e_dbg_pf_exit(pf); i40e_dbg_pf_exit(pf);
i40e_ptp_stop(pf); i40e_ptp_stop(pf);
...@@ -16393,7 +16410,7 @@ static void i40e_remove(struct pci_dev *pdev) ...@@ -16393,7 +16410,7 @@ static void i40e_remove(struct pci_dev *pdev)
kfree(pf->vsi); kfree(pf->vsi);
iounmap(hw->hw_addr); iounmap(hw->hw_addr);
kfree(pf); i40e_free_pf(pf);
pci_release_mem_regions(pdev); pci_release_mem_regions(pdev);
pci_disable_device(pdev); pci_disable_device(pdev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment