mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-19 10:53:58 +00:00
Chain the bus_dmamap_load() calls when mapping a command with a data CCB
instead of doing the first load with the BUS_DMA_NOWAIT flag. On 4.x with PAE and > 4gb of RAM this proved disastrous if there weren't enough bounce pages as amr_mapcmd() would return failure but the callback would later fire once enough bounce pages were available and would then overwrite another command's S/G list. MFC after: 3 days Submitted by: scottl (4.x version) Reviewed by: scottl (port from 4.x to HEAD)
This commit is contained in:
parent
99f08b7740
commit
44daafbccc
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=160443
@ -1785,13 +1785,44 @@ amr_setup_ccb64map(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
amr_setup_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nsegments,
|
||||
int error)
|
||||
{
|
||||
struct amr_command *ac = (struct amr_command *)arg;
|
||||
struct amr_softc *sc = ac->ac_sc;
|
||||
|
||||
amr_setup_dmamap(arg, segs, nsegments, error);
|
||||
|
||||
if (bus_dmamap_load(sc->amr_buffer_dmat, ac->ac_ccb_dmamap,
|
||||
ac->ac_ccb_data, ac->ac_ccb_length, amr_setup_ccbmap, ac,
|
||||
0) == EINPROGRESS) {
|
||||
sc->amr_state |= AMR_STATE_QUEUE_FRZN;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
amr_setup_dma64map_cb(void *arg, bus_dma_segment_t *segs, int nsegments,
|
||||
int error)
|
||||
{
|
||||
struct amr_command *ac = (struct amr_command *)arg;
|
||||
struct amr_softc *sc = ac->ac_sc;
|
||||
|
||||
amr_setup_dma64map(arg, segs, nsegments, error);
|
||||
|
||||
if (bus_dmamap_load(sc->amr_buffer64_dmat, ac->ac_ccb_dma64map,
|
||||
ac->ac_ccb_data, ac->ac_ccb_length, amr_setup_ccb64map, ac,
|
||||
0) == EINPROGRESS) {
|
||||
sc->amr_state |= AMR_STATE_QUEUE_FRZN;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
amr_mapcmd(struct amr_command *ac)
|
||||
{
|
||||
bus_dma_tag_t tag;
|
||||
bus_dmamap_t datamap, ccbmap;
|
||||
bus_dmamap_t datamap;
|
||||
bus_dmamap_callback_t *cb;
|
||||
bus_dmamap_callback_t *ccb_cb;
|
||||
struct amr_softc *sc = ac->ac_sc;
|
||||
|
||||
debug_called(3);
|
||||
@ -1799,35 +1830,22 @@ amr_mapcmd(struct amr_command *ac)
|
||||
if (AC_IS_SG64(ac)) {
|
||||
tag = sc->amr_buffer64_dmat;
|
||||
datamap = ac->ac_dma64map;
|
||||
ccbmap = ac->ac_ccb_dma64map;
|
||||
cb = amr_setup_dma64map;
|
||||
ccb_cb = amr_setup_ccb64map;
|
||||
cb = amr_setup_dma64map_cb;
|
||||
} else {
|
||||
tag = sc->amr_buffer_dmat;
|
||||
datamap = ac->ac_dmamap;
|
||||
ccbmap = ac->ac_ccb_dmamap;
|
||||
cb = amr_setup_dmamap;
|
||||
ccb_cb = amr_setup_ccbmap;
|
||||
cb = amr_setup_dmamap_cb;
|
||||
}
|
||||
|
||||
/* if the command involves data at all, and hasn't been mapped */
|
||||
if ((ac->ac_flags & AMR_CMD_MAPPED) == 0 && (ac->ac_data != NULL)) {
|
||||
if (ac->ac_ccb_data == NULL) {
|
||||
/* map the data buffers into bus space and build the s/g list */
|
||||
if (bus_dmamap_load(tag, datamap, ac->ac_data, ac->ac_length,
|
||||
amr_setup_data_dmamap, ac, 0) == EINPROGRESS) {
|
||||
sc->amr_state |= AMR_STATE_QUEUE_FRZN;
|
||||
}
|
||||
} else {
|
||||
if (bus_dmamap_load(tag, datamap, ac->ac_data, ac->ac_length,
|
||||
cb, ac, BUS_DMA_NOWAIT) != 0) {
|
||||
return (ENOMEM);
|
||||
}
|
||||
if (bus_dmamap_load(tag, ccbmap, ac->ac_ccb_data,
|
||||
ac->ac_ccb_length, ccb_cb, ac, 0) == EINPROGRESS) {
|
||||
sc->amr_state |= AMR_STATE_QUEUE_FRZN;
|
||||
}
|
||||
}
|
||||
if (ac->ac_ccb_data == NULL)
|
||||
cb = amr_setup_data_dmamap;
|
||||
/* map the data buffers into bus space and build the s/g list */
|
||||
if (bus_dmamap_load(tag, datamap, ac->ac_data, ac->ac_length,
|
||||
cb, ac, 0) == EINPROGRESS) {
|
||||
sc->amr_state |= AMR_STATE_QUEUE_FRZN;
|
||||
}
|
||||
} else {
|
||||
if (sc->amr_submit_command(ac) == EBUSY) {
|
||||
amr_freeslot(ac);
|
||||
|
Loading…
Reference in New Issue
Block a user