mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-29 22:14:41 +08:00
ice: refactor devlink_port to be per-VSI
Currently, the devlink_port structure is stored within the ice_pf. This made sense because we create a single devlink_port for each PF. This setup does not mesh with the abstractions in the driver very well, and led to a flow where we accidentally call devlink_port_unregister twice during error cleanup. In particular, if devlink_port_register or devlink_port_unregister are called twice, this leads to a kernel panic. This appears to occur during some possible flows while cleaning up from a failure during driver probe. If register_netdev fails, then we will call devlink_port_unregister in ice_cfg_netdev as it cleans up. Later, we again call devlink_port_unregister since we assume that we must cleanup the port that is associated with the PF structure. This occurs because we cleanup the devlink_port for the main PF even though it was not allocated. We allocated the port within a per-VSI function for managing the main netdev, but did not release the port when cleaning up that VSI, the allocation and destruction are not aligned. Instead of attempting to manage the devlink_port as part of the PF structure, manage it as part of the PF VSI. Doing this has advantages, as we can match the de-allocation of the devlink_port with the unregister_netdev associated with the main PF VSI. Moving the port to the VSI is preferable as it paves the way for handling devlink ports allocated for other purposes such as SR-IOV VFs. Since we're changing up how we allocate the devlink_port, also change the indexing. Originally, we indexed the port using the PF id number. This came from an old goal of sharing a devlink for each physical function. Managing devlink instances across multiple function drivers is not workable. Instead, lets set the port number to the logical port number returned by firmware and set the index using the VSI index (sometimes referred to as VSI handle). Signed-off-by: Jacob Keller <jacob.e.keller@intel.com> Tested-by: Aaron Brown <aaron.f.brown@intel.com> Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
410d06879c
commit
48d40025b5
@ -284,6 +284,10 @@ struct ice_vsi {
|
|||||||
spinlock_t arfs_lock; /* protects aRFS hash table and filter state */
|
spinlock_t arfs_lock; /* protects aRFS hash table and filter state */
|
||||||
atomic_t *arfs_last_fltr_id;
|
atomic_t *arfs_last_fltr_id;
|
||||||
|
|
||||||
|
/* devlink port data */
|
||||||
|
struct devlink_port devlink_port;
|
||||||
|
bool devlink_port_registered;
|
||||||
|
|
||||||
u16 max_frame;
|
u16 max_frame;
|
||||||
u16 rx_buf_len;
|
u16 rx_buf_len;
|
||||||
|
|
||||||
@ -375,9 +379,6 @@ enum ice_pf_flags {
|
|||||||
struct ice_pf {
|
struct ice_pf {
|
||||||
struct pci_dev *pdev;
|
struct pci_dev *pdev;
|
||||||
|
|
||||||
/* devlink port data */
|
|
||||||
struct devlink_port devlink_port;
|
|
||||||
|
|
||||||
struct devlink_region *nvm_region;
|
struct devlink_region *nvm_region;
|
||||||
struct devlink_region *devcaps_region;
|
struct devlink_region *devcaps_region;
|
||||||
|
|
||||||
|
@ -364,50 +364,60 @@ void ice_devlink_unregister(struct ice_pf *pf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ice_devlink_create_port - Create a devlink port for this PF
|
* ice_devlink_create_port - Create a devlink port for this VSI
|
||||||
* @pf: the PF to create a port for
|
* @vsi: the VSI to create a port for
|
||||||
*
|
*
|
||||||
* Create and register a devlink_port for this PF. Note that although each
|
* Create and register a devlink_port for this VSI.
|
||||||
* 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.
|
* Return: zero on success or an error code on failure.
|
||||||
*/
|
*/
|
||||||
int ice_devlink_create_port(struct ice_pf *pf)
|
int ice_devlink_create_port(struct ice_vsi *vsi)
|
||||||
{
|
{
|
||||||
struct devlink *devlink = priv_to_devlink(pf);
|
|
||||||
struct ice_vsi *vsi = ice_get_main_vsi(pf);
|
|
||||||
struct device *dev = ice_pf_to_dev(pf);
|
|
||||||
struct devlink_port_attrs attrs = {};
|
struct devlink_port_attrs attrs = {};
|
||||||
|
struct ice_port_info *pi;
|
||||||
|
struct devlink *devlink;
|
||||||
|
struct device *dev;
|
||||||
|
struct ice_pf *pf;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (!vsi) {
|
/* Currently we only create devlink_port instances for PF VSIs */
|
||||||
dev_err(dev, "%s: unable to find main VSI\n", __func__);
|
if (vsi->type != ICE_VSI_PF)
|
||||||
return -EIO;
|
return -EINVAL;
|
||||||
}
|
|
||||||
|
pf = vsi->back;
|
||||||
|
devlink = priv_to_devlink(pf);
|
||||||
|
dev = ice_pf_to_dev(pf);
|
||||||
|
pi = pf->hw.port_info;
|
||||||
|
|
||||||
attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
|
attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
|
||||||
attrs.phys.port_number = pf->hw.pf_id;
|
attrs.phys.port_number = pi->lport;
|
||||||
devlink_port_attrs_set(&pf->devlink_port, &attrs);
|
devlink_port_attrs_set(&vsi->devlink_port, &attrs);
|
||||||
err = devlink_port_register(devlink, &pf->devlink_port, pf->hw.pf_id);
|
err = devlink_port_register(devlink, &vsi->devlink_port, vsi->idx);
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_err(dev, "devlink_port_register failed: %d\n", err);
|
dev_err(dev, "devlink_port_register failed: %d\n", err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vsi->devlink_port_registered = true;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ice_devlink_destroy_port - Destroy the devlink_port for this PF
|
* ice_devlink_destroy_port - Destroy the devlink_port for this VSI
|
||||||
* @pf: the PF to cleanup
|
* @vsi: the VSI to cleanup
|
||||||
*
|
*
|
||||||
* Unregisters the devlink_port structure associated with this PF.
|
* Unregisters the devlink_port structure associated with this VSI.
|
||||||
*/
|
*/
|
||||||
void ice_devlink_destroy_port(struct ice_pf *pf)
|
void ice_devlink_destroy_port(struct ice_vsi *vsi)
|
||||||
{
|
{
|
||||||
devlink_port_type_clear(&pf->devlink_port);
|
if (!vsi->devlink_port_registered)
|
||||||
devlink_port_unregister(&pf->devlink_port);
|
return;
|
||||||
|
|
||||||
|
devlink_port_type_clear(&vsi->devlink_port);
|
||||||
|
devlink_port_unregister(&vsi->devlink_port);
|
||||||
|
|
||||||
|
vsi->devlink_port_registered = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -8,8 +8,8 @@ struct ice_pf *ice_allocate_pf(struct device *dev);
|
|||||||
|
|
||||||
int ice_devlink_register(struct ice_pf *pf);
|
int ice_devlink_register(struct ice_pf *pf);
|
||||||
void ice_devlink_unregister(struct ice_pf *pf);
|
void ice_devlink_unregister(struct ice_pf *pf);
|
||||||
int ice_devlink_create_port(struct ice_pf *pf);
|
int ice_devlink_create_port(struct ice_vsi *vsi);
|
||||||
void ice_devlink_destroy_port(struct ice_pf *pf);
|
void ice_devlink_destroy_port(struct ice_vsi *vsi);
|
||||||
|
|
||||||
void ice_devlink_init_regions(struct ice_pf *pf);
|
void ice_devlink_init_regions(struct ice_pf *pf);
|
||||||
void ice_devlink_destroy_regions(struct ice_pf *pf);
|
void ice_devlink_destroy_regions(struct ice_pf *pf);
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "ice_lib.h"
|
#include "ice_lib.h"
|
||||||
#include "ice_fltr.h"
|
#include "ice_fltr.h"
|
||||||
#include "ice_dcb_lib.h"
|
#include "ice_dcb_lib.h"
|
||||||
|
#include "ice_devlink.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ice_vsi_type_str - maps VSI type enum to string equivalents
|
* ice_vsi_type_str - maps VSI type enum to string equivalents
|
||||||
@ -2616,8 +2617,10 @@ int ice_vsi_release(struct ice_vsi *vsi)
|
|||||||
* PF that is running the work queue items currently. This is done to
|
* PF that is running the work queue items currently. This is done to
|
||||||
* avoid check_flush_dependency() warning on this wq
|
* avoid check_flush_dependency() warning on this wq
|
||||||
*/
|
*/
|
||||||
if (vsi->netdev && !ice_is_reset_in_progress(pf->state))
|
if (vsi->netdev && !ice_is_reset_in_progress(pf->state)) {
|
||||||
unregister_netdev(vsi->netdev);
|
unregister_netdev(vsi->netdev);
|
||||||
|
ice_devlink_destroy_port(vsi);
|
||||||
|
}
|
||||||
|
|
||||||
if (test_bit(ICE_FLAG_RSS_ENA, pf->flags))
|
if (test_bit(ICE_FLAG_RSS_ENA, pf->flags))
|
||||||
ice_rss_clean(vsi);
|
ice_rss_clean(vsi);
|
||||||
|
@ -2953,7 +2953,7 @@ static int ice_cfg_netdev(struct ice_vsi *vsi)
|
|||||||
u8 mac_addr[ETH_ALEN];
|
u8 mac_addr[ETH_ALEN];
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = ice_devlink_create_port(pf);
|
err = ice_devlink_create_port(vsi);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
@ -2994,7 +2994,7 @@ static int ice_cfg_netdev(struct ice_vsi *vsi)
|
|||||||
if (err)
|
if (err)
|
||||||
goto err_free_netdev;
|
goto err_free_netdev;
|
||||||
|
|
||||||
devlink_port_type_eth_set(&pf->devlink_port, vsi->netdev);
|
devlink_port_type_eth_set(&vsi->devlink_port, vsi->netdev);
|
||||||
|
|
||||||
netif_carrier_off(vsi->netdev);
|
netif_carrier_off(vsi->netdev);
|
||||||
|
|
||||||
@ -3007,7 +3007,7 @@ err_free_netdev:
|
|||||||
free_netdev(vsi->netdev);
|
free_netdev(vsi->netdev);
|
||||||
vsi->netdev = NULL;
|
vsi->netdev = NULL;
|
||||||
err_destroy_devlink_port:
|
err_destroy_devlink_port:
|
||||||
ice_devlink_destroy_port(pf);
|
ice_devlink_destroy_port(vsi);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4242,7 +4242,6 @@ probe_done:
|
|||||||
err_send_version_unroll:
|
err_send_version_unroll:
|
||||||
ice_vsi_release_all(pf);
|
ice_vsi_release_all(pf);
|
||||||
err_alloc_sw_unroll:
|
err_alloc_sw_unroll:
|
||||||
ice_devlink_destroy_port(pf);
|
|
||||||
set_bit(__ICE_SERVICE_DIS, pf->state);
|
set_bit(__ICE_SERVICE_DIS, pf->state);
|
||||||
set_bit(__ICE_DOWN, pf->state);
|
set_bit(__ICE_DOWN, pf->state);
|
||||||
devm_kfree(dev, pf->first_sw);
|
devm_kfree(dev, pf->first_sw);
|
||||||
@ -4357,7 +4356,6 @@ static void ice_remove(struct pci_dev *pdev)
|
|||||||
if (!ice_is_safe_mode(pf))
|
if (!ice_is_safe_mode(pf))
|
||||||
ice_remove_arfs(pf);
|
ice_remove_arfs(pf);
|
||||||
ice_setup_mc_magic_wake(pf);
|
ice_setup_mc_magic_wake(pf);
|
||||||
ice_devlink_destroy_port(pf);
|
|
||||||
ice_vsi_release_all(pf);
|
ice_vsi_release_all(pf);
|
||||||
ice_set_wake(pf);
|
ice_set_wake(pf);
|
||||||
ice_free_irq_msix_misc(pf);
|
ice_free_irq_msix_misc(pf);
|
||||||
|
Loading…
Reference in New Issue
Block a user