/* Reset workqueue. If any NIC has a hardware failure then a reset will be *queuedontothisworkqueue.Thisisnotaper-nicworkqueue,because *ef4_reset_work()acquiresthertnllock,soresetsarenaturallyserialised.
*/ staticstruct workqueue_struct *reset_workqueue;
/* How often and how many times to poll for a reset while waiting for a *BISTthatanotherfunctionstartedtocomplete.
*/ #define BIST_WAIT_DELAY_MS 100 #define BIST_WAIT_DELAY_COUNT 100
/* *UseseparatechannelsforTXandRXevents * *Setthisto1touseseparatechannelsforTXandRX.Itallowsus *tocontrolinterruptaffinityseparatelyforTXandRX. * *ThisisonlyusedinMSI-Xinterruptmode
*/ bool ef4_separate_tx_channels;
module_param(ef4_separate_tx_channels, bool, 0444);
MODULE_PARM_DESC(ef4_separate_tx_channels, "Use separate channels for TX and RX");
/* This is the time (in jiffies) between invocations of the hardware *monitor. *OnFalcon-basedNICs,thiswill: *-Checktheon-boardhardwaremonitor; *-Pollthelinkstateandreconfigurethehardwareasnecessary. *OnSiena-basedNICsforpowersystemswithEEHsupport,thiswillgiveEEHa *chancetostart.
*/ staticunsignedint ef4_monitor_interval = 1 * HZ;
/* Initial interrupt moderation settings. They can be modified after *moduleloadwithethtool. * *ThedefaultforRXshouldstrikeabalancebetweenincreasingthe *round-triplatencyandreducingoverhead.
*/ staticunsignedint rx_irq_mod_usec = 60;
/* Initial interrupt moderation settings. They can be modified after *moduleloadwithethtool. * *Thisdefaultischosentoensurethata10Glinkdoesnotgoidle *whileaTXqueueisstoppedafterithasbecomefull.Aqueueis *restartedwhenitdropsbelowhalffull.Thetimethistakes(assuming *worstcase3descriptorsperpacketand1024descriptors)is *512/3*1.2=205usec.
*/ staticunsignedint tx_irq_mod_usec = 150;
/* This is the first interrupt mode to try out of: *0=>MSI-X *1=>MSI *2=>legacy
*/ staticunsignedint interrupt_mode;
/* This is the requested number of CPUs to use for Receive-Side Scaling (RSS), *i.e.thenumberofCPUsamongwhichwemaydistributesimultaneous *interrupthandling. * *CardswithoutMSI-XwillonlytargetoneCPUvialegacyorMSIinterrupt. *Thedefault(0)meanstoassignaninterrupttoeachcore.
*/ staticunsignedint rss_cpus;
module_param(rss_cpus, uint, 0444);
MODULE_PARM_DESC(rss_cpus, "Number of CPUs to use for Receive-Side Scaling");
netif_vdbg(efx, intr, efx->net_dev, "channel %d NAPI poll executing on CPU %d\n",
channel->channel, raw_smp_processor_id());
spent = ef4_process_channel(channel, budget);
if (spent < budget) { if (ef4_channel_has_rx_queue(channel) &&
efx->irq_rx_adaptive &&
unlikely(++channel->irq_count == 1000)) {
ef4_update_irq_mod(efx, channel);
}
ef4_filter_rfs_expire(channel);
/* There is no race here; although napi_disable() will *onlywaitfornapi_complete(),thisisn'taproblem *sinceef4_nic_eventq_read_ack()willhavenoeffectif *interruptshavealreadybeendisabled.
*/
napi_complete_done(napi, spent);
ef4_nic_eventq_read_ack(channel);
}
/* Build an event queue with room for one event per tx and rx buffer,
* plus some extra for link state events and MCDI completions. */
entries = roundup_pow_of_two(efx->rxq_entries + efx->txq_entries + 128);
EF4_BUG_ON_PARANOID(entries > EF4_MAX_EVQ_SIZE);
channel->eventq_mask = max(entries, EF4_MIN_EVQ_SIZE) - 1;
/* Restore previously fixed features in hw_features and remove *featureswhicharefixednow
*/
efx->net_dev->hw_features |= efx->net_dev->features;
efx->net_dev->hw_features &= ~efx->fixed_features;
efx->net_dev->features |= efx->fixed_features; if (efx->net_dev->features != old_features)
netdev_features_change(efx->net_dev);
/* RX filters may also have scatter-enabled flags */ if (efx->rx_scatter != old_rx_scatter)
efx->type->filter_update_rx_scatter(efx);
/* We must keep at least one descriptor in a TX ring empty. *Wecouldavoidthiswhenthequeuesizedoesnotexactly *matchthehardwareringsize,butit'snotthatimportant. *Thereforewestopthequeuewhenonemoreskbmightfill *theringcompletely.Wewakeitwhenhalfwaybackto *empty.
*/
efx->txq_stop_thresh = efx->txq_entries - ef4_tx_max_skb_descs(efx);
efx->txq_wake_thresh = efx->txq_stop_thresh / 2;
ef4_for_each_channel(channel, efx) { /* RX packet processing is pipelined, so wait for the *NAPIhandlertocomplete.Atleasteventqueue0 *mightbekeptactivebynon-dataevents,sodon't *usenapi_synchronize()butactuallydisableNAPI *temporarily.
*/ if (ef4_channel_has_rx_queue(channel)) {
ef4_stop_eventq(channel);
ef4_start_eventq(channel);
}
}
rc = efx->type->fini_dmaq(efx); if (rc && EF4_WORKAROUND_7803(efx)) { /* Schedule a reset to recover from the flush failure. The *descriptorcachesreferencememorywe'reabouttofree, *butfalcon_reconfigure_mac_wrapper()won'treconnect *theMACsbecauseofthependingreset.
*/
netif_err(efx, drv, efx->net_dev, "Resetting to recover from flush failure\n");
ef4_schedule_reset(efx, RESET_TYPE_ALL);
} elseif (rc) {
netif_err(efx, drv, efx->net_dev, "failed to flush queues\n");
} else {
netif_dbg(efx, drv, efx->net_dev, "successfully flushed all queues\n");
}
int
ef4_realloc_channels(struct ef4_nic *efx, u32 rxq_entries, u32 txq_entries)
{ struct ef4_channel *other_channel[EF4_MAX_CHANNELS], *channel;
u32 old_rxq_entries, old_txq_entries; unsigned i, next_buffer_table = 0; int rc, rc2;
rc = ef4_check_disabled(efx); if (rc) return rc;
/* Not all channels should be reallocated. We must avoid *reallocatingtheirbuffertableentries.
*/
ef4_for_each_channel(channel, efx) { struct ef4_rx_queue *rx_queue; struct ef4_tx_queue *tx_queue;
for (i = 0; i < efx->n_channels; i++) {
channel = efx->channel[i]; if (!channel->type->copy) continue;
rc = ef4_probe_channel(channel); if (rc) goto rollback;
ef4_init_napi_channel(efx->channel[i]);
}
out: /* Destroy unused channel structures */ for (i = 0; i < efx->n_channels; i++) {
channel = other_channel[i]; if (channel && channel->type->copy) {
ef4_fini_napi_channel(channel);
ef4_remove_channel(channel);
kfree(channel);
}
}
/* This ensures that the kernel is kept informed (via *netif_carrier_on/off)ofthelinkstatus,andalsomaintainsthe *linkstatus'sstopontheport'sTXqueue.
*/ void ef4_link_status_changed(struct ef4_nic *efx)
{ struct ef4_link_state *link_state = &efx->link_state;
/* SFC Bug 5356: A net_dev notifier is registered, so we must ensure *thatnoeventsaretriggeredbetweenunregister_netdev()andthe *driverunloading.AmoregeneralconditionisthatNETDEV_CHANGE
* can only be generated between NETDEV_UP and NETDEV_DOWN */ if (!netif_running(efx->net_dev)) return;
if (link_state->up != netif_carrier_ok(efx->net_dev)) {
efx->n_link_state_changes++;
if (link_state->up)
netif_carrier_on(efx->net_dev); else
netif_carrier_off(efx->net_dev);
}
/* Status message for kernel log */ if (link_state->up)
netif_info(efx, link, efx->net_dev, "link up at %uMbps %s-duplex (MTU %d)\n",
link_state->speed, link_state->fd ? "full" : "half",
efx->net_dev->mtu); else
netif_info(efx, link, efx->net_dev, "link down\n");
}
if (count > EF4_MAX_RX_QUEUES) {
netif_cond_dbg(efx, probe, efx->net_dev, !rss_cpus, warn, "Reducing number of rx queues from %u to %u.\n",
count, EF4_MAX_RX_QUEUES);
count = EF4_MAX_RX_QUEUES;
}
return count;
}
/* Probe the number and type of interrupts we are able to obtain, and *theresultingnumbersofchannelsandRXqueues.
*/ staticint ef4_probe_interrupts(struct ef4_nic *efx)
{ unsignedint extra_channels = 0; unsignedint i, j; int rc;
for (i = 0; i < EF4_MAX_EXTRA_CHANNELS; i++) if (efx->extra_channel_type[i])
++extra_channels;
if (efx->interrupt_mode == EF4_INT_MODE_MSIX) { struct msix_entry xentries[EF4_MAX_CHANNELS]; unsignedint n_channels;
/* We need to mark which channels really have RX and TX *queues,andadjusttheTXqueuenumbersifwehaveseparate *RX-onlyandTX-onlychannels.
*/
ef4_for_each_channel(channel, efx) { if (channel->channel < efx->n_rx_channels)
channel->rx_queue.core_index = channel->channel; else
channel->rx_queue.core_index = -1;
/* If the interface is supposed to be running but is not, start *thehardwareandsoftwaredatapath,regularactivityfortheport *(MACstatistics,linkpolling,etc.)andscheduletheporttobe *reconfigured.Interruptsmustalreadybeenabled.Thisfunction *issafetocallmultipletimes,solongastheNICisnotdisabled. *RequirestheRTNLlock.
*/ staticvoid ef4_start_all(struct ef4_nic *efx)
{
EF4_ASSERT_RESET_SERIALISED(efx);
BUG_ON(efx->state == STATE_DISABLED);
/* Check that it is appropriate to restart the interface. All
* of these flags are safe to read under just the rtnl lock */ if (efx->port_enabled || !netif_running(efx->net_dev) ||
efx->reset_pending) return;
ef4_start_port(efx);
ef4_start_datapath(efx);
/* Start the hardware monitor if there is one */ if (efx->type->monitor != NULL)
queue_delayed_work(efx->workqueue, &efx->monitor_work,
ef4_monitor_interval);
/* Quiesce the hardware and software data path, and regular activity *fortheportwithoutbringingthelinkdown.Safetocallmultiple *timeswiththeNICinalmostanystate,butinterruptsshouldbe *enabled.RequirestheRTNLlock.
*/ staticvoid ef4_stop_all(struct ef4_nic *efx)
{
EF4_ASSERT_RESET_SERIALISED(efx);
/* port_enabled can be read safely under the rtnl lock */ if (!efx->port_enabled) return;
/* update stats before we go down so we can accurately count *rx_nodesc_drops
*/
efx->type->pull_stats(efx);
spin_lock_bh(&efx->stats_lock);
efx->type->update_stats(efx, NULL, NULL);
spin_unlock_bh(&efx->stats_lock);
efx->type->stop_stats(efx);
ef4_stop_port(efx);
/* Stop the kernel transmit interface. This is only valid if *thedeviceisstoppedordetached;otherwisethewatchdog *mayfireimmediately.
*/
WARN_ON(netif_running(efx->net_dev) &&
netif_device_present(efx->net_dev));
netif_tx_disable(efx->net_dev);
/* If channels are shared between RX and TX, so is IRQ *moderation.Otherwise,IRQmoderationisthesameforall *TXchannelsandisnotadaptive.
*/ if (efx->tx_channel_offset == 0) {
*tx_usecs = *rx_usecs;
} else { struct ef4_channel *tx_channel;
/* Run periodically off the general workqueue */ staticvoid ef4_monitor(struct work_struct *data)
{ struct ef4_nic *efx = container_of(data, struct ef4_nic,
monitor_work.work);
netif_vdbg(efx, timer, efx->net_dev, "hardware monitor executing on CPU %d\n",
raw_smp_processor_id());
BUG_ON(efx->type->monitor == NULL);
/* If the mac_lock is already held then it is likely a port *reconfigurationisalreadyinplace,whichwilllikelydo
* most of the work of monitor() anyway. */ if (mutex_trylock(&efx->mac_lock)) { if (efx->port_enabled)
efx->type->monitor(efx);
mutex_unlock(&efx->mac_lock);
}
/* If disabling RX n-tuple filtering, clear existing filters */ if (net_dev->features & ~data & NETIF_F_NTUPLE) {
rc = efx->type->filter_clear_rx(efx, EF4_FILTER_PRI_MANUAL); if (rc) return rc;
}
/* If Rx VLAN filter is changed, update filters via mac_reconfigure */ if ((net_dev->features ^ data) & NETIF_F_HW_VLAN_CTAG_FILTER) { /* ef4_set_rx_mode() will schedule MAC work to update filters *whenanewfeaturesarefinallysetinnet_dev.
*/
ef4_set_rx_mode(net_dev);
}
/* Enable resets to be scheduled and check whether any were *alreadyrequested.Ifso,theNICisprobablyhosedsowe *abort.
*/
efx->state = STATE_READY;
smp_mb(); /* ensure we change state before checking reset_pending */ if (efx->reset_pending) {
netif_err(efx, probe, efx->net_dev, "aborting probe due to scheduled reset\n");
rc = -EIO; goto fail_locked;
}
rc = device_create_file(&efx->pci_dev->dev, &dev_attr_phy_type); if (rc) {
netif_err(efx, drv, efx->net_dev, "failed to init net dev attributes\n"); goto fail_registered;
} return0;
fail_registered:
rtnl_lock();
ef4_dissociate(efx);
unregister_netdevice(net_dev);
fail_locked:
efx->state = STATE_UNINIT;
rtnl_unlock();
netif_err(efx, drv, efx->net_dev, "could not register net dev\n"); return rc;
}
staticvoid ef4_unregister_netdev(struct ef4_nic *efx)
{ if (!efx->net_dev) return;
/* Tears down the entire software state and most of the hardware state
* before reset. */ void ef4_reset_down(struct ef4_nic *efx, enum reset_type method)
{
EF4_ASSERT_RESET_SERIALISED(efx);
/* This function will always ensure that the locks acquired in *ef4_reset_down()arereleased.Afailurereturncodeindicates *thatwewereunabletoreinitialisethehardware,andthe *drivershouldbedisabled.Ifokisfalse,thentherxandtx
* engines are not restarted, pending a RESET_DISABLE. */ int ef4_reset_up(struct ef4_nic *efx, enum reset_type method, bool ok)
{ int rc;
EF4_ASSERT_RESET_SERIALISED(efx);
/* Ensure that SRAM is initialised even if we're disabling the device */
rc = efx->type->init(efx); if (rc) {
netif_err(efx, drv, efx->net_dev, "failed to initialise NIC\n"); goto fail;
}
if (!ok) goto fail;
if (efx->port_initialized && method != RESET_TYPE_INVISIBLE &&
method != RESET_TYPE_DATAPATH) {
rc = efx->phy_op->init(efx); if (rc) goto fail;
rc = efx->phy_op->reconfigure(efx); if (rc && rc != -EPERM)
netif_err(efx, drv, efx->net_dev, "could not restore PHY settings\n");
}
rc = ef4_enable_interrupts(efx); if (rc) goto fail;
/* Reset the NIC using the specified method. Note that the reset may *fail,inwhichcasethecardwillbeleftinanunusablestate. * *Callermustholdthertnl_lock.
*/ int ef4_reset(struct ef4_nic *efx, enum reset_type method)
{ int rc, rc2; bool disabled;
rc = efx->type->reset(efx, method); if (rc) {
netif_err(efx, drv, efx->net_dev, "failed to reset hardware\n"); goto out;
}
/* Clear flags for the scopes we covered. We assume the NIC and *driverarenowquiescentsothatthereisnoracehere.
*/ if (method < RESET_TYPE_MAX_METHOD)
efx->reset_pending &= -(1 << (method + 1)); else/* it doesn't fit into the well-ordered scope hierarchy */
__clear_bit(method, &efx->reset_pending);
/* Reinitialise bus-mastering, which may have been turned off before *theresetwasscheduled.Thisisstillappropriate,eveninthe *RESET_TYPE_DISABLEsincethisdrivergenerallyassumesthehardware
* can respond to requests. */
pci_set_master(efx->pci_dev);
/* Try recovery mechanisms. *FornowonlyEEHissupported. *Returns0iftherecoverymechanismsareunsuccessful. *Returnsanon-zerovalueotherwise.
*/ int ef4_try_recovery(struct ef4_nic *efx)
{ #ifdef CONFIG_EEH /* A PCI error can occur and not be seen by EEH because nothing *happensonthePCIbus.Inthiscasethedrivermayfailand *schedulea'recoverorreset',leadingtothisrecoveryhandler. *Manuallycalltheeehfailurecheckfunction.
*/ struct eeh_dev *eehdev = pci_dev_to_eeh_dev(efx->pci_dev); if (eeh_dev_check_failure(eehdev)) { /* The EEH mechanisms will handle the error and reset the *deviceifnecessary.
*/ return1;
} #endif return0;
}
/* The worker thread exists so that code that cannot sleep can *schedulearesetforlater.
*/ staticvoid ef4_reset_work(struct work_struct *data)
{ struct ef4_nic *efx = container_of(data, struct ef4_nic, reset_work); unsignedlong pending; enum reset_type method;
/* We checked the state in ef4_schedule_reset() but it may *havechangedbynow.NowthatwehavetheRTNLlock, *itcannotchangeagain.
*/ if (efx->state == STATE_READY)
(void)ef4_reset(efx, method);
switch (type) { case RESET_TYPE_INVISIBLE: case RESET_TYPE_ALL: case RESET_TYPE_RECOVER_OR_ALL: case RESET_TYPE_WORLD: case RESET_TYPE_DISABLE: case RESET_TYPE_RECOVER_OR_DISABLE: case RESET_TYPE_DATAPATH:
method = type;
netif_dbg(efx, drv, efx->net_dev, "scheduling %s reset\n",
RESET_TYPE(method)); break; default:
method = efx->type->map_reset_reason(type);
netif_dbg(efx, drv, efx->net_dev, "scheduling %s reset for %s\n",
RESET_TYPE(method), RESET_TYPE(type)); break;
}
set_bit(method, &efx->reset_pending);
smp_mb(); /* ensure we change reset_pending before checking state */
/* If we're not READY then just leave the flags set as the cue *toabortprobingorrescheduletheresetlater.
*/ if (READ_ONCE(efx->state) != STATE_READY) return;
/* This zeroes out and then fills in the invariants in a struct *ef4_nic(includingallsub-structures).
*/ staticint ef4_init_struct(struct ef4_nic *efx, struct pci_dev *pci_dev, struct net_device *net_dev)
{ int i;
for (i = 0; i < EF4_MAX_CHANNELS; i++) {
efx->channel[i] = ef4_alloc_channel(efx, i, NULL); if (!efx->channel[i]) goto fail;
efx->msi_context[i].efx = efx;
efx->msi_context[i].index = i;
}
/* Higher numbered interrupt modes are less capable! */
efx->interrupt_mode = max(efx->type->max_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",
pci_name(pci_dev));
efx->workqueue = create_singlethread_workqueue(efx->workqueue_name); if (!efx->workqueue) goto fail;
return0;
fail:
ef4_fini_struct(efx); return -ENOMEM;
}
staticvoid ef4_fini_struct(struct ef4_nic *efx)
{ int i;
for (i = 0; i < EF4_MAX_CHANNELS; i++)
kfree(efx->channel[i]);
kfree(efx->vpd_sn);
if (efx->workqueue) {
destroy_workqueue(efx->workqueue);
efx->workqueue = NULL;
}
}
/* Main body of final NIC shutdown code *Thisiscalledonlyatmoduleunload(orhotplugremoval).
*/ staticvoid ef4_pci_remove_main(struct ef4_nic *efx)
{ /* Flush reset_work. It can no longer be scheduled since we *arenotREADY.
*/
BUG_ON(efx->state == STATE_READY);
cancel_work_sync(&efx->reset_work);
/* Final NIC shutdown *Thisiscalledonlyatmoduleunload(orhotplugremoval).APFcancall *thisonitsVFstoensuretheyareunboundfirst.
*/ staticvoid ef4_pci_remove(struct pci_dev *pci_dev)
{ struct ef4_nic *efx;
efx = pci_get_drvdata(pci_dev); if (!efx) return;
/* Mark the NIC as fini, then stop the interface */
rtnl_lock();
ef4_dissociate(efx);
dev_close(efx->net_dev);
ef4_disable_interrupts(efx);
efx->state = STATE_UNINIT;
rtnl_unlock();
/* NIC VPD information *CalledduringprobetodisplaythepartnumberoftheinstalledNIC.
*/ staticvoid ef4_probe_vpd_strings(struct ef4_nic *efx)
{ struct pci_dev *dev = efx->pci_dev; unsignedint vpd_size, kw_len;
u8 *vpd_data; int start;
vpd_data = pci_vpd_alloc(dev, &vpd_size); if (IS_ERR(vpd_data)) {
pci_warn(dev, "Unable to read VPD\n"); return;
}
start = pci_vpd_find_ro_info_keyword(vpd_data, vpd_size,
PCI_VPD_RO_KEYWORD_PARTNO, &kw_len); if (start < 0)
pci_warn(dev, "Part number not found or incomplete\n"); else
pci_info(dev, "Part Number : %.*s\n", kw_len, vpd_data + start);
start = pci_vpd_find_ro_info_keyword(vpd_data, vpd_size,
PCI_VPD_RO_KEYWORD_SERIALNO, &kw_len); if (start < 0)
pci_warn(dev, "Serial number not found or incomplete\n"); else
efx->vpd_sn = kmemdup_nul(vpd_data + start, kw_len, GFP_KERNEL);
kfree(vpd_data);
}
/* Main body of NIC initialisation *Thisiscalledatmoduleload(orhotpluginsertion,theoretically).
*/ staticint ef4_pci_probe_main(struct ef4_nic *efx)
{ int rc;
/* Do start-of-day initialisation */
rc = ef4_probe_all(efx); if (rc) goto fail1;
ef4_init_napi(efx);
rc = efx->type->init(efx); if (rc) {
netif_err(efx, probe, efx->net_dev, "failed to initialise NIC\n"); goto fail3;
}
rc = ef4_init_port(efx); if (rc) {
netif_err(efx, probe, efx->net_dev, "failed to initialise port\n"); goto fail4;
}
rc = ef4_nic_init_interrupt(efx); if (rc) goto fail5;
rc = ef4_enable_interrupts(efx); if (rc) goto fail6;
/* Disable VLAN filtering by default. It may be enforced if *thefeatureisfixed(i.e.VLANfiltersarerequiredto *receiveVLANtaggedpacketsduetovPortrestrictions).
*/
net_dev->features &= ~NETIF_F_HW_VLAN_CTAG_FILTER;
net_dev->features |= efx->fixed_features;
rc = ef4_register_netdev(efx); if (rc) goto fail4;
/* Used for both resume and restore */ staticint ef4_pm_resume(struct device *dev)
{ struct pci_dev *pci_dev = to_pci_dev(dev); struct ef4_nic *efx = pci_get_drvdata(pci_dev); int rc;
rc = pci_set_power_state(pci_dev, PCI_D0); if (rc) return rc;
pci_restore_state(pci_dev);
rc = pci_enable_device(pci_dev); if (rc) return rc;
pci_set_master(efx->pci_dev);
rc = efx->type->reset(efx, RESET_TYPE_ALL); if (rc) return rc;
rc = efx->type->init(efx); if (rc) return rc;
rc = ef4_pm_thaw(dev); return rc;
}
staticint ef4_pm_suspend(struct device *dev)
{ int rc;
ef4_pm_freeze(dev);
rc = ef4_pm_poweroff(dev); if (rc)
ef4_pm_resume(dev); return rc;
}
status = PCI_ERS_RESULT_NEED_RESET;
} else { /* If the interface is disabled we don't want to do anything *withit.
*/
status = PCI_ERS_RESULT_RECOVERED;
}
rtnl_unlock();
pci_disable_device(pdev);
return status;
}
/* Fake a successful reset, which will be performed later in ef4_io_resume. */ static pci_ers_result_t ef4_io_slot_reset(struct pci_dev *pdev)
{ struct ef4_nic *efx = pci_get_drvdata(pdev);
pci_ers_result_t status = PCI_ERS_RESULT_RECOVERED;
if (pci_enable_device(pdev)) {
netif_err(efx, hw, efx->net_dev, "Cannot re-enable PCI device after reset.\n");
status = PCI_ERS_RESULT_DISCONNECT;
}
return status;
}
/* Perform the actual reset and resume I/O operations. */ staticvoid ef4_io_resume(struct pci_dev *pdev)
{ struct ef4_nic *efx = pci_get_drvdata(pdev); int rc;
rtnl_lock();
if (efx->state == STATE_DISABLED) goto out;
rc = ef4_reset(efx, RESET_TYPE_ALL); if (rc) {
netif_err(efx, hw, efx->net_dev, "ef4_reset failed after PCI error (%d)\n", rc);
} else {
efx->state = STATE_READY;
netif_dbg(efx, hw, efx->net_dev, "Done resetting and resuming IO after PCI error.\n");
}
out:
rtnl_unlock();
}
/* For simplicity and reliability, we always require a slot reset and try to *resetthehardwarewhenapcierroraffectingthedeviceisdetected. *Weleaveboththelink_resetandmmio_enabledcallbackunimplemented: *withourrequestforslotresetthemmio_enabledcallbackwillneverbe *called,andthelink_resetcallbackisnotusedbyAERorEEHmechanisms.
*/ staticconststruct pci_error_handlers ef4_err_handlers = {
.error_detected = ef4_io_error_detected,
.slot_reset = ef4_io_slot_reset,
.resume = ef4_io_resume,
};
MODULE_AUTHOR("Solarflare Communications and " "Michael Brown <mbrown@fensystems.co.uk>");
MODULE_DESCRIPTION("Solarflare Falcon network driver");
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, ef4_pci_table);
MODULE_VERSION(EF4_DRIVER_VERSION);
Messung V0.5 in Prozent
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.78Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-10-02)
¤
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.