Eliminate BUS_DMA <-> cache incoherencies in USB transfers.

With write-allocate cache we get into the following scenario:

1. data has been updated in the memory by the USB HC, but
2. D-cache holds an un-flushed value of it
3. when affected cache line is being replaced, the old (un-flushed) value is
flushed and overwrites the newly arrived

This is possible due to how write-allocate works with virtual caches (ARM for
example).

In case of USB transfers it leads to fatal tags discrepancies in umass(4)
operation, which look like the following:

umass0: Invalid CSW: tag 1 should be 2
(probe0:umass-sim0:0:0:0): Request completed with CAM_REQ_CMP_ERR
(probe0:umass-sim0:0:0:0): Retrying Command
umass0: Invalid CSW: tag 1 should be 3
(probe0:umass-sim0:0:0:0): Request completed with CAM_REQ_CMP_ERR
(probe0:umass-sim0:0:0:0): Retrying Command
umass0: Invalid CSW: tag 1 should be 4
(probe0:umass-sim0:0:0:0): Request completed with CAM_REQ_CMP_ERR
(probe0:umass-sim0:0:0:0): Retrying Command
umass0: Invalid CSW: tag 1 should be 5
(probe0:umass-sim0:0:0:0): Request completed with CAM_REQ_CMP_ERR
(probe0:umass-sim0:0:0:0): Retrying Command
umass0: Invalid CSW: tag 1 should be 6
(probe0:umass-sim0:0:0:0): Request completed with CAM_REQ_CMP_ERR
(probe0:umass-sim0:0:0:0): error 5
(probe0:umass-sim0:0:0:0): Retries Exausted

To eliminate this, a BUS_DMASYNC_PREREAD sync operation is required in
usbd_start_transfer().

Credits for nailing this down go to Grzegorz Bernacki gjb AT semihalf DOT com.

Reviewed by:	imp
Approved by:	cognet (mentor)
This commit is contained in:
Rafal Jaworowski 2008-02-12 11:03:29 +00:00
parent 3efe0d9d2a
commit 5713ef0ced
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=176203

View File

@ -383,7 +383,8 @@ usbd_start_transfer(void *arg, bus_dma_segment_t *segs, int nseg, int error)
* packet.
*/
bus_dmamap_sync(tag, dmap->map, BUS_DMASYNC_PREWRITE);
}
} else
bus_dmamap_sync(tag, dmap->map, BUS_DMASYNC_PREREAD);
}
err = pipe->methods->transfer(xfer);
if (err != USBD_IN_PROGRESS && err) {