On Thu, Aug 27, 2015 at 09:23:33AM +0200, Stefan Sperling wrote:
> On Thu, Aug 27, 2015 at 08:37:53AM +0200, Remi Locherer wrote:
> > >Synopsis:  iwm0 not working during upgrade with bsd.rd
> > >Category:  kernel
> > >Environment:
> >     System      : OpenBSD 5.8
> >     Details     : OpenBSD 5.8-current (GENERIC.MP) #1269: Tue Aug 25 
> > 06:26:14 MDT 2015
> >                      
> > [email protected]:/usr/src/sys/arch/amd64/compile/GENERIC.MP
> > 
> >     Architecture: OpenBSD.amd64
> >     Machine     : amd64
> > 
> > >Description:
> >     The iwm0 driver works fine with GENERIC.MP and an Intel Dual Band
> > Wireless AC 7265 card. But when booting with bsd.rd it does not work.
> > 
> > Before I press "u" to start the update the following message is printed:
> > iwm0: could not read firmware iwm-7265-9 (error 2)
> > 
> > This makes sense since the disk with the firmware files is not mounted
> > yet. Later in the upgrade after the disk gets mounted I see this message:
> > iwm0: hw rev 0x210, fw ver 25.228 (API ver 9), address 5c:e0:c5:1f:ad:c4
> > 
> > The link never becomes active instead "iwm0: device timeout" messages
> > are printed.
> 
> This is a known issue. But no fix is available yet...

This diff fixes the issue for me.

The problem happens because iwm calls ieee80211_ifdetach and
ieee80211_ifattach when firmware load succeeds for the very first time.

During ramdisk upgrades, this can happen after the netstart script has
already configured parameters such as the network key. So the key
ends up being cleared before trying to associate.

This diff replaces the big hammer detach/attach with the minimum
necessary. It works in my testing in both GENERIC and RAMDISK_CD.

I've added new interfaces to upper layers which iwm can make use of.

ok?

Index: dev/pci/if_iwm.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_iwm.c,v
retrieving revision 1.49
diff -u -p -r1.49 if_iwm.c
--- dev/pci/if_iwm.c    26 Sep 2015 10:52:09 -0000      1.49
+++ dev/pci/if_iwm.c    26 Sep 2015 13:19:40 -0000
@@ -2803,8 +2803,10 @@ iwm_run_init_mvm_ucode(struct iwm_softc 
                        printf("%s: failed to read nvm\n", DEVNAME(sc));
                        return error;
                }
-               memcpy(&sc->sc_ic.ic_myaddr,
-                   &sc->sc_nvm.hw_addr, ETHER_ADDR_LEN);
+
+               if (IEEE80211_ADDR_EQ(etheranyaddr, sc->sc_ic.ic_myaddr))
+                       IEEE80211_ADDR_COPY(sc->sc_ic.ic_myaddr,
+                           sc->sc_nvm.hw_addr);
 
                sc->sc_scan_cmd_len = sizeof(struct iwm_scan_cmd)
                    + sc->sc_capa_max_probe_len
@@ -6370,9 +6372,14 @@ iwm_preinit(struct iwm_softc *sc)
                memset(&ic->ic_sup_rates[IEEE80211_MODE_11A], 0,
                    sizeof(ic->ic_sup_rates[IEEE80211_MODE_11A]));
 
-       /* Reattach net80211 so MAC address and channel map are picked up. */
-       ieee80211_ifdetach(ifp);
-       ieee80211_ifattach(ifp);
+       /* Configure channel information obtained from firmware. */
+       ieee80211_channel_init(ifp);
+
+       /* Configure MAC address. */
+       error = if_setlladdr(ifp, ic->ic_myaddr);
+       if (error)
+               printf("%s: could not set MAC address (error %d)\n",
+                   DEVNAME(sc), error);
 
        ic->ic_node_alloc = iwm_node_alloc;
 
Index: net/if.c
===================================================================
RCS file: /cvs/src/sys/net/if.c,v
retrieving revision 1.380
diff -u -p -r1.380 if.c
--- net/if.c    13 Sep 2015 18:15:03 -0000      1.380
+++ net/if.c    26 Sep 2015 12:51:30 -0000
@@ -1568,6 +1568,22 @@ if_put(struct ifnet *ifp)
        atomic_dec_int(&ifp->if_refcnt);
 }
 
+int
+if_setlladdr(struct ifnet *ifp, caddr_t lladdr)
+{
+       struct sockaddr_dl *sdl;
+
+       sdl = (struct sockaddr_dl *)ifp->if_sadl;
+       if (sdl == NULL)
+               return (EINVAL);
+
+       bcopy(lladdr, (caddr_t)((struct arpcom *)ifp)->ac_enaddr,
+           ETHER_ADDR_LEN);
+       bcopy(lladdr, LLADDR(sdl), ETHER_ADDR_LEN);
+
+       return (0);
+}
+
 /*
  * Interface ioctls.
  */
@@ -1969,11 +1985,7 @@ ifioctl(struct socket *so, u_long cmd, c
                case IFT_CARP:
                case IFT_XETHER:
                case IFT_ISO88025:
-                       bcopy((caddr_t)ifr->ifr_addr.sa_data,
-                           (caddr_t)((struct arpcom *)ifp)->ac_enaddr,
-                           ETHER_ADDR_LEN);
-                       bcopy((caddr_t)ifr->ifr_addr.sa_data,
-                           LLADDR(sdl), ETHER_ADDR_LEN);
+                       if_setlladdr(ifp, (caddr_t)ifr->ifr_addr.sa_data);
                        error = (*ifp->if_ioctl)(ifp, cmd, data);
                        if (error == ENOTTY)
                                error = 0;
Index: net/if.h
===================================================================
RCS file: /cvs/src/sys/net/if.h,v
retrieving revision 1.167
diff -u -p -r1.167 if.h
--- net/if.h    11 Sep 2015 13:02:28 -0000      1.167
+++ net/if.h    26 Sep 2015 12:51:26 -0000
@@ -469,6 +469,7 @@ void        ifnewlladdr(struct ifnet *);
 void   if_congestion(void);
 int    if_congested(void);
 __dead void    unhandled_af(int);
+int    if_setlladdr(struct ifnet *, caddr_t);
 
 #endif /* _KERNEL */
 
Index: net/if_ethersubr.c
===================================================================
RCS file: /cvs/src/sys/net/if_ethersubr.c,v
retrieving revision 1.226
diff -u -p -r1.226 if_ethersubr.c
--- net/if_ethersubr.c  17 Sep 2015 04:53:27 -0000      1.226
+++ net/if_ethersubr.c  26 Sep 2015 13:10:39 -0000
@@ -121,8 +121,10 @@ didn't get a copy, you may request one f
 #include <netmpls/mpls.h>
 #endif /* MPLS */
 
-u_char etherbroadcastaddr[ETHER_ADDR_LEN] =
+u_int8_t etherbroadcastaddr[ETHER_ADDR_LEN] =
     { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+u_int8_t etheranyaddr[ETHER_ADDR_LEN] =
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 #define senderr(e) { error = (e); goto bad;}
 
 int
Index: net80211/ieee80211.c
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211.c,v
retrieving revision 1.45
diff -u -p -r1.45 ieee80211.c
--- net80211/ieee80211.c        11 Sep 2015 13:02:28 -0000      1.45
+++ net80211/ieee80211.c        26 Sep 2015 11:42:52 -0000
@@ -72,24 +72,12 @@ void ieee80211_setbasicrates(struct ieee
 int ieee80211_findrate(struct ieee80211com *, enum ieee80211_phymode, int);
 
 void
-ieee80211_ifattach(struct ifnet *ifp)
+ieee80211_channel_init(struct ifnet *ifp)
 {
        struct ieee80211com *ic = (void *)ifp;
        struct ieee80211_channel *c;
        int i;
 
-       memcpy(((struct arpcom *)ifp)->ac_enaddr, ic->ic_myaddr,
-               ETHER_ADDR_LEN);
-       ether_ifattach(ifp);
-
-       ifp->if_output = ieee80211_output;
-
-#if NBPFILTER > 0
-       bpfattach(&ic->ic_rawbpf, ifp, DLT_IEEE802_11,
-           sizeof(struct ieee80211_frame_addr4));
-#endif
-       ieee80211_crypto_attach(ifp);
-
        /*
         * Fill in 802.11 available channel set, mark
         * all available channels as active, and pick
@@ -130,6 +118,26 @@ ieee80211_ifattach(struct ifnet *ifp)
                ic->ic_curmode = IEEE80211_MODE_AUTO;
        ic->ic_des_chan = IEEE80211_CHAN_ANYC;  /* any channel is ok */
        ic->ic_scan_lock = IEEE80211_SCAN_UNLOCKED;
+}
+
+void
+ieee80211_ifattach(struct ifnet *ifp)
+{
+       struct ieee80211com *ic = (void *)ifp;
+
+       memcpy(((struct arpcom *)ifp)->ac_enaddr, ic->ic_myaddr,
+               ETHER_ADDR_LEN);
+       ether_ifattach(ifp);
+
+       ifp->if_output = ieee80211_output;
+
+#if NBPFILTER > 0
+       bpfattach(&ic->ic_rawbpf, ifp, DLT_IEEE802_11,
+           sizeof(struct ieee80211_frame_addr4));
+#endif
+       ieee80211_crypto_attach(ifp);
+
+       ieee80211_channel_init(ifp);
 
        /* IEEE 802.11 defines a MTU >= 2290 */
        ifp->if_capabilities |= IFCAP_VLAN_MTU;
Index: net80211/ieee80211_var.h
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211_var.h,v
retrieving revision 1.63
diff -u -p -r1.63 ieee80211_var.h
--- net80211/ieee80211_var.h    11 Sep 2015 13:02:28 -0000      1.63
+++ net80211/ieee80211_var.h    26 Sep 2015 11:42:03 -0000
@@ -380,6 +380,7 @@ extern struct ieee80211com_head ieee8021
 
 void   ieee80211_ifattach(struct ifnet *);
 void   ieee80211_ifdetach(struct ifnet *);
+void   ieee80211_channel_init(struct ifnet *);
 void   ieee80211_media_init(struct ifnet *, ifm_change_cb_t, ifm_stat_cb_t);
 int    ieee80211_media_change(struct ifnet *);
 void   ieee80211_media_status(struct ifnet *, struct ifmediareq *);
Index: netinet/if_ether.h
===================================================================
RCS file: /cvs/src/sys/netinet/if_ether.h,v
retrieving revision 1.59
diff -u -p -r1.59 if_ether.h
--- netinet/if_ether.h  13 Sep 2015 10:42:32 -0000      1.59
+++ netinet/if_ether.h  26 Sep 2015 13:09:43 -0000
@@ -186,6 +186,7 @@ struct sockaddr_inarp {
 
 #ifdef _KERNEL
 extern u_int8_t etherbroadcastaddr[ETHER_ADDR_LEN];
+extern u_int8_t etheranyaddr[ETHER_ADDR_LEN];
 extern u_int8_t ether_ipmulticast_min[ETHER_ADDR_LEN];
 extern u_int8_t ether_ipmulticast_max[ETHER_ADDR_LEN];
 extern struct niqueue arpintrq;

Reply via email to