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)) {