From 818f2e7b25ac3ae12b1a40690e3aa082ff5896ee Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Tue, 31 Mar 2015 00:44:59 -0700 Subject: i40evf: Fix Outer UDP RX checksum code Inner protocol being UDP should not stop us from verifying Outer UDP checksum correctness. If the Outer protocol is not UDP (NVGRE) we should not be doing a UDP checksum check. If the packet has zero checksum, skip checksum check. Change-ID: Ie7f153feb276a59f66a54a0938901b2c0a8100fa Signed-off-by: Anjali Singhai Jain Tested-by: Jim Young Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c index f41da5d8047b..1b5ee4655b25 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c @@ -915,9 +915,7 @@ static inline void i40e_rx_checksum(struct i40e_vsi *vsi, * so the total length of IPv4 header is IHL*4 bytes * The UDP_0 bit *may* bet set if the *inner* header is UDP */ - if (ipv4_tunnel && - (decoded.inner_prot != I40E_RX_PTYPE_INNER_PROT_UDP) && - !(rx_status & (1 << I40E_RX_DESC_STATUS_UDP_0_SHIFT))) { + if (ipv4_tunnel) { skb->transport_header = skb->mac_header + sizeof(struct ethhdr) + (ip_hdr(skb)->ihl * 4); @@ -927,15 +925,19 @@ static inline void i40e_rx_checksum(struct i40e_vsi *vsi, skb->protocol == htons(ETH_P_8021AD)) ? VLAN_HLEN : 0; - rx_udp_csum = udp_csum(skb); - iph = ip_hdr(skb); - csum = csum_tcpudp_magic( - iph->saddr, iph->daddr, - (skb->len - skb_transport_offset(skb)), - IPPROTO_UDP, rx_udp_csum); + if ((ip_hdr(skb)->protocol == IPPROTO_UDP) && + (udp_hdr(skb)->check != 0)) { + rx_udp_csum = udp_csum(skb); + iph = ip_hdr(skb); + csum = csum_tcpudp_magic(iph->saddr, iph->daddr, + (skb->len - + skb_transport_offset(skb)), + IPPROTO_UDP, rx_udp_csum); - if (udp_hdr(skb)->check != csum) - goto checksum_fail; + if (udp_hdr(skb)->check != csum) + goto checksum_fail; + + } /* else its GRE and so no outer UDP header */ } skb->ip_summed = CHECKSUM_UNNECESSARY; -- cgit v1.2.3 From b57459e913afeca56b43b09f35588e3e8b2b0f26 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Tue, 31 Mar 2015 00:45:00 -0700 Subject: i40e: validate VSI param from VFs Validate that the VF has sent us a valid VSI index before actually using that index. Without this code, a malicious or buggy VF driver could panic the host by sending an invalid index into the VSI array. Change-ID: I66a177687a0dcc281ec83e714d3813d70d18c8b4 Reported-by: Nick Nunley Signed-off-by: Mitch Williams Tested-by: Jim Young Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 0a93684130b9..bb184122f563 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -57,6 +57,8 @@ static inline bool i40e_vc_isvalid_vsi_id(struct i40e_vf *vf, u8 vsi_id) { struct i40e_pf *pf = vf->pf; + if (vsi_id > pf->num_alloc_vsi) + return false; return pf->vsi[vsi_id]->vf_id == vf->vf_id; } -- cgit v1.2.3 From 25fc0e6590d7c18886cab667430c0da16f0586c4 Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Tue, 31 Mar 2015 00:45:01 -0700 Subject: i40e: Print some more info to help figure out the cause of HMC error HMC_ERRORINFO and HMC_ERRORDATA helps explain the cause of HMC error. Change-ID: I053bbc175a5f4c5c3e9ec2ea7400d5c56aaa4ec1 Signed-off-by: Anjali Singhai Jain Tested-by: Jim Young Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 845bceeda645..77e3b84bc367 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -3197,6 +3197,9 @@ static irqreturn_t i40e_intr(int irq, void *data) if (icr0 & I40E_PFINT_ICR0_HMC_ERR_MASK) { icr0 &= ~I40E_PFINT_ICR0_HMC_ERR_MASK; dev_info(&pf->pdev->dev, "HMC error interrupt\n"); + dev_info(&pf->pdev->dev, "HMC error info 0x%x, HMC error data 0x%x\n", + rd32(hw, I40E_PFHMC_ERRORINFO), + rd32(hw, I40E_PFHMC_ERRORDATA)); } if (icr0 & I40E_PFINT_ICR0_TIMESYNC_MASK) { -- cgit v1.2.3 From 1a2f62489b5dc15bd2aadb1de2e38f732e2c4553 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Tue, 31 Mar 2015 00:45:01 -0700 Subject: i40e: Change some memcpys to struct assignments Several memcpys are not necessary and can be changed to structure assignments. Struct assignments are always type safe so this is preferable. Change-ID: I7daf45a4b5e799c686b9d5c8ba9db047584ab82b Signed-off-by: Jesse Brandeburg Tested-by: Jim Young Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 77e3b84bc367..9e19933277e6 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -1969,7 +1969,7 @@ void i40e_vlan_stripping_enable(struct i40e_vsi *vsi) I40E_AQ_VSI_PVLAN_EMOD_STR_BOTH; ctxt.seid = vsi->seid; - memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info)); + ctxt.info = vsi->info; ret = i40e_aq_update_vsi_params(&vsi->back->hw, &ctxt, NULL); if (ret) { dev_info(&vsi->back->pdev->dev, @@ -1998,7 +1998,7 @@ void i40e_vlan_stripping_disable(struct i40e_vsi *vsi) I40E_AQ_VSI_PVLAN_EMOD_NOTHING; ctxt.seid = vsi->seid; - memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info)); + ctxt.info = vsi->info; ret = i40e_aq_update_vsi_params(&vsi->back->hw, &ctxt, NULL); if (ret) { dev_info(&vsi->back->pdev->dev, @@ -2282,7 +2282,7 @@ int i40e_vsi_add_pvid(struct i40e_vsi *vsi, u16 vid) I40E_AQ_VSI_PVLAN_EMOD_STR; ctxt.seid = vsi->seid; - memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info)); + ctxt.info = vsi->info; aq_ret = i40e_aq_update_vsi_params(&vsi->back->hw, &ctxt, NULL); if (aq_ret) { dev_info(&vsi->back->pdev->dev, @@ -4395,7 +4395,7 @@ static int i40e_vsi_config_tc(struct i40e_vsi *vsi, u8 enabled_tc) ctxt.pf_num = vsi->back->hw.pf_id; ctxt.vf_num = 0; ctxt.uplink_seid = vsi->uplink_seid; - memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info)); + ctxt.info = vsi->info; i40e_vsi_setup_queue_map(vsi, &ctxt, enabled_tc, false); /* Update the VSI after updating the VSI queue-mapping information */ @@ -5223,9 +5223,8 @@ static int i40e_handle_lldp_event(struct i40e_pf *pf, goto exit; } - memset(&tmp_dcbx_cfg, 0, sizeof(tmp_dcbx_cfg)); /* Store the old configuration */ - memcpy(&tmp_dcbx_cfg, &hw->local_dcbx_config, sizeof(tmp_dcbx_cfg)); + tmp_dcbx_cfg = hw->local_dcbx_config; /* Reset the old DCBx configuration data */ memset(&hw->local_dcbx_config, 0, sizeof(hw->local_dcbx_config)); @@ -5785,11 +5784,9 @@ static void i40e_handle_link_event(struct i40e_pf *pf, struct i40e_hw *hw = &pf->hw; struct i40e_aqc_get_link_status *status = (struct i40e_aqc_get_link_status *)&e->desc.params.raw; - struct i40e_link_status *hw_link_info = &hw->phy.link_info; /* save off old link status information */ - memcpy(&pf->hw.phy.link_info_old, hw_link_info, - sizeof(pf->hw.phy.link_info_old)); + hw->phy.link_info_old = hw->phy.link_info; /* Do a new status request to re-enable LSE reporting * and load new status information into the hw struct @@ -8272,7 +8269,7 @@ static int i40e_add_vsi(struct i40e_vsi *vsi) ret, pf->hw.aq.asq_last_status); return -ENOENT; } - memcpy(&vsi->info, &ctxt.info, sizeof(ctxt.info)); + vsi->info = ctxt.info; vsi->info.valid_sections = 0; vsi->seid = ctxt.seid; @@ -8406,7 +8403,7 @@ static int i40e_add_vsi(struct i40e_vsi *vsi) ret = -ENOENT; goto err; } - memcpy(&vsi->info, &ctxt.info, sizeof(ctxt.info)); + vsi->info = ctxt.info; vsi->info.valid_sections = 0; vsi->seid = ctxt.seid; vsi->id = ctxt.vsi_number; -- cgit v1.2.3 From 8b6ed9c202c0c7c179ab7a6cf8010ff0b63d2d4f Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Tue, 31 Mar 2015 00:45:01 -0700 Subject: i40e/i40evf: fix bug when skb allocation fails If the skb allocation fails we should not continue using the skb pointer. Breaking out at the point of failure means that at the next RX interrupt the driver will try the allocation again. Change-ID: Iefaad69856ced7418bfd92afe55322676341f82e Signed-off-by: Jesse Brandeburg Tested-by: Jim Young Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 5 ++++- drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 9b11f2e7e361..5a1a67733b88 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -1565,8 +1565,11 @@ static int i40e_clean_rx_irq_ps(struct i40e_ring *rx_ring, int budget) if (likely(!skb)) { skb = netdev_alloc_skb_ip_align(rx_ring->netdev, rx_ring->rx_hdr_len); - if (!skb) + if (!skb) { rx_ring->rx_stats.alloc_buff_failed++; + break; + } + /* initialize queue mapping */ skb_record_rx_queue(skb, rx_ring->queue_index); /* we are reusing so sync this buffer for CPU use */ diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c index 1b5ee4655b25..2be50a8d3671 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c @@ -1040,8 +1040,11 @@ static int i40e_clean_rx_irq_ps(struct i40e_ring *rx_ring, int budget) if (likely(!skb)) { skb = netdev_alloc_skb_ip_align(rx_ring->netdev, rx_ring->rx_hdr_len); - if (!skb) + if (!skb) { rx_ring->rx_stats.alloc_buff_failed++; + break; + } + /* initialize queue mapping */ skb_record_rx_queue(skb, rx_ring->queue_index); /* we are reusing so sync this buffer for CPU use */ -- cgit v1.2.3 From b38da40190a1f8a1a0edcc70f983f7838aabadd4 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Tue, 31 Mar 2015 00:45:02 -0700 Subject: i40e: fix invalid void return in FCoE code A function was calling i40e_tx_map with return, but tx_map returns void, and the caller returns void, so just drop the return, and everything is good. Change-ID: I53fc676d517864761e7cbb8ca83f1ef0c15b1f8f Signed-off-by: Jesse Brandeburg Tested-by: Jim Young Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_fcoe.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_fcoe.c b/drivers/net/ethernet/intel/i40e/i40e_fcoe.c index 1ca48458e668..1803afeef23e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_fcoe.c +++ b/drivers/net/ethernet/intel/i40e/i40e_fcoe.c @@ -1306,8 +1306,7 @@ static void i40e_fcoe_tx_map(struct i40e_ring *tx_ring, /* MACLEN is ether header length in words not bytes */ td_offset |= (maclen >> 1) << I40E_TX_DESC_LENGTH_MACLEN_SHIFT; - return i40e_tx_map(tx_ring, skb, first, tx_flags, hdr_len, - td_cmd, td_offset); + i40e_tx_map(tx_ring, skb, first, tx_flags, hdr_len, td_cmd, td_offset); } /** -- cgit v1.2.3 From 6d7b967db3b1607c789f62936d68ced6321482ed Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Tue, 31 Mar 2015 00:45:02 -0700 Subject: i40e: warn at the right time The call to pci_disable_sriov got moved, but the message about not disabling VFs didn't move. So move it. While we're at, reword the message a bit to make it more consistent with other driver messages. Change-ID: I17d3e15e4fcfd5c9431a96ecb0117d728d3da18b Signed-off-by: Mitch Williams Tested-by: Jim Young Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index bb184122f563..184b00390f57 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -734,6 +734,8 @@ void i40e_free_vfs(struct i40e_pf *pf) */ if (!pci_vfs_assigned(pf->pdev)) pci_disable_sriov(pf->pdev); + else + dev_warn(&pf->pdev->dev, "VFs are assigned - not disabling SR-IOV\n"); msleep(20); /* let any messages in transit get finished up */ @@ -763,9 +765,6 @@ void i40e_free_vfs(struct i40e_pf *pf) bit_idx = (hw->func_caps.vf_base_id + vf_id) % 32; wr32(hw, I40E_GLGEN_VFLRSTAT(reg_idx), (1 << bit_idx)); } - } else { - dev_warn(&pf->pdev->dev, - "unable to disable SR-IOV because VFs are assigned.\n"); } clear_bit(__I40E_VF_DISABLE, &pf->state); } -- cgit v1.2.3 From 31eaaccff0fedb7cf6b6716efa3a2b8b8315ec68 Mon Sep 17 00:00:00 2001 From: Greg Rose Date: Tue, 31 Mar 2015 00:45:03 -0700 Subject: i40e/i40evf: Set Ethernet protocol correctly when Tx VLAN offloads are disabled If transmit VLAN HW offloads are disabled then the network stack sends up an skb with the protocol set to 8021q. In that case to get the correct checksum offloads we have to reset the skb protocol to the encapsulated ethertype. Change-ID: I903d78533de09b1c5d3ec695ee1990dd0fa5dd0d Signed-off-by: Greg Rose Tested-by: Jim Young Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 13 +++++++++++++ drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 14 ++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 5a1a67733b88..d8989f9d1798 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -2057,6 +2057,19 @@ static int i40e_tx_prepare_vlan_flags(struct sk_buff *skb, __be16 protocol = skb->protocol; u32 tx_flags = 0; + if (protocol == htons(ETH_P_8021Q) && + !(tx_ring->netdev->features & NETIF_F_HW_VLAN_CTAG_TX)) { + /* When HW VLAN acceleration is turned off by the user the + * stack sets the protocol to 8021q so that the driver + * can take any steps required to support the SW only + * VLAN handling. In our case the driver doesn't need + * to take any further steps so just set the protocol + * to the encapsulated ethertype. + */ + skb->protocol = vlan_get_protocol(skb); + goto out; + } + /* if we have a HW VLAN tag being added, default to the HW one */ if (skb_vlan_tag_present(skb)) { tx_flags |= skb_vlan_tag_get(skb) << I40E_TX_FLAGS_VLAN_SHIFT; diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c index 2be50a8d3671..e2ddb30e96f5 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c @@ -1370,6 +1370,19 @@ static int i40e_tx_prepare_vlan_flags(struct sk_buff *skb, __be16 protocol = skb->protocol; u32 tx_flags = 0; + if (protocol == htons(ETH_P_8021Q) && + !(tx_ring->netdev->features & NETIF_F_HW_VLAN_CTAG_TX)) { + /* When HW VLAN acceleration is turned off by the user the + * stack sets the protocol to 8021q so that the driver + * can take any steps required to support the SW only + * VLAN handling. In our case the driver doesn't need + * to take any further steps so just set the protocol + * to the encapsulated ethertype. + */ + skb->protocol = vlan_get_protocol(skb); + goto out; + } + /* if we have a HW VLAN tag being added, default to the HW one */ if (skb_vlan_tag_present(skb)) { tx_flags |= skb_vlan_tag_get(skb) << I40E_TX_FLAGS_VLAN_SHIFT; @@ -1386,6 +1399,7 @@ static int i40e_tx_prepare_vlan_flags(struct sk_buff *skb, tx_flags |= I40E_TX_FLAGS_SW_VLAN; } +out: *flags = tx_flags; return 0; } -- cgit v1.2.3 From c142b1dc898efd4702aeacc787bbef8918c401e7 Mon Sep 17 00:00:00 2001 From: Neerav Parikh Date: Tue, 31 Mar 2015 00:45:03 -0700 Subject: i40e: Don't register/de-register apps on NIC partitions in MFP mode Do not register or try to de-register DCB applications with the DCBNL layer in case of NIC partitions when adapter is in MFP mode. Change-ID: I603d042a61983a6562be471c6a2b181572504118 Signed-off-by: Neerav Parikh Tested-by: Jim Young Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c b/drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c index 400fb28db576..bd5079d5c1b6 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c +++ b/drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c @@ -178,6 +178,10 @@ void i40e_dcbnl_set_all(struct i40e_vsi *vsi) if (!(pf->flags & I40E_FLAG_DCB_ENABLED)) return; + /* MFP mode but not an iSCSI PF so return */ + if ((pf->flags & I40E_FLAG_MFP_ENABLED) && !(pf->hw.func_caps.iscsi)) + return; + dcbxcfg = &hw->local_dcbx_config; /* Set up all the App TLVs if DCBx is negotiated */ @@ -282,6 +286,10 @@ void i40e_dcbnl_flush_apps(struct i40e_pf *pf, struct i40e_dcb_app_priority_table app; int i; + /* MFP mode but not an iSCSI PF so return */ + if ((pf->flags & I40E_FLAG_MFP_ENABLED) && !(pf->hw.func_caps.iscsi)) + return; + for (i = 0; i < old_cfg->numapps; i++) { app = old_cfg->app[i]; /* The APP is not available anymore delete it */ -- cgit v1.2.3 From c22c06c8d1b62cd2a42a8f276c7e72bc17067183 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Tue, 31 Mar 2015 00:45:04 -0700 Subject: i40e: fix up VXLAN messages When the VXLAN ports are added and removed, the messaging was giving some bogus index info, the port was always '0' for the delete, and the message text style didn't match other messages in the driver. Also, there was an over-use of the tertiary statement which made reading a little harder than necessary. Change-ID: Ie805182a697b8b4c12024403ada87fd4e4fa2358 Signed-off-by: Shannon Nelson Tested-by: Jim Young Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 38 ++++++++++++++--------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 9e19933277e6..15cee4d7ecf8 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -6608,7 +6608,6 @@ static void i40e_sync_vxlan_filters_subtask(struct i40e_pf *pf) { struct i40e_hw *hw = &pf->hw; i40e_status ret; - u8 filter_index; __be16 port; int i; @@ -6621,22 +6620,20 @@ static void i40e_sync_vxlan_filters_subtask(struct i40e_pf *pf) if (pf->pending_vxlan_bitmap & (1 << i)) { pf->pending_vxlan_bitmap &= ~(1 << i); port = pf->vxlan_ports[i]; - ret = port ? - i40e_aq_add_udp_tunnel(hw, ntohs(port), + if (port) + ret = i40e_aq_add_udp_tunnel(hw, ntohs(port), I40E_AQC_TUNNEL_TYPE_VXLAN, - &filter_index, NULL) - : i40e_aq_del_udp_tunnel(hw, i, NULL); + NULL, NULL); + else + ret = i40e_aq_del_udp_tunnel(hw, i, NULL); if (ret) { - dev_info(&pf->pdev->dev, "Failed to execute AQ command for %s port %d with index %d\n", - port ? "adding" : "deleting", - ntohs(port), port ? i : i); - + dev_info(&pf->pdev->dev, + "%s vxlan port %d, index %d failed, err %d, aq_err %d\n", + port ? "add" : "delete", + ntohs(port), i, ret, + pf->hw.aq.asq_last_status); pf->vxlan_ports[i] = 0; - } else { - dev_info(&pf->pdev->dev, "%s port %d with AQ command with index %d\n", - port ? "Added" : "Deleted", - ntohs(port), port ? i : filter_index); } } } @@ -7829,7 +7826,8 @@ static void i40e_add_vxlan_port(struct net_device *netdev, /* Check if port already exists */ if (idx < I40E_MAX_PF_UDP_OFFLOAD_PORTS) { - netdev_info(netdev, "Port %d already offloaded\n", ntohs(port)); + netdev_info(netdev, "vxlan port %d already offloaded\n", + ntohs(port)); return; } @@ -7837,7 +7835,7 @@ static void i40e_add_vxlan_port(struct net_device *netdev, next_idx = i40e_get_vxlan_port_idx(pf, 0); if (next_idx == I40E_MAX_PF_UDP_OFFLOAD_PORTS) { - netdev_info(netdev, "Maximum number of UDP ports reached, not adding port %d\n", + netdev_info(netdev, "maximum number of vxlan UDP ports reached, not adding port %d\n", ntohs(port)); return; } @@ -7845,8 +7843,9 @@ static void i40e_add_vxlan_port(struct net_device *netdev, /* New port: add it and mark its index in the bitmap */ pf->vxlan_ports[next_idx] = port; pf->pending_vxlan_bitmap |= (1 << next_idx); - pf->flags |= I40E_FLAG_VXLAN_FILTER_SYNC; + + dev_info(&pf->pdev->dev, "adding vxlan port %d\n", ntohs(port)); } /** @@ -7874,12 +7873,13 @@ static void i40e_del_vxlan_port(struct net_device *netdev, * and make it pending */ pf->vxlan_ports[idx] = 0; - pf->pending_vxlan_bitmap |= (1 << idx); - pf->flags |= I40E_FLAG_VXLAN_FILTER_SYNC; + + dev_info(&pf->pdev->dev, "deleting vxlan port %d\n", + ntohs(port)); } else { - netdev_warn(netdev, "Port %d was not found, not deleting\n", + netdev_warn(netdev, "vxlan port %d was not found, not deleting\n", ntohs(port)); } } -- cgit v1.2.3 From 3932dbfe1ecdcf05578cc6aca7ca1b6c6dbd311e Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Tue, 31 Mar 2015 00:45:04 -0700 Subject: i40e: stop flow director on shutdown In some cases, the hardware would continue to try to access the FDIR ring after entering D3Hot state, which would cause either PCIe errors or NMIs, depending upon system configuration. Explicitly stop FDIR in our shutdown routine to eliminate this possibility. Change-ID: Ib98060d6352ec595ab9a78bfe252675a9fa5d8bc Signed-off-by: Mitch Williams Tested-by: Jim Young Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 15cee4d7ecf8..5e79054f2801 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -10210,6 +10210,8 @@ static int i40e_suspend(struct pci_dev *pdev, pm_message_t state) set_bit(__I40E_DOWN, &pf->state); del_timer_sync(&pf->service_timer); cancel_work_sync(&pf->service_task); + i40e_fdir_teardown(pf); + rtnl_lock(); i40e_prep_for_reset(pf); rtnl_unlock(); -- cgit v1.2.3 From fdf0e0bfc363a9b5380ecb5e9c46d6f5a39a9b75 Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Tue, 31 Mar 2015 00:45:05 -0700 Subject: i40e: Communicate VSI id in place of VSI index to the VFs This does not affect the Virtual channel API as such but it changes the meaning of what is communicated to the VSI resource struct as vsi_id. Earlier vsi_idx was being passed in, which was the index in the PF's VSI array. Now we pass vsi_id as communicated by the FW to the driver. This will help with future expansion of VF and FW communication. With this in place now the VF and Virtual channel driver change to move over to VSI id use is complete and is validated. Change-ID: I14246ef82b3b3dc1fa76291d2dd0c05d12cedb7c Signed-off-by: Anjali Singhai Jain Tested-by: Jim Young Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 1 + drivers/net/ethernet/intel/i40e/i40e_main.c | 16 +++ drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 110 +++++++++++---------- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h | 2 +- 4 files changed, 76 insertions(+), 53 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 1c8bd7c152c2..33c35d3b7420 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -628,6 +628,7 @@ extern const char i40e_driver_name[]; extern const char i40e_driver_version_str[]; void i40e_do_reset_safe(struct i40e_pf *pf, u32 reset_flags); void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags); +struct i40e_vsi *i40e_find_vsi_from_id(struct i40e_pf *pf, u16 id); void i40e_update_stats(struct i40e_vsi *vsi); void i40e_update_eth_stats(struct i40e_vsi *vsi); struct rtnl_link_stats64 *i40e_get_vsi_stats_struct(struct i40e_vsi *vsi); diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 5e79054f2801..89a2d76a1f69 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -249,6 +249,22 @@ static int i40e_put_lump(struct i40e_lump_tracking *pile, u16 index, u16 id) return count; } +/** + * i40e_find_vsi_from_id - searches for the vsi with the given id + * @pf - the pf structure to search for the vsi + * @id - id of the vsi it is searching for + **/ +struct i40e_vsi *i40e_find_vsi_from_id(struct i40e_pf *pf, u16 id) +{ + int i; + + for (i = 0; i < pf->num_alloc_vsi; i++) + if (pf->vsi[i] && (pf->vsi[i]->id == id)) + return pf->vsi[i]; + + return NULL; +} + /** * i40e_service_event_schedule - Schedule the service task to wake up * @pf: board private structure diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 184b00390f57..4d69e1f04901 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -53,13 +53,12 @@ static inline void i40e_vc_disable_vf(struct i40e_pf *pf, struct i40e_vf *vf) * * check for the valid VSI id **/ -static inline bool i40e_vc_isvalid_vsi_id(struct i40e_vf *vf, u8 vsi_id) +static inline bool i40e_vc_isvalid_vsi_id(struct i40e_vf *vf, u16 vsi_id) { struct i40e_pf *pf = vf->pf; + struct i40e_vsi *vsi = i40e_find_vsi_from_id(pf, vsi_id); - if (vsi_id > pf->num_alloc_vsi) - return false; - return pf->vsi[vsi_id]->vf_id == vf->vf_id; + return (vsi && (vsi->vf_id == vf->vf_id)); } /** @@ -70,12 +69,13 @@ static inline bool i40e_vc_isvalid_vsi_id(struct i40e_vf *vf, u8 vsi_id) * * check for the valid queue id **/ -static inline bool i40e_vc_isvalid_queue_id(struct i40e_vf *vf, u8 vsi_id, +static inline bool i40e_vc_isvalid_queue_id(struct i40e_vf *vf, u16 vsi_id, u8 qid) { struct i40e_pf *pf = vf->pf; + struct i40e_vsi *vsi = i40e_find_vsi_from_id(pf, vsi_id); - return qid < pf->vsi[vsi_id]->alloc_queue_pairs; + return (vsi && (qid < vsi->alloc_queue_pairs)); } /** @@ -97,18 +97,21 @@ static inline bool i40e_vc_isvalid_vector_id(struct i40e_vf *vf, u8 vector_id) /** * i40e_vc_get_pf_queue_id * @vf: pointer to the VF info - * @vsi_idx: index of VSI in PF struct + * @vsi_id: id of VSI as provided by the FW * @vsi_queue_id: vsi relative queue id * * return PF relative queue id **/ -static u16 i40e_vc_get_pf_queue_id(struct i40e_vf *vf, u8 vsi_idx, +static u16 i40e_vc_get_pf_queue_id(struct i40e_vf *vf, u16 vsi_id, u8 vsi_queue_id) { struct i40e_pf *pf = vf->pf; - struct i40e_vsi *vsi = pf->vsi[vsi_idx]; + struct i40e_vsi *vsi = i40e_find_vsi_from_id(pf, vsi_id); u16 pf_queue_id = I40E_QUEUE_END_OF_LIST; + if (!vsi) + return pf_queue_id; + if (le16_to_cpu(vsi->info.mapping_flags) & I40E_AQ_VSI_QUE_MAP_NONCONTIG) pf_queue_id = @@ -123,12 +126,12 @@ static u16 i40e_vc_get_pf_queue_id(struct i40e_vf *vf, u8 vsi_idx, /** * i40e_config_irq_link_list * @vf: pointer to the VF info - * @vsi_idx: index of VSI in PF struct + * @vsi_id: id of VSI as given by the FW * @vecmap: irq map info * * configure irq link list from the map **/ -static void i40e_config_irq_link_list(struct i40e_vf *vf, u16 vsi_idx, +static void i40e_config_irq_link_list(struct i40e_vf *vf, u16 vsi_id, struct i40e_virtchnl_vector_map *vecmap) { unsigned long linklistmap = 0, tempmap; @@ -173,7 +176,7 @@ static void i40e_config_irq_link_list(struct i40e_vf *vf, u16 vsi_idx, I40E_VIRTCHNL_SUPPORTED_QTYPES)); vsi_queue_id = next_q/I40E_VIRTCHNL_SUPPORTED_QTYPES; qtype = next_q%I40E_VIRTCHNL_SUPPORTED_QTYPES; - pf_queue_id = i40e_vc_get_pf_queue_id(vf, vsi_idx, vsi_queue_id); + pf_queue_id = i40e_vc_get_pf_queue_id(vf, vsi_id, vsi_queue_id); reg = ((qtype << I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT) | pf_queue_id); wr32(hw, reg_idx, reg); @@ -200,7 +203,7 @@ static void i40e_config_irq_link_list(struct i40e_vf *vf, u16 vsi_idx, (I40E_MAX_VSI_QP * I40E_VIRTCHNL_SUPPORTED_QTYPES)) { vsi_queue_id = next_q / I40E_VIRTCHNL_SUPPORTED_QTYPES; qtype = next_q % I40E_VIRTCHNL_SUPPORTED_QTYPES; - pf_queue_id = i40e_vc_get_pf_queue_id(vf, vsi_idx, + pf_queue_id = i40e_vc_get_pf_queue_id(vf, vsi_id, vsi_queue_id); } else { pf_queue_id = I40E_QUEUE_END_OF_LIST; @@ -223,24 +226,26 @@ irq_list_done: /** * i40e_config_vsi_tx_queue * @vf: pointer to the VF info - * @vsi_idx: index of VSI in PF struct + * @vsi_id: id of VSI as provided by the FW * @vsi_queue_id: vsi relative queue index * @info: config. info * * configure tx queue **/ -static int i40e_config_vsi_tx_queue(struct i40e_vf *vf, u16 vsi_idx, +static int i40e_config_vsi_tx_queue(struct i40e_vf *vf, u16 vsi_id, u16 vsi_queue_id, struct i40e_virtchnl_txq_info *info) { struct i40e_pf *pf = vf->pf; struct i40e_hw *hw = &pf->hw; struct i40e_hmc_obj_txq tx_ctx; + struct i40e_vsi *vsi; u16 pf_queue_id; u32 qtx_ctl; int ret = 0; - pf_queue_id = i40e_vc_get_pf_queue_id(vf, vsi_idx, vsi_queue_id); + pf_queue_id = i40e_vc_get_pf_queue_id(vf, vsi_id, vsi_queue_id); + vsi = i40e_find_vsi_from_id(pf, vsi_id); /* clear the context structure first */ memset(&tx_ctx, 0, sizeof(struct i40e_hmc_obj_txq)); @@ -248,7 +253,7 @@ static int i40e_config_vsi_tx_queue(struct i40e_vf *vf, u16 vsi_idx, /* only set the required fields */ tx_ctx.base = info->dma_ring_addr / 128; tx_ctx.qlen = info->ring_len; - tx_ctx.rdylist = le16_to_cpu(pf->vsi[vsi_idx]->info.qs_handle[0]); + tx_ctx.rdylist = le16_to_cpu(vsi->info.qs_handle[0]); tx_ctx.rdylist_act = 0; tx_ctx.head_wb_ena = info->headwb_enabled; tx_ctx.head_wb_addr = info->dma_headwb_addr; @@ -290,13 +295,13 @@ error_context: /** * i40e_config_vsi_rx_queue * @vf: pointer to the VF info - * @vsi_idx: index of VSI in PF struct + * @vsi_id: id of VSI as provided by the FW * @vsi_queue_id: vsi relative queue index * @info: config. info * * configure rx queue **/ -static int i40e_config_vsi_rx_queue(struct i40e_vf *vf, u16 vsi_idx, +static int i40e_config_vsi_rx_queue(struct i40e_vf *vf, u16 vsi_id, u16 vsi_queue_id, struct i40e_virtchnl_rxq_info *info) { @@ -306,7 +311,7 @@ static int i40e_config_vsi_rx_queue(struct i40e_vf *vf, u16 vsi_idx, u16 pf_queue_id; int ret = 0; - pf_queue_id = i40e_vc_get_pf_queue_id(vf, vsi_idx, vsi_queue_id); + pf_queue_id = i40e_vc_get_pf_queue_id(vf, vsi_id, vsi_queue_id); /* clear the context structure first */ memset(&rx_ctx, 0, sizeof(struct i40e_hmc_obj_rxq)); @@ -403,7 +408,7 @@ static int i40e_alloc_vsi_res(struct i40e_vf *vf, enum i40e_vsi_type type) } if (type == I40E_VSI_SRIOV) { u8 brdcast[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - vf->lan_vsi_index = vsi->idx; + vf->lan_vsi_idx = vsi->idx; vf->lan_vsi_id = vsi->id; /* If the port VLAN has been configured and then the * VF driver was removed then the VSI port VLAN @@ -468,8 +473,8 @@ static void i40e_enable_vf_mappings(struct i40e_vf *vf) wr32(hw, I40E_VPLAN_MAPENA(vf->vf_id), reg); /* map PF queues to VF queues */ - for (j = 0; j < pf->vsi[vf->lan_vsi_index]->alloc_queue_pairs; j++) { - u16 qid = i40e_vc_get_pf_queue_id(vf, vf->lan_vsi_index, j); + for (j = 0; j < pf->vsi[vf->lan_vsi_idx]->alloc_queue_pairs; j++) { + u16 qid = i40e_vc_get_pf_queue_id(vf, vf->lan_vsi_id, j); reg = (qid & I40E_VPLAN_QTABLE_QINDEX_MASK); wr32(hw, I40E_VPLAN_QTABLE(total_queue_pairs, vf->vf_id), reg); total_queue_pairs++; @@ -477,13 +482,13 @@ static void i40e_enable_vf_mappings(struct i40e_vf *vf) /* map PF queues to VSI */ for (j = 0; j < 7; j++) { - if (j * 2 >= pf->vsi[vf->lan_vsi_index]->alloc_queue_pairs) { + if (j * 2 >= pf->vsi[vf->lan_vsi_idx]->alloc_queue_pairs) { reg = 0x07FF07FF; /* unused */ } else { - u16 qid = i40e_vc_get_pf_queue_id(vf, vf->lan_vsi_index, + u16 qid = i40e_vc_get_pf_queue_id(vf, vf->lan_vsi_id, j * 2); reg = qid; - qid = i40e_vc_get_pf_queue_id(vf, vf->lan_vsi_index, + qid = i40e_vc_get_pf_queue_id(vf, vf->lan_vsi_id, (j * 2) + 1); reg |= qid << 16; } @@ -527,9 +532,9 @@ static void i40e_free_vf_res(struct i40e_vf *vf) int i, msix_vf; /* free vsi & disconnect it from the parent uplink */ - if (vf->lan_vsi_index) { - i40e_vsi_release(pf->vsi[vf->lan_vsi_index]); - vf->lan_vsi_index = 0; + if (vf->lan_vsi_idx) { + i40e_vsi_release(pf->vsi[vf->lan_vsi_idx]); + vf->lan_vsi_idx = 0; vf->lan_vsi_id = 0; } msix_vf = pf->hw.func_caps.num_msix_vectors_vf; @@ -584,7 +589,7 @@ static int i40e_alloc_vf_res(struct i40e_vf *vf) ret = i40e_alloc_vsi_res(vf, I40E_VSI_SRIOV); if (ret) goto error_alloc; - total_queue_pairs += pf->vsi[vf->lan_vsi_index]->alloc_queue_pairs; + total_queue_pairs += pf->vsi[vf->lan_vsi_idx]->alloc_queue_pairs; set_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps); /* store the total qps number for the runtime @@ -694,10 +699,10 @@ void i40e_reset_vf(struct i40e_vf *vf, bool flr) wr32(hw, I40E_VPGEN_VFRTRIG(vf->vf_id), reg); /* On initial reset, we won't have any queues */ - if (vf->lan_vsi_index == 0) + if (vf->lan_vsi_idx == 0) goto complete_reset; - i40e_vsi_control_rings(pf->vsi[vf->lan_vsi_index], false); + i40e_vsi_control_rings(pf->vsi[vf->lan_vsi_idx], false); complete_reset: /* reallocate VF resources to reset the VSI state */ i40e_free_vf_res(vf); @@ -1018,18 +1023,18 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf) } vfres->vf_offload_flags = I40E_VIRTCHNL_VF_OFFLOAD_L2; - vsi = pf->vsi[vf->lan_vsi_index]; + vsi = pf->vsi[vf->lan_vsi_idx]; if (!vsi->info.pvid) vfres->vf_offload_flags |= I40E_VIRTCHNL_VF_OFFLOAD_VLAN; vfres->num_vsis = num_vsis; vfres->num_queue_pairs = vf->num_queue_pairs; vfres->max_vectors = pf->hw.func_caps.num_msix_vectors_vf; - if (vf->lan_vsi_index) { - vfres->vsi_res[i].vsi_id = vf->lan_vsi_index; + if (vf->lan_vsi_idx) { + vfres->vsi_res[i].vsi_id = vf->lan_vsi_id; vfres->vsi_res[i].vsi_type = I40E_VSI_SRIOV; vfres->vsi_res[i].num_queue_pairs = - pf->vsi[vf->lan_vsi_index]->alloc_queue_pairs; + pf->vsi[vf->lan_vsi_idx]->alloc_queue_pairs; memcpy(vfres->vsi_res[i].default_mac_addr, vf->default_lan_addr.addr, ETH_ALEN); i++; @@ -1081,14 +1086,14 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf, bool allmulti = false; i40e_status aq_ret; + vsi = i40e_find_vsi_from_id(pf, info->vsi_id); if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states) || !test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps) || !i40e_vc_isvalid_vsi_id(vf, info->vsi_id) || - (pf->vsi[info->vsi_id]->type != I40E_VSI_FCOE)) { + (vsi->type != I40E_VSI_FCOE)) { aq_ret = I40E_ERR_PARAM; goto error_param; } - vsi = pf->vsi[info->vsi_id]; if (info->flags & I40E_FLAG_VF_MULTICAST_PROMISC) allmulti = true; aq_ret = i40e_aq_set_vsi_multicast_promiscuous(hw, vsi->seid, @@ -1150,7 +1155,7 @@ static int i40e_vc_config_queues_msg(struct i40e_vf *vf, u8 *msg, u16 msglen) } } /* set vsi num_queue_pairs in use to num configured by VF */ - pf->vsi[vf->lan_vsi_index]->num_queue_pairs = qci->num_queue_pairs; + pf->vsi[vf->lan_vsi_idx]->num_queue_pairs = qci->num_queue_pairs; error_param: /* send the response to the VF */ @@ -1251,7 +1256,8 @@ static int i40e_vc_enable_queues_msg(struct i40e_vf *vf, u8 *msg, u16 msglen) aq_ret = I40E_ERR_PARAM; goto error_param; } - if (i40e_vsi_control_rings(pf->vsi[vsi_id], true)) + + if (i40e_vsi_control_rings(pf->vsi[vf->lan_vsi_idx], true)) aq_ret = I40E_ERR_TIMEOUT; error_param: /* send the response to the VF */ @@ -1273,7 +1279,6 @@ static int i40e_vc_disable_queues_msg(struct i40e_vf *vf, u8 *msg, u16 msglen) struct i40e_virtchnl_queue_select *vqs = (struct i40e_virtchnl_queue_select *)msg; struct i40e_pf *pf = vf->pf; - u16 vsi_id = vqs->vsi_id; i40e_status aq_ret = 0; if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states)) { @@ -1290,7 +1295,8 @@ static int i40e_vc_disable_queues_msg(struct i40e_vf *vf, u8 *msg, u16 msglen) aq_ret = I40E_ERR_PARAM; goto error_param; } - if (i40e_vsi_control_rings(pf->vsi[vsi_id], false)) + + if (i40e_vsi_control_rings(pf->vsi[vf->lan_vsi_idx], false)) aq_ret = I40E_ERR_TIMEOUT; error_param: @@ -1328,7 +1334,7 @@ static int i40e_vc_get_stats_msg(struct i40e_vf *vf, u8 *msg, u16 msglen) goto error_param; } - vsi = pf->vsi[vqs->vsi_id]; + vsi = pf->vsi[vf->lan_vsi_idx]; if (!vsi) { aq_ret = I40E_ERR_PARAM; goto error_param; @@ -1406,7 +1412,7 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen) if (ret) goto error_param; } - vsi = pf->vsi[vsi_id]; + vsi = pf->vsi[vf->lan_vsi_idx]; /* add new addresses to the list */ for (i = 0; i < al->num_elements; i++) { @@ -1474,7 +1480,7 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen) goto error_param; } } - vsi = pf->vsi[vsi_id]; + vsi = pf->vsi[vf->lan_vsi_idx]; /* delete addresses from the list */ for (i = 0; i < al->num_elements; i++) @@ -1524,7 +1530,7 @@ static int i40e_vc_add_vlan_msg(struct i40e_vf *vf, u8 *msg, u16 msglen) goto error_param; } } - vsi = pf->vsi[vsi_id]; + vsi = pf->vsi[vf->lan_vsi_idx]; if (vsi->info.pvid) { aq_ret = I40E_ERR_PARAM; goto error_param; @@ -1577,7 +1583,7 @@ static int i40e_vc_remove_vlan_msg(struct i40e_vf *vf, u8 *msg, u16 msglen) } } - vsi = pf->vsi[vsi_id]; + vsi = pf->vsi[vf->lan_vsi_idx]; if (vsi->info.pvid) { aq_ret = I40E_ERR_PARAM; goto error_param; @@ -1966,7 +1972,7 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac) } vf = &(pf->vf[vf_id]); - vsi = pf->vsi[vf->lan_vsi_index]; + vsi = pf->vsi[vf->lan_vsi_idx]; if (!test_bit(I40E_VF_STAT_INIT, &vf->vf_states)) { dev_err(&pf->pdev->dev, "Uninitialized VF %d\n", vf_id); @@ -2040,7 +2046,7 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, } vf = &(pf->vf[vf_id]); - vsi = pf->vsi[vf->lan_vsi_index]; + vsi = pf->vsi[vf->lan_vsi_idx]; if (!test_bit(I40E_VF_STAT_INIT, &vf->vf_states)) { dev_err(&pf->pdev->dev, "Uninitialized VF %d\n", vf_id); ret = -EINVAL; @@ -2153,7 +2159,7 @@ int i40e_ndo_set_vf_bw(struct net_device *netdev, int vf_id, int min_tx_rate, } vf = &(pf->vf[vf_id]); - vsi = pf->vsi[vf->lan_vsi_index]; + vsi = pf->vsi[vf->lan_vsi_idx]; if (!test_bit(I40E_VF_STAT_INIT, &vf->vf_states)) { dev_err(&pf->pdev->dev, "Uninitialized VF %d.\n", vf_id); ret = -EINVAL; @@ -2227,7 +2233,7 @@ int i40e_ndo_get_vf_config(struct net_device *netdev, vf = &(pf->vf[vf_id]); /* first vsi is always the LAN vsi */ - vsi = pf->vsi[vf->lan_vsi_index]; + vsi = pf->vsi[vf->lan_vsi_idx]; if (!test_bit(I40E_VF_STAT_INIT, &vf->vf_states)) { dev_err(&pf->pdev->dev, "Uninitialized VF %d\n", vf_id); ret = -EINVAL; @@ -2351,7 +2357,7 @@ int i40e_ndo_set_vf_spoofchk(struct net_device *netdev, int vf_id, bool enable) vf->spoofchk = enable; memset(&ctxt, 0, sizeof(ctxt)); - ctxt.seid = pf->vsi[vf->lan_vsi_index]->seid; + ctxt.seid = pf->vsi[vf->lan_vsi_idx]->seid; ctxt.pf_num = pf->hw.pf_id; ctxt.info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_SECURITY_VALID); if (enable) diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h index 9c3a41040835..09043c1aae54 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h @@ -88,7 +88,7 @@ struct i40e_vf { * When assigned, these will be non-zero, because VSI 0 is always * the main LAN VSI for the PF. */ - u8 lan_vsi_index; /* index into PF struct */ + u8 lan_vsi_idx; /* index into PF struct */ u8 lan_vsi_id; /* ID as used by firmware */ u8 num_queue_pairs; /* num of qps assigned to VF vsis */ -- cgit v1.2.3 From 13acb54683f834cb16baf7ad7fd6e15a97b0762f Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Tue, 31 Mar 2015 00:45:05 -0700 Subject: i40evf: protect VLAN filter list The MAC filter list is protected by a critical task bit, and the VLAN list should be protected as well. This prevents list corruption if the watchdog happens to run at the same time as a VLAN filter is being added or deleted. Change-ID: Ia4867cebbbb046a1f38012771b288a634ca5882b Signed-off-by: Mitch Williams Tested-by: Jim Young Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index b08efafee1ae..46aef2a45cbf 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -664,13 +664,21 @@ i40evf_vlan_filter *i40evf_find_vlan(struct i40evf_adapter *adapter, u16 vlan) static struct i40evf_vlan_filter *i40evf_add_vlan(struct i40evf_adapter *adapter, u16 vlan) { - struct i40evf_vlan_filter *f; + struct i40evf_vlan_filter *f = NULL; + int count = 50; + + while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK, + &adapter->crit_section)) { + udelay(1); + if (--count == 0) + goto out; + } f = i40evf_find_vlan(adapter, vlan); if (!f) { f = kzalloc(sizeof(*f), GFP_ATOMIC); if (!f) - return NULL; + goto clearout; f->vlan = vlan; @@ -680,6 +688,9 @@ i40evf_vlan_filter *i40evf_add_vlan(struct i40evf_adapter *adapter, u16 vlan) adapter->aq_required |= I40EVF_FLAG_AQ_ADD_VLAN_FILTER; } +clearout: + clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section); +out: return f; } @@ -691,12 +702,21 @@ i40evf_vlan_filter *i40evf_add_vlan(struct i40evf_adapter *adapter, u16 vlan) static void i40evf_del_vlan(struct i40evf_adapter *adapter, u16 vlan) { struct i40evf_vlan_filter *f; + int count = 50; + + while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK, + &adapter->crit_section)) { + udelay(1); + if (--count == 0) + return; + } f = i40evf_find_vlan(adapter, vlan); if (f) { f->remove = true; adapter->aq_required |= I40EVF_FLAG_AQ_DEL_VLAN_FILTER; } + clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section); } /** -- cgit v1.2.3 From 9a9c8ae1c1b43e12a5ab786d3463b251fe2fd4aa Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Tue, 31 Mar 2015 00:45:06 -0700 Subject: i40evf: Refactor VF RSS code Refactor VF RSS code to allow RSS on a single queue and eliminate the need for the next_queue function. Change-ID: I9253bad96b7f542ee7036e15636db0e5d58d8ef2 Signed-off-by: Anjali Singhai Jain Tested-by: Jim Young Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 43 +++++++------------------ 1 file changed, 11 insertions(+), 32 deletions(-) diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 46aef2a45cbf..6d5f3b21c68a 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -1435,41 +1435,22 @@ restart_watchdog: } /** - * next_queue - increment to next available tx queue - * @adapter: board private structure - * @j: queue counter - * - * Helper function for RSS programming to increment through available - * queus. Returns the next queue value. - **/ -static int next_queue(struct i40evf_adapter *adapter, int j) -{ - j += 1; - - return j >= adapter->num_active_queues ? 0 : j; -} - -/** - * i40evf_configure_rss - Prepare for RSS if used + * i40evf_configure_rss - Prepare for RSS * @adapter: board private structure **/ static void i40evf_configure_rss(struct i40evf_adapter *adapter) { u32 rss_key[I40E_VFQF_HKEY_MAX_INDEX + 1]; struct i40e_hw *hw = &adapter->hw; + u32 cqueue = 0; u32 lut = 0; int i, j; u64 hena; - /* No RSS for single queue. */ - if (adapter->num_active_queues == 1) { - wr32(hw, I40E_VFQF_HENA(0), 0); - wr32(hw, I40E_VFQF_HENA(1), 0); - return; - } - /* Hash type is configured by the PF - we just supply the key */ netdev_rss_key_fill(rss_key, sizeof(rss_key)); + + /* Fill out hash function seed */ for (i = 0; i <= I40E_VFQF_HKEY_MAX_INDEX; i++) wr32(hw, I40E_VFQF_HKEY(i), rss_key[i]); @@ -1479,16 +1460,14 @@ static void i40evf_configure_rss(struct i40evf_adapter *adapter) wr32(hw, I40E_VFQF_HENA(1), (u32)(hena >> 32)); /* Populate the LUT with max no. of queues in round robin fashion */ - j = adapter->num_active_queues; for (i = 0; i <= I40E_VFQF_HLUT_MAX_INDEX; i++) { - j = next_queue(adapter, j); - lut = j; - j = next_queue(adapter, j); - lut |= j << 8; - j = next_queue(adapter, j); - lut |= j << 16; - j = next_queue(adapter, j); - lut |= j << 24; + lut = 0; + for (j = 0; j < 4; j++) { + if (cqueue == adapter->vsi_res->num_queue_pairs) + cqueue = 0; + lut |= ((cqueue) << (8 * j)); + cqueue++; + } wr32(hw, I40E_VFQF_HLUT(i), lut); } i40e_flush(hw); -- cgit v1.2.3 From 42d255ce43e1dbe28b5907ec276cd88330952661 Mon Sep 17 00:00:00 2001 From: Catherine Sullivan Date: Tue, 31 Mar 2015 00:45:06 -0700 Subject: i40e: Bump to version 1.3.1 Bump. Change-ID: I7dc88baa33264e5919bc938adf76706573209432 Signed-off-by: Catherine Sullivan Tested-by: Jim Young Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 89a2d76a1f69..63de3f4b7a94 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -38,8 +38,8 @@ static const char i40e_driver_string[] = #define DRV_KERN "-k" #define DRV_VERSION_MAJOR 1 -#define DRV_VERSION_MINOR 2 -#define DRV_VERSION_BUILD 43 +#define DRV_VERSION_MINOR 3 +#define DRV_VERSION_BUILD 1 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \ __stringify(DRV_VERSION_MINOR) "." \ __stringify(DRV_VERSION_BUILD) DRV_KERN -- cgit v1.2.3