- Add a workaround for the DMA bugs on some alpha chipsets that ATA DMA
trips over often. Specifically, in these chipsets DMA transfers that cross a page boundary result in data corruption. The workaround is to not allow any DMA transfers for non-static DMA maps (i.e. "real" transfers as opposed to work areas allocated with bus_dmamem_alloc()) to cross a page in a single S/G element. This behavior is enabled by setting 'busdma_pyxis_bug' to 1. - Add a new tunable 'machdep.busdma_pyxis_bug' that can be used to enable the workaround from the loader. This can be used to enable it on chipsets where we don't automatically enable it. - Auto-enable the workaround for buggy PYXIS 1 chipsets supported via cia(4). PR: alpha/75317
This commit is contained in:
parent
368a32e277
commit
04328504a1
@ -77,7 +77,8 @@ struct bounce_page {
|
||||
STAILQ_ENTRY(bounce_page) links;
|
||||
};
|
||||
|
||||
int busdma_swi_pending;
|
||||
int busdma_pyxis_bug, busdma_swi_pending;
|
||||
TUNABLE_INT("machdep.busdma_pyxis_bug", &busdma_pyxis_bug);
|
||||
|
||||
static struct mtx bounce_lock;
|
||||
static STAILQ_HEAD(bp_list, bounce_page) bounce_page_list;
|
||||
@ -514,6 +515,22 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dmat,
|
||||
vm_offset_t vaddr;
|
||||
bus_addr_t paddr;
|
||||
int seg;
|
||||
bus_size_t boundary;
|
||||
bus_size_t maxsegsz;
|
||||
|
||||
/*
|
||||
* Enforce a boundary of 8k for buffers that aren't allocated
|
||||
* via bus_dmamem_alloc() on systems with the Pyxis pass 1 DMA
|
||||
* bug. This is somewhat gross.
|
||||
*/
|
||||
boundary = dmat->boundary;
|
||||
maxsegsz = dmat->maxsegsz;
|
||||
if (busdma_pyxis_bug && map != &nobounce_dmamap) {
|
||||
if (boundary == 0 || boundary > 8192)
|
||||
boundary = 8192;
|
||||
if (boundary < maxsegsz)
|
||||
maxsegsz = boundary;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are being called during a callback, pagesneeded will
|
||||
@ -566,7 +583,7 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dmat,
|
||||
|
||||
vaddr = (vm_offset_t)buf;
|
||||
lastaddr = *lastaddrp;
|
||||
bmask = ~(dmat->boundary - 1);
|
||||
bmask = ~(boundary - 1);
|
||||
|
||||
for (seg = *segp; buflen > 0 ; ) {
|
||||
/*
|
||||
@ -587,8 +604,8 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dmat,
|
||||
/*
|
||||
* Make sure we don't cross any boundaries.
|
||||
*/
|
||||
if (dmat->boundary > 0) {
|
||||
baddr = (curaddr + dmat->boundary) & bmask;
|
||||
if (boundary > 0) {
|
||||
baddr = (curaddr + boundary) & bmask;
|
||||
if (sgsize > (baddr - curaddr))
|
||||
sgsize = (baddr - curaddr);
|
||||
}
|
||||
@ -611,8 +628,8 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dmat,
|
||||
first = 0;
|
||||
} else {
|
||||
if (curaddr == lastaddr &&
|
||||
(segs[seg].ds_len + sgsize) <= dmat->maxsegsz &&
|
||||
(dmat->boundary == 0 ||
|
||||
(segs[seg].ds_len + sgsize) <= maxsegsz &&
|
||||
(boundary == 0 ||
|
||||
(segs[seg].ds_addr & bmask) == (curaddr & bmask)))
|
||||
segs[seg].ds_len += sgsize;
|
||||
else {
|
||||
|
@ -50,6 +50,7 @@ extern int szfreebsd4_sigcode;
|
||||
#endif
|
||||
extern long Maxmem;
|
||||
extern int busdma_swi_pending;
|
||||
extern int busdma_pyxis_bug;
|
||||
extern struct rpb *hwrpb;
|
||||
extern volatile int mc_expected;
|
||||
extern volatile int mc_received;
|
||||
|
@ -490,6 +490,7 @@ cia_attach(device_t dev)
|
||||
ctrl &= ~(CTRL_RD_TYPE|CTRL_RL_TYPE|CTRL_RM_TYPE);
|
||||
REGVAL(CIA_CSR_CTRL) = ctrl;
|
||||
alpha_mb();
|
||||
busdma_pyxis_bug = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user