--- a/sys/dev/raid/amr/amr_pci.c +++ b/sys/dev/raid/amr/amr_pci.c @@ -544,6 +544,7 @@ amr_sglist_map(struct amr_softc *sc) size_t segsize; void *p; int error; + int retries = 0; debug_called(1); @@ -592,14 +593,23 @@ amr_sglist_map(struct amr_softc *sc) retry: error = bus_dmamem_alloc(sc->amr_sg_dmat, &p, BUS_DMA_NOWAIT, &sc->amr_sg_dmamap); if (error) { device_printf(sc->amr_dev, "can't allocate s/g table\n"); return(ENOMEM); } - bus_dmamap_load(sc->amr_sg_dmat, sc->amr_sg_dmamap, p, segsize, amr_sglist_helper, &sc->amr_sgbusaddr, 0); + error = bus_dmamap_load(sc->amr_sg_dmat, sc->amr_sg_dmamap, p, segsize, amr_sglist_helper, &sc->amr_sgbusaddr, 0); + if (error) { + device_printf(sc->amr_dev, "can't load s/g table\n"); + bus_dmamem_free(sc->amr_sg_dmat, p, sc->amr_sg_dmamap); + return(ENOMEM); + } if (sc->amr_sgbusaddr < 0x2000) { debug(1, "s/g table too low (0x%x), reallocating\n", sc->amr_sgbusaddr); + bus_dmamap_unload(sc->amr_sg_dmat, sc->amr_sg_dmamap); + bus_dmamem_free(sc->amr_sg_dmat, p, sc->amr_sg_dmamap); + if (++retries > 8) { + device_printf(sc->amr_dev, "s/g table stuck too low, giving up\n"); + return(ENOMEM); + } goto retry; } @@ -651,8 +660,13 @@ amr_setup_mbox(struct amr_softc *sc) error = bus_dmamem_alloc(sc->amr_mailbox_dmat, &p, BUS_DMA_NOWAIT, &sc->amr_mailbox_dmamap); if (error) { device_printf(sc->amr_dev, "can't allocate mailbox memory\n"); return(ENOMEM); } - bus_dmamap_load(sc->amr_mailbox_dmat, sc->amr_mailbox_dmamap, p, - sizeof(struct amr_mailbox64), amr_sglist_helper, &baddr, 0); + error = bus_dmamap_load(sc->amr_mailbox_dmat, sc->amr_mailbox_dmamap, p, + sizeof(struct amr_mailbox64), amr_sglist_helper, &baddr, 0); + if (error) { + device_printf(sc->amr_dev, "can't load mailbox\n"); + return(ENOMEM); + } @@ -695,7 +709,11 @@ amr_ccb_map(struct amr_softc *sc) if (error) { device_printf(sc->amr_dev, "can't allocate ccb memory\n"); return (ENOMEM); } - bus_dmamap_load(sc->amr_ccb_dmat, sc->amr_ccb_dmamap, sc->amr_ccb, - ccbsize, amr_sglist_helper, &sc->amr_ccb_busaddr, 0); + error = bus_dmamap_load(sc->amr_ccb_dmat, sc->amr_ccb_dmamap, sc->amr_ccb, + ccbsize, amr_sglist_helper, &sc->amr_ccb_busaddr, 0); + if (error) { + device_printf(sc->amr_dev, "can't load ccb block\n"); + return (ENOMEM); + }