ix(4): Run {mod,msf,mbx,fdir,phy}_task in if_update_admin_status

From Piotr:

This patch introduces adapter->task_requests register responsible for
recording requests for mod_task, msf_task, mbx_task, fdir_task and
phy_task calls. Instead of enqueueing these tasks with
GROUPTASK_ENQUEUE, handlers will be called directly from
ixgbe_if_update_admin_status() while holding ctx lock.

SIOCGIFXMEDIA ioctl() call reads adapter->media list. The list is
deleted and rewritten in ixgbe_handle_msf() task without holding ctx
lock. This change is needed to maintain data coherency when sharing
adapter info via ioctl() calls.

Patch co-authored by Krzysztof Galazka <krzysztof.galazka@intel.com>.

PR:		221317
Submitted by:	Piotr Pietruszewski <piotr.pietruszewski@intel.com>
Reviewed by:	sbruno@, IntelNetworking
Sponsored by:	Intel Corporation
Differential Revision:	https://reviews.freebsd.org/D18468
This commit is contained in:
erj 2019-01-31 21:44:33 +00:00
parent cddd24c832
commit 649e8ad140
3 changed files with 59 additions and 59 deletions

View File

@ -120,6 +120,7 @@ static int ixgbe_if_resume(if_ctx_t ctx);
static void ixgbe_if_stop(if_ctx_t ctx);
void ixgbe_if_enable_intr(if_ctx_t ctx);
static void ixgbe_if_disable_intr(if_ctx_t ctx);
static void ixgbe_link_intr_enable(if_ctx_t ctx);
static int ixgbe_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t qid);
static void ixgbe_if_media_status(if_ctx_t ctx, struct ifmediareq * ifmr);
static int ixgbe_if_media_change(if_ctx_t ctx);
@ -173,7 +174,7 @@ static void ixgbe_init_device_features(struct adapter *adapter);
static void ixgbe_check_fan_failure(struct adapter *, u32, bool);
static void ixgbe_add_media_types(if_ctx_t ctx);
static void ixgbe_update_stats_counters(struct adapter *adapter);
static void ixgbe_config_link(struct adapter *adapter);
static void ixgbe_config_link(if_ctx_t ctx);
static void ixgbe_get_slot_info(struct adapter *);
static void ixgbe_check_wol_support(struct adapter *adapter);
static void ixgbe_enable_rx_drop(struct adapter *);
@ -254,6 +255,7 @@ static device_method_t ixgbe_if_methods[] = {
DEVMETHOD(ifdi_msix_intr_assign, ixgbe_if_msix_intr_assign),
DEVMETHOD(ifdi_intr_enable, ixgbe_if_enable_intr),
DEVMETHOD(ifdi_intr_disable, ixgbe_if_disable_intr),
DEVMETHOD(ifdi_link_intr_enable, ixgbe_link_intr_enable),
DEVMETHOD(ifdi_tx_queue_intr_enable, ixgbe_if_rx_queue_intr_enable),
DEVMETHOD(ifdi_rx_queue_intr_enable, ixgbe_if_rx_queue_intr_enable),
DEVMETHOD(ifdi_tx_queues_alloc, ixgbe_if_tx_queues_alloc),
@ -446,19 +448,6 @@ ixgbe_if_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs,
}
iflib_config_gtask_init(ctx, &adapter->mod_task, ixgbe_handle_mod,
"mod_task");
iflib_config_gtask_init(ctx, &adapter->msf_task, ixgbe_handle_msf,
"msf_task");
iflib_config_gtask_init(ctx, &adapter->phy_task, ixgbe_handle_phy,
"phy_task");
if (adapter->feat_cap & IXGBE_FEATURE_SRIOV)
iflib_config_gtask_init(ctx, &adapter->mbx_task,
ixgbe_handle_mbx, "mbx_task");
if (adapter->feat_en & IXGBE_FEATURE_FDIR)
iflib_config_gtask_init(ctx, &adapter->fdir_task,
ixgbe_reinit_fdir, "fdir_task");
device_printf(iflib_get_dev(ctx), "allocated for %d queues\n",
adapter->num_tx_queues);
@ -1362,8 +1351,9 @@ ixgbe_is_sfp(struct ixgbe_hw *hw)
* ixgbe_config_link
************************************************************************/
static void
ixgbe_config_link(struct adapter *adapter)
ixgbe_config_link(if_ctx_t ctx)
{
struct adapter *adapter = iflib_get_softc(ctx);
struct ixgbe_hw *hw = &adapter->hw;
u32 autoneg, err = 0;
bool sfp, negotiate;
@ -1371,7 +1361,8 @@ ixgbe_config_link(struct adapter *adapter)
sfp = ixgbe_is_sfp(hw);
if (sfp) {
GROUPTASK_ENQUEUE(&adapter->mod_task);
adapter->task_requests |= IXGBE_REQUEST_TASK_MOD;
iflib_admin_intr_deferred(ctx);
} else {
if (hw->mac.ops.check_link)
err = ixgbe_check_link(hw, &adapter->link_speed,
@ -1388,7 +1379,6 @@ ixgbe_config_link(struct adapter *adapter)
err = hw->mac.ops.setup_link(hw, autoneg,
adapter->link_up);
}
} /* ixgbe_config_link */
/************************************************************************
@ -2096,8 +2086,6 @@ ixgbe_if_media_status(if_ctx_t ctx, struct ifmediareq * ifmr)
INIT_DEBUGOUT("ixgbe_if_media_status: begin");
iflib_admin_intr_deferred(ctx);
ifmr->ifm_status = IFM_AVALID;
ifmr->ifm_active = IFM_ETHER;
@ -2386,7 +2374,7 @@ ixgbe_msix_link(void *arg)
/* Link status change */
if (eicr & IXGBE_EICR_LSC) {
IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_LSC);
iflib_admin_intr_deferred(adapter->ctx);
adapter->task_requests |= IXGBE_REQUEST_TASK_LSC;
}
if (adapter->hw.mac.type != ixgbe_mac_82598EB) {
@ -2397,7 +2385,7 @@ ixgbe_msix_link(void *arg)
return (FILTER_HANDLED);
/* Disable the interrupt */
IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EICR_FLOW_DIR);
GROUPTASK_ENQUEUE(&adapter->fdir_task);
adapter->task_requests |= IXGBE_REQUEST_TASK_FDIR;
} else
if (eicr & IXGBE_EICR_ECC) {
device_printf(iflib_get_dev(adapter->ctx),
@ -2441,7 +2429,7 @@ ixgbe_msix_link(void *arg)
/* Check for VF message */
if ((adapter->feat_en & IXGBE_FEATURE_SRIOV) &&
(eicr & IXGBE_EICR_MAILBOX))
GROUPTASK_ENQUEUE(&adapter->mbx_task);
adapter->task_requests |= IXGBE_REQUEST_TASK_MBX;
}
if (ixgbe_is_sfp(hw)) {
@ -2453,16 +2441,14 @@ ixgbe_msix_link(void *arg)
if (eicr & eicr_mask) {
IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr_mask);
if (atomic_cmpset_acq_int(&adapter->sfp_reinit, 0, 1))
GROUPTASK_ENQUEUE(&adapter->mod_task);
adapter->task_requests |= IXGBE_REQUEST_TASK_MOD;
}
if ((hw->mac.type == ixgbe_mac_82599EB) &&
(eicr & IXGBE_EICR_GPI_SDP1_BY_MAC(hw))) {
IXGBE_WRITE_REG(hw, IXGBE_EICR,
IXGBE_EICR_GPI_SDP1_BY_MAC(hw));
if (atomic_cmpset_acq_int(&adapter->sfp_reinit, 0, 1))
GROUPTASK_ENQUEUE(&adapter->msf_task);
adapter->task_requests |= IXGBE_REQUEST_TASK_MSF;
}
}
@ -2476,13 +2462,10 @@ ixgbe_msix_link(void *arg)
if ((hw->phy.type == ixgbe_phy_x550em_ext_t) &&
(eicr & IXGBE_EICR_GPI_SDP0_X540)) {
IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP0_X540);
GROUPTASK_ENQUEUE(&adapter->phy_task);
adapter->task_requests |= IXGBE_REQUEST_TASK_PHY;
}
/* Re-enable other interrupts */
IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_OTHER);
return (FILTER_HANDLED);
return (adapter->task_requests != 0) ? FILTER_SCHEDULE_THREAD : FILTER_HANDLED;
} /* ixgbe_msix_link */
/************************************************************************
@ -2646,12 +2629,6 @@ ixgbe_if_detach(if_ctx_t ctx)
return (EBUSY);
}
iflib_config_gtask_deinit(&adapter->mod_task);
iflib_config_gtask_deinit(&adapter->msf_task);
iflib_config_gtask_deinit(&adapter->phy_task);
if (adapter->feat_cap & IXGBE_FEATURE_SRIOV)
iflib_config_gtask_deinit(&adapter->mbx_task);
ixgbe_setup_low_power_mode(ctx);
/* let hardware know driver is unloading */
@ -2910,6 +2887,12 @@ ixgbe_if_init(if_ctx_t ctx)
/* Configure RX settings */
ixgbe_initialize_receive_units(ctx);
/*
* Initialize variable holding task enqueue requests
* from MSI-X interrupts
*/
adapter->task_requests = 0;
/* Enable SDP & MSI-X interrupts based on adapter */
ixgbe_config_gpie(adapter);
@ -3011,7 +2994,7 @@ ixgbe_if_init(if_ctx_t ctx)
ixgbe_set_phy_power(hw, TRUE);
/* Config/Enable Link */
ixgbe_config_link(adapter);
ixgbe_config_link(ctx);
/* Hardware Packet Buffer & Flow Control setup */
ixgbe_config_delay_values(adapter);
@ -3374,7 +3357,6 @@ ixgbe_handle_mod(void *context)
device_t dev = iflib_get_dev(ctx);
u32 err, cage_full = 0;
adapter->sfp_reinit = 1;
if (adapter->hw.need_crosstalk_fix) {
switch (hw->mac.type) {
case ixgbe_mac_82599EB:
@ -3411,11 +3393,11 @@ ixgbe_handle_mod(void *context)
"Setup failure - unsupported SFP+ module type.\n");
goto handle_mod_out;
}
GROUPTASK_ENQUEUE(&adapter->msf_task);
adapter->task_requests |= IXGBE_REQUEST_TASK_MSF;
return;
handle_mod_out:
adapter->sfp_reinit = 0;
adapter->task_requests &= ~(IXGBE_REQUEST_TASK_MSF);
} /* ixgbe_handle_mod */
@ -3431,9 +3413,6 @@ ixgbe_handle_msf(void *context)
u32 autoneg;
bool negotiate;
if (adapter->sfp_reinit != 1)
return;
/* get_supported_phy_layer will call hw->phy.ops.identify_sfp() */
adapter->phy_layer = ixgbe_get_supported_physical_layer(hw);
@ -3447,8 +3426,6 @@ ixgbe_handle_msf(void *context)
ifmedia_removeall(adapter->media);
ixgbe_add_media_types(adapter->ctx);
ifmedia_set(adapter->media, IFM_ETHER | IFM_AUTO);
adapter->sfp_reinit = 0;
} /* ixgbe_handle_msf */
/************************************************************************
@ -3543,10 +3520,20 @@ ixgbe_if_update_admin_status(if_ctx_t ctx)
}
}
ixgbe_update_stats_counters(adapter);
/* Handle task requests from msix_link() */
if (adapter->task_requests & IXGBE_REQUEST_TASK_MOD)
ixgbe_handle_mod(ctx);
if (adapter->task_requests & IXGBE_REQUEST_TASK_MSF)
ixgbe_handle_msf(ctx);
if (adapter->task_requests & IXGBE_REQUEST_TASK_MBX)
ixgbe_handle_mbx(ctx);
if (adapter->task_requests & IXGBE_REQUEST_TASK_FDIR)
ixgbe_reinit_fdir(ctx);
if (adapter->task_requests & IXGBE_REQUEST_TASK_PHY)
ixgbe_handle_phy(ctx);
adapter->task_requests = 0;
/* Re-enable link interrupts */
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, IXGBE_EIMS_LSC);
ixgbe_update_stats_counters(adapter);
} /* ixgbe_if_update_admin_status */
/************************************************************************
@ -3681,6 +3668,18 @@ ixgbe_if_disable_intr(if_ctx_t ctx)
} /* ixgbe_if_disable_intr */
/************************************************************************
* ixgbe_link_intr_enable
************************************************************************/
static void
ixgbe_link_intr_enable(if_ctx_t ctx)
{
struct ixgbe_hw *hw = &((struct adapter *)iflib_get_softc(ctx))->hw;
/* Re-enable other interrupts */
IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_OTHER | IXGBE_EIMS_LSC);
} /* ixgbe_link_intr_enable */
/************************************************************************
* ixgbe_if_rx_queue_intr_enable
************************************************************************/
@ -3784,22 +3783,21 @@ ixgbe_intr(void *arg)
if (eicr & eicr_mask) {
IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr_mask);
GROUPTASK_ENQUEUE(&adapter->mod_task);
adapter->task_requests |= IXGBE_REQUEST_TASK_MOD;
}
if ((hw->mac.type == ixgbe_mac_82599EB) &&
(eicr & IXGBE_EICR_GPI_SDP1_BY_MAC(hw))) {
IXGBE_WRITE_REG(hw, IXGBE_EICR,
IXGBE_EICR_GPI_SDP1_BY_MAC(hw));
if (atomic_cmpset_acq_int(&adapter->sfp_reinit, 0, 1))
GROUPTASK_ENQUEUE(&adapter->msf_task);
adapter->task_requests |= IXGBE_REQUEST_TASK_MSF;
}
}
/* External PHY interrupt */
if ((hw->phy.type == ixgbe_phy_x550em_ext_t) &&
(eicr & IXGBE_EICR_GPI_SDP0_X540))
GROUPTASK_ENQUEUE(&adapter->phy_task);
adapter->task_requests |= IXGBE_REQUEST_TASK_PHY;
return (FILTER_SCHEDULE_THREAD);
} /* ixgbe_intr */

View File

@ -428,16 +428,11 @@ struct adapter {
/* Support for pluggable optics */
bool sfp_probe;
struct grouptask mod_task; /* SFP tasklet */
struct grouptask msf_task; /* Multispeed Fiber */
struct grouptask mbx_task; /* VF -> PF mailbox interrupt */
int sfp_reinit;
/* Flow Director */
int fdir_reinit;
struct grouptask fdir_task;
struct grouptask phy_task; /* PHY intr tasklet */
u32 task_requests;
/*
* Queues:

View File

@ -4427,4 +4427,11 @@ struct ixgbe_bypass_eeprom {
#define IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD \
(0x1F << IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT)
#define IXGBE_REQUEST_TASK_MOD 0x01
#define IXGBE_REQUEST_TASK_MSF 0x02
#define IXGBE_REQUEST_TASK_MBX 0x04
#define IXGBE_REQUEST_TASK_FDIR 0x08
#define IXGBE_REQUEST_TASK_PHY 0x10
#define IXGBE_REQUEST_TASK_LSC 0x20
#endif /* _IXGBE_TYPE_H_ */