tx_buffer->next_to_watch = NULL;
tx_buffer->skb = NULL;
dma_unmap_len_set(tx_buffer, len, 0); /* tx_buffer must be completely set up in the transmit path */
}
/* underlying hardware might not allow access and/or always return *0forthehead/tailregisterssojustusethecachedvalues
*/
head = ring->next_to_clean;
tail = ring->next_to_use;
if (head != tail) return (head < tail) ?
tail - head : (tail + ring->count - head);
return0;
}
/** *iavf_force_wb-IssueSWInterruptsoHWdoesawb *@vsi:theVSIwecareabout *@q_vector:thevectoronwhichtoforcewriteback
**/ staticvoid iavf_force_wb(struct iavf_vsi *vsi, struct iavf_q_vector *q_vector)
{
u32 val = IAVF_VFINT_DYN_CTLN1_INTENA_MASK |
IAVF_VFINT_DYN_CTLN1_ITR_INDX_MASK | /* set noitr */
IAVF_VFINT_DYN_CTLN1_SWINT_TRIG_MASK |
IAVF_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_MASK /* allow 00 to be written to the index */;
if (test_bit(__IAVF_VSI_DOWN, vsi->state)) return;
netdev = vsi->netdev; if (!netdev) return;
if (!netif_carrier_ok(netdev)) return;
for (i = 0; i < vsi->back->num_active_queues; i++) {
tx_ring = &vsi->back->tx_rings[i]; if (tx_ring && tx_ring->desc) { /* If packet counter has not changed the queue is *likelystalled,soforceaninterruptforthis *queue. * *prev_pkt_ctrwouldbenegativeiftherewasno *pendingwork.
*/
packets = tx_ring->stats.packets & INT_MAX; if (tx_ring->prev_pkt_ctr == packets) {
iavf_force_wb(vsi, tx_ring->q_vector); continue;
}
/* Memory barrier between read of packet count and call *toiavf_get_tx_pending()
*/
smp_rmb();
tx_ring->prev_pkt_ctr =
iavf_get_tx_pending(tx_ring, true) ? packets : -1;
}
}
}
tx_buf = &tx_ring->tx_bi[i];
tx_desc = IAVF_TX_DESC(tx_ring, i);
i -= tx_ring->count;
do { struct iavf_tx_desc *eop_desc = tx_buf->next_to_watch;
/* if next_to_watch is not set then there is no work pending */ if (!eop_desc) break;
/* prevent any other reads prior to eop_desc */
smp_rmb();
iavf_trace(clean_tx_irq, tx_ring, tx_desc, tx_buf); /* if the descriptor isn't done, no work yet to do */ if (!(eop_desc->cmd_type_offset_bsz &
cpu_to_le64(IAVF_TX_DESC_DTYPE_DESC_DONE))) break;
tx_buf++;
tx_desc++;
i++; if (unlikely(!i)) {
i -= tx_ring->count;
tx_buf = tx_ring->tx_bi;
tx_desc = IAVF_TX_DESC(tx_ring, 0);
}
/* unmap any remaining paged data */ if (dma_unmap_len(tx_buf, len)) {
dma_unmap_page(tx_ring->dev,
dma_unmap_addr(tx_buf, dma),
dma_unmap_len(tx_buf, len),
DMA_TO_DEVICE);
dma_unmap_len_set(tx_buf, len, 0);
}
}
/* move us one more past the eop_desc for start of next pkt */
tx_buf++;
tx_desc++;
i++; if (unlikely(!i)) {
i -= tx_ring->count;
tx_buf = tx_ring->tx_bi;
tx_desc = IAVF_TX_DESC(tx_ring, 0);
}
prefetch(tx_desc);
/* update budget accounting */
budget--;
} while (likely(budget));
if (tx_ring->flags & IAVF_TXR_FLAGS_WB_ON_ITR) { /* check to see if there are < 4 descriptors *waitingtobewrittenback,thenkickthehardwaretoforce *themtobewrittenbackincasewestayinNAPI. *InthismodeonX722wedonotenableInterrupt.
*/ unsignedint j = iavf_get_tx_pending(tx_ring, false);
staticunsignedint iavf_mbps_itr_multiplier(u32 speed_mbps)
{ switch (speed_mbps) { case SPEED_100000: return IAVF_AIM_MULTIPLIER_100G; case SPEED_50000: return IAVF_AIM_MULTIPLIER_50G; case SPEED_40000: return IAVF_AIM_MULTIPLIER_40G; case SPEED_25000: case SPEED_20000: return IAVF_AIM_MULTIPLIER_20G; case SPEED_10000: default: return IAVF_AIM_MULTIPLIER_10G; case SPEED_1000: case SPEED_100: return IAVF_AIM_MULTIPLIER_1G;
}
}
staticunsignedint
iavf_virtchnl_itr_multiplier(enum virtchnl_link_speed speed_virtchnl)
{ switch (speed_virtchnl) { case VIRTCHNL_LINK_SPEED_40GB: return IAVF_AIM_MULTIPLIER_40G; case VIRTCHNL_LINK_SPEED_25GB: case VIRTCHNL_LINK_SPEED_20GB: return IAVF_AIM_MULTIPLIER_20G; case VIRTCHNL_LINK_SPEED_10GB: default: return IAVF_AIM_MULTIPLIER_10G; case VIRTCHNL_LINK_SPEED_1GB: case VIRTCHNL_LINK_SPEED_100MB: return IAVF_AIM_MULTIPLIER_1G;
}
}
/* If we don't have any rings just leave ourselves set for maximum *possiblelatencysowetakeourselvesoutoftheequation.
*/ if (!rc->ring || !ITR_IS_DYNAMIC(rc->ring->itr_setting)) return;
/* For Rx we want to push the delay up and default to low latency. *forTxwewanttopullthedelaydownanddefaulttohighlatency.
*/
itr = iavf_container_is_rx(q_vector, rc) ?
IAVF_ITR_ADAPTIVE_MIN_USECS | IAVF_ITR_ADAPTIVE_LATENCY :
IAVF_ITR_ADAPTIVE_MAX_USECS | IAVF_ITR_ADAPTIVE_LATENCY;
/* If we didn't update within up to 1 - 2 jiffies we can assume *thateitherpacketsarecominginsoslowtherehasn'tbeen *anywork,orthatthereissomuchworkthatNAPIisdealing *withinterruptmoderationandwedon'tneedtodoanything.
*/ if (time_after(next_update, rc->next_update)) goto clear_counts;
/* If itr_countdown is set it means we programmed an ITR within *thelast4interruptcycles.Thishasasideeffectofus *potentiallyfiringanearlyinterrupt.Inordertoworkaround *thisweneedtothrowoutanydatareceivedforafew *interruptsfollowingtheupdate.
*/ if (q_vector->itr_countdown) {
itr = rc->target_itr; goto clear_counts;
}
if (iavf_container_is_rx(q_vector, rc)) { /* If Rx there are 1 to 4 packets and bytes are less than *9000assumeinsufficientdatatousebulkratelimiting *approachunlessTxisalreadyinbulkratelimiting.We *arelikelylatencydriven.
*/ if (packets && packets < 4 && bytes < 9000 &&
(q_vector->tx.target_itr & IAVF_ITR_ADAPTIVE_LATENCY)) {
itr = IAVF_ITR_ADAPTIVE_LATENCY; goto adjust_by_size;
}
} elseif (packets < 4) { /* If we have Tx and Rx ITR maxed and Tx ITR is running in *bulkmodeandwearereceiving4orfewerpacketsjust *resettheITR_ADAPTIVE_LATENCYbitforlatencymodeso *thattheRxcanrelax.
*/ if (rc->target_itr == IAVF_ITR_ADAPTIVE_MAX_USECS &&
(q_vector->rx.target_itr & IAVF_ITR_MASK) ==
IAVF_ITR_ADAPTIVE_MAX_USECS) goto clear_counts;
} elseif (packets > 32) { /* If we have processed over 32 packets in a single interrupt *forTxassumeweneedtoswitchoverto"bulk"mode.
*/
rc->target_itr &= ~IAVF_ITR_ADAPTIVE_LATENCY;
}
/* We have no packets to actually measure against. This means *eitheroneoftheotherqueuesonthisvectorisactiveor *weareaTxqueuedoingTSOwithtoohighofaninterruptrate. * *Between4and56wecanassumethatourcurrentinterruptdelay *isonlyslightlytoolow.Assuchweshouldincreaseitbyasmall *fixedamount.
*/ if (packets < 56) {
itr = rc->target_itr + IAVF_ITR_ADAPTIVE_MIN_INC; if ((itr & IAVF_ITR_MASK) > IAVF_ITR_ADAPTIVE_MAX_USECS) {
itr &= IAVF_ITR_ADAPTIVE_LATENCY;
itr += IAVF_ITR_ADAPTIVE_MAX_USECS;
} goto clear_counts;
}
/* Between 56 and 112 is our "goldilocks" zone where we are *workingout"justright".Justreportthatourcurrent *ITRisgoodforus.
*/ if (packets <= 112) goto clear_counts;
/* If packet count is 128 or greater we are likely looking *ataslightoverrunofthedelaywewant.Tryhalving *ourdelaytoseeifthatwillcutthenumberofpackets *inhalfperinterrupt.
*/
itr /= 2;
itr &= IAVF_ITR_MASK; if (itr < IAVF_ITR_ADAPTIVE_MIN_USECS)
itr = IAVF_ITR_ADAPTIVE_MIN_USECS;
goto clear_counts;
}
/* The paths below assume we are dealing with a bulk ITR since *numberofpacketsisgreaterthan256.Wearejustgoingtohave *tocomputeavalueandtrytobringthecountundercontrol, *thoughforsmallerpacketsizesthereisn'tmuchwecandoas *NAPIpollingwilllikelybekickinginsoonerratherthanlater.
*/
itr = IAVF_ITR_ADAPTIVE_BULK;
adjust_by_size: /* If packet counts are 256 or greater we can assume we have a gross *overestimationofwhattherateshouldbe.Insteadoftryingtofine *tuneitjustusetheformulabelowtotryanddialinanexactvalue *givethecurrentpacketsizeoftheframe.
*/
avg_wire_size = bytes / packets;
/* The following is a crude approximation of: *wmem_default/(size+overhead)=desired_pkts_per_int *rate/bits_per_byte/(size+ethernetoverhead)=pkt_rate *(desired_pkt_rate/pkt_rate)*usecs_per_sec=ITRvalue * *Assumingwmem_defaultis212992andoverheadis640bytesper *packet,(256skb,64headroom,320sharedinfo),wecanreducethe *formuladownto * *(170*(size+24))/(size+640)=ITR * *Wefirstdosomemathonthepacketsizeandthenfinallybitshift *by8afterroundingup.WealsohavetoaccountforPCIelinkspeed *differenceasITRscalesbasedonthis.
*/ if (avg_wire_size <= 60) { /* Start at 250k ints/sec */
avg_wire_size = 4096;
} elseif (avg_wire_size <= 380) { /* 250K ints/sec to 60K ints/sec */
avg_wire_size *= 40;
avg_wire_size += 1696;
} elseif (avg_wire_size <= 1084) { /* 60K ints/sec to 36K ints/sec */
avg_wire_size *= 15;
avg_wire_size += 11452;
} elseif (avg_wire_size <= 1980) { /* 36K ints/sec to 30K ints/sec */
avg_wire_size *= 5;
avg_wire_size += 22420;
} else { /* plateau at a limit of 30K ints/sec */
avg_wire_size = 32256;
}
/* If we are in low latency mode halve our delay which doubles the *ratetosomewherebetween100Kto16Kints/sec
*/ if (itr & IAVF_ITR_ADAPTIVE_LATENCY)
avg_wire_size /= 2;
/* Resultant value is 256 times larger than it needs to be. This *givesusroomtoadjustthevalueasneededtoeitherincrease *ordecreasethevaluebasedonlinkspeedsof10G,2.5G,1G,etc. * *Useadditionaswehavealreadyrecordedthenewlatencyflag *fortheITRvalue.
*/
itr += DIV_ROUND_UP(avg_wire_size,
iavf_itr_divisor(q_vector->adapter)) *
IAVF_ITR_ADAPTIVE_MIN_INC;
clear_counts: /* write back value */
rc->target_itr = itr;
/* next update should occur within next jiffy */
rc->next_update = next_update + 1;
rc->total_bytes = 0;
rc->total_packets = 0;
}
/** *iavf_setup_tx_descriptors-AllocatetheTxdescriptors *@tx_ring:thetxringtosetup * *Return0onsuccess,negativeonerror
**/ int iavf_setup_tx_descriptors(struct iavf_ring *tx_ring)
{ struct device *dev = tx_ring->dev; int bi_size;
if (!dev) return -ENOMEM;
/* warn if we are about to overwrite the pointer */
WARN_ON(tx_ring->tx_bi);
bi_size = sizeof(struct iavf_tx_buffer) * tx_ring->count;
tx_ring->tx_bi = kzalloc(bi_size, GFP_KERNEL); if (!tx_ring->tx_bi) goto err;
/* round up to nearest 4K */
tx_ring->size = tx_ring->count * sizeof(struct iavf_tx_desc);
tx_ring->size = ALIGN(tx_ring->size, 4096);
tx_ring->desc = dma_alloc_coherent(dev, tx_ring->size,
&tx_ring->dma, GFP_KERNEL); if (!tx_ring->desc) {
dev_info(dev, "Unable to allocate memory for the Tx descriptor ring, size=%d\n",
tx_ring->size); goto err;
}
/** *iavf_clean_rx_ring-FreeRxbuffers *@rx_ring:ringtobecleaned
**/ staticvoid iavf_clean_rx_ring(struct iavf_ring *rx_ring)
{ /* ring already cleared, nothing to do */ if (!rx_ring->rx_fqes) return;
if (rx_ring->skb) {
dev_kfree_skb(rx_ring->skb);
rx_ring->skb = NULL;
}
/* Free all the Rx ring buffers */ for (u32 i = rx_ring->next_to_clean; i != rx_ring->next_to_use; ) { conststruct libeth_fqe *rx_fqes = &rx_ring->rx_fqes[i];
if (unlikely(ipv4 && (csum_bits.ipe || csum_bits.eipe))) goto checksum_fail;
/* likely incorrect csum if alternate IP extension headers found */ if (unlikely(ipv6 && csum_bits.ipv6exadd)) return;
/* there was some L4 error, count error and punt packet to the stack */ if (unlikely(csum_bits.l4e)) goto checksum_fail;
/* handle packets that were not able to be checksummed due *toarrivalspeed,inthiscasethestackcancompute *thecsum.
*/ if (unlikely(csum_bits.pprs)) return;
/* Skip processing if timestamps aren't enabled */ if (!(rx_ring->flags & IAVF_TXRX_FLAGS_HW_TSTAMP)) return;
/* Check if this Rx descriptor has a valid timestamp */ if (!le64_get_bits(qw2, IAVF_PTP_40B_TSTAMP_VALID)) return;
/* the ts_low field only contains the valid bit and sub-nanosecond *precision,sowedon'tneedtoextractit.
*/
tstamp = le64_get_bits(qw3, IAVF_RXD_FLEX_QW3_TSTAMP_HIGH_M);
/* return some buffers to hardware, one at a time is too slow */ if (cleaned_count >= IAVF_RX_BUFFER_WRITE) {
failure = failure ||
iavf_alloc_rx_buffers(rx_ring, cleaned_count);
cleaned_count = 0;
}
/* This memory barrier is needed to keep us from reading *anyotherfieldsoutoftherx_descuntilwehave *verifiedthedescriptorhasbeenwrittenback.
*/
dma_rmb();
qw1 = le64_to_cpu(rx_desc->qw1); /* If DD field (descriptor done) is unset then other fields are *notvalid
*/ if (!iavf_is_descriptor_done(qw1, flex)) break;
rx_buffer = &rx_ring->rx_fqes[rx_ring->next_to_clean]; if (!libeth_rx_sync_for_cpu(rx_buffer, fields.len)) goto skip_data;
/* retrieve a buffer from the ring */ if (skb)
iavf_add_rx_frag(skb, rx_buffer, fields.len); else
skb = iavf_build_skb(rx_buffer, fields.len);
/* exit if we failed to retrieve a buffer */ if (!skb) {
rx_ring->rx_stats.alloc_buff_failed++; break;
}
skip_data:
cleaned_count++;
if (iavf_is_non_eop(rx_ring, fields) || unlikely(!skb)) continue;
/* RXE field in descriptor is an indication of the MAC errors *(likeCRC,alignment,oversizeetc).Ifitissettheniavf *shouldfinish.
*/ if (unlikely(fields.rxe)) {
dev_kfree_skb_any(skb);
skb = NULL; continue;
}
if (iavf_cleanup_headers(rx_ring, skb)) {
skb = NULL; continue;
}
/* probably a little skewed due to removing CRC */
total_rx_bytes += skb->len;
/* We don't bother with setting the CLEARPBA bit as the data sheet *pointsoutdoingsois"meaninglesssinceitwasalready *auto-cleared".Theauto-clearinghappenswhentheinterruptis *asserted. * *Hardwareerrata28foralsoindicatesthatwritingtoa *xxINT_DYN_CTLxCSRwithINTENA_MSK(bit31)setto0willclear *aneventinthePBAanywaysoweneedtorelyontheautomask *toholdpendingeventsforusuntiltheinterruptisre-enabled * *Theitrvalueisreportedinmicroseconds,andtheregister *valueisrecordedin2microsecondunits.Forthisreasonwe *onlyneedtoshiftbytheintervalshift-1insteadofthe *fullvalue.
*/
itr &= IAVF_ITR_MASK;
/* a small macro to shorten up some long lines */ #define INTREG IAVF_VFINT_DYN_CTLN1
/* The act of updating the ITR will cause it to immediately trigger. In order *topreventthisfromthrowingoffadaptiveupdatestatisticswedeferthe *updatesothatitcanonlyhappensooften.SoaftereitherTxorRxare *updatedwemaketheadaptiveschemewaituntileithertheITRcompletely *expiresviathenext_updateexpirationorwehavebeenthroughatleast *3interrupts.
*/ #define ITR_COUNTDOWN_START 3
if (test_bit(__IAVF_VSI_DOWN, vsi->state)) {
napi_complete(napi); return0;
}
/* Since the actual Tx work is minimal, we can give the Tx a larger *budgetandbemoreaggressiveaboutcleaninguptheTxdescriptors.
*/
iavf_for_each_ring(ring, q_vector->tx) { if (!iavf_clean_tx_irq(vsi, ring, budget)) {
clean_complete = false; continue;
}
arm_wb |= !!(ring->flags & IAVF_TXR_FLAGS_ARM_WB);
ring->flags &= ~IAVF_TXR_FLAGS_ARM_WB;
}
/* Handle case where we are called by netpoll with a budget of 0 */ if (budget <= 0) goto tx_only;
/* We attempt to distribute budget to each Rx queue fairly, but don't *allowthebudgettogobelow1becausethatwouldexitpollingearly.
*/
budget_per_ring = max(budget/q_vector->num_ringpairs, 1);
iavf_for_each_ring(ring, q_vector->rx) { int cleaned = iavf_clean_rx_irq(ring, budget_per_ring);
work_done += cleaned; /* if we clean as many as budgeted, we must not be done */ if (cleaned >= budget_per_ring)
clean_complete = false;
}
/* If work not completed, return budget and polling will return */ if (!clean_complete) { int cpu_id = smp_processor_id();
/* It is possible that the interrupt affinity has changed but, *ifthecpuispeggedat100%,pollingwillneverexitwhile *trafficcontinuesandtheinterruptwillbestuckonthis *cpu.Wechecktomakesureaffinityiscorrectbeforewe *continuetopoll,otherwisewemuststoppollingsothe *interruptcanmovetothecorrectcpu.
*/ if (!cpumask_test_cpu(cpu_id,
&q_vector->napi.config->affinity_mask)) { /* Tell napi that we are done polling */
napi_complete_done(napi, work_done);
/* Force an interrupt */
iavf_force_wb(vsi, q_vector);
/* Return budget-1 so that polling stops */ return budget - 1;
}
tx_only: if (arm_wb) {
q_vector->tx.ring[0].tx_stats.tx_force_wb++;
iavf_enable_wb_on_itr(vsi, q_vector);
} return budget;
}
if (vsi->back->flags & IAVF_TXR_FLAGS_WB_ON_ITR)
q_vector->arm_wb_state = false;
/* Exit the polling mode, but don't re-enable interrupts if stack might *pollusduetobusy-polling
*/ if (likely(napi_complete_done(napi, work_done)))
iavf_update_enable_itr(vsi, q_vector);
/* stack will only request hardware VLAN insertion offload for protocols *thatthedriversupportsandhasenabled
*/ if (!skb_vlan_tag_present(skb)) return;
/* indicate if we need to offload outer UDP header */ if ((*tx_flags & IAVF_TX_FLAGS_TSO) &&
!(skb_shinfo(skb)->gso_type & SKB_GSO_PARTIAL) &&
(skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL_CSUM))
tunnel |= IAVF_TXD_CTX_QW0_L4T_CS_MASK;
/* record tunnel offload values */
*cd_tunneling |= tunnel;
/* switch L4 header pointer from outer to inner */
l4.hdr = skb_inner_transport_header(skb);
l4_proto = 0;
/* reset type as we transition from outer to inner headers */
*tx_flags &= ~(IAVF_TX_FLAGS_IPV4 | IAVF_TX_FLAGS_IPV6); if (ip.v4->version == 4)
*tx_flags |= IAVF_TX_FLAGS_IPV4; if (ip.v6->version == 6)
*tx_flags |= IAVF_TX_FLAGS_IPV6;
}
/* Enable IP checksum offloads */ if (*tx_flags & IAVF_TX_FLAGS_IPV4) {
l4_proto = ip.v4->protocol; /* the stack computes the IP header already, the only time we *needthehardwaretorecomputeitisinthecaseofTSO.
*/
cmd |= (*tx_flags & IAVF_TX_FLAGS_TSO) ?
IAVF_TX_DESC_CMD_IIPT_IPV4_CSUM :
IAVF_TX_DESC_CMD_IIPT_IPV4;
} elseif (*tx_flags & IAVF_TX_FLAGS_IPV6) {
cmd |= IAVF_TX_DESC_CMD_IIPT_IPV6;
/* no need to check if number of frags is less than 7 */
nr_frags = skb_shinfo(skb)->nr_frags; if (nr_frags < (IAVF_MAX_BUFFER_TXD - 1)) returnfalse;
/* We need to walk through the list and validate that each group *of6fragmentstotalsatleastgso_size.
*/
nr_frags -= IAVF_MAX_BUFFER_TXD - 2;
frag = &skb_shinfo(skb)->frags[0];
/* Initialize size to the negative value of gso_size minus 1. We *usethisastheworstcasescenerioinwhichthefragahead *ofusonlyprovidesonebytewhichiswhywearelimitedto6 *descriptorsforasingletransmitastheheaderandprevious *fragmentarealreadyconsuming2descriptors.
*/
sum = 1 - skb_shinfo(skb)->gso_size;
/* Add size of frags 0 through 4 to create our initial sum */
sum += skb_frag_size(frag++);
sum += skb_frag_size(frag++);
sum += skb_frag_size(frag++);
sum += skb_frag_size(frag++);
sum += skb_frag_size(frag++);
/* Walk through fragments adding latest fragment, testing it, and *thenremovingstalefragmentsfromthesum.
*/ for (stale = &skb_shinfo(skb)->frags[0];; stale++) { int stale_size = skb_frag_size(stale);
sum += skb_frag_size(frag++);
/* The stale fragment may present us with a smaller *descriptorthantheactualfragmentsize.Toaccount *forthatweneedtoremoveallthedataonthefrontand *figureoutwhattheremainderwouldbeinthelast *descriptorassociatedwiththefragment.
*/ if (stale_size > IAVF_MAX_DATA_PER_TXD) { int align_pad = -(skb_frag_off(stale)) &
(IAVF_MAX_READ_REQ_SIZE - 1);
sum -= align_pad;
stale_size -= align_pad;
do {
sum -= IAVF_MAX_DATA_PER_TXD_ALIGNED;
stale_size -= IAVF_MAX_DATA_PER_TXD_ALIGNED;
} while (stale_size > IAVF_MAX_DATA_PER_TXD);
}
/* if sum is negative we failed to make sufficient progress */ if (sum < 0) returntrue;
if (!nr_frags--) break;
sum -= stale_size;
}
returnfalse;
}
/** *__iavf_maybe_stop_tx-2ndlevelcheckfortxstopconditions *@tx_ring:theringtobechecked *@size:thesizebufferwewanttoassureisavailable * *Returns-EBUSYifastopisneeded,else0
**/ int __iavf_maybe_stop_tx(struct iavf_ring *tx_ring, int size)
{
netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index); /* Memory barrier before checking head and tail */
smp_mb();
/* Check again in a case another CPU has just made room available. */ if (likely(IAVF_DESC_UNUSED(tx_ring) < size)) return -EBUSY;
/* A reprieve! - use start_queue because it doesn't call schedule */
netif_start_subqueue(tx_ring->netdev, tx_ring->queue_index);
++tx_ring->tx_stats.restart_queue; return0;
}
/* write last descriptor with RS and EOP bits */
td_cmd |= IAVF_TXD_CMD;
tx_desc->cmd_type_offset_bsz =
build_ctob(td_cmd, td_offset, size, td_tag);
skb_tx_timestamp(skb);
/* Force memory writes to complete before letting h/w know there *arenewdescriptorstofetch. * *Wealsousethismemorybarriertomakecertainallofthe *statusbitshavebeenupdatedbeforenext_to_watchiswritten.
*/
wmb();
/* set next_to_watch value indicating a packet is present */
first->next_to_watch = tx_desc;
/* notify HW of packet */ if (netif_xmit_stopped(txring_txq(tx_ring)) || !netdev_xmit_more()) {
writel(i, tx_ring->tail);
}
/* record the location of the first descriptor for this packet */
first = &tx_ring->tx_bi[tx_ring->next_to_use];
first->skb = skb;
first->bytecount = skb->len;
first->gso_segs = 1;
/* Always offload the checksum, since it's in the data descriptor */
tso = iavf_tx_enable_csum(skb, &tx_flags, &td_cmd, &td_offset,
tx_ring, &cd_tunneling); if (tso < 0) goto out_drop;
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.