Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pci iwm(4) can read the firmware image from disk whe...



details:   https://anonhg.NetBSD.org/src/rev/ea55aec73521
branches:  trunk
changeset: 809581:ea55aec73521
user:      nonaka <nonaka%NetBSD.org@localhost>
date:      Wed Jul 22 15:18:01 2015 +0000

description:
iwm(4) can read the firmware image from disk when interface up.
This change is useful for full-disk encryption environment.

diffstat:

 sys/dev/pci/if_iwm.c    |  234 ++++++++++++++++++++++++++++++++----------------
 sys/dev/pci/if_iwmvar.h |   17 ++-
 2 files changed, 166 insertions(+), 85 deletions(-)

diffs (truncated from 425 to 300 lines):

diff -r 74969da4f145 -r ea55aec73521 sys/dev/pci/if_iwm.c
--- a/sys/dev/pci/if_iwm.c      Wed Jul 22 14:25:39 2015 +0000
+++ b/sys/dev/pci/if_iwm.c      Wed Jul 22 15:18:01 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_iwm.c,v 1.35 2015/05/22 15:32:21 nonaka Exp $       */
+/*     $NetBSD: if_iwm.c,v 1.36 2015/07/22 15:18:01 nonaka Exp $       */
 /*     OpenBSD: if_iwm.c,v 1.41 2015/05/22 06:50:54 kettenis Exp       */
 
 /*
@@ -105,7 +105,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_iwm.c,v 1.35 2015/05/22 15:32:21 nonaka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_iwm.c,v 1.36 2015/07/22 15:18:01 nonaka Exp $");
 
 #include <sys/param.h>
 #include <sys/conf.h>
@@ -437,6 +437,9 @@
 static void    iwm_wakeup(struct iwm_softc *);
 #endif
 static void    iwm_radiotap_attach(struct iwm_softc *);
+static int     iwm_sysctl_fw_loaded_handler(SYSCTLFN_PROTO);
+
+static int iwm_sysctl_root_num;
 
 static int
 iwm_firmload(struct iwm_softc *sc)
@@ -445,6 +448,9 @@
        firmware_handle_t fwh;
        int error;
 
+       if (ISSET(sc->sc_flags, IWM_FLAG_FW_LOADED))
+               return 0;
+
        /* Open firmware image. */
        if ((error = firmware_open("if_iwm", sc->sc_fwname, &fwh)) != 0) {
                aprint_error_dev(sc->sc_dev,
@@ -452,6 +458,11 @@
                return error;
        }
 
+       if (fw->fw_rawdata != NULL && fw->fw_rawsize > 0) {
+               kmem_free(fw->fw_rawdata, fw->fw_rawsize);
+               fw->fw_rawdata = NULL;
+       }
+
        fw->fw_rawsize = firmware_get_size(fwh);
        /*
         * Well, this is how the Linux driver checks it ....
@@ -466,8 +477,7 @@
        /* some sanity */
        if (fw->fw_rawsize > IWM_FWMAXSIZE) {
                aprint_error_dev(sc->sc_dev,
-                   "firmware size is ridiculous: %zd bytes\n",
-               fw->fw_rawsize);
+                   "firmware size is ridiculous: %zd bytes\n", fw->fw_rawsize);
                error = EINVAL;
                goto out;
        }
@@ -487,6 +497,7 @@
                goto out;
        }
 
+       SET(sc->sc_flags, IWM_FLAG_FW_LOADED);
  out:
        /* caller will release memory, if necessary */
 
@@ -816,6 +827,7 @@
        if (error && fw->fw_rawdata != NULL) {
                kmem_free(fw->fw_rawdata, fw->fw_rawsize);
                fw->fw_rawdata = NULL;
+               CLR(sc->sc_flags, IWM_FLAG_FW_LOADED);
        }
        return error;
 }
@@ -5917,17 +5929,25 @@
 
        case SIOCADDMULTI:
        case SIOCDELMULTI:
+               if (!ISSET(sc->sc_flags, IWM_FLAG_ATTACHED)) {
+                       error = ENXIO;
+                       break;
+               }
                sa = ifreq_getaddr(SIOCADDMULTI, (struct ifreq *)data);
                error = (cmd == SIOCADDMULTI) ?
                    ether_addmulti(sa, &sc->sc_ec) :
                    ether_delmulti(sa, &sc->sc_ec);
-
                if (error == ENETRESET)
                        error = 0;
                break;
 
        default:
+               if (!ISSET(sc->sc_flags, IWM_FLAG_ATTACHED)) {
+                       error = ether_ioctl(ifp, cmd, data);
+                       break;
+               }
                error = ieee80211_ioctl(ic, cmd, data);
+               break;
        }
 
        if (error == ENETRESET) {
@@ -6523,13 +6543,9 @@
 static int
 iwm_preinit(struct iwm_softc *sc)
 {
+       struct ieee80211com *ic = &sc->sc_ic;
        int error;
 
-       if ((error = iwm_prepare_card_hw(sc)) != 0) {
-               aprint_error_dev(sc->sc_dev, "could not initialize hardware\n");
-               return error;
-       }
-
        if (sc->sc_flags & IWM_FLAG_ATTACHED)
                return 0;
 
@@ -6540,20 +6556,8 @@
 
        error = iwm_run_init_mvm_ucode(sc, 1);
        iwm_stop_device(sc);
-       return error;
-}
-
-static void
-iwm_attach_hook(device_t dev)
-{
-       struct iwm_softc *sc = device_private(dev);
-       struct ieee80211com *ic = &sc->sc_ic;
-       struct ifnet *ifp = &sc->sc_ec.ec_if;
-
-       KASSERT(!cold);
-
-       if (iwm_preinit(sc) != 0)
-               return;
+       if (error)
+               return error;
 
        sc->sc_flags |= IWM_FLAG_ATTACHED;
 
@@ -6565,52 +6569,11 @@
            IWM_UCODE_API(sc->sc_fwver),
            ether_sprintf(sc->sc_nvm.hw_addr));
 
-       ic->ic_ifp = ifp;
-       ic->ic_phytype = IEEE80211_T_OFDM;      /* not only, but not used */
-       ic->ic_opmode = IEEE80211_M_STA;        /* default to BSS mode */
-       ic->ic_state = IEEE80211_S_INIT;
-
-       /* Set device capabilities. */
-       ic->ic_caps =
-           IEEE80211_C_WEP |           /* WEP */
-           IEEE80211_C_WPA |           /* 802.11i */
-           IEEE80211_C_SHSLOT |        /* short slot time supported */
-           IEEE80211_C_SHPREAMBLE;     /* short preamble supported */
-
        /* not all hardware can do 5GHz band */
        if (sc->sc_nvm.sku_cap_band_52GHz_enable)
                ic->ic_sup_rates[IEEE80211_MODE_11A] = ieee80211_std_rateset_11a;
-       ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
-       ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g;
-
-       for (int i = 0; i < __arraycount(sc->sc_phyctxt); i++) {
-               sc->sc_phyctxt[i].id = i;
-       }
-
-       sc->sc_amrr.amrr_min_success_threshold =  1;
-       sc->sc_amrr.amrr_max_success_threshold = 15;
-
-       /* IBSS channel undefined for now. */
-       ic->ic_ibss_chan = &ic->ic_channels[1];
-
-#if 0
-       /* Max RSSI */
-       ic->ic_max_rssi = IWM_MAX_DBM - IWM_MIN_DBM;
-#endif
-
-       ifp->if_softc = sc;
-       ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
-       ifp->if_init = iwm_init;
-       ifp->if_stop = iwm_stop;
-       ifp->if_ioctl = iwm_ioctl;
-       ifp->if_start = iwm_start;
-       ifp->if_watchdog = iwm_watchdog;
-       IFQ_SET_READY(&ifp->if_snd);
-       memcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ);
-
-       if_initialize(ifp);
+
        ieee80211_ifattach(ic);
-       if_register(ifp);
 
        ic->ic_node_alloc = iwm_node_alloc;
 
@@ -6621,15 +6584,16 @@
        ieee80211_announce(ic);
 
        iwm_radiotap_attach(sc);
-       callout_init(&sc->sc_calib_to, 0);
-       callout_setfunc(&sc->sc_calib_to, iwm_calib_timeout, sc);
-
-       //task_set(&sc->init_task, iwm_init_task, sc);
-
-       if (pmf_device_register(dev, NULL, NULL))
-               pmf_class_network_register(dev, ifp);
-       else
-               aprint_error_dev(dev, "couldn't establish power handler\n");
+
+       return 0;
+}
+
+static void
+iwm_attach_hook(device_t dev)
+{
+       struct iwm_softc *sc = device_private(dev);
+
+       iwm_preinit(sc);
 }
 
 static void
@@ -6637,6 +6601,8 @@
 {
        struct iwm_softc *sc = device_private(self);
        struct pci_attach_args *pa = aux;
+       struct ieee80211com *ic = &sc->sc_ic;
+       struct ifnet *ifp = &sc->sc_ec.ec_if;
 #ifndef __HAVE_PCI_MSI_MSIX
        pci_intr_handle_t ih;
 #endif
@@ -6644,6 +6610,7 @@
        const char *intrstr;
        int error;
        int txq_i;
+       const struct sysctlnode *node;
 
        sc->sc_dev = self;
        sc->sc_pct = pa->pa_pc;
@@ -6810,6 +6777,92 @@
        /* Clear pending interrupts. */
        IWM_WRITE(sc, IWM_CSR_INT, 0xffffffff);
 
+       if ((error = sysctl_createv(&sc->sc_clog, 0, NULL, &node,
+           0, CTLTYPE_NODE, device_xname(sc->sc_dev),
+           SYSCTL_DESCR("iwm per-controller controls"),
+           NULL, 0, NULL, 0,
+           CTL_HW, iwm_sysctl_root_num, CTL_CREATE,
+           CTL_EOL)) != 0) {
+               aprint_normal_dev(sc->sc_dev,
+                   "couldn't create iwm per-controller sysctl node\n");
+       }
+       if (error == 0) {
+               int iwm_nodenum = node->sysctl_num;
+
+               /* Reload firmware sysctl node */
+               if ((error = sysctl_createv(&sc->sc_clog, 0, NULL, &node,
+                   CTLFLAG_READWRITE, CTLTYPE_INT, "fw_loaded",
+                   SYSCTL_DESCR("Reload firmware"),
+                   iwm_sysctl_fw_loaded_handler, 0, (void *)sc, 0,
+                   CTL_HW, iwm_sysctl_root_num, iwm_nodenum, CTL_CREATE,
+                   CTL_EOL)) != 0) {
+                       aprint_normal_dev(sc->sc_dev,
+                           "couldn't create load_fw sysctl node\n");
+               }
+       }
+
+       /*
+        * Attach interface
+        */
+       ic->ic_ifp = ifp;
+       ic->ic_phytype = IEEE80211_T_OFDM;      /* not only, but not used */
+       ic->ic_opmode = IEEE80211_M_STA;        /* default to BSS mode */
+       ic->ic_state = IEEE80211_S_INIT;
+
+       /* Set device capabilities. */
+       ic->ic_caps =
+           IEEE80211_C_WEP |           /* WEP */
+           IEEE80211_C_WPA |           /* 802.11i */
+           IEEE80211_C_SHSLOT |        /* short slot time supported */
+           IEEE80211_C_SHPREAMBLE;     /* short preamble supported */
+
+       /* all hardware can do 2.4GHz band */
+       ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
+       ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g;
+
+       for (int i = 0; i < __arraycount(sc->sc_phyctxt); i++) {
+               sc->sc_phyctxt[i].id = i;
+       }
+
+       sc->sc_amrr.amrr_min_success_threshold =  1;
+       sc->sc_amrr.amrr_max_success_threshold = 15;
+
+       /* IBSS channel undefined for now. */
+       ic->ic_ibss_chan = &ic->ic_channels[1];
+
+#if 0
+       /* Max RSSI */
+       ic->ic_max_rssi = IWM_MAX_DBM - IWM_MIN_DBM;
+#endif
+



Home | Main Index | Thread Index | Old Index