On 21.08.2024 15:52, Alexander Lobakin wrote:
> From: Wojciech Drewek <wojciech.dre...@intel.com>
> Date: Wed, 21 Aug 2024 14:15:29 +0200
>
>> From: Jacob Keller <jacob.e.kel...@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.kel...@intel.com>
>> Reviewed-by: Wojciech Drewek <wojciech.dre...@intel.com>
>> Reviewed-by: Simon Horman <ho...@kernel.org>
>> Co-developed-by: Mateusz Polchlopek <mateusz.polchlo...@intel.com>
>> Signed-off-by: Mateusz Polchlopek <mateusz.polchlo...@intel.com>
>> Signed-off-by: Wojciech Drewek <wojciech.dre...@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