/* On all EF10s up to and including SFC9220 (Medford1), all PFs use BAR 0 for *I/OspaceandBAR2(&3)formemory.OnSFC9250(Medford2),thereisnoI/O *bar;PFsuseBAR0/1formemory.
*/ staticunsignedint efx_ef10_pf_mem_bar(struct efx_nic *efx)
{ switch (efx->pci_dev->device) { case0x0b03: /* SFC9250 PF */ return0; default: return2;
}
}
/* All VFs use BAR 0/1 for memory */ staticunsignedint efx_ef10_vf_mem_bar(struct efx_nic *efx)
{ return0;
}
staticunsignedint efx_ef10_mem_map_size(struct efx_nic *efx)
{ int bar;
bar = efx->type->mem_bar(efx); return resource_size(&efx->pci_dev->resource[bar]);
}
/* record the DPCPU firmware IDs to determine VEB vswitching support.
*/
nic_data->rx_dpcpu_fw_id =
MCDI_WORD(outbuf, GET_CAPABILITIES_OUT_RX_DPCPU_FW_ID);
nic_data->tx_dpcpu_fw_id =
MCDI_WORD(outbuf, GET_CAPABILITIES_OUT_TX_DPCPU_FW_ID);
if (!(nic_data->datapath_caps &
(1 << MC_CMD_GET_CAPABILITIES_OUT_RX_PREFIX_LEN_14_LBN))) {
netif_err(efx, probe, efx->net_dev, "current firmware does not support an RX prefix\n"); return -ENODEV;
}
if (outlen >= MC_CMD_GET_CAPABILITIES_V3_OUT_LEN) {
u8 vi_window_mode = MCDI_BYTE(outbuf,
GET_CAPABILITIES_V3_OUT_VI_WINDOW_MODE);
rc = efx_mcdi_window_mode_to_stride(efx, vi_window_mode); if (rc) return rc;
} else { /* keep default VI stride */
netif_dbg(efx, probe, efx->net_dev, "firmware did not report VI window mode, assuming vi_stride = %u\n",
efx->vi_stride);
}
if (outlen >= MC_CMD_GET_CAPABILITIES_V4_OUT_LEN) {
efx->num_mac_stats = MCDI_WORD(outbuf,
GET_CAPABILITIES_V4_OUT_MAC_STATS_NUM_STATS);
netif_dbg(efx, probe, efx->net_dev, "firmware reports num_mac_stats = %u\n",
efx->num_mac_stats);
} else { /* leave num_mac_stats as the default value, MC_CMD_MAC_NSTATS */
netif_dbg(efx, probe, efx->net_dev, "firmware did not report num_mac_stats, assuming %u\n",
efx->num_mac_stats);
}
if (rc == -ENOSYS) { /* Firmware without GET_WORKAROUNDS - not a problem. */
rc = 0;
} elseif (rc == 0) { /* Bug61265 workaround is always enabled if implemented. */ if (enabled & MC_CMD_GET_WORKAROUNDS_OUT_BUG61265)
nic_data->workaround_61265 = true;
if (enabled & MC_CMD_GET_WORKAROUNDS_OUT_BUG35388) {
nic_data->workaround_35388 = true;
} elseif (implemented & MC_CMD_GET_WORKAROUNDS_OUT_BUG35388) { /* Workaround is implemented but not enabled. *Trytoenableit.
*/
rc = efx_mcdi_set_workaround(efx,
MC_CMD_WORKAROUND_BUG35388, true, NULL); if (rc == 0)
nic_data->workaround_35388 = true; /* If we failed to set the workaround just carry on. */
rc = 0;
}
}
netif_dbg(efx, probe, efx->net_dev, "workaround for bug 35388 is %sabled\n",
nic_data->workaround_35388 ? "en" : "dis");
netif_dbg(efx, probe, efx->net_dev, "workaround for bug 61265 is %sabled\n",
nic_data->workaround_61265 ? "en" : "dis");
if (rc == 0) {
efx_ef10_process_timer_config(efx, outbuf);
} elseif (rc == -ENOSYS || rc == -EPERM) { /* Not available - fall back to Huntington defaults. */ unsignedint quantum;
rc = efx_ef10_get_sysclk_freq(efx); if (rc < 0) return rc;
/* 8021q removes VID 0 on module unload for all interfaces *withVLANfilteringfeature.Weneedtokeepittoreceive *untaggedtraffic.
*/ if (vid == 0) return0;
mutex_lock(&nic_data->vlan_lock);
vlan = efx_ef10_find_vlan(efx, vid); if (!vlan) {
netif_err(efx, drv, efx->net_dev, "VLAN %u to be deleted not found\n", vid);
rc = -ENOENT;
} else {
efx_ef10_del_vlan_internal(efx, vlan);
}
/* Get the MC's warm boot count. In case it's rebooting right *now,bepreparedtoretry.
*/
i = 0; for (;;) {
rc = efx_ef10_get_warm_boot_count(efx); if (rc >= 0) break; if (++i == 5) goto fail2;
ssleep(1);
}
nic_data->warm_boot_count = rc;
/* In case we're recovering from a crash (kexec), we want to *cancelanyoutstandingrequestbytheprevioususerofthis *function.Wesendaspecialmessageusingtheleast *significantbitsofthe'high'(doorbell)register.
*/
_efx_writed(efx, cpu_to_le32(1), ER_DZ_MC_DB_HWRD);
rc = efx_mcdi_init(efx); if (rc) goto fail2;
mutex_init(&nic_data->udp_tunnels_lock); for (i = 0; i < ARRAY_SIZE(nic_data->udp_tunnels); ++i)
nic_data->udp_tunnels[i].type =
TUNNEL_ENCAP_UDP_PORT_ENTRY_INVALID;
/* Reset (most) configuration for this function */
rc = efx_mcdi_reset(efx, RESET_TYPE_ALL); if (rc) goto fail3;
/* Add unspecified VID to support VLAN filtering being disabled */
rc = efx_ef10_add_vlan(efx, EFX_FILTER_VID_UNSPEC); if (rc) goto fail_add_vid_unspec;
/* If VLAN filtering is enabled, we need VID 0 to get untagged *traffic.Itisaddedautomaticallyif8021qmoduleisloaded, *butwecan'trelyonitsincemodulemaybenotloaded.
*/
rc = efx_ef10_add_vlan(efx, 0); if (rc) goto fail_add_vid_0;
/* Link a buffer to each VI in the write-combining mapping */ for (index = 0; index < nic_data->n_piobufs; ++index) {
MCDI_SET_DWORD(inbuf, LINK_PIOBUF_IN_PIOBUF_HANDLE,
nic_data->piobuf_handle[index]);
MCDI_SET_DWORD(inbuf, LINK_PIOBUF_IN_TXQ_INSTANCE,
nic_data->pio_write_vi_base + index);
rc = efx_mcdi_rpc(efx, MC_CMD_LINK_PIOBUF,
inbuf, MC_CMD_LINK_PIOBUF_IN_LEN,
NULL, 0, NULL); if (rc) {
netif_err(efx, drv, efx->net_dev, "failed to link VI %u to PIO buffer %u (%d)\n",
nic_data->pio_write_vi_base + index, index,
rc); goto fail;
}
netif_dbg(efx, probe, efx->net_dev, "linked VI %u to PIO buffer %u\n",
nic_data->pio_write_vi_base + index, index);
}
/* Link a buffer to each TX queue */
efx_for_each_channel(channel, efx) { /* Extra channels, even those with TXQs (PTP), do not require *PIOresources.
*/ if (!channel->type->want_pio ||
channel->channel >= efx->xdp_channel_offset) continue;
efx_for_each_channel_tx_queue(tx_queue, channel) { /* We assign the PIO buffers to queues in *reverseordertoallowforthefollowing *specialcase.
*/
offset = ((efx->tx_channel_offset + efx->n_tx_channels -
tx_queue->channel->channel - 1) *
efx_piobuf_size);
index = offset / nic_data->piobuf_size;
offset = offset % nic_data->piobuf_size;
/* When the host page size is 4K, the first *hostpageintheWCmappingmaybewithin *thesameVIpageasthelastTXqueue.We *canonlylinkonebuffertoeachVI.
*/ if (tx_queue->queue == nic_data->pio_write_vi_base) {
BUG_ON(index != 0);
rc = 0;
} else {
MCDI_SET_DWORD(inbuf,
LINK_PIOBUF_IN_PIOBUF_HANDLE,
nic_data->piobuf_handle[index]);
MCDI_SET_DWORD(inbuf,
LINK_PIOBUF_IN_TXQ_INSTANCE,
tx_queue->queue);
rc = efx_mcdi_rpc(efx, MC_CMD_LINK_PIOBUF,
inbuf, MC_CMD_LINK_PIOBUF_IN_LEN,
NULL, 0, NULL);
}
if (rc) { /* This is non-fatal; the TX path just *won'tusePIOforthisqueue
*/
netif_err(efx, drv, efx->net_dev, "failed to link VI %u to PIO buffer %u (%d)\n",
tx_queue->queue, index, rc);
tx_queue->piobuf = NULL;
} else {
tx_queue->piobuf =
nic_data->pio_write_base +
index * efx->vi_stride + offset;
tx_queue->piobuf_offset = offset;
netif_dbg(efx, probe, efx->net_dev, "linked VI %u to PIO buffer %u offset %x addr %p\n",
tx_queue->queue, index,
tx_queue->piobuf_offset,
tx_queue->piobuf);
}
}
}
return0;
fail: /* inbuf was defined for MC_CMD_LINK_PIOBUF. We can use the same *bufferforMC_CMD_UNLINK_PIOBUFbecauseit'sshorter.
*/
BUILD_BUG_ON(MC_CMD_LINK_PIOBUF_IN_LEN < MC_CMD_UNLINK_PIOBUF_IN_LEN); while (index--) {
MCDI_SET_DWORD(inbuf, UNLINK_PIOBUF_IN_TXQ_INSTANCE,
nic_data->pio_write_vi_base + index);
efx_mcdi_rpc(efx, MC_CMD_UNLINK_PIOBUF,
inbuf, MC_CMD_UNLINK_PIOBUF_IN_LEN,
NULL, 0, NULL);
} return rc;
}
/* If the parent PF has no VF data structure, it doesn't know about this *VFsofailprobe.TheVFneedstobere-created.Thiscanhappen *ifthePFdriverwasunloadedwhileanyVFwasassignedtoaguest *(usingXen,only).
*/
pci_dev_pf = efx->pci_dev->physfn; if (pci_dev_pf) { struct efx_nic *efx_pf = pci_get_drvdata(pci_dev_pf); struct efx_ef10_nic_data *nic_data_pf = efx_pf->nic_data;
if (!nic_data_pf->vf) {
netif_info(efx, drv, efx->net_dev, "The VF cannot link to its parent PF; " "please destroy and re-create the VF\n"); return -EBUSY;
}
}
rc = efx_ef10_probe(efx); if (rc) return rc;
rc = efx_ef10_get_vf_index(efx); if (rc) goto fail;
nic_data_p->vf[nic_data->vf_index].efx = efx;
nic_data_p->vf[nic_data->vf_index].pci_dev =
efx->pci_dev;
} else
netif_info(efx, drv, efx->net_dev, "Could not get the PF id from VF\n");
}
/* Note that the failure path of this function does not free *resources,asthiswillbedonebyefx_ef10_remove().
*/ staticint efx_ef10_dimension_resources(struct efx_nic *efx)
{ unsignedint min_vis = max_t(unsignedint, efx->tx_queues_per_channel,
efx_separate_tx_channels ? 2 : 1); unsignedint channel_vis, pio_write_vi_base, max_vis; struct efx_ef10_nic_data *nic_data = efx->nic_data; unsignedint uc_mem_map_size, wc_mem_map_size; void __iomem *membase; int rc;
channel_vis = max(efx->n_channels,
((efx->n_tx_channels + efx->n_extra_tx_channels) *
efx->tx_queues_per_channel) +
efx->n_xdp_channels * efx->xdp_tx_per_channel); if (efx->max_vis && efx->max_vis < channel_vis) {
netif_dbg(efx, drv, efx->net_dev, "Reducing channel VIs from %u to %u\n",
channel_vis, efx->max_vis);
channel_vis = efx->max_vis;
}
#ifdef EFX_USE_PIO /* Try to allocate PIO buffers if wanted and if the full *numberofPIObufferswouldbesufficienttoallocateone *copy-bufferperTXchannel.Failureisnon-fatal,asthere *areonlyasmallnumberofPIObufferssharedbetweenall *functionsofthecontroller.
*/ if (efx_piobuf_size != 0 &&
nic_data->piobuf_size / efx_piobuf_size * EF10_TX_PIOBUF_COUNT >=
efx->n_tx_channels) { unsignedint n_piobufs =
DIV_ROUND_UP(efx->n_tx_channels,
nic_data->piobuf_size / efx_piobuf_size);
rc = efx_ef10_alloc_piobufs(efx, n_piobufs); if (rc == -ENOSPC)
netif_dbg(efx, probe, efx->net_dev, "out of PIO buffers; cannot allocate more\n"); elseif (rc == -EPERM)
netif_dbg(efx, probe, efx->net_dev, "not permitted to allocate PIO buffers\n"); elseif (rc)
netif_err(efx, probe, efx->net_dev, "failed to allocate PIO buffers (%d)\n", rc); else
netif_dbg(efx, probe, efx->net_dev, "allocated %u PIO buffers\n", n_piobufs);
} #else
nic_data->n_piobufs = 0; #endif
/* PIO buffers should be mapped with write-combining enabled, *andwewanttomakesingleUCandWCmappingsratherthan *severalofeach(infactthat'stheonlyoptionifhost *pagesizeis>4K).SowemayallocatesomeextraVIsjust *forwritingPIObuffersthrough. * *TheUCmappingcontains(channel_vis-1)completeVIsandthe *first4KofthenextVI.ThentheWCmappingbeginswith *theremainderofthislastVI.
*/
uc_mem_map_size = PAGE_ALIGN((channel_vis - 1) * efx->vi_stride +
ER_DZ_TX_PIOBUF); if (nic_data->n_piobufs) { /* pio_write_vi_base rounds down to give the number of complete *VIsinsidetheUCmapping.
*/
pio_write_vi_base = uc_mem_map_size / efx->vi_stride;
wc_mem_map_size = (PAGE_ALIGN((pio_write_vi_base +
nic_data->n_piobufs) *
efx->vi_stride) -
uc_mem_map_size);
max_vis = pio_write_vi_base + nic_data->n_piobufs;
} else {
pio_write_vi_base = 0;
wc_mem_map_size = 0;
max_vis = channel_vis;
}
/* In case the last attached driver failed to free VIs, do it now */
rc = efx_mcdi_free_vis(efx); if (rc != 0) return rc;
if (nic_data->n_allocated_vis < channel_vis) {
netif_info(efx, drv, efx->net_dev, "Could not allocate enough VIs to satisfy RSS" " requirements. Performance may not be optimal.\n"); /* We didn't get the VIs to populate our channels. *Wecouldkeepwhatwegotbutthenwe'dhavemore *interruptsthanweneed. *Insteadcalculatenewmax_channelsandrestart
*/
efx->max_channels = nic_data->n_allocated_vis;
efx->max_tx_channels =
nic_data->n_allocated_vis / efx->tx_queues_per_channel;
efx_mcdi_free_vis(efx); return -EAGAIN;
}
/* If we didn't get enough VIs to map all the PIO buffers, free the *PIObuffers
*/ if (nic_data->n_piobufs &&
nic_data->n_allocated_vis <
pio_write_vi_base + nic_data->n_piobufs) {
netif_dbg(efx, probe, efx->net_dev, "%u VIs are not sufficient to map %u PIO buffers\n",
nic_data->n_allocated_vis, nic_data->n_piobufs);
efx_ef10_free_piobufs(efx);
}
/* Shrink the original UC mapping of the memory BAR */
membase = ioremap(efx->membase_phys, uc_mem_map_size); if (!membase) {
netif_err(efx, probe, efx->net_dev, "could not shrink memory BAR to %x\n",
uc_mem_map_size); return -ENOMEM;
}
iounmap(efx->membase);
efx->membase = membase;
/* Set up the WC mapping if needed */ if (wc_mem_map_size) {
nic_data->wc_membase = ioremap_wc(efx->membase_phys +
uc_mem_map_size,
wc_mem_map_size); if (!nic_data->wc_membase) {
netif_err(efx, probe, efx->net_dev, "could not allocate WC mapping of size %x\n",
wc_mem_map_size); return -ENOMEM;
}
nic_data->pio_write_vi_base = pio_write_vi_base;
nic_data->pio_write_base =
nic_data->wc_membase +
(pio_write_vi_base * efx->vi_stride + ER_DZ_TX_PIOBUF -
uc_mem_map_size);
rc = efx_ef10_link_piobufs(efx); if (rc)
efx_ef10_free_piobufs(efx);
}
netif_dbg(efx, probe, efx->net_dev, "memory BAR at %pa (virtual %p+%x UC, %p+%x WC)\n",
&efx->membase_phys, efx->membase, uc_mem_map_size,
nic_data->wc_membase, wc_mem_map_size);
if (nic_data->must_check_datapath_caps) {
rc = efx_ef10_init_datapath_caps(efx); if (rc) return rc;
nic_data->must_check_datapath_caps = false;
}
if (efx->must_realloc_vis) { /* We cannot let the number of VIs change now */
rc = efx_ef10_alloc_vis(efx, nic_data->n_allocated_vis,
nic_data->n_allocated_vis); if (rc) return rc;
efx->must_realloc_vis = false;
}
nic_data->mc_stats = kmalloc(efx->num_mac_stats * sizeof(__le64),
GFP_KERNEL); if (!nic_data->mc_stats) return -ENOMEM;
if (nic_data->must_restore_piobufs && nic_data->n_piobufs) {
rc = efx_ef10_alloc_piobufs(efx, nic_data->n_piobufs); if (rc == 0) {
rc = efx_ef10_link_piobufs(efx); if (rc)
efx_ef10_free_piobufs(efx);
}
/* Log an error on failure, but this is non-fatal. *Permissionerrorsarelessimportant-we'vepresumably *hadthePIObufferlicenceremoved.
*/ if (rc == -EPERM)
netif_dbg(efx, drv, efx->net_dev, "not permitted to restore PIO buffers\n"); elseif (rc)
netif_err(efx, drv, efx->net_dev, "failed to restore PIO buffers (%d)\n", rc);
nic_data->must_restore_piobufs = false;
}
/* encap features might change during reset if fw variant changed */ if (efx_has_cap(efx, VXLAN_NVGRE) && !efx_ef10_is_vf(efx))
net_dev->hw_enc_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; else
net_dev->hw_enc_features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
if (efx_has_cap(efx, TX_TSO_V2_ENCAP)) { /* If this is first nic_init, or if it is a reset and a new fw *varianthasaddednewfeatures,enablethembydefault. *Ifthefeaturesarenotnew,maintaintheircurrentvalue.
*/ if (!(net_dev->hw_features & tun_feats))
net_dev->features |= tun_feats;
net_dev->hw_enc_features |= tun_feats | tso_feats;
net_dev->hw_features |= tun_feats;
} else {
net_dev->hw_enc_features &= ~(tun_feats | tso_feats);
net_dev->hw_features &= ~tun_feats;
net_dev->features &= ~tun_feats;
}
/* don't fail init if RSS setup doesn't work */
rc = efx->type->rx_push_rss_config(efx, false,
efx->rss_context.rx_indir_table, NULL);
/* All our allocations have been reset */
efx->must_realloc_vis = true;
efx_mcdi_filter_table_reset_mc_allocations(efx);
nic_data->must_restore_piobufs = true;
efx_ef10_forget_old_piobufs(efx);
efx->rss_context.priv.context_id = EFX_MCDI_RSS_CONTEXT_INVALID;
/* Driver-created vswitches and vports must be re-created */
nic_data->must_probe_vswitching = true;
efx->vport_id = EVB_PORT_ID_ASSIGNED; #ifdef CONFIG_SFC_SRIOV if (nic_data->vf) for (i = 0; i < efx->vf_count; i++)
nic_data->vf[i].vport_id = 0; #endif
}
/* Unprivileged functions return -EPERM, but need to return success *heresothatthedatapathisbroughtbackup.
*/ if (reset_type == RESET_TYPE_WORLD && rc == -EPERM)
rc = 0;
/* If it was a port reset, trigger reallocation of MC resources. *NotethatonanMCresetnothingneedstobedonenowbecausewe'll *detecttheMCresetlaterandhandleitthen. *ForanFLR,wenevergetanMCresetevent,buttheMChasresetall *resourcesassignedtous,sowehavetotriggerreallocationnow.
*/ if ((reset_type == RESET_TYPE_ALL ||
reset_type == RESET_TYPE_MCDI_TIMEOUT) && !rc)
efx_ef10_table_reset_mc_allocations(efx); return rc;
}
/* On 7000 series NICs, these statistics are only provided by the 10G MAC. *Fora10G/40Gswitchableportwedonotexposethesebecausetheymight *notincludeallthepacketstheyshould. *On8000seriesNICsthesestatisticsarealwaysprovided.
*/ #define HUNT_10G_ONLY_STAT_MASK ((1ULL << EF10_STAT_port_tx_control) | \
(1ULL << EF10_STAT_port_tx_lt64) | \
(1ULL << EF10_STAT_port_tx_64) | \
(1ULL << EF10_STAT_port_tx_65_to_127) |\
(1ULL << EF10_STAT_port_tx_128_to_255) |\
(1ULL << EF10_STAT_port_tx_256_to_511) |\
(1ULL << EF10_STAT_port_tx_512_to_1023) |\
(1ULL << EF10_STAT_port_tx_1024_to_15xx) |\
(1ULL << EF10_STAT_port_tx_15xx_to_jumbo))
/* These statistics are only provided by the 40G MAC. For a 10G/40G *switchableportwedoexposethesebecausetheerrorswillotherwise *besilent.
*/ #define HUNT_40G_EXTRA_STAT_MASK ((1ULL << EF10_STAT_port_rx_align_error) |\
(1ULL << EF10_STAT_port_rx_length_error))
/* Only show vadaptor stats when EVB capability is present */ if (nic_data->datapath_caps &
(1 << MC_CMD_GET_CAPABILITIES_OUT_EVB_LBN)) {
raw_mask[0] |= ~((1ULL << EF10_STAT_rx_unicast) - 1);
raw_mask[1] = (1ULL << (EF10_STAT_V1_COUNT - 64)) - 1;
} else {
raw_mask[1] = 0;
} /* Only show FEC stats when NIC supports MC_CMD_MAC_STATS_V2 */ if (efx->num_mac_stats >= MC_CMD_MAC_NSTATS_V2)
raw_mask[1] |= EF10_FEC_STAT_MASK;
/* CTPIO stats appear in V3. Only show them on devices that actually *supportCTPIO.Althoughthisdriverdoesn'tuseCTPIOothersmight, *andwemaybereportingthestatsfortheunderlyingport.
*/ if (efx->num_mac_stats >= MC_CMD_MAC_NSTATS_V3 &&
(nic_data->datapath_caps2 &
(1 << MC_CMD_GET_CAPABILITIES_V4_OUT_CTPIO_LBN)))
raw_mask[1] |= EF10_CTPIO_STAT_MASK;
/* If NIC was fini'd (probably resetting), then we can't read *updatedstatsrightnow.
*/ if (nic_data->mc_stats) {
efx_nic_copy_stats(efx, nic_data->mc_stats);
efx_nic_update_stats(efx_ef10_stat_desc, EF10_STAT_COUNT,
mask, stats, nic_data->mc_stats, false);
}
/* Update derived statistics */
efx_nic_fix_nodesc_drop_stat(efx,
&stats[EF10_STAT_port_rx_nodesc_drops]); /* MC Firmware reads RX_BYTES and RX_GOOD_BYTES from the MAC. *ItthencalculatesRX_BAD_BYTESandDMAsittouswithRX_BYTES. *Wereporttheseasport_rx_stats.WearenotgivenRX_GOOD_BYTES. *Herewecalculateport_rx_good_bytes.
*/
stats[EF10_STAT_port_rx_good_bytes] =
stats[EF10_STAT_port_rx_bytes] -
stats[EF10_STAT_port_rx_bytes_minus_good_bytes];
/* The asynchronous reads used to calculate RX_BAD_BYTES in *MCFirmwarearedonesuchthatweshouldnotseeanincreasein *RX_BAD_BYTESwhenagoodpackethasarrived.Unfortunatelythis *doesmeanthatthestatcandecreaseattimes.Herewedonot *updatethestatunlessithasincreasedorhasgonetozero *(InthecaseoftheNICrebooting). *PleaseseeBug33781foradiscussionofwhythingsworkthisway.
*/
efx_update_diff_stat(&stats[EF10_STAT_port_rx_bad_bytes],
stats[EF10_STAT_port_rx_bytes_minus_good_bytes]);
efx_update_sw_stats(efx, stats);
rc = efx_mcdi_rpc_quiet(efx, MC_CMD_MAC_STATS, inbuf, sizeof(inbuf),
NULL, 0, NULL);
spin_lock_bh(&efx->stats_lock); if (rc) { /* Expect ENOENT if DMA queues have not been set up */ if (rc != -ENOENT || atomic_read(&efx->active_queues))
efx_mcdi_display_error(efx, MC_CMD_MAC_STATS, sizeof(inbuf), NULL, 0, rc); goto out;
}
/* All our allocations have been reset */
efx_ef10_table_reset_mc_allocations(efx);
/* The datapath firmware might have been changed */
nic_data->must_check_datapath_caps = true;
/* MAC statistics have been cleared on the NIC; clear the local *statisticthatweupdatewithefx_update_diff_stat().
*/
nic_data->stats[EF10_STAT_port_rx_bad_bytes] = 0;
}
rc = efx_ef10_get_warm_boot_count(efx); if (rc < 0) { /* The firmware is presumably in the process of *rebooting.However,wearesupposedtoreporteach *rebootjustonce,sowemustonlydothatoncewe *canreadandstoretheupdatedwarmbootcount.
*/ return0;
}
netif_vdbg(efx, intr, efx->net_dev, "IRQ %d on CPU %d\n", irq, raw_smp_processor_id());
if (likely(READ_ONCE(efx->irq_soft_enabled))) { /* Note test interrupts */ if (context->index == efx->irq_level)
efx->last_irq_cpu = raw_smp_processor_id();
/* Schedule processing of the channel */
efx_schedule_channel_irq(efx->channel[context->index]);
}
staticint efx_ef10_tx_probe(struct efx_tx_queue *tx_queue)
{ /* low two bits of label are what we want for type */
BUILD_BUG_ON((EFX_TXQ_TYPE_OUTER_CSUM | EFX_TXQ_TYPE_INNER_CSUM) != 3);
tx_queue->type = tx_queue->label & 3; return efx_nic_alloc_buffer(tx_queue->efx, &tx_queue->txd,
(tx_queue->ptr_mask + 1) * sizeof(efx_qword_t),
GFP_KERNEL);
}
/* This writes to the TX_DESC_WPTR and also pushes data */ staticinlinevoid efx_ef10_push_tx_desc(struct efx_tx_queue *tx_queue, const efx_qword_t *txd)
{ unsignedint write_ptr;
efx_oword_t reg;
/* Only attempt to enable TX timestamping if we have the license for it, *otherwiseTXQinitwillfail
*/ if (!(nic_data->licensed_features &
(1 << LICENSED_V3_FEATURES_TX_TIMESTAMPS_LBN))) {
tx_queue->timestamping = false; /* Disable sync events on this channel. */ if (efx->type->ptp_set_ts_sync_events)
efx->type->ptp_set_ts_sync_events(efx, false, false);
}
/* TSOv2 is a limited resource that can only be configured on a limited *numberofqueues.TSOwithoutchecksumoffloadisnotreallyathing, *soweonlyenableitforthosequeues. *TSOv2cannotbeusedwithHardwaretimestamping,andisneverneeded *forXDPtx.
*/ if (efx_has_cap(efx, TX_TSO_V2)) { if ((csum_offload || inner_csum) &&
!tx_queue->timestamping && !tx_queue->xdp_tx) {
tx_queue->tso_version = 2;
netif_dbg(efx, hw, efx->net_dev, "Using TSOv2 for channel %u\n",
channel->channel);
}
} elseif (efx_has_cap(efx, TX_TSO)) {
tx_queue->tso_version = 1;
}
rc = efx_mcdi_tx_init(tx_queue); if (rc) goto fail;
/* A previous user of this TX queue might have set us up the *bombbywritingadescriptortotheTXpushcollectorbut *notthedoorbell.(Eachcollectorbelongstoaport,nota *queueorfunction,socannoteasilybereset.)Wemust *attempttopushano-opdescriptorinitsplace.
*/
tx_queue->buffer[0].flags = EFX_TX_BUF_OPTION;
tx_queue->insert_count = 1;
txd = efx_tx_desc(tx_queue, 0);
EFX_POPULATE_QWORD_7(*txd,
ESF_DZ_TX_DESC_IS_OPT, true,
ESF_DZ_TX_OPTION_TYPE,
ESE_DZ_TX_OPTION_DESC_CRC_CSUM,
ESF_DZ_TX_OPTION_UDP_TCP_CSUM, csum_offload,
ESF_DZ_TX_OPTION_IP_CSUM, csum_offload && tx_queue->tso_version != 2,
ESF_DZ_TX_OPTION_INNER_UDP_TCP_CSUM, inner_csum,
ESF_DZ_TX_OPTION_INNER_IP_CSUM, inner_csum && tx_queue->tso_version != 2,
ESF_DZ_TX_TIMESTAMP, tx_queue->timestamping);
tx_queue->write_count = 1;
if (tx_queue->tso_version == 2 && efx_has_cap(efx, TX_TSO_V2_ENCAP))
tx_queue->tso_encap = true;
wmb();
efx_ef10_push_tx_desc(tx_queue, txd);
return;
fail:
netdev_WARN(efx->net_dev, "failed to initialise TXQ %d\n",
tx_queue->queue);
}
/* This writes to the TX_DESC_WPTR; write pointer for TX descriptor ring */ staticinlinevoid efx_ef10_notify_tx_desc(struct efx_tx_queue *tx_queue)
{ unsignedint write_ptr;
efx_dword_t reg;
staticunsignedint efx_ef10_tx_limit_len(struct efx_tx_queue *tx_queue,
dma_addr_t dma_addr, unsignedint len)
{ if (len > EFX_EF10_MAX_TX_DESCRIPTOR_LEN) { /* If we need to break across multiple descriptors we should *stopatapageboundary.Thisassumesthelengthlimitis *greaterthanthepagesize.
*/
dma_addr_t end = dma_addr + EFX_EF10_MAX_TX_DESCRIPTOR_LEN;
rc = efx_mcdi_get_workarounds(efx, &implemented, &enabled); if (rc == -ENOSYS) { /* GET_WORKAROUNDS was implemented before this workaround, *thusitmustbeunavailableinthisfirmware.
*/
nic_data->workaround_26807 = false; return0;
} if (rc) return rc;
want_workaround_26807 =
implemented & MC_CMD_GET_WORKAROUNDS_OUT_BUG26807;
nic_data->workaround_26807 =
!!(enabled & MC_CMD_GET_WORKAROUNDS_OUT_BUG26807);
if (want_workaround_26807 && !nic_data->workaround_26807) { unsignedint flags;
rc = efx_mcdi_set_workaround(efx,
MC_CMD_WORKAROUND_BUG26807, true, &flags); if (!rc) { if (flags & 1 << MC_CMD_WORKAROUND_EXT_OUT_FLR_DONE_LBN) {
netif_info(efx, drv, efx->net_dev, "other functions on NIC have been reset\n");
/* Firmware requires that RX_DESC_WPTR be a multiple of 8 */
write_count = rx_queue->added_count & ~7; if (rx_queue->notified_count == write_count) return;
do
efx_ef10_build_rx_desc(
rx_queue,
rx_queue->notified_count & rx_queue->ptr_mask); while (++rx_queue->notified_count != write_count);
/* MCDI_SET_QWORD is not appropriate here since EFX_POPULATE_* has *alreadyswappedthedatatolittle-endianorder.
*/
memcpy(MCDI_PTR(inbuf, DRIVER_EVENT_IN_DATA), &event.u64[0], sizeof(efx_qword_t));
/* MCDI_SET_QWORD is not appropriate here since EFX_POPULATE_* has *alreadyswappedthedatatolittle-endianorder.
*/
memcpy(MCDI_PTR(inbuf, DRIVER_EVENT_IN_DATA), &event.u64[0], sizeof(efx_qword_t));
#ifdef CONFIG_SFC_SRIOV /* If this function is a VF and we have access to the parent PF, *thenusethePFcontrolpathtoattempttochangetheVFMACaddress.
*/ if (efx->pci_dev->is_virtfn && efx->pci_dev->physfn) { struct efx_nic *efx_pf = pci_get_drvdata(efx->pci_dev->physfn); struct efx_ef10_nic_data *nic_data = efx->nic_data;
u8 mac[ETH_ALEN];
/* net_dev->dev_addr can be zeroed by efx_net_stop in *efx_ef10_sriov_set_vf_mac,sopassinacopy.
*/
ether_addr_copy(mac, efx->net_dev->dev_addr);
rc = efx_ef10_sriov_set_vf_mac(efx_pf, nic_data->vf_index, mac); if (!rc) return0;
netif_dbg(efx, drv, efx->net_dev, "Updating VF mac via PF failed (%d), setting directly\n",
rc);
} #endif
if (was_enabled)
efx_net_open(efx->net_dev);
efx_device_attach_if_not_resetting(efx);
if (rc == -EPERM) {
netif_err(efx, drv, efx->net_dev, "Cannot change MAC address; use sfboot to enable" " mac-spoofing on this interface\n");
} elseif (rc == -ENOSYS && !efx_ef10_is_vf(efx)) { /* If the active MCFW does not support MC_CMD_VADAPTOR_SET_MAC *fall-backtothemethodofchangingtheMACaddressonthe *vport.ThisonlyappliestoPFsbecausesuchversionsof *MCFWdonotsupportVFs.
*/
rc = efx_ef10_vport_set_mac_address(efx);
} elseif (rc) {
efx_mcdi_display_error(efx, MC_CMD_VADAPTOR_SET_MAC, sizeof(inbuf), NULL, 0, rc);
}
for (type_idx = 0; ; type_idx++) { if (type_idx == EF10_NVRAM_PARTITION_COUNT) return -ENODEV;
info = efx_ef10_nvram_types + type_idx; if ((type & ~info->type_mask) == info->type) break;
} if (info->port != efx_port_num(efx)) return -ENODEV;
rc = efx_mcdi_nvram_info(efx, type, &size, &erase_size, &write_size,
&protected); if (rc) return rc; if (protected &&
(type != NVRAM_PARTITION_TYPE_DYNCONFIG_DEFAULTS &&
type != NVRAM_PARTITION_TYPE_ROMCONFIG_DEFAULTS)) /* Hide protected partitions that don't provide defaults. */ return -ENODEV;
if (protected) /* Protected partitions are read only. */
erase_size = 0;
/* If we've already exposed a partition of this type, hide this *duplicate.AlloperationsonMTDsarekeyedbythetypeanyway, *sowecan'tactontheduplicate.
*/ if (__test_and_set_bit(type_idx, found)) return -EEXIST;
staticint efx_ef10_ptp_set_ts_config(struct efx_nic *efx, struct kernel_hwtstamp_config *init)
{ int rc;
switch (init->rx_filter) { case HWTSTAMP_FILTER_NONE:
efx_ef10_ptp_set_ts_sync_events(efx, false, false); /* if TX timestamping is still requested then leave PTP on */ return efx_ptp_change_mode(efx,
init->tx_type != HWTSTAMP_TX_OFF, 0); case HWTSTAMP_FILTER_ALL: case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: case HWTSTAMP_FILTER_PTP_V2_EVENT: case HWTSTAMP_FILTER_PTP_V2_SYNC: case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: case HWTSTAMP_FILTER_NTP_ALL:
init->rx_filter = HWTSTAMP_FILTER_ALL;
rc = efx_ptp_change_mode(efx, true, 0); if (!rc)
rc = efx_ef10_ptp_set_ts_sync_events(efx, true, false); if (rc)
efx_ptp_change_mode(efx, false, 0); return rc; default: return -ERANGE;
}
}
staticint efx_ef10_vlan_rx_add_vid(struct efx_nic *efx, __be16 proto, u16 vid)
{ if (proto != htons(ETH_P_8021Q)) return -EINVAL;
return efx_ef10_add_vlan(efx, vid);
}
staticint efx_ef10_vlan_rx_kill_vid(struct efx_nic *efx, __be16 proto, u16 vid)
{ if (proto != htons(ETH_P_8021Q)) return -EINVAL;
return efx_ef10_del_vlan(efx, vid);
}
/* We rely on the MCDI wiping out our TX rings if it made any changes to the *portstable,ensuringthatanyTSOdescriptorsthatweremadeonanow- *removedtunnelportwillbeblownawayandwon'tbreakthingswhenwetry *totransmitthemusingthenewportstable.
*/ staticint efx_ef10_set_udp_tnl_ports(struct efx_nic *efx, bool unloading)
{ struct efx_ef10_nic_data *nic_data = efx->nic_data;
MCDI_DECLARE_BUF(inbuf, MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_IN_LENMAX);
MCDI_DECLARE_BUF(outbuf, MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_OUT_LEN); bool will_reset = false;
size_t num_entries = 0;
size_t inlen, outlen;
size_t i; int rc;
efx_dword_t flags_and_num_entries;
for (i = 0; i < ARRAY_SIZE(nic_data->udp_tunnels); ++i) { if (nic_data->udp_tunnels[i].type !=
TUNNEL_ENCAP_UDP_PORT_ENTRY_INVALID) {
efx_dword_t entry;
rc = efx_mcdi_rpc_quiet(efx, MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS,
inbuf, inlen, outbuf, sizeof(outbuf), &outlen); if (rc == -EIO) { /* Most likely the MC rebooted due to another function also *settingitstunnelportlist.Markthetunnelportlistas *dirty,soitwillbepusheduponcomingupfromthereboot.
*/
nic_data->udp_tunnels_dirty = true; return0;
}
if (rc) { /* expected not available on unprivileged functions */ if (rc != -EPERM)
netif_warn(efx, drv, efx->net_dev, "Unable to set UDP tunnel ports; rc=%d.\n", rc);
} elseif (MCDI_DWORD(outbuf, SET_TUNNEL_ENCAP_UDP_PORTS_OUT_FLAGS) &
(1 << MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_OUT_RESETTING_LBN)) {
netif_info(efx, drv, efx->net_dev, "Rebooting MC due to UDP tunnel port list change\n");
will_reset = true; if (unloading) /* Delay for the MC reset to complete. This will make *unloadingotherfunctionsabitsmoother.Thisisa *race,buttheotherunloadwillworkwhicheverway *itgoes,thisjustavoidsanunnecessaryerror *message.
*/
msleep(100);
} if (!will_reset && !unloading) { /* The caller will have detached, relying on the MC reset to *triggerare-attach.Sincetherewon'tbeanMCreset,we *havetodotheattachourselves.
*/
efx_device_attach_if_not_resetting(efx);
}
mutex_lock(&nic_data->udp_tunnels_lock); if (nic_data->udp_tunnels_dirty) { /* Make sure all TX are stopped while we modify the table, else *wemightraceagainstanefx_features_check().
*/
efx_device_detach_sync(efx);
rc = efx_ef10_set_udp_tnl_ports(efx, false);
}
mutex_unlock(&nic_data->udp_tunnels_lock); return rc;
}
mutex_lock(&nic_data->udp_tunnels_lock); /* Make sure all TX are stopped while we add to the table, else we *mightraceagainstanefx_features_check().
*/
efx_device_detach_sync(efx);
nic_data->udp_tunnels[entry].type = efx_tunnel_type;
nic_data->udp_tunnels[entry].port = ti->port;
rc = efx_ef10_set_udp_tnl_ports(efx, false);
mutex_unlock(&nic_data->udp_tunnels_lock);
return rc;
}
/* Called under the TX lock with the TX queue running, hence no-one can be *inthemiddleofupdatingtheUDPtunnelstable.However,theycould *havetriedandfailedtheMCDI,inwhichcasethey'llhavesetthedirty *flagbeforedroppingtheirlocks.
*/ staticbool efx_ef10_udp_tnl_has_port(struct efx_nic *efx, __be16 port)
{ struct efx_ef10_nic_data *nic_data = efx->nic_data;
size_t i;
if (!(nic_data->datapath_caps &
(1 << MC_CMD_GET_CAPABILITIES_OUT_VXLAN_NVGRE_LBN))) returnfalse;
if (nic_data->udp_tunnels_dirty) /* SW table may not match HW state, so just assume we can't *useanyUDPtunneloffloads.
*/ returnfalse;
for (i = 0; i < ARRAY_SIZE(nic_data->udp_tunnels); ++i) if (nic_data->udp_tunnels[i].type !=
TUNNEL_ENCAP_UDP_PORT_ENTRY_INVALID &&
nic_data->udp_tunnels[i].port == port) returntrue;
mutex_lock(&nic_data->udp_tunnels_lock); /* Make sure all TX are stopped while we remove from the table, else we *mightraceagainstanefx_features_check().
*/
efx_device_detach_sync(efx);
nic_data->udp_tunnels[entry].type = TUNNEL_ENCAP_UDP_PORT_ENTRY_INVALID;
nic_data->udp_tunnels[entry].port = 0;
rc = efx_ef10_set_udp_tnl_ports(efx, false);
mutex_unlock(&nic_data->udp_tunnels_lock);
staticunsignedint efx_ef10_recycle_ring_size(conststruct efx_nic *efx)
{ unsignedint ret = EFX_RECYCLE_RING_SIZE_10G;
/* There is no difference between PFs and VFs. The side is based on *themaximumlinkspeedofagivenNIC.
*/ switch (efx->pci_dev->device & 0xfff) { case0x0903: /* Farmingdale can do up to 10G */ break; case0x0923: /* Greenport can do up to 40G */ case0x0a03: /* Medford can do up to 40G */
ret *= 4; break; default: /* Medford2 can do up to 100G */
ret *= 10;
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.153Bemerkung:
(vorverarbeitet am 2026-09-28)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.