On Friday 16 February 2007 17:51, Luigi Rizzo wrote: > On Fri, Feb 16, 2007 at 05:38:28PM +0100, Max Laier wrote: > ... > > > I'm under the impression that this is more a problem of increasing > > fragmentation until we can't get a big enough unfragmented chunk. I > > don't have any proof of this assumption yet. > > makes sense. > As a matter of fact i wonder whether it wouldn't be smarter > to allocate the dma-ble memory on the first request and > keep it around until the driver is unloaded. > > If i read the code in iwi_load_firmware() correctly, > the contiguous chunks cannot be longer than 8191 bytes, > so a single contiguous buffer is not mandatory. > I just don't know if we can write the firmware to the adapter > with multiple operations (lists of command blocks) or > it needs to be just a single list ?
The linux driver uses one continuous buffer as well. I tried to hand in separate buffers, but it failed to initialize the firmware. Attached is a diff (for HEAD and RELENG_6) to allocate the DMA buffer once and keep it around. As I said earlier: As long as the firmware is as (un)stable as it is now, this might be the only sensible way. All in all it's not that bad, as we "only" throw away 212966 bytes. Could you please confirm that this works for you? -- /"\ Best regards, | [EMAIL PROTECTED] \ / Max Laier | ICQ #67774661 X http://pf4freebsd.love2party.net/ | [EMAIL PROTECTED] / \ ASCII Ribbon Campaign | Against HTML Mail and News
Index: if_iwi.c =================================================================== RCS file: /usr/store/mlaier/fcvs/src/sys/dev/iwi/if_iwi.c,v retrieving revision 1.8.2.12 diff -u -r1.8.2.12 if_iwi.c --- if_iwi.c 23 Jan 2007 22:17:48 -0000 1.8.2.12 +++ if_iwi.c 18 Feb 2007 15:05:01 -0000 @@ -118,6 +118,8 @@ }; static void iwi_dma_map_addr(void *, bus_dma_segment_t *, int, int); +static int iwi_alloc_fw_cb(struct iwi_softc *); +static void iwi_free_fw_cb(struct iwi_softc *); static int iwi_alloc_cmd_ring(struct iwi_softc *, struct iwi_cmd_ring *, int); static void iwi_reset_cmd_ring(struct iwi_softc *, struct iwi_cmd_ring *); @@ -322,6 +324,12 @@ goto fail; } + if (iwi_alloc_fw_cb(sc) != 0) { + device_printf(dev, + "could not allocate firmware command block\n"); + goto fail; + } + /* * Allocate rings. */ @@ -496,6 +504,7 @@ } iwi_put_firmware(sc); + iwi_free_fw_cb(sc); iwi_free_cmd_ring(sc, &sc->cmdq); iwi_free_tx_ring(sc, &sc->txq[0]); iwi_free_tx_ring(sc, &sc->txq[1]); @@ -536,6 +545,57 @@ } static int +iwi_alloc_fw_cb(struct iwi_softc *sc) +{ + int error; + + sc->fw_dma_size = IWI_CB_MAXDATALEN * IWI_FW_CB_MAX; + + error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 4, 0, + BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, + sc->fw_dma_size, 1, sc->fw_dma_size, 0, NULL, NULL, + &sc->fw_dmat); + if (error != 0) { + device_printf(sc->sc_dev, + "could not create firmware DMA tag\n"); + goto fail; + } + + error = bus_dmamem_alloc(sc->fw_dmat, &sc->fw_virtaddr, 0, + &sc->fw_map); + if (error != 0) { + device_printf(sc->sc_dev, + "could not allocate firmware DMA memory\n"); + goto fail; + } + + error = bus_dmamap_load(sc->fw_dmat, sc->fw_map, sc->fw_virtaddr, + sc->fw_dma_size, iwi_dma_map_addr, &sc->fw_physaddr, 0); + if (error != 0) { + device_printf(sc->sc_dev, "could not load firmware DMA map\n"); + goto fail; + } + + return (0); +fail: iwi_free_fw_cb(sc); + return (error); +} + +static void +iwi_free_fw_cb(struct iwi_softc *sc) +{ + if (sc->fw_virtaddr != NULL) { + bus_dmamap_sync(sc->fw_dmat, sc->fw_map, + BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(sc->fw_dmat, sc->fw_map); + bus_dmamem_free(sc->fw_dmat, sc->fw_virtaddr, sc->fw_map); + } + + if (sc->fw_dmat != NULL) + bus_dma_tag_destroy(sc->fw_dmat); +} + +static int iwi_alloc_cmd_ring(struct iwi_softc *sc, struct iwi_cmd_ring *ring, int count) { int error; @@ -2433,6 +2493,14 @@ uint32_t sentinel, ctl, src, dst, sum, len, mlen, tmp; int ntries, error; + if (fw->size > sc->fw_dma_size) { + device_printf(sc->sc_dev, + "to less dma memory for %s firmware (%d < %d)\n", + fw->name, sc->fw_dma_size, fw->size); + error = ENOMEM; + goto fail5; + } + /* copy firmware image to DMA memory */ memcpy(sc->fw_virtaddr, fw->data, fw->size); @@ -3099,47 +3167,18 @@ goto fail; } - /* allocate DMA memory for mapping firmware image */ - if (sc->fw_boot.size > sc->fw_dma_size) - sc->fw_dma_size = sc->fw_boot.size; - if (sc->fw_fw.size > sc->fw_dma_size) - sc->fw_dma_size = sc->fw_fw.size; - if (sc->fw_uc.size > sc->fw_dma_size) - sc->fw_dma_size = sc->fw_uc.size; - - if (bus_dma_tag_create(NULL, 4, 0, BUS_SPACE_MAXADDR_32BIT, - BUS_SPACE_MAXADDR, NULL, NULL, sc->fw_dma_size, 1, sc->fw_dma_size, - 0, NULL, NULL, &sc->fw_dmat) != 0) { - device_printf(sc->sc_dev, - "could not create firmware DMA tag\n"); - IWI_LOCK(sc); - goto fail; - } - if (bus_dmamem_alloc(sc->fw_dmat, &sc->fw_virtaddr, 0, - &sc->fw_map) != 0) { - device_printf(sc->sc_dev, - "could not allocate firmware DMA memory\n"); - IWI_LOCK(sc); - goto fail2; - } - if (bus_dmamap_load(sc->fw_dmat, sc->fw_map, sc->fw_virtaddr, - sc->fw_dma_size, iwi_dma_map_addr, &sc->fw_physaddr, 0) != 0) { - device_printf(sc->sc_dev, "could not load firmware DMA map\n"); - IWI_LOCK(sc); - goto fail3; - } IWI_LOCK(sc); if (iwi_load_firmware(sc, &sc->fw_boot) != 0) { device_printf(sc->sc_dev, "could not load boot firmware %s\n", sc->fw_boot.name); - goto fail4; + goto fail; } if (iwi_load_ucode(sc, &sc->fw_uc) != 0) { device_printf(sc->sc_dev, "could not load microcode %s\n", sc->fw_uc.name); - goto fail4; + goto fail; } iwi_stop_master(sc); @@ -3174,15 +3213,10 @@ if (iwi_load_firmware(sc, &sc->fw_fw) != 0) { device_printf(sc->sc_dev, "could not load main firmware %s\n", sc->fw_fw.name); - goto fail4; + goto fail; } sc->flags |= IWI_FLAG_FW_INITED; - bus_dmamap_sync(sc->fw_dmat, sc->fw_map, BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(sc->fw_dmat, sc->fw_map); - bus_dmamem_free(sc->fw_dmat, sc->fw_virtaddr, sc->fw_map); - bus_dma_tag_destroy(sc->fw_dmat); - if (iwi_config(sc) != 0) { device_printf(sc->sc_dev, "device configuration failed\n"); goto fail; @@ -3206,10 +3240,6 @@ sc->flags &= ~IWI_FLAG_FW_LOADING; return; -fail4: bus_dmamap_sync(sc->fw_dmat, sc->fw_map, BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(sc->fw_dmat, sc->fw_map); -fail3: bus_dmamem_free(sc->fw_dmat, sc->fw_virtaddr, sc->fw_map); -fail2: bus_dma_tag_destroy(sc->fw_dmat); fail: ifp->if_flags &= ~IFF_UP; sc->flags &= ~IWI_FLAG_FW_LOADING; iwi_stop(sc); Index: if_iwireg.h =================================================================== RCS file: /usr/store/mlaier/fcvs/src/sys/dev/iwi/if_iwireg.h,v retrieving revision 1.2.2.4 diff -u -r1.2.2.4 if_iwireg.h --- if_iwireg.h 29 Oct 2006 08:29:31 -0000 1.2.2.4 +++ if_iwireg.h 18 Feb 2007 15:04:28 -0000 @@ -144,6 +144,9 @@ #define IWI_FW_GET_MAJOR(ver) ((ver) & 0xff) #define IWI_FW_GET_MINOR(ver) (((ver) & 0xff00) >> 8) +/* max firmware size in command blocks (0x1fff) */ +#define IWI_FW_CB_MAX 26 + #define IWI_FW_MODE_UCODE 0 #define IWI_FW_MODE_BOOT 0 #define IWI_FW_MODE_BSS 0
Index: if_iwi.c =================================================================== RCS file: /usr/store/mlaier/fcvs/src/sys/dev/iwi/if_iwi.c,v retrieving revision 1.46 diff -u -r1.46 if_iwi.c --- if_iwi.c 15 Feb 2007 17:21:31 -0000 1.46 +++ if_iwi.c 18 Feb 2007 15:16:00 -0000 @@ -119,6 +119,8 @@ }; static void iwi_dma_map_addr(void *, bus_dma_segment_t *, int, int); +static int iwi_alloc_fw_cb(struct iwi_softc *); +static void iwi_free_fw_cb(struct iwi_softc *); static int iwi_alloc_cmd_ring(struct iwi_softc *, struct iwi_cmd_ring *, int); static void iwi_reset_cmd_ring(struct iwi_softc *, struct iwi_cmd_ring *); @@ -323,6 +325,12 @@ goto fail; } + if (iwi_alloc_fw_cb(sc) != 0) { + device_printf(dev, + "could not allocate firmware command block\n"); + goto fail; + } + /* * Allocate rings. */ @@ -497,6 +505,7 @@ } iwi_put_firmware(sc); + iwi_free_fw_cb(sc); iwi_free_cmd_ring(sc, &sc->cmdq); iwi_free_tx_ring(sc, &sc->txq[0]); iwi_free_tx_ring(sc, &sc->txq[1]); @@ -537,6 +546,57 @@ } static int +iwi_alloc_fw_cb(struct iwi_softc *sc) +{ + int error; + + sc->fw_dma_size = IWI_CB_MAXDATALEN * IWI_FW_CB_MAX; + + error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 4, 0, + BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, + sc->fw_dma_size, 1, sc->fw_dma_size, 0, NULL, NULL, + &sc->fw_dmat); + if (error != 0) { + device_printf(sc->sc_dev, + "could not create firmware DMA tag\n"); + goto fail; + } + + error = bus_dmamem_alloc(sc->fw_dmat, &sc->fw_virtaddr, 0, + &sc->fw_map); + if (error != 0) { + device_printf(sc->sc_dev, + "could not allocate firmware DMA memory\n"); + goto fail; + } + + error = bus_dmamap_load(sc->fw_dmat, sc->fw_map, sc->fw_virtaddr, + sc->fw_dma_size, iwi_dma_map_addr, &sc->fw_physaddr, 0); + if (error != 0) { + device_printf(sc->sc_dev, "could not load firmware DMA map\n"); + goto fail; + } + + return (0); +fail: iwi_free_fw_cb(sc); + return (error); +} + +static void +iwi_free_fw_cb(struct iwi_softc *sc) +{ + if (sc->fw_virtaddr != NULL) { + bus_dmamap_sync(sc->fw_dmat, sc->fw_map, + BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(sc->fw_dmat, sc->fw_map); + bus_dmamem_free(sc->fw_dmat, sc->fw_virtaddr, sc->fw_map); + } + + if (sc->fw_dmat != NULL) + bus_dma_tag_destroy(sc->fw_dmat); +} + +static int iwi_alloc_cmd_ring(struct iwi_softc *sc, struct iwi_cmd_ring *ring, int count) { int error; @@ -2439,6 +2499,14 @@ uint32_t sentinel, ctl, src, dst, sum, len, mlen, tmp; int ntries, error; + if (fw->size > sc->fw_dma_size) { + device_printf(sc->sc_dev, + "to less dma memory for %s firmware (%d < %d)\n", + fw->name, sc->fw_dma_size, fw->size); + error = ENOMEM; + goto fail5; + } + /* copy firmware image to DMA memory */ memcpy(sc->fw_virtaddr, fw->data, fw->size); @@ -3105,48 +3173,18 @@ goto fail; } - /* allocate DMA memory for mapping firmware image */ - if (sc->fw_boot.size > sc->fw_dma_size) - sc->fw_dma_size = sc->fw_boot.size; - if (sc->fw_fw.size > sc->fw_dma_size) - sc->fw_dma_size = sc->fw_fw.size; - if (sc->fw_uc.size > sc->fw_dma_size) - sc->fw_dma_size = sc->fw_uc.size; - - if (bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 4, 0, - BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, - sc->fw_dma_size, 1, sc->fw_dma_size, 0, NULL, NULL, - &sc->fw_dmat) != 0) { - device_printf(sc->sc_dev, - "could not create firmware DMA tag\n"); - IWI_LOCK(sc); - goto fail; - } - if (bus_dmamem_alloc(sc->fw_dmat, &sc->fw_virtaddr, 0, - &sc->fw_map) != 0) { - device_printf(sc->sc_dev, - "could not allocate firmware DMA memory\n"); - IWI_LOCK(sc); - goto fail2; - } - if (bus_dmamap_load(sc->fw_dmat, sc->fw_map, sc->fw_virtaddr, - sc->fw_dma_size, iwi_dma_map_addr, &sc->fw_physaddr, 0) != 0) { - device_printf(sc->sc_dev, "could not load firmware DMA map\n"); - IWI_LOCK(sc); - goto fail3; - } IWI_LOCK(sc); if (iwi_load_firmware(sc, &sc->fw_boot) != 0) { device_printf(sc->sc_dev, "could not load boot firmware %s\n", sc->fw_boot.name); - goto fail4; + goto fail; } if (iwi_load_ucode(sc, &sc->fw_uc) != 0) { device_printf(sc->sc_dev, "could not load microcode %s\n", sc->fw_uc.name); - goto fail4; + goto fail; } iwi_stop_master(sc); @@ -3181,15 +3219,10 @@ if (iwi_load_firmware(sc, &sc->fw_fw) != 0) { device_printf(sc->sc_dev, "could not load main firmware %s\n", sc->fw_fw.name); - goto fail4; + goto fail; } sc->flags |= IWI_FLAG_FW_INITED; - bus_dmamap_sync(sc->fw_dmat, sc->fw_map, BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(sc->fw_dmat, sc->fw_map); - bus_dmamem_free(sc->fw_dmat, sc->fw_virtaddr, sc->fw_map); - bus_dma_tag_destroy(sc->fw_dmat); - if (iwi_config(sc) != 0) { device_printf(sc->sc_dev, "device configuration failed\n"); goto fail; @@ -3213,10 +3246,6 @@ sc->flags &= ~IWI_FLAG_FW_LOADING; return; -fail4: bus_dmamap_sync(sc->fw_dmat, sc->fw_map, BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(sc->fw_dmat, sc->fw_map); -fail3: bus_dmamem_free(sc->fw_dmat, sc->fw_virtaddr, sc->fw_map); -fail2: bus_dma_tag_destroy(sc->fw_dmat); fail: ifp->if_flags &= ~IFF_UP; sc->flags &= ~IWI_FLAG_FW_LOADING; iwi_stop(sc); Index: if_iwireg.h =================================================================== RCS file: /usr/store/mlaier/fcvs/src/sys/dev/iwi/if_iwireg.h,v retrieving revision 1.13 diff -u -r1.13 if_iwireg.h --- if_iwireg.h 23 Oct 2006 00:34:07 -0000 1.13 +++ if_iwireg.h 18 Feb 2007 15:15:37 -0000 @@ -144,6 +144,9 @@ #define IWI_FW_GET_MAJOR(ver) ((ver) & 0xff) #define IWI_FW_GET_MINOR(ver) (((ver) & 0xff00) >> 8) +/* max firmware size in command blocks (0x1fff) */ +#define IWI_FW_CB_MAX 26 + #define IWI_FW_MODE_UCODE 0 #define IWI_FW_MODE_BOOT 0 #define IWI_FW_MODE_BSS 0
pgpQ3d2brmQMn.pgp
Description: PGP signature