diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 761ccc64eee980a96438d8d627344d77ccc1e14a..b29a819f721df056ece96972a37e7cf8fcd30aae 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -6456,6 +6456,7 @@ const struct efx_nic_type efx_hunt_a0_vf_nic_type = { .rx_ts_offset = ES_DZ_RX_PREFIX_TSTAMP_OFST, .can_rx_scatter = true, .always_rx_scatter = true, + .min_interrupt_mode = EFX_INT_MODE_MSIX, .max_interrupt_mode = EFX_INT_MODE_MSIX, .timer_period_max = 1 << ERF_DD_EVQ_IND_TIMER_VAL_WIDTH, .offload_features = EF10_OFFLOAD_FEATURES, @@ -6588,6 +6589,7 @@ const struct efx_nic_type efx_hunt_a0_nic_type = { .can_rx_scatter = true, .always_rx_scatter = true, .option_descriptors = true, + .min_interrupt_mode = EFX_INT_MODE_LEGACY, .max_interrupt_mode = EFX_INT_MODE_MSIX, .timer_period_max = 1 << ERF_DD_EVQ_IND_TIMER_VAL_WIDTH, .offload_features = EF10_OFFLOAD_FEATURES, diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index cb8e2c3f806a66c6eb59a43caa4bab5dd9b7dfa8..8c4c273643dc3932c472e3f30df231f2236c6e2a 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -1420,9 +1420,12 @@ static int efx_probe_interrupts(struct efx_nic *efx) xentries, 1, n_channels); if (rc < 0) { /* Fall back to single channel MSI */ - efx->interrupt_mode = EFX_INT_MODE_MSI; netif_err(efx, drv, efx->net_dev, "could not enable MSI-X\n"); + if (efx->type->min_interrupt_mode >= EFX_INT_MODE_MSI) + efx->interrupt_mode = EFX_INT_MODE_MSI; + else + return rc; } else if (rc < n_channels) { netif_err(efx, drv, efx->net_dev, "WARNING: Insufficient MSI-X vectors" @@ -1465,7 +1468,10 @@ static int efx_probe_interrupts(struct efx_nic *efx) } else { netif_err(efx, drv, efx->net_dev, "could not enable MSI\n"); - efx->interrupt_mode = EFX_INT_MODE_LEGACY; + if (efx->type->min_interrupt_mode >= EFX_INT_MODE_LEGACY) + efx->interrupt_mode = EFX_INT_MODE_LEGACY; + else + return rc; } } @@ -2935,7 +2941,7 @@ static const struct efx_phy_operations efx_dummy_phy_operations = { static int efx_init_struct(struct efx_nic *efx, struct pci_dev *pci_dev, struct net_device *net_dev) { - int i; + int rc = -ENOMEM, i; /* Initialise common structures */ INIT_LIST_HEAD(&efx->node); @@ -2976,8 +2982,15 @@ static int efx_init_struct(struct efx_nic *efx, } /* Higher numbered interrupt modes are less capable! */ + if (WARN_ON_ONCE(efx->type->max_interrupt_mode > + efx->type->min_interrupt_mode)) { + rc = -EIO; + goto fail; + } efx->interrupt_mode = max(efx->type->max_interrupt_mode, interrupt_mode); + efx->interrupt_mode = min(efx->type->min_interrupt_mode, + interrupt_mode); /* Would be good to use the net_dev name, but we're too early */ snprintf(efx->workqueue_name, sizeof(efx->workqueue_name), "sfc%s", @@ -2990,7 +3003,7 @@ static int efx_init_struct(struct efx_nic *efx, fail: efx_fini_struct(efx); - return -ENOMEM; + return rc; } static void efx_fini_struct(struct efx_nic *efx) diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index 5cb8112b1cf3d3871f95bc395945c76a63e4a3a4..c0537ea06c9ac495803f19266e2cd26c5b12a097 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -1142,8 +1142,10 @@ struct efx_udp_tunnel { * @can_rx_scatter: NIC is able to scatter packets to multiple buffers * @always_rx_scatter: NIC will always scatter packets to multiple buffers * @option_descriptors: NIC supports TX option descriptors + * @min_interrupt_mode: Lowest capability interrupt mode supported + * from &enum efx_int_mode. * @max_interrupt_mode: Highest capability interrupt mode supported - * from &enum efx_init_mode. + * from &enum efx_int_mode. * @timer_period_max: Maximum period of interrupt timer (in ticks) * @offload_features: net_device feature flags for protocol offload * features implemented in hardware @@ -1306,6 +1308,7 @@ struct efx_nic_type { bool can_rx_scatter; bool always_rx_scatter; bool option_descriptors; + unsigned int min_interrupt_mode; unsigned int max_interrupt_mode; unsigned int timer_period_max; netdev_features_t offload_features; diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c index b1d36df71ecb91cf2b2a86cabf5e61bbc8b687b8..a617f657eae35fa710e777d524c9b33708f3bdee 100644 --- a/drivers/net/ethernet/sfc/siena.c +++ b/drivers/net/ethernet/sfc/siena.c @@ -1069,6 +1069,7 @@ const struct efx_nic_type siena_a0_nic_type = { .rx_buffer_padding = 0, .can_rx_scatter = true, .option_descriptors = false, + .min_interrupt_mode = EFX_INT_MODE_LEGACY, .max_interrupt_mode = EFX_INT_MODE_MSIX, .timer_period_max = 1 << FRF_CZ_TC_TIMER_VAL_WIDTH, .offload_features = (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |