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