···11+* NXP Semiconductors PN544 NFC Controller22+33+Required properties:44+- compatible: Should be "nxp,pn544-i2c".55+- clock-frequency: I�C work frequency.66+- reg: address on the bus77+- interrupt-parent: phandle for the interrupt gpio controller88+- interrupts: GPIO interrupt to which the chip is connected99+- enable-gpios: Output GPIO pin used for enabling/disabling the PN5441010+- firmware-gpios: Output GPIO pin used to enter firmware download mode1111+1212+Optional SoC Specific Properties:1313+- pinctrl-names: Contains only one value - "default".1414+- pintctrl-0: Specifies the pin control groups used for this controller.1515+1616+Example (for ARM-based BeagleBone with PN544 on I2C2):1717+1818+&i2c2 {1919+2020+ status = "okay";2121+2222+ pn544: pn544@28 {2323+2424+ compatible = "nxp,pn544-i2c";2525+2626+ reg = <0x28>;2727+ clock-frequency = <400000>;2828+2929+ interrupt-parent = <&gpio1>;3030+ interrupts = <17 GPIO_ACTIVE_HIGH>;3131+3232+ enable-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>;3333+ firmware-gpios = <&gpio3 19 GPIO_ACTIVE_HIGH>;3434+ };3535+};
···11+* STMicroelectronics SAS. ST21NFCA NFC Controller22+33+Required properties:44+- compatible: Should be "st,st21nfca-i2c".55+- clock-frequency: I²C work frequency.66+- reg: address on the bus77+- interrupt-parent: phandle for the interrupt gpio controller88+- interrupts: GPIO interrupt to which the chip is connected99+- enable-gpios: Output GPIO pin used for enabling/disabling the ST21NFCA1010+1111+Optional SoC Specific Properties:1212+- pinctrl-names: Contains only one value - "default".1313+- pintctrl-0: Specifies the pin control groups used for this controller.1414+1515+Example (for ARM-based BeagleBoard xM with ST21NFCA on I2C2):1616+1717+&i2c2 {1818+1919+ status = "okay";2020+2121+ st21nfca: st21nfca@1 {2222+2323+ compatible = "st,st21nfca_i2c";2424+2525+ reg = <0x01>;2626+ clock-frequency = <400000>;2727+2828+ interrupt-parent = <&gpio5>;2929+ interrupts = <2 IRQ_TYPE_LEVEL_LOW>;3030+3131+ enable-gpios = <&gpio5 29 GPIO_ACTIVE_HIGH>;3232+ };3333+};
···1212Optional SoC Specific Properties:1313- pinctrl-names: Contains only one value - "default".1414- pintctrl-0: Specifies the pin control groups used for this controller.1515+- autosuspend-delay: Specify autosuspend delay in milliseconds.15161617Example (for ARM-based BeagleBone with TRF7970A on SPI1):1718···3029 ti,enable-gpios = <&gpio2 2 GPIO_ACTIVE_LOW>,3130 <&gpio2 5 GPIO_ACTIVE_LOW>;3231 vin-supply = <&ldo3_reg>;3232+ autosuspend-delay = <30000>;3333 status = "okay";3434 };3535};
···24522452 if (val == 0xffffffff)24532453 continue;2454245424552455+ /* the device has crashed so don't bother trying anymore */24562456+ if (val & FW_IND_EVENT_PENDING)24572457+ break;24582458+24552459 if (val & FW_IND_INITIALIZED)24562460 break;24572461···24682464 mdelay(10);24692465 } while (time_before(jiffies, timeout));2470246624712471- if (val == 0xffffffff || !(val & FW_IND_INITIALIZED)) {24672467+ if (val == 0xffffffff) {24682468+ ath10k_err("failed to read device register, device is gone\n");24692469+ ret = -EIO;24702470+ goto out;24712471+ }24722472+24732473+ if (val & FW_IND_EVENT_PENDING) {24742474+ ath10k_warn("device has crashed during init\n");24752475+ ret = -ECOMM;24762476+ goto out;24772477+ }24782478+24792479+ if (!(val & FW_IND_INITIALIZED)) {24722480 ath10k_err("failed to receive initialized event from target: %08x\n",24732481 val);24742482 ret = -ETIMEDOUT;
···537537 cur_conf->dtim_period = bss_conf->dtim_period;538538 cur_conf->dtim_count = 1;539539 cur_conf->ibss_creator = bss_conf->ibss_creator;540540- cur_conf->bmiss_timeout =541541- ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval;542540543541 /*544542 * It looks like mac80211 may end up using beacon interval of zero in···546548 */547549 if (cur_conf->beacon_interval == 0)548550 cur_conf->beacon_interval = 100;551551+552552+ cur_conf->bmiss_timeout =553553+ ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval;549554550555 /*551556 * We don't parse dtim period from mac80211 during the driver
+253
drivers/net/wireless/ath/ath9k/common-debug.c
···11+/*22+ * Copyright (c) 2008-2011 Atheros Communications Inc.33+ *44+ * Permission to use, copy, modify, and/or distribute this software for any55+ * purpose with or without fee is hereby granted, provided that the above66+ * copyright notice and this permission notice appear in all copies.77+ *88+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES99+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF1010+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR1111+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES1212+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN1313+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF1414+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.1515+ */1616+1717+#include "common.h"1818+1919+static ssize_t read_file_modal_eeprom(struct file *file, char __user *user_buf,2020+ size_t count, loff_t *ppos)2121+{2222+ struct ath_hw *ah = file->private_data;2323+ u32 len = 0, size = 6000;2424+ char *buf;2525+ size_t retval;2626+2727+ buf = kzalloc(size, GFP_KERNEL);2828+ if (buf == NULL)2929+ return -ENOMEM;3030+3131+ len = ah->eep_ops->dump_eeprom(ah, false, buf, len, size);3232+3333+ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);3434+ kfree(buf);3535+3636+ return retval;3737+}3838+3939+static const struct file_operations fops_modal_eeprom = {4040+ .read = read_file_modal_eeprom,4141+ .open = simple_open,4242+ .owner = THIS_MODULE,4343+ .llseek = default_llseek,4444+};4545+4646+4747+void ath9k_cmn_debug_modal_eeprom(struct dentry *debugfs_phy,4848+ struct ath_hw *ah)4949+{5050+ debugfs_create_file("modal_eeprom", S_IRUSR, debugfs_phy, ah,5151+ &fops_modal_eeprom);5252+}5353+EXPORT_SYMBOL(ath9k_cmn_debug_modal_eeprom);5454+5555+static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf,5656+ size_t count, loff_t *ppos)5757+{5858+ struct ath_hw *ah = file->private_data;5959+ u32 len = 0, size = 1500;6060+ ssize_t retval = 0;6161+ char *buf;6262+6363+ buf = kzalloc(size, GFP_KERNEL);6464+ if (!buf)6565+ return -ENOMEM;6666+6767+ len = ah->eep_ops->dump_eeprom(ah, true, buf, len, size);6868+6969+ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);7070+ kfree(buf);7171+7272+ return retval;7373+}7474+7575+static const struct file_operations fops_base_eeprom = {7676+ .read = read_file_base_eeprom,7777+ .open = simple_open,7878+ .owner = THIS_MODULE,7979+ .llseek = default_llseek,8080+};8181+8282+void ath9k_cmn_debug_base_eeprom(struct dentry *debugfs_phy,8383+ struct ath_hw *ah)8484+{8585+ debugfs_create_file("base_eeprom", S_IRUSR, debugfs_phy, ah,8686+ &fops_base_eeprom);8787+}8888+EXPORT_SYMBOL(ath9k_cmn_debug_base_eeprom);8989+9090+void ath9k_cmn_debug_stat_rx(struct ath_rx_stats *rxstats,9191+ struct ath_rx_status *rs)9292+{9393+#define RX_PHY_ERR_INC(c) rxstats->phy_err_stats[c]++9494+#define RX_CMN_STAT_INC(c) (rxstats->c++)9595+9696+ RX_CMN_STAT_INC(rx_pkts_all);9797+ rxstats->rx_bytes_all += rs->rs_datalen;9898+9999+ if (rs->rs_status & ATH9K_RXERR_CRC)100100+ RX_CMN_STAT_INC(crc_err);101101+ if (rs->rs_status & ATH9K_RXERR_DECRYPT)102102+ RX_CMN_STAT_INC(decrypt_crc_err);103103+ if (rs->rs_status & ATH9K_RXERR_MIC)104104+ RX_CMN_STAT_INC(mic_err);105105+ if (rs->rs_status & ATH9K_RX_DELIM_CRC_PRE)106106+ RX_CMN_STAT_INC(pre_delim_crc_err);107107+ if (rs->rs_status & ATH9K_RX_DELIM_CRC_POST)108108+ RX_CMN_STAT_INC(post_delim_crc_err);109109+ if (rs->rs_status & ATH9K_RX_DECRYPT_BUSY)110110+ RX_CMN_STAT_INC(decrypt_busy_err);111111+112112+ if (rs->rs_status & ATH9K_RXERR_PHY) {113113+ RX_CMN_STAT_INC(phy_err);114114+ if (rs->rs_phyerr < ATH9K_PHYERR_MAX)115115+ RX_PHY_ERR_INC(rs->rs_phyerr);116116+ }117117+118118+#undef RX_CMN_STAT_INC119119+#undef RX_PHY_ERR_INC120120+}121121+EXPORT_SYMBOL(ath9k_cmn_debug_stat_rx);122122+123123+static ssize_t read_file_recv(struct file *file, char __user *user_buf,124124+ size_t count, loff_t *ppos)125125+{126126+#define RXS_ERR(s, e) \127127+ do { \128128+ len += scnprintf(buf + len, size - len, \129129+ "%18s : %10u\n", s, \130130+ rxstats->e); \131131+ } while (0)132132+133133+ struct ath_rx_stats *rxstats = file->private_data;134134+ char *buf;135135+ unsigned int len = 0, size = 1600;136136+ ssize_t retval = 0;137137+138138+ buf = kzalloc(size, GFP_KERNEL);139139+ if (buf == NULL)140140+ return -ENOMEM;141141+142142+ RXS_ERR("PKTS-ALL", rx_pkts_all);143143+ RXS_ERR("BYTES-ALL", rx_bytes_all);144144+ RXS_ERR("BEACONS", rx_beacons);145145+ RXS_ERR("FRAGS", rx_frags);146146+ RXS_ERR("SPECTRAL", rx_spectral);147147+148148+ RXS_ERR("CRC ERR", crc_err);149149+ RXS_ERR("DECRYPT CRC ERR", decrypt_crc_err);150150+ RXS_ERR("PHY ERR", phy_err);151151+ RXS_ERR("MIC ERR", mic_err);152152+ RXS_ERR("PRE-DELIM CRC ERR", pre_delim_crc_err);153153+ RXS_ERR("POST-DELIM CRC ERR", post_delim_crc_err);154154+ RXS_ERR("DECRYPT BUSY ERR", decrypt_busy_err);155155+ RXS_ERR("LENGTH-ERR", rx_len_err);156156+ RXS_ERR("OOM-ERR", rx_oom_err);157157+ RXS_ERR("RATE-ERR", rx_rate_err);158158+ RXS_ERR("TOO-MANY-FRAGS", rx_too_many_frags_err);159159+160160+ if (len > size)161161+ len = size;162162+163163+ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);164164+ kfree(buf);165165+166166+ return retval;167167+168168+#undef RXS_ERR169169+}170170+171171+static const struct file_operations fops_recv = {172172+ .read = read_file_recv,173173+ .open = simple_open,174174+ .owner = THIS_MODULE,175175+ .llseek = default_llseek,176176+};177177+178178+void ath9k_cmn_debug_recv(struct dentry *debugfs_phy,179179+ struct ath_rx_stats *rxstats)180180+{181181+ debugfs_create_file("recv", S_IRUSR, debugfs_phy, rxstats,182182+ &fops_recv);183183+}184184+EXPORT_SYMBOL(ath9k_cmn_debug_recv);185185+186186+static ssize_t read_file_phy_err(struct file *file, char __user *user_buf,187187+ size_t count, loff_t *ppos)188188+{189189+#define PHY_ERR(s, p) \190190+ len += scnprintf(buf + len, size - len, "%22s : %10u\n", s, \191191+ rxstats->phy_err_stats[p]);192192+193193+ struct ath_rx_stats *rxstats = file->private_data;194194+ char *buf;195195+ unsigned int len = 0, size = 1600;196196+ ssize_t retval = 0;197197+198198+ buf = kzalloc(size, GFP_KERNEL);199199+ if (buf == NULL)200200+ return -ENOMEM;201201+202202+ PHY_ERR("UNDERRUN ERR", ATH9K_PHYERR_UNDERRUN);203203+ PHY_ERR("TIMING ERR", ATH9K_PHYERR_TIMING);204204+ PHY_ERR("PARITY ERR", ATH9K_PHYERR_PARITY);205205+ PHY_ERR("RATE ERR", ATH9K_PHYERR_RATE);206206+ PHY_ERR("LENGTH ERR", ATH9K_PHYERR_LENGTH);207207+ PHY_ERR("RADAR ERR", ATH9K_PHYERR_RADAR);208208+ PHY_ERR("SERVICE ERR", ATH9K_PHYERR_SERVICE);209209+ PHY_ERR("TOR ERR", ATH9K_PHYERR_TOR);210210+ PHY_ERR("OFDM-TIMING ERR", ATH9K_PHYERR_OFDM_TIMING);211211+ PHY_ERR("OFDM-SIGNAL-PARITY ERR", ATH9K_PHYERR_OFDM_SIGNAL_PARITY);212212+ PHY_ERR("OFDM-RATE ERR", ATH9K_PHYERR_OFDM_RATE_ILLEGAL);213213+ PHY_ERR("OFDM-LENGTH ERR", ATH9K_PHYERR_OFDM_LENGTH_ILLEGAL);214214+ PHY_ERR("OFDM-POWER-DROP ERR", ATH9K_PHYERR_OFDM_POWER_DROP);215215+ PHY_ERR("OFDM-SERVICE ERR", ATH9K_PHYERR_OFDM_SERVICE);216216+ PHY_ERR("OFDM-RESTART ERR", ATH9K_PHYERR_OFDM_RESTART);217217+ PHY_ERR("FALSE-RADAR-EXT ERR", ATH9K_PHYERR_FALSE_RADAR_EXT);218218+ PHY_ERR("CCK-TIMING ERR", ATH9K_PHYERR_CCK_TIMING);219219+ PHY_ERR("CCK-HEADER-CRC ERR", ATH9K_PHYERR_CCK_HEADER_CRC);220220+ PHY_ERR("CCK-RATE ERR", ATH9K_PHYERR_CCK_RATE_ILLEGAL);221221+ PHY_ERR("CCK-SERVICE ERR", ATH9K_PHYERR_CCK_SERVICE);222222+ PHY_ERR("CCK-RESTART ERR", ATH9K_PHYERR_CCK_RESTART);223223+ PHY_ERR("CCK-LENGTH ERR", ATH9K_PHYERR_CCK_LENGTH_ILLEGAL);224224+ PHY_ERR("CCK-POWER-DROP ERR", ATH9K_PHYERR_CCK_POWER_DROP);225225+ PHY_ERR("HT-CRC ERR", ATH9K_PHYERR_HT_CRC_ERROR);226226+ PHY_ERR("HT-LENGTH ERR", ATH9K_PHYERR_HT_LENGTH_ILLEGAL);227227+ PHY_ERR("HT-RATE ERR", ATH9K_PHYERR_HT_RATE_ILLEGAL);228228+229229+ if (len > size)230230+ len = size;231231+232232+ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);233233+ kfree(buf);234234+235235+ return retval;236236+237237+#undef PHY_ERR238238+}239239+240240+static const struct file_operations fops_phy_err = {241241+ .read = read_file_phy_err,242242+ .open = simple_open,243243+ .owner = THIS_MODULE,244244+ .llseek = default_llseek,245245+};246246+247247+void ath9k_cmn_debug_phy_err(struct dentry *debugfs_phy,248248+ struct ath_rx_stats *rxstats)249249+{250250+ debugfs_create_file("phy_err", S_IRUSR, debugfs_phy, rxstats,251251+ &fops_phy_err);252252+}253253+EXPORT_SYMBOL(ath9k_cmn_debug_phy_err);
+72
drivers/net/wireless/ath/ath9k/common-debug.h
···11+/*22+ * Copyright (c) 2008-2011 Atheros Communications Inc.33+ *44+ * Permission to use, copy, modify, and/or distribute this software for any55+ * purpose with or without fee is hereby granted, provided that the above66+ * copyright notice and this permission notice appear in all copies.77+ *88+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES99+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF1010+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR1111+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES1212+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN1313+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF1414+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.1515+ */1616+1717+1818+1919+/**2020+ * struct ath_rx_stats - RX Statistics2121+ * @rx_pkts_all: No. of total frames received, including ones that2222+ may have had errors.2323+ * @rx_bytes_all: No. of total bytes received, including ones that2424+ may have had errors.2525+ * @crc_err: No. of frames with incorrect CRC value2626+ * @decrypt_crc_err: No. of frames whose CRC check failed after2727+ decryption process completed2828+ * @phy_err: No. of frames whose reception failed because the PHY2929+ encountered an error3030+ * @mic_err: No. of frames with incorrect TKIP MIC verification failure3131+ * @pre_delim_crc_err: Pre-Frame delimiter CRC error detections3232+ * @post_delim_crc_err: Post-Frame delimiter CRC error detections3333+ * @decrypt_busy_err: Decryption interruptions counter3434+ * @phy_err_stats: Individual PHY error statistics3535+ * @rx_len_err: No. of frames discarded due to bad length.3636+ * @rx_oom_err: No. of frames dropped due to OOM issues.3737+ * @rx_rate_err: No. of frames dropped due to rate errors.3838+ * @rx_too_many_frags_err: Frames dropped due to too-many-frags received.3939+ * @rx_beacons: No. of beacons received.4040+ * @rx_frags: No. of rx-fragements received.4141+ * @rx_spectral: No of spectral packets received.4242+ */4343+struct ath_rx_stats {4444+ u32 rx_pkts_all;4545+ u32 rx_bytes_all;4646+ u32 crc_err;4747+ u32 decrypt_crc_err;4848+ u32 phy_err;4949+ u32 mic_err;5050+ u32 pre_delim_crc_err;5151+ u32 post_delim_crc_err;5252+ u32 decrypt_busy_err;5353+ u32 phy_err_stats[ATH9K_PHYERR_MAX];5454+ u32 rx_len_err;5555+ u32 rx_oom_err;5656+ u32 rx_rate_err;5757+ u32 rx_too_many_frags_err;5858+ u32 rx_beacons;5959+ u32 rx_frags;6060+ u32 rx_spectral;6161+};6262+6363+void ath9k_cmn_debug_modal_eeprom(struct dentry *debugfs_phy,6464+ struct ath_hw *ah);6565+void ath9k_cmn_debug_base_eeprom(struct dentry *debugfs_phy,6666+ struct ath_hw *ah);6767+void ath9k_cmn_debug_stat_rx(struct ath_rx_stats *rxstats,6868+ struct ath_rx_status *rs);6969+void ath9k_cmn_debug_recv(struct dentry *debugfs_phy,7070+ struct ath_rx_stats *rxstats);7171+void ath9k_cmn_debug_phy_err(struct dentry *debugfs_phy,7272+ struct ath_rx_stats *rxstats);
+1
drivers/net/wireless/ath/ath9k/common.h
···23232424#include "common-init.h"2525#include "common-beacon.h"2626+#include "common-debug.h"26272728/* Common header for Atheros 802.11n base driver cores */2829
···996996 goto rx_next;997997 }998998999999- ath9k_htc_err_stat_rx(priv, rxstatus);10001000-1001999 /* Get the RX status information */1002100010031001 memset(rx_status, 0, sizeof(struct ieee80211_rx_status));···10031005 /* Copy everything from ath_htc_rx_status (HTC_RX_FRAME_HEADER).10041006 * After this, we can drop this part of skb. */10051007 rx_status_htc_to_ath(&rx_stats, rxstatus);10081008+ ath9k_htc_err_stat_rx(priv, &rx_stats);10061009 rx_status->mactime = be64_to_cpu(rxstatus->rs_tstamp);10071010 skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE);10081011
···408408 mac_ctl |= B43_TXH_MAC_HWSEQ;409409 if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)410410 mac_ctl |= B43_TXH_MAC_STMSDU;411411- if (phy->type == B43_PHYTYPE_A)411411+ if (!phy->gmode)412412 mac_ctl |= B43_TXH_MAC_5GHZ;413413414414 /* Overwrite rates[0].count to make the retry calculation
···5353#define BRCMF_OBSS_COEX_OFF 05454#define BRCMF_OBSS_COEX_ON 155555656+/* join preference types for join_pref iovar */5757+enum brcmf_join_pref_types {5858+ BRCMF_JOIN_PREF_RSSI = 1,5959+ BRCMF_JOIN_PREF_WPA,6060+ BRCMF_JOIN_PREF_BAND,6161+ BRCMF_JOIN_PREF_RSSI_DELTA,6262+};6363+5664enum brcmf_fil_p2p_if_types {5765 BRCMF_FIL_P2P_IF_CLIENT,5866 BRCMF_FIL_P2P_IF_GO,···288280 __le32 chanspec_num;289281 /* list of chanspecs */290282 __le16 chanspec_list[1];283283+};284284+285285+/**286286+ * struct join_pref params - parameters for preferred join selection.287287+ *288288+ * @type: preference type (see enum brcmf_join_pref_types).289289+ * @len: length of bytes following (currently always 2).290290+ * @rssi_gain: signal gain for selection (only when @type is RSSI_DELTA).291291+ * @band: band to which selection preference applies.292292+ * This is used if @type is BAND or RSSI_DELTA.293293+ */294294+struct brcmf_join_pref_params {295295+ u8 type;296296+ u8 len;297297+ u8 rssi_gain;298298+ u8 band;291299};292300293301/* used for join with or without a specific bssid and channel list */
···22 tristate "Intel Wireless WiFi Next Gen AGN - Wireless-N/Advanced-N/Ultimate-N (iwlwifi) "33 depends on PCI && MAC80211 && HAS_IOMEM44 select FW_LOADER55- select NEW_LEDS66- select LEDS_CLASS77- select LEDS_TRIGGERS88- select MAC80211_LEDS95 ---help---106 Select to build the driver supporting the:117···3842 inserted in and removed from the running kernel whenever you want),3943 say M here and read <file:Documentation/kbuild/modules.txt>. The4044 module will be called iwlwifi.4545+4646+config IWLWIFI_LEDS4747+ bool4848+ depends on IWLWIFI4949+ depends on LEDS_CLASS=y || LEDS_CLASS=IWLWIFI5050+ select LEDS_TRIGGERS5151+ select MAC80211_LEDS5252+ default y41534254config IWLDVM4355 tristate "Intel Wireless WiFi DVM Firmware support"···128124 Enable use of experimental ucode for testing and debugging.129125130126config IWLWIFI_DEVICE_TRACING131131-132127 bool "iwlwifi device access tracing"133128 depends on IWLWIFI134129 depends on EVENT_TRACING
···1481148114821482 /* make request to uCode to retrieve statistics information */14831483 mutex_lock(&priv->mutex);14841484- ret = iwl_send_statistics_request(priv, CMD_SYNC, false);14841484+ ret = iwl_send_statistics_request(priv, 0, false);14851485 mutex_unlock(&priv->mutex);1486148614871487 if (ret)···1868186818691869 /* make request to uCode to retrieve statistics information */18701870 mutex_lock(&priv->mutex);18711871- iwl_send_statistics_request(priv, CMD_SYNC, true);18711871+ iwl_send_statistics_request(priv, 0, true);18721872 mutex_unlock(&priv->mutex);1873187318741874 return count;···21882188 struct iwl_host_cmd cmd = {21892189 .id = REPLY_ECHO,21902190 .len = { 0 },21912191- .flags = CMD_SYNC,21922191 };2193219221942193 ret = iwl_dvm_send_cmd(priv, &cmd);···23192320 mutex_lock(&priv->mutex);2320232123212322 /* take the return value to make compiler happy - it will fail anyway */23222322- ret = iwl_dvm_send_cmd_pdu(priv, REPLY_ERROR, CMD_SYNC, 0, NULL);23232323+ ret = iwl_dvm_send_cmd_pdu(priv, REPLY_ERROR, 0, 0, NULL);2323232423242325 mutex_unlock(&priv->mutex);23252326
···12431243 .bt_coex_active = true,12441244 .power_level = IWL_POWER_INDEX_1,12451245 .wd_disable = true,12461246+ .uapsd_disable = false,12461247 /* the rest are 0 by default */12471248};12481249IWL_EXPORT_SYMBOL(iwlwifi_mod_params);···1356135513571356module_param_named(nvm_file, iwlwifi_mod_params.nvm_file, charp, S_IRUGO);13581357MODULE_PARM_DESC(nvm_file, "NVM file name");13581358+13591359+module_param_named(uapsd_disable, iwlwifi_mod_params.uapsd_disable,13601360+ bool, S_IRUGO);13611361+MODULE_PARM_DESC(uapsd_disable, "disable U-APSD functionality (default: N)");1359136213601363/*13611364 * set bt_coex_active to true, uCode will do kill/defer
+9-1
drivers/net/wireless/iwlwifi/iwl-fw.h
···7474 * @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w).7575 * @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P.7676 * @IWL_UCODE_TLV_FLAGS_DW_BC_TABLE: The SCD byte count table is in DWORDS7777- * @IWL_UCODE_TLV_FLAGS_UAPSD: This uCode image supports uAPSD7777+ * @IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT: This uCode image supports uAPSD7878 * @IWL_UCODE_TLV_FLAGS_SHORT_BL: 16 entries of black list instead of 64 in scan7979 * offload profile config command.8080 * @IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS: D3 image supports up to six···107107 IWL_UCODE_TLV_FLAGS_P2P_PM = BIT(21),108108 IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM = BIT(22),109109 IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_SCM = BIT(23),110110+ IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT = BIT(24),110111 IWL_UCODE_TLV_FLAGS_EBS_SUPPORT = BIT(25),111112 IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD = BIT(26),112113 IWL_UCODE_TLV_FLAGS_BCAST_FILTERING = BIT(29),···117116/**118117 * enum iwl_ucode_tlv_api - ucode api119118 * @IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID: wowlan config includes tid field.119119+ * @IWL_UCODE_TLV_API_CSA_FLOW: ucode can do unbind-bind flow for CSA.120120 */121121enum iwl_ucode_tlv_api {122122 IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID = BIT(0),123123+ IWL_UCODE_TLV_API_CSA_FLOW = BIT(4),123124};124125125126/**···195192 struct fw_desc sec[IWL_UCODE_SECTION_MAX];196193 bool is_secure;197194 bool is_dual_cpus;195195+};196196+197197+struct iwl_sf_region {198198+ u32 addr;199199+ u32 size;198200};199201200202/* uCode version contains 4 values: Major/Minor/API/Serial */
+18
drivers/net/wireless/iwlwifi/iwl-io.c
···3333#include "iwl-io.h"3434#include "iwl-csr.h"3535#include "iwl-debug.h"3636+#include "iwl-prph.h"3637#include "iwl-fh.h"37383839#define IWL_POLL_INTERVAL 10 /* microseconds */···183182 }184183}185184IWL_EXPORT_SYMBOL(iwl_clear_bits_prph);185185+186186+void iwl_force_nmi(struct iwl_trans *trans)187187+{188188+ /*189189+ * In HW previous to the 8000 HW family, and in the 8000 HW family190190+ * itself when the revision step==0, the DEVICE_SET_NMI_REG is used191191+ * to force an NMI. Otherwise, a different register -192192+ * DEVICE_SET_NMI_8000B_REG - is used.193193+ */194194+ if ((trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) ||195195+ ((trans->hw_rev & 0xc) == 0x0))196196+ iwl_write_prph(trans, DEVICE_SET_NMI_REG, DEVICE_SET_NMI_VAL);197197+ else198198+ iwl_write_prph(trans, DEVICE_SET_NMI_8000B_REG,199199+ DEVICE_SET_NMI_8000B_VAL);200200+}201201+IWL_EXPORT_SYMBOL(iwl_force_nmi);186202187203static const char *get_fh_string(int cmd)188204{
···189189/**190190 * enum CMD_MODE - how to send the host commands ?191191 *192192- * @CMD_SYNC: The caller will be stalled until the fw responds to the command193192 * @CMD_ASYNC: Return right away and don't wait for the response194194- * @CMD_WANT_SKB: valid only with CMD_SYNC. The caller needs the buffer of the195195- * response. The caller needs to call iwl_free_resp when done.193193+ * @CMD_WANT_SKB: Not valid with CMD_ASYNC. The caller needs the buffer of194194+ * the response. The caller needs to call iwl_free_resp when done.196195 * @CMD_HIGH_PRIO: The command is high priority - it goes to the front of the197196 * command queue, but after other high priority commands. valid only198197 * with CMD_ASYNC.···201202 * (i.e. mark it as non-idle).202203 */203204enum CMD_MODE {204204- CMD_SYNC = 0,205205 CMD_ASYNC = BIT(0),206206 CMD_WANT_SKB = BIT(1),207207 CMD_SEND_IN_RFKILL = BIT(2),···425427 * @send_cmd:send a host command. Must return -ERFKILL if RFkill is asserted.426428 * If RFkill is asserted in the middle of a SYNC host command, it must427429 * return -ERFKILL straight away.428428- * May sleep only if CMD_SYNC is set430430+ * May sleep only if CMD_ASYNC is not set429431 * @tx: send an skb430432 * Must be atomic431433 * @reclaim: free packet until ssn. Returns a list of freed packets.···461463 * @unref: release a reference previously taken with @ref. Note that462464 * initially the reference count is 1, making an initial @unref463465 * necessary to allow low power states.466466+ * @dump_data: fill a data dump with debug data, maybe containing last467467+ * TX'ed commands and similar. When called with a NULL buffer and468468+ * zero buffer length, provide only the (estimated) required buffer469469+ * length. Return the used buffer length.470470+ * Note that the transport must fill in the proper file headers.464471 */465472struct iwl_trans_ops {466473···473470 void (*op_mode_leave)(struct iwl_trans *iwl_trans);474471 int (*start_fw)(struct iwl_trans *trans, const struct fw_img *fw,475472 bool run_in_rfkill);473473+ int (*update_sf)(struct iwl_trans *trans,474474+ struct iwl_sf_region *st_fwrd_space);476475 void (*fw_alive)(struct iwl_trans *trans, u32 scd_addr);477476 void (*stop_device)(struct iwl_trans *trans);478477···516511 u32 value);517512 void (*ref)(struct iwl_trans *trans);518513 void (*unref)(struct iwl_trans *trans);514514+515515+#ifdef CONFIG_IWLWIFI_DEBUGFS516516+ u32 (*dump_data)(struct iwl_trans *trans, void *buf, u32 buflen);517517+#endif519518};520519521520/**···638629 return trans->ops->start_fw(trans, fw, run_in_rfkill);639630}640631632632+static inline int iwl_trans_update_sf(struct iwl_trans *trans,633633+ struct iwl_sf_region *st_fwrd_space)634634+{635635+ might_sleep();636636+637637+ if (trans->ops->update_sf)638638+ return trans->ops->update_sf(trans, st_fwrd_space);639639+640640+ return 0;641641+}642642+641643static inline void iwl_trans_stop_device(struct iwl_trans *trans)642644{643645 might_sleep();···684664 trans->ops->unref(trans);685665}686666667667+#ifdef CONFIG_IWLWIFI_DEBUGFS668668+static inline u32 iwl_trans_dump_data(struct iwl_trans *trans,669669+ void *buf, u32 buflen)670670+{671671+ if (!trans->ops->dump_data)672672+ return 0;673673+ return trans->ops->dump_data(trans, buf, buflen);674674+}675675+#endif676676+687677static inline int iwl_trans_send_cmd(struct iwl_trans *trans,688678 struct iwl_host_cmd *cmd)689679{···707677 return -EIO;708678709679 if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) {710710- IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);680680+ IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state);711681 return -EIO;712682 }713683···749719 return -EIO;750720751721 if (unlikely(trans->state != IWL_TRANS_FW_ALIVE))752752- IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);722722+ IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state);753723754724 return trans->ops->tx(trans, skb, dev_cmd, queue);755725}···758728 int ssn, struct sk_buff_head *skbs)759729{760730 if (unlikely(trans->state != IWL_TRANS_FW_ALIVE))761761- IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);731731+ IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state);762732763733 trans->ops->reclaim(trans, queue, ssn, skbs);764734}···775745 might_sleep();776746777747 if (unlikely((trans->state != IWL_TRANS_FW_ALIVE)))778778- IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);748748+ IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state);779749780750 trans->ops->txq_enable(trans, queue, fifo, sta_id, tid,781751 frame_limit, ssn);···792762 u32 txq_bm)793763{794764 if (unlikely(trans->state != IWL_TRANS_FW_ALIVE))795795- IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);765765+ IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state);796766797767 return trans->ops->wait_tx_queue_empty(trans, txq_bm);798768}
···9999 };100100101101 IWL_DEBUG_FW(mvm, "select valid tx ant: %u\n", valid_tx_ant);102102- return iwl_mvm_send_cmd_pdu(mvm, TX_ANT_CONFIGURATION_CMD, CMD_SYNC,102102+ return iwl_mvm_send_cmd_pdu(mvm, TX_ANT_CONFIGURATION_CMD, 0,103103 sizeof(tx_ant_cmd), &tx_ant_cmd);104104}105105···137137 alive_data->scd_base_addr = le32_to_cpu(palive2->scd_base_ptr);138138 mvm->umac_error_event_table =139139 le32_to_cpu(palive2->error_info_addr);140140+ mvm->sf_space.addr = le32_to_cpu(palive2->st_fwrd_addr);141141+ mvm->sf_space.size = le32_to_cpu(palive2->st_fwrd_size);140142141143 alive_data->valid = le16_to_cpu(palive2->status) ==142144 IWL_ALIVE_STATUS_OK;···182180 int ret, i;183181 enum iwl_ucode_type old_type = mvm->cur_ucode;184182 static const u8 alive_cmd[] = { MVM_ALIVE };183183+ struct iwl_sf_region st_fwrd_space;185184186185 fw = iwl_get_ucode_image(mvm, ucode_type);187186 if (WARN_ON(!fw))···217214 mvm->cur_ucode = old_type;218215 return -EIO;219216 }217217+218218+ /*219219+ * update the sdio allocation according to the pointer we get in the220220+ * alive notification.221221+ */222222+ st_fwrd_space.addr = mvm->sf_space.addr;223223+ st_fwrd_space.size = mvm->sf_space.size;224224+ ret = iwl_trans_update_sf(mvm->trans, &st_fwrd_space);220225221226 iwl_trans_fw_alive(mvm->trans, alive_data.scd_base_addr);222227···267256 IWL_DEBUG_INFO(mvm, "Sending Phy CFG command: 0x%x\n",268257 phy_cfg_cmd.phy_cfg);269258270270- return iwl_mvm_send_cmd_pdu(mvm, PHY_CONFIGURATION_CMD, CMD_SYNC,259259+ return iwl_mvm_send_cmd_pdu(mvm, PHY_CONFIGURATION_CMD, 0,271260 sizeof(phy_cfg_cmd), &phy_cfg_cmd);272261}273262···306295 /* Read the NVM only at driver load time, no need to do this twice */307296 if (read_nvm) {308297 /* Read nvm */309309- ret = iwl_nvm_init(mvm);298298+ ret = iwl_nvm_init(mvm, true);310299 if (ret) {311300 IWL_ERR(mvm, "Failed to read NVM: %d\n", ret);312301 goto error;···314303 }315304316305 /* In case we read the NVM from external file, load it to the NIC */317317- if (iwlwifi_mod_params.nvm_file)306306+ if (mvm->nvm_file_name)318307 iwl_mvm_load_nvm_to_nic(mvm);319308320309 ret = iwl_nvm_check_version(mvm->nvm_data, mvm->trans);
+50-64
drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
···685685static int iwl_mvm_mac_ctxt_send_cmd(struct iwl_mvm *mvm,686686 struct iwl_mac_ctx_cmd *cmd)687687{688688- int ret = iwl_mvm_send_cmd_pdu(mvm, MAC_CONTEXT_CMD, CMD_SYNC,688688+ int ret = iwl_mvm_send_cmd_pdu(mvm, MAC_CONTEXT_CMD, 0,689689 sizeof(*cmd), cmd);690690 if (ret)691691 IWL_ERR(mvm, "Failed to send MAC context (action:%d): %d\n",···693693 return ret;694694}695695696696-/*697697- * Fill the specific data for mac context of type station or p2p client698698- */699699-static void iwl_mvm_mac_ctxt_cmd_fill_sta(struct iwl_mvm *mvm,700700- struct ieee80211_vif *vif,701701- struct iwl_mac_data_sta *ctxt_sta,702702- bool force_assoc_off)696696+static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,697697+ struct ieee80211_vif *vif,698698+ u32 action, bool force_assoc_off)703699{700700+ struct iwl_mac_ctx_cmd cmd = {};701701+ struct iwl_mac_data_sta *ctxt_sta;702702+703703+ WARN_ON(vif->type != NL80211_IFTYPE_STATION);704704+705705+ /* Fill the common data for all mac context types */706706+ iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);707707+708708+ if (vif->p2p) {709709+ struct ieee80211_p2p_noa_attr *noa =710710+ &vif->bss_conf.p2p_noa_attr;711711+712712+ cmd.p2p_sta.ctwin = cpu_to_le32(noa->oppps_ctwindow &713713+ IEEE80211_P2P_OPPPS_CTWINDOW_MASK);714714+ ctxt_sta = &cmd.p2p_sta.sta;715715+ } else {716716+ ctxt_sta = &cmd.sta;717717+ }718718+704719 /* We need the dtim_period to set the MAC as associated */705720 if (vif->bss_conf.assoc && vif->bss_conf.dtim_period &&706721 !force_assoc_off) {707722 u32 dtim_offs;723723+724724+ /* Allow beacons to pass through as long as we are not725725+ * associated, or we do not have dtim period information.726726+ */727727+ cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_BEACON);708728709729 /*710730 * The DTIM count counts down, so when it is N that means N···772752773753 ctxt_sta->listen_interval = cpu_to_le32(mvm->hw->conf.listen_interval);774754 ctxt_sta->assoc_id = cpu_to_le32(vif->bss_conf.aid);775775-}776776-777777-static int iwl_mvm_mac_ctxt_cmd_station(struct iwl_mvm *mvm,778778- struct ieee80211_vif *vif,779779- u32 action)780780-{781781- struct iwl_mac_ctx_cmd cmd = {};782782-783783- WARN_ON(vif->type != NL80211_IFTYPE_STATION || vif->p2p);784784-785785- /* Fill the common data for all mac context types */786786- iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);787787-788788- /* Allow beacons to pass through as long as we are not associated,or we789789- * do not have dtim period information */790790- if (!vif->bss_conf.assoc || !vif->bss_conf.dtim_period)791791- cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_BEACON);792792- else793793- cmd.filter_flags &= ~cpu_to_le32(MAC_FILTER_IN_BEACON);794794-795795- /* Fill the data specific for station mode */796796- iwl_mvm_mac_ctxt_cmd_fill_sta(mvm, vif, &cmd.sta,797797- action == FW_CTXT_ACTION_ADD);798798-799799- return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);800800-}801801-802802-static int iwl_mvm_mac_ctxt_cmd_p2p_client(struct iwl_mvm *mvm,803803- struct ieee80211_vif *vif,804804- u32 action)805805-{806806- struct iwl_mac_ctx_cmd cmd = {};807807- struct ieee80211_p2p_noa_attr *noa = &vif->bss_conf.p2p_noa_attr;808808-809809- WARN_ON(vif->type != NL80211_IFTYPE_STATION || !vif->p2p);810810-811811- /* Fill the common data for all mac context types */812812- iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);813813-814814- /* Fill the data specific for station mode */815815- iwl_mvm_mac_ctxt_cmd_fill_sta(mvm, vif, &cmd.p2p_sta.sta,816816- action == FW_CTXT_ACTION_ADD);817817-818818- cmd.p2p_sta.ctwin = cpu_to_le32(noa->oppps_ctwindow &819819- IEEE80211_P2P_OPPPS_CTWINDOW_MASK);820755821756 return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);822757}···11091134}1110113511111136static int iwl_mvm_mac_ctx_send(struct iwl_mvm *mvm, struct ieee80211_vif *vif,11121112- u32 action)11371137+ u32 action, bool force_assoc_off)11131138{11141139 switch (vif->type) {11151140 case NL80211_IFTYPE_STATION:11161116- if (!vif->p2p)11171117- return iwl_mvm_mac_ctxt_cmd_station(mvm, vif,11181118- action);11191119- else11201120- return iwl_mvm_mac_ctxt_cmd_p2p_client(mvm, vif,11211121- action);11411141+ return iwl_mvm_mac_ctxt_cmd_sta(mvm, vif, action,11421142+ force_assoc_off);11221143 break;11231144 case NL80211_IFTYPE_AP:11241145 if (!vif->p2p)···11441173 vif->addr, ieee80211_vif_type_p2p(vif)))11451174 return -EIO;1146117511471147- ret = iwl_mvm_mac_ctx_send(mvm, vif, FW_CTXT_ACTION_ADD);11761176+ ret = iwl_mvm_mac_ctx_send(mvm, vif, FW_CTXT_ACTION_ADD,11771177+ true);11481178 if (ret)11491179 return ret;11501180···11561184 return 0;11571185}1158118611591159-int iwl_mvm_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif)11871187+int iwl_mvm_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,11881188+ bool force_assoc_off)11601189{11611190 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);11621191···11651192 vif->addr, ieee80211_vif_type_p2p(vif)))11661193 return -EIO;1167119411681168- return iwl_mvm_mac_ctx_send(mvm, vif, FW_CTXT_ACTION_MODIFY);11951195+ return iwl_mvm_mac_ctx_send(mvm, vif, FW_CTXT_ACTION_MODIFY,11961196+ force_assoc_off);11691197}1170119811711199int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif)···11851211 mvmvif->color));11861212 cmd.action = cpu_to_le32(FW_CTXT_ACTION_REMOVE);1187121311881188- ret = iwl_mvm_send_cmd_pdu(mvm, MAC_CONTEXT_CMD, CMD_SYNC,12141214+ ret = iwl_mvm_send_cmd_pdu(mvm, MAC_CONTEXT_CMD, 0,11891215 sizeof(cmd), &cmd);11901216 if (ret) {11911217 IWL_ERR(mvm, "Failed to remove MAC context: %d\n", ret);···12111237 u32 rate __maybe_unused =12121238 le32_to_cpu(beacon->beacon_notify_hdr.initial_rate);1213123912401240+ lockdep_assert_held(&mvm->mutex);12411241+12141242 IWL_DEBUG_RX(mvm, "beacon status %#x retries:%d tsf:0x%16llX rate:%d\n",12151243 status & TX_STATUS_MSK,12161244 beacon->beacon_notify_hdr.failure_frame,12171245 le64_to_cpu(beacon->tsf),12181246 rate);12471247+12481248+ if (unlikely(mvm->csa_vif && mvm->csa_vif->csa_active)) {12491249+ if (!ieee80211_csa_is_complete(mvm->csa_vif)) {12501250+ iwl_mvm_mac_ctxt_beacon_changed(mvm, mvm->csa_vif);12511251+ } else {12521252+ ieee80211_csa_finish(mvm->csa_vif);12531253+ mvm->csa_vif = NULL;12541254+ }12551255+ }12561256+12191257 return 0;12201258}12211259
+130-43
drivers/net/wireless/iwlwifi/mvm/mac80211.c
···276276 IEEE80211_HW_AMPDU_AGGREGATION |277277 IEEE80211_HW_TIMING_BEACON_ONLY |278278 IEEE80211_HW_CONNECTION_MONITOR |279279- IEEE80211_HW_SUPPORTS_UAPSD |280279 IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |281280 IEEE80211_HW_SUPPORTS_STATIC_SMPS;282281···285286 IEEE80211_RADIOTAP_MCS_HAVE_STBC;286287 hw->radiotap_vht_details |= IEEE80211_RADIOTAP_VHT_KNOWN_STBC;287288 hw->rate_control_algorithm = "iwl-mvm-rs";288288- hw->uapsd_queues = IWL_UAPSD_AC_INFO;289289- hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP;290289291290 /*292291 * Enable 11w if advertised by firmware and software crypto···295298 !iwlwifi_mod_params.sw_crypto)296299 hw->flags |= IEEE80211_HW_MFP_CAPABLE;297300298298- /* Disable uAPSD due to firmware issues */299299- if (true)300300- hw->flags &= ~IEEE80211_HW_SUPPORTS_UAPSD;301301+ if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT &&302302+ IWL_UCODE_API(mvm->fw->ucode_ver) >= 9 &&303303+ !iwlwifi_mod_params.uapsd_disable) {304304+ hw->flags |= IEEE80211_HW_SUPPORTS_UAPSD;305305+ hw->uapsd_queues = IWL_UAPSD_AC_INFO;306306+ hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP;307307+ }301308302309 hw->sta_data_size = sizeof(struct iwl_mvm_sta);303310 hw->vif_data_size = sizeof(struct iwl_mvm_vif);···320319321320 if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_GO_UAPSD)322321 hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;322322+323323+ if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_CSA_FLOW)324324+ hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;323325324326 hw->wiphy->iface_combinations = iwl_mvm_iface_combinations;325327 hw->wiphy->n_iface_combinations =···543539 return -EACCES;544540545541 /* return from D0i3 before starting a new Tx aggregation */546546- if (action == IEEE80211_AMPDU_TX_START) {542542+ switch (action) {543543+ case IEEE80211_AMPDU_TX_START:544544+ case IEEE80211_AMPDU_TX_STOP_CONT:545545+ case IEEE80211_AMPDU_TX_STOP_FLUSH:546546+ case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:547547+ case IEEE80211_AMPDU_TX_OPERATIONAL:547548 iwl_mvm_ref(mvm, IWL_MVM_REF_TX_AGG);548549 tx_agg_ref = true;549550550551 /*551551- * wait synchronously until D0i3 exit to get the correct552552- * sequence number for the tid552552+ * for tx start, wait synchronously until D0i3 exit to553553+ * get the correct sequence number for the tid.554554+ * additionally, some other ampdu actions use direct555555+ * target access, which is not handled automatically556556+ * by the trans layer (unlike commands), so wait for557557+ * d0i3 exit in these cases as well.553558 */554559 if (!wait_event_timeout(mvm->d0i3_exit_waitq,555560 !test_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status), HZ)) {···566553 iwl_mvm_unref(mvm, IWL_MVM_REF_TX_AGG);567554 return -EIO;568555 }556556+ break;557557+ default:558558+ break;569559 }570560571561 mutex_lock(&mvm->mutex);···773757 .pwr_restriction = cpu_to_le16(tx_power),774758 };775759776776- return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, CMD_SYNC,760760+ return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, 0,777761 sizeof(reduce_txpwr_cmd),778762 &reduce_txpwr_cmd);779763}···832816 if (ret)833817 goto out_release;834818835835- ret = iwl_mvm_power_update_mac(mvm, vif);819819+ ret = iwl_mvm_power_update_mac(mvm);836820 if (ret)837821 goto out_release;838822839823 /* beacon filtering */840840- ret = iwl_mvm_disable_beacon_filter(mvm, vif, CMD_SYNC);824824+ ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);841825 if (ret)842826 goto out_remove_mac;843827···983967 if (mvm->vif_count && vif->type != NL80211_IFTYPE_P2P_DEVICE)984968 mvm->vif_count--;985969986986- iwl_mvm_power_update_mac(mvm, vif);970970+ iwl_mvm_power_update_mac(mvm);987971 iwl_mvm_mac_ctxt_remove(mvm, vif);988972989973out_release:···12441228 if (!iwl_mvm_bcast_filter_build_cmd(mvm, &cmd))12451229 return 0;1246123012471247- return iwl_mvm_send_cmd_pdu(mvm, BCAST_FILTER_CMD, CMD_SYNC,12311231+ return iwl_mvm_send_cmd_pdu(mvm, BCAST_FILTER_CMD, 0,12481232 sizeof(cmd), &cmd);12491233}12501234#else···12711255 if (changes & BSS_CHANGED_ASSOC && bss_conf->assoc)12721256 iwl_mvm_mac_ctxt_recalc_tsf_id(mvm, vif);1273125712741274- ret = iwl_mvm_mac_ctxt_changed(mvm, vif);12581258+ ret = iwl_mvm_mac_ctxt_changed(mvm, vif, false);12751259 if (ret)12761260 IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);12771261···13511335 iwl_mvm_remove_time_event(mvm, mvmvif,13521336 &mvmvif->time_event_data);13531337 iwl_mvm_sf_update(mvm, vif, false);13541354- WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, CMD_SYNC));13381338+ WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0));13551339 } else if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS |13561340 BSS_CHANGED_QOS)) {13571357- ret = iwl_mvm_power_update_mac(mvm, vif);13411341+ ret = iwl_mvm_power_update_mac(mvm);13581342 if (ret)13591343 IWL_ERR(mvm, "failed to update power mode\n");13601344 }···13651349 }1366135013671351 if (changes & BSS_CHANGED_CQM) {13681368- IWL_DEBUG_MAC80211(mvm, "cqm info_changed");13521352+ IWL_DEBUG_MAC80211(mvm, "cqm info_changed\n");13691353 /* reset cqm events tracking */13701354 mvmvif->bf_data.last_cqm_event = 0;13711371- ret = iwl_mvm_update_beacon_filter(mvm, vif, false, CMD_SYNC);13721372- if (ret)13731373- IWL_ERR(mvm, "failed to update CQM thresholds\n");13551355+ if (mvmvif->bf_data.bf_enabled) {13561356+ ret = iwl_mvm_enable_beacon_filter(mvm, vif, 0);13571357+ if (ret)13581358+ IWL_ERR(mvm,13591359+ "failed to update CQM thresholds\n");13601360+ }13741361 }1375136213761363 if (changes & BSS_CHANGED_ARP_FILTER) {13771377- IWL_DEBUG_MAC80211(mvm, "arp filter changed");13641364+ IWL_DEBUG_MAC80211(mvm, "arp filter changed\n");13781365 iwl_mvm_configure_bcast_filter(mvm, vif);13791366 }13801367}···14231404 mvmvif->ap_ibss_active = true;1424140514251406 /* power updated needs to be done before quotas */14261426- iwl_mvm_power_update_mac(mvm, vif);14071407+ iwl_mvm_power_update_mac(mvm);1427140814281409 ret = iwl_mvm_update_quotas(mvm, vif);14291410 if (ret)···1431141214321413 /* Need to update the P2P Device MAC (only GO, IBSS is single vif) */14331414 if (vif->p2p && mvm->p2p_device_vif)14341434- iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif);14151415+ iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif, false);1435141614361417 iwl_mvm_ref(mvm, IWL_MVM_REF_AP_IBSS);14371418···14411422 return 0;1442142314431424out_quota_failed:14441444- iwl_mvm_power_update_mac(mvm, vif);14251425+ iwl_mvm_power_update_mac(mvm);14451426 mvmvif->ap_ibss_active = false;14461427 iwl_mvm_send_rm_bcast_sta(mvm, &mvmvif->bcast_sta);14471428out_unbind:···1471145214721453 /* Need to update the P2P Device MAC (only GO, IBSS is single vif) */14731454 if (vif->p2p && mvm->p2p_device_vif)14741474- iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif);14551455+ iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif, false);1475145614761457 iwl_mvm_update_quotas(mvm, NULL);14771458 iwl_mvm_send_rm_bcast_sta(mvm, &mvmvif->bcast_sta);14781459 iwl_mvm_binding_remove_vif(mvm, vif);1479146014801480- iwl_mvm_power_update_mac(mvm, vif);14611461+ iwl_mvm_power_update_mac(mvm);1481146214821463 iwl_mvm_mac_ctxt_remove(mvm, vif);14831464···1498147914991480 if (changes & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_HT |15001481 BSS_CHANGED_BANDWIDTH) &&15011501- iwl_mvm_mac_ctxt_changed(mvm, vif))14821482+ iwl_mvm_mac_ctxt_changed(mvm, vif, false))15021483 IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);1503148415041485 /* Need to send a new beacon template to the FW */···15151496 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);1516149715171498 mutex_lock(&mvm->mutex);14991499+15001500+ if (changes & BSS_CHANGED_IDLE && !bss_conf->idle)15011501+ iwl_mvm_sched_scan_stop(mvm, true);1518150215191503 switch (vif->type) {15201504 case NL80211_IFTYPE_STATION:···1549152715501528 switch (mvm->scan_status) {15511529 case IWL_MVM_SCAN_SCHED:15521552- ret = iwl_mvm_sched_scan_stop(mvm);15301530+ ret = iwl_mvm_sched_scan_stop(mvm, true);15531531 if (ret) {15541532 ret = -EBUSY;15551533 goto out;···17371715 } else if (old_state == IEEE80211_STA_ASSOC &&17381716 new_state == IEEE80211_STA_AUTHORIZED) {17391717 /* enable beacon filtering */17401740- if (vif->bss_conf.dtim_period)17411741- WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif,17421742- CMD_SYNC));17181718+ WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0));17431719 ret = 0;17441720 } else if (old_state == IEEE80211_STA_AUTHORIZED &&17451721 new_state == IEEE80211_STA_ASSOC) {17461722 /* disable beacon filtering */17471747- WARN_ON(iwl_mvm_disable_beacon_filter(mvm, vif, CMD_SYNC));17231723+ WARN_ON(iwl_mvm_disable_beacon_filter(mvm, vif, 0));17481724 ret = 0;17491725 } else if (old_state == IEEE80211_STA_ASSOC &&17501726 new_state == IEEE80211_STA_AUTH) {···17991779 int ret;1800178018011781 mutex_lock(&mvm->mutex);18021802- ret = iwl_mvm_mac_ctxt_changed(mvm, vif);17821782+ ret = iwl_mvm_mac_ctxt_changed(mvm, vif, false);18031783 mutex_unlock(&mvm->mutex);18041784 return ret;18051785 }···18921872 int ret;1893187318941874 mutex_lock(&mvm->mutex);18951895- ret = iwl_mvm_sched_scan_stop(mvm);18751875+ ret = iwl_mvm_sched_scan_stop(mvm, false);18961876 mutex_unlock(&mvm->mutex);18971877 iwl_mvm_wait_for_async_handlers(mvm);18981878···21882168 return;2189216921902170 mutex_lock(&mvm->mutex);21712171+ iwl_mvm_bt_coex_vif_change(mvm);21912172 iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->min_def,21922173 ctx->rx_chains_static,21932174 ctx->rx_chains_dynamic);21942194- iwl_mvm_bt_coex_vif_change(mvm);21952175 mutex_unlock(&mvm->mutex);21962176}21972177···2211219122122192 switch (vif->type) {22132193 case NL80211_IFTYPE_AP:21942194+ /* Unless it's a CSA flow we have nothing to do here */21952195+ if (vif->csa_active) {21962196+ mvmvif->ap_ibss_active = true;21972197+ break;21982198+ }22142199 case NL80211_IFTYPE_ADHOC:22152200 /*22162201 * The AP binding flow is handled as part of the start_ap flow···22392214 * Power state must be updated before quotas,22402215 * otherwise fw will complain.22412216 */22422242- iwl_mvm_power_update_mac(mvm, vif);22172217+ iwl_mvm_power_update_mac(mvm);2243221822442219 /* Setting the quota at this stage is only required for monitor22452220 * interfaces. For the other types, the bss_info changed flow···22522227 goto out_remove_binding;22532228 }2254222922302230+ /* Handle binding during CSA */22312231+ if (vif->type == NL80211_IFTYPE_AP) {22322232+ iwl_mvm_update_quotas(mvm, vif);22332233+ iwl_mvm_mac_ctxt_changed(mvm, vif, false);22342234+ }22352235+22552236 goto out_unlock;2256223722572238 out_remove_binding:22582239 iwl_mvm_binding_remove_vif(mvm, vif);22592259- iwl_mvm_power_update_mac(mvm, vif);22402240+ iwl_mvm_power_update_mac(mvm);22602241 out_unlock:22612242 mutex_unlock(&mvm->mutex);22622243 if (ret)···22822251 iwl_mvm_remove_time_event(mvm, mvmvif, &mvmvif->time_event_data);2283225222842253 switch (vif->type) {22852285- case NL80211_IFTYPE_AP:22862254 case NL80211_IFTYPE_ADHOC:22872255 goto out_unlock;22882256 case NL80211_IFTYPE_MONITOR:22892257 mvmvif->monitor_active = false;22902258 iwl_mvm_update_quotas(mvm, NULL);22912259 break;22602260+ case NL80211_IFTYPE_AP:22612261+ /* This part is triggered only during CSA */22622262+ if (!vif->csa_active || !mvmvif->ap_ibss_active)22632263+ goto out_unlock;22642264+22652265+ mvmvif->ap_ibss_active = false;22662266+ iwl_mvm_update_quotas(mvm, NULL);22672267+ /*TODO: bt_coex notification here? */22922268 default:22932269 break;22942270 }2295227122962272 iwl_mvm_binding_remove_vif(mvm, vif);22972297- iwl_mvm_power_update_mac(mvm, vif);2298227322992274out_unlock:23002275 mvmvif->phy_ctxt = NULL;22762276+ iwl_mvm_power_update_mac(mvm);23012277 mutex_unlock(&mvm->mutex);23022278}23032279···23682330 return -EINVAL;2369233123702332 if (nla_get_u32(tb[IWL_MVM_TM_ATTR_BEACON_FILTER_STATE]))23712371- return iwl_mvm_enable_beacon_filter(mvm, vif,23722372- CMD_SYNC);23732373- return iwl_mvm_disable_beacon_filter(mvm, vif, CMD_SYNC);23332333+ return iwl_mvm_enable_beacon_filter(mvm, vif, 0);23342334+ return iwl_mvm_disable_beacon_filter(mvm, vif, 0);23742335 }2375233623762337 return -EOPNOTSUPP;···23892352 return err;23902353}23912354#endif23552355+23562356+static void iwl_mvm_channel_switch_beacon(struct ieee80211_hw *hw,23572357+ struct ieee80211_vif *vif,23582358+ struct cfg80211_chan_def *chandef)23592359+{23602360+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);23612361+23622362+ mutex_lock(&mvm->mutex);23632363+ if (WARN(mvm->csa_vif && mvm->csa_vif->csa_active,23642364+ "Another CSA is already in progress"))23652365+ goto out_unlock;23662366+23672367+ IWL_DEBUG_MAC80211(mvm, "CSA started to freq %d\n",23682368+ chandef->center_freq1);23692369+ mvm->csa_vif = vif;23702370+23712371+out_unlock:23722372+ mutex_unlock(&mvm->mutex);23732373+}23742374+23752375+static void iwl_mvm_mac_flush(struct ieee80211_hw *hw,23762376+ struct ieee80211_vif *vif, u32 queues, bool drop)23772377+{23782378+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);23792379+ struct iwl_mvm_vif *mvmvif;23802380+ struct iwl_mvm_sta *mvmsta;23812381+23822382+ if (!vif || vif->type != NL80211_IFTYPE_STATION)23832383+ return;23842384+23852385+ mutex_lock(&mvm->mutex);23862386+ mvmvif = iwl_mvm_vif_from_mac80211(vif);23872387+ mvmsta = iwl_mvm_sta_from_staid_protected(mvm, mvmvif->ap_sta_id);23882388+23892389+ if (WARN_ON_ONCE(!mvmsta))23902390+ goto done;23912391+23922392+ if (drop) {23932393+ if (iwl_mvm_flush_tx_path(mvm, mvmsta->tfd_queue_msk, true))23942394+ IWL_ERR(mvm, "flush request fail\n");23952395+ } else {23962396+ iwl_trans_wait_tx_queue_empty(mvm->trans,23972397+ mvmsta->tfd_queue_msk);23982398+ }23992399+done:24002400+ mutex_unlock(&mvm->mutex);24012401+}2392240223932403const struct ieee80211_ops iwl_mvm_hw_ops = {23942404 .tx = iwl_mvm_mac_tx,···24602376 .sta_rc_update = iwl_mvm_sta_rc_update,24612377 .conf_tx = iwl_mvm_mac_conf_tx,24622378 .mgd_prepare_tx = iwl_mvm_mac_mgd_prepare_tx,23792379+ .flush = iwl_mvm_mac_flush,24632380 .sched_scan_start = iwl_mvm_mac_sched_scan_start,24642381 .sched_scan_stop = iwl_mvm_mac_sched_scan_stop,24652382 .set_key = iwl_mvm_mac_set_key,···24792394 .leave_ibss = iwl_mvm_stop_ap_ibss,2480239524812396 .set_tim = iwl_mvm_set_tim,23972397+23982398+ .channel_switch_beacon = iwl_mvm_channel_switch_beacon,2482239924832400 CFG80211_TESTMODE_CMD(iwl_mvm_mac_testmode_cmd)24842401
···7474#define NVM_WRITE_OPCODE 17575#define NVM_READ_OPCODE 076767777+/* load nvm chunk response */7878+enum {7979+ READ_NVM_CHUNK_SUCCEED = 0,8080+ READ_NVM_CHUNK_NOT_VALID_ADDRESS = 18181+};8282+7783/*7884 * prepare the NVM host command w/ the pointers to the nvm buffer7985 * and send it to fw···9690 struct iwl_host_cmd cmd = {9791 .id = NVM_ACCESS_CMD,9892 .len = { sizeof(struct iwl_nvm_access_cmd), length },9999- .flags = CMD_SYNC | CMD_SEND_IN_RFKILL,9393+ .flags = CMD_SEND_IN_RFKILL,10094 .data = { &nvm_access_cmd, data },10195 /* data may come from vmalloc, so use _DUP */10296 .dataflags = { 0, IWL_HCMD_DFL_DUP },···118112 struct iwl_rx_packet *pkt;119113 struct iwl_host_cmd cmd = {120114 .id = NVM_ACCESS_CMD,121121- .flags = CMD_SYNC | CMD_WANT_SKB | CMD_SEND_IN_RFKILL,115115+ .flags = CMD_WANT_SKB | CMD_SEND_IN_RFKILL,122116 .data = { &nvm_access_cmd, },123117 };124118 int ret, bytes_read, offset_read;···145139 offset_read = le16_to_cpu(nvm_resp->offset);146140 resp_data = nvm_resp->data;147141 if (ret) {148148- IWL_ERR(mvm,149149- "NVM access command failed with status %d (device: %s)\n",150150- ret, mvm->cfg->name);151151- ret = -EINVAL;142142+ if ((offset != 0) &&143143+ (ret == READ_NVM_CHUNK_NOT_VALID_ADDRESS)) {144144+ /*145145+ * meaning of NOT_VALID_ADDRESS:146146+ * driver try to read chunk from address that is147147+ * multiple of 2K and got an error since addr is empty.148148+ * meaning of (offset != 0): driver already149149+ * read valid data from another chunk so this case150150+ * is not an error.151151+ */152152+ IWL_DEBUG_EEPROM(mvm->trans->dev,153153+ "NVM access command failed on offset 0x%x since that section size is multiple 2K\n",154154+ offset);155155+ ret = 0;156156+ } else {157157+ IWL_DEBUG_EEPROM(mvm->trans->dev,158158+ "NVM access command failed with status %d (device: %s)\n",159159+ ret, mvm->cfg->name);160160+ ret = -EIO;161161+ }152162 goto exit;153163 }154164···233211 while (ret == length) {234212 ret = iwl_nvm_read_chunk(mvm, section, offset, length, data);235213 if (ret < 0) {236236- IWL_ERR(mvm,237237- "Cannot read NVM from section %d offset %d, length %d\n",238238- section, offset, length);214214+ IWL_DEBUG_EEPROM(mvm->trans->dev,215215+ "Cannot read NVM from section %d offset %d, length %d\n",216216+ section, offset, length);239217 return ret;240218 }241219 offset += ret;···260238 return NULL;261239 }262240 } else {241241+ /* SW and REGULATORY sections are mandatory */263242 if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data ||264264- !mvm->nvm_sections[NVM_SECTION_TYPE_MAC_OVERRIDE].data ||265243 !mvm->nvm_sections[NVM_SECTION_TYPE_REGULATORY].data) {266244 IWL_ERR(mvm,267245 "Can't parse empty family 8000 NVM sections\n");246246+ return NULL;247247+ }248248+ /* MAC_OVERRIDE or at least HW section must exist */249249+ if (!mvm->nvm_sections[mvm->cfg->nvm_hw_section_num].data &&250250+ !mvm->nvm_sections[NVM_SECTION_TYPE_MAC_OVERRIDE].data) {251251+ IWL_ERR(mvm,252252+ "Can't parse mac_address, empty sections\n");268253 return NULL;269254 }270255 }···340311 * get here after that we assume the NVM request can be satisfied341312 * synchronously.342313 */343343- ret = request_firmware(&fw_entry, iwlwifi_mod_params.nvm_file,314314+ ret = request_firmware(&fw_entry, mvm->nvm_file_name,344315 mvm->trans->dev);345316 if (ret) {346317 IWL_ERR(mvm, "ERROR: %s isn't available %d\n",347347- iwlwifi_mod_params.nvm_file, ret);318318+ mvm->nvm_file_name, ret);348319 return ret;349320 }350321351322 IWL_INFO(mvm, "Loaded NVM file %s (%zu bytes)\n",352352- iwlwifi_mod_params.nvm_file, fw_entry->size);323323+ mvm->nvm_file_name, fw_entry->size);353324354325 if (fw_entry->size < sizeof(*file_sec)) {355326 IWL_ERR(mvm, "NVM file too small\n");···456427 return ret;457428}458429459459-int iwl_nvm_init(struct iwl_mvm *mvm)430430+int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic)460431{461461- int ret, i, section;432432+ int ret, section;462433 u8 *nvm_buffer, *temp;463463- int nvm_to_read[NVM_MAX_NUM_SECTIONS];464464- int num_of_sections_to_read;465434466435 if (WARN_ON_ONCE(mvm->cfg->nvm_hw_section_num >= NVM_MAX_NUM_SECTIONS))467436 return -EINVAL;468437469469- /* load external NVM if configured */470470- if (iwlwifi_mod_params.nvm_file) {471471- /* move to External NVM flow */472472- ret = iwl_mvm_read_external_nvm(mvm);473473- if (ret)474474- return ret;475475- } else {476476- /* list of NVM sections we are allowed/need to read */477477- if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) {478478- nvm_to_read[0] = mvm->cfg->nvm_hw_section_num;479479- nvm_to_read[1] = NVM_SECTION_TYPE_SW;480480- nvm_to_read[2] = NVM_SECTION_TYPE_CALIBRATION;481481- nvm_to_read[3] = NVM_SECTION_TYPE_PRODUCTION;482482- num_of_sections_to_read = 4;483483- } else {484484- nvm_to_read[0] = NVM_SECTION_TYPE_SW;485485- nvm_to_read[1] = NVM_SECTION_TYPE_CALIBRATION;486486- nvm_to_read[2] = NVM_SECTION_TYPE_PRODUCTION;487487- nvm_to_read[3] = NVM_SECTION_TYPE_REGULATORY;488488- nvm_to_read[4] = NVM_SECTION_TYPE_MAC_OVERRIDE;489489- num_of_sections_to_read = 5;490490- }491491-438438+ /* load NVM values from nic */439439+ if (read_nvm_from_nic) {492440 /* Read From FW NVM */493441 IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from NVM\n");494442495495- /* TODO: find correct NVM max size for a section */496443 nvm_buffer = kmalloc(mvm->cfg->base_params->eeprom_size,497444 GFP_KERNEL);498445 if (!nvm_buffer)499446 return -ENOMEM;500500- for (i = 0; i < num_of_sections_to_read; i++) {501501- section = nvm_to_read[i];447447+ for (section = 0; section < NVM_MAX_NUM_SECTIONS; section++) {502448 /* we override the constness for initial read */503449 ret = iwl_nvm_read_section(mvm, section, nvm_buffer);504450 if (ret < 0)505505- break;451451+ continue;506452 temp = kmemdup(nvm_buffer, ret, GFP_KERNEL);507453 if (!temp) {508454 ret = -ENOMEM;···506502 mvm->nvm_hw_blob.size = ret;507503 break;508504 }509509- WARN(1, "section: %d", section);510505 }511506#endif512507 }513508 kfree(nvm_buffer);514514- if (ret < 0)509509+ }510510+511511+ /* load external NVM if configured */512512+ if (mvm->nvm_file_name) {513513+ /* move to External NVM flow */514514+ ret = iwl_mvm_read_external_nvm(mvm);515515+ if (ret)515516 return ret;516517 }517518519519+ /* parse the relevant nvm sections */518520 mvm->nvm_data = iwl_parse_nvm_sections(mvm);519521 if (!mvm->nvm_data)520522 return -ENODATA;
+34-9
drivers/net/wireless/iwlwifi/mvm/ops.c
···7979#include "iwl-prph.h"8080#include "rs.h"8181#include "fw-api-scan.h"8282-#include "fw-error-dump.h"8382#include "time-event.h"8383+#include "iwl-fw-error-dump.h"84848585/*8686 * module name, copyright, version, etc.···220220 RX_HANDLER(BA_NOTIF, iwl_mvm_rx_ba_notif, false),221221222222 RX_HANDLER(BT_PROFILE_NOTIFICATION, iwl_mvm_rx_bt_coex_notif, true),223223- RX_HANDLER(BEACON_NOTIFICATION, iwl_mvm_rx_beacon_notif, false),223223+ RX_HANDLER(BEACON_NOTIFICATION, iwl_mvm_rx_beacon_notif, true),224224 RX_HANDLER(STATISTICS_NOTIFICATION, iwl_mvm_rx_statistics, true),225225 RX_HANDLER(ANTENNA_COUPLING_NOTIFICATION,226226 iwl_mvm_rx_ant_coupling_notif, true),···466466467467 min_backoff = calc_min_backoff(trans, cfg);468468 iwl_mvm_tt_initialize(mvm, min_backoff);469469+ /* set the nvm_file_name according to priority */470470+ if (iwlwifi_mod_params.nvm_file)471471+ mvm->nvm_file_name = iwlwifi_mod_params.nvm_file;472472+ else473473+ mvm->nvm_file_name = mvm->cfg->default_nvm_file;474474+475475+ if (WARN(cfg->no_power_up_nic_in_init && !mvm->nvm_file_name,476476+ "not allowing power-up and not having nvm_file\n"))477477+ goto out_free;469478470479 /*471471- * If the NVM exists in an external file,472472- * there is no need to unnecessarily power up the NIC at driver load480480+ * Even if nvm exists in the nvm_file driver should read agin the nvm481481+ * from the nic because there might be entries that exist in the OTP482482+ * and not in the file.483483+ * for nics with no_power_up_nic_in_init: rely completley on nvm_file473484 */474474- if (iwlwifi_mod_params.nvm_file) {475475- err = iwl_nvm_init(mvm);485485+ if (cfg->no_power_up_nic_in_init && mvm->nvm_file_name) {486486+ err = iwl_nvm_init(mvm, false);476487 if (err)477488 goto out_free;478489 } else {···530519 out_free:531520 iwl_phy_db_free(mvm->phy_db);532521 kfree(mvm->scan_cmd);533533- if (!iwlwifi_mod_params.nvm_file)522522+ if (!cfg->no_power_up_nic_in_init || !mvm->nvm_file_name)534523 iwl_trans_op_mode_leave(trans);535524 ieee80211_free_hw(mvm->hw);536525 return NULL;···827816 struct iwl_fw_error_dump_file *dump_file;828817 struct iwl_fw_error_dump_data *dump_data;829818 u32 file_len;819819+ u32 trans_len;830820831821 lockdep_assert_held(&mvm->mutex);832822···838826 mvm->fw_error_rxf_len +839827 sizeof(*dump_file) +840828 sizeof(*dump_data) * 2;829829+830830+ trans_len = iwl_trans_dump_data(mvm->trans, NULL, 0);831831+ if (trans_len)832832+ file_len += trans_len;841833842834 dump_file = vmalloc(file_len);843835 if (!dump_file)···856840 dump_data->len = cpu_to_le32(mvm->fw_error_rxf_len);857841 memcpy(dump_data->data, mvm->fw_error_rxf, mvm->fw_error_rxf_len);858842859859- dump_data = (void *)((u8 *)dump_data->data + mvm->fw_error_rxf_len);843843+ dump_data = iwl_mvm_fw_error_next_data(dump_data);860844 dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_SRAM);861845 dump_data->len = cpu_to_le32(mvm->fw_error_sram_len);862846···874858 kfree(mvm->fw_error_sram);875859 mvm->fw_error_sram = NULL;876860 mvm->fw_error_sram_len = 0;861861+862862+ if (trans_len) {863863+ void *buf = iwl_mvm_fw_error_next_data(dump_data);864864+ u32 real_trans_len = iwl_trans_dump_data(mvm->trans, buf,865865+ trans_len);866866+ dump_data = (void *)((u8 *)buf + real_trans_len);867867+ dump_file->file_len =868868+ cpu_to_le32(file_len - trans_len + real_trans_len);869869+ }877870}878871#endif879872···11681143 struct iwl_mvm *mvm = container_of(wk, struct iwl_mvm, d0i3_exit_work);11691144 struct iwl_host_cmd get_status_cmd = {11701145 .id = WOWLAN_GET_STATUSES,11711171- .flags = CMD_SYNC | CMD_HIGH_PRIO | CMD_WANT_SKB,11461146+ .flags = CMD_HIGH_PRIO | CMD_WANT_SKB,11721147 };11731148 struct iwl_wowlan_status *status;11741149 int ret;
+16-7
drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c
···156156 idle_cnt = chains_static;157157 active_cnt = chains_dynamic;158158159159+ /* In scenarios where we only ever use a single-stream rates,160160+ * i.e. legacy 11b/g/a associations, single-stream APs or even161161+ * static SMPS, enable both chains to get diversity, improving162162+ * the case where we're far enough from the AP that attenuation163163+ * between the two antennas is sufficiently different to impact164164+ * performance.165165+ */166166+ if (active_cnt == 1 && iwl_mvm_rx_diversity_allowed(mvm)) {167167+ idle_cnt = 2;168168+ active_cnt = 2;169169+ }170170+159171 cmd->rxchain_info = cpu_to_le32(mvm->fw->valid_rx_ant <<160172 PHY_RX_CHAIN_VALID_POS);161173 cmd->rxchain_info |= cpu_to_le32(idle_cnt << PHY_RX_CHAIN_CNT_POS);···199187 iwl_mvm_phy_ctxt_cmd_data(mvm, &cmd, chandef,200188 chains_static, chains_dynamic);201189202202- ret = iwl_mvm_send_cmd_pdu(mvm, PHY_CONTEXT_CMD, CMD_SYNC,190190+ ret = iwl_mvm_send_cmd_pdu(mvm, PHY_CONTEXT_CMD, 0,203191 sizeof(struct iwl_phy_context_cmd),204192 &cmd);205193 if (ret)···214202 struct cfg80211_chan_def *chandef,215203 u8 chains_static, u8 chains_dynamic)216204{217217- int ret;218218-219205 WARN_ON(!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) &&220206 ctxt->ref);221207 lockdep_assert_held(&mvm->mutex);222208223209 ctxt->channel = chandef->chan;224224- ret = iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef,225225- chains_static, chains_dynamic,226226- FW_CTXT_ACTION_ADD, 0);227210228228- return ret;211211+ return iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef,212212+ chains_static, chains_dynamic,213213+ FW_CTXT_ACTION_ADD, 0);229214}230215231216/*
+109-99
drivers/net/wireless/iwlwifi/mvm/power.c
···123123 cmd->ba_enable_beacon_abort = cpu_to_le32(mvmvif->bf_data.ba_enabled);124124}125125126126-int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm,127127- struct ieee80211_vif *vif, bool enable)128128-{129129- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);130130- struct iwl_beacon_filter_cmd cmd = {131131- IWL_BF_CMD_CONFIG_DEFAULTS,132132- .bf_enable_beacon_filter = cpu_to_le32(1),133133- .ba_enable_beacon_abort = cpu_to_le32(enable),134134- };135135-136136- if (!mvmvif->bf_data.bf_enabled)137137- return 0;138138-139139- if (mvm->cur_ucode == IWL_UCODE_WOWLAN)140140- cmd.ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_D3);141141-142142- mvmvif->bf_data.ba_enabled = enable;143143- iwl_mvm_beacon_filter_set_cqm_params(mvm, vif, &cmd);144144- iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd);145145- return iwl_mvm_beacon_filter_send_cmd(mvm, &cmd, CMD_SYNC);146146-}147147-148126static void iwl_mvm_power_log(struct iwl_mvm *mvm,149127 struct iwl_mac_power_cmd *cmd)150128{···246268 IWL_MVM_PS_HEAVY_RX_THLD_PERCENT;247269}248270271271+static void iwl_mvm_binding_iterator(void *_data, u8 *mac,272272+ struct ieee80211_vif *vif)273273+{274274+ unsigned long *data = _data;275275+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);276276+277277+ if (!mvmvif->phy_ctxt)278278+ return;279279+280280+ if (vif->type == NL80211_IFTYPE_STATION ||281281+ vif->type == NL80211_IFTYPE_AP)282282+ __set_bit(mvmvif->phy_ctxt->id, data);283283+}284284+249285static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm,250286 struct ieee80211_vif *vif)251287{252288 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);289289+ unsigned long phy_ctxt_counter = 0;290290+291291+ ieee80211_iterate_active_interfaces_atomic(mvm->hw,292292+ IEEE80211_IFACE_ITER_NORMAL,293293+ iwl_mvm_binding_iterator,294294+ &phy_ctxt_counter);253295254296 if (!memcmp(mvmvif->uapsd_misbehaving_bssid, vif->bss_conf.bssid,255297 ETH_ALEN))···285287 if (vif->p2p &&286288 (vif->bss_conf.p2p_noa_attr.oppps_ctwindow &287289 IEEE80211_P2P_OPPPS_ENABLE_BIT))290290+ return false;291291+292292+ /*293293+ * Avoid using uAPSD if client is in DCM -294294+ * low latency issue in Miracast295295+ */296296+ if (hweight8(phy_ctxt_counter) >= 2)288297 return false;289298290299 return true;···434429 memcpy(&iwl_mvm_vif_from_mac80211(vif)->mac_pwr_cmd, &cmd, sizeof(cmd));435430#endif436431437437- return iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, CMD_SYNC,432432+ return iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, 0,438433 sizeof(cmd), &cmd);439434}440435···460455 "Sending device power command with flags = 0x%X\n",461456 cmd.flags);462457463463- return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_SYNC, sizeof(cmd),458458+ return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, 0, sizeof(cmd),464459 &cmd);465460}466461···618613 ap_same_channel = (bss_mvmvif->phy_ctxt->id ==619614 ap_mvmvif->phy_ctxt->id);620615621621- /* bss is not stand alone: enable PM if alone on its channel */622622- if (vifs->bss_active && !(client_same_channel || ap_same_channel) &&616616+ /* clients are not stand alone: enable PM if DCM */617617+ if (!(client_same_channel || ap_same_channel) &&623618 (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM)) {619619+ if (vifs->bss_active)624620 bss_mvmvif->pm_enabled = true;625625- return;621621+ if (vifs->p2p_active &&622622+ (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PM))623623+ p2p_mvmvif->pm_enabled = true;624624+ return;626625 }627626628627 /*···640631 if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PM)641632 p2p_mvmvif->pm_enabled = true;642633 }643643-}644644-645645-int iwl_mvm_power_update_mac(struct iwl_mvm *mvm, struct ieee80211_vif *vif)646646-{647647- struct iwl_mvm_vif *mvmvif;648648- struct iwl_power_vifs vifs = {};649649- bool ba_enable;650650- int ret;651651-652652- lockdep_assert_held(&mvm->mutex);653653-654654- iwl_mvm_power_set_pm(mvm, &vifs);655655-656656- /* disable PS if CAM */657657- if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM) {658658- mvm->ps_disabled = true;659659- } else {660660- /* don't update device power state unless we add / remove monitor */661661- if (vifs.monitor_vif) {662662- if (vifs.monitor_active)663663- mvm->ps_disabled = true;664664- ret = iwl_mvm_power_update_device(mvm);665665- if (ret)666666- return ret;667667- }668668- }669669-670670- if (vifs.bss_vif) {671671- ret = iwl_mvm_power_send_cmd(mvm, vifs.bss_vif);672672- if (ret)673673- return ret;674674- }675675-676676- if (vifs.p2p_vif) {677677- ret = iwl_mvm_power_send_cmd(mvm, vifs.p2p_vif);678678- if (ret)679679- return ret;680680- }681681-682682- if (!vifs.bf_vif)683683- return 0;684684-685685- vif = vifs.bf_vif;686686- mvmvif = iwl_mvm_vif_from_mac80211(vif);687687-688688- ba_enable = !(!mvmvif->pm_enabled || mvm->ps_disabled ||689689- !vif->bss_conf.ps || iwl_mvm_vif_low_latency(mvmvif));690690-691691- return iwl_mvm_update_beacon_abort(mvm, vifs.bf_vif, ba_enable);692634}693635694636#ifdef CONFIG_IWLWIFI_DEBUGFS···761801 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);762802 int ret;763803764764- if (mvmvif != mvm->bf_allowed_vif ||804804+ if (mvmvif != mvm->bf_allowed_vif || !vif->bss_conf.dtim_period ||765805 vif->type != NL80211_IFTYPE_STATION || vif->p2p)766806 return 0;767807···789829 return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, flags, false);790830}791831832832+static int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm,833833+ struct ieee80211_vif *vif,834834+ bool enable)835835+{836836+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);837837+ struct iwl_beacon_filter_cmd cmd = {838838+ IWL_BF_CMD_CONFIG_DEFAULTS,839839+ .bf_enable_beacon_filter = cpu_to_le32(1),840840+ };841841+842842+ if (!mvmvif->bf_data.bf_enabled)843843+ return 0;844844+845845+ if (mvm->cur_ucode == IWL_UCODE_WOWLAN)846846+ cmd.ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_D3);847847+848848+ mvmvif->bf_data.ba_enabled = enable;849849+ return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, 0, false);850850+}851851+792852int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,793853 struct ieee80211_vif *vif,794854 u32 flags)···826846 mvmvif->bf_data.bf_enabled = false;827847828848 return ret;849849+}850850+851851+int iwl_mvm_power_update_mac(struct iwl_mvm *mvm)852852+{853853+ struct iwl_mvm_vif *mvmvif;854854+ struct iwl_power_vifs vifs = {};855855+ bool ba_enable;856856+ int ret;857857+858858+ lockdep_assert_held(&mvm->mutex);859859+860860+ iwl_mvm_power_set_pm(mvm, &vifs);861861+862862+ /* disable PS if CAM */863863+ if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM) {864864+ mvm->ps_disabled = true;865865+ } else {866866+ /* don't update device power state unless we add / remove monitor */867867+ if (vifs.monitor_vif) {868868+ if (vifs.monitor_active)869869+ mvm->ps_disabled = true;870870+ ret = iwl_mvm_power_update_device(mvm);871871+ if (ret)872872+ return ret;873873+ }874874+ }875875+876876+ if (vifs.bss_vif) {877877+ ret = iwl_mvm_power_send_cmd(mvm, vifs.bss_vif);878878+ if (ret)879879+ return ret;880880+ }881881+882882+ if (vifs.p2p_vif) {883883+ ret = iwl_mvm_power_send_cmd(mvm, vifs.p2p_vif);884884+ if (ret)885885+ return ret;886886+ }887887+888888+ if (!vifs.bf_vif)889889+ return 0;890890+891891+ mvmvif = iwl_mvm_vif_from_mac80211(vifs.bf_vif);892892+893893+ ba_enable = !(!mvmvif->pm_enabled || mvm->ps_disabled ||894894+ !vifs.bf_vif->bss_conf.ps ||895895+ iwl_mvm_vif_low_latency(mvmvif));896896+897897+ return iwl_mvm_update_beacon_abort(mvm, vifs.bf_vif, ba_enable);829898}830899831900int iwl_mvm_update_d0i3_power_mode(struct iwl_mvm *mvm,···900871 if (WARN_ON(!dtimper_msec))901872 return 0;902873903903- cmd.flags |=904904- cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);905874 cmd.skip_dtim_periods = 300 / dtimper_msec;875875+ if (cmd.skip_dtim_periods)876876+ cmd.flags |=877877+ cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);906878 }907879 iwl_mvm_power_log(mvm, &cmd);908880#ifdef CONFIG_IWLWIFI_DEBUGFS···933903 }934904935905 return ret;936936-}937937-938938-int iwl_mvm_update_beacon_filter(struct iwl_mvm *mvm,939939- struct ieee80211_vif *vif,940940- bool force,941941- u32 flags)942942-{943943- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);944944-945945- if (mvmvif != mvm->bf_allowed_vif)946946- return 0;947947-948948- if (!mvmvif->bf_data.bf_enabled) {949949- /* disable beacon filtering explicitly if force is true */950950- if (force)951951- return iwl_mvm_disable_beacon_filter(mvm, vif, flags);952952- return 0;953953- }954954-955955- return iwl_mvm_enable_beacon_filter(mvm, vif, flags);956906}
+1-1
drivers/net/wireless/iwlwifi/mvm/quota.c
···285285286286 iwl_mvm_adjust_quota_for_noa(mvm, &cmd);287287288288- ret = iwl_mvm_send_cmd_pdu(mvm, TIME_QUOTA_CMD, CMD_SYNC,288288+ ret = iwl_mvm_send_cmd_pdu(mvm, TIME_QUOTA_CMD, 0,289289 sizeof(cmd), &cmd);290290 if (ret)291291 IWL_ERR(mvm, "Failed to send quota: %d\n", ret);
+65-122
drivers/net/wireless/iwlwifi/mvm/rs.c
···211211 .next_columns = {212212 RS_COLUMN_LEGACY_ANT_B,213213 RS_COLUMN_SISO_ANT_A,214214- RS_COLUMN_SISO_ANT_B,214214+ RS_COLUMN_MIMO2,215215 RS_COLUMN_INVALID,216216 RS_COLUMN_INVALID,217217 RS_COLUMN_INVALID,···223223 .ant = ANT_B,224224 .next_columns = {225225 RS_COLUMN_LEGACY_ANT_A,226226- RS_COLUMN_SISO_ANT_A,227226 RS_COLUMN_SISO_ANT_B,227227+ RS_COLUMN_MIMO2,228228 RS_COLUMN_INVALID,229229 RS_COLUMN_INVALID,230230 RS_COLUMN_INVALID,···238238 RS_COLUMN_SISO_ANT_B,239239 RS_COLUMN_MIMO2,240240 RS_COLUMN_SISO_ANT_A_SGI,241241- RS_COLUMN_SISO_ANT_B_SGI,242241 RS_COLUMN_LEGACY_ANT_A,243242 RS_COLUMN_LEGACY_ANT_B,243243+ RS_COLUMN_INVALID,244244 RS_COLUMN_INVALID,245245 },246246 .checks = {···254254 RS_COLUMN_SISO_ANT_A,255255 RS_COLUMN_MIMO2,256256 RS_COLUMN_SISO_ANT_B_SGI,257257- RS_COLUMN_SISO_ANT_A_SGI,258257 RS_COLUMN_LEGACY_ANT_A,259258 RS_COLUMN_LEGACY_ANT_B,259259+ RS_COLUMN_INVALID,260260 RS_COLUMN_INVALID,261261 },262262 .checks = {···271271 RS_COLUMN_SISO_ANT_B_SGI,272272 RS_COLUMN_MIMO2_SGI,273273 RS_COLUMN_SISO_ANT_A,274274- RS_COLUMN_SISO_ANT_B,275275- RS_COLUMN_MIMO2,276274 RS_COLUMN_LEGACY_ANT_A,277275 RS_COLUMN_LEGACY_ANT_B,276276+ RS_COLUMN_INVALID,277277+ RS_COLUMN_INVALID,278278 },279279 .checks = {280280 rs_siso_allow,···289289 RS_COLUMN_SISO_ANT_A_SGI,290290 RS_COLUMN_MIMO2_SGI,291291 RS_COLUMN_SISO_ANT_B,292292- RS_COLUMN_SISO_ANT_A,293293- RS_COLUMN_MIMO2,294292 RS_COLUMN_LEGACY_ANT_A,295293 RS_COLUMN_LEGACY_ANT_B,294294+ RS_COLUMN_INVALID,295295+ RS_COLUMN_INVALID,296296 },297297 .checks = {298298 rs_siso_allow,···304304 .ant = ANT_AB,305305 .next_columns = {306306 RS_COLUMN_SISO_ANT_A,307307- RS_COLUMN_SISO_ANT_B,308308- RS_COLUMN_SISO_ANT_A_SGI,309309- RS_COLUMN_SISO_ANT_B_SGI,310307 RS_COLUMN_MIMO2_SGI,311308 RS_COLUMN_LEGACY_ANT_A,312309 RS_COLUMN_LEGACY_ANT_B,310310+ RS_COLUMN_INVALID,311311+ RS_COLUMN_INVALID,312312+ RS_COLUMN_INVALID,313313 },314314 .checks = {315315 rs_mimo_allow,···321321 .sgi = true,322322 .next_columns = {323323 RS_COLUMN_SISO_ANT_A_SGI,324324- RS_COLUMN_SISO_ANT_B_SGI,325325- RS_COLUMN_SISO_ANT_A,326326- RS_COLUMN_SISO_ANT_B,327324 RS_COLUMN_MIMO2,328325 RS_COLUMN_LEGACY_ANT_A,329326 RS_COLUMN_LEGACY_ANT_B,327327+ RS_COLUMN_INVALID,328328+ RS_COLUMN_INVALID,329329+ RS_COLUMN_INVALID,330330 },331331 .checks = {332332 rs_mimo_allow,···13351335 tbl->expected_tpt = rs_get_expected_tpt_table(lq_sta, column, rate->bw);13361336}1337133713381338-/*13391339- * Find starting rate for new "search" high-throughput mode of modulation.13401340- * Goal is to find lowest expected rate (under perfect conditions) that is13411341- * above the current measured throughput of "active" mode, to give new mode13421342- * a fair chance to prove itself without too many challenges.13431343- *13441344- * This gets called when transitioning to more aggressive modulation13451345- * (i.e. legacy to SISO or MIMO, or SISO to MIMO), as well as less aggressive13461346- * (i.e. MIMO to SISO). When moving to MIMO, bit rate will typically need13471347- * to decrease to match "active" throughput. When moving from MIMO to SISO,13481348- * bit rate will typically need to increase, but not if performance was bad.13491349- */13501338static s32 rs_get_best_rate(struct iwl_mvm *mvm,13511339 struct iwl_lq_sta *lq_sta,13521340 struct iwl_scale_tbl_info *tbl, /* "search" */13531353- u16 rate_mask, s8 index)13411341+ unsigned long rate_mask, s8 index)13541342{13551355- /* "active" values */13561343 struct iwl_scale_tbl_info *active_tbl =13571344 &(lq_sta->lq_info[lq_sta->active_tbl]);13581358- s32 active_sr = active_tbl->win[index].success_ratio;13591359- s32 active_tpt = active_tbl->expected_tpt[index];13601360- /* expected "search" throughput */13451345+ s32 success_ratio = active_tbl->win[index].success_ratio;13461346+ u16 expected_current_tpt = active_tbl->expected_tpt[index];13611347 const u16 *tpt_tbl = tbl->expected_tpt;13621362-13631363- s32 new_rate, high, low, start_hi;13641348 u16 high_low;13651365- s8 rate = index;13491349+ u32 target_tpt;13501350+ int rate_idx;1366135113671367- new_rate = high = low = start_hi = IWL_RATE_INVALID;13681368-13691369- while (1) {13701370- high_low = rs_get_adjacent_rate(mvm, rate, rate_mask,13711371- tbl->rate.type);13721372-13731373- low = high_low & 0xff;13741374- high = (high_low >> 8) & 0xff;13751375-13761376- /*13771377- * Lower the "search" bit rate, to give new "search" mode13781378- * approximately the same throughput as "active" if:13791379- *13801380- * 1) "Active" mode has been working modestly well (but not13811381- * great), and expected "search" throughput (under perfect13821382- * conditions) at candidate rate is above the actual13831383- * measured "active" throughput (but less than expected13841384- * "active" throughput under perfect conditions).13851385- * OR13861386- * 2) "Active" mode has been working perfectly or very well13871387- * and expected "search" throughput (under perfect13881388- * conditions) at candidate rate is above expected13891389- * "active" throughput (under perfect conditions).13901390- */13911391- if ((((100 * tpt_tbl[rate]) > lq_sta->last_tpt) &&13921392- ((active_sr > RS_SR_FORCE_DECREASE) &&13931393- (active_sr <= IWL_RATE_HIGH_TH) &&13941394- (tpt_tbl[rate] <= active_tpt))) ||13951395- ((active_sr >= IWL_RATE_SCALE_SWITCH) &&13961396- (tpt_tbl[rate] > active_tpt))) {13971397- /* (2nd or later pass)13981398- * If we've already tried to raise the rate, and are13991399- * now trying to lower it, use the higher rate. */14001400- if (start_hi != IWL_RATE_INVALID) {14011401- new_rate = start_hi;14021402- break;14031403- }14041404-14051405- new_rate = rate;14061406-14071407- /* Loop again with lower rate */14081408- if (low != IWL_RATE_INVALID)14091409- rate = low;14101410-14111411- /* Lower rate not available, use the original */14121412- else14131413- break;14141414-14151415- /* Else try to raise the "search" rate to match "active" */14161416- } else {14171417- /* (2nd or later pass)14181418- * If we've already tried to lower the rate, and are14191419- * now trying to raise it, use the lower rate. */14201420- if (new_rate != IWL_RATE_INVALID)14211421- break;14221422-14231423- /* Loop again with higher rate */14241424- else if (high != IWL_RATE_INVALID) {14251425- start_hi = high;14261426- rate = high;14271427-14281428- /* Higher rate not available, use the original */14291429- } else {14301430- new_rate = rate;14311431- break;14321432- }14331433- }13521352+ if (success_ratio > RS_SR_NO_DECREASE) {13531353+ target_tpt = 100 * expected_current_tpt;13541354+ IWL_DEBUG_RATE(mvm,13551355+ "SR %d high. Find rate exceeding EXPECTED_CURRENT %d\n",13561356+ success_ratio, target_tpt);13571357+ } else {13581358+ target_tpt = lq_sta->last_tpt;13591359+ IWL_DEBUG_RATE(mvm,13601360+ "SR %d not thag good. Find rate exceeding ACTUAL_TPT %d\n",13611361+ success_ratio, target_tpt);14341362 }1435136314361436- return new_rate;13641364+ rate_idx = find_first_bit(&rate_mask, BITS_PER_LONG);13651365+13661366+ while (rate_idx != IWL_RATE_INVALID) {13671367+ if (target_tpt < (100 * tpt_tbl[rate_idx]))13681368+ break;13691369+13701370+ high_low = rs_get_adjacent_rate(mvm, rate_idx, rate_mask,13711371+ tbl->rate.type);13721372+13731373+ rate_idx = (high_low >> 8) & 0xff;13741374+ }13751375+13761376+ IWL_DEBUG_RATE(mvm, "Best rate found %d target_tp %d expected_new %d\n",13771377+ rate_idx, target_tpt,13781378+ rate_idx != IWL_RATE_INVALID ?13791379+ 100 * tpt_tbl[rate_idx] : IWL_INVALID_VALUE);13801380+13811381+ return rate_idx;14371382}1438138314391384static u32 rs_bw_from_sta_bw(struct ieee80211_sta *sta)···1553160815541609 tpt = lq_sta->last_tpt / 100;15551610 expected_tpt_tbl = rs_get_expected_tpt_table(lq_sta, next_col,15561556- tbl->rate.bw);16111611+ rs_bw_from_sta_bw(sta));15571612 if (WARN_ON_ONCE(!expected_tpt_tbl))15581613 continue;15591614···15941649 const struct rs_tx_column *curr_column = &rs_tx_columns[tbl->column];15951650 u32 sz = (sizeof(struct iwl_scale_tbl_info) -15961651 (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));15971597- u16 rate_mask = 0;16521652+ unsigned long rate_mask = 0;15981653 u32 rate_idx = 0;1599165416001655 memcpy(search_tbl, tbl, sz);···16361691 !(BIT(rate_idx) & rate_mask)) {16371692 IWL_DEBUG_RATE(mvm,16381693 "can not switch with index %d"16391639- " rate mask %x\n",16941694+ " rate mask %lx\n",16401695 rate_idx, rate_mask);1641169616421697 goto err;···17501805 *stronger = TPC_INVALID;17511806}1752180717531753-static bool rs_tpc_allowed(struct iwl_mvm *mvm, struct rs_rate *rate,17541754- enum ieee80211_band band)18081808+static bool rs_tpc_allowed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,18091809+ struct rs_rate *rate, enum ieee80211_band band)17551810{17561811 int index = rate->index;18121812+ bool cam = (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM);18131813+ bool sta_ps_disabled = (vif->type == NL80211_IFTYPE_STATION &&18141814+ !vif->bss_conf.ps);1757181518161816+ IWL_DEBUG_RATE(mvm, "cam: %d sta_ps_disabled %d\n",18171817+ cam, sta_ps_disabled);17581818 /*17591819 * allow tpc only if power management is enabled, or bt coex17601820 * activity grade allows it and we are on 2.4Ghz.17611821 */17621762- if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM &&18221822+ if ((cam || sta_ps_disabled) &&17631823 !iwl_mvm_bt_coex_is_tpc_allowed(mvm, band))17641824 return false;17651825···1866191618671917#ifdef CONFIG_MAC80211_DEBUGFS18681918 if (lq_sta->dbg_fixed_txp_reduction <= TPC_MAX_REDUCTION) {18691869- IWL_DEBUG_RATE(mvm, "fixed tpc: %d",19191919+ IWL_DEBUG_RATE(mvm, "fixed tpc: %d\n",18701920 lq_sta->dbg_fixed_txp_reduction);18711921 lq_sta->lq.reduced_tpc = lq_sta->dbg_fixed_txp_reduction;18721922 return cur != lq_sta->dbg_fixed_txp_reduction;···18811931 band = chanctx_conf->def.chan->band;18821932 rcu_read_unlock();1883193318841884- if (!rs_tpc_allowed(mvm, rate, band)) {19341934+ if (!rs_tpc_allowed(mvm, vif, rate, band)) {18851935 IWL_DEBUG_RATE(mvm,18861886- "tpc is not allowed. remove txp restrictions");19361936+ "tpc is not allowed. remove txp restrictions\n");18871937 lq_sta->lq.reduced_tpc = TPC_NO_REDUCTION;18881938 return cur != TPC_NO_REDUCTION;18891939 }···1909195919101960 /* override actions if we are on the edge */19111961 if (weak == TPC_INVALID && action == TPC_ACTION_DECREASE) {19121912- IWL_DEBUG_RATE(mvm, "already in lowest txp, stay");19621962+ IWL_DEBUG_RATE(mvm, "already in lowest txp, stay\n");19131963 action = TPC_ACTION_STAY;19141964 } else if (strong == TPC_INVALID &&19151965 (action == TPC_ACTION_INCREASE ||19161966 action == TPC_ACTION_NO_RESTIRCTION)) {19171917- IWL_DEBUG_RATE(mvm, "already in highest txp, stay");19671967+ IWL_DEBUG_RATE(mvm, "already in highest txp, stay\n");19181968 action = TPC_ACTION_STAY;19191969 }19201970···21852235 break;21862236 case RS_ACTION_STAY:21872237 /* No change */21882188- update_lq = rs_tpc_perform(mvm, sta, lq_sta, tbl);22382238+ if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN)22392239+ update_lq = rs_tpc_perform(mvm, sta, lq_sta, tbl);21892240 break;21902241 default:21912242 break;···24402489 if (i == IWL_RATE_9M_INDEX)24412490 continue;2442249124432443- /* Disable MCS9 as a workaround */24442444- if (i == IWL_RATE_MCS_9_INDEX)24452445- continue;24462446-24472492 /* VHT MCS9 isn't valid for 20Mhz for NSS=1,2 */24482493 if (i == IWL_RATE_MCS_9_INDEX &&24492494 sta->bandwidth == IEEE80211_STA_RX_BW_20)···24562509 if (highest_mcs >= IWL_RATE_MCS_0_INDEX) {24572510 for (i = IWL_RATE_MCS_0_INDEX; i <= highest_mcs; i++) {24582511 if (i == IWL_RATE_9M_INDEX)24592459- continue;24602460-24612461- /* Disable MCS9 as a workaround */24622462- if (i == IWL_RATE_MCS_9_INDEX)24632512 continue;2464251324652514 /* VHT MCS9 isn't valid for 20Mhz for NSS=1,2 */
···327327 return -EINVAL;328328 }329329330330- ret = iwl_mvm_send_cmd_pdu(mvm, REMOVE_STA, CMD_SYNC,330330+ ret = iwl_mvm_send_cmd_pdu(mvm, REMOVE_STA, 0,331331 sizeof(rm_sta_cmd), &rm_sta_cmd);332332 if (ret) {333333 IWL_ERR(mvm, "Failed to remove station. Id=%d\n", sta_id);···10531053 cmd.sta_id = sta_id;1054105410551055 status = ADD_STA_SUCCESS;10561056- if (cmd_flags == CMD_SYNC)10571057- ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA_KEY, sizeof(cmd),10581058- &cmd, &status);10591059- else10561056+ if (cmd_flags & CMD_ASYNC)10601057 ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA_KEY, CMD_ASYNC,10611058 sizeof(cmd), &cmd);10591059+ else10601060+ ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA_KEY, sizeof(cmd),10611061+ &cmd, &status);1062106210631063 switch (status) {10641064 case ADD_STA_SUCCESS:···11111111 remove_key ? "removing" : "installing",11121112 igtk_cmd.sta_id);1113111311141114- return iwl_mvm_send_cmd_pdu(mvm, MGMT_MCAST_KEY, CMD_SYNC,11141114+ return iwl_mvm_send_cmd_pdu(mvm, MGMT_MCAST_KEY, 0,11151115 sizeof(igtk_cmd), &igtk_cmd);11161116}11171117···11981198 ieee80211_get_key_rx_seq(keyconf, 0, &seq);11991199 ieee80211_get_tkip_rx_p1k(keyconf, addr, seq.tkip.iv32, p1k);12001200 ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, sta_id,12011201- seq.tkip.iv32, p1k, CMD_SYNC);12011201+ seq.tkip.iv32, p1k, 0);12021202 break;12031203 case WLAN_CIPHER_SUITE_CCMP:12041204 ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, sta_id,12051205- 0, NULL, CMD_SYNC);12051205+ 0, NULL, 0);12061206 break;12071207 default:12081208 ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf,12091209- sta_id, 0, NULL, CMD_SYNC);12091209+ sta_id, 0, NULL, 0);12101210 }1211121112121212 if (ret)
-3
drivers/net/wireless/iwlwifi/mvm/sta.h
···287287 * @tid_disable_agg: bitmap: if bit(tid) is set, the fw won't send ampdus for288288 * tid.289289 * @max_agg_bufsize: the maximal size of the AGG buffer for this station290290- * @bt_reduced_txpower_dbg: debug mode in which %bt_reduced_txpower is forced291291- * by debugfs.292290 * @bt_reduced_txpower: is reduced tx power enabled for this station293291 * @next_status_eosp: the next reclaimed packet is a PS-Poll response and294292 * we need to signal the EOSP···307309 u32 mac_id_n_color;308310 u16 tid_disable_agg;309311 u8 max_agg_bufsize;310310- bool bt_reduced_txpower_dbg;311312 bool bt_reduced_txpower;312313 bool next_status_eosp;313314 spinlock_t lock;
+2-2
drivers/net/wireless/iwlwifi/mvm/time-event.c
···312312 ARRAY_SIZE(time_event_response),313313 iwl_mvm_time_event_response, te_data);314314315315- ret = iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, CMD_SYNC,315315+ ret = iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, 0,316316 sizeof(*te_cmd), te_cmd);317317 if (ret) {318318 IWL_ERR(mvm, "Couldn't send TIME_EVENT_CMD: %d\n", ret);···434434 cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color));435435436436 IWL_DEBUG_TE(mvm, "Removing TE 0x%x\n", le32_to_cpu(time_cmd.id));437437- ret = iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, CMD_SYNC,437437+ ret = iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, 0,438438 sizeof(time_cmd), &time_cmd);439439 if (WARN_ON(ret))440440 return;
···417417 splx->package.count != 2 ||418418 splx->package.elements[0].type != ACPI_TYPE_INTEGER ||419419 splx->package.elements[0].integer.value != 0) {420420- IWL_ERR(trans, "Unsupported splx structure");420420+ IWL_ERR(trans, "Unsupported splx structure\n");421421 return 0;422422 }423423···426426 limits->package.count < 2 ||427427 limits->package.elements[0].type != ACPI_TYPE_INTEGER ||428428 limits->package.elements[1].type != ACPI_TYPE_INTEGER) {429429- IWL_ERR(trans, "Invalid limits element");429429+ IWL_ERR(trans, "Invalid limits element\n");430430 return 0;431431 }432432433433 domain_type = &limits->package.elements[0];434434 power_limit = &limits->package.elements[1];435435 if (!(domain_type->integer.value & SPL_DOMAINTYPE_WIFI)) {436436- IWL_DEBUG_INFO(trans, "WiFi power is not limited");436436+ IWL_DEBUG_INFO(trans, "WiFi power is not limited\n");437437 return 0;438438 }439439···450450 pxsx_handle = ACPI_HANDLE(&pdev->dev);451451 if (!pxsx_handle) {452452 IWL_DEBUG_INFO(trans,453453- "Could not retrieve root port ACPI handle");453453+ "Could not retrieve root port ACPI handle\n");454454 return;455455 }456456457457 /* Get the method's handle */458458 status = acpi_get_handle(pxsx_handle, (acpi_string)SPL_METHOD, &handle);459459 if (ACPI_FAILURE(status)) {460460- IWL_DEBUG_INFO(trans, "SPL method not found");460460+ IWL_DEBUG_INFO(trans, "SPL method not found\n");461461 return;462462 }463463464464 /* Call SPLC with no arguments */465465 status = acpi_evaluate_object(handle, NULL, NULL, &splx);466466 if (ACPI_FAILURE(status)) {467467- IWL_ERR(trans, "SPLC invocation failed (0x%x)", status);467467+ IWL_ERR(trans, "SPLC invocation failed (0x%x)\n", status);468468 return;469469 }470470471471 trans->dflt_pwr_limit = splx_get_pwr_limit(trans, splx.pointer);472472- IWL_DEBUG_INFO(trans, "Default power limit set to %lld",472472+ IWL_DEBUG_INFO(trans, "Default power limit set to %lld\n",473473 trans->dflt_pwr_limit);474474 kfree(splx.pointer);475475}
+14-10
drivers/net/wireless/iwlwifi/pcie/internal.h
···117117/**118118 * iwl_queue_inc_wrap - increment queue index, wrap back to beginning119119 * @index -- current index120120- * @n_bd -- total number of entries in queue (must be power of 2)121120 */122122-static inline int iwl_queue_inc_wrap(int index, int n_bd)121121+static inline int iwl_queue_inc_wrap(int index)123122{124124- return ++index & (n_bd - 1);123123+ return ++index & (TFD_QUEUE_SIZE_MAX - 1);125124}126125127126/**128127 * iwl_queue_dec_wrap - decrement queue index, wrap back to end129128 * @index -- current index130130- * @n_bd -- total number of entries in queue (must be power of 2)131129 */132132-static inline int iwl_queue_dec_wrap(int index, int n_bd)130130+static inline int iwl_queue_dec_wrap(int index)133131{134134- return --index & (n_bd - 1);132132+ return --index & (TFD_QUEUE_SIZE_MAX - 1);135133}136134137135struct iwl_cmd_meta {···143145 *144146 * Contains common data for Rx and Tx queues.145147 *146146- * Note the difference between n_bd and n_window: the hardware147147- * always assumes 256 descriptors, so n_bd is always 256 (unless148148+ * Note the difference between TFD_QUEUE_SIZE_MAX and n_window: the hardware149149+ * always assumes 256 descriptors, so TFD_QUEUE_SIZE_MAX is always 256 (unless148150 * there might be HW changes in the future). For the normal TX149151 * queues, n_window, which is the size of the software queue data150152 * is also 256; however, for the command queue, n_window is only151153 * 32 since we don't need so many commands pending. Since the HW152152- * still uses 256 BDs for DMA though, n_bd stays 256. As a result,154154+ * still uses 256 BDs for DMA though, TFD_QUEUE_SIZE_MAX stays 256. As a result,153155 * the software buffers (in the variables @meta, @txb in struct154156 * iwl_txq) only have 32 entries, while the HW buffers (@tfds in155157 * the same struct) have 256.···160162 * data is a window overlayed over the HW queue.161163 */162164struct iwl_queue {163163- int n_bd; /* number of BDs in this queue */164165 int write_ptr; /* 1-st empty entry (index) host_w*/165166 int read_ptr; /* last used entry (index) host_r*/166167 /* use for monitoring and recovering the stuck queue */···369372void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,370373 struct sk_buff_head *skbs);371374void iwl_trans_pcie_tx_reset(struct iwl_trans *trans);375375+376376+static inline u16 iwl_pcie_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx)377377+{378378+ struct iwl_tfd_tb *tb = &tfd->tbs[idx];379379+380380+ return le16_to_cpu(tb->hi_n_len) >> 4;381381+}372382373383/*****************************************************374384* Error handling
···7373#include "iwl-csr.h"7474#include "iwl-prph.h"7575#include "iwl-agn-hw.h"7676+#include "iwl-fw-error-dump.h"7677#include "internal.h"77787879static u32 iwl_trans_pcie_read_shr(struct iwl_trans *trans, u32 reg)···454453{455454 int ret;456455 int t = 0;456456+ int iter;457457458458 IWL_DEBUG_INFO(trans, "iwl_trans_prepare_card_hw enter\n");459459···463461 if (ret >= 0)464462 return 0;465463466466- /* If HW is not ready, prepare the conditions to check again */467467- iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG,468468- CSR_HW_IF_CONFIG_REG_PREPARE);464464+ for (iter = 0; iter < 10; iter++) {465465+ /* If HW is not ready, prepare the conditions to check again */466466+ iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG,467467+ CSR_HW_IF_CONFIG_REG_PREPARE);469468470470- do {471471- ret = iwl_pcie_set_hw_ready(trans);472472- if (ret >= 0)473473- return 0;469469+ do {470470+ ret = iwl_pcie_set_hw_ready(trans);471471+ if (ret >= 0)472472+ return 0;474473475475- usleep_range(200, 1000);476476- t += 200;477477- } while (t < 150000);474474+ usleep_range(200, 1000);475475+ t += 200;476476+ } while (t < 150000);477477+ msleep(25);478478+ }479479+480480+ IWL_DEBUG_INFO(trans, "got NIC after %d iterations\n", iter);478481479482 return ret;480483}···13441337 IWL_ERR(trans,13451338 "Q %d is %sactive and mapped to fifo %d ra_tid 0x%04x [%d,%d]\n",13461339 cnt, active ? "" : "in", fifo, tbl_dw,13471347- iwl_read_prph(trans,13481348- SCD_QUEUE_RDPTR(cnt)) & (txq->q.n_bd - 1),13401340+ iwl_read_prph(trans, SCD_QUEUE_RDPTR(cnt)) &13411341+ (TFD_QUEUE_SIZE_MAX - 1),13491342 iwl_read_prph(trans, SCD_QUEUE_WRPTR(cnt)));13501343 }13511344···16761669 IWL_ERR(trans, "failed to create the trans debugfs entry\n");16771670 return -ENOMEM;16781671}16721672+16731673+static u32 iwl_trans_pcie_get_cmdlen(struct iwl_tfd *tfd)16741674+{16751675+ u32 cmdlen = 0;16761676+ int i;16771677+16781678+ for (i = 0; i < IWL_NUM_OF_TBS; i++)16791679+ cmdlen += iwl_pcie_tfd_tb_get_len(tfd, i);16801680+16811681+ return cmdlen;16821682+}16831683+16841684+static u32 iwl_trans_pcie_dump_data(struct iwl_trans *trans,16851685+ void *buf, u32 buflen)16861686+{16871687+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);16881688+ struct iwl_fw_error_dump_data *data;16891689+ struct iwl_txq *cmdq = &trans_pcie->txq[trans_pcie->cmd_queue];16901690+ struct iwl_fw_error_dump_txcmd *txcmd;16911691+ u32 len;16921692+ int i, ptr;16931693+16941694+ if (!buf)16951695+ return sizeof(*data) +16961696+ cmdq->q.n_window * (sizeof(*txcmd) +16971697+ TFD_MAX_PAYLOAD_SIZE);16981698+16991699+ len = 0;17001700+ data = buf;17011701+ data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_TXCMD);17021702+ txcmd = (void *)data->data;17031703+ spin_lock_bh(&cmdq->lock);17041704+ ptr = cmdq->q.write_ptr;17051705+ for (i = 0; i < cmdq->q.n_window; i++) {17061706+ u8 idx = get_cmd_index(&cmdq->q, ptr);17071707+ u32 caplen, cmdlen;17081708+17091709+ cmdlen = iwl_trans_pcie_get_cmdlen(&cmdq->tfds[ptr]);17101710+ caplen = min_t(u32, TFD_MAX_PAYLOAD_SIZE, cmdlen);17111711+17121712+ if (cmdlen) {17131713+ len += sizeof(*txcmd) + caplen;17141714+ txcmd->cmdlen = cpu_to_le32(cmdlen);17151715+ txcmd->caplen = cpu_to_le32(caplen);17161716+ memcpy(txcmd->data, cmdq->entries[idx].cmd, caplen);17171717+ txcmd = (void *)((u8 *)txcmd->data + caplen);17181718+ }17191719+17201720+ ptr = iwl_queue_dec_wrap(ptr);17211721+ }17221722+ spin_unlock_bh(&cmdq->lock);17231723+17241724+ data->len = cpu_to_le32(len);17251725+ return sizeof(*data) + len;17261726+}16791727#else16801728static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,16811729 struct dentry *dir)···17731711 .grab_nic_access = iwl_trans_pcie_grab_nic_access,17741712 .release_nic_access = iwl_trans_pcie_release_nic_access,17751713 .set_bits_mask = iwl_trans_pcie_set_bits_mask,17141714+17151715+#ifdef CONFIG_IWLWIFI_DEBUGFS17161716+ .dump_data = iwl_trans_pcie_dump_data,17171717+#endif17761718};1777171917781720struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
+70-71
drivers/net/wireless/iwlwifi/pcie/tx.c
···70707171 /*7272 * To avoid ambiguity between empty and completely full queues, there7373- * should always be less than q->n_bd elements in the queue.7474- * If q->n_window is smaller than q->n_bd, there is no need to reserve7575- * any queue entries for this purpose.7373+ * should always be less than TFD_QUEUE_SIZE_MAX elements in the queue.7474+ * If q->n_window is smaller than TFD_QUEUE_SIZE_MAX, there is no need7575+ * to reserve any queue entries for this purpose.7676 */7777- if (q->n_window < q->n_bd)7777+ if (q->n_window < TFD_QUEUE_SIZE_MAX)7878 max = q->n_window;7979 else8080- max = q->n_bd - 1;8080+ max = TFD_QUEUE_SIZE_MAX - 1;81818282 /*8383- * q->n_bd is a power of 2, so the following is equivalent to modulo by8484- * q->n_bd and is well defined for negative dividends.8383+ * TFD_QUEUE_SIZE_MAX is a power of 2, so the following is equivalent to8484+ * modulo by TFD_QUEUE_SIZE_MAX and is well defined.8585 */8686- used = (q->write_ptr - q->read_ptr) & (q->n_bd - 1);8686+ used = (q->write_ptr - q->read_ptr) & (TFD_QUEUE_SIZE_MAX - 1);87878888 if (WARN_ON(used > max))8989 return 0;···9494/*9595 * iwl_queue_init - Initialize queue's high/low-water and read/write indexes9696 */9797-static int iwl_queue_init(struct iwl_queue *q, int count, int slots_num, u32 id)9797+static int iwl_queue_init(struct iwl_queue *q, int slots_num, u32 id)9898{9999- q->n_bd = count;10099 q->n_window = slots_num;101100 q->id = id;102102-103103- /* count must be power-of-two size, otherwise iwl_queue_inc_wrap104104- * and iwl_queue_dec_wrap are broken. */105105- if (WARN_ON(!is_power_of_2(count)))106106- return -EINVAL;107101108102 /* slots_num must be power-of-two size, otherwise109103 * get_cmd_index is broken. */···191197 IWL_ERR(trans,192198 "Q %d is %sactive and mapped to fifo %d ra_tid 0x%04x [%d,%d]\n",193199 i, active ? "" : "in", fifo, tbl_dw,194194- iwl_read_prph(trans,195195- SCD_QUEUE_RDPTR(i)) & (txq->q.n_bd - 1),200200+ iwl_read_prph(trans, SCD_QUEUE_RDPTR(i)) &201201+ (TFD_QUEUE_SIZE_MAX - 1),196202 iwl_read_prph(trans, SCD_QUEUE_WRPTR(i)));197203 }198204199205 for (i = q->read_ptr; i != q->write_ptr;200200- i = iwl_queue_inc_wrap(i, q->n_bd))206206+ i = iwl_queue_inc_wrap(i))201207 IWL_ERR(trans, "scratch %d = 0x%08x\n", i,202208 le32_to_cpu(txq->scratchbufs[i].scratch));203209204204- iwl_write_prph(trans, DEVICE_SET_NMI_REG, 1);210210+ iwl_force_nmi(trans);205211}206212207213/*···332338 for (i = 0; i < trans->cfg->base_params->num_of_queues; i++) {333339 struct iwl_txq *txq = &trans_pcie->txq[i];334340335335- spin_lock(&txq->lock);341341+ spin_lock_bh(&txq->lock);336342 if (trans_pcie->txq[i].need_update) {337343 iwl_pcie_txq_inc_wr_ptr(trans, txq);338344 trans_pcie->txq[i].need_update = false;339345 }340340- spin_unlock(&txq->lock);346346+ spin_unlock_bh(&txq->lock);341347 }342348}343349···351357 ((dma_addr_t)(le16_to_cpu(tb->hi_n_len) & 0xF) << 16) << 16;352358353359 return addr;354354-}355355-356356-static inline u16 iwl_pcie_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx)357357-{358358- struct iwl_tfd_tb *tb = &tfd->tbs[idx];359359-360360- return le16_to_cpu(tb->hi_n_len) >> 4;361360}362361363362static inline void iwl_pcie_tfd_set_tb(struct iwl_tfd *tfd, u8 idx,···412425{413426 struct iwl_tfd *tfd_tmp = txq->tfds;414427415415- /* rd_ptr is bounded by n_bd and idx is bounded by n_window */428428+ /* rd_ptr is bounded by TFD_QUEUE_SIZE_MAX and429429+ * idx is bounded by n_window430430+ */416431 int rd_ptr = txq->q.read_ptr;417432 int idx = get_cmd_index(&txq->q, rd_ptr);418433419434 lockdep_assert_held(&txq->lock);420435421421- /* We have only q->n_window txq->entries, but we use q->n_bd tfds */436436+ /* We have only q->n_window txq->entries, but we use437437+ * TFD_QUEUE_SIZE_MAX tfds438438+ */422439 iwl_pcie_tfd_unmap(trans, &txq->entries[idx].meta, &tfd_tmp[rd_ptr]);423440424441 /* free SKB */···443452}444453445454static int iwl_pcie_txq_build_tfd(struct iwl_trans *trans, struct iwl_txq *txq,446446- dma_addr_t addr, u16 len, u8 reset)455455+ dma_addr_t addr, u16 len, bool reset)447456{448457 struct iwl_queue *q;449458 struct iwl_tfd *tfd, *tfd_tmp;···556565 BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));557566558567 /* Initialize queue's high/low-water marks, and head/tail indexes */559559- ret = iwl_queue_init(&txq->q, TFD_QUEUE_SIZE_MAX, slots_num,560560- txq_id);568568+ ret = iwl_queue_init(&txq->q, slots_num, txq_id);561569 if (ret)562570 return ret;563571···581591 struct iwl_txq *txq = &trans_pcie->txq[txq_id];582592 struct iwl_queue *q = &txq->q;583593584584- if (!q->n_bd)585585- return;586586-587594 spin_lock_bh(&txq->lock);588595 while (q->write_ptr != q->read_ptr) {589596 IWL_DEBUG_TX_REPLY(trans, "Q %d Free %d\n",590597 txq_id, q->read_ptr);591598 iwl_pcie_txq_free_tfd(trans, txq);592592- q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);599599+ q->read_ptr = iwl_queue_inc_wrap(q->read_ptr);593600 }594601 txq->active = false;595602 spin_unlock_bh(&txq->lock);···623636 }624637625638 /* De-alloc circular buffer of TFDs */626626- if (txq->q.n_bd) {627627- dma_free_coherent(dev, sizeof(struct iwl_tfd) *628628- txq->q.n_bd, txq->tfds, txq->q.dma_addr);639639+ if (txq->tfds) {640640+ dma_free_coherent(dev,641641+ sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX,642642+ txq->tfds, txq->q.dma_addr);629643 txq->q.dma_addr = 0;644644+ txq->tfds = NULL;630645631646 dma_free_coherent(dev,632647 sizeof(*txq->scratchbufs) * txq->q.n_window,···937948{938949 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);939950 struct iwl_txq *txq = &trans_pcie->txq[txq_id];940940- /* n_bd is usually 256 => n_bd - 1 = 0xff */941941- int tfd_num = ssn & (txq->q.n_bd - 1);951951+ int tfd_num = ssn & (TFD_QUEUE_SIZE_MAX - 1);942952 struct iwl_queue *q = &txq->q;943953 int last_to_free;944954···961973962974 /*Since we free until index _not_ inclusive, the one before index is963975 * the last we will free. This one must be used */964964- last_to_free = iwl_queue_dec_wrap(tfd_num, q->n_bd);976976+ last_to_free = iwl_queue_dec_wrap(tfd_num);965977966978 if (!iwl_queue_used(q, last_to_free)) {967979 IWL_ERR(trans,968980 "%s: Read index for DMA queue txq id (%d), last_to_free %d is out of range [0-%d] %d %d.\n",969969- __func__, txq_id, last_to_free, q->n_bd,981981+ __func__, txq_id, last_to_free, TFD_QUEUE_SIZE_MAX,970982 q->write_ptr, q->read_ptr);971983 goto out;972984 }···976988977989 for (;978990 q->read_ptr != tfd_num;979979- q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {991991+ q->read_ptr = iwl_queue_inc_wrap(q->read_ptr)) {980992981993 if (WARN_ON_ONCE(txq->entries[txq->q.read_ptr].skb == NULL))982994 continue;···1015102710161028 lockdep_assert_held(&txq->lock);1017102910181018- if ((idx >= q->n_bd) || (!iwl_queue_used(q, idx))) {10301030+ if ((idx >= TFD_QUEUE_SIZE_MAX) || (!iwl_queue_used(q, idx))) {10191031 IWL_ERR(trans,10201032 "%s: Read index for DMA queue txq id (%d), index %d is out of range [0-%d] %d %d.\n",10211021- __func__, txq_id, idx, q->n_bd,10331033+ __func__, txq_id, idx, TFD_QUEUE_SIZE_MAX,10221034 q->write_ptr, q->read_ptr);10231035 return;10241036 }1025103710261026- for (idx = iwl_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx;10271027- q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {10381038+ for (idx = iwl_queue_inc_wrap(idx); q->read_ptr != idx;10391039+ q->read_ptr = iwl_queue_inc_wrap(q->read_ptr)) {1028104010291041 if (nfreed++ > 0) {10301042 IWL_ERR(trans, "HCMD skipped: index (%d) %d %d\n",10311043 idx, q->write_ptr, q->read_ptr);10321032- iwl_write_prph(trans, DEVICE_SET_NMI_REG, 1);10441044+ iwl_force_nmi(trans);10331045 }10341046 }10351047···13151327 cmd_pos = offsetof(struct iwl_device_cmd, payload);13161328 copy_size = sizeof(out_cmd->hdr);13171329 for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) {13181318- int copy = 0;13301330+ int copy;1319133113201332 if (!cmd->len[i])13211333 continue;1322133413231323- /* need at least IWL_HCMD_SCRATCHBUF_SIZE copied */13351335+ /* copy everything if not nocopy/dup */13361336+ if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY |13371337+ IWL_HCMD_DFL_DUP))) {13381338+ copy = cmd->len[i];13391339+13401340+ memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], copy);13411341+ cmd_pos += copy;13421342+ copy_size += copy;13431343+ continue;13441344+ }13451345+13461346+ /*13471347+ * Otherwise we need at least IWL_HCMD_SCRATCHBUF_SIZE copied13481348+ * in total (for the scratchbuf handling), but copy up to what13491349+ * we can fit into the payload for debug dump purposes.13501350+ */13511351+ copy = min_t(int, TFD_MAX_PAYLOAD_SIZE - cmd_pos, cmd->len[i]);13521352+13531353+ memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], copy);13541354+ cmd_pos += copy;13551355+13561356+ /* However, treat copy_size the proper way, we need it below */13241357 if (copy_size < IWL_HCMD_SCRATCHBUF_SIZE) {13251358 copy = IWL_HCMD_SCRATCHBUF_SIZE - copy_size;1326135913271360 if (copy > cmd->len[i])13281361 copy = cmd->len[i];13291329- }13301330-13311331- /* copy everything if not nocopy/dup */13321332- if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY |13331333- IWL_HCMD_DFL_DUP)))13341334- copy = cmd->len[i];13351335-13361336- if (copy) {13371337- memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], copy);13381338- cmd_pos += copy;13391362 copy_size += copy;13401363 }13411364 }···13621363 memcpy(&txq->scratchbufs[q->write_ptr], &out_cmd->hdr, scratch_size);13631364 iwl_pcie_txq_build_tfd(trans, txq,13641365 iwl_pcie_get_scratchbuf_dma(txq, q->write_ptr),13651365- scratch_size, 1);13661366+ scratch_size, true);1366136713671368 /* map first command fragment, if any remains */13681369 if (copy_size > scratch_size) {···13781379 }1379138013801381 iwl_pcie_txq_build_tfd(trans, txq, phys_addr,13811381- copy_size - scratch_size, 0);13821382+ copy_size - scratch_size, false);13821383 }1383138413841385 /* map the remaining (adjusted) nocopy/dup fragments */···14011402 goto out;14021403 }1403140414041404- iwl_pcie_txq_build_tfd(trans, txq, phys_addr, cmdlen[i], 0);14051405+ iwl_pcie_txq_build_tfd(trans, txq, phys_addr, cmdlen[i], false);14051406 }1406140714071408 out_meta->flags = cmd->flags;···14441445 }1445144614461447 /* Increment and update queue's write index */14471447- q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);14481448+ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr);14481449 iwl_pcie_txq_inc_wr_ptr(trans, txq);1449145014501451 spin_unlock_irqrestore(&trans_pcie->reg_lock, flags);···16001601 get_cmd_string(trans_pcie, cmd->id));16011602 ret = -ETIMEDOUT;1602160316031603- iwl_write_prph(trans, DEVICE_SET_NMI_REG, 1);16041604+ iwl_force_nmi(trans);16041605 iwl_trans_fw_error(trans);1605160616061607 goto cancel;···17391740 memcpy(&txq->scratchbufs[q->write_ptr], &dev_cmd->hdr,17401741 IWL_HCMD_SCRATCHBUF_SIZE);17411742 iwl_pcie_txq_build_tfd(trans, txq, tb0_phys,17421742- IWL_HCMD_SCRATCHBUF_SIZE, 1);17431743+ IWL_HCMD_SCRATCHBUF_SIZE, true);1743174417441745 /* there must be data left over for TB1 or this code must be changed */17451746 BUILD_BUG_ON(sizeof(struct iwl_tx_cmd) < IWL_HCMD_SCRATCHBUF_SIZE);···17491750 tb1_phys = dma_map_single(trans->dev, tb1_addr, tb1_len, DMA_TO_DEVICE);17501751 if (unlikely(dma_mapping_error(trans->dev, tb1_phys)))17511752 goto out_err;17521752- iwl_pcie_txq_build_tfd(trans, txq, tb1_phys, tb1_len, 0);17531753+ iwl_pcie_txq_build_tfd(trans, txq, tb1_phys, tb1_len, false);1753175417541755 /*17551756 * Set up TFD's third entry to point directly to remainder···17651766 &txq->tfds[q->write_ptr]);17661767 goto out_err;17671768 }17681768- iwl_pcie_txq_build_tfd(trans, txq, tb2_phys, tb2_len, 0);17691769+ iwl_pcie_txq_build_tfd(trans, txq, tb2_phys, tb2_len, false);17691770 }1770177117711772 /* Set up entry for this TFD in Tx byte-count array */···17871788 mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout);1788178917891790 /* Tell device the write index *just past* this latest filled TFD */17901790- q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);17911791+ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr);17911792 if (!wait_write_ptr)17921793 iwl_pcie_txq_inc_wr_ptr(trans, txq);17931794
+3-4
drivers/net/wireless/libertas/cfg.c
···10061006} __packed;1007100710081008static int lbs_set_key_material(struct lbs_private *priv,10091009- int key_type,10101010- int key_info,10111011- u8 *key, u16 key_len)10091009+ int key_type, int key_info,10101010+ const u8 *key, u16 key_len)10121011{10131012 struct cmd_key_material cmd;10141013 int ret;···16091610 */1610161116111612static int lbs_cfg_get_station(struct wiphy *wiphy, struct net_device *dev,16121612- u8 *mac, struct station_info *sinfo)16131613+ const u8 *mac, struct station_info *sinfo)16131614{16141615 struct lbs_private *priv = wiphy_priv(wiphy);16151616 s8 signal, noise;
+2-1
drivers/net/wireless/libertas/defs.h
···9090#define lbs_deb_cfg80211(fmt, args...) LBS_DEB_LL(LBS_DEB_CFG80211, " cfg80211", fmt, ##args)91919292#ifdef DEBUG9393-static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, int len)9393+static inline void lbs_deb_hex(unsigned int grp, const char *prompt,9494+ const u8 *buf, int len)9495{9596 int i = 0;9697
+5-3
drivers/net/wireless/libertas/rx.c
···71717272 skb->ip_summed = CHECKSUM_NONE;73737474- if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR)7575- return process_rxed_802_11_packet(priv, skb);7474+ if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) {7575+ ret = process_rxed_802_11_packet(priv, skb);7676+ goto done;7777+ }76787779 p_rx_pd = (struct rxpd *) skb->data;7880 p_rx_pkt = (struct rxpackethdr *) ((u8 *)p_rx_pd +···8886 if (skb->len < (ETH_HLEN + 8 + sizeof(struct rxpd))) {8987 lbs_deb_rx("rx err: frame received with bad length\n");9088 dev->stats.rx_length_errors++;9191- ret = 0;8989+ ret = -EINVAL;9290 dev_kfree_skb(skb);9391 goto done;9492 }
+42
drivers/net/wireless/mwifiex/11n.c
···749749750750 return;751751}752752+753753+u8 mwifiex_get_sec_chan_offset(int chan)754754+{755755+ u8 sec_offset;756756+757757+ switch (chan) {758758+ case 36:759759+ case 44:760760+ case 52:761761+ case 60:762762+ case 100:763763+ case 108:764764+ case 116:765765+ case 124:766766+ case 132:767767+ case 140:768768+ case 149:769769+ case 157:770770+ sec_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;771771+ break;772772+ case 40:773773+ case 48:774774+ case 56:775775+ case 64:776776+ case 104:777777+ case 112:778778+ case 120:779779+ case 128:780780+ case 136:781781+ case 144:782782+ case 153:783783+ case 161:784784+ sec_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW;785785+ break;786786+ case 165:787787+ default:788788+ sec_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;789789+ break;790790+ }791791+792792+ return sec_offset;793793+}
···10711071 * is mapped to PCI device memory. Tx ring pointers are advanced accordingly.10721072 * Download ready interrupt to FW is deffered if Tx ring is not full and10731073 * additional payload can be accomodated.10741074+ * Caller must ensure tx_param parameter to this function is not NULL.10741075 */10751076static int10761077mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb,
+5-1
drivers/net/wireless/mwifiex/sdio.c
···16781678 if (ret) {16791679 if (type == MWIFIEX_TYPE_CMD)16801680 adapter->cmd_sent = false;16811681- if (type == MWIFIEX_TYPE_DATA)16811681+ if (type == MWIFIEX_TYPE_DATA) {16821682 adapter->data_sent = false;16831683+ /* restore curr_wr_port in error cases */16841684+ card->curr_wr_port = port;16851685+ card->mp_wr_bitmap |= (u32)(1 << card->curr_wr_port);16861686+ }16831687 } else {16841688 if (type == MWIFIEX_TYPE_DATA) {16851689 if (!(card->mp_wr_bitmap & (1 << card->curr_wr_port)))
···865865866866 switch (action) {867867 case ACT_TDLS_DELETE:868868- if (reason)869869- dev_err(priv->adapter->dev,870870- "TDLS link delete for %pM failed: reason %d\n",871871- cmd_tdls_oper->peer_mac, reason);872872- else868868+ if (reason) {869869+ if (!node || reason == TDLS_ERR_LINK_NONEXISTENT)870870+ dev_dbg(priv->adapter->dev,871871+ "TDLS link delete for %pM failed: reason %d\n",872872+ cmd_tdls_oper->peer_mac, reason);873873+ else874874+ dev_err(priv->adapter->dev,875875+ "TDLS link delete for %pM failed: reason %d\n",876876+ cmd_tdls_oper->peer_mac, reason);877877+ } else {873878 dev_dbg(priv->adapter->dev,874874- "TDLS link config for %pM successful\n",879879+ "TDLS link delete for %pM successful\n",875880 cmd_tdls_oper->peer_mac);881881+ }876882 break;877883 case ACT_TDLS_CREATE:878884 if (reason) {
+44
drivers/net/wireless/mwifiex/sta_event.c
···134134 netif_carrier_off(priv->netdev);135135}136136137137+static int mwifiex_parse_tdls_event(struct mwifiex_private *priv,138138+ struct sk_buff *event_skb)139139+{140140+ int ret = 0;141141+ struct mwifiex_adapter *adapter = priv->adapter;142142+ struct mwifiex_sta_node *sta_ptr;143143+ struct mwifiex_tdls_generic_event *tdls_evt =144144+ (void *)event_skb->data + sizeof(adapter->event_cause);145145+146146+ /* reserved 2 bytes are not mandatory in tdls event */147147+ if (event_skb->len < (sizeof(struct mwifiex_tdls_generic_event) -148148+ sizeof(u16) - sizeof(adapter->event_cause))) {149149+ dev_err(adapter->dev, "Invalid event length!\n");150150+ return -1;151151+ }152152+153153+ sta_ptr = mwifiex_get_sta_entry(priv, tdls_evt->peer_mac);154154+ if (!sta_ptr) {155155+ dev_err(adapter->dev, "cannot get sta entry!\n");156156+ return -1;157157+ }158158+159159+ switch (le16_to_cpu(tdls_evt->type)) {160160+ case TDLS_EVENT_LINK_TEAR_DOWN:161161+ cfg80211_tdls_oper_request(priv->netdev,162162+ tdls_evt->peer_mac,163163+ NL80211_TDLS_TEARDOWN,164164+ le16_to_cpu(tdls_evt->u.reason_code),165165+ GFP_KERNEL);166166+ ret = mwifiex_tdls_oper(priv, tdls_evt->peer_mac,167167+ MWIFIEX_TDLS_DISABLE_LINK);168168+ queue_work(adapter->workqueue, &adapter->main_work);169169+ break;170170+ default:171171+ break;172172+ }173173+174174+ return ret;175175+}176176+137177/*138178 * This function handles events generated by firmware.139179 *···497457 HostCmd_ACT_GEN_SET, 0,498458 priv->curr_bss_params.bss_descriptor.mac_address,499459 false);460460+ break;461461+462462+ case EVENT_TDLS_GENERIC_EVENT:463463+ ret = mwifiex_parse_tdls_event(priv, adapter->event_skb);500464 break;501465502466 default:
+14-2
drivers/net/wireless/mwifiex/sta_rx.c
···183183 struct rx_packet_hdr *rx_pkt_hdr;184184 u8 ta[ETH_ALEN];185185 u16 rx_pkt_type, rx_pkt_offset, rx_pkt_length, seq_num;186186+ struct mwifiex_sta_node *sta_ptr;186187187188 local_rx_pd = (struct rxpd *) (skb->data);188189 rx_pkt_type = le16_to_cpu(local_rx_pd->rx_pkt_type);···214213 * If the packet is not an unicast packet then send the packet215214 * directly to os. Don't pass thru rx reordering216215 */217217- if (!IS_11N_ENABLED(priv) ||216216+ if ((!IS_11N_ENABLED(priv) &&217217+ !(ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&218218+ !(local_rx_pd->flags & MWIFIEX_RXPD_FLAGS_TDLS_PACKET))) ||218219 !ether_addr_equal_unaligned(priv->curr_addr, rx_pkt_hdr->eth803_hdr.h_dest)) {219220 mwifiex_process_rx_packet(priv, skb);220221 return ret;221222 }222223223223- if (mwifiex_queuing_ra_based(priv)) {224224+ if (mwifiex_queuing_ra_based(priv) ||225225+ (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&226226+ local_rx_pd->flags & MWIFIEX_RXPD_FLAGS_TDLS_PACKET)) {224227 memcpy(ta, rx_pkt_hdr->eth803_hdr.h_source, ETH_ALEN);228228+ if (local_rx_pd->flags & MWIFIEX_RXPD_FLAGS_TDLS_PACKET &&229229+ local_rx_pd->priority < MAX_NUM_TID) {230230+ sta_ptr = mwifiex_get_sta_entry(priv, ta);231231+ if (sta_ptr)232232+ sta_ptr->rx_seq[local_rx_pd->priority] =233233+ le16_to_cpu(local_rx_pd->seq_num);234234+ }225235 } else {226236 if (rx_pkt_type != PKT_TYPE_BAR)227237 priv->rx_seq[local_rx_pd->priority] = seq_num;
···259259 * NULL is returned if station entry is not found in associated STA list.260260 */261261struct mwifiex_sta_node *262262-mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac)262262+mwifiex_get_sta_entry(struct mwifiex_private *priv, const u8 *mac)263263{264264 struct mwifiex_sta_node *node;265265···280280 * If received mac address is NULL, NULL is returned.281281 */282282struct mwifiex_sta_node *283283-mwifiex_add_sta_entry(struct mwifiex_private *priv, u8 *mac)283283+mwifiex_add_sta_entry(struct mwifiex_private *priv, const u8 *mac)284284{285285 struct mwifiex_sta_node *node;286286 unsigned long flags;···332332}333333334334/* This function will delete a station entry from station list */335335-void mwifiex_del_sta_entry(struct mwifiex_private *priv, u8 *mac)335335+void mwifiex_del_sta_entry(struct mwifiex_private *priv, const u8 *mac)336336{337337 struct mwifiex_sta_node *node;338338 unsigned long flags;
+6-6
drivers/net/wireless/mwifiex/wmm.c
···9292 * The function also initializes the list with the provided RA.9393 */9494static struct mwifiex_ra_list_tbl *9595-mwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, u8 *ra)9595+mwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, const u8 *ra)9696{9797 struct mwifiex_ra_list_tbl *ra_list;9898···139139 * This function allocates and adds a RA list for all TIDs140140 * with the given RA.141141 */142142-void143143-mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra)142142+void mwifiex_ralist_add(struct mwifiex_private *priv, const u8 *ra)144143{145144 int i;146145 struct mwifiex_ra_list_tbl *ra_list;···565566 */566567static struct mwifiex_ra_list_tbl *567568mwifiex_wmm_get_ralist_node(struct mwifiex_private *priv, u8 tid,568568- u8 *ra_addr)569569+ const u8 *ra_addr)569570{570571 struct mwifiex_ra_list_tbl *ra_list;571572···586587 * retrieved.587588 */588589struct mwifiex_ra_list_tbl *589589-mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, u8 *ra_addr)590590+mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid,591591+ const u8 *ra_addr)590592{591593 struct mwifiex_ra_list_tbl *ra_list;592594···648648 if (ntohs(eth_hdr->h_proto) == ETH_P_TDLS)649649 dev_dbg(adapter->dev,650650 "TDLS setup packet for %pM. Don't block\n", ra);651651- else651651+ else if (memcmp(priv->cfg_bssid, ra, ETH_ALEN))652652 tdls_status = mwifiex_get_tdls_link_status(priv, ra);653653 }654654
···656656 case IEEE80211_AMPDU_TX_START:657657 common->vif_info[ii].seq_start = seq_no;658658 ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);659659+ status = 0;659660 break;660661661662 case IEEE80211_AMPDU_TX_STOP_CONT:
+6
drivers/net/wireless/rt2x00/rt2x00usb.c
···6868 }6969 }70707171+ /* If the port is powered down, we get a -EPROTO error, and this7272+ * leads to a endless loop. So just say that the device is gone.7373+ */7474+ if (status == -EPROTO)7575+ clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);7676+7177 rt2x00_err(rt2x00dev,7278 "Vendor Request 0x%02x failed for offset 0x%04x with error %d\n",7379 request, offset, status);
+12-5
drivers/net/wireless/rtl818x/rtl8180/dev.c
···284284 rx_status.band = dev->conf.chandef.chan->band;285285 rx_status.mactime = tsft;286286 rx_status.flag |= RX_FLAG_MACTIME_START;287287+ if (flags & RTL818X_RX_DESC_FLAG_SPLCP)288288+ rx_status.flag |= RX_FLAG_SHORTPRE;287289 if (flags & RTL818X_RX_DESC_FLAG_CRC32_ERR)288290 rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;289291···463461 RTL818X_TX_DESC_FLAG_NO_ENC;464462465463 rc_flags = info->control.rates[0].flags;464464+465465+ /* HW will perform RTS-CTS when only RTS flags is set.466466+ * HW will perform CTS-to-self when both RTS and CTS flags are set.467467+ * RTS rate and RTS duration will be used also for CTS-to-self.468468+ */466469 if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) {467470 tx_flags |= RTL818X_TX_DESC_FLAG_RTS;468471 tx_flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19;472472+ rts_duration = ieee80211_rts_duration(dev, priv->vif,473473+ skb->len, info);469474 } else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {470470- tx_flags |= RTL818X_TX_DESC_FLAG_CTS;475475+ tx_flags |= RTL818X_TX_DESC_FLAG_RTS | RTL818X_TX_DESC_FLAG_CTS;471476 tx_flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19;477477+ rts_duration = ieee80211_ctstoself_duration(dev, priv->vif,478478+ skb->len, info);472479 }473473-474474- if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS)475475- rts_duration = ieee80211_rts_duration(dev, priv->vif, skb->len,476476- info);477480478481 if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8180) {479482 unsigned int remainder;
+10-1
drivers/net/wireless/rtl818x/rtl8187/dev.c
···253253 flags |= ieee80211_get_tx_rate(dev, info)->hw_value << 24;254254 if (ieee80211_has_morefrags(tx_hdr->frame_control))255255 flags |= RTL818X_TX_DESC_FLAG_MOREFRAG;256256+257257+ /* HW will perform RTS-CTS when only RTS flags is set.258258+ * HW will perform CTS-to-self when both RTS and CTS flags are set.259259+ * RTS rate and RTS duration will be used also for CTS-to-self.260260+ */256261 if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) {257262 flags |= RTL818X_TX_DESC_FLAG_RTS;258263 flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19;259264 rts_dur = ieee80211_rts_duration(dev, priv->vif,260265 skb->len, info);261266 } else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {262262- flags |= RTL818X_TX_DESC_FLAG_CTS;267267+ flags |= RTL818X_TX_DESC_FLAG_RTS | RTL818X_TX_DESC_FLAG_CTS;263268 flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19;269269+ rts_dur = ieee80211_ctstoself_duration(dev, priv->vif,270270+ skb->len, info);264271 }265272266273 if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {···388381 rx_status.freq = dev->conf.chandef.chan->center_freq;389382 rx_status.band = dev->conf.chandef.chan->band;390383 rx_status.flag |= RX_FLAG_MACTIME_START;384384+ if (flags & RTL818X_RX_DESC_FLAG_SPLCP)385385+ rx_status.flag |= RX_FLAG_SHORTPRE;391386 if (flags & RTL818X_RX_DESC_FLAG_CRC32_ERR)392387 rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;393388 memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
···124124 return ret;125125 }126126127127- if (wl->vif && vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID) {127127+ if (vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID) {128128 wl1251_debug(DEBUG_EVENT, "SYNCHRONIZATION_TIMEOUT_EVENT");129129130130 /* indicate to the stack, that beacons have been lost */131131- ieee80211_beacon_loss(wl->vif);131131+ if (wl->vif && wl->vif->type == NL80211_IFTYPE_STATION)132132+ ieee80211_beacon_loss(wl->vif);132133 }133134134135 if (vector & REGAINED_BSS_EVENT_ID) {
+39-29
drivers/net/wireless/ti/wl1251/main.c
···550550 mutex_unlock(&wl->mutex);551551}552552553553+static int wl1251_build_null_data(struct wl1251 *wl)554554+{555555+ struct sk_buff *skb = NULL;556556+ int size;557557+ void *ptr;558558+ int ret = -ENOMEM;559559+560560+ if (wl->bss_type == BSS_TYPE_IBSS) {561561+ size = sizeof(struct wl12xx_null_data_template);562562+ ptr = NULL;563563+ } else {564564+ skb = ieee80211_nullfunc_get(wl->hw, wl->vif);565565+ if (!skb)566566+ goto out;567567+ size = skb->len;568568+ ptr = skb->data;569569+ }570570+571571+ ret = wl1251_cmd_template_set(wl, CMD_NULL_DATA, ptr, size);572572+573573+out:574574+ dev_kfree_skb(skb);575575+ if (ret)576576+ wl1251_warning("cmd buld null data failed: %d", ret);577577+578578+ return ret;579579+}580580+553581static int wl1251_build_qos_null_data(struct wl1251 *wl)554582{555583 struct ieee80211_qos_hdr template;···713685 goto out_sleep;714686715687 wl->power_level = conf->power_level;716716- }717717-718718- /*719719- * Tell stack that connection is lost because hw encryption isn't720720- * supported in monitor mode.721721- * This requires temporary enabling of the hw connection monitor flag722722- */723723- if ((changed & IEEE80211_CONF_CHANGE_MONITOR) && wl->vif) {724724- wl->hw->flags |= IEEE80211_HW_CONNECTION_MONITOR;725725- ieee80211_connection_loss(wl->vif);726688 }727689728690out_sleep:···11211103 wl->rssi_thold = bss_conf->cqm_rssi_thold;11221104 }1123110511241124- if (changed & BSS_CHANGED_BSSID) {11061106+ if ((changed & BSS_CHANGED_BSSID) &&11071107+ memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) {11251108 memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN);1126110911271127- skb = ieee80211_nullfunc_get(wl->hw, wl->vif);11281128- if (!skb)11291129- goto out_sleep;11101110+ if (!is_zero_ether_addr(wl->bssid)) {11111111+ ret = wl1251_build_null_data(wl);11121112+ if (ret < 0)11131113+ goto out_sleep;1130111411311131- ret = wl1251_cmd_template_set(wl, CMD_NULL_DATA,11321132- skb->data, skb->len);11331133- dev_kfree_skb(skb);11341134- if (ret < 0)11351135- goto out_sleep;11151115+ ret = wl1251_build_qos_null_data(wl);11161116+ if (ret < 0)11171117+ goto out_sleep;1136111811371137- ret = wl1251_build_qos_null_data(wl);11381138- if (ret < 0)11391139- goto out;11401140-11411141- if (wl->bss_type != BSS_TYPE_IBSS) {11421119 ret = wl1251_join(wl, wl->bss_type, wl->channel,11431120 wl->beacon_int, wl->dtim_period);11441121 if (ret < 0)···11421129 }1143113011441131 if (changed & BSS_CHANGED_ASSOC) {11451145- /* Disable temporary enabled hw connection monitor flag */11461146- wl->hw->flags &= ~IEEE80211_HW_CONNECTION_MONITOR;11471147-11481132 if (bss_conf->assoc) {11491133 wl->beacon_int = bss_conf->beacon_int;11501134···12261216 if (ret < 0)12271217 goto out_sleep;1228121812291229- ret = wl1251_join(wl, wl->bss_type, wl->beacon_int,12301230- wl->channel, wl->dtim_period);12191219+ ret = wl1251_join(wl, wl->bss_type, wl->channel,12201220+ wl->beacon_int, wl->dtim_period);1231122112321222 if (ret < 0)12331223 goto out_sleep;
···2222#include <linux/module.h>2323#include <linux/i2c.h>2424#include <linux/gpio.h>2525+#include <linux/of_gpio.h>2626+#include <linux/of_irq.h>2527#include <linux/miscdevice.h>2628#include <linux/interrupt.h>2729#include <linux/delay.h>···859857 }860858}861859860860+#ifdef CONFIG_OF861861+862862+static int pn544_hci_i2c_of_request_resources(struct i2c_client *client)863863+{864864+ struct pn544_i2c_phy *phy = i2c_get_clientdata(client);865865+ struct device_node *pp;866866+ int ret;867867+868868+ pp = client->dev.of_node;869869+ if (!pp) {870870+ ret = -ENODEV;871871+ goto err_dt;872872+ }873873+874874+ /* Obtention of EN GPIO from device tree */875875+ ret = of_get_named_gpio(pp, "enable-gpios", 0);876876+ if (ret < 0) {877877+ if (ret != -EPROBE_DEFER)878878+ nfc_err(&client->dev,879879+ "Failed to get EN gpio, error: %d\n", ret);880880+ goto err_dt;881881+ }882882+ phy->gpio_en = ret;883883+884884+ /* Configuration of EN GPIO */885885+ ret = gpio_request(phy->gpio_en, "pn544_en");886886+ if (ret) {887887+ nfc_err(&client->dev, "Fail EN pin\n");888888+ goto err_dt;889889+ }890890+ ret = gpio_direction_output(phy->gpio_en, 0);891891+ if (ret) {892892+ nfc_err(&client->dev, "Fail EN pin direction\n");893893+ goto err_gpio_en;894894+ }895895+896896+ /* Obtention of FW GPIO from device tree */897897+ ret = of_get_named_gpio(pp, "firmware-gpios", 0);898898+ if (ret < 0) {899899+ if (ret != -EPROBE_DEFER)900900+ nfc_err(&client->dev,901901+ "Failed to get FW gpio, error: %d\n", ret);902902+ goto err_gpio_en;903903+ }904904+ phy->gpio_fw = ret;905905+906906+ /* Configuration of FW GPIO */907907+ ret = gpio_request(phy->gpio_fw, "pn544_fw");908908+ if (ret) {909909+ nfc_err(&client->dev, "Fail FW pin\n");910910+ goto err_gpio_en;911911+ }912912+ ret = gpio_direction_output(phy->gpio_fw, 0);913913+ if (ret) {914914+ nfc_err(&client->dev, "Fail FW pin direction\n");915915+ goto err_gpio_fw;916916+ }917917+918918+ /* IRQ */919919+ ret = irq_of_parse_and_map(pp, 0);920920+ if (ret < 0) {921921+ nfc_err(&client->dev,922922+ "Unable to get irq, error: %d\n", ret);923923+ goto err_gpio_fw;924924+ }925925+ client->irq = ret;926926+927927+ return 0;928928+929929+err_gpio_fw:930930+ gpio_free(phy->gpio_fw);931931+err_gpio_en:932932+ gpio_free(phy->gpio_en);933933+err_dt:934934+ return ret;935935+}936936+937937+#else938938+939939+static int pn544_hci_i2c_of_request_resources(struct i2c_client *client)940940+{941941+ return -ENODEV;942942+}943943+944944+#endif945945+862946static int pn544_hci_i2c_probe(struct i2c_client *client,863947 const struct i2c_device_id *id)864948{···975887 i2c_set_clientdata(client, phy);976888977889 pdata = client->dev.platform_data;978978- if (pdata == NULL) {890890+891891+ /* No platform data, using device tree. */892892+ if (!pdata && client->dev.of_node) {893893+ r = pn544_hci_i2c_of_request_resources(client);894894+ if (r) {895895+ nfc_err(&client->dev, "No DT data\n");896896+ return r;897897+ }898898+ /* Using platform data. */899899+ } else if (pdata) {900900+901901+ if (pdata->request_resources == NULL) {902902+ nfc_err(&client->dev, "request_resources() missing\n");903903+ return -EINVAL;904904+ }905905+906906+ r = pdata->request_resources(client);907907+ if (r) {908908+ nfc_err(&client->dev,909909+ "Cannot get platform resources\n");910910+ return r;911911+ }912912+913913+ phy->gpio_en = pdata->get_gpio(NFC_GPIO_ENABLE);914914+ phy->gpio_fw = pdata->get_gpio(NFC_GPIO_FW_RESET);915915+ phy->gpio_irq = pdata->get_gpio(NFC_GPIO_IRQ);916916+ } else {979917 nfc_err(&client->dev, "No platform data\n");980918 return -EINVAL;981919 }982982-983983- if (pdata->request_resources == NULL) {984984- nfc_err(&client->dev, "request_resources() missing\n");985985- return -EINVAL;986986- }987987-988988- r = pdata->request_resources(client);989989- if (r) {990990- nfc_err(&client->dev, "Cannot get platform resources\n");991991- return r;992992- }993993-994994- phy->gpio_en = pdata->get_gpio(NFC_GPIO_ENABLE);995995- phy->gpio_fw = pdata->get_gpio(NFC_GPIO_FW_RESET);996996- phy->gpio_irq = pdata->get_gpio(NFC_GPIO_IRQ);997920998921 pn544_hci_i2c_platform_init(phy);999922···1029930 free_irq(client->irq, phy);10309311031932err_rti:10321032- if (pdata->free_resources != NULL)933933+ if (!pdata) {934934+ gpio_free(phy->gpio_en);935935+ gpio_free(phy->gpio_fw);936936+ } else if (pdata->free_resources) {1033937 pdata->free_resources();938938+ }10349391035940 return r;1036941}···1056953 pn544_hci_i2c_disable(phy);10579541058955 free_irq(client->irq, phy);10591059- if (pdata->free_resources)956956+957957+ /* No platform data, GPIOs have been requested by this driver */958958+ if (!pdata) {959959+ gpio_free(phy->gpio_en);960960+ gpio_free(phy->gpio_fw);961961+ /* Using platform data */962962+ } else if (pdata->free_resources) {1060963 pdata->free_resources();964964+ }10619651062966 return 0;1063967}1064968969969+static const struct of_device_id of_pn544_i2c_match[] = {970970+ { .compatible = "nxp,pn544-i2c", },971971+ {},972972+};973973+MODULE_DEVICE_TABLE(of, of_pn544_i2c_match);974974+1065975static struct i2c_driver pn544_hci_i2c_driver = {1066976 .driver = {1067977 .name = PN544_HCI_I2C_DRIVER_NAME,978978+ .owner = THIS_MODULE,979979+ .of_match_table = of_match_ptr(of_pn544_i2c_match),1068980 },1069981 .probe = pn544_hci_i2c_probe,1070982 .id_table = pn544_hci_i2c_id_table,
+23
drivers/nfc/st21nfca/Kconfig
···11+config NFC_ST21NFCA22+ tristate "STMicroelectronics ST21NFCA NFC driver"33+ depends on NFC_HCI44+ select CRC_CCITT55+ default n66+ ---help---77+ STMicroelectronics ST21NFCA core driver. It implements the chipset88+ HCI logic and hooks into the NFC kernel APIs. Physical layers will99+ register against it.1010+1111+ To compile this driver as a module, choose m here. The module will1212+ be called st21nfca.1313+ Say N if unsure.1414+1515+config NFC_ST21NFCA_I2C1616+ tristate "NFC ST21NFCA i2c support"1717+ depends on NFC_ST21NFCA && I2C && NFC_SHDLC1818+ ---help---1919+ This module adds support for the STMicroelectronics st21nfca i2c interface.2020+ Select this if your platform is using the i2c bus.2121+2222+ If you choose to build a module, it'll be called st21nfca_i2c.2323+ Say N if unsure.
+8
drivers/nfc/st21nfca/Makefile
···11+#22+# Makefile for ST21NFCA HCI based NFC driver33+#44+55+st21nfca_i2c-objs = i2c.o66+77+obj-$(CONFIG_NFC_ST21NFCA) += st21nfca.o88+obj-$(CONFIG_NFC_ST21NFCA_I2C) += st21nfca_i2c.o
+724
drivers/nfc/st21nfca/i2c.c
···11+/*22+ * I2C Link Layer for ST21NFCA HCI based Driver33+ * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved.44+ *55+ * This program is free software; you can redistribute it and/or modify it66+ * under the terms and conditions of the GNU General Public License,77+ * version 2, as published by the Free Software Foundation.88+ *99+ * This program is distributed in the hope that it will be useful,1010+ * but WITHOUT ANY WARRANTY; without even the implied warranty of1111+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1212+ * GNU General Public License for more details.1313+ *1414+ * You should have received a copy of the GNU General Public License1515+ * along with this program; if not, see <http://www.gnu.org/licenses/>.1616+ */1717+1818+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt1919+2020+#include <linux/crc-ccitt.h>2121+#include <linux/module.h>2222+#include <linux/i2c.h>2323+#include <linux/gpio.h>2424+#include <linux/of_irq.h>2525+#include <linux/of_gpio.h>2626+#include <linux/miscdevice.h>2727+#include <linux/interrupt.h>2828+#include <linux/delay.h>2929+#include <linux/nfc.h>3030+#include <linux/firmware.h>3131+#include <linux/unaligned/access_ok.h>3232+#include <linux/platform_data/st21nfca.h>3333+3434+#include <net/nfc/hci.h>3535+#include <net/nfc/llc.h>3636+#include <net/nfc/nfc.h>3737+3838+#include "st21nfca.h"3939+4040+/*4141+ * Every frame starts with ST21NFCA_SOF_EOF and ends with ST21NFCA_SOF_EOF.4242+ * Because ST21NFCA_SOF_EOF is a possible data value, there is a mecanism4343+ * called byte stuffing has been introduced.4444+ *4545+ * if byte == ST21NFCA_SOF_EOF or ST21NFCA_ESCAPE_BYTE_STUFFING4646+ * - insert ST21NFCA_ESCAPE_BYTE_STUFFING (escape byte)4747+ * - xor byte with ST21NFCA_BYTE_STUFFING_MASK4848+ */4949+#define ST21NFCA_SOF_EOF 0x7e5050+#define ST21NFCA_BYTE_STUFFING_MASK 0x205151+#define ST21NFCA_ESCAPE_BYTE_STUFFING 0x7d5252+5353+/* SOF + 00 */5454+#define ST21NFCA_FRAME_HEADROOM 25555+5656+/* 2 bytes crc + EOF */5757+#define ST21NFCA_FRAME_TAILROOM 35858+#define IS_START_OF_FRAME(buf) (buf[0] == ST21NFCA_SOF_EOF && \5959+ buf[1] == 0)6060+6161+#define ST21NFCA_HCI_I2C_DRIVER_NAME "st21nfca_hci_i2c"6262+6363+static struct i2c_device_id st21nfca_hci_i2c_id_table[] = {6464+ {ST21NFCA_HCI_DRIVER_NAME, 0},6565+ {}6666+};6767+6868+MODULE_DEVICE_TABLE(i2c, st21nfca_hci_i2c_id_table);6969+7070+struct st21nfca_i2c_phy {7171+ struct i2c_client *i2c_dev;7272+ struct nfc_hci_dev *hdev;7373+7474+ unsigned int gpio_ena;7575+ unsigned int gpio_irq;7676+ unsigned int irq_polarity;7777+7878+ struct sk_buff *pending_skb;7979+ int current_read_len;8080+ /*8181+ * crc might have fail because i2c macro8282+ * is disable due to other interface activity8383+ */8484+ int crc_trials;8585+8686+ int powered;8787+ int run_mode;8888+8989+ /*9090+ * < 0 if hardware error occured (e.g. i2c err)9191+ * and prevents normal operation.9292+ */9393+ int hard_fault;9494+ struct mutex phy_lock;9595+};9696+static u8 len_seq[] = { 13, 24, 15, 29 };9797+static u16 wait_tab[] = { 2, 3, 5, 15, 20, 40};9898+9999+#define I2C_DUMP_SKB(info, skb) \100100+do { \101101+ pr_debug("%s:\n", info); \102102+ print_hex_dump(KERN_DEBUG, "i2c: ", DUMP_PREFIX_OFFSET, \103103+ 16, 1, (skb)->data, (skb)->len, 0); \104104+} while (0)105105+106106+/*107107+ * In order to get the CLF in a known state we generate an internal reboot108108+ * using a proprietary command.109109+ * Once the reboot is completed, we expect to receive a ST21NFCA_SOF_EOF110110+ * fill buffer.111111+ */112112+static int st21nfca_hci_platform_init(struct st21nfca_i2c_phy *phy)113113+{114114+ u16 wait_reboot[] = { 50, 300, 1000 };115115+ char reboot_cmd[] = { 0x7E, 0x66, 0x48, 0xF6, 0x7E };116116+ u8 tmp[ST21NFCA_HCI_LLC_MAX_SIZE];117117+ int i, r = -1;118118+119119+ for (i = 0; i < ARRAY_SIZE(wait_reboot) && r < 0; i++) {120120+ r = i2c_master_send(phy->i2c_dev, reboot_cmd,121121+ sizeof(reboot_cmd));122122+ if (r < 0)123123+ msleep(wait_reboot[i]);124124+ }125125+ if (r < 0)126126+ return r;127127+128128+ /* CLF is spending about 20ms to do an internal reboot */129129+ msleep(20);130130+ r = -1;131131+ for (i = 0; i < ARRAY_SIZE(wait_reboot) && r < 0; i++) {132132+ r = i2c_master_recv(phy->i2c_dev, tmp,133133+ ST21NFCA_HCI_LLC_MAX_SIZE);134134+ if (r < 0)135135+ msleep(wait_reboot[i]);136136+ }137137+ if (r < 0)138138+ return r;139139+140140+ for (i = 0; i < ST21NFCA_HCI_LLC_MAX_SIZE &&141141+ tmp[i] == ST21NFCA_SOF_EOF; i++)142142+ ;143143+144144+ if (r != ST21NFCA_HCI_LLC_MAX_SIZE)145145+ return -ENODEV;146146+147147+ usleep_range(1000, 1500);148148+ return 0;149149+}150150+151151+static int st21nfca_hci_i2c_enable(void *phy_id)152152+{153153+ struct st21nfca_i2c_phy *phy = phy_id;154154+155155+ gpio_set_value(phy->gpio_ena, 1);156156+ phy->powered = 1;157157+ phy->run_mode = ST21NFCA_HCI_MODE;158158+159159+ usleep_range(10000, 15000);160160+161161+ return 0;162162+}163163+164164+static void st21nfca_hci_i2c_disable(void *phy_id)165165+{166166+ struct st21nfca_i2c_phy *phy = phy_id;167167+168168+ pr_info("\n");169169+ gpio_set_value(phy->gpio_ena, 0);170170+171171+ phy->powered = 0;172172+}173173+174174+static void st21nfca_hci_add_len_crc(struct sk_buff *skb)175175+{176176+ u16 crc;177177+ u8 tmp;178178+179179+ *skb_push(skb, 1) = 0;180180+181181+ crc = crc_ccitt(0xffff, skb->data, skb->len);182182+ crc = ~crc;183183+184184+ tmp = crc & 0x00ff;185185+ *skb_put(skb, 1) = tmp;186186+187187+ tmp = (crc >> 8) & 0x00ff;188188+ *skb_put(skb, 1) = tmp;189189+}190190+191191+static void st21nfca_hci_remove_len_crc(struct sk_buff *skb)192192+{193193+ skb_pull(skb, ST21NFCA_FRAME_HEADROOM);194194+ skb_trim(skb, skb->len - ST21NFCA_FRAME_TAILROOM);195195+}196196+197197+/*198198+ * Writing a frame must not return the number of written bytes.199199+ * It must return either zero for success, or <0 for error.200200+ * In addition, it must not alter the skb201201+ */202202+static int st21nfca_hci_i2c_write(void *phy_id, struct sk_buff *skb)203203+{204204+ int r = -1, i, j;205205+ struct st21nfca_i2c_phy *phy = phy_id;206206+ struct i2c_client *client = phy->i2c_dev;207207+ u8 tmp[ST21NFCA_HCI_LLC_MAX_SIZE * 2];208208+209209+ I2C_DUMP_SKB("st21nfca_hci_i2c_write", skb);210210+211211+212212+ if (phy->hard_fault != 0)213213+ return phy->hard_fault;214214+215215+ /*216216+ * Compute CRC before byte stuffing computation on frame217217+ * Note st21nfca_hci_add_len_crc is doing a byte stuffing218218+ * on its own value219219+ */220220+ st21nfca_hci_add_len_crc(skb);221221+222222+ /* add ST21NFCA_SOF_EOF on tail */223223+ *skb_put(skb, 1) = ST21NFCA_SOF_EOF;224224+ /* add ST21NFCA_SOF_EOF on head */225225+ *skb_push(skb, 1) = ST21NFCA_SOF_EOF;226226+227227+ /*228228+ * Compute byte stuffing229229+ * if byte == ST21NFCA_SOF_EOF or ST21NFCA_ESCAPE_BYTE_STUFFING230230+ * insert ST21NFCA_ESCAPE_BYTE_STUFFING (escape byte)231231+ * xor byte with ST21NFCA_BYTE_STUFFING_MASK232232+ */233233+ tmp[0] = skb->data[0];234234+ for (i = 1, j = 1; i < skb->len - 1; i++, j++) {235235+ if (skb->data[i] == ST21NFCA_SOF_EOF236236+ || skb->data[i] == ST21NFCA_ESCAPE_BYTE_STUFFING) {237237+ tmp[j] = ST21NFCA_ESCAPE_BYTE_STUFFING;238238+ j++;239239+ tmp[j] = skb->data[i] ^ ST21NFCA_BYTE_STUFFING_MASK;240240+ } else {241241+ tmp[j] = skb->data[i];242242+ }243243+ }244244+ tmp[j] = skb->data[i];245245+ j++;246246+247247+ /*248248+ * Manage sleep mode249249+ * Try 3 times to send data with delay between each250250+ */251251+ mutex_lock(&phy->phy_lock);252252+ for (i = 0; i < ARRAY_SIZE(wait_tab) && r < 0; i++) {253253+ r = i2c_master_send(client, tmp, j);254254+ if (r < 0)255255+ msleep(wait_tab[i]);256256+ }257257+ mutex_unlock(&phy->phy_lock);258258+259259+ if (r >= 0) {260260+ if (r != j)261261+ r = -EREMOTEIO;262262+ else263263+ r = 0;264264+ }265265+266266+ st21nfca_hci_remove_len_crc(skb);267267+268268+ return r;269269+}270270+271271+static int get_frame_size(u8 *buf, int buflen)272272+{273273+ int len = 0;274274+ if (buf[len + 1] == ST21NFCA_SOF_EOF)275275+ return 0;276276+277277+ for (len = 1; len < buflen && buf[len] != ST21NFCA_SOF_EOF; len++)278278+ ;279279+280280+ return len;281281+}282282+283283+static int check_crc(u8 *buf, int buflen)284284+{285285+ u16 crc;286286+287287+ crc = crc_ccitt(0xffff, buf, buflen - 2);288288+ crc = ~crc;289289+290290+ if (buf[buflen - 2] != (crc & 0xff) || buf[buflen - 1] != (crc >> 8)) {291291+ pr_err(ST21NFCA_HCI_DRIVER_NAME292292+ ": CRC error 0x%x != 0x%x 0x%x\n", crc, buf[buflen - 1],293293+ buf[buflen - 2]);294294+295295+ pr_info(DRIVER_DESC ": %s : BAD CRC\n", __func__);296296+ print_hex_dump(KERN_DEBUG, "crc: ", DUMP_PREFIX_NONE,297297+ 16, 2, buf, buflen, false);298298+ return -EPERM;299299+ }300300+ return 0;301301+}302302+303303+/*304304+ * Prepare received data for upper layer.305305+ * Received data include byte stuffing, crc and sof/eof306306+ * which is not usable by hci part.307307+ * returns:308308+ * frame size without sof/eof, header and byte stuffing309309+ * -EBADMSG : frame was incorrect and discarded310310+ */311311+static int st21nfca_hci_i2c_repack(struct sk_buff *skb)312312+{313313+ int i, j, r, size;314314+ if (skb->len < 1 || (skb->len > 1 && skb->data[1] != 0))315315+ return -EBADMSG;316316+317317+ size = get_frame_size(skb->data, skb->len);318318+ if (size > 0) {319319+ skb_trim(skb, size);320320+ /* remove ST21NFCA byte stuffing for upper layer */321321+ for (i = 1, j = 0; i < skb->len; i++) {322322+ if (skb->data[i + j] ==323323+ (u8) ST21NFCA_ESCAPE_BYTE_STUFFING) {324324+ skb->data[i] = skb->data[i + j + 1]325325+ | ST21NFCA_BYTE_STUFFING_MASK;326326+ i++;327327+ j++;328328+ }329329+ skb->data[i] = skb->data[i + j];330330+ }331331+ /* remove byte stuffing useless byte */332332+ skb_trim(skb, i - j);333333+ /* remove ST21NFCA_SOF_EOF from head */334334+ skb_pull(skb, 1);335335+336336+ r = check_crc(skb->data, skb->len);337337+ if (r != 0) {338338+ i = 0;339339+ return -EBADMSG;340340+ }341341+342342+ /* remove headbyte */343343+ skb_pull(skb, 1);344344+ /* remove crc. Byte Stuffing is already removed here */345345+ skb_trim(skb, skb->len - 2);346346+ return skb->len;347347+ }348348+ return 0;349349+}350350+351351+/*352352+ * Reads an shdlc frame and returns it in a newly allocated sk_buff. Guarantees353353+ * that i2c bus will be flushed and that next read will start on a new frame.354354+ * returned skb contains only LLC header and payload.355355+ * returns:356356+ * frame size : if received frame is complete (find ST21NFCA_SOF_EOF at357357+ * end of read)358358+ * -EAGAIN : if received frame is incomplete (not find ST21NFCA_SOF_EOF359359+ * at end of read)360360+ * -EREMOTEIO : i2c read error (fatal)361361+ * -EBADMSG : frame was incorrect and discarded362362+ * (value returned from st21nfca_hci_i2c_repack)363363+ * -EIO : if no ST21NFCA_SOF_EOF is found after reaching364364+ * the read length end sequence365365+ */366366+static int st21nfca_hci_i2c_read(struct st21nfca_i2c_phy *phy,367367+ struct sk_buff *skb)368368+{369369+ int r, i;370370+ u8 len;371371+ u8 buf[ST21NFCA_HCI_LLC_MAX_PAYLOAD];372372+ struct i2c_client *client = phy->i2c_dev;373373+374374+ if (phy->current_read_len < ARRAY_SIZE(len_seq)) {375375+ len = len_seq[phy->current_read_len];376376+377377+ /*378378+ * Add retry mecanism379379+ * Operation on I2C interface may fail in case of operation on380380+ * RF or SWP interface381381+ */382382+ r = 0;383383+ mutex_lock(&phy->phy_lock);384384+ for (i = 0; i < ARRAY_SIZE(wait_tab) && r <= 0; i++) {385385+ r = i2c_master_recv(client, buf, len);386386+ if (r < 0)387387+ msleep(wait_tab[i]);388388+ }389389+ mutex_unlock(&phy->phy_lock);390390+391391+ if (r != len) {392392+ phy->current_read_len = 0;393393+ return -EREMOTEIO;394394+ }395395+396396+ /*397397+ * The first read sequence does not start with SOF.398398+ * Data is corrupeted so we drop it.399399+ */400400+ if (!phy->current_read_len && buf[0] != ST21NFCA_SOF_EOF) {401401+ skb_trim(skb, 0);402402+ phy->current_read_len = 0;403403+ return -EIO;404404+ } else if (phy->current_read_len &&405405+ IS_START_OF_FRAME(buf)) {406406+ /*407407+ * Previous frame transmission was interrupted and408408+ * the frame got repeated.409409+ * Received frame start with ST21NFCA_SOF_EOF + 00.410410+ */411411+ skb_trim(skb, 0);412412+ phy->current_read_len = 0;413413+ }414414+415415+ memcpy(skb_put(skb, len), buf, len);416416+417417+ if (skb->data[skb->len - 1] == ST21NFCA_SOF_EOF) {418418+ phy->current_read_len = 0;419419+ return st21nfca_hci_i2c_repack(skb);420420+ }421421+ phy->current_read_len++;422422+ return -EAGAIN;423423+ }424424+ return -EIO;425425+}426426+427427+/*428428+ * Reads an shdlc frame from the chip. This is not as straightforward as it429429+ * seems. The frame format is data-crc, and corruption can occur anywhere430430+ * while transiting on i2c bus, such that we could read an invalid data.431431+ * The tricky case is when we read a corrupted data or crc. We must detect432432+ * this here in order to determine that data can be transmitted to the hci433433+ * core. This is the reason why we check the crc here.434434+ * The CLF will repeat a frame until we send a RR on that frame.435435+ *436436+ * On ST21NFCA, IRQ goes in idle when read starts. As no size information are437437+ * available in the incoming data, other IRQ might come. Every IRQ will trigger438438+ * a read sequence with different length and will fill the current frame.439439+ * The reception is complete once we reach a ST21NFCA_SOF_EOF.440440+ */441441+static irqreturn_t st21nfca_hci_irq_thread_fn(int irq, void *phy_id)442442+{443443+ struct st21nfca_i2c_phy *phy = phy_id;444444+ struct i2c_client *client;445445+446446+ int r;447447+448448+ if (!phy || irq != phy->i2c_dev->irq) {449449+ WARN_ON_ONCE(1);450450+ return IRQ_NONE;451451+ }452452+453453+ client = phy->i2c_dev;454454+ dev_dbg(&client->dev, "IRQ\n");455455+456456+ if (phy->hard_fault != 0)457457+ return IRQ_HANDLED;458458+459459+ r = st21nfca_hci_i2c_read(phy, phy->pending_skb);460460+ if (r == -EREMOTEIO) {461461+ phy->hard_fault = r;462462+463463+ nfc_hci_recv_frame(phy->hdev, NULL);464464+465465+ return IRQ_HANDLED;466466+ } else if (r == -EAGAIN || r == -EIO) {467467+ return IRQ_HANDLED;468468+ } else if (r == -EBADMSG && phy->crc_trials < ARRAY_SIZE(wait_tab)) {469469+ /*470470+ * With ST21NFCA, only one interface (I2C, RF or SWP)471471+ * may be active at a time.472472+ * Having incorrect crc is usually due to i2c macrocell473473+ * deactivation in the middle of a transmission.474474+ * It may generate corrupted data on i2c.475475+ * We give sometime to get i2c back.476476+ * The complete frame will be repeated.477477+ */478478+ msleep(wait_tab[phy->crc_trials]);479479+ phy->crc_trials++;480480+ phy->current_read_len = 0;481481+ kfree_skb(phy->pending_skb);482482+ } else if (r > 0) {483483+ /*484484+ * We succeeded to read data from the CLF and485485+ * data is valid.486486+ * Reset counter.487487+ */488488+ nfc_hci_recv_frame(phy->hdev, phy->pending_skb);489489+ phy->crc_trials = 0;490490+ }491491+492492+ phy->pending_skb = alloc_skb(ST21NFCA_HCI_LLC_MAX_SIZE * 2, GFP_KERNEL);493493+ if (phy->pending_skb == NULL) {494494+ phy->hard_fault = -ENOMEM;495495+ nfc_hci_recv_frame(phy->hdev, NULL);496496+ }497497+498498+ return IRQ_HANDLED;499499+}500500+501501+static struct nfc_phy_ops i2c_phy_ops = {502502+ .write = st21nfca_hci_i2c_write,503503+ .enable = st21nfca_hci_i2c_enable,504504+ .disable = st21nfca_hci_i2c_disable,505505+};506506+507507+#ifdef CONFIG_OF508508+static int st21nfca_hci_i2c_of_request_resources(struct i2c_client *client)509509+{510510+ struct st21nfca_i2c_phy *phy = i2c_get_clientdata(client);511511+ struct device_node *pp;512512+ int gpio;513513+ int r;514514+515515+ pp = client->dev.of_node;516516+ if (!pp)517517+ return -ENODEV;518518+519519+ /* Get GPIO from device tree */520520+ gpio = of_get_named_gpio(pp, "enable-gpios", 0);521521+ if (gpio < 0) {522522+ nfc_err(&client->dev, "Failed to retrieve enable-gpios from device tree\n");523523+ return gpio;524524+ }525525+526526+ /* GPIO request and configuration */527527+ r = devm_gpio_request(&client->dev, gpio, "clf_enable");528528+ if (r) {529529+ nfc_err(&client->dev, "Failed to request enable pin\n");530530+ return -ENODEV;531531+ }532532+533533+ r = gpio_direction_output(gpio, 1);534534+ if (r) {535535+ nfc_err(&client->dev, "Failed to set enable pin direction as output\n");536536+ return -ENODEV;537537+ }538538+ phy->gpio_ena = gpio;539539+540540+ /* IRQ */541541+ r = irq_of_parse_and_map(pp, 0);542542+ if (r < 0) {543543+ nfc_err(&client->dev,544544+ "Unable to get irq, error: %d\n", r);545545+ return r;546546+ }547547+548548+ phy->irq_polarity = irq_get_trigger_type(r);549549+ client->irq = r;550550+551551+ return 0;552552+}553553+#else554554+static int st21nfca_hci_i2c_of_request_resources(struct i2c_client *client)555555+{556556+ return -ENODEV;557557+}558558+#endif559559+560560+static int st21nfca_hci_i2c_request_resources(struct i2c_client *client)561561+{562562+ struct st21nfca_nfc_platform_data *pdata;563563+ struct st21nfca_i2c_phy *phy = i2c_get_clientdata(client);564564+ int r;565565+ int irq;566566+567567+ pdata = client->dev.platform_data;568568+ if (pdata == NULL) {569569+ nfc_err(&client->dev, "No platform data\n");570570+ return -EINVAL;571571+ }572572+573573+ /* store for later use */574574+ phy->gpio_irq = pdata->gpio_irq;575575+ phy->gpio_ena = pdata->gpio_ena;576576+ phy->irq_polarity = pdata->irq_polarity;577577+578578+ r = devm_gpio_request(&client->dev, phy->gpio_irq, "wake_up");579579+ if (r) {580580+ pr_err("%s : gpio_request failed\n", __FILE__);581581+ return -ENODEV;582582+ }583583+584584+ r = gpio_direction_input(phy->gpio_irq);585585+ if (r) {586586+ pr_err("%s : gpio_direction_input failed\n", __FILE__);587587+ return -ENODEV;588588+ }589589+590590+ if (phy->gpio_ena > 0) {591591+ r = devm_gpio_request(&client->dev,592592+ phy->gpio_ena, "clf_enable");593593+ if (r) {594594+ pr_err("%s : ena gpio_request failed\n", __FILE__);595595+ return -ENODEV;596596+ }597597+ r = gpio_direction_output(phy->gpio_ena, 1);598598+599599+ if (r) {600600+ pr_err("%s : ena gpio_direction_output failed\n",601601+ __FILE__);602602+ return -ENODEV;603603+ }604604+ }605605+606606+ /* IRQ */607607+ irq = gpio_to_irq(phy->gpio_irq);608608+ if (irq < 0) {609609+ nfc_err(&client->dev,610610+ "Unable to get irq number for GPIO %d error %d\n",611611+ phy->gpio_irq, r);612612+ return -ENODEV;613613+ }614614+ client->irq = irq;615615+616616+ return 0;617617+}618618+619619+static int st21nfca_hci_i2c_probe(struct i2c_client *client,620620+ const struct i2c_device_id *id)621621+{622622+ struct st21nfca_i2c_phy *phy;623623+ struct st21nfca_nfc_platform_data *pdata;624624+ int r;625625+626626+ dev_dbg(&client->dev, "%s\n", __func__);627627+ dev_dbg(&client->dev, "IRQ: %d\n", client->irq);628628+629629+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {630630+ nfc_err(&client->dev, "Need I2C_FUNC_I2C\n");631631+ return -ENODEV;632632+ }633633+634634+ phy = devm_kzalloc(&client->dev, sizeof(struct st21nfca_i2c_phy),635635+ GFP_KERNEL);636636+ if (!phy) {637637+ nfc_err(&client->dev,638638+ "Cannot allocate memory for st21nfca i2c phy.\n");639639+ return -ENOMEM;640640+ }641641+642642+ phy->i2c_dev = client;643643+ phy->pending_skb = alloc_skb(ST21NFCA_HCI_LLC_MAX_SIZE * 2, GFP_KERNEL);644644+ if (phy->pending_skb == NULL)645645+ return -ENOMEM;646646+647647+ phy->current_read_len = 0;648648+ phy->crc_trials = 0;649649+ mutex_init(&phy->phy_lock);650650+ i2c_set_clientdata(client, phy);651651+652652+ pdata = client->dev.platform_data;653653+ if (!pdata && client->dev.of_node) {654654+ r = st21nfca_hci_i2c_of_request_resources(client);655655+ if (r) {656656+ nfc_err(&client->dev, "No platform data\n");657657+ return r;658658+ }659659+ } else if (pdata) {660660+ r = st21nfca_hci_i2c_request_resources(client);661661+ if (r) {662662+ nfc_err(&client->dev, "Cannot get platform resources\n");663663+ return r;664664+ }665665+ } else {666666+ nfc_err(&client->dev, "st21nfca platform resources not available\n");667667+ return -ENODEV;668668+ }669669+670670+ r = st21nfca_hci_platform_init(phy);671671+ if (r < 0) {672672+ nfc_err(&client->dev, "Unable to reboot st21nfca\n");673673+ return -ENODEV;674674+ }675675+676676+ r = devm_request_threaded_irq(&client->dev, client->irq, NULL,677677+ st21nfca_hci_irq_thread_fn,678678+ phy->irq_polarity | IRQF_ONESHOT,679679+ ST21NFCA_HCI_DRIVER_NAME, phy);680680+ if (r < 0) {681681+ nfc_err(&client->dev, "Unable to register IRQ handler\n");682682+ return r;683683+ }684684+685685+ return st21nfca_hci_probe(phy, &i2c_phy_ops, LLC_SHDLC_NAME,686686+ ST21NFCA_FRAME_HEADROOM, ST21NFCA_FRAME_TAILROOM,687687+ ST21NFCA_HCI_LLC_MAX_PAYLOAD, &phy->hdev);688688+}689689+690690+static int st21nfca_hci_i2c_remove(struct i2c_client *client)691691+{692692+ struct st21nfca_i2c_phy *phy = i2c_get_clientdata(client);693693+694694+ dev_dbg(&client->dev, "%s\n", __func__);695695+696696+ st21nfca_hci_remove(phy->hdev);697697+698698+ if (phy->powered)699699+ st21nfca_hci_i2c_disable(phy);700700+701701+ return 0;702702+}703703+704704+static const struct of_device_id of_st21nfca_i2c_match[] = {705705+ { .compatible = "st,st21nfca_i2c", },706706+ {}707707+};708708+709709+static struct i2c_driver st21nfca_hci_i2c_driver = {710710+ .driver = {711711+ .owner = THIS_MODULE,712712+ .name = ST21NFCA_HCI_I2C_DRIVER_NAME,713713+ .owner = THIS_MODULE,714714+ .of_match_table = of_match_ptr(of_st21nfca_i2c_match),715715+ },716716+ .probe = st21nfca_hci_i2c_probe,717717+ .id_table = st21nfca_hci_i2c_id_table,718718+ .remove = st21nfca_hci_i2c_remove,719719+};720720+721721+module_i2c_driver(st21nfca_hci_i2c_driver);722722+723723+MODULE_LICENSE("GPL");724724+MODULE_DESCRIPTION(DRIVER_DESC);
+698
drivers/nfc/st21nfca/st21nfca.c
···11+/*22+ * HCI based Driver for STMicroelectronics NFC Chip33+ *44+ * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved.55+ *66+ * This program is free software; you can redistribute it and/or modify it77+ * under the terms and conditions of the GNU General Public License,88+ * version 2, as published by the Free Software Foundation.99+ *1010+ * This program is distributed in the hope that it will be useful,1111+ * but WITHOUT ANY WARRANTY; without even the implied warranty of1212+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1313+ * GNU General Public License for more details.1414+ *1515+ * You should have received a copy of the GNU General Public License1616+ * along with this program; if not, see <http://www.gnu.org/licenses/>.1717+ */1818+1919+#include <linux/module.h>2020+#include <linux/nfc.h>2121+#include <net/nfc/hci.h>2222+#include <net/nfc/llc.h>2323+2424+#include "st21nfca.h"2525+2626+#define DRIVER_DESC "HCI NFC driver for ST21NFCA"2727+2828+#define FULL_VERSION_LEN 32929+3030+/* Proprietary gates, events, commands and registers */3131+3232+/* Commands that apply to all RF readers */3333+#define ST21NFCA_RF_READER_CMD_PRESENCE_CHECK 0x303434+3535+#define ST21NFCA_RF_READER_ISO15693_GATE 0x123636+#define ST21NFCA_RF_READER_ISO15693_INVENTORY 0x013737+3838+/*3939+ * Reader gate for communication with contact-less cards using Type A4040+ * protocol ISO14443-3 but not compliant with ISO14443-44141+ */4242+#define ST21NFCA_RF_READER_14443_3_A_GATE 0x154343+#define ST21NFCA_RF_READER_14443_3_A_UID 0x024444+#define ST21NFCA_RF_READER_14443_3_A_ATQA 0x034545+#define ST21NFCA_RF_READER_14443_3_A_SAK 0x044646+4747+#define ST21NFCA_DEVICE_MGNT_GATE 0x014848+#define ST21NFCA_DEVICE_MGNT_PIPE 0x024949+5050+#define ST21NFCA_DM_GETINFO 0x135151+#define ST21NFCA_DM_GETINFO_PIPE_LIST 0x025252+#define ST21NFCA_DM_GETINFO_PIPE_INFO 0x015353+#define ST21NFCA_DM_PIPE_CREATED 0x025454+#define ST21NFCA_DM_PIPE_OPEN 0x045555+#define ST21NFCA_DM_RF_ACTIVE 0x805656+5757+#define ST21NFCA_DM_IS_PIPE_OPEN(p) \5858+ ((p & 0x0f) == (ST21NFCA_DM_PIPE_CREATED | ST21NFCA_DM_PIPE_OPEN))5959+6060+#define ST21NFCA_NFC_MODE 0x03 /* NFC_MODE parameter*/6161+6262+static DECLARE_BITMAP(dev_mask, ST21NFCA_NUM_DEVICES);6363+6464+static struct nfc_hci_gate st21nfca_gates[] = {6565+ {NFC_HCI_ADMIN_GATE, NFC_HCI_ADMIN_PIPE},6666+ {NFC_HCI_LOOPBACK_GATE, NFC_HCI_INVALID_PIPE},6767+ {NFC_HCI_ID_MGMT_GATE, NFC_HCI_INVALID_PIPE},6868+ {NFC_HCI_LINK_MGMT_GATE, NFC_HCI_LINK_MGMT_PIPE},6969+ {NFC_HCI_RF_READER_B_GATE, NFC_HCI_INVALID_PIPE},7070+ {NFC_HCI_RF_READER_A_GATE, NFC_HCI_INVALID_PIPE},7171+ {ST21NFCA_DEVICE_MGNT_GATE, ST21NFCA_DEVICE_MGNT_PIPE},7272+ {ST21NFCA_RF_READER_F_GATE, NFC_HCI_INVALID_PIPE},7373+ {ST21NFCA_RF_READER_14443_3_A_GATE, NFC_HCI_INVALID_PIPE},7474+ {ST21NFCA_RF_READER_ISO15693_GATE, NFC_HCI_INVALID_PIPE},7575+};7676+7777+struct st21nfca_pipe_info {7878+ u8 pipe_state;7979+ u8 src_host_id;8080+ u8 src_gate_id;8181+ u8 dst_host_id;8282+ u8 dst_gate_id;8383+} __packed;8484+8585+/* Largest headroom needed for outgoing custom commands */8686+#define ST21NFCA_CMDS_HEADROOM 78787+8888+static int st21nfca_hci_load_session(struct nfc_hci_dev *hdev)8989+{9090+ int i, j, r;9191+ struct sk_buff *skb_pipe_list, *skb_pipe_info;9292+ struct st21nfca_pipe_info *info;9393+9494+ u8 pipe_list[] = { ST21NFCA_DM_GETINFO_PIPE_LIST,9595+ NFC_HCI_TERMINAL_HOST_ID9696+ };9797+ u8 pipe_info[] = { ST21NFCA_DM_GETINFO_PIPE_INFO,9898+ NFC_HCI_TERMINAL_HOST_ID, 09999+ };100100+101101+ skb_pipe_list = alloc_skb(ST21NFCA_HCI_LLC_MAX_SIZE, GFP_KERNEL);102102+ if (!skb_pipe_list) {103103+ r = -ENOMEM;104104+ goto free_list;105105+ }106106+107107+ skb_pipe_info = alloc_skb(ST21NFCA_HCI_LLC_MAX_SIZE, GFP_KERNEL);108108+ if (!skb_pipe_info) {109109+ r = -ENOMEM;110110+ goto free_info;111111+ }112112+113113+ /* On ST21NFCA device pipes number are dynamics114114+ * A maximum of 16 pipes can be created at the same time115115+ * If pipes are already created, hci_dev_up will fail.116116+ * Doing a clear all pipe is a bad idea because:117117+ * - It does useless EEPROM cycling118118+ * - It might cause issue for secure elements support119119+ * (such as removing connectivity or APDU reader pipe)120120+ * A better approach on ST21NFCA is to:121121+ * - get a pipe list for each host.122122+ * (eg: NFC_HCI_HOST_CONTROLLER_ID for now).123123+ * (TODO Later on UICC HOST and eSE HOST)124124+ * - get pipe information125125+ * - match retrieved pipe list in st21nfca_gates126126+ * ST21NFCA_DEVICE_MGNT_GATE is a proprietary gate127127+ * with ST21NFCA_DEVICE_MGNT_PIPE.128128+ * Pipe can be closed and need to be open.129129+ */130130+ r = nfc_hci_connect_gate(hdev, NFC_HCI_HOST_CONTROLLER_ID,131131+ ST21NFCA_DEVICE_MGNT_GATE, ST21NFCA_DEVICE_MGNT_PIPE);132132+ if (r < 0)133133+ goto free_info;134134+135135+ /* Get pipe list */136136+ r = nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE,137137+ ST21NFCA_DM_GETINFO, pipe_list, sizeof(pipe_list),138138+ &skb_pipe_list);139139+ if (r < 0)140140+ goto free_info;141141+142142+ /* Complete the existing gate_pipe table */143143+ for (i = 0; i < skb_pipe_list->len; i++) {144144+ pipe_info[2] = skb_pipe_list->data[i];145145+ r = nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE,146146+ ST21NFCA_DM_GETINFO, pipe_info,147147+ sizeof(pipe_info), &skb_pipe_info);148148+149149+ if (r)150150+ continue;151151+152152+ /*153153+ * Match pipe ID and gate ID154154+ * Output format from ST21NFC_DM_GETINFO is:155155+ * - pipe state (1byte)156156+ * - source hid (1byte)157157+ * - source gid (1byte)158158+ * - destination hid (1byte)159159+ * - destination gid (1byte)160160+ */161161+ info = (struct st21nfca_pipe_info *) skb_pipe_info->data;162162+ for (j = 0; (j < ARRAY_SIZE(st21nfca_gates)) &&163163+ (st21nfca_gates[j].gate != info->dst_gate_id);164164+ j++)165165+ ;166166+167167+ if (j < ARRAY_SIZE(st21nfca_gates) &&168168+ st21nfca_gates[j].gate == info->dst_gate_id &&169169+ ST21NFCA_DM_IS_PIPE_OPEN(info->pipe_state)) {170170+ st21nfca_gates[j].pipe = pipe_info[2];171171+ hdev->gate2pipe[st21nfca_gates[j].gate] =172172+ st21nfca_gates[j].pipe;173173+ }174174+ }175175+176176+ /*177177+ * 3 gates have a well known pipe ID.178178+ * They will never appear in the pipe list179179+ */180180+ if (skb_pipe_list->len + 3 < ARRAY_SIZE(st21nfca_gates)) {181181+ for (i = skb_pipe_list->len + 3;182182+ i < ARRAY_SIZE(st21nfca_gates); i++) {183183+ r = nfc_hci_connect_gate(hdev,184184+ NFC_HCI_HOST_CONTROLLER_ID,185185+ st21nfca_gates[i].gate,186186+ st21nfca_gates[i].pipe);187187+ if (r < 0)188188+ goto free_info;189189+ }190190+ }191191+192192+ memcpy(hdev->init_data.gates, st21nfca_gates, sizeof(st21nfca_gates));193193+free_info:194194+ kfree_skb(skb_pipe_info);195195+free_list:196196+ kfree_skb(skb_pipe_list);197197+ return r;198198+}199199+200200+static int st21nfca_hci_open(struct nfc_hci_dev *hdev)201201+{202202+ struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);203203+ int r;204204+205205+ mutex_lock(&info->info_lock);206206+207207+ if (info->state != ST21NFCA_ST_COLD) {208208+ r = -EBUSY;209209+ goto out;210210+ }211211+212212+ r = info->phy_ops->enable(info->phy_id);213213+214214+ if (r == 0)215215+ info->state = ST21NFCA_ST_READY;216216+217217+out:218218+ mutex_unlock(&info->info_lock);219219+ return r;220220+}221221+222222+static void st21nfca_hci_close(struct nfc_hci_dev *hdev)223223+{224224+ struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);225225+226226+ mutex_lock(&info->info_lock);227227+228228+ if (info->state == ST21NFCA_ST_COLD)229229+ goto out;230230+231231+ info->phy_ops->disable(info->phy_id);232232+ info->state = ST21NFCA_ST_COLD;233233+234234+out:235235+ mutex_unlock(&info->info_lock);236236+}237237+238238+static int st21nfca_hci_ready(struct nfc_hci_dev *hdev)239239+{240240+ struct sk_buff *skb;241241+242242+ u8 param;243243+ int r;244244+245245+ param = NFC_HCI_UICC_HOST_ID;246246+ r = nfc_hci_set_param(hdev, NFC_HCI_ADMIN_GATE,247247+ NFC_HCI_ADMIN_WHITELIST, ¶m, 1);248248+ if (r < 0)249249+ return r;250250+251251+ /* Set NFC_MODE in device management gate to enable */252252+ r = nfc_hci_get_param(hdev, ST21NFCA_DEVICE_MGNT_GATE,253253+ ST21NFCA_NFC_MODE, &skb);254254+ if (r < 0)255255+ return r;256256+257257+ if (skb->data[0] == 0) {258258+ kfree_skb(skb);259259+ param = 1;260260+261261+ r = nfc_hci_set_param(hdev, ST21NFCA_DEVICE_MGNT_GATE,262262+ ST21NFCA_NFC_MODE, ¶m, 1);263263+ if (r < 0)264264+ return r;265265+ }266266+267267+ r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE,268268+ NFC_HCI_EVT_END_OPERATION, NULL, 0);269269+ if (r < 0)270270+ return r;271271+272272+ r = nfc_hci_get_param(hdev, NFC_HCI_ID_MGMT_GATE,273273+ NFC_HCI_ID_MGMT_VERSION_SW, &skb);274274+ if (r < 0)275275+ return r;276276+277277+ if (skb->len != FULL_VERSION_LEN) {278278+ kfree_skb(skb);279279+ return -EINVAL;280280+ }281281+282282+ print_hex_dump(KERN_DEBUG, "FULL VERSION SOFTWARE INFO: ",283283+ DUMP_PREFIX_NONE, 16, 1,284284+ skb->data, FULL_VERSION_LEN, false);285285+286286+ kfree_skb(skb);287287+288288+ return 0;289289+}290290+291291+static int st21nfca_hci_xmit(struct nfc_hci_dev *hdev, struct sk_buff *skb)292292+{293293+ struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);294294+295295+ return info->phy_ops->write(info->phy_id, skb);296296+}297297+298298+static int st21nfca_hci_start_poll(struct nfc_hci_dev *hdev,299299+ u32 im_protocols, u32 tm_protocols)300300+{301301+ int r;302302+303303+ pr_info(DRIVER_DESC ": %s protocols 0x%x 0x%x\n",304304+ __func__, im_protocols, tm_protocols);305305+306306+ r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE,307307+ NFC_HCI_EVT_END_OPERATION, NULL, 0);308308+ if (r < 0)309309+ return r;310310+ if (im_protocols) {311311+ /*312312+ * enable polling according to im_protocols & tm_protocols313313+ * - CLOSE pipe according to im_protocols & tm_protocols314314+ */315315+ if ((NFC_HCI_RF_READER_B_GATE & im_protocols) == 0) {316316+ r = nfc_hci_disconnect_gate(hdev,317317+ NFC_HCI_RF_READER_B_GATE);318318+ if (r < 0)319319+ return r;320320+ }321321+322322+ if ((NFC_HCI_RF_READER_A_GATE & im_protocols) == 0) {323323+ r = nfc_hci_disconnect_gate(hdev,324324+ NFC_HCI_RF_READER_A_GATE);325325+ if (r < 0)326326+ return r;327327+ }328328+329329+ if ((ST21NFCA_RF_READER_F_GATE & im_protocols) == 0) {330330+ r = nfc_hci_disconnect_gate(hdev,331331+ ST21NFCA_RF_READER_F_GATE);332332+ if (r < 0)333333+ return r;334334+ }335335+336336+ if ((ST21NFCA_RF_READER_14443_3_A_GATE & im_protocols) == 0) {337337+ r = nfc_hci_disconnect_gate(hdev,338338+ ST21NFCA_RF_READER_14443_3_A_GATE);339339+ if (r < 0)340340+ return r;341341+ }342342+343343+ if ((ST21NFCA_RF_READER_ISO15693_GATE & im_protocols) == 0) {344344+ r = nfc_hci_disconnect_gate(hdev,345345+ ST21NFCA_RF_READER_ISO15693_GATE);346346+ if (r < 0)347347+ return r;348348+ }349349+350350+ r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE,351351+ NFC_HCI_EVT_READER_REQUESTED, NULL, 0);352352+ if (r < 0)353353+ nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE,354354+ NFC_HCI_EVT_END_OPERATION, NULL, 0);355355+ }356356+ return r;357357+}358358+359359+static int st21nfca_get_iso14443_3_atqa(struct nfc_hci_dev *hdev, u16 *atqa)360360+{361361+ int r;362362+ struct sk_buff *atqa_skb = NULL;363363+364364+ r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_14443_3_A_GATE,365365+ ST21NFCA_RF_READER_14443_3_A_ATQA, &atqa_skb);366366+ if (r < 0)367367+ goto exit;368368+369369+ if (atqa_skb->len != 2) {370370+ r = -EPROTO;371371+ goto exit;372372+ }373373+374374+ *atqa = be16_to_cpu(*(__be16 *) atqa_skb->data);375375+376376+exit:377377+ kfree_skb(atqa_skb);378378+ return r;379379+}380380+381381+static int st21nfca_get_iso14443_3_sak(struct nfc_hci_dev *hdev, u8 *sak)382382+{383383+ int r;384384+ struct sk_buff *sak_skb = NULL;385385+386386+ r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_14443_3_A_GATE,387387+ ST21NFCA_RF_READER_14443_3_A_SAK, &sak_skb);388388+ if (r < 0)389389+ goto exit;390390+391391+ if (sak_skb->len != 1) {392392+ r = -EPROTO;393393+ goto exit;394394+ }395395+396396+ *sak = sak_skb->data[0];397397+398398+exit:399399+ kfree_skb(sak_skb);400400+ return r;401401+}402402+403403+static int st21nfca_get_iso14443_3_uid(struct nfc_hci_dev *hdev, u8 *gate,404404+ int *len)405405+{406406+ int r;407407+ struct sk_buff *uid_skb = NULL;408408+409409+ r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_14443_3_A_GATE,410410+ ST21NFCA_RF_READER_14443_3_A_UID, &uid_skb);411411+ if (r < 0)412412+ goto exit;413413+414414+ if (uid_skb->len == 0 || uid_skb->len > NFC_NFCID1_MAXSIZE) {415415+ r = -EPROTO;416416+ goto exit;417417+ }418418+419419+ gate = uid_skb->data;420420+ *len = uid_skb->len;421421+exit:422422+ kfree_skb(uid_skb);423423+ return r;424424+}425425+426426+static int st21nfca_get_iso15693_inventory(struct nfc_hci_dev *hdev,427427+ struct nfc_target *target)428428+{429429+ int r;430430+ struct sk_buff *inventory_skb = NULL;431431+432432+ r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_ISO15693_GATE,433433+ ST21NFCA_RF_READER_ISO15693_INVENTORY,434434+ &inventory_skb);435435+ if (r < 0)436436+ goto exit;437437+438438+ skb_pull(inventory_skb, 2);439439+440440+ if (inventory_skb->len == 0 ||441441+ inventory_skb->len > NFC_ISO15693_UID_MAXSIZE) {442442+ r = -EPROTO;443443+ goto exit;444444+ }445445+446446+ memcpy(target->iso15693_uid, inventory_skb->data, inventory_skb->len);447447+ target->iso15693_dsfid = inventory_skb->data[1];448448+ target->is_iso15693 = 1;449449+exit:450450+ kfree_skb(inventory_skb);451451+ return r;452452+}453453+454454+static int st21nfca_hci_target_from_gate(struct nfc_hci_dev *hdev, u8 gate,455455+ struct nfc_target *target)456456+{457457+ int r, len;458458+ u16 atqa;459459+ u8 sak;460460+ u8 uid[NFC_NFCID1_MAXSIZE];461461+462462+ switch (gate) {463463+ case ST21NFCA_RF_READER_F_GATE:464464+ target->supported_protocols = NFC_PROTO_FELICA_MASK;465465+ break;466466+ case ST21NFCA_RF_READER_14443_3_A_GATE:467467+ /* ISO14443-3 type 1 or 2 tags */468468+ r = st21nfca_get_iso14443_3_atqa(hdev, &atqa);469469+ if (r < 0)470470+ return r;471471+ if (atqa == 0x000c) {472472+ target->supported_protocols = NFC_PROTO_JEWEL_MASK;473473+ target->sens_res = 0x0c00;474474+ } else {475475+ r = st21nfca_get_iso14443_3_sak(hdev, &sak);476476+ if (r < 0)477477+ return r;478478+479479+ r = st21nfca_get_iso14443_3_uid(hdev, uid, &len);480480+ if (r < 0)481481+ return r;482482+483483+ target->supported_protocols =484484+ nfc_hci_sak_to_protocol(sak);485485+ if (target->supported_protocols == 0xffffffff)486486+ return -EPROTO;487487+488488+ target->sens_res = atqa;489489+ target->sel_res = sak;490490+ memcpy(target->nfcid1, uid, len);491491+ target->nfcid1_len = len;492492+ }493493+494494+ break;495495+ case ST21NFCA_RF_READER_ISO15693_GATE:496496+ target->supported_protocols = NFC_PROTO_ISO15693_MASK;497497+ r = st21nfca_get_iso15693_inventory(hdev, target);498498+ if (r < 0)499499+ return r;500500+ break;501501+ default:502502+ return -EPROTO;503503+ }504504+505505+ return 0;506506+}507507+508508+#define ST21NFCA_CB_TYPE_READER_ISO15693 1509509+static void st21nfca_hci_data_exchange_cb(void *context, struct sk_buff *skb,510510+ int err)511511+{512512+ struct st21nfca_hci_info *info = context;513513+514514+ switch (info->async_cb_type) {515515+ case ST21NFCA_CB_TYPE_READER_ISO15693:516516+ if (err == 0)517517+ skb_trim(skb, skb->len - 1);518518+ info->async_cb(info->async_cb_context, skb, err);519519+ break;520520+ default:521521+ if (err == 0)522522+ kfree_skb(skb);523523+ break;524524+ }525525+}526526+527527+/*528528+ * Returns:529529+ * <= 0: driver handled the data exchange530530+ * 1: driver doesn't especially handle, please do standard processing531531+ */532532+static int st21nfca_hci_im_transceive(struct nfc_hci_dev *hdev,533533+ struct nfc_target *target,534534+ struct sk_buff *skb,535535+ data_exchange_cb_t cb, void *cb_context)536536+{537537+ struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);538538+539539+ pr_info(DRIVER_DESC ": %s for gate=%d len=%d\n", __func__,540540+ target->hci_reader_gate, skb->len);541541+542542+ switch (target->hci_reader_gate) {543543+ case ST21NFCA_RF_READER_F_GATE:544544+ *skb_push(skb, 1) = 0x1a;545545+ return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate,546546+ ST21NFCA_WR_XCHG_DATA, skb->data,547547+ skb->len, cb, cb_context);548548+ case ST21NFCA_RF_READER_14443_3_A_GATE:549549+ *skb_push(skb, 1) = 0x1a; /* CTR, see spec:10.2.2.1 */550550+551551+ return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate,552552+ ST21NFCA_WR_XCHG_DATA, skb->data,553553+ skb->len, cb, cb_context);554554+ case ST21NFCA_RF_READER_ISO15693_GATE:555555+ info->async_cb_type = ST21NFCA_CB_TYPE_READER_ISO15693;556556+ info->async_cb = cb;557557+ info->async_cb_context = cb_context;558558+559559+ *skb_push(skb, 1) = 0x17;560560+561561+ return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate,562562+ ST21NFCA_WR_XCHG_DATA, skb->data,563563+ skb->len,564564+ st21nfca_hci_data_exchange_cb,565565+ info);566566+ break;567567+ default:568568+ return 1;569569+ }570570+}571571+572572+static int st21nfca_hci_check_presence(struct nfc_hci_dev *hdev,573573+ struct nfc_target *target)574574+{575575+ u8 fwi = 0x11;576576+ switch (target->hci_reader_gate) {577577+ case NFC_HCI_RF_READER_A_GATE:578578+ case NFC_HCI_RF_READER_B_GATE:579579+ /*580580+ * PRESENCE_CHECK on those gates is available581581+ * However, the answer to this command is taking 3 * fwi582582+ * if the card is no present.583583+ * Instead, we send an empty I-Frame with a very short584584+ * configurable fwi ~604µs.585585+ */586586+ return nfc_hci_send_cmd(hdev, target->hci_reader_gate,587587+ ST21NFCA_WR_XCHG_DATA, &fwi, 1, NULL);588588+ case ST21NFCA_RF_READER_14443_3_A_GATE:589589+ return nfc_hci_send_cmd(hdev, target->hci_reader_gate,590590+ ST21NFCA_RF_READER_CMD_PRESENCE_CHECK,591591+ NULL, 0, NULL);592592+ default:593593+ return -EOPNOTSUPP;594594+ }595595+}596596+597597+static struct nfc_hci_ops st21nfca_hci_ops = {598598+ .open = st21nfca_hci_open,599599+ .close = st21nfca_hci_close,600600+ .load_session = st21nfca_hci_load_session,601601+ .hci_ready = st21nfca_hci_ready,602602+ .xmit = st21nfca_hci_xmit,603603+ .start_poll = st21nfca_hci_start_poll,604604+ .target_from_gate = st21nfca_hci_target_from_gate,605605+ .im_transceive = st21nfca_hci_im_transceive,606606+ .check_presence = st21nfca_hci_check_presence,607607+};608608+609609+int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops,610610+ char *llc_name, int phy_headroom, int phy_tailroom,611611+ int phy_payload, struct nfc_hci_dev **hdev)612612+{613613+ struct st21nfca_hci_info *info;614614+ int r = 0;615615+ int dev_num;616616+ u32 protocols;617617+ struct nfc_hci_init_data init_data;618618+ unsigned long quirks = 0;619619+620620+ info = kzalloc(sizeof(struct st21nfca_hci_info), GFP_KERNEL);621621+ if (!info) {622622+ r = -ENOMEM;623623+ goto err_alloc_hdev;624624+ }625625+626626+ info->phy_ops = phy_ops;627627+ info->phy_id = phy_id;628628+ info->state = ST21NFCA_ST_COLD;629629+ mutex_init(&info->info_lock);630630+631631+ init_data.gate_count = ARRAY_SIZE(st21nfca_gates);632632+633633+ memcpy(init_data.gates, st21nfca_gates, sizeof(st21nfca_gates));634634+635635+ /*636636+ * Session id must include the driver name + i2c bus addr637637+ * persistent info to discriminate 2 identical chips638638+ */639639+ dev_num = find_first_zero_bit(dev_mask, ST21NFCA_NUM_DEVICES);640640+ if (dev_num >= ST21NFCA_NUM_DEVICES)641641+ goto err_alloc_hdev;642642+643643+ scnprintf(init_data.session_id, sizeof(init_data.session_id), "%s%2x",644644+ "ST21AH", dev_num);645645+646646+ protocols = NFC_PROTO_JEWEL_MASK |647647+ NFC_PROTO_MIFARE_MASK |648648+ NFC_PROTO_FELICA_MASK |649649+ NFC_PROTO_ISO14443_MASK |650650+ NFC_PROTO_ISO14443_B_MASK |651651+ NFC_PROTO_ISO15693_MASK;652652+653653+ set_bit(NFC_HCI_QUIRK_SHORT_CLEAR, &quirks);654654+655655+ info->hdev =656656+ nfc_hci_allocate_device(&st21nfca_hci_ops, &init_data, quirks,657657+ protocols, llc_name,658658+ phy_headroom + ST21NFCA_CMDS_HEADROOM,659659+ phy_tailroom, phy_payload);660660+661661+ if (!info->hdev) {662662+ pr_err("Cannot allocate nfc hdev.\n");663663+ r = -ENOMEM;664664+ goto err_alloc_hdev;665665+ }666666+667667+ nfc_hci_set_clientdata(info->hdev, info);668668+669669+ r = nfc_hci_register_device(info->hdev);670670+ if (r)671671+ goto err_regdev;672672+673673+ *hdev = info->hdev;674674+675675+ return 0;676676+677677+err_regdev:678678+ nfc_hci_free_device(info->hdev);679679+680680+err_alloc_hdev:681681+ kfree(info);682682+683683+ return r;684684+}685685+EXPORT_SYMBOL(st21nfca_hci_probe);686686+687687+void st21nfca_hci_remove(struct nfc_hci_dev *hdev)688688+{689689+ struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);690690+691691+ nfc_hci_unregister_device(hdev);692692+ nfc_hci_free_device(hdev);693693+ kfree(info);694694+}695695+EXPORT_SYMBOL(st21nfca_hci_remove);696696+697697+MODULE_LICENSE("GPL");698698+MODULE_DESCRIPTION(DRIVER_DESC);
+87
drivers/nfc/st21nfca/st21nfca.h
···11+/*22+ * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved.33+ *44+ * This program is free software; you can redistribute it and/or modify it55+ * under the terms and conditions of the GNU General Public License,66+ * version 2, as published by the Free Software Foundation.77+ *88+ * This program is distributed in the hope that it will be useful,99+ * but WITHOUT ANY WARRANTY; without even the implied warranty of1010+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1111+ * GNU General Public License for more details.1212+ *1313+ * You should have received a copy of the GNU General Public License1414+ * along with this program; if not, see <http://www.gnu.org/licenses/>.1515+ */1616+1717+#ifndef __LOCAL_ST21NFCA_H_1818+#define __LOCAL_ST21NFCA_H_1919+2020+#include <net/nfc/hci.h>2121+2222+#define HCI_MODE 02323+2424+/* framing in HCI mode */2525+#define ST21NFCA_SOF_EOF_LEN 22626+2727+/* Almost every time value is 0 */2828+#define ST21NFCA_HCI_LLC_LEN 12929+3030+/* Size in worst case :3131+ * In normal case CRC len = 2 but byte stuffing3232+ * may appear in case one CRC byte = ST21NFCA_SOF_EOF3333+ */3434+#define ST21NFCA_HCI_LLC_CRC 43535+3636+#define ST21NFCA_HCI_LLC_LEN_CRC (ST21NFCA_SOF_EOF_LEN + \3737+ ST21NFCA_HCI_LLC_LEN + \3838+ ST21NFCA_HCI_LLC_CRC)3939+#define ST21NFCA_HCI_LLC_MIN_SIZE (1 + ST21NFCA_HCI_LLC_LEN_CRC)4040+4141+/* Worst case when adding byte stuffing between each byte */4242+#define ST21NFCA_HCI_LLC_MAX_PAYLOAD 294343+#define ST21NFCA_HCI_LLC_MAX_SIZE (ST21NFCA_HCI_LLC_LEN_CRC + 1 + \4444+ ST21NFCA_HCI_LLC_MAX_PAYLOAD)4545+4646+#define DRIVER_DESC "HCI NFC driver for ST21NFCA"4747+4848+#define ST21NFCA_HCI_MODE 04949+5050+#define ST21NFCA_NUM_DEVICES 2565151+5252+int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops,5353+ char *llc_name, int phy_headroom, int phy_tailroom,5454+ int phy_payload, struct nfc_hci_dev **hdev);5555+void st21nfca_hci_remove(struct nfc_hci_dev *hdev);5656+5757+enum st21nfca_state {5858+ ST21NFCA_ST_COLD,5959+ ST21NFCA_ST_READY,6060+};6161+6262+struct st21nfca_hci_info {6363+ struct nfc_phy_ops *phy_ops;6464+ void *phy_id;6565+6666+ struct nfc_hci_dev *hdev;6767+6868+ enum st21nfca_state state;6969+7070+ struct mutex info_lock;7171+7272+ int async_cb_type;7373+ data_exchange_cb_t async_cb;7474+ void *async_cb_context;7575+7676+} __packed;7777+7878+/* Reader RF commands */7979+#define ST21NFCA_WR_XCHG_DATA 0x108080+8181+#define ST21NFCA_RF_READER_F_GATE 0x148282+#define ST21NFCA_RF_READER_F_DATARATE 0x018383+#define ST21NFCA_RF_READER_F_DATARATE_106 0x018484+#define ST21NFCA_RF_READER_F_DATARATE_212 0x028585+#define ST21NFCA_RF_READER_F_DATARATE_424 0x048686+8787+#endif /* __LOCAL_ST21NFCA_H_ */
+182-70
drivers/nfc/trf7970a.c
···1616#include <linux/device.h>1717#include <linux/netdevice.h>1818#include <linux/interrupt.h>1919+#include <linux/pm_runtime.h>1920#include <linux/nfc.h>2021#include <linux/skbuff.h>2122#include <linux/delay.h>···6867 * only the SRX bit set, it means that all of the data has been received6968 * (once what's in the fifo has been read). However, depending on timing7069 * an interrupt status with only the SRX bit set may not be recived. In7171- * those cases, the timeout mechanism is used to wait 5 ms in case more7272- * data arrives. After 5 ms, it is assumed that all of the data has been7070+ * those cases, the timeout mechanism is used to wait 20 ms in case more7171+ * data arrives. After 20 ms, it is assumed that all of the data has been7372 * received and the accumulated rx data is sent upstream. The7473 * 'TRF7970A_ST_WAIT_FOR_RX_DATA_CONT' state is used for this purpose7574 * (i.e., it indicates that some data has been received but we're not sure7675 * if there is more coming so a timeout in this state means all data has7777- * been received and there isn't an error). The delay is 5 ms since delays7878- * over 2 ms have been observed during testing (a little extra just in case).7676+ * been received and there isn't an error). The delay is 20 ms since delays7777+ * of ~16 ms have been observed during testing.7978 *8079 * Type 2 write and sector select commands respond with a 4-bit ACK or NACK.8180 * Having only 4 bits in the FIFO won't normally generate an interrupt so···105104106105#define TRF7970A_SUPPORTED_PROTOCOLS \107106 (NFC_PROTO_MIFARE_MASK | NFC_PROTO_ISO14443_MASK | \108108- NFC_PROTO_ISO15693_MASK)107107+ NFC_PROTO_ISO14443_B_MASK | NFC_PROTO_ISO15693_MASK)108108+109109+#define TRF7970A_AUTOSUSPEND_DELAY 30000 /* 30 seconds */109110110111/* TX data must be prefixed with a FIFO reset cmd, a cmd that depends111112 * on what the current framing is, the address of the TX length byte 1···123120/* TX length is 3 nibbles long ==> 4KB - 1 bytes max */124121#define TRF7970A_TX_MAX (4096 - 1)125122126126-#define TRF7970A_WAIT_FOR_RX_DATA_TIMEOUT 5123123+#define TRF7970A_WAIT_FOR_RX_DATA_TIMEOUT 20127124#define TRF7970A_WAIT_FOR_FIFO_DRAIN_TIMEOUT 3128125#define TRF7970A_WAIT_TO_ISSUE_ISO15693_EOF 20129126···333330 struct regulator *regulator;334331 struct nfc_digital_dev *ddev;335332 u32 quirks;336336- bool powering_up;337333 bool aborting;338334 struct sk_buff *tx_skb;339335 struct sk_buff *rx_skb;340336 nfc_digital_cmd_complete_t cb;341337 void *cb_arg;338338+ u8 chip_status_ctrl;342339 u8 iso_ctrl;340340+ u8 iso_ctrl_tech;341341+ u8 modulator_sys_clk_ctrl;343342 u8 special_fcn_reg1;344343 int technology;345344 int framing;···686681 trf->ignore_timeout =687682 !cancel_delayed_work(&trf->timeout_work);688683 trf7970a_drain_fifo(trf, status);689689- } else if (!(status & TRF7970A_IRQ_STATUS_TX)) {684684+ } else if (status == TRF7970A_IRQ_STATUS_TX) {685685+ trf7970a_cmd(trf, TRF7970A_CMD_FIFO_RESET);686686+ } else {690687 trf7970a_send_err_upstream(trf, -EIO);691688 }692689 break;···764757 if (ret)765758 goto err_out;766759767767- ret = trf7970a_write(trf, TRF7970A_MODULATOR_SYS_CLK_CTRL,768768- TRF7970A_MODULATOR_DEPTH_OOK);760760+ /* Must clear NFC Target Detection Level reg due to erratum */761761+ ret = trf7970a_write(trf, TRF7970A_NFC_TARGET_LEVEL, 0);769762 if (ret)770763 goto err_out;771764···781774782775 trf->special_fcn_reg1 = 0;783776784784- ret = trf7970a_write(trf, TRF7970A_CHIP_STATUS_CTRL,785785- TRF7970A_CHIP_STATUS_RF_ON |786786- TRF7970A_CHIP_STATUS_VRS5_3);787787- if (ret)788788- goto err_out;789789-777777+ trf->iso_ctrl = 0xff;790778 return 0;791779792780err_out:···793791{794792 dev_dbg(trf->dev, "Switching rf off\n");795793796796- gpio_set_value(trf->en_gpio, 0);797797- gpio_set_value(trf->en2_gpio, 0);794794+ trf->chip_status_ctrl &= ~TRF7970A_CHIP_STATUS_RF_ON;795795+796796+ trf7970a_write(trf, TRF7970A_CHIP_STATUS_CTRL, trf->chip_status_ctrl);798797799798 trf->aborting = false;800799 trf->state = TRF7970A_ST_OFF;800800+801801+ pm_runtime_mark_last_busy(trf->dev);802802+ pm_runtime_put_autosuspend(trf->dev);801803}802804803803-static int trf7970a_switch_rf_on(struct trf7970a *trf)805805+static void trf7970a_switch_rf_on(struct trf7970a *trf)804806{805805- unsigned long delay;806806- int ret;807807-808807 dev_dbg(trf->dev, "Switching rf on\n");809808810810- if (trf->powering_up)811811- usleep_range(5000, 6000);809809+ pm_runtime_get_sync(trf->dev);812810813813- gpio_set_value(trf->en2_gpio, 1);814814- usleep_range(1000, 2000);815815- gpio_set_value(trf->en_gpio, 1);816816-817817- /* The delay between enabling the trf7970a and issuing the first818818- * command is significantly longer the very first time after powering819819- * up. Make sure the longer delay is only done the first time.820820- */821821- if (trf->powering_up) {822822- delay = 20000;823823- trf->powering_up = false;824824- } else {825825- delay = 5000;826826- }827827-828828- usleep_range(delay, delay + 1000);829829-830830- ret = trf7970a_init(trf);831831- if (ret)832832- trf7970a_switch_rf_off(trf);833833- else834834- trf->state = TRF7970A_ST_IDLE;835835-836836- return ret;811811+ trf->state = TRF7970A_ST_IDLE;837812}838813839814static int trf7970a_switch_rf(struct nfc_digital_dev *ddev, bool on)840815{841816 struct trf7970a *trf = nfc_digital_get_drvdata(ddev);842842- int ret = 0;843817844818 dev_dbg(trf->dev, "Switching RF - state: %d, on: %d\n", trf->state, on);845819···824846 if (on) {825847 switch (trf->state) {826848 case TRF7970A_ST_OFF:827827- ret = trf7970a_switch_rf_on(trf);849849+ trf7970a_switch_rf_on(trf);828850 break;829851 case TRF7970A_ST_IDLE:830852 case TRF7970A_ST_IDLE_RX_BLOCKED:···849871 }850872851873 mutex_unlock(&trf->lock);852852- return ret;874874+ return 0;853875}854876855877static int trf7970a_config_rf_tech(struct trf7970a *trf, int tech)···860882861883 switch (tech) {862884 case NFC_DIGITAL_RF_TECH_106A:863863- trf->iso_ctrl = TRF7970A_ISO_CTRL_14443A_106;885885+ trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_14443A_106;886886+ trf->modulator_sys_clk_ctrl = TRF7970A_MODULATOR_DEPTH_OOK;887887+ break;888888+ case NFC_DIGITAL_RF_TECH_106B:889889+ trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_14443B_106;890890+ trf->modulator_sys_clk_ctrl = TRF7970A_MODULATOR_DEPTH_ASK10;864891 break;865892 case NFC_DIGITAL_RF_TECH_ISO15693:866866- trf->iso_ctrl = TRF7970A_ISO_CTRL_15693_SGL_1OF4_2648;893893+ trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_15693_SGL_1OF4_2648;894894+ trf->modulator_sys_clk_ctrl = TRF7970A_MODULATOR_DEPTH_OOK;867895 break;868896 default:869897 dev_dbg(trf->dev, "Unsupported rf technology: %d\n", tech);···883899884900static int trf7970a_config_framing(struct trf7970a *trf, int framing)885901{902902+ u8 iso_ctrl = trf->iso_ctrl_tech;903903+ int ret;904904+886905 dev_dbg(trf->dev, "framing: %d\n", framing);887906888907 switch (framing) {889908 case NFC_DIGITAL_FRAMING_NFCA_SHORT:890909 case NFC_DIGITAL_FRAMING_NFCA_STANDARD:891910 trf->tx_cmd = TRF7970A_CMD_TRANSMIT_NO_CRC;892892- trf->iso_ctrl |= TRF7970A_ISO_CTRL_RX_CRC_N;911911+ iso_ctrl |= TRF7970A_ISO_CTRL_RX_CRC_N;893912 break;894913 case NFC_DIGITAL_FRAMING_NFCA_STANDARD_WITH_CRC_A:895914 case NFC_DIGITAL_FRAMING_NFCA_T4T:915915+ case NFC_DIGITAL_FRAMING_NFCB:916916+ case NFC_DIGITAL_FRAMING_NFCB_T4T:896917 case NFC_DIGITAL_FRAMING_ISO15693_INVENTORY:897918 case NFC_DIGITAL_FRAMING_ISO15693_T5T:898919 trf->tx_cmd = TRF7970A_CMD_TRANSMIT;899899- trf->iso_ctrl &= ~TRF7970A_ISO_CTRL_RX_CRC_N;920920+ iso_ctrl &= ~TRF7970A_ISO_CTRL_RX_CRC_N;900921 break;901922 case NFC_DIGITAL_FRAMING_NFCA_T2T:902923 trf->tx_cmd = TRF7970A_CMD_TRANSMIT;903903- trf->iso_ctrl |= TRF7970A_ISO_CTRL_RX_CRC_N;924924+ iso_ctrl |= TRF7970A_ISO_CTRL_RX_CRC_N;904925 break;905926 default:906927 dev_dbg(trf->dev, "Unsupported Framing: %d\n", framing);···914925915926 trf->framing = framing;916927917917- return trf7970a_write(trf, TRF7970A_ISO_CTRL, trf->iso_ctrl);928928+ if (iso_ctrl != trf->iso_ctrl) {929929+ ret = trf7970a_write(trf, TRF7970A_ISO_CTRL, iso_ctrl);930930+ if (ret)931931+ return ret;932932+933933+ trf->iso_ctrl = iso_ctrl;934934+935935+ ret = trf7970a_write(trf, TRF7970A_MODULATOR_SYS_CLK_CTRL,936936+ trf->modulator_sys_clk_ctrl);937937+ if (ret)938938+ return ret;939939+ }940940+941941+ if (!(trf->chip_status_ctrl & TRF7970A_CHIP_STATUS_RF_ON)) {942942+ ret = trf7970a_write(trf, TRF7970A_CHIP_STATUS_CTRL,943943+ trf->chip_status_ctrl |944944+ TRF7970A_CHIP_STATUS_RF_ON);945945+ if (ret)946946+ return ret;947947+948948+ trf->chip_status_ctrl |= TRF7970A_CHIP_STATUS_RF_ON;949949+950950+ usleep_range(5000, 6000);951951+ }952952+953953+ return 0;918954}919955920956static int trf7970a_in_configure_hw(struct nfc_digital_dev *ddev, int type,921957 int param)922958{923959 struct trf7970a *trf = nfc_digital_get_drvdata(ddev);924924- int ret = 0;960960+ int ret;925961926962 dev_dbg(trf->dev, "Configure hw - type: %d, param: %d\n", type, param);927963928964 mutex_lock(&trf->lock);929965930930- if (trf->state == TRF7970A_ST_OFF) {931931- ret = trf7970a_switch_rf_on(trf);932932- if (ret)933933- goto err_out;934934- }966966+ if (trf->state == TRF7970A_ST_OFF)967967+ trf7970a_switch_rf_on(trf);935968936969 switch (type) {937970 case NFC_DIGITAL_CONFIG_RF_TECH:···967956 ret = -EINVAL;968957 }969958970970-err_out:971959 mutex_unlock(&trf->lock);972960 return ret;973961}···12011191 dev_dbg(trf->dev, "Abort process initiated\n");1202119212031193 mutex_lock(&trf->lock);12041204- trf->aborting = true;11941194+11951195+ switch (trf->state) {11961196+ case TRF7970A_ST_WAIT_FOR_TX_FIFO:11971197+ case TRF7970A_ST_WAIT_FOR_RX_DATA:11981198+ case TRF7970A_ST_WAIT_FOR_RX_DATA_CONT:11991199+ case TRF7970A_ST_WAIT_TO_ISSUE_EOF:12001200+ trf->aborting = true;12011201+ break;12021202+ default:12031203+ break;12041204+ }12051205+12051206 mutex_unlock(&trf->lock);12061207}12071208···12271206 .abort_cmd = trf7970a_abort_cmd,12281207};1229120812091209+static int trf7970a_get_autosuspend_delay(struct device_node *np)12101210+{12111211+ int autosuspend_delay, ret;12121212+12131213+ ret = of_property_read_u32(np, "autosuspend-delay", &autosuspend_delay);12141214+ if (ret)12151215+ autosuspend_delay = TRF7970A_AUTOSUSPEND_DELAY;12161216+12171217+ of_node_put(np);12181218+12191219+ return autosuspend_delay;12201220+}12211221+12301222static int trf7970a_probe(struct spi_device *spi)12311223{12321224 struct device_node *np = spi->dev.of_node;12331225 const struct spi_device_id *id = spi_get_device_id(spi);12341226 struct trf7970a *trf;12351235- int ret;12271227+ int uvolts, autosuspend_delay, ret;1236122812371229 if (!np) {12381230 dev_err(&spi->dev, "No Device Tree entry\n");···13151281 goto err_destroy_lock;13161282 }1317128313181318- trf->powering_up = true;12841284+ uvolts = regulator_get_voltage(trf->regulator);12851285+12861286+ if (uvolts > 4000000)12871287+ trf->chip_status_ctrl = TRF7970A_CHIP_STATUS_VRS5_3;1319128813201289 trf->ddev = nfc_digital_allocate_device(&trf7970a_nfc_ops,13211290 TRF7970A_SUPPORTED_PROTOCOLS,···13341297 nfc_digital_set_drvdata(trf->ddev, trf);13351298 spi_set_drvdata(spi, trf);1336129913001300+ autosuspend_delay = trf7970a_get_autosuspend_delay(np);13011301+13021302+ pm_runtime_set_autosuspend_delay(trf->dev, autosuspend_delay);13031303+ pm_runtime_use_autosuspend(trf->dev);13041304+ pm_runtime_enable(trf->dev);13051305+13371306 ret = nfc_digital_register_device(trf->ddev);13381307 if (ret) {13391308 dev_err(trf->dev, "Can't register NFC digital device: %d\n",···13501307 return 0;1351130813521309err_free_ddev:13101310+ pm_runtime_disable(trf->dev);13531311 nfc_digital_free_device(trf->ddev);13541312err_disable_regulator:13551313 regulator_disable(trf->regulator);···1365132113661322 mutex_lock(&trf->lock);1367132313681368- trf7970a_switch_rf_off(trf);13691369- trf7970a_init(trf);13701370-13711324 switch (trf->state) {13721325 case TRF7970A_ST_WAIT_FOR_TX_FIFO:13731326 case TRF7970A_ST_WAIT_FOR_RX_DATA:13741327 case TRF7970A_ST_WAIT_FOR_RX_DATA_CONT:13751328 case TRF7970A_ST_WAIT_TO_ISSUE_EOF:13761329 trf7970a_send_err_upstream(trf, -ECANCELED);13301330+ /* FALLTHROUGH */13311331+ case TRF7970A_ST_IDLE:13321332+ case TRF7970A_ST_IDLE_RX_BLOCKED:13331333+ pm_runtime_put_sync(trf->dev);13771334 break;13781335 default:13791336 break;13801337 }1381133813821339 mutex_unlock(&trf->lock);13401340+13411341+ pm_runtime_disable(trf->dev);1383134213841343 nfc_digital_unregister_device(trf->ddev);13851344 nfc_digital_free_device(trf->ddev);···1393134613941347 return 0;13951348}13491349+13501350+#ifdef CONFIG_PM_RUNTIME13511351+static int trf7970a_pm_runtime_suspend(struct device *dev)13521352+{13531353+ struct spi_device *spi = container_of(dev, struct spi_device, dev);13541354+ struct trf7970a *trf = spi_get_drvdata(spi);13551355+ int ret;13561356+13571357+ dev_dbg(dev, "Runtime suspend\n");13581358+13591359+ if (trf->state != TRF7970A_ST_OFF) {13601360+ dev_dbg(dev, "Can't suspend - not in OFF state (%d)\n",13611361+ trf->state);13621362+ return -EBUSY;13631363+ }13641364+13651365+ gpio_set_value(trf->en_gpio, 0);13661366+ gpio_set_value(trf->en2_gpio, 0);13671367+13681368+ ret = regulator_disable(trf->regulator);13691369+ if (ret)13701370+ dev_err(dev, "%s - Can't disable VIN: %d\n", __func__, ret);13711371+13721372+ return ret;13731373+}13741374+13751375+static int trf7970a_pm_runtime_resume(struct device *dev)13761376+{13771377+ struct spi_device *spi = container_of(dev, struct spi_device, dev);13781378+ struct trf7970a *trf = spi_get_drvdata(spi);13791379+ int ret;13801380+13811381+ dev_dbg(dev, "Runtime resume\n");13821382+13831383+ ret = regulator_enable(trf->regulator);13841384+ if (ret) {13851385+ dev_err(dev, "%s - Can't enable VIN: %d\n", __func__, ret);13861386+ return ret;13871387+ }13881388+13891389+ usleep_range(5000, 6000);13901390+13911391+ gpio_set_value(trf->en2_gpio, 1);13921392+ usleep_range(1000, 2000);13931393+ gpio_set_value(trf->en_gpio, 1);13941394+13951395+ usleep_range(20000, 21000);13961396+13971397+ ret = trf7970a_init(trf);13981398+ if (ret) {13991399+ dev_err(dev, "%s - Can't initialize: %d\n", __func__, ret);14001400+ return ret;14011401+ }14021402+14031403+ pm_runtime_mark_last_busy(dev);14041404+14051405+ return 0;14061406+}14071407+#endif14081408+14091409+static const struct dev_pm_ops trf7970a_pm_ops = {14101410+ SET_RUNTIME_PM_OPS(trf7970a_pm_runtime_suspend,14111411+ trf7970a_pm_runtime_resume, NULL)14121412+};1396141313971414static const struct spi_device_id trf7970a_id_table[] = {13981415 { "trf7970a", TRF7970A_QUIRK_IRQ_STATUS_READ_ERRATA },···14711360 .driver = {14721361 .name = "trf7970a",14731362 .owner = THIS_MODULE,13631363+ .pm = &trf7970a_pm_ops,14741364 },14751365};14761366
···36363737 int (*get_mac_revision)(void);3838 int (*external_reset)(void);3939+4040+ bool use_eeprom;3941};40424143#endif /* _LINUX_ATH9K_PLATFORM_H */
···11+/*22+ * Driver include for the ST21NFCA NFC chip.33+ *44+ * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved.55+ *66+ * This program is free software; you can redistribute it and/or modify it77+ * under the terms and conditions of the GNU General Public License,88+ * version 2, as published by the Free Software Foundation.99+ *1010+ * This program is distributed in the hope that it will be useful,1111+ * but WITHOUT ANY WARRANTY; without even the implied warranty of1212+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1313+ * GNU General Public License for more details.1414+ *1515+ * You should have received a copy of the GNU General Public License1616+ * along with this program; if not, see <http://www.gnu.org/licenses/>.1717+ */1818+1919+#ifndef _ST21NFCA_HCI_H_2020+#define _ST21NFCA_HCI_H_2121+2222+#include <linux/i2c.h>2323+2424+#define ST21NFCA_HCI_DRIVER_NAME "st21nfca_hci"2525+2626+struct st21nfca_nfc_platform_data {2727+ unsigned int gpio_irq;2828+ unsigned int gpio_ena;2929+ unsigned int irq_polarity;3030+};3131+3232+#endif /* _ST21NFCA_HCI_H_ */
-10
include/linux/rfkill-gpio.h
···2727 * struct rfkill_gpio_platform_data - platform data for rfkill gpio device.2828 * for unused gpio's, the expected value is -1.2929 * @name: name for the gpio rf kill instance3030- * @reset_gpio: GPIO which is used for reseting rfkill switch3131- * @shutdown_gpio: GPIO which is used for shutdown of rfkill switch3232- * @power_clk_name: [optional] name of clk to turn off while blocked3333- * @gpio_runtime_close: clean up platform specific gpio configuration3434- * @gpio_runtime_setup: set up platform specific gpio configuration3530 */36313732struct rfkill_gpio_platform_data {3833 char *name;3939- int reset_gpio;4040- int shutdown_gpio;4141- const char *power_clk_name;4234 enum rfkill_type type;4343- void (*gpio_runtime_close)(struct platform_device *);4444- int (*gpio_runtime_setup)(struct platform_device *);4535};46364737#endif /* __RFKILL_GPIO_H */
+1
include/linux/ssb/ssb.h
···3333 u8 et1phyaddr; /* MII address for enet1 */3434 u8 et0mdcport; /* MDIO for enet0 */3535 u8 et1mdcport; /* MDIO for enet1 */3636+ u16 dev_id; /* Device ID overriding e.g. PCI ID */3637 u16 board_rev; /* Board revision number from SPROM. */3738 u16 board_num; /* Board number from SPROM. */3839 u16 board_type; /* Board type from SPROM. */
+133-58
include/net/cfg80211.h
···341341 * @seq_len: length of @seq.342342 */343343struct key_params {344344- u8 *key;345345- u8 *seq;344344+ const u8 *key;345345+ const u8 *seq;346346 int key_len;347347 int seq_len;348348 u32 cipher;···458458 */459459int cfg80211_chandef_dfs_required(struct wiphy *wiphy,460460 const struct cfg80211_chan_def *chandef,461461- enum nl80211_iftype);461461+ enum nl80211_iftype iftype);462462463463/**464464 * ieee80211_chandef_rate_flags - returns rate flags for a channel···694694 *695695 * @chandef: defines the channel to use after the switch696696 * @beacon_csa: beacon data while performing the switch697697- * @counter_offset_beacon: offset for the counter within the beacon (tail)698698- * @counter_offset_presp: offset for the counter within the probe response697697+ * @counter_offsets_beacon: offsets of the counters within the beacon (tail)698698+ * @counter_offsets_presp: offsets of the counters within the probe response699699+ * @n_counter_offsets_beacon: number of csa counters the beacon (tail)700700+ * @n_counter_offsets_presp: number of csa counters in the probe response699701 * @beacon_after: beacon data to be used on the new channel700702 * @radar_required: whether radar detection is required on the new channel701703 * @block_tx: whether transmissions should be blocked while changing···706704struct cfg80211_csa_settings {707705 struct cfg80211_chan_def chandef;708706 struct cfg80211_beacon_data beacon_csa;709709- u16 counter_offset_beacon, counter_offset_presp;707707+ const u16 *counter_offsets_beacon;708708+ const u16 *counter_offsets_presp;709709+ unsigned int n_counter_offsets_beacon;710710+ unsigned int n_counter_offsets_presp;710711 struct cfg80211_beacon_data beacon_after;711712 bool radar_required;712713 bool block_tx;···873868 * @STATION_INFO_NONPEER_PM: @nonpeer_pm filled874869 * @STATION_INFO_CHAIN_SIGNAL: @chain_signal filled875870 * @STATION_INFO_CHAIN_SIGNAL_AVG: @chain_signal_avg filled871871+ * @STATION_INFO_EXPECTED_THROUGHPUT: @expected_throughput filled876872 */877873enum station_info_flags {878878- STATION_INFO_INACTIVE_TIME = 1<<0,879879- STATION_INFO_RX_BYTES = 1<<1,880880- STATION_INFO_TX_BYTES = 1<<2,881881- STATION_INFO_LLID = 1<<3,882882- STATION_INFO_PLID = 1<<4,883883- STATION_INFO_PLINK_STATE = 1<<5,884884- STATION_INFO_SIGNAL = 1<<6,885885- STATION_INFO_TX_BITRATE = 1<<7,886886- STATION_INFO_RX_PACKETS = 1<<8,887887- STATION_INFO_TX_PACKETS = 1<<9,888888- STATION_INFO_TX_RETRIES = 1<<10,889889- STATION_INFO_TX_FAILED = 1<<11,890890- STATION_INFO_RX_DROP_MISC = 1<<12,891891- STATION_INFO_SIGNAL_AVG = 1<<13,892892- STATION_INFO_RX_BITRATE = 1<<14,893893- STATION_INFO_BSS_PARAM = 1<<15,894894- STATION_INFO_CONNECTED_TIME = 1<<16,895895- STATION_INFO_ASSOC_REQ_IES = 1<<17,896896- STATION_INFO_STA_FLAGS = 1<<18,897897- STATION_INFO_BEACON_LOSS_COUNT = 1<<19,898898- STATION_INFO_T_OFFSET = 1<<20,899899- STATION_INFO_LOCAL_PM = 1<<21,900900- STATION_INFO_PEER_PM = 1<<22,901901- STATION_INFO_NONPEER_PM = 1<<23,902902- STATION_INFO_RX_BYTES64 = 1<<24,903903- STATION_INFO_TX_BYTES64 = 1<<25,904904- STATION_INFO_CHAIN_SIGNAL = 1<<26,905905- STATION_INFO_CHAIN_SIGNAL_AVG = 1<<27,874874+ STATION_INFO_INACTIVE_TIME = BIT(0),875875+ STATION_INFO_RX_BYTES = BIT(1),876876+ STATION_INFO_TX_BYTES = BIT(2),877877+ STATION_INFO_LLID = BIT(3),878878+ STATION_INFO_PLID = BIT(4),879879+ STATION_INFO_PLINK_STATE = BIT(5),880880+ STATION_INFO_SIGNAL = BIT(6),881881+ STATION_INFO_TX_BITRATE = BIT(7),882882+ STATION_INFO_RX_PACKETS = BIT(8),883883+ STATION_INFO_TX_PACKETS = BIT(9),884884+ STATION_INFO_TX_RETRIES = BIT(10),885885+ STATION_INFO_TX_FAILED = BIT(11),886886+ STATION_INFO_RX_DROP_MISC = BIT(12),887887+ STATION_INFO_SIGNAL_AVG = BIT(13),888888+ STATION_INFO_RX_BITRATE = BIT(14),889889+ STATION_INFO_BSS_PARAM = BIT(15),890890+ STATION_INFO_CONNECTED_TIME = BIT(16),891891+ STATION_INFO_ASSOC_REQ_IES = BIT(17),892892+ STATION_INFO_STA_FLAGS = BIT(18),893893+ STATION_INFO_BEACON_LOSS_COUNT = BIT(19),894894+ STATION_INFO_T_OFFSET = BIT(20),895895+ STATION_INFO_LOCAL_PM = BIT(21),896896+ STATION_INFO_PEER_PM = BIT(22),897897+ STATION_INFO_NONPEER_PM = BIT(23),898898+ STATION_INFO_RX_BYTES64 = BIT(24),899899+ STATION_INFO_TX_BYTES64 = BIT(25),900900+ STATION_INFO_CHAIN_SIGNAL = BIT(26),901901+ STATION_INFO_CHAIN_SIGNAL_AVG = BIT(27),902902+ STATION_INFO_EXPECTED_THROUGHPUT = BIT(28),906903};907904908905/**···10261019 * @local_pm: local mesh STA power save mode10271020 * @peer_pm: peer mesh STA power save mode10281021 * @nonpeer_pm: non-peer mesh STA power save mode10221022+ * @expected_throughput: expected throughput in kbps (including 802.11 headers)10231023+ * towards this station.10291024 */10301025struct station_info {10311026 u32 filled;···10661057 enum nl80211_mesh_power_mode peer_pm;10671058 enum nl80211_mesh_power_mode nonpeer_pm;1068105910601060+ u32 expected_throughput;10611061+10691062 /*10701063 * Note: Add a new enum station_info_flags value for each new field and10711064 * use it to check which fields are initialized.10721065 */10731066};10671067+10681068+/**10691069+ * cfg80211_get_station - retrieve information about a given station10701070+ * @dev: the device where the station is supposed to be connected to10711071+ * @mac_addr: the mac address of the station of interest10721072+ * @sinfo: pointer to the structure to fill with the information10731073+ *10741074+ * Returns 0 on success and sinfo is filled with the available information10751075+ * otherwise returns a negative error code and the content of sinfo has to be10761076+ * considered undefined.10771077+ */10781078+int cfg80211_get_station(struct net_device *dev, const u8 *mac_addr,10791079+ struct station_info *sinfo);1074108010751081/**10761082 * enum monitor_flags - monitor flags···11881164 int use_cts_prot;11891165 int use_short_preamble;11901166 int use_short_slot_time;11911191- u8 *basic_rates;11671167+ const u8 *basic_rates;11921168 u8 basic_rates_len;11931169 int ap_isolate;11941170 int ht_opmode;···17181694 * @ht_capa_mask: The bits of ht_capa which are to be used.17191695 */17201696struct cfg80211_ibss_params {17211721- u8 *ssid;17221722- u8 *bssid;16971697+ const u8 *ssid;16981698+ const u8 *bssid;17231699 struct cfg80211_chan_def chandef;17241724- u8 *ie;17001700+ const u8 *ie;17251701 u8 ssid_len, ie_len;17261702 u16 beacon_interval;17271703 u32 basic_rates;···18301806 * @pmkid: The PMK material itself.18311807 */18321808struct cfg80211_pmksa {18331833- u8 *bssid;18341834- u8 *pmkid;18091809+ const u8 *bssid;18101810+ const u8 *pmkid;18351811};1836181218371813/**···18461822 * memory, free @mask only!18471823 */18481824struct cfg80211_pkt_pattern {18491849- u8 *mask, *pattern;18251825+ const u8 *mask, *pattern;18501826 int pattern_len;18511827 int pkt_offset;18521828};···20101986 * @len: buffer length20111987 * @no_cck: don't use cck rates for this frame20121988 * @dont_wait_for_ack: tells the low level not to wait for an ack19891989+ * @n_csa_offsets: length of csa_offsets array19901990+ * @csa_offsets: array of all the csa offsets in the frame20131991 */20141992struct cfg80211_mgmt_tx_params {20151993 struct ieee80211_channel *chan;···20211995 size_t len;20221996 bool no_cck;20231997 bool dont_wait_for_ack;19981998+ int n_csa_offsets;19991999+ const u16 *csa_offsets;20242000};2025200120262002/**···236423362365233723662338 int (*add_station)(struct wiphy *wiphy, struct net_device *dev,23672367- u8 *mac, struct station_parameters *params);23392339+ const u8 *mac,23402340+ struct station_parameters *params);23682341 int (*del_station)(struct wiphy *wiphy, struct net_device *dev,23692369- u8 *mac);23422342+ const u8 *mac);23702343 int (*change_station)(struct wiphy *wiphy, struct net_device *dev,23712371- u8 *mac, struct station_parameters *params);23442344+ const u8 *mac,23452345+ struct station_parameters *params);23722346 int (*get_station)(struct wiphy *wiphy, struct net_device *dev,23732373- u8 *mac, struct station_info *sinfo);23472347+ const u8 *mac, struct station_info *sinfo);23742348 int (*dump_station)(struct wiphy *wiphy, struct net_device *dev,23752375- int idx, u8 *mac, struct station_info *sinfo);23492349+ int idx, u8 *mac, struct station_info *sinfo);2376235023772351 int (*add_mpath)(struct wiphy *wiphy, struct net_device *dev,23782378- u8 *dst, u8 *next_hop);23522352+ const u8 *dst, const u8 *next_hop);23792353 int (*del_mpath)(struct wiphy *wiphy, struct net_device *dev,23802380- u8 *dst);23542354+ const u8 *dst);23812355 int (*change_mpath)(struct wiphy *wiphy, struct net_device *dev,23822382- u8 *dst, u8 *next_hop);23562356+ const u8 *dst, const u8 *next_hop);23832357 int (*get_mpath)(struct wiphy *wiphy, struct net_device *dev,23842384- u8 *dst, u8 *next_hop,23852385- struct mpath_info *pinfo);23582358+ u8 *dst, u8 *next_hop, struct mpath_info *pinfo);23862359 int (*dump_mpath)(struct wiphy *wiphy, struct net_device *dev,23872387- int idx, u8 *dst, u8 *next_hop,23882388- struct mpath_info *pinfo);23602360+ int idx, u8 *dst, u8 *next_hop,23612361+ struct mpath_info *pinfo);23892362 int (*get_mesh_config)(struct wiphy *wiphy,23902363 struct net_device *dev,23912364 struct mesh_config *conf);···25162487 struct cfg80211_gtk_rekey_data *data);2517248825182489 int (*tdls_mgmt)(struct wiphy *wiphy, struct net_device *dev,25192519- u8 *peer, u8 action_code, u8 dialog_token,24902490+ const u8 *peer, u8 action_code, u8 dialog_token,25202491 u16 status_code, u32 peer_capability,25212492 const u8 *buf, size_t len);25222493 int (*tdls_oper)(struct wiphy *wiphy, struct net_device *dev,25232523- u8 *peer, enum nl80211_tdls_operation oper);24942494+ const u8 *peer, enum nl80211_tdls_operation oper);2524249525252496 int (*probe_client)(struct wiphy *wiphy, struct net_device *dev,25262497 const u8 *peer, u64 *cookie);···26672638 * between infrastructure and AP types must match. This is required26682639 * only in special cases.26692640 * @radar_detect_widths: bitmap of channel widths supported for radar detection26412641+ * @radar_detect_regions: bitmap of regions supported for radar detection26702642 *26712643 * With this structure the driver can describe which interface26722644 * combinations it supports concurrently.···27252695 u8 n_limits;27262696 bool beacon_int_infra_match;27272697 u8 radar_detect_widths;26982698+ u8 radar_detect_regions;27282699};2729270027302701struct ieee80211_txrx_stypes {···29562925 * (including P2P GO) or 0 to indicate no such limit is advertised. The29572926 * driver is allowed to advertise a theoretical limit that it can reach in29582927 * some cases, but may not always reach.29282928+ *29292929+ * @max_num_csa_counters: Number of supported csa_counters in beacons29302930+ * and probe responses. This value should be set if the driver29312931+ * wishes to limit the number of csa counters. Default (0) means29322932+ * infinite.29332933+ * @max_adj_channel_rssi_comp: max offset of between the channel on which the29342934+ * frame was sent and the channel on which the frame was heard for which29352935+ * the reported rssi is still valid. If a driver is able to compensate the29362936+ * low rssi when a frame is heard on different channel, then it should set29372937+ * this variable to the maximal offset for which it can compensate.29382938+ * This value should be set in MHz.29592939 */29602940struct wiphy {29612941 /* assign these fields before you register the wiphy */···30833041 int n_vendor_commands, n_vendor_events;3084304230853043 u16 max_ap_assoc_sta;30443044+30453045+ u8 max_num_csa_counters;30463046+ u8 max_adj_channel_rssi_comp;3086304730873048 char priv[0] __aligned(NETDEV_ALIGN);30883049};···33153270 struct cfg80211_ibss_params ibss;33163271 struct cfg80211_connect_params connect;33173272 struct cfg80211_cached_keys *keys;33183318- u8 *ie;32733273+ const u8 *ie;33193274 size_t ie_len;33203275 u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];33213276 u8 ssid[IEEE80211_MAX_SSID_LEN];···35563511 * Return: 0 on success, or a negative error code.35573512 */35583513int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,35593559- enum nl80211_iftype iftype, u8 *bssid, bool qos);35143514+ enum nl80211_iftype iftype, const u8 *bssid,35153515+ bool qos);3560351635613517/**35623518 * ieee80211_amsdu_to_8023s - decode an IEEE 802.11n A-MSDU frame···43584312 * and not try to connect to any AP any more.43594313 */43604314void cfg80211_disconnected(struct net_device *dev, u16 reason,43614361- u8 *ie, size_t ie_len, gfp_t gfp);43154315+ const u8 *ie, size_t ie_len, gfp_t gfp);4362431643634317/**43644318 * cfg80211_ready_on_channel - notification of remain_on_channel start···48134767 void (*iter)(const struct ieee80211_iface_combination *c,48144768 void *data),48154769 void *data);47704770+47714771+/*47724772+ * cfg80211_stop_iface - trigger interface disconnection47734773+ *47744774+ * @wiphy: the wiphy47754775+ * @wdev: wireless device47764776+ * @gfp: context flags47774777+ *47784778+ * Trigger interface to be stopped as if AP was stopped, IBSS/mesh left, STA47794779+ * disconnected.47804780+ *47814781+ * Note: This doesn't need any locks and is asynchronous.47824782+ */47834783+void cfg80211_stop_iface(struct wiphy *wiphy, struct wireless_dev *wdev,47844784+ gfp_t gfp);47854785+47864786+/**47874787+ * cfg80211_shutdown_all_interfaces - shut down all interfaces for a wiphy47884788+ * @wiphy: the wiphy to shut down47894789+ *47904790+ * This function shuts down all interfaces belonging to this wiphy by47914791+ * calling dev_close() (and treating non-netdev interfaces as needed).47924792+ * It shouldn't really be used unless there are some fatal device errors47934793+ * that really can't be recovered in any other way.47944794+ *47954795+ * Callers must hold the RTNL and be able to deal with callbacks into47964796+ * the driver while the function is running.47974797+ */47984798+void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy);4816479948174800/* Logging, debugging and troubleshooting/diagnostic helpers. */48184801
+70-8
include/net/mac80211.h
···11131113 * @addr: address of this interface11141114 * @p2p: indicates whether this AP or STA interface is a p2p11151115 * interface, i.e. a GO or p2p-sta respectively11161116- * @csa_active: marks whether a channel switch is going on11161116+ * @csa_active: marks whether a channel switch is going on. Internally it is11171117+ * write-protected by sdata_lock and local->mtx so holding either is fine11181118+ * for read access.11171119 * @driver_flags: flags/capabilities the driver has for this interface,11181120 * these need to be set (or cleared) when the interface is added11191121 * or, if supported by the driver, the interface type is changed···13761374 * the station moves to associated state.13771375 * @smps_mode: current SMPS mode (off, static or dynamic)13781376 * @rates: rate control selection table13771377+ * @tdls: indicates whether the STA is a TDLS peer13791378 */13801379struct ieee80211_sta {13811380 u32 supp_rates[IEEE80211_NUM_BANDS];···13911388 enum ieee80211_sta_rx_bandwidth bandwidth;13921389 enum ieee80211_smps_mode smps_mode;13931390 struct ieee80211_sta_rates __rcu *rates;13911391+ bool tdls;1394139213951393 /* must be last */13961394 u8 drv_priv[0] __aligned(sizeof(void *));···27692765 * information in bss_conf is set up and the beacon can be retrieved. A27702766 * channel context is bound before this is called.27712767 * @leave_ibss: Leave the IBSS again.27682768+ *27692769+ * @get_expected_throughput: extract the expected throughput towards the27702770+ * specified station. The returned value is expressed in Kbps. It returns 027712771+ * if the RC algorithm does not have proper data to provide.27722772 */27732773struct ieee80211_ops {27742774 void (*tx)(struct ieee80211_hw *hw,···2966295829672959 int (*join_ibss)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);29682960 void (*leave_ibss)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);29612961+ u32 (*get_expected_throughput)(struct ieee80211_sta *sta);29692962};2970296329712964/**···34163407 */34173408void ieee80211_report_low_ack(struct ieee80211_sta *sta, u32 num_packets);3418340934103410+#define IEEE80211_MAX_CSA_COUNTERS_NUM 234113411+34123412+/**34133413+ * struct ieee80211_mutable_offsets - mutable beacon offsets34143414+ * @tim_offset: position of TIM element34153415+ * @tim_length: size of TIM element34163416+ * @csa_counter_offs: array of IEEE80211_MAX_CSA_COUNTERS_NUM offsets34173417+ * to CSA counters. This array can contain zero values which34183418+ * should be ignored.34193419+ */34203420+struct ieee80211_mutable_offsets {34213421+ u16 tim_offset;34223422+ u16 tim_length;34233423+34243424+ u16 csa_counter_offs[IEEE80211_MAX_CSA_COUNTERS_NUM];34253425+};34263426+34273427+/**34283428+ * ieee80211_beacon_get_template - beacon template generation function34293429+ * @hw: pointer obtained from ieee80211_alloc_hw().34303430+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.34313431+ * @offs: &struct ieee80211_mutable_offsets pointer to struct that will34323432+ * receive the offsets that may be updated by the driver.34333433+ *34343434+ * If the driver implements beaconing modes, it must use this function to34353435+ * obtain the beacon template.34363436+ *34373437+ * This function should be used if the beacon frames are generated by the34383438+ * device, and then the driver must use the returned beacon as the template34393439+ * The driver or the device are responsible to update the DTIM and, when34403440+ * applicable, the CSA count.34413441+ *34423442+ * The driver is responsible for freeing the returned skb.34433443+ *34443444+ * Return: The beacon template. %NULL on error.34453445+ */34463446+struct sk_buff *34473447+ieee80211_beacon_get_template(struct ieee80211_hw *hw,34483448+ struct ieee80211_vif *vif,34493449+ struct ieee80211_mutable_offsets *offs);34503450+34193451/**34203452 * ieee80211_beacon_get_tim - beacon generation function34213453 * @hw: pointer obtained from ieee80211_alloc_hw().···34683418 * Set to 0 if invalid (in non-AP modes).34693419 *34703420 * If the driver implements beaconing modes, it must use this function to34713471- * obtain the beacon frame/template.34213421+ * obtain the beacon frame.34723422 *34733423 * If the beacon frames are generated by the host system (i.e., not in34743424 * hardware/firmware), the driver uses this function to get each beacon34753475- * frame from mac80211 -- it is responsible for calling this function34763476- * before the beacon is needed (e.g. based on hardware interrupt).34773477- *34783478- * If the beacon frames are generated by the device, then the driver34793479- * must use the returned beacon as the template and change the TIM IE34803480- * according to the current DTIM parameters/TIM bitmap.34253425+ * frame from mac80211 -- it is responsible for calling this function exactly34263426+ * once before the beacon is needed (e.g. based on hardware interrupt).34813427 *34823428 * The driver is responsible for freeing the returned skb.34833429 *···34973451{34983452 return ieee80211_beacon_get_tim(hw, vif, NULL, NULL);34993453}34543454+34553455+/**34563456+ * ieee80211_csa_update_counter - request mac80211 to decrement the csa counter34573457+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.34583458+ *34593459+ * The csa counter should be updated after each beacon transmission.34603460+ * This function is called implicitly when34613461+ * ieee80211_beacon_get/ieee80211_beacon_get_tim are called, however if the34623462+ * beacon frames are generated by the device, the driver should call this34633463+ * function after each beacon transmission to sync mac80211's csa counters.34643464+ *34653465+ * Return: new csa counter value34663466+ */34673467+u8 ieee80211_csa_update_counter(struct ieee80211_vif *vif);3500346835013469/**35023470 * ieee80211_csa_finish - notify mac80211 about channel switch···45404480 void (*add_sta_debugfs)(void *priv, void *priv_sta,45414481 struct dentry *dir);45424482 void (*remove_sta_debugfs)(void *priv, void *priv_sta);44834483+44844484+ u32 (*get_expected_throughput)(void *priv_sta);45434485};4544448645454487static inline int rate_supported(struct ieee80211_sta *sta,
···503503 * TX status event pertaining to the TX request.504504 * %NL80211_ATTR_TX_NO_CCK_RATE is used to decide whether to send the505505 * management frames at CCK rate or not in 2GHz band.506506+ * %NL80211_ATTR_CSA_C_OFFSETS_TX is an array of offsets to CSA507507+ * counters which will be updated to the current value. This attribute508508+ * is used during CSA period.506509 * @NL80211_CMD_FRAME_WAIT_CANCEL: When an off-channel TX was requested, this507510 * command may be used with the corresponding cookie to cancel the wait508511 * time if it is known that it is no longer necessary.···15281525 * operation).15291526 * @NL80211_ATTR_CSA_IES: Nested set of attributes containing the IE information15301527 * for the time while performing a channel switch.15311531- * @NL80211_ATTR_CSA_C_OFF_BEACON: Offset of the channel switch counter15321532- * field in the beacons tail (%NL80211_ATTR_BEACON_TAIL).15331533- * @NL80211_ATTR_CSA_C_OFF_PRESP: Offset of the channel switch counter15341534- * field in the probe response (%NL80211_ATTR_PROBE_RESP).15281528+ * @NL80211_ATTR_CSA_C_OFF_BEACON: An array of offsets (u16) to the channel15291529+ * switch counters in the beacons tail (%NL80211_ATTR_BEACON_TAIL).15301530+ * @NL80211_ATTR_CSA_C_OFF_PRESP: An array of offsets (u16) to the channel15311531+ * switch counters in the probe response (%NL80211_ATTR_PROBE_RESP).15351532 *15361533 * @NL80211_ATTR_RXMGMT_FLAGS: flags for nl80211_send_mgmt(), u32.15371534 * As specified in the &enum nl80211_rxmgmt_flags.···15781575 * other concurrent operations may affect this), drivers are allowed to15791576 * advertise values that cannot always be met. In such cases, an attempt15801577 * to add a new station entry with @NL80211_CMD_NEW_STATION may fail.15781578+ *15791579+ * @NL80211_ATTR_CSA_C_OFFSETS_TX: An array of csa counter offsets (u16) which15801580+ * should be updated when the frame is transmitted.15811581+ * @NL80211_ATTR_MAX_CSA_COUNTERS: U8 attribute used to advertise the maximum15821582+ * supported number of csa counters.15811583 *15821584 * @NL80211_ATTR_TDLS_PEER_CAPABILITY: flags for TDLS peer capabilities, u32.15831585 * As specified in the &enum nl80211_tdls_peer_capability.···1928192019291921 NL80211_ATTR_IFACE_SOCKET_OWNER,1930192219231923+ NL80211_ATTR_CSA_C_OFFSETS_TX,19241924+ NL80211_ATTR_MAX_CSA_COUNTERS,19251925+19311926 /* add attributes here, update the policy in nl80211.c */1932192719331928 __NL80211_ATTR_AFTER_LAST,···21992188 * Contains a nested array of signal strength attributes (u8, dBm)22002189 * @NL80211_STA_INFO_CHAIN_SIGNAL_AVG: per-chain signal strength average22012190 * Same format as NL80211_STA_INFO_CHAIN_SIGNAL.21912191+ * @NL80211_STA_EXPECTED_THROUGHPUT: expected throughput considering also the21922192+ * 802.11 header (u32, kbps)22022193 * @__NL80211_STA_INFO_AFTER_LAST: internal22032194 * @NL80211_STA_INFO_MAX: highest possible station info attribute22042195 */···22322219 NL80211_STA_INFO_TX_BYTES64,22332220 NL80211_STA_INFO_CHAIN_SIGNAL,22342221 NL80211_STA_INFO_CHAIN_SIGNAL_AVG,22222222+ NL80211_STA_INFO_EXPECTED_THROUGHPUT,2235222322362224 /* keep last */22372225 __NL80211_STA_INFO_AFTER_LAST,···37023688 * different channels may be used within this group.37033689 * @NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS: u32 attribute containing the bitmap37043690 * of supported channel widths for radar detection.36913691+ * @NL80211_IFACE_COMB_RADAR_DETECT_REGIONS: u32 attribute containing the bitmap36923692+ * of supported regulatory regions for radar detection.37053693 * @NUM_NL80211_IFACE_COMB: number of attributes37063694 * @MAX_NL80211_IFACE_COMB: highest attribute number37073695 *···37373721 NL80211_IFACE_COMB_STA_AP_BI_MATCH,37383722 NL80211_IFACE_COMB_NUM_CHANNELS,37393723 NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS,37243724+ NL80211_IFACE_COMB_RADAR_DETECT_REGIONS,3740372537413726 /* keep last */37423727 NUM_NL80211_IFACE_COMB,
···23282328/* functions for drivers to get certain frames */2329232923302330static void __ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,23312331- struct ps_data *ps, struct sk_buff *skb)23312331+ struct ps_data *ps, struct sk_buff *skb,23322332+ bool is_template)23322333{23332334 u8 *pos, *tim;23342335 int aid0 = 0;···23422341 * checking byte-for-byte */23432342 have_bits = !bitmap_empty((unsigned long *)ps->tim,23442343 IEEE80211_MAX_AID+1);23452345-23462346- if (ps->dtim_count == 0)23472347- ps->dtim_count = sdata->vif.bss_conf.dtim_period - 1;23482348- else23492349- ps->dtim_count--;23442344+ if (!is_template) {23452345+ if (ps->dtim_count == 0)23462346+ ps->dtim_count = sdata->vif.bss_conf.dtim_period - 1;23472347+ else23482348+ ps->dtim_count--;23492349+ }2350235023512351 tim = pos = (u8 *) skb_put(skb, 6);23522352 *pos++ = WLAN_EID_TIM;···23932391}2394239223952393static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,23962396- struct ps_data *ps, struct sk_buff *skb)23942394+ struct ps_data *ps, struct sk_buff *skb,23952395+ bool is_template)23972396{23982397 struct ieee80211_local *local = sdata->local;23992398···24062403 * of the tim bitmap in mac80211 and the driver.24072404 */24082405 if (local->tim_in_locked_section) {24092409- __ieee80211_beacon_add_tim(sdata, ps, skb);24062406+ __ieee80211_beacon_add_tim(sdata, ps, skb, is_template);24102407 } else {24112408 spin_lock_bh(&local->tim_lock);24122412- __ieee80211_beacon_add_tim(sdata, ps, skb);24092409+ __ieee80211_beacon_add_tim(sdata, ps, skb, is_template);24132410 spin_unlock_bh(&local->tim_lock);24142411 }2415241224162413 return 0;24172414}2418241524192419-static void ieee80211_update_csa(struct ieee80211_sub_if_data *sdata,24202420- struct beacon_data *beacon)24162416+static void ieee80211_set_csa(struct ieee80211_sub_if_data *sdata,24172417+ struct beacon_data *beacon)24212418{24222419 struct probe_resp *resp;24232423- int counter_offset_beacon = sdata->csa_counter_offset_beacon;24242424- int counter_offset_presp = sdata->csa_counter_offset_presp;24252420 u8 *beacon_data;24262421 size_t beacon_data_len;24222422+ int i;24232423+ u8 count = sdata->csa_current_counter;2427242424282425 switch (sdata->vif.type) {24292426 case NL80211_IFTYPE_AP:···24412438 default:24422439 return;24432440 }24442444- if (WARN_ON(counter_offset_beacon >= beacon_data_len))24452445- return;2446244124472447- /* Warn if the driver did not check for/react to csa24482448- * completeness. A beacon with CSA counter set to 0 should24492449- * never occur, because a counter of 1 means switch just24502450- * before the next beacon.24512451- */24522452- if (WARN_ON(beacon_data[counter_offset_beacon] == 1))24532453- return;24422442+ for (i = 0; i < IEEE80211_MAX_CSA_COUNTERS_NUM; ++i) {24432443+ u16 counter_offset_beacon =24442444+ sdata->csa_counter_offset_beacon[i];24452445+ u16 counter_offset_presp = sdata->csa_counter_offset_presp[i];2454244624552455- beacon_data[counter_offset_beacon]--;24472447+ if (counter_offset_beacon) {24482448+ if (WARN_ON(counter_offset_beacon >= beacon_data_len))24492449+ return;2456245024572457- if (sdata->vif.type == NL80211_IFTYPE_AP && counter_offset_presp) {24582458- rcu_read_lock();24592459- resp = rcu_dereference(sdata->u.ap.probe_resp);24602460-24612461- /* if nl80211 accepted the offset, this should not happen. */24622462- if (WARN_ON(!resp)) {24632463- rcu_read_unlock();24642464- return;24512451+ beacon_data[counter_offset_beacon] = count;24652452 }24662466- resp->data[counter_offset_presp]--;24672467- rcu_read_unlock();24532453+24542454+ if (sdata->vif.type == NL80211_IFTYPE_AP &&24552455+ counter_offset_presp) {24562456+ rcu_read_lock();24572457+ resp = rcu_dereference(sdata->u.ap.probe_resp);24582458+24592459+ /* If nl80211 accepted the offset, this should24602460+ * not happen.24612461+ */24622462+ if (WARN_ON(!resp)) {24632463+ rcu_read_unlock();24642464+ return;24652465+ }24662466+ resp->data[counter_offset_presp] = count;24672467+ rcu_read_unlock();24682468+ }24682469 }24692470}24712471+24722472+u8 ieee80211_csa_update_counter(struct ieee80211_vif *vif)24732473+{24742474+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);24752475+24762476+ sdata->csa_current_counter--;24772477+24782478+ /* the counter should never reach 0 */24792479+ WARN_ON(!sdata->csa_current_counter);24802480+24812481+ return sdata->csa_current_counter;24822482+}24832483+EXPORT_SYMBOL(ieee80211_csa_update_counter);2470248424712485bool ieee80211_csa_is_complete(struct ieee80211_vif *vif)24722486{···24912471 struct beacon_data *beacon = NULL;24922472 u8 *beacon_data;24932473 size_t beacon_data_len;24942494- int counter_beacon = sdata->csa_counter_offset_beacon;24742474+ int counter_beacon = sdata->csa_counter_offset_beacon[0];24952475 int ret = false;2496247624972477 if (!ieee80211_sdata_running(sdata))···25412521}25422522EXPORT_SYMBOL(ieee80211_csa_is_complete);2543252325442544-struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,25452545- struct ieee80211_vif *vif,25462546- u16 *tim_offset, u16 *tim_length)25242524+static struct sk_buff *25252525+__ieee80211_beacon_get(struct ieee80211_hw *hw,25262526+ struct ieee80211_vif *vif,25272527+ struct ieee80211_mutable_offsets *offs,25282528+ bool is_template)25472529{25482530 struct ieee80211_local *local = hw_to_local(hw);25492531 struct sk_buff *skb = NULL;···25542532 enum ieee80211_band band;25552533 struct ieee80211_tx_rate_control txrc;25562534 struct ieee80211_chanctx_conf *chanctx_conf;25352535+ int csa_off_base = 0;2557253625582537 rcu_read_lock();25592538···25642541 if (!ieee80211_sdata_running(sdata) || !chanctx_conf)25652542 goto out;2566254325672567- if (tim_offset)25682568- *tim_offset = 0;25692569- if (tim_length)25702570- *tim_length = 0;25442544+ if (offs)25452545+ memset(offs, 0, sizeof(*offs));2571254625722547 if (sdata->vif.type == NL80211_IFTYPE_AP) {25732548 struct ieee80211_if_ap *ap = &sdata->u.ap;25742549 struct beacon_data *beacon = rcu_dereference(ap->beacon);2575255025762551 if (beacon) {25772577- if (sdata->vif.csa_active)25782578- ieee80211_update_csa(sdata, beacon);25522552+ if (sdata->vif.csa_active) {25532553+ if (!is_template)25542554+ ieee80211_csa_update_counter(vif);25552555+25562556+ ieee80211_set_csa(sdata, beacon);25572557+ }2579255825802559 /*25812560 * headroom, head length,···25942569 memcpy(skb_put(skb, beacon->head_len), beacon->head,25952570 beacon->head_len);2596257125972597- ieee80211_beacon_add_tim(sdata, &ap->ps, skb);25722572+ ieee80211_beacon_add_tim(sdata, &ap->ps, skb,25732573+ is_template);2598257425992599- if (tim_offset)26002600- *tim_offset = beacon->head_len;26012601- if (tim_length)26022602- *tim_length = skb->len - beacon->head_len;25752575+ if (offs) {25762576+ offs->tim_offset = beacon->head_len;25772577+ offs->tim_length = skb->len - beacon->head_len;25782578+25792579+ /* for AP the csa offsets are from tail */25802580+ csa_off_base = skb->len;25812581+ }2603258226042583 if (beacon->tail)26052584 memcpy(skb_put(skb, beacon->tail_len),···26182589 if (!presp)26192590 goto out;2620259126212621- if (sdata->vif.csa_active)26222622- ieee80211_update_csa(sdata, presp);25922592+ if (sdata->vif.csa_active) {25932593+ if (!is_template)25942594+ ieee80211_csa_update_counter(vif);2623259525962596+ ieee80211_set_csa(sdata, presp);25972597+ }2624259826252599 skb = dev_alloc_skb(local->tx_headroom + presp->head_len +26262600 local->hw.extra_beacon_tailroom);···26432611 if (!bcn)26442612 goto out;2645261326462646- if (sdata->vif.csa_active)26472647- ieee80211_update_csa(sdata, bcn);26142614+ if (sdata->vif.csa_active) {26152615+ if (!is_template)26162616+ /* TODO: For mesh csa_counter is in TU, so26172617+ * decrementing it by one isn't correct, but26182618+ * for now we leave it consistent with overall26192619+ * mac80211's behavior.26202620+ */26212621+ ieee80211_csa_update_counter(vif);26222622+26232623+ ieee80211_set_csa(sdata, bcn);26242624+ }2648262526492626 if (ifmsh->sync_ops)26502627 ifmsh->sync_ops->adjust_tbtt(sdata, bcn);···26672626 goto out;26682627 skb_reserve(skb, local->tx_headroom);26692628 memcpy(skb_put(skb, bcn->head_len), bcn->head, bcn->head_len);26702670- ieee80211_beacon_add_tim(sdata, &ifmsh->ps, skb);26292629+ ieee80211_beacon_add_tim(sdata, &ifmsh->ps, skb, is_template);26302630+26312631+ if (offs) {26322632+ offs->tim_offset = bcn->head_len;26332633+ offs->tim_length = skb->len - bcn->head_len;26342634+ }26352635+26712636 memcpy(skb_put(skb, bcn->tail_len), bcn->tail, bcn->tail_len);26722637 } else {26732638 WARN_ON(1);26742639 goto out;26402640+ }26412641+26422642+ /* CSA offsets */26432643+ if (offs) {26442644+ int i;26452645+26462646+ for (i = 0; i < IEEE80211_MAX_CSA_COUNTERS_NUM; i++) {26472647+ u16 csa_off = sdata->csa_counter_offset_beacon[i];26482648+26492649+ if (!csa_off)26502650+ continue;26512651+26522652+ offs->csa_counter_offs[i] = csa_off_base + csa_off;26532653+ }26752654 }2676265526772656 band = chanctx_conf->def.chan->band;···27242663 out:27252664 rcu_read_unlock();27262665 return skb;26662666+26672667+}26682668+26692669+struct sk_buff *26702670+ieee80211_beacon_get_template(struct ieee80211_hw *hw,26712671+ struct ieee80211_vif *vif,26722672+ struct ieee80211_mutable_offsets *offs)26732673+{26742674+ return __ieee80211_beacon_get(hw, vif, offs, true);26752675+}26762676+EXPORT_SYMBOL(ieee80211_beacon_get_template);26772677+26782678+struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,26792679+ struct ieee80211_vif *vif,26802680+ u16 *tim_offset, u16 *tim_length)26812681+{26822682+ struct ieee80211_mutable_offsets offs = {};26832683+ struct sk_buff *bcn = __ieee80211_beacon_get(hw, vif, &offs, false);26842684+26852685+ if (tim_offset)26862686+ *tim_offset = offs.tim_offset;26872687+26882688+ if (tim_length)26892689+ *tim_length = offs.tim_length;26902690+26912691+ return bcn;27272692}27282693EXPORT_SYMBOL(ieee80211_beacon_get_tim);27292694
+43-3
net/mac80211/util.c
···14571457 drv_stop(local);14581458}1459145914601460+static void ieee80211_handle_reconfig_failure(struct ieee80211_local *local)14611461+{14621462+ struct ieee80211_sub_if_data *sdata;14631463+ struct ieee80211_chanctx *ctx;14641464+14651465+ /*14661466+ * We get here if during resume the device can't be restarted properly.14671467+ * We might also get here if this happens during HW reset, which is a14681468+ * slightly different situation and we need to drop all connections in14691469+ * the latter case.14701470+ *14711471+ * Ask cfg80211 to turn off all interfaces, this will result in more14721472+ * warnings but at least we'll then get into a clean stopped state.14731473+ */14741474+14751475+ local->resuming = false;14761476+ local->suspended = false;14771477+ local->started = false;14781478+14791479+ /* scheduled scan clearly can't be running any more, but tell14801480+ * cfg80211 and clear local state14811481+ */14821482+ ieee80211_sched_scan_end(local);14831483+14841484+ list_for_each_entry(sdata, &local->interfaces, list)14851485+ sdata->flags &= ~IEEE80211_SDATA_IN_DRIVER;14861486+14871487+ /* Mark channel contexts as not being in the driver any more to avoid14881488+ * removing them from the driver during the shutdown process...14891489+ */14901490+ mutex_lock(&local->chanctx_mtx);14911491+ list_for_each_entry(ctx, &local->chanctx_list, list)14921492+ ctx->driver_present = false;14931493+ mutex_unlock(&local->chanctx_mtx);14941494+14951495+ cfg80211_shutdown_all_interfaces(local->hw.wiphy);14961496+}14971497+14601498static void ieee80211_assign_chanctx(struct ieee80211_local *local,14611499 struct ieee80211_sub_if_data *sdata)14621500{···15581520 */15591521 res = drv_start(local);15601522 if (res) {15611561- WARN(local->suspended, "Hardware became unavailable "15621562- "upon resume. This could be a software issue "15631563- "prior to suspend or a hardware issue.\n");15231523+ if (local->suspended)15241524+ WARN(1, "Hardware became unavailable upon resume. This could be a software issue prior to suspend or a hardware issue.\n");15251525+ else15261526+ WARN(1, "Hardware became unavailable during restart.\n");15271527+ ieee80211_handle_reconfig_failure(local);15641528 return res;15651529 }15661530
···225225 goto exit;226226 }227227228228- targets->sens_res = be16_to_cpu(*(u16 *)atqa_skb->data);228228+ targets->sens_res = be16_to_cpu(*(__be16 *)atqa_skb->data);229229 targets->sel_res = sak_skb->data[0];230230231231 r = nfc_hci_get_param(hdev, NFC_HCI_RF_READER_A_GATE,···380380 if (r < 0)381381 goto disconnect_all;382382383383- if (skb->len && skb->len == strlen(hdev->init_data.session_id))384384- if (memcmp(hdev->init_data.session_id, skb->data,385385- skb->len) == 0) {386386- /* TODO ELa: restore gate<->pipe table from387387- * some TBD location.388388- * note: it doesn't seem possible to get the chip389389- * currently open gate/pipe table.390390- * It is only possible to obtain the supported391391- * gate list.392392- */383383+ if (skb->len && skb->len == strlen(hdev->init_data.session_id) &&384384+ (memcmp(hdev->init_data.session_id, skb->data,385385+ skb->len) == 0) && hdev->ops->load_session) {386386+ /* Restore gate<->pipe table from some proprietary location. */393387394394- /* goto exit395395- * For now, always do a full initialization */396396- }388388+ r = hdev->ops->load_session(hdev);397389398398- r = nfc_hci_disconnect_all_gates(hdev);399399- if (r < 0)400400- goto exit;390390+ if (r < 0)391391+ goto disconnect_all;392392+ } else {401393402402- r = hci_dev_connect_gates(hdev, hdev->init_data.gate_count,403403- hdev->init_data.gates);404404- if (r < 0)405405- goto disconnect_all;394394+ r = nfc_hci_disconnect_all_gates(hdev);395395+ if (r < 0)396396+ goto exit;406397407407- r = nfc_hci_set_param(hdev, NFC_HCI_ADMIN_GATE,408408- NFC_HCI_ADMIN_SESSION_IDENTITY,409409- hdev->init_data.session_id,410410- strlen(hdev->init_data.session_id));398398+ r = hci_dev_connect_gates(hdev, hdev->init_data.gate_count,399399+ hdev->init_data.gates);400400+ if (r < 0)401401+ goto disconnect_all;402402+403403+ r = nfc_hci_set_param(hdev, NFC_HCI_ADMIN_GATE,404404+ NFC_HCI_ADMIN_SESSION_IDENTITY,405405+ hdev->init_data.session_id,406406+ strlen(hdev->init_data.session_id));407407+ }411408 if (r == 0)412409 goto exit;413410
···370370 case NL80211_IFTYPE_AP_VLAN:371371 case NL80211_IFTYPE_WDS:372372 case NL80211_IFTYPE_P2P_DEVICE:373373- case NL80211_IFTYPE_UNSPECIFIED:374373 break;374374+ case NL80211_IFTYPE_UNSPECIFIED:375375 case NUM_NL80211_IFTYPES:376376 WARN_ON(1);377377 }···796796 !cfg80211_go_permissive_chan(rdev, chandef->chan))797797 prohibited_flags |= IEEE80211_CHAN_NO_IR;798798799799- if (cfg80211_chandef_dfs_required(wiphy, chandef,800800- NL80211_IFTYPE_UNSPECIFIED) > 0 &&799799+ if (cfg80211_chandef_dfs_required(wiphy, chandef, iftype) > 0 &&801800 cfg80211_chandef_dfs_available(wiphy, chandef)) {802801 /* We can skip IEEE80211_CHAN_NO_IR if chandef dfs available */803802 prohibited_flags = IEEE80211_CHAN_DISABLED;