staticconstchar ixgbe_overheat_msg[] = "Network adapter has been stopped because it has over heated. Restart the computer. If the problem persists, power off the system and replace the adapter";
#ifdef CONFIG_PCI_IOV staticunsignedint max_vfs;
module_param(max_vfs, uint, 0);
MODULE_PARM_DESC(max_vfs, "Maximum number of virtual functions to allocate per physical function - default is zero and maximum value is 63. (Deprecated)"); #endif/* CONFIG_PCI_IOV */
staticbool allow_unsupported_sfp;
module_param(allow_unsupported_sfp, bool, 0444);
MODULE_PARM_DESC(allow_unsupported_sfp, "Allow unsupported and untested SFP+ modules on 82599-based adapters");
/* Get the negotiated link width and speed from PCI config space of the * parent, as this device is behind a switch
*/
err = ixgbe_read_pci_cfg_word_parent(adapter, 18, &link_status);
/* assume caller will handle error case */ if (err) return err;
/** * ixgbe_pcie_from_parent - Determine whether PCIe info should come from parent * @hw: hw specific details * * This function is used by probe to determine whether a device's PCI-Express * bandwidth details should be gathered from the parent bus instead of from the * device. Used to ensure that various locations all have the correct device ID * checks. * * Return: true if information should be collected from the parent bus, false * otherwise
*/ staticbool ixgbe_pcie_from_parent(struct ixgbe_hw *hw)
{ switch (hw->device_id) { case IXGBE_DEV_ID_82599_SFP_SF_QP: case IXGBE_DEV_ID_82599_QSFP_SF_QP: returntrue; default: returnfalse;
}
}
/* Some devices are not connected over PCIe and thus do not negotiate * speed. These devices do not have valid bus info, and thus any report * we generate may not be correct.
*/ if (hw->bus.type == ixgbe_bus_type_internal) return;
/* determine whether to use the parent device */ if (ixgbe_pcie_from_parent(&adapter->hw))
pdev = adapter->pdev->bus->parent->self; else
pdev = adapter->pdev;
reg_addr = READ_ONCE(hw->hw_addr); if (ixgbe_removed(reg_addr)) return IXGBE_FAILED_READ_REG;
/* Register read of 0xFFFFFFF can indicate the adapter has been removed, * so perform several status register reads to determine if the adapter * has been removed.
*/ for (i = 0; i < IXGBE_FAILED_READ_RETRIES; i++) {
value = readl(reg_addr + IXGBE_STATUS); if (value != IXGBE_FAILED_READ_REG) break;
mdelay(3);
}
if (value == IXGBE_FAILED_READ_REG)
ixgbe_remove_adapter(hw); else
value = readl(reg_addr + reg); return value;
}
/** * ixgbe_read_reg - Read from device register * @hw: hw specific details * @reg: offset of register to read * * Returns : value read or IXGBE_FAILED_READ_REG if removed * * This function is used to read device registers. It checks for device * removal by confirming any read that returns all ones by checking the * status register value for all ones. This function avoids reading from * the hardware if a removal was previously detected in which case it * returns IXGBE_FAILED_READ_REG (all ones).
*/
u32 ixgbe_read_reg(struct ixgbe_hw *hw, u32 reg)
{
u8 __iomem *reg_addr = READ_ONCE(hw->hw_addr);
u32 value;
if (ixgbe_removed(reg_addr)) return IXGBE_FAILED_READ_REG; if (unlikely(hw->phy.nw_mng_if_sel &
IXGBE_NW_MNG_IF_SEL_SGMII_ENABLE)) { struct ixgbe_adapter *adapter; int i;
for (i = 0; i < 200; ++i) {
value = readl(reg_addr + IXGBE_MAC_SGMII_BUSY); if (likely(!value)) goto writes_completed; if (value == IXGBE_FAILED_READ_REG) {
ixgbe_remove_adapter(hw); return IXGBE_FAILED_READ_REG;
}
udelay(5);
}
switch (reginfo->ofs) { case IXGBE_SRRCTL(0): for (i = 0; i < 64; i++)
regs[i] = IXGBE_READ_REG(hw, IXGBE_SRRCTL(i)); break; case IXGBE_DCA_RXCTRL(0): for (i = 0; i < 64; i++)
regs[i] = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i)); break; case IXGBE_RDLEN(0): for (i = 0; i < 64; i++)
regs[i] = IXGBE_READ_REG(hw, IXGBE_RDLEN(i)); break; case IXGBE_RDH(0): for (i = 0; i < 64; i++)
regs[i] = IXGBE_READ_REG(hw, IXGBE_RDH(i)); break; case IXGBE_RDT(0): for (i = 0; i < 64; i++)
regs[i] = IXGBE_READ_REG(hw, IXGBE_RDT(i)); break; case IXGBE_RXDCTL(0): for (i = 0; i < 64; i++)
regs[i] = IXGBE_READ_REG(hw, IXGBE_RXDCTL(i)); break; case IXGBE_RDBAL(0): for (i = 0; i < 64; i++)
regs[i] = IXGBE_READ_REG(hw, IXGBE_RDBAL(i)); break; case IXGBE_RDBAH(0): for (i = 0; i < 64; i++)
regs[i] = IXGBE_READ_REG(hw, IXGBE_RDBAH(i)); break; case IXGBE_TDBAL(0): for (i = 0; i < 64; i++)
regs[i] = IXGBE_READ_REG(hw, IXGBE_TDBAL(i)); break; case IXGBE_TDBAH(0): for (i = 0; i < 64; i++)
regs[i] = IXGBE_READ_REG(hw, IXGBE_TDBAH(i)); break; case IXGBE_TDLEN(0): for (i = 0; i < 64; i++)
regs[i] = IXGBE_READ_REG(hw, IXGBE_TDLEN(i)); break; case IXGBE_TDH(0): for (i = 0; i < 64; i++)
regs[i] = IXGBE_READ_REG(hw, IXGBE_TDH(i)); break; case IXGBE_TDT(0): for (i = 0; i < 64; i++)
regs[i] = IXGBE_READ_REG(hw, IXGBE_TDT(i)); break; case IXGBE_TXDCTL(0): for (i = 0; i < 64; i++)
regs[i] = IXGBE_READ_REG(hw, IXGBE_TXDCTL(i)); break; default:
pr_info("%-15s %08x\n",
reginfo->name, IXGBE_READ_REG(hw, reginfo->ofs)); return;
}
i = 0; while (i < 64) { int j; char buf[9 * 8 + 1]; char *p = buf;
snprintf(rname, 16, "%s[%d-%d]", reginfo->name, i, i + 7); for (j = 0; j < 8; j++)
p += sprintf(p, " %08x", regs[i++]);
pr_err("%-15s%s\n", rname, buf);
}
}
staticvoid ixgbe_print_buffer(struct ixgbe_ring *ring, int n)
{ struct ixgbe_tx_buffer *tx_buffer;
/* Let firmware take over control of h/w */
ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT);
IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT,
ctrl_ext & ~IXGBE_CTRL_EXT_DRV_LOAD);
}
/* Let firmware know the driver has taken over */
ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT);
IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT,
ctrl_ext | IXGBE_CTRL_EXT_DRV_LOAD);
}
/** * ixgbe_set_ivar - set the IVAR registers, mapping interrupt causes to vectors * @adapter: pointer to adapter struct * @direction: 0 for Rx, 1 for Tx, -1 for other causes * @queue: queue to map the corresponding interrupt to * @msix_vector: the vector to map to the corresponding queue *
*/ staticvoid ixgbe_set_ivar(struct ixgbe_adapter *adapter, s8 direction,
u8 queue, u8 msix_vector)
{
u32 ivar, index; struct ixgbe_hw *hw = &adapter->hw; switch (hw->mac.type) { case ixgbe_mac_82598EB:
msix_vector |= IXGBE_IVAR_ALLOC_VAL; if (direction == -1)
direction = 0;
index = (((direction * 64) + queue) >> 2) & 0x1F;
ivar = IXGBE_READ_REG(hw, IXGBE_IVAR(index));
ivar &= ~(0xFF << (8 * (queue & 0x3)));
ivar |= (msix_vector << (8 * (queue & 0x3)));
IXGBE_WRITE_REG(hw, IXGBE_IVAR(index), ivar); break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: case ixgbe_mac_x550em_a: case ixgbe_mac_e610: if (direction == -1) { /* other causes */
msix_vector |= IXGBE_IVAR_ALLOC_VAL;
index = ((queue & 1) * 8);
ivar = IXGBE_READ_REG(&adapter->hw, IXGBE_IVAR_MISC);
ivar &= ~(0xFF << index);
ivar |= (msix_vector << index);
IXGBE_WRITE_REG(&adapter->hw, IXGBE_IVAR_MISC, ivar); break;
} else { /* tx or rx causes */
msix_vector |= IXGBE_IVAR_ALLOC_VAL;
index = ((16 * (queue & 1)) + (8 * direction));
ivar = IXGBE_READ_REG(hw, IXGBE_IVAR(queue >> 1));
ivar &= ~(0xFF << index);
ivar |= (msix_vector << index);
IXGBE_WRITE_REG(hw, IXGBE_IVAR(queue >> 1), ivar); break;
} default: break;
}
}
/** * ixgbe_get_vf_idx - provide VF index number based on queue index * @adapter: pointer to the adapter struct * @queue: Tx queue identifier * @vf: output VF index * * Provide VF index number associated to the input queue. * * Returns: 0 if VF provided or error number.
*/ staticint ixgbe_get_vf_idx(struct ixgbe_adapter *adapter, u16 queue, u16 *vf)
{ struct ixgbe_hw *hw = &adapter->hw;
u8 queue_count;
u32 reg;
if (queue >= adapter->num_tx_queues) return -EINVAL;
/* Determine number of queues by checking * number of virtual functions
*/
reg = IXGBE_READ_REG(hw, IXGBE_GCR_EXT); switch (reg & IXGBE_GCR_EXT_VT_MODE_MASK) { case IXGBE_GCR_EXT_VT_MODE_64:
queue_count = IXGBE_64VFS_QUEUES; break; case IXGBE_GCR_EXT_VT_MODE_32:
queue_count = IXGBE_32VFS_QUEUES; break; case IXGBE_GCR_EXT_VT_MODE_16:
queue_count = IXGBE_16VFS_QUEUES; break; default: return -EINVAL;
}
/* * Check for a hung queue, but be thorough. This verifies * that a transmit has been completed since the previous * check AND there is at least one packet pending. The * ARMED bit is set to indicate a potential hang. The * bit is cleared if a pause frame is received to remove * false hang detection due to PFC or 802.3x frames. By * requiring this to fail twice we avoid races with * pfc clearing the ARMED bit and conditions where we * run the check_tx_hang logic with a transmit completion * pending but without time to complete it yet.
*/ if (tx_done_old == tx_done && tx_pending) /* make sure it is true for two checks in a row */ return test_and_set_bit(__IXGBE_HANG_CHECK_ARMED,
&tx_ring->state); /* update completed stats and continue */
tx_ring->tx_stats.tx_done_old = tx_done; /* reset the countdown */
clear_bit(__IXGBE_HANG_CHECK_ARMED, &tx_ring->state);
/* Do the reset outside of interrupt context */ if (!test_bit(__IXGBE_DOWN, &adapter->state)) {
set_bit(__IXGBE_RESET_REQUESTED, &adapter->state);
e_warn(drv, "initiating reset due to tx timeout\n");
ixgbe_service_event_schedule(adapter);
}
}
/** * ixgbe_tx_maxrate - callback to set the maximum per-queue bitrate * @netdev: network interface device structure * @queue_index: Tx queue to set * @maxrate: desired maximum transmit bitrate
**/ staticint ixgbe_tx_maxrate(struct net_device *netdev, int queue_index, u32 maxrate)
{ struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev); struct ixgbe_hw *hw = &adapter->hw;
u32 bcnrc_val = ixgbe_link_mbps(adapter);
if (!maxrate) return 0;
/* Calculate the rate factor values to set */
bcnrc_val <<= IXGBE_RTTBCNRC_RF_INT_SHIFT;
bcnrc_val /= maxrate;
/* clear everything but the rate factor */
bcnrc_val &= IXGBE_RTTBCNRC_RF_INT_MASK |
IXGBE_RTTBCNRC_RF_DEC_MASK;
/* enable the rate scheduler */
bcnrc_val |= IXGBE_RTTBCNRC_RS_ENA;
/** * ixgbe_update_tx_ring_stats - Update Tx ring specific counters * @tx_ring: ring to update * @q_vector: queue vector ring belongs to * @pkts: number of processed packets * @bytes: number of processed bytes
*/ void ixgbe_update_tx_ring_stats(struct ixgbe_ring *tx_ring, struct ixgbe_q_vector *q_vector, u64 pkts,
u64 bytes)
{
u64_stats_update_begin(&tx_ring->syncp);
tx_ring->stats.bytes += bytes;
tx_ring->stats.packets += pkts;
u64_stats_update_end(&tx_ring->syncp);
q_vector->tx.total_bytes += bytes;
q_vector->tx.total_packets += pkts;
}
/** * ixgbe_update_rx_ring_stats - Update Rx ring specific counters * @rx_ring: ring to update * @q_vector: queue vector ring belongs to * @pkts: number of processed packets * @bytes: number of processed bytes
*/ void ixgbe_update_rx_ring_stats(struct ixgbe_ring *rx_ring, struct ixgbe_q_vector *q_vector, u64 pkts,
u64 bytes)
{
u64_stats_update_begin(&rx_ring->syncp);
rx_ring->stats.bytes += bytes;
rx_ring->stats.packets += pkts;
u64_stats_update_end(&rx_ring->syncp);
q_vector->rx.total_bytes += bytes;
q_vector->rx.total_packets += pkts;
}
/** * ixgbe_pf_handle_tx_hang - handle Tx hang on PF * @tx_ring: tx ring number * @next: next ring * * Prints a message containing details about the tx hang.
*/ staticvoid ixgbe_pf_handle_tx_hang(struct ixgbe_ring *tx_ring, unsignedint next)
{ struct ixgbe_adapter *adapter = netdev_priv(tx_ring->netdev); struct ixgbe_hw *hw = &adapter->hw;
/** * ixgbe_vf_handle_tx_hang - handle Tx hang on VF * @adapter: structure containing ring specific data * @vf: VF index * * Print a message containing details about malicious driver detection. * Set malicious VF link down if the detection happened several times.
*/ staticvoid ixgbe_vf_handle_tx_hang(struct ixgbe_adapter *adapter, u16 vf)
{ struct ixgbe_hw *hw = &adapter->hw;
if (adapter->hw.mac.type != ixgbe_mac_e610) return;
e_warn(drv, "Malicious Driver Detection tx hang detected on PF %d VF %d MAC: %pM",
hw->bus.func, vf, adapter->vfinfo[vf].vf_mac_addresses);
/** * ixgbe_check_illegal_queue - search for queue with illegal packet * @adapter: structure containing ring specific data * @queue: queue index * * Check if tx descriptor connected with input queue * contains illegal packet. * * Returns: true if queue contain illegal packet.
*/ staticbool ixgbe_check_illegal_queue(struct ixgbe_adapter *adapter,
u16 queue)
{
u32 hdr_len_reg, mss_len_reg, type_reg; struct ixgbe_hw *hw = &adapter->hw;
u32 mss_len, header_len, reg;
for (u16 i = 0; i < IXGBE_MAX_TX_DESCRIPTORS; i++) { /* HW will clear bit IXGBE_TXDESCIC_READY when address * is written to address field. HW will set this bit * when iCache read is done, and data is ready at TIC_DWx. * Set descriptor address.
*/
read_poll_timeout(ixgbe_poll_tx_icache, reg,
!(reg & IXGBE_TXDESCIC_READY), 0, 0, false,
hw, queue, i);
/* update the statistics for this packet */
total_bytes += tx_buffer->bytecount;
total_packets += tx_buffer->gso_segs; if (tx_buffer->tx_flags & IXGBE_TX_FLAGS_IPSEC)
total_ipsec++;
/* free the skb */ if (ring_is_xdp(tx_ring))
xdp_return_frame(tx_buffer->xdpf); else
napi_consume_skb(tx_buffer->skb, napi_budget);
/* clear tx_buffer data */
dma_unmap_len_set(tx_buffer, len, 0);
/* unmap remaining buffers */ while (tx_desc != eop_desc) {
tx_buffer++;
tx_desc++;
i++; if (unlikely(!i)) {
i -= tx_ring->count;
tx_buffer = tx_ring->tx_buffer_info;
tx_desc = IXGBE_TX_DESC(tx_ring, 0);
}
/* unmap any remaining paged data */ if (dma_unmap_len(tx_buffer, len)) {
dma_unmap_page(tx_ring->dev,
dma_unmap_addr(tx_buffer, dma),
dma_unmap_len(tx_buffer, len),
DMA_TO_DEVICE);
dma_unmap_len_set(tx_buffer, len, 0);
}
}
/* move us one more past the eop_desc for start of next pkt */
tx_buffer++;
tx_desc++;
i++; if (unlikely(!i)) {
i -= tx_ring->count;
tx_buffer = tx_ring->tx_buffer_info;
tx_desc = IXGBE_TX_DESC(tx_ring, 0);
}
/* issue prefetch for next Tx descriptor */
prefetch(tx_desc);
/* update budget accounting */
budget--;
} while (likely(budget));
if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
txctrl = dca3_get_tag(tx_ring->dev, cpu);
switch (hw->mac.type) { case ixgbe_mac_82598EB:
reg_offset = IXGBE_DCA_TXCTRL(tx_ring->reg_idx); break; case ixgbe_mac_82599EB: case ixgbe_mac_X540:
reg_offset = IXGBE_DCA_TXCTRL_82599(tx_ring->reg_idx);
txctrl <<= IXGBE_DCA_TXCTRL_CPUID_SHIFT_82599; break; default: /* for unknown hardware do not write register */ return;
}
/* * We can enable relaxed ordering for reads, but not writes when * DCA is enabled. This is due to a known issue in some chipsets * which will cause the DCA tag to be cleared.
*/
txctrl |= IXGBE_DCA_TXCTRL_DESC_RRO_EN |
IXGBE_DCA_TXCTRL_DATA_RRO_EN |
IXGBE_DCA_TXCTRL_DESC_DCA_EN;
if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
rxctrl = dca3_get_tag(rx_ring->dev, cpu);
switch (hw->mac.type) { case ixgbe_mac_82599EB: case ixgbe_mac_X540:
rxctrl <<= IXGBE_DCA_RXCTRL_CPUID_SHIFT_82599; break; default: break;
}
/* * We can enable relaxed ordering for reads, but not writes when * DCA is enabled. This is due to a known issue in some chipsets * which will cause the DCA tag to be cleared.
*/
rxctrl |= IXGBE_DCA_RXCTRL_DESC_RRO_EN |
IXGBE_DCA_RXCTRL_DATA_DCA_EN |
IXGBE_DCA_RXCTRL_DESC_DCA_EN;
staticvoid ixgbe_setup_dca(struct ixgbe_adapter *adapter)
{ int i;
/* always use CB2 mode, difference is masked in the CB driver */ if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL,
IXGBE_DCA_CTRL_DCA_MODE_CB2); else
IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL,
IXGBE_DCA_CTRL_DCA_DISABLE);
for (i = 0; i < adapter->num_q_vectors; i++) {
adapter->q_vector[i]->cpu = -1;
ixgbe_update_dca(adapter->q_vector[i]);
}
}
#ifdef IXGBE_FCOE /** * ixgbe_rx_is_fcoe - check the rx desc for incoming pkt type * @ring: structure containing ring specific data * @rx_desc: advanced rx descriptor * * Returns : true if it is FCoE pkt
*/ staticinlinebool ixgbe_rx_is_fcoe(struct ixgbe_ring *ring, union ixgbe_adv_rx_desc *rx_desc)
{
__le16 pkt_info = rx_desc->wb.lower.lo_dword.hs_rss.pkt_info;
#endif/* IXGBE_FCOE */ /** * ixgbe_rx_checksum - indicate in skb if hw indicated a good cksum * @ring: structure containing ring specific data * @rx_desc: current Rx descriptor being processed * @skb: skb currently being received and modified
**/ staticinlinevoid ixgbe_rx_checksum(struct ixgbe_ring *ring, union ixgbe_adv_rx_desc *rx_desc, struct sk_buff *skb)
{
__le16 pkt_info = rx_desc->wb.lower.lo_dword.hs_rss.pkt_info; bool encap_pkt = false;
skb_checksum_none_assert(skb);
/* Rx csum disabled */ if (!(ring->netdev->features & NETIF_F_RXCSUM)) return;
/* check for VXLAN and Geneve packets */ if (pkt_info & cpu_to_le16(IXGBE_RXDADV_PKTTYPE_VXLAN)) {
encap_pkt = true;
skb->encapsulation = 1;
}
/* if IP and error */ if (ixgbe_test_staterr(rx_desc, IXGBE_RXD_STAT_IPCS) &&
ixgbe_test_staterr(rx_desc, IXGBE_RXDADV_ERR_IPE)) {
ring->rx_stats.csum_err++; return;
}
if (!ixgbe_test_staterr(rx_desc, IXGBE_RXD_STAT_L4CS)) return;
if (ixgbe_test_staterr(rx_desc, IXGBE_RXDADV_ERR_TCPE)) { /* * 82599 errata, UDP frames with a 0 checksum can be marked as * checksum errors.
*/ if ((pkt_info & cpu_to_le16(IXGBE_RXDADV_PKTTYPE_UDP)) &&
test_bit(__IXGBE_RX_CSUM_UDP_ZERO_ERR, &ring->state)) return;
ring->rx_stats.csum_err++; return;
}
/* It must be a TCP or UDP packet with a valid checksum */
skb->ip_summed = CHECKSUM_UNNECESSARY; if (encap_pkt) { if (!ixgbe_test_staterr(rx_desc, IXGBE_RXD_STAT_OUTERIPCS)) return;
if (ixgbe_test_staterr(rx_desc, IXGBE_RXDADV_ERR_OUTERIPER)) {
skb->ip_summed = CHECKSUM_NONE; return;
} /* If we checked the outer header let the stack know */
skb->csum_level = 1;
}
}
/* since we are recycling buffers we should seldom need to alloc */ if (likely(page)) returntrue;
/* alloc new page for storage */
page = dev_alloc_pages(ixgbe_rx_pg_order(rx_ring)); if (unlikely(!page)) {
rx_ring->rx_stats.alloc_rx_page_failed++; returnfalse;
}
/* map page for use */
dma = dma_map_page_attrs(rx_ring->dev, page, 0,
ixgbe_rx_pg_size(rx_ring),
DMA_FROM_DEVICE,
IXGBE_RX_DMA_ATTR);
/* * if mapping failed free memory back to system since * there isn't much point in holding memory we can't use
*/ if (dma_mapping_error(rx_ring->dev, dma)) {
__free_pages(page, ixgbe_rx_pg_order(rx_ring));
/** * ixgbe_alloc_rx_buffers - Replace used receive buffers * @rx_ring: ring to place buffers on * @cleaned_count: number of buffers to replace
**/ void ixgbe_alloc_rx_buffers(struct ixgbe_ring *rx_ring, u16 cleaned_count)
{ union ixgbe_adv_rx_desc *rx_desc; struct ixgbe_rx_buffer *bi;
u16 i = rx_ring->next_to_use;
u16 bufsz;
/* nothing to do */ if (!cleaned_count) return;
rx_desc = IXGBE_RX_DESC(rx_ring, i);
bi = &rx_ring->rx_buffer_info[i];
i -= rx_ring->count;
bufsz = ixgbe_rx_bufsz(rx_ring);
do { if (!ixgbe_alloc_mapped_page(rx_ring, bi)) break;
/* sync the buffer for use by the device */
dma_sync_single_range_for_device(rx_ring->dev, bi->dma,
bi->page_offset, bufsz,
DMA_FROM_DEVICE);
/* * Refresh the desc even if buffer_addrs didn't change * because each write-back erases this info.
*/
rx_desc->read.pkt_addr = cpu_to_le64(bi->dma + bi->page_offset);
rx_desc++;
bi++;
i++; if (unlikely(!i)) {
rx_desc = IXGBE_RX_DESC(rx_ring, 0);
bi = rx_ring->rx_buffer_info;
i -= rx_ring->count;
}
/* clear the length for the next_to_use descriptor */
rx_desc->wb.upper.length = 0;
cleaned_count--;
} while (cleaned_count);
i += rx_ring->count;
if (rx_ring->next_to_use != i) {
rx_ring->next_to_use = i;
/* update next to alloc since we have filled the ring */
rx_ring->next_to_alloc = i;
/* Force memory writes to complete before letting h/w * know there are new descriptors to fetch. (Only * applicable for weak-ordered memory model archs, * such as IA-64).
*/
wmb();
writel(i, rx_ring->tail);
}
}
/* set gso_size to avoid messing up TCP MSS */
skb_shinfo(skb)->gso_size = DIV_ROUND_UP((skb->len - hdr_len),
IXGBE_CB(skb)->append_cnt);
skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
}
staticvoid ixgbe_update_rsc_stats(struct ixgbe_ring *rx_ring, struct sk_buff *skb)
{ /* if append_cnt is 0 then frame is not RSC */ if (!IXGBE_CB(skb)->append_cnt) return;
/* gso_size is computed using append_cnt so always clear it last */
IXGBE_CB(skb)->append_cnt = 0;
}
/** * ixgbe_process_skb_fields - Populate skb header fields from Rx descriptor * @rx_ring: rx descriptor ring packet is being transacted on * @rx_desc: pointer to the EOP Rx descriptor * @skb: pointer to current skb being populated * * This function checks the ring, descriptor, and packet information in * order to populate the hash, checksum, VLAN, timestamp, protocol, and * other fields within the skb.
**/ void ixgbe_process_skb_fields(struct ixgbe_ring *rx_ring, union ixgbe_adv_rx_desc *rx_desc, struct sk_buff *skb)
{ struct net_device *dev = rx_ring->netdev;
u32 flags = rx_ring->q_vector->adapter->flags;
ixgbe_update_rsc_stats(rx_ring, skb);
ixgbe_rx_hash(rx_ring, rx_desc, skb);
ixgbe_rx_checksum(rx_ring, rx_desc, skb);
if (unlikely(flags & IXGBE_FLAG_RX_HWTSTAMP_ENABLED))
ixgbe_ptp_rx_hwtstamp(rx_ring, rx_desc, skb);
if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) &&
ixgbe_test_staterr(rx_desc, IXGBE_RXD_STAT_VP)) {
u16 vid = le16_to_cpu(rx_desc->wb.upper.vlan);
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid);
}
if (ixgbe_test_staterr(rx_desc, IXGBE_RXDADV_STAT_SECP))
ixgbe_ipsec_rx(rx_ring, rx_desc, skb);
/* record Rx queue, or update MACVLAN statistics */ if (netif_is_ixgbe(dev))
skb_record_rx_queue(skb, rx_ring->queue_index); else
macvlan_count_rx(netdev_priv(dev), skb->len + ETH_HLEN, true, false);
/** * ixgbe_is_non_eop - process handling of non-EOP buffers * @rx_ring: Rx ring being processed * @rx_desc: Rx descriptor for current buffer * @skb: Current socket buffer containing buffer in progress * * This function updates next to clean. If the buffer is an EOP buffer * this function exits returning false, otherwise it will place the * sk_buff in the next buffer to be chained and return true indicating * that this is in fact a non-EOP buffer.
**/ staticbool ixgbe_is_non_eop(struct ixgbe_ring *rx_ring, union ixgbe_adv_rx_desc *rx_desc, struct sk_buff *skb)
{
u32 ntc = rx_ring->next_to_clean + 1;
/* fetch, update, and store next to clean */
ntc = (ntc < rx_ring->count) ? ntc : 0;
rx_ring->next_to_clean = ntc;
prefetch(IXGBE_RX_DESC(rx_ring, ntc));
/* update RSC append count if present */ if (ring_is_rsc_enabled(rx_ring)) {
__le32 rsc_enabled = rx_desc->wb.lower.lo_dword.data &
cpu_to_le32(IXGBE_RXDADV_RSCCNT_MASK);
if (unlikely(rsc_enabled)) {
u32 rsc_cnt = le32_to_cpu(rsc_enabled);
/* update ntc based on RSC value */
ntc = le32_to_cpu(rx_desc->wb.upper.status_error);
ntc &= IXGBE_RXDADV_NEXTP_MASK;
ntc >>= IXGBE_RXDADV_NEXTP_SHIFT;
}
}
/* if we are the last buffer then there is nothing else to do */ if (likely(ixgbe_test_staterr(rx_desc, IXGBE_RXD_STAT_EOP))) returnfalse;
/* place skb in next buffer to be received */
rx_ring->rx_buffer_info[ntc].skb = skb;
rx_ring->rx_stats.non_eop_descs++;
returntrue;
}
/** * ixgbe_pull_tail - ixgbe specific version of skb_pull_tail * @rx_ring: rx descriptor ring packet is being transacted on * @skb: pointer to current skb being adjusted * * This function is an ixgbe specific version of __pskb_pull_tail. The * main difference between this version and the original function is that * this function can make several assumptions about the state of things * that allow for significant optimizations versus the standard function. * As a result we can do things like drop a frag and maintain an accurate * truesize for the skb.
*/ staticvoid ixgbe_pull_tail(struct ixgbe_ring *rx_ring, struct sk_buff *skb)
{
skb_frag_t *frag = &skb_shinfo(skb)->frags[0]; unsignedchar *va; unsignedint pull_len;
/* * it is valid to use page_address instead of kmap since we are * working with pages allocated out of the lomem pool per * alloc_page(GFP_ATOMIC)
*/
va = skb_frag_address(frag);
/* * we need the header to contain the greater of either ETH_HLEN or * 60 bytes if the skb->len is less than 60 for skb_pad.
*/
pull_len = eth_get_headlen(skb->dev, va, IXGBE_RX_HDR_SIZE);
/* align pull length to size of long to optimize memcpy performance */
skb_copy_to_linear_data(skb, va, ALIGN(pull_len, sizeof(long)));
/* update all of the pointers */
skb_frag_size_sub(frag, pull_len);
skb_frag_off_add(frag, pull_len);
skb->data_len -= pull_len;
skb->tail += pull_len;
}
/** * ixgbe_dma_sync_frag - perform DMA sync for first frag of SKB * @rx_ring: rx descriptor ring packet is being transacted on * @skb: pointer to current skb being updated * * This function provides a basic DMA sync up for the first fragment of an * skb. The reason for doing this is that the first fragment cannot be * unmapped until we have reached the end of packet descriptor for a buffer * chain.
*/ staticvoid ixgbe_dma_sync_frag(struct ixgbe_ring *rx_ring, struct sk_buff *skb)
{ if (ring_uses_build_skb(rx_ring)) { unsignedlong mask = (unsignedlong)ixgbe_rx_pg_size(rx_ring) - 1; unsignedlong offset = (unsignedlong)(skb->data) & mask;
/* If the page was released, just unmap it. */ if (unlikely(IXGBE_CB(skb)->page_released)) {
dma_unmap_page_attrs(rx_ring->dev, IXGBE_CB(skb)->dma,
ixgbe_rx_pg_size(rx_ring),
DMA_FROM_DEVICE,
IXGBE_RX_DMA_ATTR);
}
}
/** * ixgbe_cleanup_headers - Correct corrupted or empty headers * @rx_ring: rx descriptor ring packet is being transacted on * @rx_desc: pointer to the EOP Rx descriptor * @skb: pointer to current skb being fixed * * Check if the skb is valid in the XDP case it will be an error pointer. * Return true in this case to abort processing and advance to next * descriptor. * * Check for corrupted packet headers caused by senders on the local L2 * embedded NIC switch not setting up their Tx Descriptors right. These * should be very rare. * * Also address the case where we are pulling data in on pages only * and as such no data is present in the skb header. * * In addition if skb is not at least 60 bytes we need to pad it so that * it is large enough to qualify as a valid Ethernet frame. * * Returns true if an error was encountered and skb was freed.
**/ bool ixgbe_cleanup_headers(struct ixgbe_ring *rx_ring, union ixgbe_adv_rx_desc *rx_desc, struct sk_buff *skb)
{ struct net_device *netdev = rx_ring->netdev;
/* Verify netdev is present, and that packet does not have any * errors that would be unacceptable to the netdev.
*/ if (!netdev ||
(unlikely(ixgbe_test_staterr(rx_desc,
IXGBE_RXDADV_ERR_FRAME_ERR_MASK) &&
!(netdev->features & NETIF_F_RXALL)))) {
dev_kfree_skb_any(skb); returntrue;
}
/* place header in linear portion of buffer */ if (!skb_headlen(skb))
ixgbe_pull_tail(rx_ring, skb);
#ifdef IXGBE_FCOE /* do not attempt to pad FCoE Frames as this will disrupt DDP */ if (ixgbe_rx_is_fcoe(rx_ring, rx_desc)) returnfalse;
#endif /* if eth_skb_pad returns an error the skb was freed */ if (eth_skb_pad(skb)) returntrue;
returnfalse;
}
/** * ixgbe_reuse_rx_page - page flip buffer and store it back on the ring * @rx_ring: rx descriptor ring to store buffers on * @old_buff: donor buffer to have page reused * * Synchronizes page for reuse by the adapter
**/ staticvoid ixgbe_reuse_rx_page(struct ixgbe_ring *rx_ring, struct ixgbe_rx_buffer *old_buff)
{ struct ixgbe_rx_buffer *new_buff;
u16 nta = rx_ring->next_to_alloc;
new_buff = &rx_ring->rx_buffer_info[nta];
/* update, and store next to alloc */
nta++;
rx_ring->next_to_alloc = (nta < rx_ring->count) ? nta : 0;
/* Transfer page from old buffer to new buffer. * Move each member individually to avoid possible store * forwarding stalls and unnecessary copy of skb.
*/
new_buff->dma = old_buff->dma;
new_buff->page = old_buff->page;
new_buff->page_offset = old_buff->page_offset;
new_buff->pagecnt_bias = old_buff->pagecnt_bias;
}
/* avoid re-using remote and pfmemalloc pages */ if (!dev_page_is_reusable(page)) returnfalse;
#if (PAGE_SIZE < 8192) /* if we are only owner of page we can reuse it */ if (unlikely((rx_buffer_pgcnt - pagecnt_bias) > 1)) returnfalse; #else /* The last offset is a bit aggressive in that we assume the * worst case of FCoE being enabled and using a 3K buffer. * However this should have minimal impact as the 1K extra is * still less than one buffer in size.
*/ #define IXGBE_LAST_OFFSET \
(SKB_WITH_OVERHEAD(PAGE_SIZE) - IXGBE_RXBUFFER_3K) if (rx_buffer->page_offset > IXGBE_LAST_OFFSET) returnfalse; #endif
/* If we have drained the page fragment pool we need to update * the pagecnt_bias and page count so that we fully restock the * number of references the driver holds.
*/ if (unlikely(pagecnt_bias == 1)) {
page_ref_add(page, USHRT_MAX - 1);
rx_buffer->pagecnt_bias = USHRT_MAX;
}
returntrue;
}
/** * ixgbe_add_rx_frag - Add contents of Rx buffer to sk_buff * @rx_ring: rx descriptor ring to transact packets on * @rx_buffer: buffer containing page to add * @skb: sk_buff to place the data into * @size: size of data in rx_buffer * * This function will add the data contained in rx_buffer->page to the skb. * This is done either through a direct copy if the data in the buffer is * less than the skb header size, otherwise it will just attach the page as * a frag to the skb. * * The function will then update the page offset if necessary and return * true if the buffer can be reused by the adapter.
**/ staticvoid ixgbe_add_rx_frag(struct ixgbe_ring *rx_ring, struct ixgbe_rx_buffer *rx_buffer, struct sk_buff *skb, unsignedint size)
{ #if (PAGE_SIZE < 8192) unsignedint truesize = ixgbe_rx_pg_size(rx_ring) / 2; #else unsignedint truesize = rx_ring->rx_offset ?
--> --------------------
--> maximum size reached
--> --------------------
Messung V0.5
¤ Dauer der Verarbeitung: 0.42 Sekunden
(vorverarbeitet)
¤
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.