drivers/net/ethernet/mellanox/mlx4/eq.c
Source file repositories/reference/linux-study-clean/drivers/net/ethernet/mellanox/mlx4/eq.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/net/ethernet/mellanox/mlx4/eq.c- Extension
.c- Size
- 45726 bytes
- Lines
- 1563
- Domain
- Driver Families
- Bucket
- drivers/net
- Inferred role
- Driver Families: exported/initcall integration point
- Status
- integration implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/interrupt.hlinux/slab.hlinux/export.hlinux/mm.hlinux/dma-mapping.hlinux/mlx4/cmd.hlinux/cpu_rmap.hmlx4.hfw.h
Detected Declarations
function get_async_ev_maskfunction eq_set_cifunction mlx4_gen_slave_eqefunction slave_eventfunction mlx4_slave_eventfunction mlx4_set_eq_affinity_hintfunction mlx4_gen_pkey_eqefunction mlx4_gen_guid_change_eqefunction mlx4_gen_port_state_change_eqefunction mlx4_get_slave_port_statefunction mlx4_set_slave_port_statefunction set_all_slave_statefunction set_and_calc_slave_port_statefunction mlx4_gen_slaves_port_mgt_evfunction mlx4_master_handle_slave_flrfunction mlx4_eq_intfunction mlx4_interruptfunction mlx4_msi_x_interruptfunction mlx4_MAP_EQ_wrapperfunction mlx4_MAP_EQfunction mlx4_SW2HW_EQfunction mlx4_HW2SW_EQfunction mlx4_num_eq_uarfunction mlx4_unmap_uarfunction mlx4_create_eqfunction mlx4_free_eqfunction mlx4_free_irqsfunction mlx4_map_clr_intfunction mlx4_unmap_clr_intfunction mlx4_alloc_eq_tablefunction mlx4_free_eq_tablefunction mlx4_init_eq_tablefunction mlx4_cleanup_eq_tablefunction mlx4_test_asyncfunction mlx4_test_interruptfunction mlx4_is_eq_vector_validfunction mlx4_get_eqs_per_portfunction mlx4_is_eq_sharedfunction mlx4_assign_eqfunction mlx4_eq_get_irqfunction mlx4_release_eqexport mlx4_gen_pkey_eqeexport mlx4_gen_guid_change_eqeexport mlx4_gen_port_state_change_eqeexport mlx4_get_slave_port_stateexport set_and_calc_slave_port_stateexport mlx4_gen_slaves_port_mgt_evexport mlx4_test_async
Annotated Snippet
mlx4_is_bonded(dev)) {
struct mlx4_port_cap port_cap;
if (!mlx4_QUERY_PORT(dev, 1, &port_cap) && port_cap.link_state)
goto consume;
if (!mlx4_QUERY_PORT(dev, 2, &port_cap) && port_cap.link_state)
goto consume;
}
/* All active slaves need to receive the event */
if (slave == ALL_SLAVES) {
for (i = 0; i <= dev->persist->num_vfs; i++) {
phys_port = 0;
if (eqe->type == MLX4_EVENT_TYPE_PORT_MNG_CHG_EVENT &&
eqe->subtype == MLX4_DEV_PMC_SUBTYPE_PORT_INFO) {
phys_port = eqe->event.port_mgmt_change.port;
slave_port = mlx4_phys_to_slave_port(dev, i, phys_port);
if (slave_port < 0) /* VF doesn't have this port */
continue;
eqe->event.port_mgmt_change.port = slave_port;
}
if (mlx4_GEN_EQE(dev, i, eqe))
mlx4_warn(dev, "Failed to generate event for slave %d\n",
i);
if (phys_port)
eqe->event.port_mgmt_change.port = phys_port;
}
} else {
if (mlx4_GEN_EQE(dev, slave, eqe))
mlx4_warn(dev, "Failed to generate event for slave %d\n",
slave);
}
consume:
++slave_eq->cons;
}
}
static void slave_event(struct mlx4_dev *dev, u8 slave, struct mlx4_eqe *eqe)
{
struct mlx4_priv *priv = mlx4_priv(dev);
struct mlx4_slave_event_eq *slave_eq = &priv->mfunc.master.slave_eq;
struct mlx4_eqe *s_eqe;
unsigned long flags;
spin_lock_irqsave(&slave_eq->event_lock, flags);
s_eqe = &slave_eq->event_eqe[slave_eq->prod & (SLAVE_EVENT_EQ_SIZE - 1)];
if ((!!(s_eqe->owner & 0x80)) ^
(!!(slave_eq->prod & SLAVE_EVENT_EQ_SIZE))) {
mlx4_warn(dev, "Master failed to generate an EQE for slave: %d. No free EQE on slave events queue\n",
slave);
spin_unlock_irqrestore(&slave_eq->event_lock, flags);
return;
}
memcpy(s_eqe, eqe, sizeof(struct mlx4_eqe) - 1);
s_eqe->slave_id = slave;
/* ensure all information is written before setting the ownership bit */
dma_wmb();
s_eqe->owner = !!(slave_eq->prod & SLAVE_EVENT_EQ_SIZE) ? 0x0 : 0x80;
++slave_eq->prod;
queue_work(priv->mfunc.master.comm_wq,
&priv->mfunc.master.slave_event_work);
spin_unlock_irqrestore(&slave_eq->event_lock, flags);
}
static void mlx4_slave_event(struct mlx4_dev *dev, int slave,
struct mlx4_eqe *eqe)
{
struct mlx4_priv *priv = mlx4_priv(dev);
if (slave < 0 || slave > dev->persist->num_vfs ||
slave == dev->caps.function ||
!priv->mfunc.master.slave_state[slave].active)
return;
slave_event(dev, slave, eqe);
}
#if defined(CONFIG_SMP)
static void mlx4_set_eq_affinity_hint(struct mlx4_priv *priv, int vec)
{
int hint_err;
struct mlx4_dev *dev = &priv->dev;
struct mlx4_eq *eq = &priv->eq_table.eq[vec];
if (!cpumask_available(eq->affinity_mask) ||
cpumask_empty(eq->affinity_mask))
return;
Annotation
- Immediate include surface: `linux/interrupt.h`, `linux/slab.h`, `linux/export.h`, `linux/mm.h`, `linux/dma-mapping.h`, `linux/mlx4/cmd.h`, `linux/cpu_rmap.h`, `mlx4.h`.
- Detected declarations: `function get_async_ev_mask`, `function eq_set_ci`, `function mlx4_gen_slave_eqe`, `function slave_event`, `function mlx4_slave_event`, `function mlx4_set_eq_affinity_hint`, `function mlx4_gen_pkey_eqe`, `function mlx4_gen_guid_change_eqe`, `function mlx4_gen_port_state_change_eqe`, `function mlx4_get_slave_port_state`.
- Atlas domain: Driver Families / drivers/net.
- Implementation status: integration implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.