Message ID | 20240821121539.374343-5-wojciech.drewek@intel.com (mailing list archive) |
---|---|
State | Awaiting Upstream |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | Add support for Rx timestamping for both ice and iavf drivers | expand |
Context | Check | Description |
---|---|---|
netdev/tree_selection | success | Guessing tree name failed - patch did not apply |
From: Wojciech Drewek <wojciech.drewek@intel.com> Date: Wed, 21 Aug 2024 14:15:29 +0200 > From: Jacob Keller <jacob.e.keller@intel.com> > > Enable support for VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC, to enable the VF > driver the ability to determine what Rx descriptor formats are > available. This requires sending an additional message during > initialization and reset, the VIRTCHNL_OP_GET_SUPPORTED_RXDIDS. This > operation requests the supported Rx descriptor IDs available from the > PF. > > This is treated the same way that VLAN V2 capabilities are handled. Add > a new set of extended capability flags, used to process send and receipt > of the VIRTCHNL_OP_GET_SUPPORTED_RXDIDS message. > > This ensures we finish negotiating for the supported descriptor formats > prior to beginning configuration of receive queues. > > This change stores the supported format bitmap into the iavf_adapter > structure. Additionally, if VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC is enabled > by the PF, we need to make sure that the Rx queue configuration > specifies the format. > > Signed-off-by: Jacob Keller <jacob.e.keller@intel.com> > Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com> > Reviewed-by: Simon Horman <horms@kernel.org> > Co-developed-by: Mateusz Polchlopek <mateusz.polchlopek@intel.com> > Signed-off-by: Mateusz Polchlopek <mateusz.polchlopek@intel.com> > Signed-off-by: Wojciech Drewek <wojciech.drewek@intel.com> [...] > +/** > + * iavf_select_rx_desc_format - Select Rx descriptor format > + * @adapter: adapter private structure > + * > + * Select what Rx descriptor format based on availability and enabled > + * features. > + * > + * Return: the desired RXDID to select for a given Rx queue, as defined by > + * enum virtchnl_rxdid_format. > + */ > +static u8 iavf_select_rx_desc_format(const struct iavf_adapter *adapter) > +{ > + u64 rxdids = adapter->supp_rxdids; > + > + /* If we did not negotiate VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC, we must > + * stick with the default value of the legacy 32 byte format. > + */ > + if (!IAVF_RXDID_ALLOWED(adapter)) > + return VIRTCHNL_RXDID_1_32B_BASE; > + > + /* Warn if the PF does not list support for the default legacy > + * descriptor format. This shouldn't happen, as this is the format > + * used if VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC is not supported. It is > + * likely caused by a bug in the PF implementation failing to indicate > + * support for the format. > + */ > + if (!(rxdids & VIRTCHNL_RXDID_1_32B_BASE_M)) > + dev_warn(&adapter->pdev->dev, "PF does not list support for default Rx descriptor format\n"); pci_warn() or netdev_warn() if netdev is available here, sorry if I didn't mention this earlier =\ > + > + return VIRTCHNL_RXDID_1_32B_BASE; > +} > + > /** > * iavf_configure_rx - Configure Receive Unit after Reset > * @adapter: board private structure [...] > @@ -262,6 +276,37 @@ int iavf_get_vf_vlan_v2_caps(struct iavf_adapter *adapter) > return err; > } > > +int iavf_get_vf_supported_rxdids(struct iavf_adapter *adapter) > +{ > + struct iavf_hw *hw = &adapter->hw; > + struct iavf_arq_event_info event; > + u32 len = sizeof(u64); > + enum virtchnl_ops op; > + enum iavf_status err; > + u8 rxdids; > + > + event.msg_buf = &rxdids; > + event.buf_len = len; This looks suspicious. @rxdids is u8, while @len is sizeof(u64), i.e 8 bytes, not 1. Is this intended? Or maybe @rxdids should be u64 here as well, just like adapter->supported_rxdids? > + > + while (1) { @op can be declared right here. @err can be also declared right here if you address the comment below. > + /* When the AQ is empty, iavf_clean_arq_element will return > + * nonzero and this loop will terminate. > + */ > + err = iavf_clean_arq_element(hw, &event, NULL); > + if (err != IAVF_SUCCESS) > + return err; > + op = le32_to_cpu(event.desc.cookie_high); > + if (op == VIRTCHNL_OP_GET_SUPPORTED_RXDIDS) When one of the elements you want to compare is a compile-time constant, you will get more optimized code if you do __le32 op; op = event.desc.cookie_high; if (op == cpu_to_le32(VIRTCHNL_OP_GET_SUPPORTED_RXDIDS)) because then you won't need to byteswap a variable and constants get byteswapped at compilation time. But given that iavf runs on LE 99% of time and it's not hotpath, it's up to you whether to do it like that here or just leave as it is. > + break; > + } > + > + err = le32_to_cpu(event.desc.cookie_low); > + if (!err) if (!event.desc.cookie_low) Because 0 == le32_to_cpu(0), it's always 0. So you don't need @err here and it can be declared inside the loop above. > + adapter->supp_rxdids = rxdids; > + > + return 0; > +} > + > /** > * iavf_configure_queues > * @adapter: adapter structure > @@ -308,6 +353,8 @@ void iavf_configure_queues(struct iavf_adapter *adapter) > vqpi->rxq.dma_ring_addr = adapter->rx_rings[i].dma; > vqpi->rxq.max_pkt_size = max_frame; > vqpi->rxq.databuffer_size = adapter->rx_rings[i].rx_buf_len; > + if (IAVF_RXDID_ALLOWED(adapter)) > + vqpi->rxq.rxdid = adapter->rxdid; > if (CRC_OFFLOAD_ALLOWED(adapter)) > vqpi->rxq.crc_disable = !!(adapter->netdev->features & > NETIF_F_RXFCS); > @@ -2372,6 +2419,10 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter, > aq_required; > } > break; > + case VIRTCHNL_OP_GET_SUPPORTED_RXDIDS: > + memcpy(&adapter->supp_rxdids, msg, > + min_t(u16, msglen, sizeof(adapter->supp_rxdids))); Why is this needed if you assign ->supp_rxdids in iavf_get_vf_supported_rxdids()? Or is this something different? I'd also say this memcpy() is not safe. ->supp_rxdids is u64. If somehow @msglen is less than 8 bytes, you'd probably get a corrupted u64 value. I think you should compare @msglen to sizeof(u64) and bail out if it's different. If it's the same, you should just do adapter->supp_rxdids = *(u64 *)msg; > + break; > case VIRTCHNL_OP_ENABLE_QUEUES: > /* enable transmits */ > iavf_irq_enable(adapter, true); > diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl.c b/drivers/net/ethernet/intel/ice/ice_virtchnl.c > index b60df6e9b3e7..3c2d6a504aa0 100644 > --- a/drivers/net/ethernet/intel/ice/ice_virtchnl.c > +++ b/drivers/net/ethernet/intel/ice/ice_virtchnl.c > @@ -2709,12 +2709,12 @@ static int ice_vc_set_rss_hena(struct ice_vf *vf, u8 *msg) > static int ice_vc_query_rxdid(struct ice_vf *vf) > { > enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS; > - struct virtchnl_supported_rxdids *rxdid = NULL; > struct ice_hw *hw = &vf->pf->hw; > struct ice_pf *pf = vf->pf; > - int len = 0; > - int ret, i; > + u32 len = sizeof(u64); > u32 regval; > + u64 rxdid; > + int ret, i; RCT broke here =\ > > if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) { > v_ret = VIRTCHNL_STATUS_ERR_PARAM; Thanks, Olek
On 21.08.2024 15:52, Alexander Lobakin wrote: > From: Wojciech Drewek <wojciech.drewek@intel.com> > Date: Wed, 21 Aug 2024 14:15:29 +0200 > >> From: Jacob Keller <jacob.e.keller@intel.com> >> >> Enable support for VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC, to enable the VF >> driver the ability to determine what Rx descriptor formats are >> available. This requires sending an additional message during >> initialization and reset, the VIRTCHNL_OP_GET_SUPPORTED_RXDIDS. This >> operation requests the supported Rx descriptor IDs available from the >> PF. >> >> This is treated the same way that VLAN V2 capabilities are handled. Add >> a new set of extended capability flags, used to process send and receipt >> of the VIRTCHNL_OP_GET_SUPPORTED_RXDIDS message. >> >> This ensures we finish negotiating for the supported descriptor formats >> prior to beginning configuration of receive queues. >> >> This change stores the supported format bitmap into the iavf_adapter >> structure. Additionally, if VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC is enabled >> by the PF, we need to make sure that the Rx queue configuration >> specifies the format. >> >> Signed-off-by: Jacob Keller <jacob.e.keller@intel.com> >> Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com> >> Reviewed-by: Simon Horman <horms@kernel.org> >> Co-developed-by: Mateusz Polchlopek <mateusz.polchlopek@intel.com> >> Signed-off-by: Mateusz Polchlopek <mateusz.polchlopek@intel.com> >> Signed-off-by: Wojciech Drewek <wojciech.drewek@intel.com> > > [...] > >> +/** >> + * iavf_select_rx_desc_format - Select Rx descriptor format >> + * @adapter: adapter private structure >> + * >> + * Select what Rx descriptor format based on availability and enabled >> + * features. >> + * >> + * Return: the desired RXDID to select for a given Rx queue, as defined by >> + * enum virtchnl_rxdid_format. >> + */ >> +static u8 iavf_select_rx_desc_format(const struct iavf_adapter *adapter) >> +{ >> + u64 rxdids = adapter->supp_rxdids; >> + >> + /* If we did not negotiate VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC, we must >> + * stick with the default value of the legacy 32 byte format. >> + */ >> + if (!IAVF_RXDID_ALLOWED(adapter)) >> + return VIRTCHNL_RXDID_1_32B_BASE; >> + >> + /* Warn if the PF does not list support for the default legacy >> + * descriptor format. This shouldn't happen, as this is the format >> + * used if VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC is not supported. It is >> + * likely caused by a bug in the PF implementation failing to indicate >> + * support for the format. >> + */ >> + if (!(rxdids & VIRTCHNL_RXDID_1_32B_BASE_M)) >> + dev_warn(&adapter->pdev->dev, "PF does not list support for default Rx descriptor format\n"); > > pci_warn() or netdev_warn() if netdev is available here, sorry if I > didn't mention this earlier =\ sure > >> + >> + return VIRTCHNL_RXDID_1_32B_BASE; >> +} >> + >> /** >> * iavf_configure_rx - Configure Receive Unit after Reset >> * @adapter: board private structure > > [...] > >> @@ -262,6 +276,37 @@ int iavf_get_vf_vlan_v2_caps(struct iavf_adapter *adapter) >> return err; >> } >> >> +int iavf_get_vf_supported_rxdids(struct iavf_adapter *adapter) >> +{ >> + struct iavf_hw *hw = &adapter->hw; >> + struct iavf_arq_event_info event; >> + u32 len = sizeof(u64); >> + enum virtchnl_ops op; >> + enum iavf_status err; >> + u8 rxdids; >> + >> + event.msg_buf = &rxdids; >> + event.buf_len = len; > > This looks suspicious. @rxdids is u8, while @len is sizeof(u64), i.e 8 > bytes, not 1. Is this intended? Or maybe @rxdids should be u64 here as > well, just like adapter->supported_rxdids? > >> + >> + while (1) { > > @op can be declared right here. > @err can be also declared right here if you address the comment below. > >> + /* When the AQ is empty, iavf_clean_arq_element will return >> + * nonzero and this loop will terminate. >> + */ >> + err = iavf_clean_arq_element(hw, &event, NULL); >> + if (err != IAVF_SUCCESS) >> + return err; >> + op = le32_to_cpu(event.desc.cookie_high); >> + if (op == VIRTCHNL_OP_GET_SUPPORTED_RXDIDS) > > When one of the elements you want to compare is a compile-time constant, > you will get more optimized code if you do > > __le32 op; > > op = event.desc.cookie_high; > if (op == cpu_to_le32(VIRTCHNL_OP_GET_SUPPORTED_RXDIDS)) > > because then you won't need to byteswap a variable and constants get > byteswapped at compilation time. > > But given that iavf runs on LE 99% of time and it's not hotpath, it's up > to you whether to do it like that here or just leave as it is. > >> + break; >> + } >> + >> + err = le32_to_cpu(event.desc.cookie_low); >> + if (!err) > > if (!event.desc.cookie_low) > > Because 0 == le32_to_cpu(0), it's always 0. > So you don't need @err here and it can be declared inside the loop above. I'll refactor this function to use iavf_poll_virtchnl_msg, so this loop will disappear from hear. > >> + adapter->supp_rxdids = rxdids; >> + >> + return 0; >> +} >> + >> /** >> * iavf_configure_queues >> * @adapter: adapter structure >> @@ -308,6 +353,8 @@ void iavf_configure_queues(struct iavf_adapter *adapter) >> vqpi->rxq.dma_ring_addr = adapter->rx_rings[i].dma; >> vqpi->rxq.max_pkt_size = max_frame; >> vqpi->rxq.databuffer_size = adapter->rx_rings[i].rx_buf_len; >> + if (IAVF_RXDID_ALLOWED(adapter)) >> + vqpi->rxq.rxdid = adapter->rxdid; >> if (CRC_OFFLOAD_ALLOWED(adapter)) >> vqpi->rxq.crc_disable = !!(adapter->netdev->features & >> NETIF_F_RXFCS); >> @@ -2372,6 +2419,10 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter, >> aq_required; >> } >> break; >> + case VIRTCHNL_OP_GET_SUPPORTED_RXDIDS: >> + memcpy(&adapter->supp_rxdids, msg, >> + min_t(u16, msglen, sizeof(adapter->supp_rxdids))); > > Why is this needed if you assign ->supp_rxdids in > iavf_get_vf_supported_rxdids()? Or is this something different? I think that iavf_get_vf_supported_rxdids is used only during init. This part here is used later during reset e.g. > > I'd also say this memcpy() is not safe. ->supp_rxdids is u64. If somehow > @msglen is less than 8 bytes, you'd probably get a corrupted u64 value. > I think you should compare @msglen to sizeof(u64) and bail out if it's > different. If it's the same, you should just do Sure, I can make it like that. > > adapter->supp_rxdids = *(u64 *)msg; > >> + break; >> case VIRTCHNL_OP_ENABLE_QUEUES: >> /* enable transmits */ >> iavf_irq_enable(adapter, true); >> diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl.c b/drivers/net/ethernet/intel/ice/ice_virtchnl.c >> index b60df6e9b3e7..3c2d6a504aa0 100644 >> --- a/drivers/net/ethernet/intel/ice/ice_virtchnl.c >> +++ b/drivers/net/ethernet/intel/ice/ice_virtchnl.c >> @@ -2709,12 +2709,12 @@ static int ice_vc_set_rss_hena(struct ice_vf *vf, u8 *msg) >> static int ice_vc_query_rxdid(struct ice_vf *vf) >> { >> enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS; >> - struct virtchnl_supported_rxdids *rxdid = NULL; >> struct ice_hw *hw = &vf->pf->hw; >> struct ice_pf *pf = vf->pf; >> - int len = 0; >> - int ret, i; >> + u32 len = sizeof(u64); >> u32 regval; >> + u64 rxdid; >> + int ret, i; > > RCT broke here =\ sure > >> >> if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) { >> v_ret = VIRTCHNL_STATUS_ERR_PARAM; > > Thanks, > Olek
diff --git a/drivers/net/ethernet/intel/iavf/iavf.h b/drivers/net/ethernet/intel/iavf/iavf.h index 48cd1d06761c..f1506b3d01ce 100644 --- a/drivers/net/ethernet/intel/iavf/iavf.h +++ b/drivers/net/ethernet/intel/iavf/iavf.h @@ -267,6 +267,7 @@ struct iavf_adapter { /* Lock to protect accesses to MAC and VLAN lists */ spinlock_t mac_vlan_list_lock; char misc_vector_name[IFNAMSIZ + 9]; + u8 rxdid; int num_active_queues; int num_req_queues; @@ -336,6 +337,14 @@ struct iavf_adapter { #define IAVF_FLAG_AQ_DISABLE_CTAG_VLAN_INSERTION BIT_ULL(36) #define IAVF_FLAG_AQ_ENABLE_STAG_VLAN_INSERTION BIT_ULL(37) #define IAVF_FLAG_AQ_DISABLE_STAG_VLAN_INSERTION BIT_ULL(38) +#define IAVF_FLAG_AQ_GET_SUPPORTED_RXDIDS BIT_ULL(39) + + /* AQ messages that must be sent after IAVF_FLAG_AQ_GET_CONFIG, in + * order to negotiated extended capabilities. + */ +#define IAVF_FLAG_AQ_EXTENDED_CAPS \ + (IAVF_FLAG_AQ_GET_OFFLOAD_VLAN_V2_CAPS | \ + IAVF_FLAG_AQ_GET_SUPPORTED_RXDIDS) /* flags for processing extended capability messages during * __IAVF_INIT_EXTENDED_CAPS. Each capability exchange requires @@ -347,10 +356,14 @@ struct iavf_adapter { u64 extended_caps; #define IAVF_EXTENDED_CAP_SEND_VLAN_V2 BIT_ULL(0) #define IAVF_EXTENDED_CAP_RECV_VLAN_V2 BIT_ULL(1) +#define IAVF_EXTENDED_CAP_SEND_RXDID BIT_ULL(2) +#define IAVF_EXTENDED_CAP_RECV_RXDID BIT_ULL(3) #define IAVF_EXTENDED_CAPS \ (IAVF_EXTENDED_CAP_SEND_VLAN_V2 | \ - IAVF_EXTENDED_CAP_RECV_VLAN_V2) + IAVF_EXTENDED_CAP_RECV_VLAN_V2 | \ + IAVF_EXTENDED_CAP_SEND_RXDID | \ + IAVF_EXTENDED_CAP_RECV_RXDID) /* Lock to prevent possible clobbering of * current_netdev_promisc_flags @@ -408,12 +421,15 @@ struct iavf_adapter { VIRTCHNL_VF_OFFLOAD_FDIR_PF) #define ADV_RSS_SUPPORT(_a) ((_a)->vf_res->vf_cap_flags & \ VIRTCHNL_VF_OFFLOAD_ADV_RSS_PF) +#define IAVF_RXDID_ALLOWED(a) ((a)->vf_res->vf_cap_flags & \ + VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC) struct virtchnl_vf_resource *vf_res; /* incl. all VSIs */ struct virtchnl_vsi_resource *vsi_res; /* our LAN VSI */ struct virtchnl_version_info pf_version; #define PF_IS_V11(_a) (((_a)->pf_version.major == 1) && \ ((_a)->pf_version.minor == 1)) struct virtchnl_vlan_caps vlan_v2_caps; + u64 supp_rxdids; u16 msg_enable; struct iavf_eth_stats current_stats; struct iavf_vsi vsi; @@ -551,6 +567,8 @@ int iavf_send_vf_config_msg(struct iavf_adapter *adapter); int iavf_get_vf_config(struct iavf_adapter *adapter); int iavf_get_vf_vlan_v2_caps(struct iavf_adapter *adapter); int iavf_send_vf_offload_vlan_v2_msg(struct iavf_adapter *adapter); +int iavf_send_vf_supported_rxdids_msg(struct iavf_adapter *adapter); +int iavf_get_vf_supported_rxdids(struct iavf_adapter *adapter); void iavf_set_queue_vlan_tag_loc(struct iavf_adapter *adapter); u16 iavf_get_num_vlans_added(struct iavf_adapter *adapter); void iavf_irq_enable(struct iavf_adapter *adapter, bool flush); diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c index f782402cd789..df905b2dea28 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_main.c +++ b/drivers/net/ethernet/intel/iavf/iavf_main.c @@ -709,6 +709,38 @@ static void iavf_configure_tx(struct iavf_adapter *adapter) adapter->tx_rings[i].tail = hw->hw_addr + IAVF_QTX_TAIL1(i); } +/** + * iavf_select_rx_desc_format - Select Rx descriptor format + * @adapter: adapter private structure + * + * Select what Rx descriptor format based on availability and enabled + * features. + * + * Return: the desired RXDID to select for a given Rx queue, as defined by + * enum virtchnl_rxdid_format. + */ +static u8 iavf_select_rx_desc_format(const struct iavf_adapter *adapter) +{ + u64 rxdids = adapter->supp_rxdids; + + /* If we did not negotiate VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC, we must + * stick with the default value of the legacy 32 byte format. + */ + if (!IAVF_RXDID_ALLOWED(adapter)) + return VIRTCHNL_RXDID_1_32B_BASE; + + /* Warn if the PF does not list support for the default legacy + * descriptor format. This shouldn't happen, as this is the format + * used if VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC is not supported. It is + * likely caused by a bug in the PF implementation failing to indicate + * support for the format. + */ + if (!(rxdids & VIRTCHNL_RXDID_1_32B_BASE_M)) + dev_warn(&adapter->pdev->dev, "PF does not list support for default Rx descriptor format\n"); + + return VIRTCHNL_RXDID_1_32B_BASE; +} + /** * iavf_configure_rx - Configure Receive Unit after Reset * @adapter: board private structure @@ -719,8 +751,12 @@ static void iavf_configure_rx(struct iavf_adapter *adapter) { struct iavf_hw *hw = &adapter->hw; - for (u32 i = 0; i < adapter->num_active_queues; i++) + adapter->rxdid = iavf_select_rx_desc_format(adapter); + + for (u32 i = 0; i < adapter->num_active_queues; i++) { adapter->rx_rings[i].tail = hw->hw_addr + IAVF_QRX_TAIL1(i); + adapter->rx_rings[i].rxdid = adapter->rxdid; + } } /** @@ -2045,6 +2081,8 @@ static int iavf_process_aq_command(struct iavf_adapter *adapter) return iavf_send_vf_config_msg(adapter); if (adapter->aq_required & IAVF_FLAG_AQ_GET_OFFLOAD_VLAN_V2_CAPS) return iavf_send_vf_offload_vlan_v2_msg(adapter); + if (adapter->aq_required & IAVF_FLAG_AQ_GET_SUPPORTED_RXDIDS) + return iavf_send_vf_supported_rxdids_msg(adapter); if (adapter->aq_required & IAVF_FLAG_AQ_DISABLE_QUEUES) { iavf_disable_queues(adapter); return 0; @@ -2558,6 +2596,63 @@ static void iavf_init_recv_offload_vlan_v2_caps(struct iavf_adapter *adapter) iavf_change_state(adapter, __IAVF_INIT_FAILED); } +/** + * iavf_init_send_supported_rxdids - part of querying for supported RXDID + * formats + * @adapter: board private structure + * + * Function processes send of the request for supported RXDIDs to the PF. + * Must clear IAVF_EXTENDED_CAP_RECV_RXDID if the message is not sent, e.g. + * due to the PF not negotiating VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC. + */ +static void iavf_init_send_supported_rxdids(struct iavf_adapter *adapter) +{ + int ret; + + ret = iavf_send_vf_supported_rxdids_msg(adapter); + if (ret == -EOPNOTSUPP) { + /* PF does not support VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC. In this + * case, we did not send the capability exchange message and + * do not expect a response. + */ + adapter->extended_caps &= ~IAVF_EXTENDED_CAP_RECV_RXDID; + } + + /* We sent the message, so move on to the next step */ + adapter->extended_caps &= ~IAVF_EXTENDED_CAP_SEND_RXDID; +} + +/** + * iavf_init_recv_supported_rxdids - part of querying for supported RXDID + * formats + * @adapter: board private structure + * + * Function processes receipt of the supported RXDIDs message from the PF. + **/ +static void iavf_init_recv_supported_rxdids(struct iavf_adapter *adapter) +{ + int ret; + + memset(&adapter->supp_rxdids, 0, sizeof(adapter->supp_rxdids)); + + ret = iavf_get_vf_supported_rxdids(adapter); + if (ret) + goto err; + + /* We've processed the PF response to the + * VIRTCHNL_OP_GET_SUPPORTED_RXDIDS message we sent previously. + */ + adapter->extended_caps &= ~IAVF_EXTENDED_CAP_RECV_RXDID; + return; + +err: + /* We didn't receive a reply. Make sure we try sending again when + * __IAVF_INIT_FAILED attempts to recover. + */ + adapter->extended_caps |= IAVF_EXTENDED_CAP_SEND_RXDID; + iavf_change_state(adapter, __IAVF_INIT_FAILED); +} + /** * iavf_init_process_extended_caps - Part of driver startup * @adapter: board private structure @@ -2582,6 +2677,15 @@ static void iavf_init_process_extended_caps(struct iavf_adapter *adapter) return; } + /* Process capability exchange for RXDID formats */ + if (adapter->extended_caps & IAVF_EXTENDED_CAP_SEND_RXDID) { + iavf_init_send_supported_rxdids(adapter); + return; + } else if (adapter->extended_caps & IAVF_EXTENDED_CAP_RECV_RXDID) { + iavf_init_recv_supported_rxdids(adapter); + return; + } + /* When we reach here, no further extended capabilities exchanges are * necessary, so we finally transition into __IAVF_INIT_CONFIG_ADAPTER */ @@ -3050,15 +3154,18 @@ static void iavf_reset_task(struct work_struct *work) } adapter->aq_required |= IAVF_FLAG_AQ_GET_CONFIG; - /* always set since VIRTCHNL_OP_GET_VF_RESOURCES has not been - * sent/received yet, so VLAN_V2_ALLOWED() cannot is not reliable here, - * however the VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS won't be sent until - * VIRTCHNL_OP_GET_VF_RESOURCES and VIRTCHNL_VF_OFFLOAD_VLAN_V2 have - * been successfully sent and negotiated - */ - adapter->aq_required |= IAVF_FLAG_AQ_GET_OFFLOAD_VLAN_V2_CAPS; adapter->aq_required |= IAVF_FLAG_AQ_MAP_VECTORS; + /* Certain capabilities require an extended negotiation process using + * extra messages that must be processed after getting the VF + * configuration. The related checks such as VLAN_V2_ALLOWED() are not + * reliable here, since the configuration has not yet been negotiated. + * + * Always set these flags, since them related VIRTCHNL messages won't + * be sent until after VIRTCHNL_OP_GET_VF_RESOURCES. + */ + adapter->aq_required |= IAVF_FLAG_AQ_EXTENDED_CAPS; + spin_lock_bh(&adapter->mac_vlan_list_lock); /* Delete filter for the current MAC address, it could have diff --git a/drivers/net/ethernet/intel/iavf/iavf_txrx.h b/drivers/net/ethernet/intel/iavf/iavf_txrx.h index d7b5587aeb8e..e8421994235b 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_txrx.h +++ b/drivers/net/ethernet/intel/iavf/iavf_txrx.h @@ -262,6 +262,8 @@ struct iavf_ring { u16 next_to_use; u16 next_to_clean; + u16 rxdid; /* Rx descriptor format */ + u16 flags; #define IAVF_TXR_FLAGS_WB_ON_ITR BIT(0) #define IAVF_TXR_FLAGS_ARM_WB BIT(1) diff --git a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c index 7e810b65380c..bbd0eb06acd3 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c +++ b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c @@ -144,6 +144,7 @@ int iavf_send_vf_config_msg(struct iavf_adapter *adapter) VIRTCHNL_VF_OFFLOAD_ENCAP | VIRTCHNL_VF_OFFLOAD_TC_U32 | VIRTCHNL_VF_OFFLOAD_VLAN_V2 | + VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC | VIRTCHNL_VF_OFFLOAD_CRC | VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM | VIRTCHNL_VF_OFFLOAD_REQ_QUEUES | @@ -176,6 +177,19 @@ int iavf_send_vf_offload_vlan_v2_msg(struct iavf_adapter *adapter) NULL, 0); } +int iavf_send_vf_supported_rxdids_msg(struct iavf_adapter *adapter) +{ + adapter->aq_required &= ~IAVF_FLAG_AQ_GET_SUPPORTED_RXDIDS; + + if (!IAVF_RXDID_ALLOWED(adapter)) + return -EOPNOTSUPP; + + adapter->current_op = VIRTCHNL_OP_GET_SUPPORTED_RXDIDS; + + return iavf_send_pf_msg(adapter, VIRTCHNL_OP_GET_SUPPORTED_RXDIDS, + NULL, 0); +} + /** * iavf_validate_num_queues * @adapter: adapter structure @@ -262,6 +276,37 @@ int iavf_get_vf_vlan_v2_caps(struct iavf_adapter *adapter) return err; } +int iavf_get_vf_supported_rxdids(struct iavf_adapter *adapter) +{ + struct iavf_hw *hw = &adapter->hw; + struct iavf_arq_event_info event; + u32 len = sizeof(u64); + enum virtchnl_ops op; + enum iavf_status err; + u8 rxdids; + + event.msg_buf = &rxdids; + event.buf_len = len; + + while (1) { + /* When the AQ is empty, iavf_clean_arq_element will return + * nonzero and this loop will terminate. + */ + err = iavf_clean_arq_element(hw, &event, NULL); + if (err != IAVF_SUCCESS) + return err; + op = le32_to_cpu(event.desc.cookie_high); + if (op == VIRTCHNL_OP_GET_SUPPORTED_RXDIDS) + break; + } + + err = le32_to_cpu(event.desc.cookie_low); + if (!err) + adapter->supp_rxdids = rxdids; + + return 0; +} + /** * iavf_configure_queues * @adapter: adapter structure @@ -308,6 +353,8 @@ void iavf_configure_queues(struct iavf_adapter *adapter) vqpi->rxq.dma_ring_addr = adapter->rx_rings[i].dma; vqpi->rxq.max_pkt_size = max_frame; vqpi->rxq.databuffer_size = adapter->rx_rings[i].rx_buf_len; + if (IAVF_RXDID_ALLOWED(adapter)) + vqpi->rxq.rxdid = adapter->rxdid; if (CRC_OFFLOAD_ALLOWED(adapter)) vqpi->rxq.crc_disable = !!(adapter->netdev->features & NETIF_F_RXFCS); @@ -2372,6 +2419,10 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter, aq_required; } break; + case VIRTCHNL_OP_GET_SUPPORTED_RXDIDS: + memcpy(&adapter->supp_rxdids, msg, + min_t(u16, msglen, sizeof(adapter->supp_rxdids))); + break; case VIRTCHNL_OP_ENABLE_QUEUES: /* enable transmits */ iavf_irq_enable(adapter, true); diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl.c b/drivers/net/ethernet/intel/ice/ice_virtchnl.c index b60df6e9b3e7..3c2d6a504aa0 100644 --- a/drivers/net/ethernet/intel/ice/ice_virtchnl.c +++ b/drivers/net/ethernet/intel/ice/ice_virtchnl.c @@ -2709,12 +2709,12 @@ static int ice_vc_set_rss_hena(struct ice_vf *vf, u8 *msg) static int ice_vc_query_rxdid(struct ice_vf *vf) { enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS; - struct virtchnl_supported_rxdids *rxdid = NULL; struct ice_hw *hw = &vf->pf->hw; struct ice_pf *pf = vf->pf; - int len = 0; - int ret, i; + u32 len = sizeof(u64); u32 regval; + u64 rxdid; + int ret, i; if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) { v_ret = VIRTCHNL_STATUS_ERR_PARAM; @@ -2726,34 +2726,25 @@ static int ice_vc_query_rxdid(struct ice_vf *vf) goto err; } - len = sizeof(struct virtchnl_supported_rxdids); - rxdid = kzalloc(len, GFP_KERNEL); - if (!rxdid) { - v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY; - len = 0; - goto err; - } - /* RXDIDs supported by DDP package can be read from the register * to get the supported RXDID bitmap. But the legacy 32byte RXDID * is not listed in DDP package, add it in the bitmap manually. * Legacy 16byte descriptor is not supported. */ - rxdid->supported_rxdids |= BIT(ICE_RXDID_LEGACY_1); + rxdid |= BIT(ICE_RXDID_LEGACY_1); for (i = ICE_RXDID_FLEX_NIC; i < ICE_FLEX_DESC_RXDID_MAX_NUM; i++) { regval = rd32(hw, GLFLXP_RXDID_FLAGS(i, 0)); if ((regval >> GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_S) & GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_M) - rxdid->supported_rxdids |= BIT(i); + rxdid |= BIT(i); } - pf->supported_rxdids = rxdid->supported_rxdids; + pf->supported_rxdids = rxdid; err: ret = ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_GET_SUPPORTED_RXDIDS, - v_ret, (u8 *)rxdid, len); - kfree(rxdid); + v_ret, (u8 *)&rxdid, len); return ret; } diff --git a/include/linux/avf/virtchnl.h b/include/linux/avf/virtchnl.h index 2b8f915df012..d8f6687dfe47 100644 --- a/include/linux/avf/virtchnl.h +++ b/include/linux/avf/virtchnl.h @@ -1087,11 +1087,6 @@ struct virtchnl_filter { VIRTCHNL_CHECK_STRUCT_LEN(272, virtchnl_filter); -struct virtchnl_supported_rxdids { - /* see enum virtchnl_rx_desc_id_bitmasks */ - u64 supported_rxdids; -}; - /* VIRTCHNL_OP_EVENT * PF sends this message to inform the VF driver of events that may affect it. * No direct response is expected from the VF, though it may generate other