[PATCH 2/2] wifi: ath11k: use unique QRTR instance ID

Jeffrey Hugo quic_jhugo at quicinc.com
Mon Nov 7 10:02:32 PST 2022


On 11/7/2022 10:52 AM, Robert Marko wrote:
> On Mon, 7 Nov 2022 at 18:47, Manivannan Sadhasivam <mani at kernel.org> wrote:
>>
>> On Sat, Nov 05, 2022 at 08:49:43PM +0100, Robert Marko wrote:
>>> Currently, trying to use AHB + PCI/MHI cards or multiple PCI/MHI cards
>>> will cause a clash in the QRTR instance node ID and prevent the driver
>>> from talking via QMI to the card and thus initializing it with:
>>> [    9.836329] ath11k c000000.wifi: host capability request failed: 1 90
>>> [    9.842047] ath11k c000000.wifi: failed to send qmi host cap: -22
>>>
>>
>> There is still an outstanding issue where you cannot connect two WLAN modules
>> with same node id.
> 
> Yes, but as far as I can understand QRTR that is never gonna be
> possible, node ID-s
> must be different, but I dont have any docs at all.
> 
>>
>>> So, in order to allow for this combination of cards, especially AHB + PCI
>>> cards like IPQ8074 + QCN9074 (Used by me and tested on) set the desired
>>> QRTR instance ID offset by calculating a unique one based on PCI domain
>>> and bus ID-s and writing it to bits 7-0 of BHI_ERRDBG2 MHI register by
>>> using the SBL state callback that is added as part of the series.
>>> We also have to make sure that new QRTR offset is added on top of the
>>> default QRTR instance ID-s that are currently used in the driver.
>>>
>>
>> Register BHI_ERRDBG2 is listed as Read only from Host as per the BHI spec.
>> So I'm not sure if this solution is going to work on all ath11k supported
>> chipsets.
>>
>> Kalle, can you confirm?
>>
>>> This finally allows using AHB + PCI or multiple PCI cards on the same
>>> system.
>>>
>>> Before:
>>> root at OpenWrt:/# qrtr-lookup
>>>    Service Version Instance Node  Port
>>>       1054       1        0    7     1 <unknown>
>>>         69       1        2    7     3 ATH10k WLAN firmware service
>>>
>>> After:
>>> root at OpenWrt:/# qrtr-lookup
>>>    Service Version Instance Node  Port
>>>       1054       1        0    7     1 <unknown>
>>>         69       1        2    7     3 ATH10k WLAN firmware service
>>>         15       1        0    8     1 Test service
>>>         69       1        8    8     2 ATH10k WLAN firmware service
>>>
>>> Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.5.0.1-01208-QCAHKSWPL_SILICONZ-1
>>> Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.5.0.1-01208-QCAHKSWPL_SILICONZ-1
>>>
>>> Signed-off-by: Robert Marko <robimarko at gmail.com>
>>> ---
>>>   drivers/net/wireless/ath/ath11k/mhi.c | 47 ++++++++++++++++++---------
>>>   drivers/net/wireless/ath/ath11k/mhi.h |  3 ++
>>>   drivers/net/wireless/ath/ath11k/pci.c |  5 ++-
>>>   3 files changed, 38 insertions(+), 17 deletions(-)
>>>
>>> diff --git a/drivers/net/wireless/ath/ath11k/mhi.c b/drivers/net/wireless/ath/ath11k/mhi.c
>>> index 86995e8dc913..23e85ea902f5 100644
>>> --- a/drivers/net/wireless/ath/ath11k/mhi.c
>>> +++ b/drivers/net/wireless/ath/ath11k/mhi.c
>>> @@ -294,6 +294,32 @@ static void ath11k_mhi_op_runtime_put(struct mhi_controller *mhi_cntrl)
>>>   {
>>>   }
>>>
>>> +static int ath11k_mhi_op_read_reg(struct mhi_controller *mhi_cntrl,
>>> +                               void __iomem *addr,
>>> +                               u32 *out)
>>> +{
>>> +     *out = readl(addr);
>>> +
>>> +     return 0;
>>> +}
>>> +
>>> +static void ath11k_mhi_op_write_reg(struct mhi_controller *mhi_cntrl,
>>> +                                 void __iomem *addr,
>>> +                                 u32 val)
>>> +{
>>> +     writel(val, addr);
>>> +}
>>> +
>>> +static void ath11k_mhi_qrtr_instance_set(struct mhi_controller *mhi_cntrl)
>>> +{
>>> +     struct ath11k_base *ab = dev_get_drvdata(mhi_cntrl->cntrl_dev);
>>> +
>>> +     ath11k_mhi_op_write_reg(mhi_cntrl,
>>> +                             mhi_cntrl->bhi + BHI_ERRDBG2,
>>> +                             FIELD_PREP(QRTR_INSTANCE_MASK,
>>> +                             ab->qmi.service_ins_id - ab->hw_params.qmi_service_ins_id));
>>> +}
>>> +
>>>   static char *ath11k_mhi_op_callback_to_str(enum mhi_callback reason)
>>>   {
>>>        switch (reason) {
>>> @@ -315,6 +341,8 @@ static char *ath11k_mhi_op_callback_to_str(enum mhi_callback reason)
>>>                return "MHI_CB_FATAL_ERROR";
>>>        case MHI_CB_BW_REQ:
>>>                return "MHI_CB_BW_REQ";
>>> +     case MHI_CB_EE_SBL_MODE:
>>> +             return "MHI_CB_EE_SBL_MODE";
>>>        default:
>>>                return "UNKNOWN";
>>>        }
>>> @@ -336,27 +364,14 @@ static void ath11k_mhi_op_status_cb(struct mhi_controller *mhi_cntrl,
>>>                if (!(test_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags)))
>>>                        queue_work(ab->workqueue_aux, &ab->reset_work);
>>>                break;
>>> +     case MHI_CB_EE_SBL_MODE:
>>> +             ath11k_mhi_qrtr_instance_set(mhi_cntrl);
>>
>> I still don't understand how SBL could make use of this information during
>> boot without waiting for an update.
> 
> Me neither, but it works reliably as long as it's updated once SBL is live.
> Trying to do it earlier or later does nothing, it will just use the
> default node ID then.

If I recall correctly, PBL will write to the register at the end of the 
BHI process, even in the success case.  So, you have a race condition 
where you need to update the register after BHI is complete, but before 
SBL reads it.

If the value is just based on the BDF, I don't see why the device 
couldn't compute it without input from the host.  This whole mechanism 
seems pretty poorly designed, but sadly I don't have any brilliant ideas 
on how to fix it for you.



More information about the ath11k mailing list