Commit 2ae0aa47 authored by Wojciech Drewek's avatar Wojciech Drewek Committed by Tony Nguyen
Browse files

ice: Move devlink port to PF/VF struct



Keeping devlink port inside VSI data structure causes some issues.
Since VF VSI is released during reset that means that we have to
unregister devlink port and register it again every time reset is
triggered. With the new changes in devlink API it
might cause deadlock issues. After calling
devlink_port_register/devlink_port_unregister devlink API is going to
lock rtnl_mutex. It's an issue when VF reset is triggered in netlink
operation context (like setting VF MAC address or VLAN),
because rtnl_lock is already taken by netlink. Another call of
rtnl_lock from devlink API results in dead-lock.

By moving devlink port to PF/VF we avoid creating/destroying it
during reset. Since this patch, devlink ports are created during
ice_probe, destroyed during ice_remove for PF and created during
ice_repr_add, destroyed during ice_repr_rem for VF.

Signed-off-by: default avatarWojciech Drewek <wojciech.drewek@intel.com>
Tested-by: default avatarSandeep Penigalapati <sandeep.penigalapati@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent 3ea9bd5d
Loading
Loading
Loading
Loading
+3 −4
Original line number Original line Diff line number Diff line
@@ -311,10 +311,6 @@ 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;


@@ -426,6 +422,9 @@ struct ice_pf {
	struct devlink_region *nvm_region;
	struct devlink_region *nvm_region;
	struct devlink_region *devcaps_region;
	struct devlink_region *devcaps_region;


	/* devlink port data */
	struct devlink_port devlink_port;

	/* OS reserved IRQ details */
	/* OS reserved IRQ details */
	struct msix_entry *msix_entries;
	struct msix_entry *msix_entries;
	struct ice_res_tracker *irq_tracker;
	struct ice_res_tracker *irq_tracker;
+82 −27
Original line number Original line Diff line number Diff line
@@ -487,60 +487,115 @@ void ice_devlink_unregister(struct ice_pf *pf)
}
}


/**
/**
 * ice_devlink_create_port - Create a devlink port for this VSI
 * ice_devlink_create_pf_port - Create a devlink port for this PF
 * @vsi: the VSI to create a port for
 * @pf: the PF to create a devlink port for
 *
 *
 * Create and register a devlink_port for this VSI.
 * Create and register a devlink_port for this PF.
 *
 *
 * 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_vsi *vsi)
int ice_devlink_create_pf_port(struct ice_pf *pf)
{
{
	struct devlink_port_attrs attrs = {};
	struct devlink_port_attrs attrs = {};
	struct ice_port_info *pi;
	struct devlink_port *devlink_port;
	struct devlink *devlink;
	struct devlink *devlink;
	struct ice_vsi *vsi;
	struct device *dev;
	struct device *dev;
	struct ice_pf *pf;
	int err;
	int err;


	/* Currently we only create devlink_port instances for PF VSIs */
	if (vsi->type != ICE_VSI_PF)
		return -EINVAL;

	pf = vsi->back;
	devlink = priv_to_devlink(pf);
	dev = ice_pf_to_dev(pf);
	dev = ice_pf_to_dev(pf);
	pi = pf->hw.port_info;

	devlink_port = &pf->devlink_port;

	vsi = ice_get_main_vsi(pf);
	if (!vsi)
		return -EIO;


	attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
	attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
	attrs.phys.port_number = pi->lport;
	attrs.phys.port_number = pf->hw.bus.func;
	devlink_port_attrs_set(&vsi->devlink_port, &attrs);
	devlink_port_attrs_set(devlink_port, &attrs);
	err = devlink_port_register(devlink, &vsi->devlink_port, vsi->idx);
	devlink = priv_to_devlink(pf);

	err = devlink_port_register(devlink, devlink_port, vsi->idx);
	if (err) {
	if (err) {
		dev_err(dev, "devlink_port_register failed: %d\n", err);
		dev_err(dev, "Failed to create devlink port for PF %d, error %d\n",
			pf->hw.pf_id, err);
		return err;
		return err;
	}
	}


	vsi->devlink_port_registered = true;
	return 0;
}

/**
 * ice_devlink_destroy_pf_port - Destroy the devlink_port for this PF
 * @pf: the PF to cleanup
 *
 * Unregisters the devlink_port structure associated with this PF.
 */
void ice_devlink_destroy_pf_port(struct ice_pf *pf)
{
	struct devlink_port *devlink_port;

	devlink_port = &pf->devlink_port;

	devlink_port_type_clear(devlink_port);
	devlink_port_unregister(devlink_port);
}

/**
 * ice_devlink_create_vf_port - Create a devlink port for this VF
 * @vf: the VF to create a port for
 *
 * Create and register a devlink_port for this VF.
 *
 * Return: zero on success or an error code on failure.
 */
int ice_devlink_create_vf_port(struct ice_vf *vf)
{
	struct devlink_port_attrs attrs = {};
	struct devlink_port *devlink_port;
	struct devlink *devlink;
	struct ice_vsi *vsi;
	struct device *dev;
	struct ice_pf *pf;
	int err;

	pf = vf->pf;
	dev = ice_pf_to_dev(pf);
	vsi = ice_get_vf_vsi(vf);
	devlink_port = &vf->devlink_port;

	attrs.flavour = DEVLINK_PORT_FLAVOUR_PCI_VF;
	attrs.pci_vf.pf = pf->hw.bus.func;
	attrs.pci_vf.vf = vf->vf_id;

	devlink_port_attrs_set(devlink_port, &attrs);
	devlink = priv_to_devlink(pf);

	err = devlink_port_register(devlink, devlink_port, vsi->idx);
	if (err) {
		dev_err(dev, "Failed to create devlink port for VF %d, error %d\n",
			vf->vf_id, err);
		return err;
	}


	return 0;
	return 0;
}
}


/**
/**
 * ice_devlink_destroy_port - Destroy the devlink_port for this VSI
 * ice_devlink_destroy_vf_port - Destroy the devlink_port for this VF
 * @vsi: the VSI to cleanup
 * @vf: the VF to cleanup
 *
 *
 * Unregisters the devlink_port structure associated with this VSI.
 * Unregisters the devlink_port structure associated with this VF.
 */
 */
void ice_devlink_destroy_port(struct ice_vsi *vsi)
void ice_devlink_destroy_vf_port(struct ice_vf *vf)
{
{
	if (!vsi->devlink_port_registered)
	struct devlink_port *devlink_port;
		return;


	devlink_port_type_clear(&vsi->devlink_port);
	devlink_port = &vf->devlink_port;
	devlink_port_unregister(&vsi->devlink_port);


	vsi->devlink_port_registered = false;
	devlink_port_type_clear(devlink_port);
	devlink_port_unregister(devlink_port);
}
}


/**
/**
+4 −2
Original line number Original line Diff line number Diff line
@@ -8,8 +8,10 @@ struct ice_pf *ice_allocate_pf(struct device *dev);


void ice_devlink_register(struct ice_pf *pf);
void 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_vsi *vsi);
int ice_devlink_create_pf_port(struct ice_pf *pf);
void ice_devlink_destroy_port(struct ice_vsi *vsi);
void ice_devlink_destroy_pf_port(struct ice_pf *pf);
int ice_devlink_create_vf_port(struct ice_vf *vf);
void ice_devlink_destroy_vf_port(struct ice_vf *vf);


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);
+2 −1
Original line number Original line Diff line number Diff line
@@ -2859,7 +2859,8 @@ int ice_vsi_release(struct ice_vsi *vsi)
		clear_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state);
		clear_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state);
	}
	}


	ice_devlink_destroy_port(vsi);
	if (vsi->type == ICE_VSI_PF)
		ice_devlink_destroy_pf_port(pf);


	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);
+2 −2
Original line number Original line Diff line number Diff line
@@ -4174,11 +4174,11 @@ static int ice_register_netdev(struct ice_pf *pf)
	set_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state);
	set_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state);
	netif_carrier_off(vsi->netdev);
	netif_carrier_off(vsi->netdev);
	netif_tx_stop_all_queues(vsi->netdev);
	netif_tx_stop_all_queues(vsi->netdev);
	err = ice_devlink_create_port(vsi);
	err = ice_devlink_create_pf_port(pf);
	if (err)
	if (err)
		goto err_devlink_create;
		goto err_devlink_create;


	devlink_port_type_eth_set(&vsi->devlink_port, vsi->netdev);
	devlink_port_type_eth_set(&pf->devlink_port, vsi->netdev);


	return 0;
	return 0;
err_devlink_create:
err_devlink_create:
Loading