diff options
Diffstat (limited to 'drivers/net/ethernet/intel/i40e/i40e_txrx.c')
-rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_txrx.c | 131 |
1 files changed, 78 insertions, 53 deletions
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 97d46058d71d..3880e417f167 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -203,7 +203,6 @@ static int i40e_add_del_fdir_udpv4(struct i40e_vsi *vsi, struct i40e_pf *pf = vsi->back; struct udphdr *udp; struct iphdr *ip; - bool err = false; u8 *raw_packet; int ret; static char packet[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0, @@ -219,9 +218,9 @@ static int i40e_add_del_fdir_udpv4(struct i40e_vsi *vsi, udp = (struct udphdr *)(raw_packet + IP_HEADER_OFFSET + sizeof(struct iphdr)); - ip->daddr = fd_data->dst_ip[0]; + ip->daddr = fd_data->dst_ip; udp->dest = fd_data->dst_port; - ip->saddr = fd_data->src_ip[0]; + ip->saddr = fd_data->src_ip; udp->source = fd_data->src_port; fd_data->pctype = I40E_FILTER_PCTYPE_NONF_IPV4_UDP; @@ -230,7 +229,9 @@ static int i40e_add_del_fdir_udpv4(struct i40e_vsi *vsi, dev_info(&pf->pdev->dev, "PCTYPE:%d, Filter command send failed for fd_id:%d (ret = %d)\n", fd_data->pctype, fd_data->fd_id, ret); - err = true; + /* Free the packet buffer since it wasn't added to the ring */ + kfree(raw_packet); + return -EOPNOTSUPP; } else if (I40E_DEBUG_FD & pf->hw.debug_mask) { if (add) dev_info(&pf->pdev->dev, @@ -241,10 +242,13 @@ static int i40e_add_del_fdir_udpv4(struct i40e_vsi *vsi, "Filter deleted for PCTYPE %d loc = %d\n", fd_data->pctype, fd_data->fd_id); } - if (err) - kfree(raw_packet); - return err ? -EOPNOTSUPP : 0; + if (add) + pf->fd_udp4_filter_cnt++; + else + pf->fd_udp4_filter_cnt--; + + return 0; } #define I40E_TCPIP_DUMMY_PACKET_LEN 54 @@ -263,7 +267,6 @@ static int i40e_add_del_fdir_tcpv4(struct i40e_vsi *vsi, struct i40e_pf *pf = vsi->back; struct tcphdr *tcp; struct iphdr *ip; - bool err = false; u8 *raw_packet; int ret; /* Dummy packet */ @@ -281,36 +284,20 @@ static int i40e_add_del_fdir_tcpv4(struct i40e_vsi *vsi, tcp = (struct tcphdr *)(raw_packet + IP_HEADER_OFFSET + sizeof(struct iphdr)); - ip->daddr = fd_data->dst_ip[0]; + ip->daddr = fd_data->dst_ip; tcp->dest = fd_data->dst_port; - ip->saddr = fd_data->src_ip[0]; + ip->saddr = fd_data->src_ip; tcp->source = fd_data->src_port; - if (add) { - pf->fd_tcp_rule++; - if ((pf->flags & I40E_FLAG_FD_ATR_ENABLED) && - I40E_DEBUG_FD & pf->hw.debug_mask) - dev_info(&pf->pdev->dev, "Forcing ATR off, sideband rules for TCP/IPv4 flow being applied\n"); - pf->auto_disable_flags |= I40E_FLAG_FD_ATR_ENABLED; - } else { - pf->fd_tcp_rule = (pf->fd_tcp_rule > 0) ? - (pf->fd_tcp_rule - 1) : 0; - if (pf->fd_tcp_rule == 0) { - if ((pf->flags & I40E_FLAG_FD_ATR_ENABLED) && - I40E_DEBUG_FD & pf->hw.debug_mask) - dev_info(&pf->pdev->dev, "ATR re-enabled due to no sideband TCP/IPv4 rules\n"); - pf->auto_disable_flags &= ~I40E_FLAG_FD_ATR_ENABLED; - } - } - fd_data->pctype = I40E_FILTER_PCTYPE_NONF_IPV4_TCP; ret = i40e_program_fdir_filter(fd_data, raw_packet, pf, add); - if (ret) { dev_info(&pf->pdev->dev, "PCTYPE:%d, Filter command send failed for fd_id:%d (ret = %d)\n", fd_data->pctype, fd_data->fd_id, ret); - err = true; + /* Free the packet buffer since it wasn't added to the ring */ + kfree(raw_packet); + return -EOPNOTSUPP; } else if (I40E_DEBUG_FD & pf->hw.debug_mask) { if (add) dev_info(&pf->pdev->dev, "Filter OK for PCTYPE %d loc = %d)\n", @@ -321,10 +308,23 @@ static int i40e_add_del_fdir_tcpv4(struct i40e_vsi *vsi, fd_data->pctype, fd_data->fd_id); } - if (err) - kfree(raw_packet); + if (add) { + pf->fd_tcp4_filter_cnt++; + if ((pf->flags & I40E_FLAG_FD_ATR_ENABLED) && + I40E_DEBUG_FD & pf->hw.debug_mask) + dev_info(&pf->pdev->dev, "Forcing ATR off, sideband rules for TCP/IPv4 flow being applied\n"); + pf->hw_disabled_flags |= I40E_FLAG_FD_ATR_ENABLED; + } else { + pf->fd_tcp4_filter_cnt--; + if (pf->fd_tcp4_filter_cnt == 0) { + if ((pf->flags & I40E_FLAG_FD_ATR_ENABLED) && + I40E_DEBUG_FD & pf->hw.debug_mask) + dev_info(&pf->pdev->dev, "ATR re-enabled due to no sideband TCP/IPv4 rules\n"); + pf->hw_disabled_flags &= ~I40E_FLAG_FD_ATR_ENABLED; + } + } - return err ? -EOPNOTSUPP : 0; + return 0; } #define I40E_IP_DUMMY_PACKET_LEN 34 @@ -343,7 +343,6 @@ static int i40e_add_del_fdir_ipv4(struct i40e_vsi *vsi, { struct i40e_pf *pf = vsi->back; struct iphdr *ip; - bool err = false; u8 *raw_packet; int ret; int i; @@ -359,18 +358,21 @@ static int i40e_add_del_fdir_ipv4(struct i40e_vsi *vsi, memcpy(raw_packet, packet, I40E_IP_DUMMY_PACKET_LEN); ip = (struct iphdr *)(raw_packet + IP_HEADER_OFFSET); - ip->saddr = fd_data->src_ip[0]; - ip->daddr = fd_data->dst_ip[0]; + ip->saddr = fd_data->src_ip; + ip->daddr = fd_data->dst_ip; ip->protocol = 0; fd_data->pctype = i; ret = i40e_program_fdir_filter(fd_data, raw_packet, pf, add); - if (ret) { dev_info(&pf->pdev->dev, "PCTYPE:%d, Filter command send failed for fd_id:%d (ret = %d)\n", fd_data->pctype, fd_data->fd_id, ret); - err = true; + /* The packet buffer wasn't added to the ring so we + * need to free it now. + */ + kfree(raw_packet); + return -EOPNOTSUPP; } else if (I40E_DEBUG_FD & pf->hw.debug_mask) { if (add) dev_info(&pf->pdev->dev, @@ -383,10 +385,12 @@ static int i40e_add_del_fdir_ipv4(struct i40e_vsi *vsi, } } - if (err) - kfree(raw_packet); + if (add) + pf->fd_ip4_filter_cnt++; + else + pf->fd_ip4_filter_cnt--; - return err ? -EOPNOTSUPP : 0; + return 0; } /** @@ -484,8 +488,8 @@ static void i40e_fd_handle_status(struct i40e_ring *rx_ring, pf->fd_atr_cnt = i40e_get_current_atr_cnt(pf); if ((rx_desc->wb.qword0.hi_dword.fd_id == 0) && - (pf->auto_disable_flags & I40E_FLAG_FD_SB_ENABLED)) { - pf->auto_disable_flags |= I40E_FLAG_FD_ATR_ENABLED; + (pf->hw_disabled_flags & I40E_FLAG_FD_SB_ENABLED)) { + pf->hw_disabled_flags |= I40E_FLAG_FD_ATR_ENABLED; set_bit(__I40E_FD_FLUSH_REQUESTED, &pf->state); } @@ -498,11 +502,11 @@ static void i40e_fd_handle_status(struct i40e_ring *rx_ring, */ if (fcnt_prog >= (fcnt_avail - I40E_FDIR_BUFFER_FULL_MARGIN)) { if ((pf->flags & I40E_FLAG_FD_SB_ENABLED) && - !(pf->auto_disable_flags & + !(pf->hw_disabled_flags & I40E_FLAG_FD_SB_ENABLED)) { if (I40E_DEBUG_FD & pf->hw.debug_mask) dev_warn(&pdev->dev, "FD filter space full, new ntuple rules will not be added\n"); - pf->auto_disable_flags |= + pf->hw_disabled_flags |= I40E_FLAG_FD_SB_ENABLED; } } @@ -1010,7 +1014,6 @@ err: **/ void i40e_clean_rx_ring(struct i40e_ring *rx_ring) { - struct device *dev = rx_ring->dev; unsigned long bi_size; u16 i; @@ -1030,7 +1033,20 @@ void i40e_clean_rx_ring(struct i40e_ring *rx_ring) if (!rx_bi->page) continue; - dma_unmap_page(dev, rx_bi->dma, PAGE_SIZE, DMA_FROM_DEVICE); + /* 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, + rx_bi->dma, + rx_bi->page_offset, + I40E_RXBUFFER_2048, + DMA_FROM_DEVICE); + + /* free resources associated with mapping */ + dma_unmap_page_attrs(rx_ring->dev, rx_bi->dma, + PAGE_SIZE, + DMA_FROM_DEVICE, + I40E_RX_DMA_ATTR); __free_pages(rx_bi->page, 0); rx_bi->page = NULL; @@ -1159,7 +1175,10 @@ static bool i40e_alloc_mapped_page(struct i40e_ring *rx_ring, } /* map page for use */ - dma = dma_map_page(rx_ring->dev, page, 0, PAGE_SIZE, DMA_FROM_DEVICE); + dma = dma_map_page_attrs(rx_ring->dev, page, 0, + PAGE_SIZE, + DMA_FROM_DEVICE, + I40E_RX_DMA_ATTR); /* if mapping failed free memory back to system since * there isn't much point in holding memory we can't use @@ -1219,6 +1238,12 @@ bool i40e_alloc_rx_buffers(struct i40e_ring *rx_ring, u16 cleaned_count) if (!i40e_alloc_mapped_page(rx_ring, bi)) goto no_buffers; + /* sync the buffer for use by the device */ + dma_sync_single_range_for_device(rx_ring->dev, bi->dma, + bi->page_offset, + I40E_RXBUFFER_2048, + DMA_FROM_DEVICE); + /* Refresh the desc even if buffer_addrs didn't change * because each write-back erases this info. */ @@ -1685,8 +1710,8 @@ struct sk_buff *i40e_fetch_rx_buffer(struct i40e_ring *rx_ring, rx_ring->rx_stats.page_reuse_count++; } else { /* we are not reusing the buffer so unmap it */ - dma_unmap_page(rx_ring->dev, rx_buffer->dma, PAGE_SIZE, - DMA_FROM_DEVICE); + dma_unmap_page_attrs(rx_ring->dev, rx_buffer->dma, PAGE_SIZE, + DMA_FROM_DEVICE, I40E_RX_DMA_ATTR); } /* clear contents of buffer_info */ @@ -2079,7 +2104,7 @@ static void i40e_atr(struct i40e_ring *tx_ring, struct sk_buff *skb, if (!(pf->flags & I40E_FLAG_FD_ATR_ENABLED)) return; - if ((pf->auto_disable_flags & I40E_FLAG_FD_ATR_ENABLED)) + if ((pf->hw_disabled_flags & I40E_FLAG_FD_ATR_ENABLED)) return; /* if sampling is disabled do nothing */ @@ -2113,10 +2138,10 @@ static void i40e_atr(struct i40e_ring *tx_ring, struct sk_buff *skb, th = (struct tcphdr *)(hdr.network + hlen); /* Due to lack of space, no more new filters can be programmed */ - if (th->syn && (pf->auto_disable_flags & I40E_FLAG_FD_ATR_ENABLED)) + if (th->syn && (pf->hw_disabled_flags & I40E_FLAG_FD_ATR_ENABLED)) return; if ((pf->flags & I40E_FLAG_HW_ATR_EVICT_CAPABLE) && - (!(pf->auto_disable_flags & I40E_FLAG_HW_ATR_EVICT_CAPABLE))) { + (!(pf->hw_disabled_flags & I40E_FLAG_HW_ATR_EVICT_CAPABLE))) { /* HW ATR eviction will take care of removing filters on FIN * and RST packets. */ @@ -2179,7 +2204,7 @@ static void i40e_atr(struct i40e_ring *tx_ring, struct sk_buff *skb, I40E_TXD_FLTR_QW1_CNTINDEX_MASK; if ((pf->flags & I40E_FLAG_HW_ATR_EVICT_CAPABLE) && - (!(pf->auto_disable_flags & I40E_FLAG_HW_ATR_EVICT_CAPABLE))) + (!(pf->hw_disabled_flags & I40E_FLAG_HW_ATR_EVICT_CAPABLE))) dtype_cmd |= I40E_TXD_FLTR_QW1_ATR_MASK; fdir_desc->qindex_flex_ptype_vsi = cpu_to_le32(flex_ptype); |