/* Repartition PBA for greater than 9k MTU if required */
pba = IGC_PBA_34K;
/* flow control settings * The high water mark must be low enough to fit one full frame * after transmitting the pause frame. As such we must have enough * space to allow for us to complete our current transmit and then * receive the frame that is in progress from the link partner. * Set it to: * - the full Rx FIFO size minus one full Tx plus one full Rx frame
*/
hwm = (pba << 10) - (adapter->max_frame_size + MAX_JUMBO_FRAME_SIZE);
if (!netif_running(adapter->netdev))
igc_power_down_phy_copper_base(&adapter->hw);
/* Enable HW to recognize an 802.1Q VLAN Ethernet packet */
wr32(IGC_VET, ETH_P_8021Q);
/* Re-enable PTP, where applicable. */
igc_ptp_reset(adapter);
/* Re-enable TSN offloading, where applicable. */
igc_tsn_reset(adapter);
igc_get_phy_info(hw);
}
/** * igc_power_up_link - Power up the phy link * @adapter: address of board private structure
*/ staticvoid igc_power_up_link(struct igc_adapter *adapter)
{
igc_reset_phy(&adapter->hw);
igc_power_up_phy_copper(&adapter->hw);
igc_setup_link(&adapter->hw);
}
/** * igc_release_hw_control - release control of the h/w to f/w * @adapter: address of board private structure * * igc_release_hw_control resets CTRL_EXT:DRV_LOAD bit. * For ASF and Pass Through versions of f/w this means that the * driver is no longer loaded.
*/ staticvoid igc_release_hw_control(struct igc_adapter *adapter)
{ struct igc_hw *hw = &adapter->hw;
u32 ctrl_ext;
if (!pci_device_is_present(adapter->pdev)) return;
/* Let firmware take over control of h/w */
ctrl_ext = rd32(IGC_CTRL_EXT);
wr32(IGC_CTRL_EXT,
ctrl_ext & ~IGC_CTRL_EXT_DRV_LOAD);
}
/** * igc_get_hw_control - get control of the h/w from f/w * @adapter: address of board private structure * * igc_get_hw_control sets CTRL_EXT:DRV_LOAD bit. * For ASF and Pass Through versions of f/w this means that * the driver is loaded.
*/ staticvoid igc_get_hw_control(struct igc_adapter *adapter)
{ struct igc_hw *hw = &adapter->hw;
u32 ctrl_ext;
/* Let firmware know the driver has taken over */
ctrl_ext = rd32(IGC_CTRL_EXT);
wr32(IGC_CTRL_EXT,
ctrl_ext | IGC_CTRL_EXT_DRV_LOAD);
}
/** * igc_clean_tx_ring - Free Tx Buffers * @tx_ring: ring to be cleaned
*/ staticvoid igc_clean_tx_ring(struct igc_ring *tx_ring)
{
u16 i = tx_ring->next_to_clean; struct igc_tx_buffer *tx_buffer = &tx_ring->tx_buffer_info[i];
u32 xsk_frames = 0;
while (i != tx_ring->next_to_use) { union igc_adv_tx_desc *eop_desc, *tx_desc;
switch (tx_buffer->type) { case IGC_TX_BUFFER_TYPE_XSK:
xsk_frames++; break; case IGC_TX_BUFFER_TYPE_XDP:
xdp_return_frame(tx_buffer->xdpf);
igc_unmap_tx_buffer(tx_ring->dev, tx_buffer); break; case IGC_TX_BUFFER_TYPE_SKB:
dev_kfree_skb_any(tx_buffer->skb);
igc_unmap_tx_buffer(tx_ring->dev, tx_buffer); break; default:
netdev_warn_once(tx_ring->netdev, "Unknown Tx buffer type\n"); break;
}
/* check for eop_desc to determine the end of the packet */
eop_desc = tx_buffer->next_to_watch;
tx_desc = IGC_TX_DESC(tx_ring, i);
/* unmap remaining buffers */ while (tx_desc != eop_desc) {
tx_buffer++;
tx_desc++;
i++; if (unlikely(i == tx_ring->count)) {
i = 0;
tx_buffer = tx_ring->tx_buffer_info;
tx_desc = IGC_TX_DESC(tx_ring, 0);
}
/* unmap any remaining paged data */ if (dma_unmap_len(tx_buffer, len))
igc_unmap_tx_buffer(tx_ring->dev, tx_buffer);
}
tx_buffer->next_to_watch = NULL;
/* move us one more past the eop_desc for start of next pkt */
tx_buffer++;
i++; if (unlikely(i == tx_ring->count)) {
i = 0;
tx_buffer = tx_ring->tx_buffer_info;
}
}
if (tx_ring->xsk_pool && xsk_frames)
xsk_tx_completed(tx_ring->xsk_pool, xsk_frames);
/* reset BQL for queue */
netdev_tx_reset_queue(txring_txq(tx_ring));
/* Zero out the buffer ring */
memset(tx_ring->tx_buffer_info, 0, sizeof(*tx_ring->tx_buffer_info) * tx_ring->count);
/* Zero out the descriptor ring */
memset(tx_ring->desc, 0, tx_ring->size);
err:
vfree(tx_ring->tx_buffer_info);
netdev_err(ndev, "Unable to allocate memory for Tx descriptor ring\n"); return -ENOMEM;
}
/** * igc_setup_all_tx_resources - wrapper to allocate Tx resources for all queues * @adapter: board private structure * * Return 0 on success, negative on failure
*/ staticint igc_setup_all_tx_resources(struct igc_adapter *adapter)
{ struct net_device *dev = adapter->netdev; int i, err = 0;
for (i = 0; i < adapter->num_tx_queues; i++) {
err = igc_setup_tx_resources(adapter->tx_ring[i]); if (err) {
netdev_err(dev, "Error on Tx queue %u setup\n", i); for (i--; i >= 0; i--)
igc_free_tx_resources(adapter->tx_ring[i]); break;
}
}
return err;
}
staticvoid igc_clean_rx_ring_page_shared(struct igc_ring *rx_ring)
{
u16 i = rx_ring->next_to_clean;
dev_kfree_skb(rx_ring->skb);
rx_ring->skb = NULL;
/* Free all the Rx ring sk_buffs */ while (i != rx_ring->next_to_alloc) { struct igc_rx_buffer *buffer_info = &rx_ring->rx_buffer_info[i];
/* Invalidate cache lines that may have been written to by * device so that we avoid corrupting memory.
*/
dma_sync_single_range_for_cpu(rx_ring->dev,
buffer_info->dma,
buffer_info->page_offset,
igc_rx_bufsz(rx_ring),
DMA_FROM_DEVICE);
/** * igc_free_all_rx_resources - Free Rx Resources for All Queues * @adapter: board private structure * * Free all receive software resources
*/ staticvoid igc_free_all_rx_resources(struct igc_adapter *adapter)
{ int i;
for (i = 0; i < adapter->num_rx_queues; i++)
igc_free_rx_resources(adapter->rx_ring[i]);
}
/** * igc_setup_rx_resources - allocate Rx resources (Descriptors) * @rx_ring: rx descriptor ring (for a specific queue) to setup * * Returns 0 on success, negative on failure
*/ int igc_setup_rx_resources(struct igc_ring *rx_ring)
{ struct net_device *ndev = rx_ring->netdev; struct device *dev = rx_ring->dev;
u8 index = rx_ring->queue_index; int size, desc_len, res;
/* XDP RX-queue info */ if (xdp_rxq_info_is_reg(&rx_ring->xdp_rxq))
xdp_rxq_info_unreg(&rx_ring->xdp_rxq);
res = xdp_rxq_info_reg(&rx_ring->xdp_rxq, ndev, index,
rx_ring->q_vector->napi.napi_id); if (res < 0) {
netdev_err(ndev, "Failed to register xdp_rxq index %u\n",
index); return res;
}
err:
xdp_rxq_info_unreg(&rx_ring->xdp_rxq);
vfree(rx_ring->rx_buffer_info);
rx_ring->rx_buffer_info = NULL;
netdev_err(ndev, "Unable to allocate memory for Rx descriptor ring\n"); return -ENOMEM;
}
/** * igc_setup_all_rx_resources - wrapper to allocate Rx resources * (Descriptors) for all queues * @adapter: board private structure * * Return 0 on success, negative on failure
*/ staticint igc_setup_all_rx_resources(struct igc_adapter *adapter)
{ struct net_device *dev = adapter->netdev; int i, err = 0;
for (i = 0; i < adapter->num_rx_queues; i++) {
err = igc_setup_rx_resources(adapter->rx_ring[i]); if (err) {
netdev_err(dev, "Error on Rx queue %u setup\n", i); for (i--; i >= 0; i--)
igc_free_rx_resources(adapter->rx_ring[i]); break;
}
}
/** * igc_configure_rx_ring - Configure a receive ring after Reset * @adapter: board private structure * @ring: receive ring to be configured * * Configure the Rx unit of the MAC after a reset.
*/ staticvoid igc_configure_rx_ring(struct igc_adapter *adapter, struct igc_ring *ring)
{ struct igc_hw *hw = &adapter->hw; union igc_adv_rx_desc *rx_desc; int reg_idx = ring->reg_idx;
u32 srrctl = 0, rxdctl = 0;
u64 rdba = ring->dma;
u32 buf_size;
/** * igc_configure_rx - Configure receive Unit after Reset * @adapter: board private structure * * Configure the Rx unit of the MAC after a reset.
*/ staticvoid igc_configure_rx(struct igc_adapter *adapter)
{ int i;
/* Setup the HW Rx Head and Tail Descriptor Pointers and * the Base and Length of the Rx Descriptor Ring
*/ for (i = 0; i < adapter->num_rx_queues; i++)
igc_configure_rx_ring(adapter, adapter->rx_ring[i]);
}
/** * igc_configure_tx_ring - Configure transmit ring after Reset * @adapter: board private structure * @ring: tx ring to configure * * Configure a transmit ring after a reset.
*/ staticvoid igc_configure_tx_ring(struct igc_adapter *adapter, struct igc_ring *ring)
{ struct igc_hw *hw = &adapter->hw; int reg_idx = ring->reg_idx;
u64 tdba = ring->dma;
u32 txdctl = 0;
ring->xsk_pool = igc_get_xsk_pool(adapter, ring);
/* disable the queue */
wr32(IGC_TXDCTL(reg_idx), 0);
wrfl();
/** * igc_configure_tx - Configure transmit Unit after Reset * @adapter: board private structure * * Configure the Tx unit of the MAC after a reset.
*/ staticvoid igc_configure_tx(struct igc_adapter *adapter)
{ int i;
for (i = 0; i < adapter->num_tx_queues; i++)
igc_configure_tx_ring(adapter, adapter->tx_ring[i]);
}
/* Disable raw packet checksumming so that RSS hash is placed in * descriptor on writeback. No need to enable TCP/UDP/IP checksum * offloads as they are enabled by default
*/
rxcsum = rd32(IGC_RXCSUM);
rxcsum |= IGC_RXCSUM_PCSD;
/* This is useful for sniffing bad packets. */ if (adapter->netdev->features & NETIF_F_RXALL) { /* UPE and MPE will be handled by normal PROMISC logic * in set_rx_mode
*/
rctl |= (IGC_RCTL_SBP | /* Receive bad packets */
IGC_RCTL_BAM | /* RX All Bcast Pkts */
IGC_RCTL_PMCF); /* RX All MAC Ctrl Pkts */
/* disable queue 0 which icould be enabled by default */
wr32(IGC_TXDCTL(0), 0);
/* Program the Transmit Control Register */
tctl = rd32(IGC_TCTL);
tctl &= ~IGC_TCTL_CT;
tctl |= IGC_TCTL_PSP | IGC_TCTL_RTLC |
(IGC_COLLISION_THRESHOLD << IGC_CT_SHIFT);
/* Enable transmits */
tctl |= IGC_TCTL_EN;
wr32(IGC_TCTL, tctl);
}
/** * igc_set_mac_filter_hw() - Set MAC address filter in hardware * @adapter: Pointer to adapter where the filter should be set * @index: Filter index * @type: MAC address filter type (source or destination) * @addr: MAC address * @queue: If non-negative, queue assignment feature is enabled and frames * matching the filter are enqueued onto 'queue'. Otherwise, queue * assignment is disabled.
*/ staticvoid igc_set_mac_filter_hw(struct igc_adapter *adapter, int index, enum igc_mac_filter_type type, const u8 *addr, int queue)
{ struct net_device *dev = adapter->netdev; struct igc_hw *hw = &adapter->hw;
u32 ral, rah;
if (WARN_ON(index >= hw->mac.rar_entry_count)) return;
netdev_dbg(dev, "MAC address filter set in HW: index %d", index);
}
/** * igc_clear_mac_filter_hw() - Clear MAC address filter in hardware * @adapter: Pointer to adapter where the filter should be cleared * @index: Filter index
*/ staticvoid igc_clear_mac_filter_hw(struct igc_adapter *adapter, int index)
{ struct net_device *dev = adapter->netdev; struct igc_hw *hw = &adapter->hw;
if (WARN_ON(index >= hw->mac.rar_entry_count)) return;
wr32(IGC_RAL(index), 0);
wr32(IGC_RAH(index), 0);
netdev_dbg(dev, "MAC address filter cleared in HW: index %d", index);
}
/* Set default MAC address for the PF in the first RAR entry */ staticvoid igc_set_default_mac_filter(struct igc_adapter *adapter)
{ struct net_device *dev = adapter->netdev;
u8 *addr = adapter->hw.mac.addr;
netdev_dbg(dev, "Set default MAC address filter: address %pM", addr);
/* set the correct pool for the new PF MAC address in entry 0 */
igc_set_default_mac_filter(adapter);
return 0;
}
/** * igc_write_mc_addr_list - write multicast addresses to MTA * @netdev: network interface device structure * * Writes multicast address list to the MTA hash table. * Returns: -ENOMEM on failure * 0 on no addresses written * X on writing X addresses to MTA
**/ staticint igc_write_mc_addr_list(struct net_device *netdev)
{ struct igc_adapter *adapter = netdev_priv(netdev); struct igc_hw *hw = &adapter->hw; struct netdev_hw_addr *ha;
u8 *mta_list; int i;
if (netdev_mc_empty(netdev)) { /* nothing to program, so clear mc list */
igc_update_mc_addr_list(hw, NULL, 0); return 0;
}
mta_list = kcalloc(netdev_mc_count(netdev), 6, GFP_ATOMIC); if (!mta_list) return -ENOMEM;
/* The shared function expects a packed array of only addresses. */
i = 0;
netdev_for_each_mc_addr(ha, netdev)
memcpy(mta_list + (i++ * ETH_ALEN), ha->addr, ETH_ALEN);
if (ktime_compare(txtime, end_of_cycle) >= 0) { if (baset_est != ring->last_ff_cycle) {
*first_flag = true;
ring->last_ff_cycle = baset_est;
if (ktime_compare(end_of_cycle, ring->last_tx_cycle) > 0)
*insert_empty = true;
}
}
/* Introducing a window at end of cycle on which packets * potentially not honor launchtime. Window of 5us chosen * considering software update the tail pointer and packets * are dma'ed to packet buffer.
*/ if ((ktime_sub_ns(end_of_cycle, now) < 5 * NSEC_PER_USEC))
netdev_warn(ring->netdev, "Packet with txtime=%llu may not be honoured\n",
txtime);
i++;
tx_ring->next_to_use = (i < tx_ring->count) ? i : 0;
/* set bits to identify this as an advanced context descriptor */
type_tucmd |= IGC_TXD_CMD_DEXT | IGC_ADVTXD_DTYP_CTXT;
/* For i225, context index must be unique per ring. */ if (test_bit(IGC_RING_FLAG_TX_CTX_IDX, &tx_ring->flags))
mss_l4len_idx |= tx_ring->reg_idx << 4;
if (first_flag)
mss_l4len_idx |= IGC_ADVTXD_TSN_CNTX_FIRST;
static u32 igc_tx_cmd_type(struct sk_buff *skb, u32 tx_flags)
{ /* set type for advanced descriptor with frame checksum insertion */
u32 cmd_type = IGC_ADVTXD_DTYP_DATA |
IGC_ADVTXD_DCMD_DEXT |
IGC_ADVTXD_DCMD_IFCS;
/* set HW vlan bit if vlan is present */
cmd_type |= IGC_SET_FLAG(tx_flags, IGC_TX_FLAGS_VLAN,
IGC_ADVTXD_DCMD_VLE);
/* set segmentation bits for TSO */
cmd_type |= IGC_SET_FLAG(tx_flags, IGC_TX_FLAGS_TSO,
(IGC_ADVTXD_DCMD_TSE));
/* set timestamp bit if present, will select the register set * based on the _TSTAMP(_X) bit.
*/
cmd_type |= IGC_SET_FLAG(tx_flags, IGC_TX_FLAGS_TSTAMP,
(IGC_ADVTXD_MAC_TSTAMP));
/* Use the second timer (free running, in general) for the timestamp */
olinfo_status |= IGC_SET_FLAG(tx_flags, IGC_TX_FLAGS_TSTAMP_TIMER_1,
IGC_TXD_PTP2_TIMER_1);
/* set the timestamp */
first->time_stamp = jiffies;
skb_tx_timestamp(skb);
/* 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). * * We also need this memory barrier to make certain all of the * status bits have been updated before next_to_watch is written.
*/
wmb();
/* set next_to_watch value indicating a packet is present */
first->next_to_watch = tx_desc;
i++; if (i == tx_ring->count)
i = 0;
tx_ring->next_to_use = i;
/* Make sure there is space in the ring for the next send. */
igc_maybe_stop_tx(tx_ring, DESC_NEEDED);
if (netif_xmit_stopped(txring_txq(tx_ring)) || !netdev_xmit_more()) {
writel(i, tx_ring->tail);
}
/* IP header will have to cancel out any data that * is not a part of the outer IP header
*/
ip.v4->check = csum_fold(csum_partial(trans_start,
csum_start - trans_start,
0));
type_tucmd |= IGC_ADVTXD_TUCMD_IPV4;
/* need: 1 descriptor per page * PAGE_SIZE/IGC_MAX_DATA_PER_TXD, * + 1 desc for skb_headlen/IGC_MAX_DATA_PER_TXD, * + 2 desc gap to keep tail from touching head, * + 1 desc for context descriptor, * + 2 desc for inserting an empty packet for launch time, * otherwise try next time
*/ for (f = 0; f < skb_shinfo(skb)->nr_frags; f++)
count += TXD_USE_COUNT(skb_frag_size(
&skb_shinfo(skb)->frags[f]));
if (igc_maybe_stop_tx(tx_ring, count + 5)) { /* this is a hard error */ return NETDEV_TX_BUSY;
}
if (insert_empty) { /* Reset the launch time if the required empty frame fails to * be inserted. However, this packet is not dropped, so it * "dirties" the current Qbv cycle. This ensures that the * upcoming packet, which is scheduled in the next Qbv cycle, * does not require an empty frame. This way, the launch time * continues to function correctly despite the current failure * to insert the empty frame.
*/ if (igc_insert_empty_frame(tx_ring))
launch_time = 0;
}
done: /* record the location of the first descriptor for this packet */
first = &tx_ring->tx_buffer_info[tx_ring->next_to_use];
first->type = IGC_TX_BUFFER_TYPE_SKB;
first->skb = skb;
first->bytecount = skb->len;
first->gso_segs = 1;
if (adapter->qbv_transition || tx_ring->oper_gate_closed) goto out_drop;
/* record initial flags and protocol */
first->tx_flags = tx_flags;
first->protocol = protocol;
/* For preemptible queue, manually pad the skb so that HW includes * padding bytes in mCRC calculation
*/ if (tx_ring->preemptible && skb->len < ETH_ZLEN) { if (skb_padto(skb, ETH_ZLEN)) goto out_drop;
skb_put(skb, ETH_ZLEN - skb->len);
}
/* The minimum packet size with TCTL.PSP set is 17 so pad the skb * in order to meet this minimum size requirement.
*/ if (skb->len < 17) { if (skb_padto(skb, 17)) return NETDEV_TX_OK;
skb->len = 17;
}
/* Ignore Checksum bit is set */ if (igc_test_staterr(rx_desc, IGC_RXD_STAT_IXSM)) return;
/* Rx checksum disabled via ethtool */ if (!(ring->netdev->features & NETIF_F_RXCSUM)) return;
/* TCP/UDP checksum error bit is set */ if (igc_test_staterr(rx_desc,
IGC_RXDEXT_STATERR_L4E |
IGC_RXDEXT_STATERR_IPE)) { /* work around errata with sctp packets where the TCPE aka * L4E bit is set incorrectly on 64 byte (60 byte w/o crc) * packets (aka let the stack check the crc32c)
*/ if (!(skb->len == 60 &&
test_bit(IGC_RING_FLAG_RX_SCTP_CSUM, &ring->flags))) {
u64_stats_update_begin(&ring->rx_syncp);
ring->rx_stats.csum_err++;
u64_stats_update_end(&ring->rx_syncp);
} /* let the stack verify checksum errors */ return;
} /* It must be a TCP or UDP packet with a valid checksum */ if (igc_test_staterr(rx_desc, IGC_RXD_STAT_TCPCS |
IGC_RXD_STAT_UDPCS))
skb->ip_summed = CHECKSUM_UNNECESSARY;
/** * igc_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, protocol, and other fields within the * skb.
*/ staticvoid igc_process_skb_fields(struct igc_ring *rx_ring, union igc_adv_rx_desc *rx_desc, struct sk_buff *skb)
{
igc_rx_hash(rx_ring, rx_desc, skb);
/* we are reusing so sync this buffer for CPU use */
dma_sync_single_range_for_cpu(rx_ring->dev,
rx_buffer->dma,
rx_buffer->page_offset,
size,
DMA_FROM_DEVICE);
/** * igc_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 buffer to be added * * This function will add the data contained in rx_buffer->page to the skb.
*/ staticvoid igc_add_rx_frag(struct igc_ring *rx_ring, struct igc_rx_buffer *rx_buffer, struct sk_buff *skb, unsignedint size)
{ unsignedint truesize;
/* prefetch first cache line of first page */
net_prefetch(xdp->data_meta);
/* build an skb around the page buffer */
skb = napi_build_skb(xdp->data_hard_start, truesize); if (unlikely(!skb)) return NULL;
/* update pointers within the skb to store the data */
skb_reserve(skb, xdp->data - xdp->data_hard_start);
__skb_put(skb, size); if (metasize)
skb_metadata_set(skb, metasize);
/* prefetch first cache line of first page */
net_prefetch(xdp->data_meta);
/* allocate a skb to store the frags */
skb = napi_alloc_skb(&rx_ring->q_vector->napi,
IGC_RX_HDR_LEN + metasize); if (unlikely(!skb)) return NULL;
if (ctx->rx_ts) {
skb_shinfo(skb)->tx_flags |= SKBTX_HW_TSTAMP_NETDEV;
skb_hwtstamps(skb)->netdev_data = ctx->rx_ts;
}
/* Determine available headroom for copy */
headlen = size; if (headlen > IGC_RX_HDR_LEN)
headlen = eth_get_headlen(skb->dev, va, IGC_RX_HDR_LEN);
/* align pull length to size of long to optimize memcpy performance */
memcpy(__skb_put(skb, headlen + metasize), xdp->data_meta,
ALIGN(headlen + metasize, sizeof(long)));
if (metasize) {
skb_metadata_set(skb, metasize);
__skb_pull(skb, metasize);
}
/* update all of the pointers */
size -= headlen; if (size) {
skb_add_rx_frag(skb, 0, rx_buffer->page,
(va + headlen) - page_address(rx_buffer->page),
size, truesize);
igc_rx_buffer_flip(rx_buffer, truesize);
} else {
rx_buffer->pagecnt_bias++;
}
return skb;
}
/** * igc_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 igc_reuse_rx_page(struct igc_ring *rx_ring, struct igc_rx_buffer *old_buff)
{
u16 nta = rx_ring->next_to_alloc; struct igc_rx_buffer *new_buff;
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.
*/
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 #define IGC_LAST_OFFSET \
(SKB_WITH_OVERHEAD(PAGE_SIZE) - IGC_RXBUFFER_2048)
if (rx_buffer->page_offset > IGC_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;
}
/** * igc_is_non_eop - process handling of non-EOP buffers * @rx_ring: Rx ring being processed * @rx_desc: Rx descriptor for current buffer * * 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 igc_is_non_eop(struct igc_ring *rx_ring, union igc_adv_rx_desc *rx_desc)
{
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(IGC_RX_DESC(rx_ring, ntc));
if (likely(igc_test_staterr(rx_desc, IGC_RXD_STAT_EOP))) returnfalse;
returntrue;
}
/** * igc_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 * * 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.
*/ staticbool igc_cleanup_headers(struct igc_ring *rx_ring, union igc_adv_rx_desc *rx_desc, struct sk_buff *skb)
{ if (unlikely(igc_test_staterr(rx_desc, IGC_RXDEXT_STATERR_RXE))) { struct net_device *netdev = rx_ring->netdev;
if (!(netdev->features & NETIF_F_RXALL)) {
dev_kfree_skb_any(skb); returntrue;
}
}
/* if eth_skb_pad returns an error the skb was freed */ if (eth_skb_pad(skb)) returntrue;
returnfalse;
}
staticvoid igc_put_rx_buffer(struct igc_ring *rx_ring, struct igc_rx_buffer *rx_buffer, int rx_buffer_pgcnt)
{ if (igc_can_reuse_rx_page(rx_buffer, rx_buffer_pgcnt)) { /* hand second half of page back to the ring */
igc_reuse_rx_page(rx_ring, rx_buffer);
} else { /* We are not reusing the buffer so unmap it and free * any references we are holding to it
*/
dma_unmap_page_attrs(rx_ring->dev, rx_buffer->dma,
igc_rx_pg_size(rx_ring), DMA_FROM_DEVICE,
IGC_RX_DMA_ATTR);
__page_frag_cache_drain(rx_buffer->page,
rx_buffer->pagecnt_bias);
}
/* clear contents of rx_buffer */
rx_buffer->page = NULL;
}
/* since we are recycling buffers we should seldom need to alloc */ if (likely(page)) returntrue;
/* alloc new page for storage */
page = dev_alloc_pages(igc_rx_pg_order(rx_ring)); if (unlikely(!page)) {
rx_ring->rx_stats.alloc_failed++;
set_bit(IGC_RING_FLAG_RX_ALLOC_FAILED, &rx_ring->flags); returnfalse;
}
/* map page for use */
dma = dma_map_page_attrs(rx_ring->dev, page, 0,
igc_rx_pg_size(rx_ring),
DMA_FROM_DEVICE,
IGC_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_page(page);
/** * igc_alloc_rx_buffers - Replace used receive buffers; packet split * @rx_ring: rx descriptor ring * @cleaned_count: number of buffers to clean
*/ staticvoid igc_alloc_rx_buffers(struct igc_ring *rx_ring, u16 cleaned_count)
{ union igc_adv_rx_desc *rx_desc;
u16 i = rx_ring->next_to_use; struct igc_rx_buffer *bi;
u16 bufsz;
/* nothing to do */ if (!cleaned_count) return;
rx_desc = IGC_RX_DESC(rx_ring, i);
bi = &rx_ring->rx_buffer_info[i];
i -= rx_ring->count;
bufsz = igc_rx_bufsz(rx_ring);
do { if (!igc_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 = IGC_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) { /* record the next descriptor to use */
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);
}
}
staticbool igc_alloc_rx_buffers_zc(struct igc_ring *ring, u16 count)
{ union igc_adv_rx_desc *desc;
u16 i = ring->next_to_use; struct igc_rx_buffer *bi;
dma_addr_t dma; bool ok = true;
if (!count) return ok;
XSK_CHECK_PRIV_TYPE(struct igc_xdp_buff);
desc = IGC_RX_DESC(ring, i);
bi = &ring->rx_buffer_info[i];
i -= ring->count;
do {
bi->xdp = xsk_buff_alloc(ring->xsk_pool); if (!bi->xdp) {
ok = false; break;
}
desc++;
bi++;
i++; if (unlikely(!i)) {
desc = IGC_RX_DESC(ring, 0);
bi = ring->rx_buffer_info;
i -= ring->count;
}
/* Clear the length for the next_to_use descriptor. */
desc->wb.upper.length = 0;
count--;
} while (count);
i += ring->count;
if (ring->next_to_use != i) {
ring->next_to_use = 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, ring->tail);
}
return ok;
}
/* This function requires __netif_tx_lock is held by the caller. */ staticint igc_xdp_init_tx_descriptor(struct igc_ring *ring, struct xdp_frame *xdpf)
{ struct skb_shared_info *sinfo = xdp_get_shared_info_from_frame(xdpf);
u8 nr_frags = unlikely(xdp_frame_has_frags(xdpf)) ? sinfo->nr_frags : 0;
u16 count, index = ring->next_to_use; struct igc_tx_buffer *head = &ring->tx_buffer_info[index]; struct igc_tx_buffer *buffer = head; union igc_adv_tx_desc *desc = IGC_TX_DESC(ring, index);
u32 olinfo_status, len = xdpf->len, cmd_type; void *data = xdpf->data;
u16 i;
count = TXD_USE_COUNT(len); for (i = 0; i < nr_frags; i++)
count += TXD_USE_COUNT(skb_frag_size(&sinfo->frags[i]));
if (igc_maybe_stop_tx(ring, count + 3)) { /* this is a hard error */ return -EBUSY;
}
data = skb_frag_address(&sinfo->frags[i]);
len = skb_frag_size(&sinfo->frags[i]);
i++;
}
desc->read.cmd_type_len |= cpu_to_le32(IGC_TXD_DCMD);
netdev_tx_sent_queue(txring_txq(ring), head->bytecount); /* set the timestamp */
head->time_stamp = jiffies; /* set next_to_watch value indicating a packet is present */
head->next_to_watch = desc;
ring->next_to_use = index;
return 0;
unmap: for (;;) {
buffer = &ring->tx_buffer_info[index]; if (dma_unmap_len(buffer, len))
dma_unmap_page(ring->dev,
dma_unmap_addr(buffer, dma),
dma_unmap_len(buffer, len),
DMA_TO_DEVICE);
dma_unmap_len_set(buffer, len, 0); if (buffer == head) break;
if (!index)
index += ring->count;
index--;
}
return -ENOMEM;
}
struct igc_ring *igc_get_tx_ring(struct igc_adapter *adapter, int cpu)
{ int index = cpu;
if (unlikely(index < 0))
index = 0;
while (index >= adapter->num_tx_queues)
index -= adapter->num_tx_queues;
return adapter->tx_ring[index];
}
staticint igc_xdp_xmit_back(struct igc_adapter *adapter, struct xdp_buff *xdp)
{ struct xdp_frame *xdpf = xdp_convert_buff_to_frame(xdp); int cpu = smp_processor_id(); struct netdev_queue *nq; struct igc_ring *ring; int res;
if (unlikely(!xdpf)) return -EFAULT;
ring = igc_get_tx_ring(adapter, cpu);
nq = txring_txq(ring);
__netif_tx_lock(nq, cpu); /* Avoid transmit queue timeout since we share it with the slow path */
txq_trans_cond_update(nq);
res = igc_xdp_init_tx_descriptor(ring, xdpf);
__netif_tx_unlock(nq); return res;
}
/* This function assumes rcu_read_lock() is held by the caller. */ staticint __igc_xdp_run_prog(struct igc_adapter *adapter, struct bpf_prog *prog, struct xdp_buff *xdp)
{
u32 act = bpf_prog_run_xdp(prog, xdp);
switch (act) { case XDP_PASS: return IGC_XDP_PASS; case XDP_TX: if (igc_xdp_xmit_back(adapter, xdp) < 0) goto out_failure; return IGC_XDP_TX; case XDP_REDIRECT: if (xdp_do_redirect(adapter->netdev, xdp, prog) < 0) goto out_failure; return IGC_XDP_REDIRECT; break; default:
bpf_warn_invalid_xdp_action(adapter->netdev, prog, act);
fallthrough; case XDP_ABORTED:
out_failure:
trace_xdp_exception(adapter->netdev, prog, act);
fallthrough; case XDP_DROP: return IGC_XDP_CONSUMED;
}
}
prog = READ_ONCE(adapter->xdp_prog); if (!prog) {
res = IGC_XDP_PASS; goto out;
}
res = __igc_xdp_run_prog(adapter, prog, xdp);
out: return res;
}
/* This function assumes __netif_tx_lock is held by the caller. */ void igc_flush_tx_descriptors(struct igc_ring *ring)
{ /* Once tail pointer is updated, hardware can fetch the descriptors * any time so we issue a write membar here to ensure all memory * writes are complete before the tail pointer is updated.
*/
wmb();
writel(ring->next_to_use, ring->tail);
}
staticvoid igc_finalize_xdp(struct igc_adapter *adapter, int status)
{ int cpu = smp_processor_id(); struct netdev_queue *nq; struct igc_ring *ring;
if (status & IGC_XDP_TX) {
ring = igc_get_tx_ring(adapter, cpu);
nq = txring_txq(ring);
while (likely(total_packets < budget)) { struct igc_xdp_buff ctx = { .rx_ts = NULL }; struct igc_rx_buffer *rx_buffer; union igc_adv_rx_desc *rx_desc; unsignedint size, truesize; int pkt_offset = 0; void *pktbuf;
/* return some buffers to hardware, one at a time is too slow */ if (cleaned_count >= IGC_RX_BUFFER_WRITE) {
igc_alloc_rx_buffers(rx_ring, cleaned_count);
cleaned_count = 0;
}
rx_desc = IGC_RX_DESC(rx_ring, rx_ring->next_to_clean);
size = le16_to_cpu(rx_desc->wb.upper.length); if (!size) break;
/* This memory barrier is needed to keep us from reading * any other fields out of the rx_desc until we know the * descriptor has been written back
*/
dma_rmb();
/* exit if we failed to retrieve a buffer */ if (!xdp_res && !skb) {
rx_ring->rx_stats.alloc_failed++;
rx_buffer->pagecnt_bias++;
set_bit(IGC_RING_FLAG_RX_ALLOC_FAILED, &rx_ring->flags); break;
}
staticstruct igc_xdp_buff *xsk_buff_to_igc_ctx(struct xdp_buff *xdp)
{ /* xdp_buff pointer used by ZC code path is alloc as xdp_buff_xsk. The * igc_xdp_buff shares its layout with xdp_buff_xsk and private * igc_xdp_buff fields fall into xdp_buff_xsk->cb
*/ return (struct igc_xdp_buff *)xdp;
}
while (likely(total_packets < budget)) { union igc_adv_rx_desc *desc; struct igc_rx_buffer *bi; struct igc_xdp_buff *ctx; unsignedint size; int res;
desc = IGC_RX_DESC(ring, ntc);
size = le16_to_cpu(desc->wb.upper.length); if (!size) break;
/* This memory barrier is needed to keep us from reading * any other fields out of the rx_desc until we know the * descriptor has been written back
*/
dma_rmb();
if (igc_test_staterr(desc, IGC_RXDADV_STAT_TSIP)) {
ctx->rx_ts = bi->xdp->data;
bi->xdp->data += IGC_TS_HDR_LEN;
/* HW timestamp has been copied into local variable. Metadata * length when XDP program is called should be 0.
*/
bi->xdp->data_meta += IGC_TS_HDR_LEN;
size -= IGC_TS_HDR_LEN;
} else {
ctx->rx_ts = NULL;
}
/* Search for available tstamp regs */ for (i = 0; i < IGC_MAX_TX_TSTAMP_REGS; i++) {
tstamp = &adapter->tx_tstamp[i];
/* tstamp->skb and tstamp->xsk_tx_buffer are in union. * When tstamp->skb is equal to NULL, * tstamp->xsk_tx_buffer is equal to NULL as well. * This condition means that the particular tstamp reg * is not occupied by other packet.
*/ if (!tstamp->skb) {
found = true; break;
}
}
/* Return if no available tstamp regs */ if (!found) {
adapter->tx_hwtstamp_skipped++;
spin_unlock_irqrestore(&adapter->ptp_tx_lock,
lock_flags); return;
}
/* Hold the transmit completion until timestamp is ready */
meta_req->tx_buffer->xsk_pending_ts = true;
/* Keep the pointer to tx_timestamp, which is located in XDP * metadata area. It is the location to store the value of * tx hardware timestamp.
*/
xsk_tx_metadata_to_compl(meta_req->meta, &tstamp->xsk_meta);
/* Set timestamp bit based on the _TSTAMP(_X) bit. */
tx_flags |= tstamp->flags;
meta_req->cmd_type |= IGC_SET_FLAG(tx_flags,
IGC_TX_FLAGS_TSTAMP,
(IGC_ADVTXD_MAC_TSTAMP));
meta_req->cmd_type |= IGC_SET_FLAG(tx_flags,
IGC_TX_FLAGS_TSTAMP_1,
(IGC_ADVTXD_TSTAMP_REG_1));
meta_req->cmd_type |= IGC_SET_FLAG(tx_flags,
IGC_TX_FLAGS_TSTAMP_2,
(IGC_ADVTXD_TSTAMP_REG_2));
meta_req->cmd_type |= IGC_SET_FLAG(tx_flags,
IGC_TX_FLAGS_TSTAMP_3,
(IGC_ADVTXD_TSTAMP_REG_3));
launch_time_offset = igc_tx_launchtime(tx_ring,
ns_to_ktime(launch_time),
&first_flag, &insert_empty); if (insert_empty) { /* Disregard the launch time request if the required empty frame * fails to be inserted.
*/ if (igc_insert_empty_frame(tx_ring)) return;
meta_req->tx_buffer =
&tx_ring->tx_buffer_info[tx_ring->next_to_use]; /* Inserting an empty packet requires two descriptors: * one data descriptor and one context descriptor.
*/
used_desc += 2;
}
/* Use one context descriptor to specify launch time and first flag. */
igc_tx_ctxtdesc(tx_ring, launch_time_offset, first_flag, 0, 0, 0);
used_desc += 1;
/* Update the number of used descriptors in this request */
meta_req->used_desc += used_desc;
}
/* Packets with launch time require one data descriptor and one context * descriptor. When the launch time falls into the next Qbv cycle, we * may need to insert an empty packet, which requires two more * descriptors. Therefore, to be safe, we always ensure we have at least * 4 descriptors available.
*/ while (budget >= 4 && xsk_tx_peek_desc(pool, &xdp_desc)) { struct igc_metadata_request meta_req; struct xsk_tx_metadata *meta = NULL; struct igc_tx_buffer *bi;
u32 olinfo_status;
dma_addr_t dma;
if (tx_desc) {
igc_flush_tx_descriptors(ring);
xsk_tx_release(pool);
}
__netif_tx_unlock(nq);
}
/** * igc_clean_tx_irq - Reclaim resources after transmit completes * @q_vector: pointer to q_vector containing needed info * @napi_budget: Used to determine if we are in netpoll * * returns true if ring is completely cleaned
*/ staticbool igc_clean_tx_irq(struct igc_q_vector *q_vector, int napi_budget)
{ struct igc_adapter *adapter = q_vector->adapter; unsignedint total_bytes = 0, total_packets = 0; unsignedint budget = q_vector->tx.work_limit; struct igc_ring *tx_ring = q_vector->tx.ring; unsignedint i = tx_ring->next_to_clean; struct igc_tx_buffer *tx_buffer; union igc_adv_tx_desc *tx_desc;
u32 xsk_frames = 0;
if (test_bit(__IGC_DOWN, &adapter->state)) returntrue;
tx_buffer = &tx_ring->tx_buffer_info[i];
tx_desc = IGC_TX_DESC(tx_ring, i);
i -= tx_ring->count;
do { union igc_adv_tx_desc *eop_desc = tx_buffer->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();
/* if DD is not set pending work has not been completed */ if (!(eop_desc->wb.status & cpu_to_le32(IGC_TXD_STAT_DD))) break;
if (igc_fpe_is_pmac_enabled(adapter) &&
igc_fpe_transmitted_smd_v(tx_desc))
ethtool_mmsv_event_handle(&adapter->fpe.mmsv,
ETHTOOL_MMSV_LD_SENT_VERIFY_MPACKET);
/* Hold the completions while there's a pending tx hardware * timestamp request from XDP Tx metadata.
*/ if (tx_buffer->type == IGC_TX_BUFFER_TYPE_XSK &&
tx_buffer->xsk_pending_ts) break;
/* update the statistics for this packet */
total_bytes += tx_buffer->bytecount;
total_packets += tx_buffer->gso_segs;
switch (tx_buffer->type) { case IGC_TX_BUFFER_TYPE_XSK:
xsk_frames++; break; case IGC_TX_BUFFER_TYPE_XDP:
xdp_return_frame(tx_buffer->xdpf);
igc_unmap_tx_buffer(tx_ring->dev, tx_buffer); break; case IGC_TX_BUFFER_TYPE_SKB:
napi_consume_skb(tx_buffer->skb, napi_budget);
igc_unmap_tx_buffer(tx_ring->dev, tx_buffer); break; default:
netdev_warn_once(tx_ring->netdev, "Unknown Tx buffer type\n"); break;
}
/* clear last DMA location and 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 = IGC_TX_DESC(tx_ring, 0);
}
/* unmap any remaining paged data */ if (dma_unmap_len(tx_buffer, len))
igc_unmap_tx_buffer(tx_ring->dev, tx_buffer);
}
/* 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 = IGC_TX_DESC(tx_ring, 0);
}
/* issue prefetch for next Tx descriptor */
prefetch(tx_desc);
/* update budget accounting */
budget--;
} while (likely(budget));
if (tx_ring->xsk_pool) { if (xsk_frames)
xsk_tx_completed(tx_ring->xsk_pool, xsk_frames); if (xsk_uses_need_wakeup(tx_ring->xsk_pool))
xsk_set_tx_need_wakeup(tx_ring->xsk_pool);
igc_xdp_xmit_zc(tx_ring);
}
if (test_bit(IGC_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags)) { struct igc_hw *hw = &adapter->hw;
/* Detect a transmit hang in hardware, this serializes the * check with the clearing of time_stamp and movement of i
*/
clear_bit(IGC_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags); if (tx_buffer->next_to_watch &&
time_after(jiffies, tx_buffer->time_stamp +
(adapter->tx_timeout_factor * HZ)) &&
!(rd32(IGC_STATUS) & IGC_STATUS_TXOFF) &&
(rd32(IGC_TDH(tx_ring->reg_idx)) != readl(tx_ring->tail)) &&
!tx_ring->oper_gate_closed) { /* detected Tx unit hang */
netdev_err(tx_ring->netdev, "Detected Tx Unit Hang\n" " Tx Queue <%d>\n" " TDH <%x>\n" " TDT <%x>\n" " next_to_use <%x>\n" " next_to_clean <%x>\n" "buffer_info[next_to_clean]\n" " time_stamp <%lx>\n" " next_to_watch <%p>\n" " jiffies <%lx>\n" " desc.status <%x>\n",
tx_ring->queue_index,
rd32(IGC_TDH(tx_ring->reg_idx)),
readl(tx_ring->tail),
tx_ring->next_to_use,
tx_ring->next_to_clean,
tx_buffer->time_stamp,
tx_buffer->next_to_watch,
jiffies,
tx_buffer->next_to_watch->wb.status);
netif_stop_subqueue(tx_ring->netdev,
tx_ring->queue_index);
/* we are about to reset, no point in enabling stuff */ returntrue;
}
}
#define TX_WAKE_THRESHOLD (DESC_NEEDED * 2) if (unlikely(total_packets &&
netif_carrier_ok(tx_ring->netdev) &&
igc_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD)) { /* Make sure that anybody stopping the queue after this * sees the new next_to_clean.
*/
smp_mb(); if (__netif_subqueue_stopped(tx_ring->netdev,
tx_ring->queue_index) &&
!(test_bit(__IGC_DOWN, &adapter->state))) {
netif_wake_subqueue(tx_ring->netdev,
tx_ring->queue_index);
for (i = 0; i < max_entries; i++) {
ral = rd32(IGC_RAL(i));
rah = rd32(IGC_RAH(i));
if (!(rah & IGC_RAH_AV)) continue; if (!!(rah & IGC_RAH_ASEL_SRC_ADDR) != type) continue; if ((rah & IGC_RAH_RAH_MASK) !=
le16_to_cpup((__le16 *)(addr + 4))) continue; if (ral != le32_to_cpup((__le32 *)(addr))) continue;
return i;
}
return -1;
}
staticint igc_get_avail_mac_filter_slot(struct igc_adapter *adapter)
{ struct igc_hw *hw = &adapter->hw; int max_entries = hw->mac.rar_entry_count;
u32 rah; int i;
for (i = 0; i < max_entries; i++) {
rah = rd32(IGC_RAH(i));
if (!(rah & IGC_RAH_AV)) return i;
}
return -1;
}
/** * igc_add_mac_filter() - Add MAC address filter * @adapter: Pointer to adapter where the filter should be added * @type: MAC address filter type (source or destination) * @addr: MAC address * @queue: If non-negative, queue assignment feature is enabled and frames * matching the filter are enqueued onto 'queue'. Otherwise, queue * assignment is disabled. * * Return: 0 in case of success, negative errno code otherwise.
*/ staticint igc_add_mac_filter(struct igc_adapter *adapter, enum igc_mac_filter_type type, const u8 *addr, int queue)
{ struct net_device *dev = adapter->netdev; int index;
index = igc_find_mac_filter(adapter, type, addr); if (index >= 0) goto update_filter;
index = igc_get_avail_mac_filter_slot(adapter); if (index < 0) return -ENOSPC;
netdev_dbg(dev, "Add MAC address filter: index %d type %s address %pM queue %d\n",
index, type == IGC_MAC_FILTER_TYPE_DST ? "dst" : "src",
addr, queue);
/** * igc_del_mac_filter() - Delete MAC address filter * @adapter: Pointer to adapter where the filter should be deleted from * @type: MAC address filter type (source or destination) * @addr: MAC address
*/ staticvoid igc_del_mac_filter(struct igc_adapter *adapter, enum igc_mac_filter_type type, const u8 *addr)
{ struct net_device *dev = adapter->netdev; int index;
index = igc_find_mac_filter(adapter, type, addr); if (index < 0) return;
if (index == 0) { /* If this is the default filter, we don't actually delete it. * We just reset to its default value i.e. disable queue * assignment.
*/
netdev_dbg(dev, "Disable default MAC filter queue assignment");
igc_set_mac_filter_hw(adapter, 0, type, addr, -1);
} else {
netdev_dbg(dev, "Delete MAC address filter: index %d type %s address %pM\n",
index,
type == IGC_MAC_FILTER_TYPE_DST ? "dst" : "src",
addr);
igc_clear_mac_filter_hw(adapter, index);
}
}
/** * igc_add_vlan_prio_filter() - Add VLAN priority filter * @adapter: Pointer to adapter where the filter should be added * @prio: VLAN priority value * @queue: Queue number which matching frames are assigned to * * Return: 0 in case of success, negative errno code otherwise.
*/ staticint igc_add_vlan_prio_filter(struct igc_adapter *adapter, int prio, int queue)
{ struct net_device *dev = adapter->netdev; struct igc_hw *hw = &adapter->hw;
u32 vlanpqf;
vlanpqf = rd32(IGC_VLANPQF);
if (vlanpqf & IGC_VLANPQF_VALID(prio)) {
netdev_dbg(dev, "VLAN priority filter already in use\n"); return -EEXIST;
}
/** * igc_del_vlan_prio_filter() - Delete VLAN priority filter * @adapter: Pointer to adapter where the filter should be deleted from * @prio: VLAN priority value
*/ staticvoid igc_del_vlan_prio_filter(struct igc_adapter *adapter, int prio)
{ struct igc_hw *hw = &adapter->hw;
u32 vlanpqf;
for (i = 0; i < MAX_ETYPE_FILTER; i++) {
u32 etqf = rd32(IGC_ETQF(i));
if (!(etqf & IGC_ETQF_FILTER_ENABLE)) return i;
}
return -1;
}
/** * igc_add_etype_filter() - Add ethertype filter * @adapter: Pointer to adapter where the filter should be added * @etype: Ethertype value * @queue: If non-negative, queue assignment feature is enabled and frames * matching the filter are enqueued onto 'queue'. Otherwise, queue * assignment is disabled. * * Return: 0 in case of success, negative errno code otherwise.
*/ staticint igc_add_etype_filter(struct igc_adapter *adapter, u16 etype, int queue)
{ struct igc_hw *hw = &adapter->hw; int index;
u32 etqf;
index = igc_get_avail_etype_filter_slot(adapter); if (index < 0) return -ENOSPC;
for (i = 0; i < MAX_ETYPE_FILTER; i++) {
u32 etqf = rd32(IGC_ETQF(i));
if ((etqf & IGC_ETQF_ETYPE_MASK) == etype) return i;
}
return -1;
}
/** * igc_del_etype_filter() - Delete ethertype filter * @adapter: Pointer to adapter where the filter should be deleted from * @etype: Ethertype value
*/ staticvoid igc_del_etype_filter(struct igc_adapter *adapter, u16 etype)
{ struct igc_hw *hw = &adapter->hw; int index;
index = igc_find_etype_filter(adapter, etype); if (index < 0) return;
/* Length has to be aligned to 8. Otherwise the filter will fail. Bail * out early to avoid surprises later.
*/ if (input->length % 8 != 0) {
netdev_err(adapter->netdev, "The length of a flex filter has to be 8 byte aligned!\n"); return -EINVAL;
}
/* Select corresponding flex filter register and get base for host table. */
ret = igc_flex_filter_select(adapter, input, &fhft); if (ret) return ret;
/* When adding a filter globally disable flex filter feature. That is * recommended within the datasheet.
*/
wufc = rd32(IGC_WUFC);
wufc &= ~IGC_WUFC_FLEX_HQ;
wr32(IGC_WUFC, wufc);
/* mask is only valid for MASK(7, 0) */
tmp = rd32(fhft + row_idx + 8);
tmp &= ~GENMASK(7, 0);
tmp |= mask[i];
wr32(fhft + row_idx + 8, tmp);
}
/* Enable filter. */
wufc |= IGC_WUFC_FLEX_HQ; if (input->index > 8) { /* Filter 0-7 are enabled via WUFC. The other 24 filters are not. */
u32 wufc_ext = rd32(IGC_WUFC_EXT);
for (i = 0; i < MAX_FLEX_FILTER; i++) { if (i < 8) { if (!(wufc & (IGC_WUFC_FLX0 << i))) return i;
} else { if (!(wufc_ext & (IGC_WUFC_EXT_FLX8 << (i - 8)))) return i;
}
}
/* Add user data */ if (rule->filter.match_flags & IGC_FILTER_FLAG_USER_DATA)
igc_flex_filter_add_field(&flex, &filter->user_data,
user_offset, sizeof(filter->user_data),
filter->user_mask);
/* Add it down to the hardware and enable it. */
ret = igc_write_flex_filter_ll(adapter, &flex); if (ret) return ret;
/* Just disable the filter. The filter table itself is kept * intact. Another flex_filter_add() should override the "old" data * then.
*/ if (reg_index > 8) {
u32 wufc_ext = rd32(IGC_WUFC_EXT);
staticvoid igc_reset_default_queue_filter(struct igc_adapter *adapter)
{ /* Reset the default queue to its default value which is Queue 0 */
igc_set_default_queue_filter(adapter, 0);
}
staticint igc_enable_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule)
{ int err;
if (rule->flex) { return igc_add_flex_filter(adapter, rule);
}
if (rule->filter.match_flags & IGC_FILTER_FLAG_ETHER_TYPE) {
err = igc_add_etype_filter(adapter, rule->filter.etype,
rule->action); if (err) return err;
}
if (rule->filter.match_flags & IGC_FILTER_FLAG_SRC_MAC_ADDR) {
err = igc_add_mac_filter(adapter, IGC_MAC_FILTER_TYPE_SRC,
rule->filter.src_addr, rule->action); if (err) return err;
}
if (rule->filter.match_flags & IGC_FILTER_FLAG_DST_MAC_ADDR) {
err = igc_add_mac_filter(adapter, IGC_MAC_FILTER_TYPE_DST,
rule->filter.dst_addr, rule->action); if (err) return err;
}
if (rule->filter.match_flags & IGC_FILTER_FLAG_VLAN_TCI) { int prio = FIELD_GET(VLAN_PRIO_MASK, rule->filter.vlan_tci);
err = igc_add_vlan_prio_filter(adapter, prio, rule->action); if (err) return err;
}
if (rule->filter.match_flags & IGC_FILTER_FLAG_DEFAULT_QUEUE)
igc_set_default_queue_filter(adapter, rule->action);
if (rule->filter.match_flags & IGC_FILTER_FLAG_ETHER_TYPE)
igc_del_etype_filter(adapter, rule->filter.etype);
if (rule->filter.match_flags & IGC_FILTER_FLAG_VLAN_TCI) { int prio = FIELD_GET(VLAN_PRIO_MASK, rule->filter.vlan_tci);
igc_del_vlan_prio_filter(adapter, prio);
}
if (rule->filter.match_flags & IGC_FILTER_FLAG_SRC_MAC_ADDR)
igc_del_mac_filter(adapter, IGC_MAC_FILTER_TYPE_SRC,
rule->filter.src_addr);
if (rule->filter.match_flags & IGC_FILTER_FLAG_DST_MAC_ADDR)
igc_del_mac_filter(adapter, IGC_MAC_FILTER_TYPE_DST,
rule->filter.dst_addr);
if (rule->filter.match_flags & IGC_FILTER_FLAG_DEFAULT_QUEUE)
igc_reset_default_queue_filter(adapter);
}
/** * igc_get_nfc_rule() - Get NFC rule * @adapter: Pointer to adapter * @location: Rule location * * Context: Expects adapter->nfc_rule_lock to be held by caller. * * Return: Pointer to NFC rule at @location. If not found, NULL.
*/ struct igc_nfc_rule *igc_get_nfc_rule(struct igc_adapter *adapter,
u32 location)
{ struct igc_nfc_rule *rule;
list_for_each_entry(rule, &adapter->nfc_rule_list, list) { if (rule->location == location) return rule; if (rule->location > location) break;
}
return NULL;
}
/** * igc_del_nfc_rule() - Delete NFC rule * @adapter: Pointer to adapter * @rule: Pointer to rule to be deleted * * Disable NFC rule in hardware and delete it from adapter. * * Context: Expects adapter->nfc_rule_lock to be held by caller.
*/ void igc_del_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule)
{
igc_disable_nfc_rule(adapter, rule);
/** * igc_add_nfc_rule() - Add NFC rule * @adapter: Pointer to adapter * @rule: Pointer to rule to be added * * Enable NFC rule in hardware and add it to adapter. * * Context: Expects adapter->nfc_rule_lock to be held by caller. * * Return: 0 on success, negative errno on failure.
*/ int igc_add_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule)
{ struct igc_nfc_rule *pred, *cur; int err;
err = igc_enable_nfc_rule(adapter, rule); if (err) return err;
pred = NULL;
list_for_each_entry(cur, &adapter->nfc_rule_list, list) { if (cur->location >= rule->location) break;
pred = cur;
}
list_add(&rule->list, pred ? &pred->list : &adapter->nfc_rule_list);
adapter->nfc_rule_count++; return 0;
}
/** * igc_enable_empty_addr_recv - Enable Rx of packets with all-zeroes MAC address * @adapter: Pointer to the igc_adapter structure. * * Frame preemption verification requires that packets with the all-zeroes * MAC address are allowed to be received by the driver. This function adds the * all-zeroes destination address to the list of acceptable addresses. * * Return: 0 on success, negative value otherwise.
*/ int igc_enable_empty_addr_recv(struct igc_adapter *adapter)
{
u8 empty[ETH_ALEN] = {};
/** * igc_set_rx_mode - Secondary Unicast, Multicast and Promiscuous mode set * @netdev: network interface device structure * * The set_rx_mode entry point is called whenever the unicast or multicast * address lists or the network interface flags are updated. This routine is * responsible for configuring the hardware for proper unicast, multicast, * promiscuous mode, and all-multi behavior.
*/ staticvoid igc_set_rx_mode(struct net_device *netdev)
{ struct igc_adapter *adapter = netdev_priv(netdev); struct igc_hw *hw = &adapter->hw;
u32 rctl = 0, rlpml = MAX_JUMBO_FRAME_SIZE; int count;
/* Check for Promiscuous and All Multicast modes */ if (netdev->flags & IFF_PROMISC) {
rctl |= IGC_RCTL_UPE | IGC_RCTL_MPE;
} else { if (netdev->flags & IFF_ALLMULTI) {
rctl |= IGC_RCTL_MPE;
} else { /* Write addresses to the MTA, if the attempt fails * then we should just turn on promiscuous mode so * that we can at least receive multicast traffic
*/
count = igc_write_mc_addr_list(netdev); if (count < 0)
rctl |= IGC_RCTL_MPE;
}
}
/* Write addresses to available RAR registers, if there is not * sufficient space to store all the addresses then enable * unicast promiscuous mode
*/ if (__dev_uc_sync(netdev, igc_uc_sync, igc_uc_unsync))
rctl |= IGC_RCTL_UPE;
/* update state of unicast and multicast */
rctl |= rd32(IGC_RCTL) & ~(IGC_RCTL_UPE | IGC_RCTL_MPE);
wr32(IGC_RCTL, rctl);
/* call igc_desc_unused which always leaves * at least 1 descriptor unused to make sure * next_to_use != next_to_clean
*/ for (i = 0; i < adapter->num_rx_queues; i++) { struct igc_ring *ring = adapter->rx_ring[i];
if (ring->xsk_pool)
igc_alloc_rx_buffers_zc(ring, igc_desc_unused(ring)); else
igc_alloc_rx_buffers(ring, igc_desc_unused(ring));
}
}
/** * igc_write_ivar - configure ivar for given MSI-X vector * @hw: pointer to the HW structure * @msix_vector: vector number we are allocating to a given ring * @index: row index of IVAR register to write within IVAR table * @offset: column offset of in IVAR, should be multiple of 8 * * The IVAR table consists of 2 columns, * each containing an cause allocation for an Rx and Tx ring, and a * variable number of rows depending on the number of queues supported.
*/ staticvoid igc_write_ivar(struct igc_hw *hw, int msix_vector, int index, int offset)
{
u32 ivar = array_rd32(IGC_IVAR0, index);
/* clear any bits that are currently set */
ivar &= ~((u32)0xFF << offset);
/* write vector and valid bit */
ivar |= (msix_vector | IGC_IVAR_VALID) << offset;
array_wr32(IGC_IVAR0, index, ivar);
}
staticvoid igc_assign_vector(struct igc_q_vector *q_vector, int msix_vector)
{ struct igc_adapter *adapter = q_vector->adapter; struct igc_hw *hw = &adapter->hw; int rx_queue = IGC_N0_QUEUE; int tx_queue = IGC_N0_QUEUE;
if (q_vector->rx.ring)
rx_queue = q_vector->rx.ring->reg_idx; if (q_vector->tx.ring)
tx_queue = q_vector->tx.ring->reg_idx;
/* add q_vector eims value to global eims_enable_mask */
adapter->eims_enable_mask |= q_vector->eims_value;
/* configure q_vector to set itr on first interrupt */
q_vector->set_itr = 1;
}
/** * igc_configure_msix - Configure MSI-X hardware * @adapter: Pointer to adapter structure * * igc_configure_msix sets up the hardware to properly * generate MSI-X interrupts.
*/ staticvoid igc_configure_msix(struct igc_adapter *adapter)
{ struct igc_hw *hw = &adapter->hw; int i, vector = 0;
u32 tmp;
adapter->eims_enable_mask = 0;
/* set vector for other causes, i.e. link changes */ switch (hw->mac.type) { case igc_i225: /* Turn on MSI-X capability first, or our settings * won't stick. And it will take days to debug.
*/
wr32(IGC_GPIE, IGC_GPIE_MSIX_MODE |
IGC_GPIE_PBA | IGC_GPIE_EIAME |
IGC_GPIE_NSICR);
for (i = 0; i < adapter->num_q_vectors; i++)
synchronize_irq(adapter->msix_entries[vector++].vector);
} else {
synchronize_irq(adapter->pdev->irq);
}
}
void igc_set_flag_queue_pairs(struct igc_adapter *adapter, const u32 max_rss_queues)
{ /* Determine if we need to pair queues. */ /* If rss_queues > half of max_rss_queues, pair the queues in * order to conserve interrupts due to limited supply.
*/ if (adapter->rss_queues > (max_rss_queues / 2))
adapter->flags |= IGC_FLAG_QUEUE_PAIRS; else
adapter->flags &= ~IGC_FLAG_QUEUE_PAIRS;
}
/** * igc_reset_q_vector - Reset config for interrupt vector * @adapter: board private structure to initialize * @v_idx: Index of vector to be reset * * If NAPI is enabled it will delete any references to the * NAPI struct. This is preparation for igc_free_q_vector.
*/ staticvoid igc_reset_q_vector(struct igc_adapter *adapter, int v_idx)
{ struct igc_q_vector *q_vector = adapter->q_vector[v_idx];
/* if we're coming from igc_set_interrupt_capability, the vectors are * not yet allocated
*/ if (!q_vector) return;
if (q_vector->tx.ring)
adapter->tx_ring[q_vector->tx.ring->queue_index] = NULL;
if (q_vector->rx.ring)
adapter->rx_ring[q_vector->rx.ring->queue_index] = NULL;
netif_napi_del(&q_vector->napi);
}
/** * igc_free_q_vector - Free memory allocated for specific interrupt vector * @adapter: board private structure to initialize * @v_idx: Index of vector to be freed * * This function frees the memory allocated to the q_vector.
*/ staticvoid igc_free_q_vector(struct igc_adapter *adapter, int v_idx)
{ struct igc_q_vector *q_vector = adapter->q_vector[v_idx];
adapter->q_vector[v_idx] = NULL;
/* igc_get_stats64() might access the rings on this vector, * we must wait a grace period before freeing it.
*/ if (q_vector)
kfree_rcu(q_vector, rcu);
}
/** * igc_free_q_vectors - Free memory allocated for interrupt vectors * @adapter: board private structure to initialize * * This function frees the memory allocated to the q_vectors. In addition if * NAPI is enabled it will delete any references to the NAPI struct prior * to freeing the q_vector.
*/ staticvoid igc_free_q_vectors(struct igc_adapter *adapter)
{ int v_idx = adapter->num_q_vectors;
while (v_idx--) {
igc_reset_q_vector(adapter, v_idx);
igc_free_q_vector(adapter, v_idx);
}
}
/** * igc_update_itr - update the dynamic ITR value based on statistics * @q_vector: pointer to q_vector * @ring_container: ring info to update the itr for * * Stores a new ITR value based on packets and byte * counts during the last interrupt. The advantage of per interrupt * computation is faster updates and more accurate ITR for the current * traffic pattern. Constants in this function were computed * based on theoretical maximum wire speed and thresholds were set based * on testing data as well as attempting to minimize response time * while increasing bulk throughput. * NOTE: These calculations are only valid when operating in a single- * queue environment.
*/ staticvoid igc_update_itr(struct igc_q_vector *q_vector, struct igc_ring_container *ring_container)
{ unsignedint packets = ring_container->total_packets; unsignedint bytes = ring_container->total_bytes;
u8 itrval = ring_container->itr;
/* no packets, exit with status unchanged */ if (packets == 0) return;
/* for non-gigabit speeds, just fix the interrupt rate at 4000 */ switch (adapter->link_speed) { case SPEED_10: case SPEED_100:
current_itr = 0;
new_itr = IGC_4K_ITR; goto set_itr_now; default: break;
}
switch (current_itr) { /* counts and packets in update_itr are dependent on these numbers */ case lowest_latency:
new_itr = IGC_70K_ITR; /* 70,000 ints/sec */ break; case low_latency:
new_itr = IGC_20K_ITR; /* 20,000 ints/sec */ break; case bulk_latency:
new_itr = IGC_4K_ITR; /* 4,000 ints/sec */ break; default: break;
}
set_itr_now: if (new_itr != q_vector->itr_val) { /* this attempts to bias the interrupt rate towards Bulk * by adding intermediate steps when interrupt rate is * increasing
*/
new_itr = new_itr > q_vector->itr_val ?
max((new_itr * q_vector->itr_val) /
(new_itr + (q_vector->itr_val >> 2)),
new_itr) : new_itr; /* Don't write the value here; it resets the adapter's * internal timer, and causes us to delay far longer than * we should between interrupts. Instead, we write the ITR * value at the beginning of the next interrupt so the timing * ends up being correct.
*/
q_vector->itr_val = new_itr;
q_vector->set_itr = 1;
}
}
staticvoid igc_reset_interrupt_capability(struct igc_adapter *adapter)
{ int v_idx = adapter->num_q_vectors;
while (v_idx--)
igc_reset_q_vector(adapter, v_idx);
}
/** * igc_set_interrupt_capability - set MSI or MSI-X if supported * @adapter: Pointer to adapter structure * @msix: boolean value for MSI-X capability * * Attempt to configure interrupts using the best available * capabilities of the hardware and kernel.
*/ staticvoid igc_set_interrupt_capability(struct igc_adapter *adapter, bool msix)
{ int numvecs, i; int err;
if (!msix) goto msi_only;
adapter->flags |= IGC_FLAG_HAS_MSIX;
/* Number of supported queues. */
adapter->num_rx_queues = adapter->rss_queues;
adapter->num_tx_queues = adapter->rss_queues;
/* start with one vector for every Rx queue */
numvecs = adapter->num_rx_queues;
/* if Tx handler is separate add 1 for every Tx queue */ if (!(adapter->flags & IGC_FLAG_QUEUE_PAIRS))
numvecs += adapter->num_tx_queues;
/* store the number of vectors reserved for queues */
adapter->num_q_vectors = numvecs;
/* add 1 vector for link status interrupts */
numvecs++;
/** * igc_update_ring_itr - update the dynamic ITR value based on packet size * @q_vector: pointer to q_vector * * Stores a new ITR value based on strictly on packet size. This * algorithm is less sophisticated than that used in igc_update_itr, * due to the difficulty of synchronizing statistics across multiple * receive rings. The divisors and thresholds used by this function * were determined based on theoretical maximum wire speed and testing * data, in order to minimize response time while increasing bulk * throughput. * NOTE: This function is called only when operating in a multiqueue * receive environment.
*/ staticvoid igc_update_ring_itr(struct igc_q_vector *q_vector)
{ struct igc_adapter *adapter = q_vector->adapter; int new_val = q_vector->itr_val; int avg_wire_size = 0; unsignedint packets;
/* For non-gigabit speeds, just fix the interrupt rate at 4000 * ints/sec - ITR timer value of 120 ticks.
*/ switch (adapter->link_speed) { case SPEED_10: case SPEED_100:
new_val = IGC_4K_ITR; goto set_itr_val; default: break;
}
packets = q_vector->rx.total_packets; if (packets)
avg_wire_size = q_vector->rx.total_bytes / packets;
/** * igc_cache_ring_register - Descriptor ring to register mapping * @adapter: board private structure to initialize * * Once we know the feature-set enabled for the device, we'll cache * the register offset the descriptor ring is assigned to.
*/ staticvoid igc_cache_ring_register(struct igc_adapter *adapter)
{ int i = 0, j = 0;
switch (adapter->hw.mac.type) { case igc_i225: default: for (; i < adapter->num_rx_queues; i++)
adapter->rx_ring[i]->reg_idx = i; for (; j < adapter->num_tx_queues; j++)
adapter->tx_ring[j]->reg_idx = j; break;
}
}
/** * igc_poll - NAPI Rx polling callback * @napi: napi polling structure * @budget: count of how many packets we should handle
*/ staticint igc_poll(struct napi_struct *napi, int budget)
{ struct igc_q_vector *q_vector = container_of(napi, struct igc_q_vector,
napi); struct igc_ring *rx_ring = q_vector->rx.ring; bool clean_complete = true; int work_done = 0;
if (q_vector->tx.ring)
clean_complete = igc_clean_tx_irq(q_vector, budget);
if (rx_ring) { int cleaned = rx_ring->xsk_pool ?
igc_clean_rx_irq_zc(q_vector, budget) :
igc_clean_rx_irq(q_vector, budget);
/* If all work not completed, return budget and keep polling */ if (!clean_complete) return budget;
/* Exit the polling mode, but don't re-enable interrupts if stack might * poll us due to busy-polling
*/ if (likely(napi_complete_done(napi, work_done)))
igc_ring_irq_enable(q_vector);
return min(work_done, budget - 1);
}
/** * igc_alloc_q_vector - Allocate memory for a single interrupt vector * @adapter: board private structure to initialize * @v_count: q_vectors allocated on adapter, used for ring interleaving * @v_idx: index of vector in adapter struct * @txr_count: total number of Tx rings to allocate * @txr_idx: index of first Tx ring to allocate * @rxr_count: total number of Rx rings to allocate * @rxr_idx: index of first Rx ring to allocate * * We allocate one q_vector. If allocation fails we return -ENOMEM.
*/ staticint igc_alloc_q_vector(struct igc_adapter *adapter, unsignedint v_count, unsignedint v_idx, unsignedint txr_count, unsignedint txr_idx, unsignedint rxr_count, unsignedint rxr_idx)
{ struct igc_q_vector *q_vector; struct igc_ring *ring; int ring_count;
/* igc only supports 1 Tx and/or 1 Rx queue per vector */ if (txr_count > 1 || rxr_count > 1) return -ENOMEM;
ring_count = txr_count + rxr_count;
/* allocate q_vector and rings */
q_vector = adapter->q_vector[v_idx]; if (!q_vector)
q_vector = kzalloc(struct_size(q_vector, ring, ring_count),
GFP_KERNEL); else
memset(q_vector, 0, struct_size(q_vector, ring, ring_count)); if (!q_vector) return -ENOMEM;
/* initialize NAPI */
netif_napi_add(adapter->netdev, &q_vector->napi, igc_poll);
/* tie q_vector and adapter together */
adapter->q_vector[v_idx] = q_vector;
q_vector->adapter = adapter;
/* initialize work limits */
q_vector->tx.work_limit = adapter->tx_work_limit;
while (v_idx--)
igc_free_q_vector(adapter, v_idx);
return -ENOMEM;
}
/** * igc_init_interrupt_scheme - initialize interrupts, allocate queues/vectors * @adapter: Pointer to adapter structure * @msix: boolean for MSI-X capability * * This function initializes the interrupts and allocates all of the queues.
*/ staticint igc_init_interrupt_scheme(struct igc_adapter *adapter, bool msix)
{ struct net_device *dev = adapter->netdev; int err = 0;
igc_set_interrupt_capability(adapter, msix);
err = igc_alloc_q_vectors(adapter); if (err) {
netdev_err(dev, "Unable to allocate memory for vectors\n"); goto err_alloc_q_vectors;
}
/* set default work limits */
adapter->tx_work_limit = IGC_DEFAULT_TX_WORK;
/* adjust max frame to be at least the size of a standard frame */
adapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN +
VLAN_HLEN;
adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
spin_lock_init(&adapter->stats64_lock);
spin_lock_init(&adapter->qbv_tx_lock); /* Assume MSI-X interrupts, will be checked during IRQ allocation */
adapter->flags |= IGC_FLAG_HAS_MSIX;
igc_init_queue_configuration(adapter);
/* This call may decrease the number of queues */ if (igc_init_interrupt_scheme(adapter, true)) {
netdev_err(netdev, "Unable to allocate memory for queues\n"); return -ENOMEM;
}
/* Explicitly disable IRQ since the NIC can be in any state. */
igc_irq_disable(adapter);
/* Prevent stats update while adapter is being reset, or if the pci * connection is down.
*/ if (adapter->link_speed == 0) return; if (pci_channel_offline(pdev)) return;
packets = 0;
bytes = 0;
rcu_read_lock(); for (i = 0; i < adapter->num_rx_queues; i++) { struct igc_ring *ring = adapter->rx_ring[i];
u32 rqdpc = rd32(IGC_RQDPC(i));
if (hw->mac.type >= igc_i225)
wr32(IGC_RQDPC(i), 0);
if (rqdpc) {
ring->rx_stats.drops += rqdpc;
net_stats->rx_fifo_errors += rqdpc;
}
/* Fill out the OS statistics structure */
net_stats->multicast = adapter->stats.mprc;
net_stats->collisions = adapter->stats.colc;
/* Rx Errors */
/* RLEC on some newer hardware can be incorrect so build * our own version based on RUC and ROC
*/
net_stats->rx_errors = adapter->stats.rxerrc +
adapter->stats.crcerrs + adapter->stats.algnerrc +
adapter->stats.ruc + adapter->stats.roc +
adapter->stats.cexterr;
net_stats->rx_length_errors = adapter->stats.ruc +
adapter->stats.roc;
net_stats->rx_crc_errors = adapter->stats.crcerrs;
net_stats->rx_frame_errors = adapter->stats.algnerrc;
net_stats->rx_missed_errors = adapter->stats.mpc;
/** * igc_down - Close the interface * @adapter: board private structure
*/ void igc_down(struct igc_adapter *adapter)
{ struct net_device *netdev = adapter->netdev; struct igc_hw *hw = &adapter->hw;
u32 tctl, rctl; int i = 0;
set_bit(__IGC_DOWN, &adapter->state);
igc_ptp_suspend(adapter);
if (pci_device_is_present(adapter->pdev)) { /* disable receives in the hardware */
rctl = rd32(IGC_RCTL);
wr32(IGC_RCTL, rctl & ~IGC_RCTL_EN); /* flush and sleep below */
} /* set trans_start so we don't get spurious watchdogs during reset */
netif_trans_update(netdev);
if (pci_device_is_present(adapter->pdev)) { /* disable transmits in the hardware */
tctl = rd32(IGC_TCTL);
tctl &= ~IGC_TCTL_EN;
wr32(IGC_TCTL, tctl); /* flush both disables and wait for them to finish */
wrfl();
usleep_range(10000, 20000);
igc_irq_disable(adapter);
}
adapter->flags &= ~IGC_FLAG_NEED_LINK_UPDATE;
for (i = 0; i < adapter->num_q_vectors; i++) { if (adapter->q_vector[i]) {
napi_synchronize(&adapter->q_vector[i]->napi);
igc_set_queue_napi(adapter, i, NULL);
napi_disable(&adapter->q_vector[i]->napi);
}
}
rtnl_lock(); /* If we're already down or resetting, just bail */ if (test_bit(__IGC_DOWN, &adapter->state) ||
test_bit(__IGC_RESETTING, &adapter->state)) {
rtnl_unlock(); return;
}
/** * igc_change_mtu - Change the Maximum Transfer Unit * @netdev: network interface device structure * @new_mtu: new value for maximum frame size * * Returns 0 on success, negative on failure
*/ staticint igc_change_mtu(struct net_device *netdev, int new_mtu)
{ int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; struct igc_adapter *adapter = netdev_priv(netdev);
if (igc_xdp_is_enabled(adapter) && new_mtu > ETH_DATA_LEN) {
netdev_dbg(netdev, "Jumbo frames not supported with XDP"); return -EINVAL;
}
/* adjust max frame to be at least the size of a standard frame */ if (max_frame < (ETH_FRAME_LEN + ETH_FCS_LEN))
max_frame = ETH_FRAME_LEN + ETH_FCS_LEN;
while (test_and_set_bit(__IGC_RESETTING, &adapter->state))
usleep_range(1000, 2000);
/* igc_down has a dependency on max_frame_size */
adapter->max_frame_size = max_frame;
if (netif_running(netdev))
igc_down(adapter);
netdev_dbg(netdev, "changing MTU from %d to %d\n", netdev->mtu, new_mtu);
WRITE_ONCE(netdev->mtu, new_mtu);
if (netif_running(netdev))
igc_up(adapter); else
igc_reset(adapter);
clear_bit(__IGC_RESETTING, &adapter->state);
return 0;
}
/** * igc_tx_timeout - Respond to a Tx Hang * @netdev: network interface device structure * @txqueue: queue number that timed out
**/ staticvoid igc_tx_timeout(struct net_device *netdev, unsignedint __always_unused txqueue)
{ struct igc_adapter *adapter = netdev_priv(netdev); struct igc_hw *hw = &adapter->hw;
/* Do the reset outside of interrupt context */
adapter->tx_timeout_count++;
schedule_work(&adapter->reset_task);
wr32(IGC_EICS,
(adapter->eims_enable_mask & ~adapter->eims_other));
}
/** * igc_get_stats64 - Get System Network Statistics * @netdev: network interface device structure * @stats: rtnl_link_stats64 pointer * * Returns the address of the device statistics structure. * The statistics are updated here and also from the timer callback.
*/ staticvoid igc_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats)
{ struct igc_adapter *adapter = netdev_priv(netdev);
spin_lock(&adapter->stats64_lock); if (!test_bit(__IGC_RESETTING, &adapter->state))
igc_update_stats(adapter);
memcpy(stats, &adapter->stats64, sizeof(*stats));
spin_unlock(&adapter->stats64_lock);
}
static netdev_features_t igc_fix_features(struct net_device *netdev,
netdev_features_t features)
{ /* Since there is no support for separate Rx/Tx vlan accel * enable/disable make sure Tx flag is always in same state as Rx.
*/ if (features & NETIF_F_HW_VLAN_CTAG_RX)
features |= NETIF_F_HW_VLAN_CTAG_TX; else
features &= ~NETIF_F_HW_VLAN_CTAG_TX;
/* Make certain the headers can be described by a context descriptor */
mac_hdr_len = skb_network_offset(skb); if (unlikely(mac_hdr_len > IGC_MAX_MAC_HDR_LEN)) return features & ~(NETIF_F_HW_CSUM |
NETIF_F_SCTP_CRC |
NETIF_F_HW_VLAN_CTAG_TX |
NETIF_F_TSO |
NETIF_F_TSO6);
network_hdr_len = skb_checksum_start(skb) - skb_network_header(skb); if (unlikely(network_hdr_len > IGC_MAX_NETWORK_HDR_LEN)) return features & ~(NETIF_F_HW_CSUM |
NETIF_F_SCTP_CRC |
NETIF_F_TSO |
NETIF_F_TSO6);
/* We can only support IPv4 TSO in tunnels if we can mangle the * inner IP ID field, so strip TSO if MANGLEID is not supported.
*/ if (skb->encapsulation && !(features & NETIF_F_TSO_MANGLEID))
features &= ~NETIF_F_TSO;
/** * igc_msix_other - msix other interrupt handler * @irq: interrupt number * @data: pointer to a q_vector
*/ static irqreturn_t igc_msix_other(int irq, void *data)
{ struct igc_adapter *adapter = data; struct igc_hw *hw = &adapter->hw;
u32 icr = rd32(IGC_ICR);
/* reading ICR causes bit 31 of EICR to be cleared */ if (icr & IGC_ICR_DRSTA)
schedule_work(&adapter->reset_task);
if (icr & IGC_ICR_DOUTSYNC) { /* HW is reporting DMA is out of sync */
adapter->stats.doosync++;
}
if (icr & IGC_ICR_LSC) {
hw->mac.get_link_status = true; /* guard against interrupt when we're going down */ if (!test_bit(__IGC_DOWN, &adapter->state))
mod_timer(&adapter->watchdog_timer, jiffies + 1);
}
if (icr & IGC_ICR_TS)
igc_tsync_interrupt(adapter);
if (num_q_vectors > MAX_Q_VECTORS) {
num_q_vectors = MAX_Q_VECTORS;
dev_warn(&adapter->pdev->dev, "The number of queue vectors (%d) is higher than max allowed (%d)\n",
adapter->num_q_vectors, MAX_Q_VECTORS);
} for (i = 0; i < num_q_vectors; i++) { struct igc_q_vector *q_vector = adapter->q_vector[i];
vector--; for (i = 0; i < vector; i++) {
free_irq(adapter->msix_entries[free_vector++].vector,
adapter->q_vector[i]);
}
err_out: return err;
}
/** * igc_clear_interrupt_scheme - reset the device to a state of no interrupts * @adapter: Pointer to adapter structure * * This function resets the device so that it has 0 rx queues, tx queues, and * MSI-X interrupts allocated.
*/ staticvoid igc_clear_interrupt_scheme(struct igc_adapter *adapter)
{
igc_free_q_vectors(adapter);
igc_reset_interrupt_capability(adapter);
}
/* Need to wait a few seconds after link up to get diagnostic information from * the phy
*/ staticvoid igc_update_phy_info(struct timer_list *t)
{ struct igc_adapter *adapter = timer_container_of(adapter, t,
phy_info_timer);
igc_get_phy_info(&adapter->hw);
}
/** * igc_has_link - check shared code for link and determine up/down * @adapter: pointer to driver private info
*/ bool igc_has_link(struct igc_adapter *adapter)
{ struct igc_hw *hw = &adapter->hw; bool link_active = false;
/* get_link_status is set on LSC (link status) interrupt or * rx sequence error interrupt. get_link_status will stay * false until the igc_check_for_link establishes link * for copper adapters ONLY
*/ if (!hw->mac.get_link_status) returntrue;
hw->mac.ops.check_for_link(hw);
link_active = !hw->mac.get_link_status;
ctrl = rd32(IGC_CTRL); /* Link status message must follow this format */
netdev_info(netdev, "NIC Link is Up %d Mbps %s Duplex, Flow Control: %s\n",
adapter->link_speed,
adapter->link_duplex == FULL_DUPLEX ? "Full" : "Half",
(ctrl & IGC_CTRL_TFCE) &&
(ctrl & IGC_CTRL_RFCE) ? "RX/TX" :
(ctrl & IGC_CTRL_RFCE) ? "RX" :
(ctrl & IGC_CTRL_TFCE) ? "TX" : "None");
/* disable EEE if enabled */ if ((adapter->flags & IGC_FLAG_EEE) &&
adapter->link_duplex == HALF_DUPLEX) {
netdev_info(netdev, "EEE Disabled: unsupported at half duplex. Re-enable using ethtool when at full duplex\n");
adapter->hw.dev_spec._base.eee_enable = false;
adapter->flags &= ~IGC_FLAG_EEE;
}
/* check if SmartSpeed worked */
igc_check_downshift(hw); if (phy->speed_downgraded)
netdev_warn(netdev, "Link Speed was downgraded by SmartSpeed\n");
/* adjust timeout factor according to speed/duplex */
adapter->tx_timeout_factor = 1; switch (adapter->link_speed) { case SPEED_10:
adapter->tx_timeout_factor = 14; break; case SPEED_100: case SPEED_1000: case SPEED_2500:
adapter->tx_timeout_factor = 1; break;
}
/* Once the launch time has been set on the wire, there * is a delay before the link speed can be determined * based on link-up activity. Write into the register * as soon as we know the correct link speed.
*/
igc_tsn_adjust_txtime_offset(adapter);
if (adapter->fpe.mmsv.pmac_enabled)
ethtool_mmsv_link_state_handle(&adapter->fpe.mmsv, true);
if (adapter->link_speed != SPEED_1000) goto no_wait;
/* wait for Remote receiver status OK */
retry_read_status: if (!igc_read_phy_reg(hw, PHY_1000T_STATUS,
&phy_data)) { if (!(phy_data & SR_1000T_REMOTE_RX_STATUS) &&
retry_count) {
msleep(100);
retry_count--; goto retry_read_status;
} elseif (!retry_count) {
netdev_err(netdev, "exceed max 2 second\n");
}
} else {
netdev_err(netdev, "read 1000Base-T Status Reg\n");
}
no_wait:
netif_carrier_on(netdev);
/* link state has changed, schedule phy info update */ if (!test_bit(__IGC_DOWN, &adapter->state))
mod_timer(&adapter->phy_info_timer,
round_jiffies(jiffies + 2 * HZ));
}
} else { if (netif_carrier_ok(netdev)) {
adapter->link_speed = 0;
adapter->link_duplex = 0;
/* Links status message must follow this format */
netdev_info(netdev, "NIC Link is Down\n");
netif_carrier_off(netdev);
if (adapter->fpe.mmsv.pmac_enabled)
ethtool_mmsv_link_state_handle(&adapter->fpe.mmsv, false);
/* link state has changed, schedule phy info update */ if (!test_bit(__IGC_DOWN, &adapter->state))
mod_timer(&adapter->phy_info_timer,
round_jiffies(jiffies + 2 * HZ));
for (i = 0; i < adapter->num_tx_queues; i++) { struct igc_ring *tx_ring = adapter->tx_ring[i];
if (!netif_carrier_ok(netdev)) { /* We've lost link, so the controller stops DMA, * but we've got queued Tx work that's never going * to get done, so reset controller to flush Tx. * (Do the reset outside of interrupt context).
*/ if (igc_desc_unused(tx_ring) + 1 < tx_ring->count) {
adapter->tx_timeout_count++;
schedule_work(&adapter->reset_task); /* return immediately since reset is imminent */ return;
}
}
/* Force detection of hung controller every watchdog period */
set_bit(IGC_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags);
}
/* Cause software interrupt to ensure Rx ring is cleaned */ if (adapter->flags & IGC_FLAG_HAS_MSIX) {
u32 eics = 0;
for (i = 0; i < adapter->num_q_vectors; i++) { struct igc_q_vector *q_vector = adapter->q_vector[i]; struct igc_ring *rx_ring;
if (icr & IGC_ICR_DRSTA)
schedule_work(&adapter->reset_task);
if (icr & IGC_ICR_DOUTSYNC) { /* HW is reporting DMA is out of sync */
adapter->stats.doosync++;
}
if (icr & (IGC_ICR_RXSEQ | IGC_ICR_LSC)) {
hw->mac.get_link_status = true; if (!test_bit(__IGC_DOWN, &adapter->state))
mod_timer(&adapter->watchdog_timer, jiffies + 1);
}
if (icr & IGC_ICR_TS)
igc_tsync_interrupt(adapter);
napi_schedule(&q_vector->napi);
return IRQ_HANDLED;
}
/** * igc_intr - Legacy Interrupt Handler * @irq: interrupt number * @data: pointer to a network interface device structure
*/ static irqreturn_t igc_intr(int irq, void *data)
{ struct igc_adapter *adapter = data; struct igc_q_vector *q_vector = adapter->q_vector[0]; struct igc_hw *hw = &adapter->hw; /* Interrupt Auto-Mask...upon reading ICR, interrupts are masked. No * need for the IMC write
*/
u32 icr = rd32(IGC_ICR);
/* IMS will not auto-mask if INT_ASSERTED is not set, and if it is * not set, then the adapter didn't send an interrupt
*/ if (!(icr & IGC_ICR_INT_ASSERTED)) return IRQ_NONE;
igc_write_itr(q_vector);
if (icr & IGC_ICR_DRSTA)
schedule_work(&adapter->reset_task);
if (icr & IGC_ICR_DOUTSYNC) { /* HW is reporting DMA is out of sync */
adapter->stats.doosync++;
}
if (icr & (IGC_ICR_RXSEQ | IGC_ICR_LSC)) {
hw->mac.get_link_status = true; /* guard against interrupt when we're going down */ if (!test_bit(__IGC_DOWN, &adapter->state))
mod_timer(&adapter->watchdog_timer, jiffies + 1);
}
if (icr & IGC_ICR_TS)
igc_tsync_interrupt(adapter);
napi_schedule(&q_vector->napi);
return IRQ_HANDLED;
}
staticvoid igc_free_irq(struct igc_adapter *adapter)
{ if (adapter->msix_entries) { int vector = 0, i;
for (i = 0; i < adapter->num_q_vectors; i++)
free_irq(adapter->msix_entries[vector++].vector,
adapter->q_vector[i]);
} else {
free_irq(adapter->pdev->irq, adapter);
}
}
/** * igc_request_irq - initialize interrupts * @adapter: Pointer to adapter structure * * Attempts to configure interrupts using the best available * capabilities of the hardware and kernel.
*/ staticint igc_request_irq(struct igc_adapter *adapter)
{ struct net_device *netdev = adapter->netdev; struct pci_dev *pdev = adapter->pdev; int err = 0;
if (adapter->flags & IGC_FLAG_HAS_MSIX) {
err = igc_request_msix(adapter); if (!err) goto request_done; /* fall back to MSI */
igc_free_all_tx_resources(adapter);
igc_free_all_rx_resources(adapter);
if (err)
netdev_err(netdev, "Error %d getting interrupt\n", err);
request_done: return err;
}
/** * __igc_open - Called when a network interface is made active * @netdev: network interface device structure * @resuming: boolean indicating if the device is resuming * * Returns 0 on success, negative value on failure * * The open entry point is called when a network interface is made * active by the system (IFF_UP). At this point all resources needed * for transmit and receive operations are allocated, the interrupt * handler is registered with the OS, the watchdog timer is started, * and the stack is notified that the interface is ready.
*/ staticint __igc_open(struct net_device *netdev, bool resuming)
{ struct igc_adapter *adapter = netdev_priv(netdev); struct pci_dev *pdev = adapter->pdev; struct igc_hw *hw = &adapter->hw; struct napi_struct *napi; int err = 0; int i = 0;
/* disallow open during test */
if (test_bit(__IGC_TESTING, &adapter->state)) {
WARN_ON(resuming); return -EBUSY;
}
int igc_open(struct net_device *netdev)
{ struct igc_adapter *adapter = netdev_priv(netdev); int err;
/* Notify the stack of the actual queue counts. */
err = netif_set_real_num_queues(netdev, adapter->num_tx_queues,
adapter->num_rx_queues); if (err) {
netdev_err(netdev, "error setting real queue count\n"); return err;
}
return __igc_open(netdev, false);
}
/** * __igc_close - Disables a network interface * @netdev: network interface device structure * @suspending: boolean indicating the device is suspending * * Returns 0, this is not allowed to fail * * The close entry point is called when an interface is de-activated * by the OS. The hardware is still under the driver's control, but * needs to be disabled. A global MAC reset is issued to stop the * hardware, and all transmit and receive resources are freed.
*/ staticint __igc_close(struct net_device *netdev, bool suspending)
{ struct igc_adapter *adapter = netdev_priv(netdev); struct pci_dev *pdev = adapter->pdev;
/* If we program the controller's BASET registers with a time * in the future, it will hold all the packets until that * time, causing a lot of TX Hangs, so to avoid that, we * reject schedules that would start in the future. * Note: Limitation above is no longer in i226.
*/ if (!is_base_time_past(qopt->base_time, &now) &&
igc_is_device_id_i225(hw)) returnfalse;
for (n = 0; n < qopt->num_entries; n++) { conststruct tc_taprio_sched_entry *e, *prev; int i;
prev = n ? &qopt->entries[n - 1] : NULL;
e = &qopt->entries[n];
/* i225 only supports "global" frame preemption * settings.
*/ if (e->command != TC_TAPRIO_CMD_SET_GATES) returnfalse;
for (i = 0; i < adapter->num_tx_queues; i++) if (e->gate_mask & BIT(i)) {
queue_uses[i]++;
/* There are limitations: A single queue cannot * be opened and closed multiple times per cycle * unless the gate stays open. Check for it.
*/ if (queue_uses[i] > 1 &&
!(prev->gate_mask & BIT(i))) returnfalse;
}
}
if (igc_is_device_id_i225(hw) && adapter->taprio_offload_enable) return -EALREADY;
if (!validate_schedule(adapter, qopt)) return -EINVAL;
if (qopt->mqprio.preemptible_tcs &&
!(adapter->flags & IGC_FLAG_TSN_REVERSE_TXQ_PRIO)) {
NL_SET_ERR_MSG_MOD(qopt->extack, "reverse-tsn-txq-prio private flag must be enabled before setting preemptible tc"); return -ENODEV;
}
igc_ptp_read(adapter, &now);
if (igc_tsn_is_taprio_activated_by_user(adapter) &&
is_base_time_past(qopt->base_time, &now))
adapter->qbv_config_change_errors++;
for (n = 0; n < qopt->num_entries; n++) { struct tc_taprio_sched_entry *e = &qopt->entries[n];
end_time += e->interval;
/* If any of the conditions below are true, we need to manually * control the end time of the cycle. * 1. Qbv users can specify a cycle time that is not equal * to the total GCL intervals. Hence, recalculation is * necessary here to exclude the time interval that * exceeds the cycle time. * 2. According to IEEE Std. 802.1Q-2018 section 8.6.9.2, * once the end of the list is reached, it will switch * to the END_OF_CYCLE state and leave the gates in the * same state until the next cycle is started.
*/ if (end_time > adapter->cycle_time ||
n + 1 == qopt->num_entries)
end_time = adapter->cycle_time;
for (i = 0; i < adapter->num_tx_queues; i++) { struct igc_ring *ring = adapter->tx_ring[i];
if (!(e->gate_mask & BIT(i))) continue;
/* Check whether a queue stays open for more than one * entry. If so, keep the start and advance the end * time.
*/ if (!queue_configured[i])
ring->start_time = start_time;
ring->end_time = end_time;
/* Check whether a queue gets configured. * If not, set the start and end time to be end time.
*/ for (i = 0; i < adapter->num_tx_queues; i++) { struct igc_ring *ring = adapter->tx_ring[i];
switch (qopt->cmd) { case TAPRIO_CMD_REPLACE:
err = igc_save_qbv_schedule(adapter, qopt); break; case TAPRIO_CMD_DESTROY:
err = igc_tsn_clear_schedule(adapter); break; case TAPRIO_CMD_STATS:
igc_taprio_stats(adapter->netdev, &qopt->stats); return 0; case TAPRIO_CMD_QUEUE_STATS:
igc_taprio_queue_stats(adapter->netdev, &qopt->queue_stats); return 0; default: return -EOPNOTSUPP;
}
if (err) return err;
return igc_tsn_offload_apply(adapter);
}
staticint igc_save_cbs_params(struct igc_adapter *adapter, int queue, bool enable, int idleslope, int sendslope, int hicredit, int locredit)
{ bool cbs_status[IGC_MAX_SR_QUEUES] = { false }; struct net_device *netdev = adapter->netdev; struct igc_ring *ring; int i;
/* i225 has two sets of credit-based shaper logic. * Supporting it only on the top two priority queues
*/ if (queue < 0 || queue > 1) return -EINVAL;
ring = adapter->tx_ring[queue];
for (i = 0; i < IGC_MAX_SR_QUEUES; i++) if (adapter->tx_ring[i])
cbs_status[i] = adapter->tx_ring[i]->cbs_enable;
/* CBS should be enabled on the highest priority queue first in order * for the CBS algorithm to operate as intended.
*/ if (enable) { if (queue == 1 && !cbs_status[0]) {
netdev_err(netdev, "Enabling CBS on queue1 before queue0\n"); return -EINVAL;
}
} else { if (queue == 0 && cbs_status[1]) {
netdev_err(netdev, "Disabling CBS on queue0 before queue1\n"); return -EINVAL;
}
}
/* There are as many TCs as Tx queues. */ if (mqprio->qopt.num_tc != adapter->num_tx_queues) {
NL_SET_ERR_MSG_FMT_MOD(mqprio->extack, "Only %d traffic classes supported",
adapter->num_tx_queues); return -EOPNOTSUPP;
}
/* Only one queue per TC is supported. */ for (i = 0; i < mqprio->qopt.num_tc; i++) { if (mqprio->qopt.count[i] != 1) {
NL_SET_ERR_MSG_MOD(mqprio->extack, "Only one queue per TC supported"); return -EOPNOTSUPP;
}
}
if (!igc_tsn_is_tc_to_queue_priority_ordered(mqprio)) {
NL_SET_ERR_MSG_MOD(mqprio->extack, "tc to queue mapping must preserve increasing priority (higher tc -> higher queue)"); return -EOPNOTSUPP;
}
/* Copy the default MAC and PHY function pointers */
memcpy(&hw->mac.ops, ei->mac_ops, sizeof(hw->mac.ops));
memcpy(&hw->phy.ops, ei->phy_ops, sizeof(hw->phy.ops));
/* setup the private structure */
err = igc_sw_init(adapter); if (err) goto err_sw_init;
/* copy netdev features into list of user selectable features */
netdev->hw_features |= NETIF_F_NTUPLE;
netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX;
netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX;
netdev->hw_features |= netdev->features;
/* before reading the NVM, reset the controller to put the device in a * known good starting state
*/
hw->mac.ops.reset_hw(hw);
if (igc_get_flash_presence_i225(hw)) { if (hw->nvm.ops.validate(hw) < 0) {
dev_err(&pdev->dev, "The NVM Checksum Is Not Valid\n");
err = -EIO; goto err_eeprom;
}
}
if (eth_platform_get_mac_address(&pdev->dev, hw->mac.addr)) { /* copy the MAC address out of the NVM */ if (hw->mac.ops.read_mac_addr(hw))
dev_err(&pdev->dev, "NVM Read Error\n");
}
eth_hw_addr_set(netdev, hw->mac.addr);
if (!is_valid_ether_addr(netdev->dev_addr)) {
dev_err(&pdev->dev, "Invalid MAC Address\n");
err = -EIO; goto err_eeprom;
}
/* configure RXPBSIZE and TXPBSIZE */
wr32(IGC_RXPBS, IGC_RXPBSIZE_EXP_BMC_DEFAULT);
wr32(IGC_TXPBS, IGC_TXPBSIZE_DEFAULT);
/** * igc_remove - Device Removal Routine * @pdev: PCI device information struct * * igc_remove is called by the PCI subsystem to alert the driver * that it should release a PCI device. This could be caused by a * Hot-Plug event, or because the driver is going to be removed from * memory.
*/ staticvoid igc_remove(struct pci_dev *pdev)
{ struct net_device *netdev = pci_get_drvdata(pdev); struct igc_adapter *adapter = netdev_priv(netdev);
if (IS_ENABLED(CONFIG_IGC_LEDS) && adapter->leds_available)
igc_led_free(adapter);
/* Release control of h/w to f/w. If f/w is AMT enabled, this * would have already happened in close and is redundant.
*/
igc_release_hw_control(adapter);
unregister_netdev(netdev);
status = rd32(IGC_STATUS); if (status & IGC_STATUS_LU)
wufc &= ~IGC_WUFC_LNKC;
if (wufc) {
igc_setup_rctl(adapter);
igc_set_rx_mode(netdev);
/* turn on all-multi mode if wake on multicast is enabled */ if (wufc & IGC_WUFC_MC) {
rctl = rd32(IGC_RCTL);
rctl |= IGC_RCTL_MPE;
wr32(IGC_RCTL, rctl);
}
wake = wufc || adapter->en_mng_pt; if (!wake)
igc_power_down_phy_copper_base(&adapter->hw); else
igc_power_up_link(adapter);
if (enable_wake)
*enable_wake = wake;
/* Release control of h/w to f/w. If f/w is AMT enabled, this * would have already happened in close and is redundant.
*/
igc_release_hw_control(adapter);
/* WUPM stores only the first 128 bytes of the wake packet. * Read the packet only if we have the whole thing.
*/ if (wupl == 0 || wupl > IGC_WUPM_BYTES) return;
skb = netdev_alloc_skb_ip_align(netdev, IGC_WUPM_BYTES); if (!skb) return;
/** * igc_io_error_detected - called when PCI error is detected * @pdev: Pointer to PCI device * @state: The current PCI connection state * * This function is called after a PCI bus error affecting * this device has been detected.
**/ static pci_ers_result_t igc_io_error_detected(struct pci_dev *pdev,
pci_channel_state_t state)
{ struct net_device *netdev = pci_get_drvdata(pdev); struct igc_adapter *adapter = netdev_priv(netdev);
rtnl_lock();
netif_device_detach(netdev);
if (state == pci_channel_io_perm_failure) {
rtnl_unlock(); return PCI_ERS_RESULT_DISCONNECT;
}
if (netif_running(netdev))
igc_down(adapter);
pci_disable_device(pdev);
rtnl_unlock();
/* Request a slot reset. */ return PCI_ERS_RESULT_NEED_RESET;
}
/** * igc_io_slot_reset - called after the PCI bus has been reset. * @pdev: Pointer to PCI device * * Restart the card from scratch, as if from a cold-boot. Implementation * resembles the first-half of the __igc_resume routine.
**/ static pci_ers_result_t igc_io_slot_reset(struct pci_dev *pdev)
{ struct net_device *netdev = pci_get_drvdata(pdev); struct igc_adapter *adapter = netdev_priv(netdev); struct igc_hw *hw = &adapter->hw;
pci_ers_result_t result;
if (pci_enable_device_mem(pdev)) {
netdev_err(netdev, "Could not re-enable PCI device after reset\n");
result = PCI_ERS_RESULT_DISCONNECT;
} else {
pci_set_master(pdev);
pci_restore_state(pdev);
pci_save_state(pdev);
if (igc_is_device_id_i226(hw))
pci_disable_link_state_locked(pdev, PCIE_LINK_STATE_L1_2);
/* In case of PCI error, adapter loses its HW address * so we should re-assign it here.
*/
hw->hw_addr = adapter->io_addr;
igc_reset(adapter);
wr32(IGC_WUS, ~0);
result = PCI_ERS_RESULT_RECOVERED;
}
return result;
}
/** * igc_io_resume - called when traffic can start to flow again. * @pdev: Pointer to PCI device * * This callback is called when the error recovery driver tells us that * its OK to resume normal operation. Implementation resembles the * second-half of the __igc_resume routine.
*/ staticvoid igc_io_resume(struct pci_dev *pdev)
{ struct net_device *netdev = pci_get_drvdata(pdev); struct igc_adapter *adapter = netdev_priv(netdev);
rtnl_lock(); if (netif_running(netdev)) { if (igc_open(netdev)) {
rtnl_unlock();
netdev_err(netdev, "igc_open failed after reset\n"); return;
}
}
netif_device_attach(netdev);
/* let the f/w know that the h/w is now under the control of the * driver.
*/
igc_get_hw_control(adapter);
rtnl_unlock();
}
/** * igc_init_module - Driver Registration Routine * * igc_init_module is the first routine called when the driver is * loaded. All it does is register with the PCI subsystem.
*/ staticint __init igc_init_module(void)
{ int ret;
ret = pci_register_driver(&igc_driver); return ret;
}
module_init(igc_init_module);
/** * igc_exit_module - Driver Exit Cleanup Routine * * igc_exit_module is called just before the driver is removed * from memory.
*/ staticvoid __exit igc_exit_module(void)
{
pci_unregister_driver(&igc_driver);
}
module_exit(igc_exit_module); /* igc_main.c */
Messung V0.5 in Prozent
¤ 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.148Bemerkung:
(vorverarbeitet am 2026-04-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.