Hi,

On Thu, Feb 15, 2007 at 11:34:48PM +0200, V.Chukharev wrote:
> Hi,
> 
> It seems that iwi driver cannot survive more than just a few cycles
> of switching down/up.
> In a place with a bad wireless connection I needed to do that quite
> a number of times
> (that was the simplest way to restore connectivity I knew), and after
> 5-10 cycles I needed
> to reboot my notebook totally.
> 
> Can anybody with iwi (<Intel(R) PRO/Wireless 2200BG>) confirm (or
> better unconfirm)
> that doing
> 
>     for ii in `jot 100`; do sudo ifconfig iwi0 down; sleep 2; sudo ifconfig 
> iwi0 up; done
> 
> always results in the following messages (and lost connectivity):
> 
> Feb 15 09:43:59 chu kernel: iwi0: link state changed to DOWN
> Feb 15 09:44:13 chu kernel: iwi0: link state changed to UP
> Feb 15 09:44:13 chu kernel: iwi0: link state changed to DOWN
> Feb 15 09:44:18 chu kernel: iwi0: device timeout
> Feb 15 09:44:20 chu kernel: iwi0: could not allocate firmware DMA memory
> 
> A fix for this would be even better ;))

cognet@ has once provided me a tiny hack to the iwi(4) driver and
I never get such errors.  Maybe I'm not suffering enough UP/DOWN
cycles to trigger it, but it might be worth trying it.

Note that he has insisted that this is a *hack*.

The patch is attached.  Please let us know if it makes things
better.

Regards,
-- 
Jeremie Le Hen
< jeremie at le-hen dot org >< ttz at chchile dot org >
Index: if_iwi.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/iwi/if_iwi.c,v
retrieving revision 1.45
diff -u -p -r1.45 if_iwi.c
--- if_iwi.c    2 Feb 2007 05:17:18 -0000       1.45
+++ if_iwi.c    16 Feb 2007 17:40:33 -0000
@@ -512,6 +512,12 @@ iwi_detach(device_t dev)
        if (sc->mem != NULL)
                bus_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, sc->mem);
 
+       if (sc->fw_map)
+               bus_dmamap_unload(sc->fw_dmat, sc->fw_map);
+       if (sc->fw_virtaddr != 0)
+               bus_dmamem_free(sc->fw_dmat, sc->fw_virtaddr, sc->fw_map);
+       if (sc->fw_dmat)
+               bus_dma_tag_destroy(sc->fw_dmat);
        if (ifp != NULL)
                if_free(ifp);
 
@@ -3085,6 +3091,7 @@ iwi_init_locked(void *priv, int force)
        struct ifnet *ifp = ic->ic_ifp;
        struct iwi_rx_data *data;
        int i;
+       int must_realloc = 0;
        IWI_LOCK_DECL;
 
        if (sc->flags & IWI_FLAG_FW_LOADING)
@@ -3106,14 +3113,27 @@ iwi_init_locked(void *priv, int force)
        }
 
        /* allocate DMA memory for mapping firmware image */
-       if (sc->fw_boot.size > sc->fw_dma_size)
+       if (sc->fw_boot.size > sc->fw_dma_size) {
+               must_realloc = 1;
                sc->fw_dma_size = sc->fw_boot.size;
-       if (sc->fw_fw.size > sc->fw_dma_size)
+       }
+       if (sc->fw_fw.size > sc->fw_dma_size) {
+               must_realloc = 1;
                sc->fw_dma_size = sc->fw_fw.size;
-       if (sc->fw_uc.size > sc->fw_dma_size)
+       }
+       if (sc->fw_uc.size > sc->fw_dma_size) {
                sc->fw_dma_size = sc->fw_uc.size;
+               must_realloc = 1;
+       }
+       if (must_realloc && sc->fw_virtaddr != 0) {
+               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 (bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 4, 0, 
+       if (must_realloc &&
+           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) {
@@ -3122,14 +3142,16 @@ iwi_init_locked(void *priv, int force)
                IWI_LOCK(sc);
                goto fail;
        }
-       if (bus_dmamem_alloc(sc->fw_dmat, &sc->fw_virtaddr, 0,
+       if (must_realloc &&
+           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,
+       if (must_realloc &&
+           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);
@@ -3185,11 +3207,6 @@ iwi_init_locked(void *priv, int force)
        }
        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;
@@ -3218,6 +3235,7 @@ fail4:    bus_dmamap_sync(sc->fw_dmat, sc->
 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->fw_virtaddr = 0;
        sc->flags &= ~IWI_FLAG_FW_LOADING;
        iwi_stop(sc);
        iwi_put_firmware(sc);
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-net
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to