Re: [PATCH 1/2] mwifiex: Use non-posted PCI register writes

From: Heiner Kallweit
Date: Wed Sep 01 2021 - 15:07:55 EST


On 01.09.2021 19:07, Johannes Berg wrote:
> On Wed, 2021-09-01 at 18:51 +0200, Heiner Kallweit wrote:
>> On 01.09.2021 17:51, Pali Rohár wrote:
>>> On Wednesday 01 September 2021 16:01:54 Jonas Dreßler wrote:
>>>> On 8/30/21 2:49 PM, Andy Shevchenko wrote:
>>>>> On Mon, Aug 30, 2021 at 3:38 PM Jonas Dreßler <verdre@xxxxxxx> wrote:
>>>>>>
>>>>>> On the 88W8897 card it's very important the TX ring write pointer is
>>>>>> updated correctly to its new value before setting the TX ready
>>>>>> interrupt, otherwise the firmware appears to crash (probably because
>>>>>> it's trying to DMA-read from the wrong place).
>>>>>>
>>
>> This sounds somehow like the typical case where you write DMA descriptors
>> and then ring the doorbell. This normally requires a dma_wmb().
>> Maybe something like that is missing here?
>
> But it looks like this "TX ring write pointer" is actually the register?
>
> However, I would agree that doing it in mwifiex_write_reg() is possibly
> too big a hammer - could be done only for reg->tx_wrptr, not all the
> registers?
>
> Actually, can two writes actually cross on PCI?
>
> johannes
>

In case we're talking about the following piece of code both register
writes are IOMEM writes that are ordered. Maybe the writes arrive properly
ordered but some chip-internal delays cause the issue? Then the read-back
would be something like an ordinary udelay()?
Instead of always reading back register writes, is it sufficient to read
an arbitrary register after mwifiex_write_reg(adapter, reg->tx_wrptr ?


/* Write the TX ring write pointer in to reg->tx_wrptr */
if (mwifiex_write_reg(adapter, reg->tx_wrptr,
card->txbd_wrptr | rx_val)) {
mwifiex_dbg(adapter, ERROR,
"SEND DATA: failed to write reg->tx_wrptr\n");
ret = -1;
goto done_unmap;
}
if ((mwifiex_pcie_txbd_not_full(card)) &&
tx_param->next_pkt_len) {
/* have more packets and TxBD still can hold more */
mwifiex_dbg(adapter, DATA,
"SEND DATA: delay dnld-rdy interrupt.\n");
adapter->data_sent = false;
} else {
/* Send the TX ready interrupt */
if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
CPU_INTR_DNLD_RDY)) {