Commit f61c72be authored by David S. Miller's avatar David S. Miller

Merge branch '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue into main

Tony nguyen says:

====================
Intel Wired LAN Driver Updates 2024-06-28 (MAINTAINERS, ice)

This series contains updates to MAINTAINERS file and ice driver.

Jesse replaces himself with Przemek in the maintainers file.

Karthik Sundaravel adds support for VF get/set MAC address via devlink.

Eric checks for errors from ice_vsi_rebuild() during queue
reconfiguration.

Paul adjusts FW API version check for E830 devices.

Piotr adds differentiation of unload type when shutting down AdminQ.

Przemek changes ice_adapter initialization to occur once per physical
card.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 2e7b4711 0f0023c6
......@@ -11051,8 +11051,8 @@ F: include/drm/xe*
F: include/uapi/drm/xe_drm.h
INTEL ETHERNET DRIVERS
M: Jesse Brandeburg <jesse.brandeburg@intel.com>
M: Tony Nguyen <anthony.l.nguyen@intel.com>
M: Przemek Kitszel <przemyslaw.kitszel@intel.com>
L: intel-wired-lan@lists.osuosl.org (moderated for non-subscribers)
S: Supported
W: https://www.intel.com/content/www/us/en/support.html
......
......@@ -372,6 +372,62 @@ void ice_devlink_destroy_pf_port(struct ice_pf *pf)
devl_port_unregister(&pf->devlink_port);
}
/**
* ice_devlink_port_get_vf_fn_mac - .port_fn_hw_addr_get devlink handler
* @port: devlink port structure
* @hw_addr: MAC address of the port
* @hw_addr_len: length of MAC address
* @extack: extended netdev ack structure
*
* Callback for the devlink .port_fn_hw_addr_get operation
* Return: zero on success or an error code on failure.
*/
static int ice_devlink_port_get_vf_fn_mac(struct devlink_port *port,
u8 *hw_addr, int *hw_addr_len,
struct netlink_ext_ack *extack)
{
struct ice_vf *vf = container_of(port, struct ice_vf, devlink_port);
ether_addr_copy(hw_addr, vf->dev_lan_addr);
*hw_addr_len = ETH_ALEN;
return 0;
}
/**
* ice_devlink_port_set_vf_fn_mac - .port_fn_hw_addr_set devlink handler
* @port: devlink port structure
* @hw_addr: MAC address of the port
* @hw_addr_len: length of MAC address
* @extack: extended netdev ack structure
*
* Callback for the devlink .port_fn_hw_addr_set operation
* Return: zero on success or an error code on failure.
*/
static int ice_devlink_port_set_vf_fn_mac(struct devlink_port *port,
const u8 *hw_addr,
int hw_addr_len,
struct netlink_ext_ack *extack)
{
struct devlink_port_attrs *attrs = &port->attrs;
struct devlink_port_pci_vf_attrs *pci_vf;
struct devlink *devlink = port->devlink;
struct ice_pf *pf;
u16 vf_id;
pf = devlink_priv(devlink);
pci_vf = &attrs->pci_vf;
vf_id = pci_vf->vf;
return __ice_set_vf_mac(pf, vf_id, hw_addr);
}
static const struct devlink_port_ops ice_devlink_vf_port_ops = {
.port_fn_hw_addr_get = ice_devlink_port_get_vf_fn_mac,
.port_fn_hw_addr_set = ice_devlink_port_set_vf_fn_mac,
};
/**
* ice_devlink_create_vf_port - Create a devlink port for this VF
* @vf: the VF to create a port for
......@@ -407,7 +463,8 @@ int ice_devlink_create_vf_port(struct ice_vf *vf)
devlink_port_attrs_set(devlink_port, &attrs);
devlink = priv_to_devlink(pf);
err = devl_port_register(devlink, devlink_port, vsi->idx);
err = devl_port_register_with_ops(devlink, devlink_port, vsi->idx,
&ice_devlink_vf_port_ops);
if (err) {
dev_err(dev, "Failed to create devlink port for VF %d, error %d\n",
vf->vf_id, err);
......
......@@ -11,6 +11,7 @@
#include "ice_adapter.h"
static DEFINE_XARRAY(ice_adapters);
static DEFINE_MUTEX(ice_adapters_mutex);
/* PCI bus number is 8 bits. Slot is 5 bits. Domain can have the rest. */
#define INDEX_FIELD_DOMAIN GENMASK(BITS_PER_LONG - 1, 13)
......@@ -47,8 +48,6 @@ static void ice_adapter_free(struct ice_adapter *adapter)
kfree(adapter);
}
DEFINE_FREE(ice_adapter_free, struct ice_adapter*, if (_T) ice_adapter_free(_T))
/**
* ice_adapter_get - Get a shared ice_adapter structure.
* @pdev: Pointer to the pci_dev whose driver is getting the ice_adapter.
......@@ -64,27 +63,26 @@ DEFINE_FREE(ice_adapter_free, struct ice_adapter*, if (_T) ice_adapter_free(_T))
*/
struct ice_adapter *ice_adapter_get(const struct pci_dev *pdev)
{
struct ice_adapter *ret, __free(ice_adapter_free) *adapter = NULL;
unsigned long index = ice_adapter_index(pdev);
adapter = ice_adapter_new();
if (!adapter)
return ERR_PTR(-ENOMEM);
xa_lock(&ice_adapters);
ret = __xa_cmpxchg(&ice_adapters, index, NULL, adapter, GFP_KERNEL);
if (xa_is_err(ret)) {
ret = ERR_PTR(xa_err(ret));
goto unlock;
}
if (ret) {
refcount_inc(&ret->refcount);
goto unlock;
struct ice_adapter *adapter;
int err;
scoped_guard(mutex, &ice_adapters_mutex) {
err = xa_insert(&ice_adapters, index, NULL, GFP_KERNEL);
if (err == -EBUSY) {
adapter = xa_load(&ice_adapters, index);
refcount_inc(&adapter->refcount);
return adapter;
}
if (err)
return ERR_PTR(err);
adapter = ice_adapter_new();
if (!adapter)
return ERR_PTR(-ENOMEM);
xa_store(&ice_adapters, index, adapter, GFP_KERNEL);
}
ret = no_free_ptr(adapter);
unlock:
xa_unlock(&ice_adapters);
return ret;
return adapter;
}
/**
......@@ -94,23 +92,21 @@ struct ice_adapter *ice_adapter_get(const struct pci_dev *pdev)
* Releases the reference to ice_adapter previously obtained with
* ice_adapter_get.
*
* Context: Any.
* Context: Process, may sleep.
*/
void ice_adapter_put(const struct pci_dev *pdev)
{
unsigned long index = ice_adapter_index(pdev);
struct ice_adapter *adapter;
xa_lock(&ice_adapters);
adapter = xa_load(&ice_adapters, index);
if (WARN_ON(!adapter))
goto unlock;
scoped_guard(mutex, &ice_adapters_mutex) {
adapter = xa_load(&ice_adapters, index);
if (WARN_ON(!adapter))
return;
if (!refcount_dec_and_test(&adapter->refcount))
return;
if (!refcount_dec_and_test(&adapter->refcount))
goto unlock;
WARN_ON(__xa_erase(&ice_adapters, index) != adapter);
WARN_ON(xa_erase(&ice_adapters, index) != adapter);
}
ice_adapter_free(adapter);
unlock:
xa_unlock(&ice_adapters);
}
......@@ -23,7 +23,7 @@ int ice_check_reset(struct ice_hw *hw);
int ice_reset(struct ice_hw *hw, enum ice_reset_req req);
int ice_create_all_ctrlq(struct ice_hw *hw);
int ice_init_all_ctrlq(struct ice_hw *hw);
void ice_shutdown_all_ctrlq(struct ice_hw *hw);
void ice_shutdown_all_ctrlq(struct ice_hw *hw, bool unloading);
void ice_destroy_all_ctrlq(struct ice_hw *hw);
int
ice_clean_rq_elem(struct ice_hw *hw, struct ice_ctl_q_info *cq,
......
......@@ -510,16 +510,19 @@ static int ice_shutdown_sq(struct ice_hw *hw, struct ice_ctl_q_info *cq)
*/
static bool ice_aq_ver_check(struct ice_hw *hw)
{
if (hw->api_maj_ver > EXP_FW_API_VER_MAJOR) {
u8 exp_fw_api_ver_major = EXP_FW_API_VER_MAJOR_BY_MAC(hw);
u8 exp_fw_api_ver_minor = EXP_FW_API_VER_MINOR_BY_MAC(hw);
if (hw->api_maj_ver > exp_fw_api_ver_major) {
/* Major API version is newer than expected, don't load */
dev_warn(ice_hw_to_dev(hw),
"The driver for the device stopped because the NVM image is newer than expected. You must install the most recent version of the network driver.\n");
return false;
} else if (hw->api_maj_ver == EXP_FW_API_VER_MAJOR) {
if (hw->api_min_ver > (EXP_FW_API_VER_MINOR + 2))
} else if (hw->api_maj_ver == exp_fw_api_ver_major) {
if (hw->api_min_ver > (exp_fw_api_ver_minor + 2))
dev_info(ice_hw_to_dev(hw),
"The driver for the device detected a newer version of the NVM image than expected. Please install the most recent version of the network driver.\n");
else if ((hw->api_min_ver + 2) < EXP_FW_API_VER_MINOR)
else if ((hw->api_min_ver + 2) < exp_fw_api_ver_minor)
dev_info(ice_hw_to_dev(hw),
"The driver for the device detected an older version of the NVM image than expected. Please update the NVM image.\n");
} else {
......@@ -684,10 +687,12 @@ struct ice_ctl_q_info *ice_get_sbq(struct ice_hw *hw)
* ice_shutdown_ctrlq - shutdown routine for any control queue
* @hw: pointer to the hardware structure
* @q_type: specific Control queue type
* @unloading: is the driver unloading itself
*
* NOTE: this function does not destroy the control queue locks.
*/
static void ice_shutdown_ctrlq(struct ice_hw *hw, enum ice_ctl_q q_type)
static void ice_shutdown_ctrlq(struct ice_hw *hw, enum ice_ctl_q q_type,
bool unloading)
{
struct ice_ctl_q_info *cq;
......@@ -695,7 +700,7 @@ static void ice_shutdown_ctrlq(struct ice_hw *hw, enum ice_ctl_q q_type)
case ICE_CTL_Q_ADMIN:
cq = &hw->adminq;
if (ice_check_sq_alive(hw, cq))
ice_aq_q_shutdown(hw, true);
ice_aq_q_shutdown(hw, unloading);
break;
case ICE_CTL_Q_SB:
cq = &hw->sbq;
......@@ -714,20 +719,21 @@ static void ice_shutdown_ctrlq(struct ice_hw *hw, enum ice_ctl_q q_type)
/**
* ice_shutdown_all_ctrlq - shutdown routine for all control queues
* @hw: pointer to the hardware structure
* @unloading: is the driver unloading itself
*
* NOTE: this function does not destroy the control queue locks. The driver
* may call this at runtime to shutdown and later restart control queues, such
* as in response to a reset event.
*/
void ice_shutdown_all_ctrlq(struct ice_hw *hw)
void ice_shutdown_all_ctrlq(struct ice_hw *hw, bool unloading)
{
/* Shutdown FW admin queue */
ice_shutdown_ctrlq(hw, ICE_CTL_Q_ADMIN);
ice_shutdown_ctrlq(hw, ICE_CTL_Q_ADMIN, unloading);
/* Shutdown PHY Sideband */
if (ice_is_sbq_supported(hw))
ice_shutdown_ctrlq(hw, ICE_CTL_Q_SB);
ice_shutdown_ctrlq(hw, ICE_CTL_Q_SB, unloading);
/* Shutdown PF-VF Mailbox */
ice_shutdown_ctrlq(hw, ICE_CTL_Q_MAILBOX);
ice_shutdown_ctrlq(hw, ICE_CTL_Q_MAILBOX, unloading);
}
/**
......@@ -759,7 +765,7 @@ int ice_init_all_ctrlq(struct ice_hw *hw)
break;
ice_debug(hw, ICE_DBG_AQ_MSG, "Retry Admin Queue init due to FW critical error\n");
ice_shutdown_ctrlq(hw, ICE_CTL_Q_ADMIN);
ice_shutdown_ctrlq(hw, ICE_CTL_Q_ADMIN, true);
msleep(ICE_CTL_Q_ADMIN_INIT_MSEC);
} while (retry++ < ICE_CTL_Q_ADMIN_INIT_TIMEOUT);
......@@ -840,7 +846,7 @@ static void ice_destroy_ctrlq_locks(struct ice_ctl_q_info *cq)
void ice_destroy_all_ctrlq(struct ice_hw *hw)
{
/* shut down all the control queues first */
ice_shutdown_all_ctrlq(hw);
ice_shutdown_all_ctrlq(hw, true);
ice_destroy_ctrlq_locks(&hw->adminq);
if (ice_is_sbq_supported(hw))
......
......@@ -21,9 +21,18 @@
/* Defines that help manage the driver vs FW API checks.
* Take a look at ice_aq_ver_check in ice_controlq.c for actual usage.
*/
#define EXP_FW_API_VER_BRANCH 0x00
#define EXP_FW_API_VER_MAJOR 0x01
#define EXP_FW_API_VER_MINOR 0x05
#define EXP_FW_API_VER_MAJOR_E810 0x01
#define EXP_FW_API_VER_MINOR_E810 0x05
#define EXP_FW_API_VER_MAJOR_E830 0x01
#define EXP_FW_API_VER_MINOR_E830 0x07
#define EXP_FW_API_VER_MAJOR_BY_MAC(hw) ((hw)->mac_type == ICE_MAC_E830 ? \
EXP_FW_API_VER_MAJOR_E830 : \
EXP_FW_API_VER_MAJOR_E810)
#define EXP_FW_API_VER_MINOR_BY_MAC(hw) ((hw)->mac_type == ICE_MAC_E830 ? \
EXP_FW_API_VER_MINOR_E830 : \
EXP_FW_API_VER_MINOR_E810)
/* Different control queue types: These are mainly for SW consumption. */
enum ice_ctl_q {
......
......@@ -623,7 +623,7 @@ ice_prepare_for_reset(struct ice_pf *pf, enum ice_reset_req reset_type)
if (hw->port_info)
ice_sched_clear_port(hw->port_info);
ice_shutdown_all_ctrlq(hw);
ice_shutdown_all_ctrlq(hw, false);
set_bit(ICE_PREPARED_FOR_RESET, pf->state);
}
......@@ -4158,13 +4158,17 @@ int ice_vsi_recfg_qs(struct ice_vsi *vsi, int new_rx, int new_tx, bool locked)
/* set for the next time the netdev is started */
if (!netif_running(vsi->netdev)) {
ice_vsi_rebuild(vsi, ICE_VSI_FLAG_NO_INIT);
err = ice_vsi_rebuild(vsi, ICE_VSI_FLAG_NO_INIT);
if (err)
goto rebuild_err;
dev_dbg(ice_pf_to_dev(pf), "Link is down, queue count change happens when link is brought up\n");
goto done;
}
ice_vsi_close(vsi);
ice_vsi_rebuild(vsi, ICE_VSI_FLAG_NO_INIT);
err = ice_vsi_rebuild(vsi, ICE_VSI_FLAG_NO_INIT);
if (err)
goto rebuild_err;
ice_for_each_traffic_class(i) {
if (vsi->tc_cfg.ena_tc & BIT(i))
......@@ -4175,6 +4179,11 @@ int ice_vsi_recfg_qs(struct ice_vsi *vsi, int new_rx, int new_tx, bool locked)
}
ice_pf_dcb_recfg(pf, locked);
ice_vsi_open(vsi);
goto done;
rebuild_err:
dev_err(ice_pf_to_dev(pf), "Error during VSI rebuild: %d. Unload and reload the driver.\n",
err);
done:
clear_bit(ICE_CFG_BUSY, pf->state);
return err;
......@@ -5490,7 +5499,7 @@ static void ice_prepare_for_shutdown(struct ice_pf *pf)
if (pf->vsi[v])
pf->vsi[v]->vsi_num = 0;
ice_shutdown_all_ctrlq(hw);
ice_shutdown_all_ctrlq(hw, true);
}
/**
......@@ -7750,7 +7759,7 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type)
err_sched_init_port:
ice_sched_cleanup_all(hw);
err_init_ctrlq:
ice_shutdown_all_ctrlq(hw);
ice_shutdown_all_ctrlq(hw, false);
set_bit(ICE_RESET_FAILED, pf->state);
clear_recovery:
/* set this bit in PF state to control service task scheduling */
......
......@@ -1416,21 +1416,23 @@ ice_get_vf_cfg(struct net_device *netdev, int vf_id, struct ifla_vf_info *ivi)
}
/**
* ice_set_vf_mac
* @netdev: network interface device structure
* __ice_set_vf_mac - program VF MAC address
* @pf: PF to be configure
* @vf_id: VF identifier
* @mac: MAC address
*
* program VF MAC address
* Return: zero on success or an error code on failure
*/
int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
int __ice_set_vf_mac(struct ice_pf *pf, u16 vf_id, const u8 *mac)
{
struct ice_pf *pf = ice_netdev_to_pf(netdev);
struct device *dev;
struct ice_vf *vf;
int ret;
dev = ice_pf_to_dev(pf);
if (is_multicast_ether_addr(mac)) {
netdev_err(netdev, "%pM not a valid unicast address\n", mac);
dev_err(dev, "%pM not a valid unicast address\n", mac);
return -EINVAL;
}
......@@ -1459,13 +1461,13 @@ int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
if (is_zero_ether_addr(mac)) {
/* VF will send VIRTCHNL_OP_ADD_ETH_ADDR message with its MAC */
vf->pf_set_mac = false;
netdev_info(netdev, "Removing MAC on VF %d. VF driver will be reinitialized\n",
vf->vf_id);
dev_info(dev, "Removing MAC on VF %d. VF driver will be reinitialized\n",
vf->vf_id);
} else {
/* PF will add MAC rule for the VF */
vf->pf_set_mac = true;
netdev_info(netdev, "Setting MAC %pM on VF %d. VF driver will be reinitialized\n",
mac, vf_id);
dev_info(dev, "Setting MAC %pM on VF %d. VF driver will be reinitialized\n",
mac, vf_id);
}
ice_reset_vf(vf, ICE_VF_RESET_NOTIFY);
......@@ -1476,6 +1478,20 @@ int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
return ret;
}
/**
* ice_set_vf_mac - .ndo_set_vf_mac handler
* @netdev: network interface device structure
* @vf_id: VF identifier
* @mac: MAC address
*
* program VF MAC address
* Return: zero on success or an error code on failure
*/
int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
{
return __ice_set_vf_mac(ice_netdev_to_pf(netdev), vf_id, mac);
}
/**
* ice_set_vf_trust
* @netdev: network interface device structure
......
......@@ -28,6 +28,7 @@
#ifdef CONFIG_PCI_IOV
void ice_process_vflr_event(struct ice_pf *pf);
int ice_sriov_configure(struct pci_dev *pdev, int num_vfs);
int __ice_set_vf_mac(struct ice_pf *pf, u16 vf_id, const u8 *mac);
int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac);
int
ice_get_vf_cfg(struct net_device *netdev, int vf_id, struct ifla_vf_info *ivi);
......@@ -80,6 +81,13 @@ ice_sriov_configure(struct pci_dev __always_unused *pdev,
return -EOPNOTSUPP;
}
static inline int
__ice_set_vf_mac(struct ice_pf __always_unused *pf,
u16 __always_unused vf_id, const u8 __always_unused *mac)
{
return -EOPNOTSUPP;
}
static inline int
ice_set_vf_mac(struct net_device __always_unused *netdev,
int __always_unused vf_id, u8 __always_unused *mac)
......
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