···33441. Introduction552. Implementation details66-3. Kernel driver guidelines77-4. Kernel API88-5. Userspace support66+3. Kernel API77+4. Userspace support9810911101. Introduction···1819situations where transmitters need to be turned off, for example on1920aircraft.20212222+The rfkill subsystem has a concept of "hard" and "soft" block, which2323+differ little in their meaning (block == transmitters off) but rather in2424+whether they can be changed or not:2525+ - hard block: read-only radio block that cannot be overriden by software2626+ - soft block: writable radio block (need not be readable) that is set by2727+ the system software.2128222923302. Implementation details24312525-The rfkill subsystem is composed of various components: the rfkill class, the2626-rfkill-input module (an input layer handler), and some specific input layer2727-events.3232+The rfkill subsystem is composed of three main components:3333+ * the rfkill core,3434+ * the deprecated rfkill-input module (an input layer handler, being3535+ replaced by userspace policy code) and3636+ * the rfkill drivers.28372929-The rfkill class is provided for kernel drivers to register their radio3030-transmitter with the kernel, provide methods for turning it on and off and,3131-optionally, letting the system know about hardware-disabled states that may3232-be implemented on the device. This code is enabled with the CONFIG_RFKILL3333-Kconfig option, which drivers can "select".3838+The rfkill core provides API for kernel drivers to register their radio3939+transmitter with the kernel, methods for turning it on and off and, letting4040+the system know about hardware-disabled states that may be implemented on4141+the device.34423535-The rfkill class code also notifies userspace of state changes, this is3636-achieved via uevents. It also provides some sysfs files for userspace to3737-check the status of radio transmitters. See the "Userspace support" section3838-below.3939-4040-4141-The rfkill-input code implements a basic response to rfkill buttons -- it4242-implements turning on/off all devices of a certain class (or all).4343+The rfkill core code also notifies userspace of state changes, and provides4444+ways for userspace to query the current states. See the "Userspace support"4545+section below.43464447When the device is hard-blocked (either by a call to rfkill_set_hw_state()4545-or from query_hw_block) set_block() will be invoked but drivers can well4646-ignore the method call since they can use the return value of the function4747-rfkill_set_hw_state() to sync the software state instead of keeping track4848-of calls to set_block().4848+or from query_hw_block) set_block() will be invoked for additional software4949+block, but drivers can ignore the method call since they can use the return5050+value of the function rfkill_set_hw_state() to sync the software state5151+instead of keeping track of calls to set_block(). In fact, drivers should5252+use the return value of rfkill_set_hw_state() unless the hardware actually5353+keeps track of soft and hard block separately.495450555151-The entire functionality is spread over more than one subsystem:5252-5353- * The kernel input layer generates KEY_WWAN, KEY_WLAN etc. and5454- SW_RFKILL_ALL -- when the user presses a button. Drivers for radio5555- transmitters generally do not register to the input layer, unless the5656- device really provides an input device (i.e. a button that has no5757- effect other than generating a button press event)5858-5959- * The rfkill-input code hooks up to these events and switches the soft-block6060- of the various radio transmitters, depending on the button type.6161-6262- * The rfkill drivers turn off/on their transmitters as requested.6363-6464- * The rfkill class will generate userspace notifications (uevents) to tell6565- userspace what the current state is.5656+3. Kernel API665767586868-6969-3. Kernel driver guidelines7070-7171-7272-Drivers for radio transmitters normally implement only the rfkill class.7373-These drivers may not unblock the transmitter based on own decisions, they7474-should act on information provided by the rfkill class only.5959+Drivers for radio transmitters normally implement an rfkill driver.75607661Platform drivers might implement input devices if the rfkill button is just7762that, a button. If that button influences the hardware then you need to7878-implement an rfkill class instead. This also applies if the platform provides6363+implement an rfkill driver instead. This also applies if the platform provides7964a way to turn on/off the transmitter(s).80658181-During suspend/hibernation, transmitters should only be left enabled when8282-wake-on wlan or similar functionality requires it and the device wasn't8383-blocked before suspend/hibernate. Note that it may be necessary to update8484-the rfkill subsystem's idea of what the current state is at resume time if8585-the state may have changed over suspend.6666+For some platforms, it is possible that the hardware state changes during6767+suspend/hibernation, in which case it will be necessary to update the rfkill6868+core with the current state is at resume time.86697070+To create an rfkill driver, driver's Kconfig needs to have87717272+ depends on RFKILL || !RFKILL88738989-4. Kernel API9090-9191-To build a driver with rfkill subsystem support, the driver should depend on9292-(or select) the Kconfig symbol RFKILL.9393-9494-The hardware the driver talks to may be write-only (where the current state9595-of the hardware is unknown), or read-write (where the hardware can be queried9696-about its current state).7474+to ensure the driver cannot be built-in when rfkill is modular. The !RFKILL7575+case allows the driver to be built when rfkill is not configured, which which7676+case all rfkill API can still be used but will be provided by static inlines7777+which compile to almost nothing.97789879Calling rfkill_set_hw_state() when a state change happens is required from9980rfkill drivers that control devices that can be hard-blocked unless they also···84105851065. Userspace support861078787-The following sysfs entries exist for every rfkill device:108108+The recommended userspace interface to use is /dev/rfkill, which is a misc109109+character device that allows userspace to obtain and set the state of rfkill110110+devices and sets of devices. It also notifies userspace about device addition111111+and removal. The API is a simple read/write API that is defined in112112+linux/rfkill.h, with one ioctl that allows turning off the deprecated input113113+handler in the kernel for the transition period.114114+115115+Except for the one ioctl, communication with the kernel is done via read()116116+and write() of instances of 'struct rfkill_event'. In this structure, the117117+soft and hard block are properly separated (unlike sysfs, see below) and118118+userspace is able to get a consistent snapshot of all rfkill devices in the119119+system. Also, it is possible to switch all rfkill drivers (or all drivers of120120+a specified type) into a state which also updates the default state for121121+hotplugged devices.122122+123123+After an application opens /dev/rfkill, it can read the current state of124124+all devices, and afterwards can poll the descriptor for hotplug or state125125+change events.126126+127127+Applications must ignore operations (the "op" field) they do not handle,128128+this allows the API to be extended in the future.129129+130130+Additionally, each rfkill device is registered in sysfs and there has the131131+following attributes:8813289133 name: Name assigned by driver to this key (interface or driver name).9090- type: Name of the key type ("wlan", "bluetooth", etc).134134+ type: Driver type string ("wlan", "bluetooth", etc).91135 state: Current state of the transmitter92136 0: RFKILL_STATE_SOFT_BLOCKED93137 transmitter is turned off by software···119117 2: RFKILL_STATE_HARD_BLOCKED120118 transmitter is forced off by something outside of121119 the driver's control.122122- claim: 0: Kernel handles events (currently always reads that value)120120+ This file is deprecated because it can only properly show121121+ three of the four possible states, soft-and-hard-blocked is122122+ missing.123123+ claim: 0: Kernel handles events124124+ This file is deprecated because there no longer is a way to125125+ claim just control over a single rfkill instance.123126124127rfkill devices also issue uevents (with an action of "change"), with the125128following environment variables set:···135128136129The contents of these variables corresponds to the "name", "state" and137130"type" sysfs files explained above.138138-139139-An alternative userspace interface exists as a misc device /dev/rfkill,140140-which allows userspace to obtain and set the state of rfkill devices and141141-sets of devices. It also notifies userspace about device addition and142142-removal. The API is a simple read/write API that is defined in143143-linux/rfkill.h.
+3-2
drivers/net/wireless/ath/ath5k/pcu.c
···733733 /*734734 * Set the beacon register and enable all timers.735735 */736736- /* When in AP mode zero timer0 to start TSF */737737- if (ah->ah_op_mode == NL80211_IFTYPE_AP)736736+ /* When in AP or Mesh Point mode zero timer0 to start TSF */737737+ if (ah->ah_op_mode == NL80211_IFTYPE_AP ||738738+ ah->ah_op_mode == NL80211_IFTYPE_MESH_POINT)738739 ath5k_hw_reg_write(ah, 0, AR5K_TIMER0);739740740741 ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0);
···21522152 /* we should be verifying the device is ready to be opened */21532153 mutex_lock(&priv->mutex);2154215421552155- memset(&priv->staging_rxon, 0, sizeof(struct iwl_rxon_cmd));21562155 /* fetch ucode file from disk, alloc and copy to bus-master buffers ...21572156 * ucode filename and max sizes are card-specific. */21582157
+85-54
drivers/net/wireless/iwlwifi/iwl-core.c
···629629 if (!sta_ht_inf->ht_supported)630630 return 0;631631 }632632-633633- if (iwl_ht_conf->ht_protection & IEEE80211_HT_OP_MODE_PROTECTION_20MHZ)634634- return 1;635635- else636636- return iwl_is_channel_extension(priv, priv->band,637637- le16_to_cpu(priv->staging_rxon.channel),638638- iwl_ht_conf->extension_chan_offset);632632+ return iwl_is_channel_extension(priv, priv->band,633633+ le16_to_cpu(priv->staging_rxon.channel),634634+ iwl_ht_conf->extension_chan_offset);639635}640636EXPORT_SYMBOL(iwl_is_fat_tx_allowed);641637···822826 RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);823827 if (iwl_is_fat_tx_allowed(priv, NULL)) {824828 /* pure 40 fat */825825- if (rxon->flags & RXON_FLG_FAT_PROT_MSK)829829+ if (ht_info->ht_protection == IEEE80211_HT_OP_MODE_PROTECTION_20MHZ) {826830 rxon->flags |= RXON_FLG_CHANNEL_MODE_PURE_40;827827- else {831831+ /* Note: control channel is opposite of extension channel */832832+ switch (ht_info->extension_chan_offset) {833833+ case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:834834+ rxon->flags &= ~RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;835835+ break;836836+ case IEEE80211_HT_PARAM_CHA_SEC_BELOW:837837+ rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;838838+ break;839839+ }840840+ } else {828841 /* Note: control channel is opposite of extension channel */829842 switch (ht_info->extension_chan_offset) {830843 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:···23952390 priv->ibss_beacon = ieee80211_beacon_get(hw, vif);23962391 }2397239223982398- if ((changes & BSS_CHANGED_BSSID) && !iwl_is_rfkill(priv)) {23992399- /* If there is currently a HW scan going on in the background24002400- * then we need to cancel it else the RXON below will fail. */23932393+ if (changes & BSS_CHANGED_BEACON_INT) {23942394+ priv->beacon_int = bss_conf->beacon_int;23952395+ /* TODO: in AP mode, do something to make this take effect */23962396+ }23972397+23982398+ if (changes & BSS_CHANGED_BSSID) {23992399+ IWL_DEBUG_MAC80211(priv, "BSSID %pM\n", bss_conf->bssid);24002400+24012401+ /*24022402+ * If there is currently a HW scan going on in the24032403+ * background then we need to cancel it else the RXON24042404+ * below/in post_associate will fail.24052405+ */24012406 if (iwl_scan_cancel_timeout(priv, 100)) {24022402- IWL_WARN(priv, "Aborted scan still in progress "24032403- "after 100ms\n");24072407+ IWL_WARN(priv, "Aborted scan still in progress after 100ms\n");24042408 IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n");24052409 mutex_unlock(&priv->mutex);24062410 return;24072411 }24082408- memcpy(priv->staging_rxon.bssid_addr,24092409- bss_conf->bssid, ETH_ALEN);2410241224112411- /* TODO: Audit driver for usage of these members and see24122412- * if mac80211 deprecates them (priv->bssid looks like it24132413- * shouldn't be there, but I haven't scanned the IBSS code24142414- * to verify) - jpk */24152415- memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);24132413+ /* mac80211 only sets assoc when in STATION mode */24142414+ if (priv->iw_mode == NL80211_IFTYPE_ADHOC ||24152415+ bss_conf->assoc) {24162416+ memcpy(priv->staging_rxon.bssid_addr,24172417+ bss_conf->bssid, ETH_ALEN);2416241824172417- if (priv->iw_mode == NL80211_IFTYPE_AP)24182418- iwlcore_config_ap(priv);24192419- else {24202420- int rc = iwlcore_commit_rxon(priv);24212421- if ((priv->iw_mode == NL80211_IFTYPE_STATION) && rc)24222422- iwl_rxon_add_station(24232423- priv, priv->active_rxon.bssid_addr, 1);24192419+ /* currently needed in a few places */24202420+ memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);24212421+ } else {24222422+ priv->staging_rxon.filter_flags &=24232423+ ~RXON_FILTER_ASSOC_MSK;24242424 }24252425- } else if (!iwl_is_rfkill(priv)) {24262426- iwl_scan_cancel_timeout(priv, 100);24272427- priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;24282428- iwlcore_commit_rxon(priv);24252425+24292426 }2430242724282428+ /*24292429+ * This needs to be after setting the BSSID in case24302430+ * mac80211 decides to do both changes at once because24312431+ * it will invoke post_associate.24322432+ */24312433 if (priv->iw_mode == NL80211_IFTYPE_ADHOC &&24322434 changes & BSS_CHANGED_BEACON) {24332435 struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);···24422430 if (beacon)24432431 iwl_mac_beacon_update(hw, beacon);24442432 }24452445-24462446- mutex_unlock(&priv->mutex);2447243324482434 if (changes & BSS_CHANGED_ERP_PREAMBLE) {24492435 IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n",···24602450 priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK;24612451 }2462245224532453+ if (changes & BSS_CHANGED_BASIC_RATES) {24542454+ /* XXX use this information24552455+ *24562456+ * To do that, remove code from iwl_set_rate() and put something24572457+ * like this here:24582458+ *24592459+ if (A-band)24602460+ priv->staging_rxon.ofdm_basic_rates =24612461+ bss_conf->basic_rates;24622462+ else24632463+ priv->staging_rxon.ofdm_basic_rates =24642464+ bss_conf->basic_rates >> 4;24652465+ priv->staging_rxon.cck_basic_rates =24662466+ bss_conf->basic_rates & 0xF;24672467+ */24682468+ }24692469+24632470 if (changes & BSS_CHANGED_HT) {24642471 iwl_ht_conf(priv, bss_conf);24652472···2486245924872460 if (changes & BSS_CHANGED_ASSOC) {24882461 IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc);24892489- /* This should never happen as this function should24902490- * never be called from interrupt context. */24912491- if (WARN_ON_ONCE(in_interrupt()))24922492- return;24932462 if (bss_conf->assoc) {24942463 priv->assoc_id = bss_conf->aid;24952464 priv->beacon_int = bss_conf->beacon_int;···24932470 priv->timestamp = bss_conf->timestamp;24942471 priv->assoc_capability = bss_conf->assoc_capability;2495247224962496- /* we have just associated, don't start scan too early24972497- * leave time for EAPOL exchange to complete24732473+ /*24742474+ * We have just associated, don't start scan too early24752475+ * leave time for EAPOL exchange to complete.24762476+ *24772477+ * XXX: do this in mac8021124982478 */24992479 priv->next_scan_jiffies = jiffies +25002480 IWL_DELAY_NEXT_SCAN_AFTER_ASSOC;25012501- mutex_lock(&priv->mutex);25022502- priv->cfg->ops->lib->post_associate(priv);25032503- mutex_unlock(&priv->mutex);25042504- } else {24812481+ if (!iwl_is_rfkill(priv))24822482+ priv->cfg->ops->lib->post_associate(priv);24832483+ } else25052484 priv->assoc_id = 0;25062506- IWL_DEBUG_MAC80211(priv, "DISASSOC %d\n", bss_conf->assoc);25072507- }25082508- } else if (changes && iwl_is_associated(priv) && priv->assoc_id) {25092509- IWL_DEBUG_MAC80211(priv, "Associated Changes %d\n", changes);25102510- ret = iwl_send_rxon_assoc(priv);25112511- if (!ret)25122512- /* Sync active_rxon with latest change. */25132513- memcpy((void *)&priv->active_rxon,25142514- &priv->staging_rxon,25152515- sizeof(struct iwl_rxon_cmd));24852485+25162486 }24872487+24882488+ if (changes && iwl_is_associated(priv) && priv->assoc_id) {24892489+ IWL_DEBUG_MAC80211(priv, "Changes (%#x) while associated\n",24902490+ changes);24912491+ ret = iwl_send_rxon_assoc(priv);24922492+ if (!ret) {24932493+ /* Sync active_rxon with latest change. */24942494+ memcpy((void *)&priv->active_rxon,24952495+ &priv->staging_rxon,24962496+ sizeof(struct iwl_rxon_cmd));24972497+ }24982498+ }24992499+25002500+ mutex_unlock(&priv->mutex);25012501+25172502 IWL_DEBUG_MAC80211(priv, "leave\n");25182503}25192504EXPORT_SYMBOL(iwl_bss_info_changed);
+1-3
drivers/net/wireless/iwlwifi/iwl3945-base.c
···24982498 struct iwl3945_rxon_cmd *active_rxon =24992499 (struct iwl3945_rxon_cmd *)(&priv->active_rxon);2500250025012501- memcpy(&priv->staging_rxon, &priv->active_rxon,25022502- sizeof(priv->staging_rxon));25012501+ priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;25032502 active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;25042503 } else {25052504 /* Initialize our rx_config data */···31463147 /* we should be verifying the device is ready to be opened */31473148 mutex_lock(&priv->mutex);3148314931493149- memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon));31503150 /* fetch ucode file from disk, alloc and copy to bus-master buffers ...31513151 * ucode filename and max sizes are card-specific. */31523152
+6-5
drivers/net/wireless/libertas/if_spi.c
···812812static void if_spi_e2h(struct if_spi_card *card)813813{814814 int err = 0;815815- unsigned long flags;816815 u32 cause;817816 struct lbs_private *priv = card->priv;818817···826827 /* generate a card interrupt */827828 spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG, IF_SPI_CIC_HOST_EVENT);828829829829- spin_lock_irqsave(&priv->driver_lock, flags);830830 lbs_queue_event(priv, cause & 0xff);831831- spin_unlock_irqrestore(&priv->driver_lock, flags);832832-833831out:834832 if (err)835833 lbs_pr_err("%s: error %d\n", __func__, err);···871875 err = if_spi_c2h_data(card);872876 if (err)873877 goto err;874874- if (hiStatus & IF_SPI_HIST_CMD_DOWNLOAD_RDY) {878878+879879+ /* workaround: in PS mode, the card does not set the Command880880+ * Download Ready bit, but it sets TX Download Ready. */881881+ if (hiStatus & IF_SPI_HIST_CMD_DOWNLOAD_RDY ||882882+ (card->priv->psstate != PS_STATE_FULL_POWER &&883883+ (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY))) {875884 /* This means two things. First of all,876885 * if there was a previous command sent, the card has877886 * successfully received it.
+1-1
drivers/platform/x86/dell-laptop.c
···177177static int dell_rfkill_set(void *data, bool blocked)178178{179179 struct calling_interface_buffer buffer;180180- int disable = blocked ? 0 : 1;180180+ int disable = blocked ? 1 : 0;181181 unsigned long radio = (unsigned long)data;182182183183 memset(&buffer, 0, sizeof(struct calling_interface_buffer));
+3-2
drivers/platform/x86/sony-laptop.c
···11331133 continue;1134113411351135 if (hwblock) {11361136- if (rfkill_set_hw_state(sony_rfkill_devices[i], true))11371137- sony_nc_rfkill_set((void *)i, true);11361136+ if (rfkill_set_hw_state(sony_rfkill_devices[i], true)) {11371137+ /* we already know we're blocked */11381138+ }11381139 continue;11391140 }11401141