diff options
author | John W. Linville <linville@tuxdriver.com> | 2013-11-08 09:03:10 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-11-08 09:03:10 -0500 |
commit | c1f3bb6bd317994beb3af7bbec4bf54ed0035509 (patch) | |
tree | 878833c714ddcb35f1574f2b11e1f69d1130d206 | |
parent | dcd607718385d02ce3741de225927a57f528f93b (diff) | |
parent | 3c57e865cfb2dcbb48fdfa08e7d4e3479e9b40f0 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
89 files changed, 3037 insertions, 1517 deletions
diff --git a/Documentation/DocBook/80211.tmpl b/Documentation/DocBook/80211.tmpl index f403ec3c5c9a..46ad6faee9ab 100644 --- a/Documentation/DocBook/80211.tmpl +++ b/Documentation/DocBook/80211.tmpl | |||
@@ -152,8 +152,8 @@ | |||
152 | !Finclude/net/cfg80211.h cfg80211_scan_request | 152 | !Finclude/net/cfg80211.h cfg80211_scan_request |
153 | !Finclude/net/cfg80211.h cfg80211_scan_done | 153 | !Finclude/net/cfg80211.h cfg80211_scan_done |
154 | !Finclude/net/cfg80211.h cfg80211_bss | 154 | !Finclude/net/cfg80211.h cfg80211_bss |
155 | !Finclude/net/cfg80211.h cfg80211_inform_bss_frame | 155 | !Finclude/net/cfg80211.h cfg80211_inform_bss_width_frame |
156 | !Finclude/net/cfg80211.h cfg80211_inform_bss | 156 | !Finclude/net/cfg80211.h cfg80211_inform_bss_width |
157 | !Finclude/net/cfg80211.h cfg80211_unlink_bss | 157 | !Finclude/net/cfg80211.h cfg80211_unlink_bss |
158 | !Finclude/net/cfg80211.h cfg80211_find_ie | 158 | !Finclude/net/cfg80211.h cfg80211_find_ie |
159 | !Finclude/net/cfg80211.h ieee80211_bss_get_ie | 159 | !Finclude/net/cfg80211.h ieee80211_bss_get_ie |
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 30868fa870f6..c0ff34f2d2df 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c | |||
@@ -1629,7 +1629,6 @@ static struct usb_driver btusb_driver = { | |||
1629 | #ifdef CONFIG_PM | 1629 | #ifdef CONFIG_PM |
1630 | .suspend = btusb_suspend, | 1630 | .suspend = btusb_suspend, |
1631 | .resume = btusb_resume, | 1631 | .resume = btusb_resume, |
1632 | .reset_resume = btusb_resume, | ||
1633 | #endif | 1632 | #endif |
1634 | .id_table = btusb_table, | 1633 | .id_table = btusb_table, |
1635 | .supports_autosuspend = 1, | 1634 | .supports_autosuspend = 1, |
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index e89db64532f5..d8643ebabd30 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -845,7 +845,8 @@ static const struct ieee80211_iface_limit if_limits[] = { | |||
845 | }; | 845 | }; |
846 | 846 | ||
847 | static const struct ieee80211_iface_limit if_dfs_limits[] = { | 847 | static const struct ieee80211_iface_limit if_dfs_limits[] = { |
848 | { .max = 1, .types = BIT(NL80211_IFTYPE_AP) }, | 848 | { .max = 1, .types = BIT(NL80211_IFTYPE_AP) | |
849 | BIT(NL80211_IFTYPE_ADHOC) }, | ||
849 | }; | 850 | }; |
850 | 851 | ||
851 | static const struct ieee80211_iface_combination if_comb[] = { | 852 | static const struct ieee80211_iface_combination if_comb[] = { |
diff --git a/drivers/net/wireless/iwlwifi/dvm/ucode.c b/drivers/net/wireless/iwlwifi/dvm/ucode.c index 86270b69cd02..63637949a146 100644 --- a/drivers/net/wireless/iwlwifi/dvm/ucode.c +++ b/drivers/net/wireless/iwlwifi/dvm/ucode.c | |||
@@ -330,15 +330,14 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv, | |||
330 | enum iwl_ucode_type old_type; | 330 | enum iwl_ucode_type old_type; |
331 | static const u8 alive_cmd[] = { REPLY_ALIVE }; | 331 | static const u8 alive_cmd[] = { REPLY_ALIVE }; |
332 | 332 | ||
333 | old_type = priv->cur_ucode; | ||
334 | priv->cur_ucode = ucode_type; | ||
335 | fw = iwl_get_ucode_image(priv, ucode_type); | 333 | fw = iwl_get_ucode_image(priv, ucode_type); |
334 | if (WARN_ON(!fw)) | ||
335 | return -EINVAL; | ||
336 | 336 | ||
337 | old_type = priv->cur_ucode; | ||
338 | priv->cur_ucode = ucode_type; | ||
337 | priv->ucode_loaded = false; | 339 | priv->ucode_loaded = false; |
338 | 340 | ||
339 | if (!fw) | ||
340 | return -EINVAL; | ||
341 | |||
342 | iwl_init_notification_wait(&priv->notif_wait, &alive_wait, | 341 | iwl_init_notification_wait(&priv->notif_wait, &alive_wait, |
343 | alive_cmd, ARRAY_SIZE(alive_cmd), | 342 | alive_cmd, ARRAY_SIZE(alive_cmd), |
344 | iwl_alive_fn, &alive_data); | 343 | iwl_alive_fn, &alive_data); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h index 87b66a821ec8..75db087120c3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw.h | |||
@@ -100,7 +100,7 @@ enum iwl_ucode_tlv_flag { | |||
100 | IWL_UCODE_TLV_FLAGS_P2P = BIT(3), | 100 | IWL_UCODE_TLV_FLAGS_P2P = BIT(3), |
101 | IWL_UCODE_TLV_FLAGS_DW_BC_TABLE = BIT(4), | 101 | IWL_UCODE_TLV_FLAGS_DW_BC_TABLE = BIT(4), |
102 | IWL_UCODE_TLV_FLAGS_NEWBT_COEX = BIT(5), | 102 | IWL_UCODE_TLV_FLAGS_NEWBT_COEX = BIT(5), |
103 | IWL_UCODE_TLV_FLAGS_UAPSD = BIT(6), | 103 | IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT = BIT(6), |
104 | IWL_UCODE_TLV_FLAGS_SHORT_BL = BIT(7), | 104 | IWL_UCODE_TLV_FLAGS_SHORT_BL = BIT(7), |
105 | IWL_UCODE_TLV_FLAGS_RX_ENERGY_API = BIT(8), | 105 | IWL_UCODE_TLV_FLAGS_RX_ENERGY_API = BIT(8), |
106 | IWL_UCODE_TLV_FLAGS_TIME_EVENT_API_V2 = BIT(9), | 106 | IWL_UCODE_TLV_FLAGS_TIME_EVENT_API_V2 = BIT(9), |
@@ -113,6 +113,7 @@ enum iwl_ucode_tlv_flag { | |||
113 | IWL_UCODE_TLV_FLAGS_SCHED_SCAN = BIT(17), | 113 | IWL_UCODE_TLV_FLAGS_SCHED_SCAN = BIT(17), |
114 | IWL_UCODE_TLV_FLAGS_STA_KEY_CMD = BIT(19), | 114 | IWL_UCODE_TLV_FLAGS_STA_KEY_CMD = BIT(19), |
115 | IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD = BIT(20), | 115 | IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD = BIT(20), |
116 | IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT = BIT(24), | ||
116 | }; | 117 | }; |
117 | 118 | ||
118 | /* The default calibrate table size if not specified by firmware file */ | 119 | /* The default calibrate table size if not specified by firmware file */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c index dfa4d2e3aaa2..ad8e19a56eca 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/iwlwifi/iwl-io.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include "iwl-csr.h" | 34 | #include "iwl-csr.h" |
35 | #include "iwl-debug.h" | 35 | #include "iwl-debug.h" |
36 | #include "iwl-fh.h" | 36 | #include "iwl-fh.h" |
37 | #include "iwl-csr.h" | ||
38 | 37 | ||
39 | #define IWL_POLL_INTERVAL 10 /* microseconds */ | 38 | #define IWL_POLL_INTERVAL 10 /* microseconds */ |
40 | 39 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index c6bac7c90b00..143292b4dbbf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
@@ -344,7 +344,7 @@ struct iwl_trans_config { | |||
344 | u8 cmd_queue; | 344 | u8 cmd_queue; |
345 | u8 cmd_fifo; | 345 | u8 cmd_fifo; |
346 | const u8 *no_reclaim_cmds; | 346 | const u8 *no_reclaim_cmds; |
347 | int n_no_reclaim_cmds; | 347 | unsigned int n_no_reclaim_cmds; |
348 | 348 | ||
349 | bool rx_buf_size_8k; | 349 | bool rx_buf_size_8k; |
350 | bool bc_table_dword; | 350 | bool bc_table_dword; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c index 5b630f12bbff..5d066cbc5ac7 100644 --- a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c +++ b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c | |||
@@ -505,12 +505,16 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, | |||
505 | struct iwl_mvm_sta *mvmsta; | 505 | struct iwl_mvm_sta *mvmsta; |
506 | int ret; | 506 | int ret; |
507 | 507 | ||
508 | /* This can happen if the station has been removed right now */ | ||
509 | if (sta_id == IWL_MVM_STATION_COUNT) | 508 | if (sta_id == IWL_MVM_STATION_COUNT) |
510 | return 0; | 509 | return 0; |
511 | 510 | ||
512 | sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id], | 511 | sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id], |
513 | lockdep_is_held(&mvm->mutex)); | 512 | lockdep_is_held(&mvm->mutex)); |
513 | |||
514 | /* This can happen if the station has been removed right now */ | ||
515 | if (IS_ERR_OR_NULL(sta)) | ||
516 | return 0; | ||
517 | |||
514 | mvmsta = (void *)sta->drv_priv; | 518 | mvmsta = (void *)sta->drv_priv; |
515 | 519 | ||
516 | /* nothing to do */ | 520 | /* nothing to do */ |
@@ -751,7 +755,7 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm) | |||
751 | 755 | ||
752 | cmd.bt_secondary_ci = | 756 | cmd.bt_secondary_ci = |
753 | iwl_ci_mask[chan->def.chan->hw_value][ci_bw_idx]; | 757 | iwl_ci_mask[chan->def.chan->hw_value][ci_bw_idx]; |
754 | cmd.secondary_ch_phy_id = *((u16 *)data.primary->drv_priv); | 758 | cmd.secondary_ch_phy_id = *((u16 *)data.secondary->drv_priv); |
755 | } | 759 | } |
756 | 760 | ||
757 | rcu_read_unlock(); | 761 | rcu_read_unlock(); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index 0675f0c8ef93..9864d713eb2c 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c | |||
@@ -342,6 +342,7 @@ static void iwl_dbgfs_update_pm(struct iwl_mvm *mvm, | |||
342 | case MVM_DEBUGFS_PM_DISABLE_POWER_OFF: | 342 | case MVM_DEBUGFS_PM_DISABLE_POWER_OFF: |
343 | IWL_DEBUG_POWER(mvm, "disable_power_off=%d\n", val); | 343 | IWL_DEBUG_POWER(mvm, "disable_power_off=%d\n", val); |
344 | dbgfs_pm->disable_power_off = val; | 344 | dbgfs_pm->disable_power_off = val; |
345 | break; | ||
345 | case MVM_DEBUGFS_PM_LPRX_ENA: | 346 | case MVM_DEBUGFS_PM_LPRX_ENA: |
346 | IWL_DEBUG_POWER(mvm, "lprx %s\n", val ? "enabled" : "disabled"); | 347 | IWL_DEBUG_POWER(mvm, "lprx %s\n", val ? "enabled" : "disabled"); |
347 | dbgfs_pm->lprx_ena = val; | 348 | dbgfs_pm->lprx_ena = val; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c index 83fc5ca04433..70e5297646b2 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/iwlwifi/mvm/fw.c | |||
@@ -151,13 +151,11 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, | |||
151 | enum iwl_ucode_type old_type = mvm->cur_ucode; | 151 | enum iwl_ucode_type old_type = mvm->cur_ucode; |
152 | static const u8 alive_cmd[] = { MVM_ALIVE }; | 152 | static const u8 alive_cmd[] = { MVM_ALIVE }; |
153 | 153 | ||
154 | mvm->cur_ucode = ucode_type; | ||
155 | fw = iwl_get_ucode_image(mvm, ucode_type); | 154 | fw = iwl_get_ucode_image(mvm, ucode_type); |
156 | 155 | if (WARN_ON(!fw)) | |
157 | mvm->ucode_loaded = false; | ||
158 | |||
159 | if (!fw) | ||
160 | return -EINVAL; | 156 | return -EINVAL; |
157 | mvm->cur_ucode = ucode_type; | ||
158 | mvm->ucode_loaded = false; | ||
161 | 159 | ||
162 | iwl_init_notification_wait(&mvm->notif_wait, &alive_wait, | 160 | iwl_init_notification_wait(&mvm->notif_wait, &alive_wait, |
163 | alive_cmd, ARRAY_SIZE(alive_cmd), | 161 | alive_cmd, ARRAY_SIZE(alive_cmd), |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c index ab5a7ac90dcd..f41f9b079831 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | |||
@@ -719,7 +719,9 @@ static int iwl_mvm_mac_ctxt_cmd_listener(struct iwl_mvm *mvm, | |||
719 | cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_PROMISC | | 719 | cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_PROMISC | |
720 | MAC_FILTER_IN_CONTROL_AND_MGMT | | 720 | MAC_FILTER_IN_CONTROL_AND_MGMT | |
721 | MAC_FILTER_IN_BEACON | | 721 | MAC_FILTER_IN_BEACON | |
722 | MAC_FILTER_IN_PROBE_REQUEST); | 722 | MAC_FILTER_IN_PROBE_REQUEST | |
723 | MAC_FILTER_IN_CRC32); | ||
724 | mvm->hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS; | ||
723 | 725 | ||
724 | return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd); | 726 | return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd); |
725 | } | 727 | } |
@@ -1122,6 +1124,10 @@ int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
1122 | } | 1124 | } |
1123 | 1125 | ||
1124 | mvmvif->uploaded = false; | 1126 | mvmvif->uploaded = false; |
1127 | |||
1128 | if (vif->type == NL80211_IFTYPE_MONITOR) | ||
1129 | mvm->hw->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS; | ||
1130 | |||
1125 | return 0; | 1131 | return 0; |
1126 | } | 1132 | } |
1127 | 1133 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index f40685c3764e..74bc2c8af06d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
@@ -164,8 +164,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
164 | IEEE80211_HW_TIMING_BEACON_ONLY | | 164 | IEEE80211_HW_TIMING_BEACON_ONLY | |
165 | IEEE80211_HW_CONNECTION_MONITOR | | 165 | IEEE80211_HW_CONNECTION_MONITOR | |
166 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | | 166 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | |
167 | IEEE80211_HW_SUPPORTS_STATIC_SMPS | | 167 | IEEE80211_HW_SUPPORTS_STATIC_SMPS; |
168 | IEEE80211_HW_SUPPORTS_UAPSD; | ||
169 | 168 | ||
170 | hw->queues = mvm->first_agg_queue; | 169 | hw->queues = mvm->first_agg_queue; |
171 | hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE; | 170 | hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE; |
@@ -180,6 +179,12 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
180 | !iwlwifi_mod_params.sw_crypto) | 179 | !iwlwifi_mod_params.sw_crypto) |
181 | hw->flags |= IEEE80211_HW_MFP_CAPABLE; | 180 | hw->flags |= IEEE80211_HW_MFP_CAPABLE; |
182 | 181 | ||
182 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT) { | ||
183 | hw->flags |= IEEE80211_HW_SUPPORTS_UAPSD; | ||
184 | hw->uapsd_queues = IWL_UAPSD_AC_INFO; | ||
185 | hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP; | ||
186 | } | ||
187 | |||
183 | hw->sta_data_size = sizeof(struct iwl_mvm_sta); | 188 | hw->sta_data_size = sizeof(struct iwl_mvm_sta); |
184 | hw->vif_data_size = sizeof(struct iwl_mvm_vif); | 189 | hw->vif_data_size = sizeof(struct iwl_mvm_vif); |
185 | hw->chanctx_data_size = sizeof(u16); | 190 | hw->chanctx_data_size = sizeof(u16); |
@@ -204,8 +209,6 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
204 | 209 | ||
205 | hw->wiphy->max_remain_on_channel_duration = 10000; | 210 | hw->wiphy->max_remain_on_channel_duration = 10000; |
206 | hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL; | 211 | hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL; |
207 | hw->uapsd_queues = IWL_UAPSD_AC_INFO; | ||
208 | hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP; | ||
209 | 212 | ||
210 | /* Extract MAC address */ | 213 | /* Extract MAC address */ |
211 | memcpy(mvm->addresses[0].addr, mvm->nvm_data->hw_addr, ETH_ALEN); | 214 | memcpy(mvm->addresses[0].addr, mvm->nvm_data->hw_addr, ETH_ALEN); |
@@ -861,7 +864,8 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | |||
861 | /* reset rssi values */ | 864 | /* reset rssi values */ |
862 | mvmvif->bf_data.ave_beacon_signal = 0; | 865 | mvmvif->bf_data.ave_beacon_signal = 0; |
863 | 866 | ||
864 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD)) { | 867 | if (!(mvm->fw->ucode_capa.flags & |
868 | IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT)) { | ||
865 | /* Workaround for FW bug, otherwise FW disables device | 869 | /* Workaround for FW bug, otherwise FW disables device |
866 | * power save upon disassociation | 870 | * power save upon disassociation |
867 | */ | 871 | */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 6235cb729f5c..fed21ef4162d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h | |||
@@ -73,7 +73,6 @@ | |||
73 | #include "iwl-trans.h" | 73 | #include "iwl-trans.h" |
74 | #include "iwl-notif-wait.h" | 74 | #include "iwl-notif-wait.h" |
75 | #include "iwl-eeprom-parse.h" | 75 | #include "iwl-eeprom-parse.h" |
76 | #include "iwl-trans.h" | ||
77 | #include "sta.h" | 76 | #include "sta.h" |
78 | #include "fw-api.h" | 77 | #include "fw-api.h" |
79 | #include "constants.h" | 78 | #include "constants.h" |
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index 59b7cb3c6134..d86083c6f445 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c | |||
@@ -459,7 +459,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
459 | if (err) | 459 | if (err) |
460 | goto out_unregister; | 460 | goto out_unregister; |
461 | 461 | ||
462 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD) | 462 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT) |
463 | mvm->pm_ops = &pm_mac_ops; | 463 | mvm->pm_ops = &pm_mac_ops; |
464 | else | 464 | else |
465 | mvm->pm_ops = &pm_legacy_ops; | 465 | mvm->pm_ops = &pm_legacy_ops; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c index a4af5019a496..3a1f3982109d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/iwlwifi/mvm/rx.c | |||
@@ -300,10 +300,14 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | |||
300 | return 0; | 300 | return 0; |
301 | } | 301 | } |
302 | 302 | ||
303 | /* | ||
304 | * Keep packets with CRC errors (and with overrun) for monitor mode | ||
305 | * (otherwise the firmware discards them) but mark them as bad. | ||
306 | */ | ||
303 | if (!(rx_pkt_status & RX_MPDU_RES_STATUS_CRC_OK) || | 307 | if (!(rx_pkt_status & RX_MPDU_RES_STATUS_CRC_OK) || |
304 | !(rx_pkt_status & RX_MPDU_RES_STATUS_OVERRUN_OK)) { | 308 | !(rx_pkt_status & RX_MPDU_RES_STATUS_OVERRUN_OK)) { |
305 | IWL_DEBUG_RX(mvm, "Bad CRC or FIFO: 0x%08X.\n", rx_pkt_status); | 309 | IWL_DEBUG_RX(mvm, "Bad CRC or FIFO: 0x%08X.\n", rx_pkt_status); |
306 | return 0; | 310 | rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; |
307 | } | 311 | } |
308 | 312 | ||
309 | /* This will be used in several places later */ | 313 | /* This will be used in several places later */ |
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index f644fcf861a8..059c5acad3a0 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c | |||
@@ -1499,12 +1499,11 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans, | |||
1499 | IWL_DEBUG_INFO(trans, "Attempting to send sync command %s\n", | 1499 | IWL_DEBUG_INFO(trans, "Attempting to send sync command %s\n", |
1500 | get_cmd_string(trans_pcie, cmd->id)); | 1500 | get_cmd_string(trans_pcie, cmd->id)); |
1501 | 1501 | ||
1502 | if (WARN_ON(test_and_set_bit(STATUS_HCMD_ACTIVE, | 1502 | if (WARN(test_and_set_bit(STATUS_HCMD_ACTIVE, |
1503 | &trans_pcie->status))) { | 1503 | &trans_pcie->status), |
1504 | IWL_ERR(trans, "Command %s: a command is already active!\n", | 1504 | "Command %s: a command is already active!\n", |
1505 | get_cmd_string(trans_pcie, cmd->id)); | 1505 | get_cmd_string(trans_pcie, cmd->id))) |
1506 | return -EIO; | 1506 | return -EIO; |
1507 | } | ||
1508 | 1507 | ||
1509 | IWL_DEBUG_INFO(trans, "Setting HCMD_ACTIVE for command %s\n", | 1508 | IWL_DEBUG_INFO(trans, "Setting HCMD_ACTIVE for command %s\n", |
1510 | get_cmd_string(trans_pcie, cmd->id)); | 1509 | get_cmd_string(trans_pcie, cmd->id)); |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 2cd3f54e1efa..de0df86704e7 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -167,6 +167,7 @@ struct hwsim_vif_priv { | |||
167 | u32 magic; | 167 | u32 magic; |
168 | u8 bssid[ETH_ALEN]; | 168 | u8 bssid[ETH_ALEN]; |
169 | bool assoc; | 169 | bool assoc; |
170 | bool bcn_en; | ||
170 | u16 aid; | 171 | u16 aid; |
171 | }; | 172 | }; |
172 | 173 | ||
@@ -1170,6 +1171,16 @@ static void mac80211_hwsim_configure_filter(struct ieee80211_hw *hw, | |||
1170 | *total_flags = data->rx_filter; | 1171 | *total_flags = data->rx_filter; |
1171 | } | 1172 | } |
1172 | 1173 | ||
1174 | static void mac80211_hwsim_bcn_en_iter(void *data, u8 *mac, | ||
1175 | struct ieee80211_vif *vif) | ||
1176 | { | ||
1177 | unsigned int *count = data; | ||
1178 | struct hwsim_vif_priv *vp = (void *)vif->drv_priv; | ||
1179 | |||
1180 | if (vp->bcn_en) | ||
1181 | (*count)++; | ||
1182 | } | ||
1183 | |||
1173 | static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, | 1184 | static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, |
1174 | struct ieee80211_vif *vif, | 1185 | struct ieee80211_vif *vif, |
1175 | struct ieee80211_bss_conf *info, | 1186 | struct ieee80211_bss_conf *info, |
@@ -1180,7 +1191,8 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, | |||
1180 | 1191 | ||
1181 | hwsim_check_magic(vif); | 1192 | hwsim_check_magic(vif); |
1182 | 1193 | ||
1183 | wiphy_debug(hw->wiphy, "%s(changed=0x%x)\n", __func__, changed); | 1194 | wiphy_debug(hw->wiphy, "%s(changed=0x%x vif->addr=%pM)\n", |
1195 | __func__, changed, vif->addr); | ||
1184 | 1196 | ||
1185 | if (changed & BSS_CHANGED_BSSID) { | 1197 | if (changed & BSS_CHANGED_BSSID) { |
1186 | wiphy_debug(hw->wiphy, "%s: BSSID changed: %pM\n", | 1198 | wiphy_debug(hw->wiphy, "%s: BSSID changed: %pM\n", |
@@ -1202,6 +1214,7 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, | |||
1202 | 1214 | ||
1203 | if (changed & BSS_CHANGED_BEACON_ENABLED) { | 1215 | if (changed & BSS_CHANGED_BEACON_ENABLED) { |
1204 | wiphy_debug(hw->wiphy, " BCN EN: %d\n", info->enable_beacon); | 1216 | wiphy_debug(hw->wiphy, " BCN EN: %d\n", info->enable_beacon); |
1217 | vp->bcn_en = info->enable_beacon; | ||
1205 | if (data->started && | 1218 | if (data->started && |
1206 | !hrtimer_is_queued(&data->beacon_timer.timer) && | 1219 | !hrtimer_is_queued(&data->beacon_timer.timer) && |
1207 | info->enable_beacon) { | 1220 | info->enable_beacon) { |
@@ -1215,8 +1228,16 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, | |||
1215 | tasklet_hrtimer_start(&data->beacon_timer, | 1228 | tasklet_hrtimer_start(&data->beacon_timer, |
1216 | ns_to_ktime(until_tbtt * 1000), | 1229 | ns_to_ktime(until_tbtt * 1000), |
1217 | HRTIMER_MODE_REL); | 1230 | HRTIMER_MODE_REL); |
1218 | } else if (!info->enable_beacon) | 1231 | } else if (!info->enable_beacon) { |
1219 | tasklet_hrtimer_cancel(&data->beacon_timer); | 1232 | unsigned int count = 0; |
1233 | ieee80211_iterate_active_interfaces( | ||
1234 | data->hw, IEEE80211_IFACE_ITER_NORMAL, | ||
1235 | mac80211_hwsim_bcn_en_iter, &count); | ||
1236 | wiphy_debug(hw->wiphy, " beaconing vifs remaining: %u", | ||
1237 | count); | ||
1238 | if (count == 0) | ||
1239 | tasklet_hrtimer_cancel(&data->beacon_timer); | ||
1240 | } | ||
1220 | } | 1241 | } |
1221 | 1242 | ||
1222 | if (changed & BSS_CHANGED_ERP_CTS_PROT) { | 1243 | if (changed & BSS_CHANGED_ERP_CTS_PROT) { |
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c index 591526b99154..be7129ba16ad 100644 --- a/drivers/net/wireless/ti/wl12xx/main.c +++ b/drivers/net/wireless/ti/wl12xx/main.c | |||
@@ -333,11 +333,11 @@ static struct wlcore_conf wl12xx_conf = { | |||
333 | .always = 0, | 333 | .always = 0, |
334 | }, | 334 | }, |
335 | .fwlog = { | 335 | .fwlog = { |
336 | .mode = WL12XX_FWLOG_ON_DEMAND, | 336 | .mode = WL12XX_FWLOG_CONTINUOUS, |
337 | .mem_blocks = 2, | 337 | .mem_blocks = 2, |
338 | .severity = 0, | 338 | .severity = 0, |
339 | .timestamp = WL12XX_FWLOG_TIMESTAMP_DISABLED, | 339 | .timestamp = WL12XX_FWLOG_TIMESTAMP_DISABLED, |
340 | .output = WL12XX_FWLOG_OUTPUT_HOST, | 340 | .output = WL12XX_FWLOG_OUTPUT_DBG_PINS, |
341 | .threshold = 0, | 341 | .threshold = 0, |
342 | }, | 342 | }, |
343 | .rate = { | 343 | .rate = { |
@@ -717,6 +717,9 @@ static int wl12xx_identify_chip(struct wl1271 *wl) | |||
717 | goto out; | 717 | goto out; |
718 | } | 718 | } |
719 | 719 | ||
720 | wl->fw_mem_block_size = 256; | ||
721 | wl->fwlog_end = 0x2000000; | ||
722 | |||
720 | /* common settings */ | 723 | /* common settings */ |
721 | wl->scan_templ_id_2_4 = CMD_TEMPL_APP_PROBE_REQ_2_4_LEGACY; | 724 | wl->scan_templ_id_2_4 = CMD_TEMPL_APP_PROBE_REQ_2_4_LEGACY; |
722 | wl->scan_templ_id_5 = CMD_TEMPL_APP_PROBE_REQ_5_LEGACY; | 725 | wl->scan_templ_id_5 = CMD_TEMPL_APP_PROBE_REQ_5_LEGACY; |
@@ -1262,9 +1265,10 @@ static int wl12xx_boot(struct wl1271 *wl) | |||
1262 | BA_SESSION_RX_CONSTRAINT_EVENT_ID | | 1265 | BA_SESSION_RX_CONSTRAINT_EVENT_ID | |
1263 | REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID | | 1266 | REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID | |
1264 | INACTIVE_STA_EVENT_ID | | 1267 | INACTIVE_STA_EVENT_ID | |
1265 | MAX_TX_RETRY_EVENT_ID | | ||
1266 | CHANNEL_SWITCH_COMPLETE_EVENT_ID; | 1268 | CHANNEL_SWITCH_COMPLETE_EVENT_ID; |
1267 | 1269 | ||
1270 | wl->ap_event_mask = MAX_TX_RETRY_EVENT_ID; | ||
1271 | |||
1268 | ret = wlcore_boot_run_firmware(wl); | 1272 | ret = wlcore_boot_run_firmware(wl); |
1269 | if (ret < 0) | 1273 | if (ret < 0) |
1270 | goto out; | 1274 | goto out; |
@@ -1648,6 +1652,11 @@ static bool wl12xx_lnk_low_prio(struct wl1271 *wl, u8 hlid, | |||
1648 | return true; | 1652 | return true; |
1649 | } | 1653 | } |
1650 | 1654 | ||
1655 | static u32 wl12xx_convert_hwaddr(struct wl1271 *wl, u32 hwaddr) | ||
1656 | { | ||
1657 | return hwaddr << 5; | ||
1658 | } | ||
1659 | |||
1651 | static int wl12xx_setup(struct wl1271 *wl); | 1660 | static int wl12xx_setup(struct wl1271 *wl); |
1652 | 1661 | ||
1653 | static struct wlcore_ops wl12xx_ops = { | 1662 | static struct wlcore_ops wl12xx_ops = { |
@@ -1684,6 +1693,7 @@ static struct wlcore_ops wl12xx_ops = { | |||
1684 | .channel_switch = wl12xx_cmd_channel_switch, | 1693 | .channel_switch = wl12xx_cmd_channel_switch, |
1685 | .pre_pkt_send = NULL, | 1694 | .pre_pkt_send = NULL, |
1686 | .set_peer_cap = wl12xx_set_peer_cap, | 1695 | .set_peer_cap = wl12xx_set_peer_cap, |
1696 | .convert_hwaddr = wl12xx_convert_hwaddr, | ||
1687 | .lnk_high_prio = wl12xx_lnk_high_prio, | 1697 | .lnk_high_prio = wl12xx_lnk_high_prio, |
1688 | .lnk_low_prio = wl12xx_lnk_low_prio, | 1698 | .lnk_low_prio = wl12xx_lnk_low_prio, |
1689 | }; | 1699 | }; |
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c index d0daca1d23bc..ec37b16585df 100644 --- a/drivers/net/wireless/ti/wl18xx/main.c +++ b/drivers/net/wireless/ti/wl18xx/main.c | |||
@@ -456,11 +456,11 @@ static struct wlcore_conf wl18xx_conf = { | |||
456 | .always = 0, | 456 | .always = 0, |
457 | }, | 457 | }, |
458 | .fwlog = { | 458 | .fwlog = { |
459 | .mode = WL12XX_FWLOG_ON_DEMAND, | 459 | .mode = WL12XX_FWLOG_CONTINUOUS, |
460 | .mem_blocks = 2, | 460 | .mem_blocks = 2, |
461 | .severity = 0, | 461 | .severity = 0, |
462 | .timestamp = WL12XX_FWLOG_TIMESTAMP_DISABLED, | 462 | .timestamp = WL12XX_FWLOG_TIMESTAMP_DISABLED, |
463 | .output = WL12XX_FWLOG_OUTPUT_HOST, | 463 | .output = WL12XX_FWLOG_OUTPUT_DBG_PINS, |
464 | .threshold = 0, | 464 | .threshold = 0, |
465 | }, | 465 | }, |
466 | .rate = { | 466 | .rate = { |
@@ -505,7 +505,7 @@ static struct wlcore_conf wl18xx_conf = { | |||
505 | 505 | ||
506 | static struct wl18xx_priv_conf wl18xx_default_priv_conf = { | 506 | static struct wl18xx_priv_conf wl18xx_default_priv_conf = { |
507 | .ht = { | 507 | .ht = { |
508 | .mode = HT_MODE_DEFAULT, | 508 | .mode = HT_MODE_WIDE, |
509 | }, | 509 | }, |
510 | .phy = { | 510 | .phy = { |
511 | .phy_standalone = 0x00, | 511 | .phy_standalone = 0x00, |
@@ -516,7 +516,7 @@ static struct wl18xx_priv_conf wl18xx_default_priv_conf = { | |||
516 | .auto_detect = 0x00, | 516 | .auto_detect = 0x00, |
517 | .dedicated_fem = FEM_NONE, | 517 | .dedicated_fem = FEM_NONE, |
518 | .low_band_component = COMPONENT_3_WAY_SWITCH, | 518 | .low_band_component = COMPONENT_3_WAY_SWITCH, |
519 | .low_band_component_type = 0x04, | 519 | .low_band_component_type = 0x05, |
520 | .high_band_component = COMPONENT_2_WAY_SWITCH, | 520 | .high_band_component = COMPONENT_2_WAY_SWITCH, |
521 | .high_band_component_type = 0x09, | 521 | .high_band_component_type = 0x09, |
522 | .tcxo_ldo_voltage = 0x00, | 522 | .tcxo_ldo_voltage = 0x00, |
@@ -556,15 +556,15 @@ static struct wl18xx_priv_conf wl18xx_default_priv_conf = { | |||
556 | .per_chan_pwr_limit_arr_11p = { 0xff, 0xff, 0xff, 0xff, | 556 | .per_chan_pwr_limit_arr_11p = { 0xff, 0xff, 0xff, 0xff, |
557 | 0xff, 0xff, 0xff }, | 557 | 0xff, 0xff, 0xff }, |
558 | .psat = 0, | 558 | .psat = 0, |
559 | .low_power_val = 0x08, | ||
560 | .med_power_val = 0x12, | ||
561 | .high_power_val = 0x18, | ||
562 | .low_power_val_2nd = 0x05, | ||
563 | .med_power_val_2nd = 0x0a, | ||
564 | .high_power_val_2nd = 0x14, | ||
565 | .external_pa_dc2dc = 0, | 559 | .external_pa_dc2dc = 0, |
566 | .number_of_assembled_ant2_4 = 2, | 560 | .number_of_assembled_ant2_4 = 2, |
567 | .number_of_assembled_ant5 = 1, | 561 | .number_of_assembled_ant5 = 1, |
562 | .low_power_val = 0xff, | ||
563 | .med_power_val = 0xff, | ||
564 | .high_power_val = 0xff, | ||
565 | .low_power_val_2nd = 0xff, | ||
566 | .med_power_val_2nd = 0xff, | ||
567 | .high_power_val_2nd = 0xff, | ||
568 | .tx_rf_margin = 1, | 568 | .tx_rf_margin = 1, |
569 | }, | 569 | }, |
570 | }; | 570 | }; |
@@ -686,6 +686,9 @@ static int wl18xx_identify_chip(struct wl1271 *wl) | |||
686 | goto out; | 686 | goto out; |
687 | } | 687 | } |
688 | 688 | ||
689 | wl->fw_mem_block_size = 272; | ||
690 | wl->fwlog_end = 0x40000000; | ||
691 | |||
689 | wl->scan_templ_id_2_4 = CMD_TEMPL_CFG_PROBE_REQ_2_4; | 692 | wl->scan_templ_id_2_4 = CMD_TEMPL_CFG_PROBE_REQ_2_4; |
690 | wl->scan_templ_id_5 = CMD_TEMPL_CFG_PROBE_REQ_5; | 693 | wl->scan_templ_id_5 = CMD_TEMPL_CFG_PROBE_REQ_5; |
691 | wl->sched_scan_templ_id_2_4 = CMD_TEMPL_PROBE_REQ_2_4_PERIODIC; | 694 | wl->sched_scan_templ_id_2_4 = CMD_TEMPL_PROBE_REQ_2_4_PERIODIC; |
@@ -988,10 +991,11 @@ static int wl18xx_boot(struct wl1271 *wl) | |||
988 | BA_SESSION_RX_CONSTRAINT_EVENT_ID | | 991 | BA_SESSION_RX_CONSTRAINT_EVENT_ID | |
989 | REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID | | 992 | REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID | |
990 | INACTIVE_STA_EVENT_ID | | 993 | INACTIVE_STA_EVENT_ID | |
991 | MAX_TX_FAILURE_EVENT_ID | | ||
992 | CHANNEL_SWITCH_COMPLETE_EVENT_ID | | 994 | CHANNEL_SWITCH_COMPLETE_EVENT_ID | |
993 | DFS_CHANNELS_CONFIG_COMPLETE_EVENT; | 995 | DFS_CHANNELS_CONFIG_COMPLETE_EVENT; |
994 | 996 | ||
997 | wl->ap_event_mask = MAX_TX_FAILURE_EVENT_ID; | ||
998 | |||
995 | ret = wlcore_boot_run_firmware(wl); | 999 | ret = wlcore_boot_run_firmware(wl); |
996 | if (ret < 0) | 1000 | if (ret < 0) |
997 | goto out; | 1001 | goto out; |
@@ -1604,6 +1608,11 @@ static bool wl18xx_lnk_low_prio(struct wl1271 *wl, u8 hlid, | |||
1604 | return lnk->allocated_pkts < thold; | 1608 | return lnk->allocated_pkts < thold; |
1605 | } | 1609 | } |
1606 | 1610 | ||
1611 | static u32 wl18xx_convert_hwaddr(struct wl1271 *wl, u32 hwaddr) | ||
1612 | { | ||
1613 | return hwaddr & ~0x80000000; | ||
1614 | } | ||
1615 | |||
1607 | static int wl18xx_setup(struct wl1271 *wl); | 1616 | static int wl18xx_setup(struct wl1271 *wl); |
1608 | 1617 | ||
1609 | static struct wlcore_ops wl18xx_ops = { | 1618 | static struct wlcore_ops wl18xx_ops = { |
@@ -1641,6 +1650,7 @@ static struct wlcore_ops wl18xx_ops = { | |||
1641 | .pre_pkt_send = wl18xx_pre_pkt_send, | 1650 | .pre_pkt_send = wl18xx_pre_pkt_send, |
1642 | .sta_rc_update = wl18xx_sta_rc_update, | 1651 | .sta_rc_update = wl18xx_sta_rc_update, |
1643 | .set_peer_cap = wl18xx_set_peer_cap, | 1652 | .set_peer_cap = wl18xx_set_peer_cap, |
1653 | .convert_hwaddr = wl18xx_convert_hwaddr, | ||
1644 | .lnk_high_prio = wl18xx_lnk_high_prio, | 1654 | .lnk_high_prio = wl18xx_lnk_high_prio, |
1645 | .lnk_low_prio = wl18xx_lnk_low_prio, | 1655 | .lnk_low_prio = wl18xx_lnk_low_prio, |
1646 | }; | 1656 | }; |
diff --git a/drivers/net/wireless/ti/wlcore/acx.c b/drivers/net/wireless/ti/wlcore/acx.c index 7a970cd9c555..ec83675a2446 100644 --- a/drivers/net/wireless/ti/wlcore/acx.c +++ b/drivers/net/wireless/ti/wlcore/acx.c | |||
@@ -162,7 +162,8 @@ int wl1271_acx_mem_map(struct wl1271 *wl, struct acx_header *mem_map, | |||
162 | 162 | ||
163 | wl1271_debug(DEBUG_ACX, "acx mem map"); | 163 | wl1271_debug(DEBUG_ACX, "acx mem map"); |
164 | 164 | ||
165 | ret = wl1271_cmd_interrogate(wl, ACX_MEM_MAP, mem_map, len); | 165 | ret = wl1271_cmd_interrogate(wl, ACX_MEM_MAP, mem_map, |
166 | sizeof(struct acx_header), len); | ||
166 | if (ret < 0) | 167 | if (ret < 0) |
167 | return ret; | 168 | return ret; |
168 | 169 | ||
@@ -722,6 +723,7 @@ int wl1271_acx_statistics(struct wl1271 *wl, void *stats) | |||
722 | wl1271_debug(DEBUG_ACX, "acx statistics"); | 723 | wl1271_debug(DEBUG_ACX, "acx statistics"); |
723 | 724 | ||
724 | ret = wl1271_cmd_interrogate(wl, ACX_STATISTICS, stats, | 725 | ret = wl1271_cmd_interrogate(wl, ACX_STATISTICS, stats, |
726 | sizeof(struct acx_header), | ||
725 | wl->stats.fw_stats_len); | 727 | wl->stats.fw_stats_len); |
726 | if (ret < 0) { | 728 | if (ret < 0) { |
727 | wl1271_warning("acx statistics failed: %d", ret); | 729 | wl1271_warning("acx statistics failed: %d", ret); |
@@ -1470,8 +1472,8 @@ int wl12xx_acx_tsf_info(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
1470 | 1472 | ||
1471 | tsf_info->role_id = wlvif->role_id; | 1473 | tsf_info->role_id = wlvif->role_id; |
1472 | 1474 | ||
1473 | ret = wl1271_cmd_interrogate(wl, ACX_TSF_INFO, | 1475 | ret = wl1271_cmd_interrogate(wl, ACX_TSF_INFO, tsf_info, |
1474 | tsf_info, sizeof(*tsf_info)); | 1476 | sizeof(struct acx_header), sizeof(*tsf_info)); |
1475 | if (ret < 0) { | 1477 | if (ret < 0) { |
1476 | wl1271_warning("acx tsf info interrogate failed"); | 1478 | wl1271_warning("acx tsf info interrogate failed"); |
1477 | goto out; | 1479 | goto out; |
@@ -1752,7 +1754,7 @@ int wlcore_acx_average_rssi(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
1752 | 1754 | ||
1753 | acx->role_id = wlvif->role_id; | 1755 | acx->role_id = wlvif->role_id; |
1754 | ret = wl1271_cmd_interrogate(wl, ACX_ROAMING_STATISTICS_TBL, | 1756 | ret = wl1271_cmd_interrogate(wl, ACX_ROAMING_STATISTICS_TBL, |
1755 | acx, sizeof(*acx)); | 1757 | acx, sizeof(*acx), sizeof(*acx)); |
1756 | if (ret < 0) { | 1758 | if (ret < 0) { |
1757 | wl1271_warning("acx roaming statistics failed: %d", ret); | 1759 | wl1271_warning("acx roaming statistics failed: %d", ret); |
1758 | ret = -ENOMEM; | 1760 | ret = -ENOMEM; |
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index 9e5416f8764d..34d9dfff2ad3 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c | |||
@@ -60,7 +60,8 @@ static int __wlcore_cmd_send(struct wl1271 *wl, u16 id, void *buf, | |||
60 | u16 status; | 60 | u16 status; |
61 | u16 poll_count = 0; | 61 | u16 poll_count = 0; |
62 | 62 | ||
63 | if (WARN_ON(unlikely(wl->state == WLCORE_STATE_RESTARTING))) | 63 | if (WARN_ON(wl->state == WLCORE_STATE_RESTARTING && |
64 | id != CMD_STOP_FWLOGGER)) | ||
64 | return -EIO; | 65 | return -EIO; |
65 | 66 | ||
66 | cmd = buf; | 67 | cmd = buf; |
@@ -845,7 +846,8 @@ EXPORT_SYMBOL_GPL(wl1271_cmd_test); | |||
845 | * @buf: buffer for the response, including all headers, must work with dma | 846 | * @buf: buffer for the response, including all headers, must work with dma |
846 | * @len: length of buf | 847 | * @len: length of buf |
847 | */ | 848 | */ |
848 | int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len) | 849 | int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, |
850 | size_t cmd_len, size_t res_len) | ||
849 | { | 851 | { |
850 | struct acx_header *acx = buf; | 852 | struct acx_header *acx = buf; |
851 | int ret; | 853 | int ret; |
@@ -854,10 +856,10 @@ int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len) | |||
854 | 856 | ||
855 | acx->id = cpu_to_le16(id); | 857 | acx->id = cpu_to_le16(id); |
856 | 858 | ||
857 | /* payload length, does not include any headers */ | 859 | /* response payload length, does not include any headers */ |
858 | acx->len = cpu_to_le16(len - sizeof(*acx)); | 860 | acx->len = cpu_to_le16(res_len - sizeof(*acx)); |
859 | 861 | ||
860 | ret = wl1271_cmd_send(wl, CMD_INTERROGATE, acx, sizeof(*acx), len); | 862 | ret = wl1271_cmd_send(wl, CMD_INTERROGATE, acx, cmd_len, res_len); |
861 | if (ret < 0) | 863 | if (ret < 0) |
862 | wl1271_error("INTERROGATE command failed"); | 864 | wl1271_error("INTERROGATE command failed"); |
863 | 865 | ||
diff --git a/drivers/net/wireless/ti/wlcore/cmd.h b/drivers/net/wireless/ti/wlcore/cmd.h index fd34123047cd..323d4a856e4b 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.h +++ b/drivers/net/wireless/ti/wlcore/cmd.h | |||
@@ -45,7 +45,8 @@ int wl12xx_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
45 | enum ieee80211_band band, int channel); | 45 | enum ieee80211_band band, int channel); |
46 | int wl12xx_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif); | 46 | int wl12xx_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif); |
47 | int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); | 47 | int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); |
48 | int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); | 48 | int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, |
49 | size_t cmd_len, size_t res_len); | ||
49 | int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); | 50 | int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); |
50 | int wlcore_cmd_configure_failsafe(struct wl1271 *wl, u16 id, void *buf, | 51 | int wlcore_cmd_configure_failsafe(struct wl1271 *wl, u16 id, void *buf, |
51 | size_t len, unsigned long valid_rets); | 52 | size_t len, unsigned long valid_rets); |
diff --git a/drivers/net/wireless/ti/wlcore/conf.h b/drivers/net/wireless/ti/wlcore/conf.h index 2b96ff821341..40995c42bef8 100644 --- a/drivers/net/wireless/ti/wlcore/conf.h +++ b/drivers/net/wireless/ti/wlcore/conf.h | |||
@@ -1274,6 +1274,9 @@ struct conf_rx_streaming_settings { | |||
1274 | u8 always; | 1274 | u8 always; |
1275 | } __packed; | 1275 | } __packed; |
1276 | 1276 | ||
1277 | #define CONF_FWLOG_MIN_MEM_BLOCKS 2 | ||
1278 | #define CONF_FWLOG_MAX_MEM_BLOCKS 16 | ||
1279 | |||
1277 | struct conf_fwlog { | 1280 | struct conf_fwlog { |
1278 | /* Continuous or on-demand */ | 1281 | /* Continuous or on-demand */ |
1279 | u8 mode; | 1282 | u8 mode; |
@@ -1281,7 +1284,7 @@ struct conf_fwlog { | |||
1281 | /* | 1284 | /* |
1282 | * Number of memory blocks dedicated for the FW logger | 1285 | * Number of memory blocks dedicated for the FW logger |
1283 | * | 1286 | * |
1284 | * Range: 1-3, or 0 to disable the FW logger | 1287 | * Range: 2-16, or 0 to disable the FW logger |
1285 | */ | 1288 | */ |
1286 | u8 mem_blocks; | 1289 | u8 mem_blocks; |
1287 | 1290 | ||
diff --git a/drivers/net/wireless/ti/wlcore/debugfs.c b/drivers/net/wireless/ti/wlcore/debugfs.c index e17630c2a849..89893c717025 100644 --- a/drivers/net/wireless/ti/wlcore/debugfs.c +++ b/drivers/net/wireless/ti/wlcore/debugfs.c | |||
@@ -437,6 +437,7 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, | |||
437 | int res = 0; | 437 | int res = 0; |
438 | ssize_t ret; | 438 | ssize_t ret; |
439 | char *buf; | 439 | char *buf; |
440 | struct wl12xx_vif *wlvif; | ||
440 | 441 | ||
441 | #define DRIVER_STATE_BUF_LEN 1024 | 442 | #define DRIVER_STATE_BUF_LEN 1024 |
442 | 443 | ||
@@ -450,12 +451,28 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, | |||
450 | (res += scnprintf(buf + res, DRIVER_STATE_BUF_LEN - res,\ | 451 | (res += scnprintf(buf + res, DRIVER_STATE_BUF_LEN - res,\ |
451 | #x " = " fmt "\n", wl->x)) | 452 | #x " = " fmt "\n", wl->x)) |
452 | 453 | ||
454 | #define DRIVER_STATE_PRINT_GENERIC(x, fmt, args...) \ | ||
455 | (res += scnprintf(buf + res, DRIVER_STATE_BUF_LEN - res,\ | ||
456 | #x " = " fmt "\n", args)) | ||
457 | |||
453 | #define DRIVER_STATE_PRINT_LONG(x) DRIVER_STATE_PRINT(x, "%ld") | 458 | #define DRIVER_STATE_PRINT_LONG(x) DRIVER_STATE_PRINT(x, "%ld") |
454 | #define DRIVER_STATE_PRINT_INT(x) DRIVER_STATE_PRINT(x, "%d") | 459 | #define DRIVER_STATE_PRINT_INT(x) DRIVER_STATE_PRINT(x, "%d") |
455 | #define DRIVER_STATE_PRINT_STR(x) DRIVER_STATE_PRINT(x, "%s") | 460 | #define DRIVER_STATE_PRINT_STR(x) DRIVER_STATE_PRINT(x, "%s") |
456 | #define DRIVER_STATE_PRINT_LHEX(x) DRIVER_STATE_PRINT(x, "0x%lx") | 461 | #define DRIVER_STATE_PRINT_LHEX(x) DRIVER_STATE_PRINT(x, "0x%lx") |
457 | #define DRIVER_STATE_PRINT_HEX(x) DRIVER_STATE_PRINT(x, "0x%x") | 462 | #define DRIVER_STATE_PRINT_HEX(x) DRIVER_STATE_PRINT(x, "0x%x") |
458 | 463 | ||
464 | wl12xx_for_each_wlvif_sta(wl, wlvif) { | ||
465 | if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) | ||
466 | continue; | ||
467 | |||
468 | DRIVER_STATE_PRINT_GENERIC(channel, "%d (%s)", wlvif->channel, | ||
469 | wlvif->p2p ? "P2P-CL" : "STA"); | ||
470 | } | ||
471 | |||
472 | wl12xx_for_each_wlvif_ap(wl, wlvif) | ||
473 | DRIVER_STATE_PRINT_GENERIC(channel, "%d (%s)", wlvif->channel, | ||
474 | wlvif->p2p ? "P2P-GO" : "AP"); | ||
475 | |||
459 | DRIVER_STATE_PRINT_INT(tx_blocks_available); | 476 | DRIVER_STATE_PRINT_INT(tx_blocks_available); |
460 | DRIVER_STATE_PRINT_INT(tx_allocated_blocks); | 477 | DRIVER_STATE_PRINT_INT(tx_allocated_blocks); |
461 | DRIVER_STATE_PRINT_INT(tx_allocated_pkts[0]); | 478 | DRIVER_STATE_PRINT_INT(tx_allocated_pkts[0]); |
@@ -474,7 +491,6 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, | |||
474 | DRIVER_STATE_PRINT_INT(tx_blocks_freed); | 491 | DRIVER_STATE_PRINT_INT(tx_blocks_freed); |
475 | DRIVER_STATE_PRINT_INT(rx_counter); | 492 | DRIVER_STATE_PRINT_INT(rx_counter); |
476 | DRIVER_STATE_PRINT_INT(state); | 493 | DRIVER_STATE_PRINT_INT(state); |
477 | DRIVER_STATE_PRINT_INT(channel); | ||
478 | DRIVER_STATE_PRINT_INT(band); | 494 | DRIVER_STATE_PRINT_INT(band); |
479 | DRIVER_STATE_PRINT_INT(power_level); | 495 | DRIVER_STATE_PRINT_INT(power_level); |
480 | DRIVER_STATE_PRINT_INT(sg_enabled); | 496 | DRIVER_STATE_PRINT_INT(sg_enabled); |
diff --git a/drivers/net/wireless/ti/wlcore/event.c b/drivers/net/wireless/ti/wlcore/event.c index 67f61689b49e..8d3b34965db3 100644 --- a/drivers/net/wireless/ti/wlcore/event.c +++ b/drivers/net/wireless/ti/wlcore/event.c | |||
@@ -266,6 +266,7 @@ int wl1271_event_unmask(struct wl1271 *wl) | |||
266 | { | 266 | { |
267 | int ret; | 267 | int ret; |
268 | 268 | ||
269 | wl1271_debug(DEBUG_EVENT, "unmasking event_mask 0x%x", wl->event_mask); | ||
269 | ret = wl1271_acx_event_mbox_mask(wl, ~(wl->event_mask)); | 270 | ret = wl1271_acx_event_mbox_mask(wl, ~(wl->event_mask)); |
270 | if (ret < 0) | 271 | if (ret < 0) |
271 | return ret; | 272 | return ret; |
diff --git a/drivers/net/wireless/ti/wlcore/hw_ops.h b/drivers/net/wireless/ti/wlcore/hw_ops.h index 7fd260c02a0a..51f8d634d32f 100644 --- a/drivers/net/wireless/ti/wlcore/hw_ops.h +++ b/drivers/net/wireless/ti/wlcore/hw_ops.h | |||
@@ -222,6 +222,15 @@ wlcore_hw_set_peer_cap(struct wl1271 *wl, | |||
222 | return 0; | 222 | return 0; |
223 | } | 223 | } |
224 | 224 | ||
225 | static inline u32 | ||
226 | wlcore_hw_convert_hwaddr(struct wl1271 *wl, u32 hwaddr) | ||
227 | { | ||
228 | if (!wl->ops->convert_hwaddr) | ||
229 | BUG_ON(1); | ||
230 | |||
231 | return wl->ops->convert_hwaddr(wl, hwaddr); | ||
232 | } | ||
233 | |||
225 | static inline bool | 234 | static inline bool |
226 | wlcore_hw_lnk_high_prio(struct wl1271 *wl, u8 hlid, | 235 | wlcore_hw_lnk_high_prio(struct wl1271 *wl, u8 hlid, |
227 | struct wl1271_link *lnk) | 236 | struct wl1271_link *lnk) |
diff --git a/drivers/net/wireless/ti/wlcore/init.c b/drivers/net/wireless/ti/wlcore/init.c index 5c6f11e157d9..7699f9d07e26 100644 --- a/drivers/net/wireless/ti/wlcore/init.c +++ b/drivers/net/wireless/ti/wlcore/init.c | |||
@@ -571,6 +571,12 @@ int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif) | |||
571 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); | 571 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); |
572 | if (ret < 0) | 572 | if (ret < 0) |
573 | return ret; | 573 | return ret; |
574 | |||
575 | /* unmask ap events */ | ||
576 | wl->event_mask |= wl->ap_event_mask; | ||
577 | ret = wl1271_event_unmask(wl); | ||
578 | if (ret < 0) | ||
579 | return ret; | ||
574 | /* first STA, no APs */ | 580 | /* first STA, no APs */ |
575 | } else if (wl->sta_count == 0 && wl->ap_count == 0 && !is_ap) { | 581 | } else if (wl->sta_count == 0 && wl->ap_count == 0 && !is_ap) { |
576 | u8 sta_auth = wl->conf.conn.sta_sleep_auth; | 582 | u8 sta_auth = wl->conf.conn.sta_sleep_auth; |
diff --git a/drivers/net/wireless/ti/wlcore/io.h b/drivers/net/wireless/ti/wlcore/io.h index af7d9f9b3b4d..07e3d6a049ad 100644 --- a/drivers/net/wireless/ti/wlcore/io.h +++ b/drivers/net/wireless/ti/wlcore/io.h | |||
@@ -165,8 +165,8 @@ static inline int __must_check wlcore_read_hwaddr(struct wl1271 *wl, int hwaddr, | |||
165 | int physical; | 165 | int physical; |
166 | int addr; | 166 | int addr; |
167 | 167 | ||
168 | /* Addresses are stored internally as addresses to 32 bytes blocks */ | 168 | /* Convert from FW internal address which is chip arch dependent */ |
169 | addr = hwaddr << 5; | 169 | addr = wl->ops->convert_hwaddr(wl, hwaddr); |
170 | 170 | ||
171 | physical = wlcore_translate_addr(wl, addr); | 171 | physical = wlcore_translate_addr(wl, addr); |
172 | 172 | ||
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index bbdd10632373..0368b9cbfb89 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #define WL1271_BOOT_RETRIES 3 | 44 | #define WL1271_BOOT_RETRIES 3 |
45 | 45 | ||
46 | static char *fwlog_param; | 46 | static char *fwlog_param; |
47 | static int fwlog_mem_blocks = -1; | ||
47 | static int bug_on_recovery = -1; | 48 | static int bug_on_recovery = -1; |
48 | static int no_recovery = -1; | 49 | static int no_recovery = -1; |
49 | 50 | ||
@@ -291,6 +292,18 @@ static void wlcore_adjust_conf(struct wl1271 *wl) | |||
291 | { | 292 | { |
292 | /* Adjust settings according to optional module parameters */ | 293 | /* Adjust settings according to optional module parameters */ |
293 | 294 | ||
295 | /* Firmware Logger params */ | ||
296 | if (fwlog_mem_blocks != -1) { | ||
297 | if (fwlog_mem_blocks >= CONF_FWLOG_MIN_MEM_BLOCKS && | ||
298 | fwlog_mem_blocks <= CONF_FWLOG_MAX_MEM_BLOCKS) { | ||
299 | wl->conf.fwlog.mem_blocks = fwlog_mem_blocks; | ||
300 | } else { | ||
301 | wl1271_error( | ||
302 | "Illegal fwlog_mem_blocks=%d using default %d", | ||
303 | fwlog_mem_blocks, wl->conf.fwlog.mem_blocks); | ||
304 | } | ||
305 | } | ||
306 | |||
294 | if (fwlog_param) { | 307 | if (fwlog_param) { |
295 | if (!strcmp(fwlog_param, "continuous")) { | 308 | if (!strcmp(fwlog_param, "continuous")) { |
296 | wl->conf.fwlog.mode = WL12XX_FWLOG_CONTINUOUS; | 309 | wl->conf.fwlog.mode = WL12XX_FWLOG_CONTINUOUS; |
@@ -780,6 +793,7 @@ void wl12xx_queue_recovery_work(struct wl1271 *wl) | |||
780 | if (wl->state == WLCORE_STATE_ON) { | 793 | if (wl->state == WLCORE_STATE_ON) { |
781 | wl->state = WLCORE_STATE_RESTARTING; | 794 | wl->state = WLCORE_STATE_RESTARTING; |
782 | set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags); | 795 | set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags); |
796 | wl1271_ps_elp_wakeup(wl); | ||
783 | wlcore_disable_interrupts_nosync(wl); | 797 | wlcore_disable_interrupts_nosync(wl); |
784 | ieee80211_queue_work(wl->hw, &wl->recovery_work); | 798 | ieee80211_queue_work(wl->hw, &wl->recovery_work); |
785 | } | 799 | } |
@@ -787,19 +801,10 @@ void wl12xx_queue_recovery_work(struct wl1271 *wl) | |||
787 | 801 | ||
788 | size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen) | 802 | size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen) |
789 | { | 803 | { |
790 | size_t len = 0; | 804 | size_t len; |
791 | |||
792 | /* The FW log is a length-value list, find where the log end */ | ||
793 | while (len < maxlen) { | ||
794 | if (memblock[len] == 0) | ||
795 | break; | ||
796 | if (len + memblock[len] + 1 > maxlen) | ||
797 | break; | ||
798 | len += memblock[len] + 1; | ||
799 | } | ||
800 | 805 | ||
801 | /* Make sure we have enough room */ | 806 | /* Make sure we have enough room */ |
802 | len = min(len, (size_t)(PAGE_SIZE - wl->fwlog_size)); | 807 | len = min(maxlen, (size_t)(PAGE_SIZE - wl->fwlog_size)); |
803 | 808 | ||
804 | /* Fill the FW log file, consumed by the sysfs fwlog entry */ | 809 | /* Fill the FW log file, consumed by the sysfs fwlog entry */ |
805 | memcpy(wl->fwlog + wl->fwlog_size, memblock, len); | 810 | memcpy(wl->fwlog + wl->fwlog_size, memblock, len); |
@@ -808,10 +813,9 @@ size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen) | |||
808 | return len; | 813 | return len; |
809 | } | 814 | } |
810 | 815 | ||
811 | #define WLCORE_FW_LOG_END 0x2000000 | ||
812 | |||
813 | static void wl12xx_read_fwlog_panic(struct wl1271 *wl) | 816 | static void wl12xx_read_fwlog_panic(struct wl1271 *wl) |
814 | { | 817 | { |
818 | struct wlcore_partition_set part, old_part; | ||
815 | u32 addr; | 819 | u32 addr; |
816 | u32 offset; | 820 | u32 offset; |
817 | u32 end_of_log; | 821 | u32 end_of_log; |
@@ -824,7 +828,7 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl) | |||
824 | 828 | ||
825 | wl1271_info("Reading FW panic log"); | 829 | wl1271_info("Reading FW panic log"); |
826 | 830 | ||
827 | block = kmalloc(WL12XX_HW_BLOCK_SIZE, GFP_KERNEL); | 831 | block = kmalloc(wl->fw_mem_block_size, GFP_KERNEL); |
828 | if (!block) | 832 | if (!block) |
829 | return; | 833 | return; |
830 | 834 | ||
@@ -850,17 +854,31 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl) | |||
850 | 854 | ||
851 | if (wl->conf.fwlog.mode == WL12XX_FWLOG_CONTINUOUS) { | 855 | if (wl->conf.fwlog.mode == WL12XX_FWLOG_CONTINUOUS) { |
852 | offset = sizeof(addr) + sizeof(struct wl1271_rx_descriptor); | 856 | offset = sizeof(addr) + sizeof(struct wl1271_rx_descriptor); |
853 | end_of_log = WLCORE_FW_LOG_END; | 857 | end_of_log = wl->fwlog_end; |
854 | } else { | 858 | } else { |
855 | offset = sizeof(addr); | 859 | offset = sizeof(addr); |
856 | end_of_log = addr; | 860 | end_of_log = addr; |
857 | } | 861 | } |
858 | 862 | ||
863 | old_part = wl->curr_part; | ||
864 | memset(&part, 0, sizeof(part)); | ||
865 | |||
859 | /* Traverse the memory blocks linked list */ | 866 | /* Traverse the memory blocks linked list */ |
860 | do { | 867 | do { |
861 | memset(block, 0, WL12XX_HW_BLOCK_SIZE); | 868 | part.mem.start = wlcore_hw_convert_hwaddr(wl, addr); |
862 | ret = wlcore_read_hwaddr(wl, addr, block, WL12XX_HW_BLOCK_SIZE, | 869 | part.mem.size = PAGE_SIZE; |
863 | false); | 870 | |
871 | ret = wlcore_set_partition(wl, &part); | ||
872 | if (ret < 0) { | ||
873 | wl1271_error("%s: set_partition start=0x%X size=%d", | ||
874 | __func__, part.mem.start, part.mem.size); | ||
875 | goto out; | ||
876 | } | ||
877 | |||
878 | memset(block, 0, wl->fw_mem_block_size); | ||
879 | ret = wlcore_read_hwaddr(wl, addr, block, | ||
880 | wl->fw_mem_block_size, false); | ||
881 | |||
864 | if (ret < 0) | 882 | if (ret < 0) |
865 | goto out; | 883 | goto out; |
866 | 884 | ||
@@ -871,8 +889,9 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl) | |||
871 | * on demand mode and is equal to 0x2000000 in continuous mode. | 889 | * on demand mode and is equal to 0x2000000 in continuous mode. |
872 | */ | 890 | */ |
873 | addr = le32_to_cpup((__le32 *)block); | 891 | addr = le32_to_cpup((__le32 *)block); |
892 | |||
874 | if (!wl12xx_copy_fwlog(wl, block + offset, | 893 | if (!wl12xx_copy_fwlog(wl, block + offset, |
875 | WL12XX_HW_BLOCK_SIZE - offset)) | 894 | wl->fw_mem_block_size - offset)) |
876 | break; | 895 | break; |
877 | } while (addr && (addr != end_of_log)); | 896 | } while (addr && (addr != end_of_log)); |
878 | 897 | ||
@@ -880,6 +899,7 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl) | |||
880 | 899 | ||
881 | out: | 900 | out: |
882 | kfree(block); | 901 | kfree(block); |
902 | wlcore_set_partition(wl, &old_part); | ||
883 | } | 903 | } |
884 | 904 | ||
885 | static void wlcore_print_recovery(struct wl1271 *wl) | 905 | static void wlcore_print_recovery(struct wl1271 *wl) |
@@ -924,7 +944,8 @@ static void wl1271_recovery_work(struct work_struct *work) | |||
924 | goto out_unlock; | 944 | goto out_unlock; |
925 | 945 | ||
926 | if (!test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)) { | 946 | if (!test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)) { |
927 | wl12xx_read_fwlog_panic(wl); | 947 | if (wl->conf.fwlog.output == WL12XX_FWLOG_OUTPUT_HOST) |
948 | wl12xx_read_fwlog_panic(wl); | ||
928 | wlcore_print_recovery(wl); | 949 | wlcore_print_recovery(wl); |
929 | } | 950 | } |
930 | 951 | ||
@@ -1928,8 +1949,10 @@ static void wlcore_op_stop_locked(struct wl1271 *wl) | |||
1928 | 1949 | ||
1929 | /* | 1950 | /* |
1930 | * FW channels must be re-calibrated after recovery, | 1951 | * FW channels must be re-calibrated after recovery, |
1931 | * clear the last Reg-Domain channel configuration. | 1952 | * save current Reg-Domain channel configuration and clear it. |
1932 | */ | 1953 | */ |
1954 | memcpy(wl->reg_ch_conf_pending, wl->reg_ch_conf_last, | ||
1955 | sizeof(wl->reg_ch_conf_pending)); | ||
1933 | memset(wl->reg_ch_conf_last, 0, sizeof(wl->reg_ch_conf_last)); | 1956 | memset(wl->reg_ch_conf_last, 0, sizeof(wl->reg_ch_conf_last)); |
1934 | } | 1957 | } |
1935 | 1958 | ||
@@ -2623,6 +2646,12 @@ deinit: | |||
2623 | !test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)) | 2646 | !test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)) |
2624 | goto unlock; | 2647 | goto unlock; |
2625 | 2648 | ||
2649 | if (wl->ap_count == 0 && is_ap) { | ||
2650 | /* mask ap events */ | ||
2651 | wl->event_mask &= ~wl->ap_event_mask; | ||
2652 | wl1271_event_unmask(wl); | ||
2653 | } | ||
2654 | |||
2626 | if (wl->ap_count == 0 && is_ap && wl->sta_count) { | 2655 | if (wl->ap_count == 0 && is_ap && wl->sta_count) { |
2627 | u8 sta_auth = wl->conf.conn.sta_sleep_auth; | 2656 | u8 sta_auth = wl->conf.conn.sta_sleep_auth; |
2628 | /* Configure for power according to debugfs */ | 2657 | /* Configure for power according to debugfs */ |
@@ -6152,6 +6181,9 @@ module_param_named(fwlog, fwlog_param, charp, 0); | |||
6152 | MODULE_PARM_DESC(fwlog, | 6181 | MODULE_PARM_DESC(fwlog, |
6153 | "FW logger options: continuous, ondemand, dbgpins or disable"); | 6182 | "FW logger options: continuous, ondemand, dbgpins or disable"); |
6154 | 6183 | ||
6184 | module_param(fwlog_mem_blocks, int, S_IRUSR | S_IWUSR); | ||
6185 | MODULE_PARM_DESC(fwlog_mem_blocks, "fwlog mem_blocks"); | ||
6186 | |||
6155 | module_param(bug_on_recovery, int, S_IRUSR | S_IWUSR); | 6187 | module_param(bug_on_recovery, int, S_IRUSR | S_IWUSR); |
6156 | MODULE_PARM_DESC(bug_on_recovery, "BUG() on fw recovery"); | 6188 | MODULE_PARM_DESC(bug_on_recovery, "BUG() on fw recovery"); |
6157 | 6189 | ||
diff --git a/drivers/net/wireless/ti/wlcore/scan.c b/drivers/net/wireless/ti/wlcore/scan.c index 13e743df2e31..7ed86203304b 100644 --- a/drivers/net/wireless/ti/wlcore/scan.c +++ b/drivers/net/wireless/ti/wlcore/scan.c | |||
@@ -92,9 +92,31 @@ out: | |||
92 | static void wlcore_started_vifs_iter(void *data, u8 *mac, | 92 | static void wlcore_started_vifs_iter(void *data, u8 *mac, |
93 | struct ieee80211_vif *vif) | 93 | struct ieee80211_vif *vif) |
94 | { | 94 | { |
95 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | ||
96 | bool active = false; | ||
95 | int *count = (int *)data; | 97 | int *count = (int *)data; |
96 | 98 | ||
97 | if (!vif->bss_conf.idle) | 99 | /* |
100 | * count active interfaces according to interface type. | ||
101 | * checking only bss_conf.idle is bad for some cases, e.g. | ||
102 | * we don't want to count sta in p2p_find as active interface. | ||
103 | */ | ||
104 | switch (wlvif->bss_type) { | ||
105 | case BSS_TYPE_STA_BSS: | ||
106 | if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) | ||
107 | active = true; | ||
108 | break; | ||
109 | |||
110 | case BSS_TYPE_AP_BSS: | ||
111 | if (wlvif->wl->active_sta_count > 0) | ||
112 | active = true; | ||
113 | break; | ||
114 | |||
115 | default: | ||
116 | break; | ||
117 | } | ||
118 | |||
119 | if (active) | ||
98 | (*count)++; | 120 | (*count)++; |
99 | } | 121 | } |
100 | 122 | ||
diff --git a/drivers/net/wireless/ti/wlcore/testmode.c b/drivers/net/wireless/ti/wlcore/testmode.c index a3b7d950d8e9..ddad58f614da 100644 --- a/drivers/net/wireless/ti/wlcore/testmode.c +++ b/drivers/net/wireless/ti/wlcore/testmode.c | |||
@@ -179,7 +179,8 @@ static int wl1271_tm_cmd_interrogate(struct wl1271 *wl, struct nlattr *tb[]) | |||
179 | goto out_sleep; | 179 | goto out_sleep; |
180 | } | 180 | } |
181 | 181 | ||
182 | ret = wl1271_cmd_interrogate(wl, ie_id, cmd, sizeof(*cmd)); | 182 | ret = wl1271_cmd_interrogate(wl, ie_id, cmd, |
183 | sizeof(struct acx_header), sizeof(*cmd)); | ||
183 | if (ret < 0) { | 184 | if (ret < 0) { |
184 | wl1271_warning("testmode cmd interrogate failed: %d", ret); | 185 | wl1271_warning("testmode cmd interrogate failed: %d", ret); |
185 | goto out_free; | 186 | goto out_free; |
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h index 54ce5d5e84db..06efc12a39e5 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/drivers/net/wireless/ti/wlcore/wlcore.h | |||
@@ -110,6 +110,7 @@ struct wlcore_ops { | |||
110 | struct ieee80211_sta_ht_cap *ht_cap, | 110 | struct ieee80211_sta_ht_cap *ht_cap, |
111 | bool allow_ht_operation, | 111 | bool allow_ht_operation, |
112 | u32 rate_set, u8 hlid); | 112 | u32 rate_set, u8 hlid); |
113 | u32 (*convert_hwaddr)(struct wl1271 *wl, u32 hwaddr); | ||
113 | bool (*lnk_high_prio)(struct wl1271 *wl, u8 hlid, | 114 | bool (*lnk_high_prio)(struct wl1271 *wl, u8 hlid, |
114 | struct wl1271_link *lnk); | 115 | struct wl1271_link *lnk); |
115 | bool (*lnk_low_prio)(struct wl1271 *wl, u8 hlid, | 116 | bool (*lnk_low_prio)(struct wl1271 *wl, u8 hlid, |
@@ -290,6 +291,12 @@ struct wl1271 { | |||
290 | /* Number of valid bytes in the FW log buffer */ | 291 | /* Number of valid bytes in the FW log buffer */ |
291 | ssize_t fwlog_size; | 292 | ssize_t fwlog_size; |
292 | 293 | ||
294 | /* FW log end marker */ | ||
295 | u32 fwlog_end; | ||
296 | |||
297 | /* FW memory block size */ | ||
298 | u32 fw_mem_block_size; | ||
299 | |||
293 | /* Sysfs FW log entry readers wait queue */ | 300 | /* Sysfs FW log entry readers wait queue */ |
294 | wait_queue_head_t fwlog_waitq; | 301 | wait_queue_head_t fwlog_waitq; |
295 | 302 | ||
@@ -307,6 +314,8 @@ struct wl1271 { | |||
307 | 314 | ||
308 | /* The mbox event mask */ | 315 | /* The mbox event mask */ |
309 | u32 event_mask; | 316 | u32 event_mask; |
317 | /* events to unmask only when ap interface is up */ | ||
318 | u32 ap_event_mask; | ||
310 | 319 | ||
311 | /* Mailbox pointers */ | 320 | /* Mailbox pointers */ |
312 | u32 mbox_size; | 321 | u32 mbox_size; |
diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h index 2a50e089b0e7..ce7261ce8b59 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore_i.h +++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h | |||
@@ -550,6 +550,4 @@ void wl1271_rx_filter_flatten_fields(struct wl12xx_rx_filter *filter, | |||
550 | #define HW_HT_RATES_OFFSET 16 | 550 | #define HW_HT_RATES_OFFSET 16 |
551 | #define HW_MIMO_RATES_OFFSET 24 | 551 | #define HW_MIMO_RATES_OFFSET 24 |
552 | 552 | ||
553 | #define WL12XX_HW_BLOCK_SIZE 256 | ||
554 | |||
555 | #endif /* __WLCORE_I_H__ */ | 553 | #endif /* __WLCORE_I_H__ */ |
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 7c1e1ebc0e23..8c3b26a21574 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h | |||
@@ -697,6 +697,18 @@ struct ieee80211_sec_chan_offs_ie { | |||
697 | } __packed; | 697 | } __packed; |
698 | 698 | ||
699 | /** | 699 | /** |
700 | * struct ieee80211_mesh_chansw_params_ie - mesh channel switch parameters IE | ||
701 | * | ||
702 | * This structure represents the "Mesh Channel Switch Paramters element" | ||
703 | */ | ||
704 | struct ieee80211_mesh_chansw_params_ie { | ||
705 | u8 mesh_ttl; | ||
706 | u8 mesh_flags; | ||
707 | __le16 mesh_reason; | ||
708 | __le16 mesh_pre_value; | ||
709 | } __packed; | ||
710 | |||
711 | /** | ||
700 | * struct ieee80211_wide_bw_chansw_ie - wide bandwidth channel switch IE | 712 | * struct ieee80211_wide_bw_chansw_ie - wide bandwidth channel switch IE |
701 | */ | 713 | */ |
702 | struct ieee80211_wide_bw_chansw_ie { | 714 | struct ieee80211_wide_bw_chansw_ie { |
@@ -751,6 +763,14 @@ enum mesh_config_capab_flags { | |||
751 | }; | 763 | }; |
752 | 764 | ||
753 | /** | 765 | /** |
766 | * mesh channel switch parameters element's flag indicator | ||
767 | * | ||
768 | */ | ||
769 | #define WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT BIT(0) | ||
770 | #define WLAN_EID_CHAN_SWITCH_PARAM_INITIATOR BIT(1) | ||
771 | #define WLAN_EID_CHAN_SWITCH_PARAM_REASON BIT(2) | ||
772 | |||
773 | /** | ||
754 | * struct ieee80211_rann_ie | 774 | * struct ieee80211_rann_ie |
755 | * | 775 | * |
756 | * This structure refers to "Root Announcement information element" | 776 | * This structure refers to "Root Announcement information element" |
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 2cc9517fb0d5..2a628b28249f 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h | |||
@@ -282,6 +282,7 @@ struct bt_skb_cb { | |||
282 | __u8 incoming; | 282 | __u8 incoming; |
283 | __u16 expect; | 283 | __u16 expect; |
284 | __u8 force_active; | 284 | __u8 force_active; |
285 | struct l2cap_chan *chan; | ||
285 | struct l2cap_ctrl control; | 286 | struct l2cap_ctrl control; |
286 | struct hci_req_ctrl req; | 287 | struct hci_req_ctrl req; |
287 | bdaddr_t bdaddr; | 288 | bdaddr_t bdaddr; |
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index b096f5f73789..1784c48699f0 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h | |||
@@ -115,6 +115,7 @@ enum { | |||
115 | HCI_PAIRABLE, | 115 | HCI_PAIRABLE, |
116 | HCI_SERVICE_CACHE, | 116 | HCI_SERVICE_CACHE, |
117 | HCI_DEBUG_KEYS, | 117 | HCI_DEBUG_KEYS, |
118 | HCI_DUT_MODE, | ||
118 | HCI_UNREGISTER, | 119 | HCI_UNREGISTER, |
119 | HCI_USER_CHANNEL, | 120 | HCI_USER_CHANNEL, |
120 | 121 | ||
@@ -125,6 +126,7 @@ enum { | |||
125 | HCI_ADVERTISING, | 126 | HCI_ADVERTISING, |
126 | HCI_CONNECTABLE, | 127 | HCI_CONNECTABLE, |
127 | HCI_DISCOVERABLE, | 128 | HCI_DISCOVERABLE, |
129 | HCI_LIMITED_DISCOVERABLE, | ||
128 | HCI_LINK_SECURITY, | 130 | HCI_LINK_SECURITY, |
129 | HCI_PERIODIC_INQ, | 131 | HCI_PERIODIC_INQ, |
130 | HCI_FAST_CONNECTABLE, | 132 | HCI_FAST_CONNECTABLE, |
@@ -823,6 +825,12 @@ struct hci_rp_read_num_supported_iac { | |||
823 | 825 | ||
824 | #define HCI_OP_READ_CURRENT_IAC_LAP 0x0c39 | 826 | #define HCI_OP_READ_CURRENT_IAC_LAP 0x0c39 |
825 | 827 | ||
828 | #define HCI_OP_WRITE_CURRENT_IAC_LAP 0x0c3a | ||
829 | struct hci_cp_write_current_iac_lap { | ||
830 | __u8 num_iac; | ||
831 | __u8 iac_lap[6]; | ||
832 | } __packed; | ||
833 | |||
826 | #define HCI_OP_WRITE_INQUIRY_MODE 0x0c45 | 834 | #define HCI_OP_WRITE_INQUIRY_MODE 0x0c45 |
827 | 835 | ||
828 | #define HCI_MAX_EIR_LENGTH 240 | 836 | #define HCI_MAX_EIR_LENGTH 240 |
@@ -1036,6 +1044,10 @@ struct hci_rp_write_remote_amp_assoc { | |||
1036 | __u8 phy_handle; | 1044 | __u8 phy_handle; |
1037 | } __packed; | 1045 | } __packed; |
1038 | 1046 | ||
1047 | #define HCI_OP_ENABLE_DUT_MODE 0x1803 | ||
1048 | |||
1049 | #define HCI_OP_WRITE_SSP_DEBUG_MODE 0x1804 | ||
1050 | |||
1039 | #define HCI_OP_LE_SET_EVENT_MASK 0x2001 | 1051 | #define HCI_OP_LE_SET_EVENT_MASK 0x2001 |
1040 | struct hci_cp_le_set_event_mask { | 1052 | struct hci_cp_le_set_event_mask { |
1041 | __u8 mask[8]; | 1053 | __u8 mask[8]; |
@@ -1056,11 +1068,6 @@ struct hci_rp_le_read_local_features { | |||
1056 | 1068 | ||
1057 | #define HCI_OP_LE_SET_RANDOM_ADDR 0x2005 | 1069 | #define HCI_OP_LE_SET_RANDOM_ADDR 0x2005 |
1058 | 1070 | ||
1059 | #define LE_ADV_IND 0x00 | ||
1060 | #define LE_ADV_DIRECT_IND 0x01 | ||
1061 | #define LE_ADV_SCAN_IND 0x02 | ||
1062 | #define LE_ADV_NONCONN_IND 0x03 | ||
1063 | |||
1064 | #define HCI_OP_LE_SET_ADV_PARAM 0x2006 | 1071 | #define HCI_OP_LE_SET_ADV_PARAM 0x2006 |
1065 | struct hci_cp_le_set_adv_param { | 1072 | struct hci_cp_le_set_adv_param { |
1066 | __le16 min_interval; | 1073 | __le16 min_interval; |
@@ -1087,6 +1094,12 @@ struct hci_cp_le_set_adv_data { | |||
1087 | __u8 data[HCI_MAX_AD_LENGTH]; | 1094 | __u8 data[HCI_MAX_AD_LENGTH]; |
1088 | } __packed; | 1095 | } __packed; |
1089 | 1096 | ||
1097 | #define HCI_OP_LE_SET_SCAN_RSP_DATA 0x2009 | ||
1098 | struct hci_cp_le_set_scan_rsp_data { | ||
1099 | __u8 length; | ||
1100 | __u8 data[HCI_MAX_AD_LENGTH]; | ||
1101 | } __packed; | ||
1102 | |||
1090 | #define HCI_OP_LE_SET_ADV_ENABLE 0x200a | 1103 | #define HCI_OP_LE_SET_ADV_ENABLE 0x200a |
1091 | 1104 | ||
1092 | #define LE_SCAN_PASSIVE 0x00 | 1105 | #define LE_SCAN_PASSIVE 0x00 |
@@ -1567,11 +1580,11 @@ struct hci_ev_le_ltk_req { | |||
1567 | } __packed; | 1580 | } __packed; |
1568 | 1581 | ||
1569 | /* Advertising report event types */ | 1582 | /* Advertising report event types */ |
1570 | #define ADV_IND 0x00 | 1583 | #define LE_ADV_IND 0x00 |
1571 | #define ADV_DIRECT_IND 0x01 | 1584 | #define LE_ADV_DIRECT_IND 0x01 |
1572 | #define ADV_SCAN_IND 0x02 | 1585 | #define LE_ADV_SCAN_IND 0x02 |
1573 | #define ADV_NONCONN_IND 0x03 | 1586 | #define LE_ADV_NONCONN_IND 0x03 |
1574 | #define ADV_SCAN_RSP 0x04 | 1587 | #define LE_ADV_SCAN_RSP 0x04 |
1575 | 1588 | ||
1576 | #define ADDR_LE_DEV_PUBLIC 0x00 | 1589 | #define ADDR_LE_DEV_PUBLIC 0x00 |
1577 | #define ADDR_LE_DEV_RANDOM 0x01 | 1590 | #define ADDR_LE_DEV_RANDOM 0x01 |
@@ -1779,6 +1792,4 @@ struct hci_inquiry_req { | |||
1779 | }; | 1792 | }; |
1780 | #define IREQ_CACHE_FLUSH 0x0001 | 1793 | #define IREQ_CACHE_FLUSH 0x0001 |
1781 | 1794 | ||
1782 | extern bool enable_hs; | ||
1783 | |||
1784 | #endif /* __HCI_H */ | 1795 | #endif /* __HCI_H */ |
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 2dc467939be7..f8555ad7b104 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
@@ -81,6 +81,7 @@ struct hci_conn_hash { | |||
81 | struct bdaddr_list { | 81 | struct bdaddr_list { |
82 | struct list_head list; | 82 | struct list_head list; |
83 | bdaddr_t bdaddr; | 83 | bdaddr_t bdaddr; |
84 | u8 bdaddr_type; | ||
84 | }; | 85 | }; |
85 | 86 | ||
86 | struct bt_uuid { | 87 | struct bt_uuid { |
@@ -141,6 +142,7 @@ struct hci_dev { | |||
141 | __u8 dev_type; | 142 | __u8 dev_type; |
142 | bdaddr_t bdaddr; | 143 | bdaddr_t bdaddr; |
143 | bdaddr_t static_addr; | 144 | bdaddr_t static_addr; |
145 | __u8 own_addr_type; | ||
144 | __u8 dev_name[HCI_MAX_NAME_LENGTH]; | 146 | __u8 dev_name[HCI_MAX_NAME_LENGTH]; |
145 | __u8 short_name[HCI_MAX_SHORT_NAME_LENGTH]; | 147 | __u8 short_name[HCI_MAX_SHORT_NAME_LENGTH]; |
146 | __u8 eir[HCI_MAX_EIR_LENGTH]; | 148 | __u8 eir[HCI_MAX_EIR_LENGTH]; |
@@ -167,6 +169,9 @@ struct hci_dev { | |||
167 | __u8 page_scan_type; | 169 | __u8 page_scan_type; |
168 | __u16 le_scan_interval; | 170 | __u16 le_scan_interval; |
169 | __u16 le_scan_window; | 171 | __u16 le_scan_window; |
172 | __u16 le_conn_min_interval; | ||
173 | __u16 le_conn_max_interval; | ||
174 | __u8 ssp_debug_mode; | ||
170 | 175 | ||
171 | __u16 devid_source; | 176 | __u16 devid_source; |
172 | __u16 devid_vendor; | 177 | __u16 devid_vendor; |
@@ -283,6 +288,8 @@ struct hci_dev { | |||
283 | __s8 adv_tx_power; | 288 | __s8 adv_tx_power; |
284 | __u8 adv_data[HCI_MAX_AD_LENGTH]; | 289 | __u8 adv_data[HCI_MAX_AD_LENGTH]; |
285 | __u8 adv_data_len; | 290 | __u8 adv_data_len; |
291 | __u8 scan_rsp_data[HCI_MAX_AD_LENGTH]; | ||
292 | __u8 scan_rsp_data_len; | ||
286 | 293 | ||
287 | int (*open)(struct hci_dev *hdev); | 294 | int (*open)(struct hci_dev *hdev); |
288 | int (*close)(struct hci_dev *hdev); | 295 | int (*close)(struct hci_dev *hdev); |
@@ -311,7 +318,6 @@ struct hci_conn { | |||
311 | __u8 attempt; | 318 | __u8 attempt; |
312 | __u8 dev_class[3]; | 319 | __u8 dev_class[3]; |
313 | __u8 features[HCI_MAX_PAGES][8]; | 320 | __u8 features[HCI_MAX_PAGES][8]; |
314 | __u16 interval; | ||
315 | __u16 pkt_type; | 321 | __u16 pkt_type; |
316 | __u16 link_policy; | 322 | __u16 link_policy; |
317 | __u32 link_mode; | 323 | __u32 link_mode; |
@@ -339,8 +345,8 @@ struct hci_conn { | |||
339 | struct list_head chan_list; | 345 | struct list_head chan_list; |
340 | 346 | ||
341 | struct delayed_work disc_work; | 347 | struct delayed_work disc_work; |
342 | struct timer_list idle_timer; | 348 | struct delayed_work auto_accept_work; |
343 | struct timer_list auto_accept_timer; | 349 | struct delayed_work idle_work; |
344 | 350 | ||
345 | struct device dev; | 351 | struct device dev; |
346 | 352 | ||
@@ -648,7 +654,7 @@ static inline void hci_conn_drop(struct hci_conn *conn) | |||
648 | switch (conn->type) { | 654 | switch (conn->type) { |
649 | case ACL_LINK: | 655 | case ACL_LINK: |
650 | case LE_LINK: | 656 | case LE_LINK: |
651 | del_timer(&conn->idle_timer); | 657 | cancel_delayed_work(&conn->idle_work); |
652 | if (conn->state == BT_CONNECTED) { | 658 | if (conn->state == BT_CONNECTED) { |
653 | timeo = conn->disc_timeout; | 659 | timeo = conn->disc_timeout; |
654 | if (!conn->out) | 660 | if (!conn->out) |
@@ -729,7 +735,7 @@ int hci_get_auth_info(struct hci_dev *hdev, void __user *arg); | |||
729 | int hci_inquiry(void __user *arg); | 735 | int hci_inquiry(void __user *arg); |
730 | 736 | ||
731 | struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, | 737 | struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, |
732 | bdaddr_t *bdaddr); | 738 | bdaddr_t *bdaddr, u8 type); |
733 | int hci_blacklist_clear(struct hci_dev *hdev); | 739 | int hci_blacklist_clear(struct hci_dev *hdev); |
734 | int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); | 740 | int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); |
735 | int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); | 741 | int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); |
@@ -764,8 +770,6 @@ int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count); | |||
764 | int hci_recv_stream_fragment(struct hci_dev *hdev, void *data, int count); | 770 | int hci_recv_stream_fragment(struct hci_dev *hdev, void *data, int count); |
765 | 771 | ||
766 | void hci_init_sysfs(struct hci_dev *hdev); | 772 | void hci_init_sysfs(struct hci_dev *hdev); |
767 | int hci_add_sysfs(struct hci_dev *hdev); | ||
768 | void hci_del_sysfs(struct hci_dev *hdev); | ||
769 | void hci_conn_init_sysfs(struct hci_conn *conn); | 773 | void hci_conn_init_sysfs(struct hci_conn *conn); |
770 | void hci_conn_add_sysfs(struct hci_conn *conn); | 774 | void hci_conn_add_sysfs(struct hci_conn *conn); |
771 | void hci_conn_del_sysfs(struct hci_conn *conn); | 775 | void hci_conn_del_sysfs(struct hci_conn *conn); |
@@ -1008,34 +1012,6 @@ static inline bool eir_has_data_type(u8 *data, size_t data_len, u8 type) | |||
1008 | return false; | 1012 | return false; |
1009 | } | 1013 | } |
1010 | 1014 | ||
1011 | static inline size_t eir_get_length(u8 *eir, size_t eir_len) | ||
1012 | { | ||
1013 | size_t parsed = 0; | ||
1014 | |||
1015 | while (parsed < eir_len) { | ||
1016 | u8 field_len = eir[0]; | ||
1017 | |||
1018 | if (field_len == 0) | ||
1019 | return parsed; | ||
1020 | |||
1021 | parsed += field_len + 1; | ||
1022 | eir += field_len + 1; | ||
1023 | } | ||
1024 | |||
1025 | return eir_len; | ||
1026 | } | ||
1027 | |||
1028 | static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data, | ||
1029 | u8 data_len) | ||
1030 | { | ||
1031 | eir[eir_len++] = sizeof(type) + data_len; | ||
1032 | eir[eir_len++] = type; | ||
1033 | memcpy(&eir[eir_len], data, data_len); | ||
1034 | eir_len += data_len; | ||
1035 | |||
1036 | return eir_len; | ||
1037 | } | ||
1038 | |||
1039 | int hci_register_cb(struct hci_cb *hcb); | 1015 | int hci_register_cb(struct hci_cb *hcb); |
1040 | int hci_unregister_cb(struct hci_cb *hcb); | 1016 | int hci_unregister_cb(struct hci_cb *hcb); |
1041 | 1017 | ||
@@ -1099,11 +1075,12 @@ void mgmt_index_added(struct hci_dev *hdev); | |||
1099 | void mgmt_index_removed(struct hci_dev *hdev); | 1075 | void mgmt_index_removed(struct hci_dev *hdev); |
1100 | void mgmt_set_powered_failed(struct hci_dev *hdev, int err); | 1076 | void mgmt_set_powered_failed(struct hci_dev *hdev, int err); |
1101 | int mgmt_powered(struct hci_dev *hdev, u8 powered); | 1077 | int mgmt_powered(struct hci_dev *hdev, u8 powered); |
1102 | int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable); | 1078 | void mgmt_discoverable_timeout(struct hci_dev *hdev); |
1103 | int mgmt_connectable(struct hci_dev *hdev, u8 connectable); | 1079 | void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable); |
1104 | int mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status); | 1080 | void mgmt_connectable(struct hci_dev *hdev, u8 connectable); |
1105 | int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, | 1081 | void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status); |
1106 | bool persistent); | 1082 | void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, |
1083 | bool persistent); | ||
1107 | void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | 1084 | void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, |
1108 | u8 addr_type, u32 flags, u8 *name, u8 name_len, | 1085 | u8 addr_type, u32 flags, u8 *name, u8 name_len, |
1109 | u8 *dev_class); | 1086 | u8 *dev_class); |
@@ -1113,11 +1090,11 @@ void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, | |||
1113 | u8 link_type, u8 addr_type, u8 status); | 1090 | u8 link_type, u8 addr_type, u8 status); |
1114 | void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | 1091 | void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, |
1115 | u8 addr_type, u8 status); | 1092 | u8 addr_type, u8 status); |
1116 | int mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure); | 1093 | void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure); |
1117 | int mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, | 1094 | void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, |
1118 | u8 status); | 1095 | u8 status); |
1119 | int mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, | 1096 | void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, |
1120 | u8 status); | 1097 | u8 status); |
1121 | int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr, | 1098 | int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr, |
1122 | u8 link_type, u8 addr_type, __le32 value, | 1099 | u8 link_type, u8 addr_type, __le32 value, |
1123 | u8 confirm_hint); | 1100 | u8 confirm_hint); |
@@ -1134,15 +1111,15 @@ int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, | |||
1134 | int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr, | 1111 | int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr, |
1135 | u8 link_type, u8 addr_type, u32 passkey, | 1112 | u8 link_type, u8 addr_type, u32 passkey, |
1136 | u8 entered); | 1113 | u8 entered); |
1137 | int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | 1114 | void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, |
1138 | u8 addr_type, u8 status); | 1115 | u8 addr_type, u8 status); |
1139 | int mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status); | 1116 | void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status); |
1140 | int mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status); | 1117 | void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status); |
1141 | int mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class, | 1118 | void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class, |
1142 | u8 status); | 1119 | u8 status); |
1143 | int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status); | 1120 | void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status); |
1144 | int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash, | 1121 | void mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash, |
1145 | u8 *randomizer, u8 status); | 1122 | u8 *randomizer, u8 status); |
1146 | void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | 1123 | void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, |
1147 | u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name, | 1124 | u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name, |
1148 | u8 ssp, u8 *eir, u16 eir_len); | 1125 | u8 ssp, u8 *eir, u16 eir_len); |
@@ -1151,7 +1128,7 @@ void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | |||
1151 | void mgmt_discovering(struct hci_dev *hdev, u8 discovering); | 1128 | void mgmt_discovering(struct hci_dev *hdev, u8 discovering); |
1152 | int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); | 1129 | int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); |
1153 | int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); | 1130 | int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); |
1154 | int mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent); | 1131 | void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent); |
1155 | void mgmt_reenable_advertising(struct hci_dev *hdev); | 1132 | void mgmt_reenable_advertising(struct hci_dev *hdev); |
1156 | 1133 | ||
1157 | /* HCI info for socket */ | 1134 | /* HCI info for socket */ |
@@ -1182,8 +1159,6 @@ struct hci_sec_filter { | |||
1182 | #define hci_req_lock(d) mutex_lock(&d->req_lock) | 1159 | #define hci_req_lock(d) mutex_lock(&d->req_lock) |
1183 | #define hci_req_unlock(d) mutex_unlock(&d->req_lock) | 1160 | #define hci_req_unlock(d) mutex_unlock(&d->req_lock) |
1184 | 1161 | ||
1185 | void hci_update_ad(struct hci_request *req); | ||
1186 | |||
1187 | void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, | 1162 | void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, |
1188 | u16 latency, u16 to_multiplier); | 1163 | u16 latency, u16 to_multiplier); |
1189 | void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8], | 1164 | void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8], |
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 07757a2af942..51329905bfaa 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h | |||
@@ -435,8 +435,6 @@ struct l2cap_seq_list { | |||
435 | #define L2CAP_SEQ_LIST_TAIL 0x8000 | 435 | #define L2CAP_SEQ_LIST_TAIL 0x8000 |
436 | 436 | ||
437 | struct l2cap_chan { | 437 | struct l2cap_chan { |
438 | struct sock *sk; | ||
439 | |||
440 | struct l2cap_conn *conn; | 438 | struct l2cap_conn *conn; |
441 | struct hci_conn *hs_hcon; | 439 | struct hci_conn *hs_hcon; |
442 | struct hci_chan *hs_hchan; | 440 | struct hci_chan *hs_hchan; |
@@ -551,10 +549,12 @@ struct l2cap_ops { | |||
551 | void (*teardown) (struct l2cap_chan *chan, int err); | 549 | void (*teardown) (struct l2cap_chan *chan, int err); |
552 | void (*close) (struct l2cap_chan *chan); | 550 | void (*close) (struct l2cap_chan *chan); |
553 | void (*state_change) (struct l2cap_chan *chan, | 551 | void (*state_change) (struct l2cap_chan *chan, |
554 | int state); | 552 | int state, int err); |
555 | void (*ready) (struct l2cap_chan *chan); | 553 | void (*ready) (struct l2cap_chan *chan); |
556 | void (*defer) (struct l2cap_chan *chan); | 554 | void (*defer) (struct l2cap_chan *chan); |
557 | void (*resume) (struct l2cap_chan *chan); | 555 | void (*resume) (struct l2cap_chan *chan); |
556 | void (*set_shutdown) (struct l2cap_chan *chan); | ||
557 | long (*get_sndtimeo) (struct l2cap_chan *chan); | ||
558 | struct sk_buff *(*alloc_skb) (struct l2cap_chan *chan, | 558 | struct sk_buff *(*alloc_skb) (struct l2cap_chan *chan, |
559 | unsigned long len, int nb); | 559 | unsigned long len, int nb); |
560 | }; | 560 | }; |
@@ -795,6 +795,19 @@ static inline void l2cap_chan_no_defer(struct l2cap_chan *chan) | |||
795 | { | 795 | { |
796 | } | 796 | } |
797 | 797 | ||
798 | static inline void l2cap_chan_no_resume(struct l2cap_chan *chan) | ||
799 | { | ||
800 | } | ||
801 | |||
802 | static inline void l2cap_chan_no_set_shutdown(struct l2cap_chan *chan) | ||
803 | { | ||
804 | } | ||
805 | |||
806 | static inline long l2cap_chan_no_get_sndtimeo(struct l2cap_chan *chan) | ||
807 | { | ||
808 | return 0; | ||
809 | } | ||
810 | |||
798 | extern bool disable_ertm; | 811 | extern bool disable_ertm; |
799 | 812 | ||
800 | int l2cap_init_sockets(void); | 813 | int l2cap_init_sockets(void); |
@@ -802,7 +815,6 @@ void l2cap_cleanup_sockets(void); | |||
802 | bool l2cap_is_socket(struct socket *sock); | 815 | bool l2cap_is_socket(struct socket *sock); |
803 | 816 | ||
804 | void __l2cap_connect_rsp_defer(struct l2cap_chan *chan); | 817 | void __l2cap_connect_rsp_defer(struct l2cap_chan *chan); |
805 | int __l2cap_wait_ack(struct sock *sk); | ||
806 | 818 | ||
807 | int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm); | 819 | int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm); |
808 | int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid); | 820 | int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid); |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 419202ce3f95..3eae46cb1acf 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -744,6 +744,10 @@ enum station_parameters_apply_mask { | |||
744 | * @capability: station capability | 744 | * @capability: station capability |
745 | * @ext_capab: extended capabilities of the station | 745 | * @ext_capab: extended capabilities of the station |
746 | * @ext_capab_len: number of extended capabilities | 746 | * @ext_capab_len: number of extended capabilities |
747 | * @supported_channels: supported channels in IEEE 802.11 format | ||
748 | * @supported_channels_len: number of supported channels | ||
749 | * @supported_oper_classes: supported oper classes in IEEE 802.11 format | ||
750 | * @supported_oper_classes_len: number of supported operating classes | ||
747 | */ | 751 | */ |
748 | struct station_parameters { | 752 | struct station_parameters { |
749 | const u8 *supported_rates; | 753 | const u8 *supported_rates; |
@@ -763,6 +767,10 @@ struct station_parameters { | |||
763 | u16 capability; | 767 | u16 capability; |
764 | const u8 *ext_capab; | 768 | const u8 *ext_capab; |
765 | u8 ext_capab_len; | 769 | u8 ext_capab_len; |
770 | const u8 *supported_channels; | ||
771 | u8 supported_channels_len; | ||
772 | const u8 *supported_oper_classes; | ||
773 | u8 supported_oper_classes_len; | ||
766 | }; | 774 | }; |
767 | 775 | ||
768 | /** | 776 | /** |
@@ -1656,6 +1664,9 @@ struct cfg80211_disassoc_request { | |||
1656 | * sets/clears %NL80211_STA_FLAG_AUTHORIZED. If true, the driver is | 1664 | * sets/clears %NL80211_STA_FLAG_AUTHORIZED. If true, the driver is |
1657 | * required to assume that the port is unauthorized until authorized by | 1665 | * required to assume that the port is unauthorized until authorized by |
1658 | * user space. Otherwise, port is marked authorized by default. | 1666 | * user space. Otherwise, port is marked authorized by default. |
1667 | * @userspace_handles_dfs: whether user space controls DFS operation, i.e. | ||
1668 | * changes the channel when a radar is detected. This is required | ||
1669 | * to operate on DFS channels. | ||
1659 | * @basic_rates: bitmap of basic rates to use when creating the IBSS | 1670 | * @basic_rates: bitmap of basic rates to use when creating the IBSS |
1660 | * @mcast_rate: per-band multicast rate index + 1 (0: disabled) | 1671 | * @mcast_rate: per-band multicast rate index + 1 (0: disabled) |
1661 | * @ht_capa: HT Capabilities over-rides. Values set in ht_capa_mask | 1672 | * @ht_capa: HT Capabilities over-rides. Values set in ht_capa_mask |
@@ -1673,6 +1684,7 @@ struct cfg80211_ibss_params { | |||
1673 | bool channel_fixed; | 1684 | bool channel_fixed; |
1674 | bool privacy; | 1685 | bool privacy; |
1675 | bool control_port; | 1686 | bool control_port; |
1687 | bool userspace_handles_dfs; | ||
1676 | int mcast_rate[IEEE80211_NUM_BANDS]; | 1688 | int mcast_rate[IEEE80211_NUM_BANDS]; |
1677 | struct ieee80211_ht_cap ht_capa; | 1689 | struct ieee80211_ht_cap ht_capa; |
1678 | struct ieee80211_ht_cap ht_capa_mask; | 1690 | struct ieee80211_ht_cap ht_capa_mask; |
@@ -3053,6 +3065,7 @@ struct cfg80211_cached_keys; | |||
3053 | * @conn: (private) cfg80211 software SME connection state machine data | 3065 | * @conn: (private) cfg80211 software SME connection state machine data |
3054 | * @connect_keys: (private) keys to set after connection is established | 3066 | * @connect_keys: (private) keys to set after connection is established |
3055 | * @ibss_fixed: (private) IBSS is using fixed BSSID | 3067 | * @ibss_fixed: (private) IBSS is using fixed BSSID |
3068 | * @ibss_dfs_possible: (private) IBSS may change to a DFS channel | ||
3056 | * @event_list: (private) list for internal event processing | 3069 | * @event_list: (private) list for internal event processing |
3057 | * @event_lock: (private) lock for event list | 3070 | * @event_lock: (private) lock for event list |
3058 | */ | 3071 | */ |
@@ -3091,6 +3104,7 @@ struct wireless_dev { | |||
3091 | struct ieee80211_channel *channel; | 3104 | struct ieee80211_channel *channel; |
3092 | 3105 | ||
3093 | bool ibss_fixed; | 3106 | bool ibss_fixed; |
3107 | bool ibss_dfs_possible; | ||
3094 | 3108 | ||
3095 | bool ps; | 3109 | bool ps; |
3096 | int ps_timeout; | 3110 | int ps_timeout; |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index f386c480e134..7ceed99a05bc 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -1503,6 +1503,10 @@ struct ieee80211_tx_control { | |||
1503 | * @IEEE80211_HW_TIMING_BEACON_ONLY: Use sync timing from beacon frames | 1503 | * @IEEE80211_HW_TIMING_BEACON_ONLY: Use sync timing from beacon frames |
1504 | * only, to allow getting TBTT of a DTIM beacon. | 1504 | * only, to allow getting TBTT of a DTIM beacon. |
1505 | * | 1505 | * |
1506 | * @IEEE80211_HW_SUPPORTS_HT_CCK_RATES: Hardware supports mixing HT/CCK rates | ||
1507 | * and can cope with CCK rates in an aggregation session (e.g. by not | ||
1508 | * using aggregation for such frames.) | ||
1509 | * | ||
1506 | * @IEEE80211_HW_CHANCTX_STA_CSA: Support 802.11h based channel-switch (CSA) | 1510 | * @IEEE80211_HW_CHANCTX_STA_CSA: Support 802.11h based channel-switch (CSA) |
1507 | * for a single active channel while using channel contexts. When support | 1511 | * for a single active channel while using channel contexts. When support |
1508 | * is not enabled the default action is to disconnect when getting the | 1512 | * is not enabled the default action is to disconnect when getting the |
@@ -4567,4 +4571,18 @@ void ieee80211_report_wowlan_wakeup(struct ieee80211_vif *vif, | |||
4567 | struct cfg80211_wowlan_wakeup *wakeup, | 4571 | struct cfg80211_wowlan_wakeup *wakeup, |
4568 | gfp_t gfp); | 4572 | gfp_t gfp); |
4569 | 4573 | ||
4574 | /** | ||
4575 | * ieee80211_tx_prepare_skb - prepare an 802.11 skb for transmission | ||
4576 | * @hw: pointer as obtained from ieee80211_alloc_hw() | ||
4577 | * @vif: virtual interface | ||
4578 | * @skb: frame to be sent from within the driver | ||
4579 | * @band: the band to transmit on | ||
4580 | * @sta: optional pointer to get the station to send the frame to | ||
4581 | * | ||
4582 | * Note: must be called under RCU lock | ||
4583 | */ | ||
4584 | bool ieee80211_tx_prepare_skb(struct ieee80211_hw *hw, | ||
4585 | struct ieee80211_vif *vif, struct sk_buff *skb, | ||
4586 | int band, struct ieee80211_sta **sta); | ||
4587 | |||
4570 | #endif /* MAC80211_H */ | 4588 | #endif /* MAC80211_H */ |
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index fde2c021b26d..f752e9821e71 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h | |||
@@ -988,7 +988,7 @@ enum nl80211_commands { | |||
988 | * to query the CRDA to retrieve one regulatory domain. This attribute can | 988 | * to query the CRDA to retrieve one regulatory domain. This attribute can |
989 | * also be used by userspace to query the kernel for the currently set | 989 | * also be used by userspace to query the kernel for the currently set |
990 | * regulatory domain. We chose an alpha2 as that is also used by the | 990 | * regulatory domain. We chose an alpha2 as that is also used by the |
991 | * IEEE-802.11d country information element to identify a country. | 991 | * IEEE-802.11 country information element to identify a country. |
992 | * Users can also simply ask the wireless core to set regulatory domain | 992 | * Users can also simply ask the wireless core to set regulatory domain |
993 | * to a specific alpha2. | 993 | * to a specific alpha2. |
994 | * @NL80211_ATTR_REG_RULES: a nested array of regulatory domain regulatory | 994 | * @NL80211_ATTR_REG_RULES: a nested array of regulatory domain regulatory |
@@ -1496,6 +1496,18 @@ enum nl80211_commands { | |||
1496 | * @NL80211_ATTR_RXMGMT_FLAGS: flags for nl80211_send_mgmt(), u32. | 1496 | * @NL80211_ATTR_RXMGMT_FLAGS: flags for nl80211_send_mgmt(), u32. |
1497 | * As specified in the &enum nl80211_rxmgmt_flags. | 1497 | * As specified in the &enum nl80211_rxmgmt_flags. |
1498 | * | 1498 | * |
1499 | * @NL80211_ATTR_STA_SUPPORTED_CHANNELS: array of supported channels. | ||
1500 | * | ||
1501 | * @NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES: array of supported | ||
1502 | * supported operating classes. | ||
1503 | * | ||
1504 | * @NL80211_ATTR_HANDLE_DFS: A flag indicating whether user space | ||
1505 | * controls DFS operation in IBSS mode. If the flag is included in | ||
1506 | * %NL80211_CMD_JOIN_IBSS request, the driver will allow use of DFS | ||
1507 | * channels and reports radar events to userspace. Userspace is required | ||
1508 | * to react to radar events, e.g. initiate a channel switch or leave the | ||
1509 | * IBSS network. | ||
1510 | * | ||
1499 | * @NL80211_ATTR_MAX: highest attribute number currently defined | 1511 | * @NL80211_ATTR_MAX: highest attribute number currently defined |
1500 | * @__NL80211_ATTR_AFTER_LAST: internal use | 1512 | * @__NL80211_ATTR_AFTER_LAST: internal use |
1501 | */ | 1513 | */ |
@@ -1806,6 +1818,12 @@ enum nl80211_attrs { | |||
1806 | 1818 | ||
1807 | NL80211_ATTR_RXMGMT_FLAGS, | 1819 | NL80211_ATTR_RXMGMT_FLAGS, |
1808 | 1820 | ||
1821 | NL80211_ATTR_STA_SUPPORTED_CHANNELS, | ||
1822 | |||
1823 | NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES, | ||
1824 | |||
1825 | NL80211_ATTR_HANDLE_DFS, | ||
1826 | |||
1809 | /* add attributes here, update the policy in nl80211.c */ | 1827 | /* add attributes here, update the policy in nl80211.c */ |
1810 | 1828 | ||
1811 | __NL80211_ATTR_AFTER_LAST, | 1829 | __NL80211_ATTR_AFTER_LAST, |
@@ -3860,13 +3878,12 @@ enum nl80211_radar_event { | |||
3860 | * | 3878 | * |
3861 | * Channel states used by the DFS code. | 3879 | * Channel states used by the DFS code. |
3862 | * | 3880 | * |
3863 | * @IEEE80211_DFS_USABLE: The channel can be used, but channel availability | 3881 | * @NL80211_DFS_USABLE: The channel can be used, but channel availability |
3864 | * check (CAC) must be performed before using it for AP or IBSS. | 3882 | * check (CAC) must be performed before using it for AP or IBSS. |
3865 | * @IEEE80211_DFS_UNAVAILABLE: A radar has been detected on this channel, it | 3883 | * @NL80211_DFS_UNAVAILABLE: A radar has been detected on this channel, it |
3866 | * is therefore marked as not available. | 3884 | * is therefore marked as not available. |
3867 | * @IEEE80211_DFS_AVAILABLE: The channel has been CAC checked and is available. | 3885 | * @NL80211_DFS_AVAILABLE: The channel has been CAC checked and is available. |
3868 | */ | 3886 | */ |
3869 | |||
3870 | enum nl80211_dfs_state { | 3887 | enum nl80211_dfs_state { |
3871 | NL80211_DFS_USABLE, | 3888 | NL80211_DFS_USABLE, |
3872 | NL80211_DFS_UNAVAILABLE, | 3889 | NL80211_DFS_UNAVAILABLE, |
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index 60ca52819247..efcd108822c4 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c | |||
@@ -672,7 +672,8 @@ static void a2mp_chan_close_cb(struct l2cap_chan *chan) | |||
672 | l2cap_chan_put(chan); | 672 | l2cap_chan_put(chan); |
673 | } | 673 | } |
674 | 674 | ||
675 | static void a2mp_chan_state_change_cb(struct l2cap_chan *chan, int state) | 675 | static void a2mp_chan_state_change_cb(struct l2cap_chan *chan, int state, |
676 | int err) | ||
676 | { | 677 | { |
677 | struct amp_mgr *mgr = chan->data; | 678 | struct amp_mgr *mgr = chan->data; |
678 | 679 | ||
@@ -709,6 +710,9 @@ static struct l2cap_ops a2mp_chan_ops = { | |||
709 | .teardown = l2cap_chan_no_teardown, | 710 | .teardown = l2cap_chan_no_teardown, |
710 | .ready = l2cap_chan_no_ready, | 711 | .ready = l2cap_chan_no_ready, |
711 | .defer = l2cap_chan_no_defer, | 712 | .defer = l2cap_chan_no_defer, |
713 | .resume = l2cap_chan_no_resume, | ||
714 | .set_shutdown = l2cap_chan_no_set_shutdown, | ||
715 | .get_sndtimeo = l2cap_chan_no_get_sndtimeo, | ||
712 | }; | 716 | }; |
713 | 717 | ||
714 | static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked) | 718 | static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked) |
@@ -832,6 +836,9 @@ struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn, | |||
832 | { | 836 | { |
833 | struct amp_mgr *mgr; | 837 | struct amp_mgr *mgr; |
834 | 838 | ||
839 | if (conn->hcon->type != ACL_LINK) | ||
840 | return NULL; | ||
841 | |||
835 | mgr = amp_mgr_create(conn, false); | 842 | mgr = amp_mgr_create(conn, false); |
836 | if (!mgr) { | 843 | if (!mgr) { |
837 | BT_ERR("Could not create AMP manager"); | 844 | BT_ERR("Could not create AMP manager"); |
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 1f1a1118f489..f6a1671ea2ff 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c | |||
@@ -25,6 +25,7 @@ | |||
25 | /* Bluetooth address family and sockets. */ | 25 | /* Bluetooth address family and sockets. */ |
26 | 26 | ||
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/debugfs.h> | ||
28 | #include <asm/ioctls.h> | 29 | #include <asm/ioctls.h> |
29 | 30 | ||
30 | #include <net/bluetooth/bluetooth.h> | 31 | #include <net/bluetooth/bluetooth.h> |
@@ -708,12 +709,17 @@ static struct net_proto_family bt_sock_family_ops = { | |||
708 | .create = bt_sock_create, | 709 | .create = bt_sock_create, |
709 | }; | 710 | }; |
710 | 711 | ||
712 | struct dentry *bt_debugfs; | ||
713 | EXPORT_SYMBOL_GPL(bt_debugfs); | ||
714 | |||
711 | static int __init bt_init(void) | 715 | static int __init bt_init(void) |
712 | { | 716 | { |
713 | int err; | 717 | int err; |
714 | 718 | ||
715 | BT_INFO("Core ver %s", VERSION); | 719 | BT_INFO("Core ver %s", VERSION); |
716 | 720 | ||
721 | bt_debugfs = debugfs_create_dir("bluetooth", NULL); | ||
722 | |||
717 | err = bt_sysfs_init(); | 723 | err = bt_sysfs_init(); |
718 | if (err < 0) | 724 | if (err < 0) |
719 | return err; | 725 | return err; |
@@ -754,7 +760,6 @@ error: | |||
754 | 760 | ||
755 | static void __exit bt_exit(void) | 761 | static void __exit bt_exit(void) |
756 | { | 762 | { |
757 | |||
758 | sco_exit(); | 763 | sco_exit(); |
759 | 764 | ||
760 | l2cap_exit(); | 765 | l2cap_exit(); |
@@ -764,6 +769,8 @@ static void __exit bt_exit(void) | |||
764 | sock_unregister(PF_BLUETOOTH); | 769 | sock_unregister(PF_BLUETOOTH); |
765 | 770 | ||
766 | bt_sysfs_cleanup(); | 771 | bt_sysfs_cleanup(); |
772 | |||
773 | debugfs_remove_recursive(bt_debugfs); | ||
767 | } | 774 | } |
768 | 775 | ||
769 | subsys_initcall(bt_init); | 776 | subsys_initcall(bt_init); |
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index ff04b051792d..ba5366c320da 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -317,8 +317,10 @@ static void hci_conn_timeout(struct work_struct *work) | |||
317 | } | 317 | } |
318 | 318 | ||
319 | /* Enter sniff mode */ | 319 | /* Enter sniff mode */ |
320 | static void hci_conn_enter_sniff_mode(struct hci_conn *conn) | 320 | static void hci_conn_idle(struct work_struct *work) |
321 | { | 321 | { |
322 | struct hci_conn *conn = container_of(work, struct hci_conn, | ||
323 | idle_work.work); | ||
322 | struct hci_dev *hdev = conn->hdev; | 324 | struct hci_dev *hdev = conn->hdev; |
323 | 325 | ||
324 | BT_DBG("hcon %p mode %d", conn, conn->mode); | 326 | BT_DBG("hcon %p mode %d", conn, conn->mode); |
@@ -352,21 +354,12 @@ static void hci_conn_enter_sniff_mode(struct hci_conn *conn) | |||
352 | } | 354 | } |
353 | } | 355 | } |
354 | 356 | ||
355 | static void hci_conn_idle(unsigned long arg) | 357 | static void hci_conn_auto_accept(struct work_struct *work) |
356 | { | ||
357 | struct hci_conn *conn = (void *) arg; | ||
358 | |||
359 | BT_DBG("hcon %p mode %d", conn, conn->mode); | ||
360 | |||
361 | hci_conn_enter_sniff_mode(conn); | ||
362 | } | ||
363 | |||
364 | static void hci_conn_auto_accept(unsigned long arg) | ||
365 | { | 358 | { |
366 | struct hci_conn *conn = (void *) arg; | 359 | struct hci_conn *conn = container_of(work, struct hci_conn, |
367 | struct hci_dev *hdev = conn->hdev; | 360 | auto_accept_work.work); |
368 | 361 | ||
369 | hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, sizeof(conn->dst), | 362 | hci_send_cmd(conn->hdev, HCI_OP_USER_CONFIRM_REPLY, sizeof(conn->dst), |
370 | &conn->dst); | 363 | &conn->dst); |
371 | } | 364 | } |
372 | 365 | ||
@@ -415,9 +408,8 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) | |||
415 | INIT_LIST_HEAD(&conn->chan_list); | 408 | INIT_LIST_HEAD(&conn->chan_list); |
416 | 409 | ||
417 | INIT_DELAYED_WORK(&conn->disc_work, hci_conn_timeout); | 410 | INIT_DELAYED_WORK(&conn->disc_work, hci_conn_timeout); |
418 | setup_timer(&conn->idle_timer, hci_conn_idle, (unsigned long)conn); | 411 | INIT_DELAYED_WORK(&conn->auto_accept_work, hci_conn_auto_accept); |
419 | setup_timer(&conn->auto_accept_timer, hci_conn_auto_accept, | 412 | INIT_DELAYED_WORK(&conn->idle_work, hci_conn_idle); |
420 | (unsigned long) conn); | ||
421 | 413 | ||
422 | atomic_set(&conn->refcnt, 0); | 414 | atomic_set(&conn->refcnt, 0); |
423 | 415 | ||
@@ -438,11 +430,9 @@ int hci_conn_del(struct hci_conn *conn) | |||
438 | 430 | ||
439 | BT_DBG("%s hcon %p handle %d", hdev->name, conn, conn->handle); | 431 | BT_DBG("%s hcon %p handle %d", hdev->name, conn, conn->handle); |
440 | 432 | ||
441 | del_timer(&conn->idle_timer); | ||
442 | |||
443 | cancel_delayed_work_sync(&conn->disc_work); | 433 | cancel_delayed_work_sync(&conn->disc_work); |
444 | 434 | cancel_delayed_work_sync(&conn->auto_accept_work); | |
445 | del_timer(&conn->auto_accept_timer); | 435 | cancel_delayed_work_sync(&conn->idle_work); |
446 | 436 | ||
447 | if (conn->type == ACL_LINK) { | 437 | if (conn->type == ACL_LINK) { |
448 | struct hci_conn *sco = conn->link; | 438 | struct hci_conn *sco = conn->link; |
@@ -568,11 +558,12 @@ static int hci_create_le_conn(struct hci_conn *conn) | |||
568 | bacpy(&cp.peer_addr, &conn->dst); | 558 | bacpy(&cp.peer_addr, &conn->dst); |
569 | cp.peer_addr_type = conn->dst_type; | 559 | cp.peer_addr_type = conn->dst_type; |
570 | cp.own_address_type = conn->src_type; | 560 | cp.own_address_type = conn->src_type; |
571 | cp.conn_interval_min = __constant_cpu_to_le16(0x0028); | 561 | cp.conn_interval_min = cpu_to_le16(hdev->le_conn_min_interval); |
572 | cp.conn_interval_max = __constant_cpu_to_le16(0x0038); | 562 | cp.conn_interval_max = cpu_to_le16(hdev->le_conn_max_interval); |
573 | cp.supervision_timeout = __constant_cpu_to_le16(0x002a); | 563 | cp.supervision_timeout = __constant_cpu_to_le16(0x002a); |
574 | cp.min_ce_len = __constant_cpu_to_le16(0x0000); | 564 | cp.min_ce_len = __constant_cpu_to_le16(0x0000); |
575 | cp.max_ce_len = __constant_cpu_to_le16(0x0000); | 565 | cp.max_ce_len = __constant_cpu_to_le16(0x0000); |
566 | |||
576 | hci_req_add(&req, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp); | 567 | hci_req_add(&req, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp); |
577 | 568 | ||
578 | err = hci_req_run(&req, create_le_conn_complete); | 569 | err = hci_req_run(&req, create_le_conn_complete); |
@@ -625,12 +616,7 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, | |||
625 | else | 616 | else |
626 | conn->dst_type = ADDR_LE_DEV_RANDOM; | 617 | conn->dst_type = ADDR_LE_DEV_RANDOM; |
627 | 618 | ||
628 | if (bacmp(&conn->src, BDADDR_ANY)) { | 619 | conn->src_type = hdev->own_addr_type; |
629 | conn->src_type = ADDR_LE_DEV_PUBLIC; | ||
630 | } else { | ||
631 | bacpy(&conn->src, &hdev->static_addr); | ||
632 | conn->src_type = ADDR_LE_DEV_RANDOM; | ||
633 | } | ||
634 | 620 | ||
635 | conn->state = BT_CONNECT; | 621 | conn->state = BT_CONNECT; |
636 | conn->out = true; | 622 | conn->out = true; |
@@ -922,8 +908,8 @@ void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active) | |||
922 | 908 | ||
923 | timer: | 909 | timer: |
924 | if (hdev->idle_timeout > 0) | 910 | if (hdev->idle_timeout > 0) |
925 | mod_timer(&conn->idle_timer, | 911 | queue_delayed_work(hdev->workqueue, &conn->idle_work, |
926 | jiffies + msecs_to_jiffies(hdev->idle_timeout)); | 912 | msecs_to_jiffies(hdev->idle_timeout)); |
927 | } | 913 | } |
928 | 914 | ||
929 | /* Drop all connection on the device */ | 915 | /* Drop all connection on the device */ |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 7add9c96e32c..6ccc4eb9e55e 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -27,8 +27,9 @@ | |||
27 | 27 | ||
28 | #include <linux/export.h> | 28 | #include <linux/export.h> |
29 | #include <linux/idr.h> | 29 | #include <linux/idr.h> |
30 | |||
31 | #include <linux/rfkill.h> | 30 | #include <linux/rfkill.h> |
31 | #include <linux/debugfs.h> | ||
32 | #include <asm/unaligned.h> | ||
32 | 33 | ||
33 | #include <net/bluetooth/bluetooth.h> | 34 | #include <net/bluetooth/bluetooth.h> |
34 | #include <net/bluetooth/hci_core.h> | 35 | #include <net/bluetooth/hci_core.h> |
@@ -55,6 +56,586 @@ static void hci_notify(struct hci_dev *hdev, int event) | |||
55 | hci_sock_dev_event(hdev, event); | 56 | hci_sock_dev_event(hdev, event); |
56 | } | 57 | } |
57 | 58 | ||
59 | /* ---- HCI debugfs entries ---- */ | ||
60 | |||
61 | static ssize_t dut_mode_read(struct file *file, char __user *user_buf, | ||
62 | size_t count, loff_t *ppos) | ||
63 | { | ||
64 | struct hci_dev *hdev = file->private_data; | ||
65 | char buf[3]; | ||
66 | |||
67 | buf[0] = test_bit(HCI_DUT_MODE, &hdev->dev_flags) ? 'Y': 'N'; | ||
68 | buf[1] = '\n'; | ||
69 | buf[2] = '\0'; | ||
70 | return simple_read_from_buffer(user_buf, count, ppos, buf, 2); | ||
71 | } | ||
72 | |||
73 | static ssize_t dut_mode_write(struct file *file, const char __user *user_buf, | ||
74 | size_t count, loff_t *ppos) | ||
75 | { | ||
76 | struct hci_dev *hdev = file->private_data; | ||
77 | struct sk_buff *skb; | ||
78 | char buf[32]; | ||
79 | size_t buf_size = min(count, (sizeof(buf)-1)); | ||
80 | bool enable; | ||
81 | int err; | ||
82 | |||
83 | if (!test_bit(HCI_UP, &hdev->flags)) | ||
84 | return -ENETDOWN; | ||
85 | |||
86 | if (copy_from_user(buf, user_buf, buf_size)) | ||
87 | return -EFAULT; | ||
88 | |||
89 | buf[buf_size] = '\0'; | ||
90 | if (strtobool(buf, &enable)) | ||
91 | return -EINVAL; | ||
92 | |||
93 | if (enable == test_bit(HCI_DUT_MODE, &hdev->dev_flags)) | ||
94 | return -EALREADY; | ||
95 | |||
96 | hci_req_lock(hdev); | ||
97 | if (enable) | ||
98 | skb = __hci_cmd_sync(hdev, HCI_OP_ENABLE_DUT_MODE, 0, NULL, | ||
99 | HCI_CMD_TIMEOUT); | ||
100 | else | ||
101 | skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, | ||
102 | HCI_CMD_TIMEOUT); | ||
103 | hci_req_unlock(hdev); | ||
104 | |||
105 | if (IS_ERR(skb)) | ||
106 | return PTR_ERR(skb); | ||
107 | |||
108 | err = -bt_to_errno(skb->data[0]); | ||
109 | kfree_skb(skb); | ||
110 | |||
111 | if (err < 0) | ||
112 | return err; | ||
113 | |||
114 | change_bit(HCI_DUT_MODE, &hdev->dev_flags); | ||
115 | |||
116 | return count; | ||
117 | } | ||
118 | |||
119 | static const struct file_operations dut_mode_fops = { | ||
120 | .open = simple_open, | ||
121 | .read = dut_mode_read, | ||
122 | .write = dut_mode_write, | ||
123 | .llseek = default_llseek, | ||
124 | }; | ||
125 | |||
126 | static int features_show(struct seq_file *f, void *ptr) | ||
127 | { | ||
128 | struct hci_dev *hdev = f->private; | ||
129 | u8 p; | ||
130 | |||
131 | hci_dev_lock(hdev); | ||
132 | for (p = 0; p < HCI_MAX_PAGES && p <= hdev->max_page; p++) { | ||
133 | seq_printf(f, "%2u: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x " | ||
134 | "0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n", p, | ||
135 | hdev->features[p][0], hdev->features[p][1], | ||
136 | hdev->features[p][2], hdev->features[p][3], | ||
137 | hdev->features[p][4], hdev->features[p][5], | ||
138 | hdev->features[p][6], hdev->features[p][7]); | ||
139 | } | ||
140 | if (lmp_le_capable(hdev)) | ||
141 | seq_printf(f, "LE: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x " | ||
142 | "0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n", | ||
143 | hdev->le_features[0], hdev->le_features[1], | ||
144 | hdev->le_features[2], hdev->le_features[3], | ||
145 | hdev->le_features[4], hdev->le_features[5], | ||
146 | hdev->le_features[6], hdev->le_features[7]); | ||
147 | hci_dev_unlock(hdev); | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | static int features_open(struct inode *inode, struct file *file) | ||
153 | { | ||
154 | return single_open(file, features_show, inode->i_private); | ||
155 | } | ||
156 | |||
157 | static const struct file_operations features_fops = { | ||
158 | .open = features_open, | ||
159 | .read = seq_read, | ||
160 | .llseek = seq_lseek, | ||
161 | .release = single_release, | ||
162 | }; | ||
163 | |||
164 | static int blacklist_show(struct seq_file *f, void *p) | ||
165 | { | ||
166 | struct hci_dev *hdev = f->private; | ||
167 | struct bdaddr_list *b; | ||
168 | |||
169 | hci_dev_lock(hdev); | ||
170 | list_for_each_entry(b, &hdev->blacklist, list) | ||
171 | seq_printf(f, "%pMR (type %u)\n", &b->bdaddr, b->bdaddr_type); | ||
172 | hci_dev_unlock(hdev); | ||
173 | |||
174 | return 0; | ||
175 | } | ||
176 | |||
177 | static int blacklist_open(struct inode *inode, struct file *file) | ||
178 | { | ||
179 | return single_open(file, blacklist_show, inode->i_private); | ||
180 | } | ||
181 | |||
182 | static const struct file_operations blacklist_fops = { | ||
183 | .open = blacklist_open, | ||
184 | .read = seq_read, | ||
185 | .llseek = seq_lseek, | ||
186 | .release = single_release, | ||
187 | }; | ||
188 | |||
189 | static int uuids_show(struct seq_file *f, void *p) | ||
190 | { | ||
191 | struct hci_dev *hdev = f->private; | ||
192 | struct bt_uuid *uuid; | ||
193 | |||
194 | hci_dev_lock(hdev); | ||
195 | list_for_each_entry(uuid, &hdev->uuids, list) { | ||
196 | u8 i, val[16]; | ||
197 | |||
198 | /* The Bluetooth UUID values are stored in big endian, | ||
199 | * but with reversed byte order. So convert them into | ||
200 | * the right order for the %pUb modifier. | ||
201 | */ | ||
202 | for (i = 0; i < 16; i++) | ||
203 | val[i] = uuid->uuid[15 - i]; | ||
204 | |||
205 | seq_printf(f, "%pUb\n", val); | ||
206 | } | ||
207 | hci_dev_unlock(hdev); | ||
208 | |||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | static int uuids_open(struct inode *inode, struct file *file) | ||
213 | { | ||
214 | return single_open(file, uuids_show, inode->i_private); | ||
215 | } | ||
216 | |||
217 | static const struct file_operations uuids_fops = { | ||
218 | .open = uuids_open, | ||
219 | .read = seq_read, | ||
220 | .llseek = seq_lseek, | ||
221 | .release = single_release, | ||
222 | }; | ||
223 | |||
224 | static int inquiry_cache_show(struct seq_file *f, void *p) | ||
225 | { | ||
226 | struct hci_dev *hdev = f->private; | ||
227 | struct discovery_state *cache = &hdev->discovery; | ||
228 | struct inquiry_entry *e; | ||
229 | |||
230 | hci_dev_lock(hdev); | ||
231 | |||
232 | list_for_each_entry(e, &cache->all, all) { | ||
233 | struct inquiry_data *data = &e->data; | ||
234 | seq_printf(f, "%pMR %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n", | ||
235 | &data->bdaddr, | ||
236 | data->pscan_rep_mode, data->pscan_period_mode, | ||
237 | data->pscan_mode, data->dev_class[2], | ||
238 | data->dev_class[1], data->dev_class[0], | ||
239 | __le16_to_cpu(data->clock_offset), | ||
240 | data->rssi, data->ssp_mode, e->timestamp); | ||
241 | } | ||
242 | |||
243 | hci_dev_unlock(hdev); | ||
244 | |||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | static int inquiry_cache_open(struct inode *inode, struct file *file) | ||
249 | { | ||
250 | return single_open(file, inquiry_cache_show, inode->i_private); | ||
251 | } | ||
252 | |||
253 | static const struct file_operations inquiry_cache_fops = { | ||
254 | .open = inquiry_cache_open, | ||
255 | .read = seq_read, | ||
256 | .llseek = seq_lseek, | ||
257 | .release = single_release, | ||
258 | }; | ||
259 | |||
260 | static int link_keys_show(struct seq_file *f, void *ptr) | ||
261 | { | ||
262 | struct hci_dev *hdev = f->private; | ||
263 | struct list_head *p, *n; | ||
264 | |||
265 | hci_dev_lock(hdev); | ||
266 | list_for_each_safe(p, n, &hdev->link_keys) { | ||
267 | struct link_key *key = list_entry(p, struct link_key, list); | ||
268 | seq_printf(f, "%pMR %u %*phN %u\n", &key->bdaddr, key->type, | ||
269 | HCI_LINK_KEY_SIZE, key->val, key->pin_len); | ||
270 | } | ||
271 | hci_dev_unlock(hdev); | ||
272 | |||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | static int link_keys_open(struct inode *inode, struct file *file) | ||
277 | { | ||
278 | return single_open(file, link_keys_show, inode->i_private); | ||
279 | } | ||
280 | |||
281 | static const struct file_operations link_keys_fops = { | ||
282 | .open = link_keys_open, | ||
283 | .read = seq_read, | ||
284 | .llseek = seq_lseek, | ||
285 | .release = single_release, | ||
286 | }; | ||
287 | |||
288 | static ssize_t use_debug_keys_read(struct file *file, char __user *user_buf, | ||
289 | size_t count, loff_t *ppos) | ||
290 | { | ||
291 | struct hci_dev *hdev = file->private_data; | ||
292 | char buf[3]; | ||
293 | |||
294 | buf[0] = test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) ? 'Y': 'N'; | ||
295 | buf[1] = '\n'; | ||
296 | buf[2] = '\0'; | ||
297 | return simple_read_from_buffer(user_buf, count, ppos, buf, 2); | ||
298 | } | ||
299 | |||
300 | static const struct file_operations use_debug_keys_fops = { | ||
301 | .open = simple_open, | ||
302 | .read = use_debug_keys_read, | ||
303 | .llseek = default_llseek, | ||
304 | }; | ||
305 | |||
306 | static int dev_class_show(struct seq_file *f, void *ptr) | ||
307 | { | ||
308 | struct hci_dev *hdev = f->private; | ||
309 | |||
310 | hci_dev_lock(hdev); | ||
311 | seq_printf(f, "0x%.2x%.2x%.2x\n", hdev->dev_class[2], | ||
312 | hdev->dev_class[1], hdev->dev_class[0]); | ||
313 | hci_dev_unlock(hdev); | ||
314 | |||
315 | return 0; | ||
316 | } | ||
317 | |||
318 | static int dev_class_open(struct inode *inode, struct file *file) | ||
319 | { | ||
320 | return single_open(file, dev_class_show, inode->i_private); | ||
321 | } | ||
322 | |||
323 | static const struct file_operations dev_class_fops = { | ||
324 | .open = dev_class_open, | ||
325 | .read = seq_read, | ||
326 | .llseek = seq_lseek, | ||
327 | .release = single_release, | ||
328 | }; | ||
329 | |||
330 | static int voice_setting_get(void *data, u64 *val) | ||
331 | { | ||
332 | struct hci_dev *hdev = data; | ||
333 | |||
334 | hci_dev_lock(hdev); | ||
335 | *val = hdev->voice_setting; | ||
336 | hci_dev_unlock(hdev); | ||
337 | |||
338 | return 0; | ||
339 | } | ||
340 | |||
341 | DEFINE_SIMPLE_ATTRIBUTE(voice_setting_fops, voice_setting_get, | ||
342 | NULL, "0x%4.4llx\n"); | ||
343 | |||
344 | static int auto_accept_delay_set(void *data, u64 val) | ||
345 | { | ||
346 | struct hci_dev *hdev = data; | ||
347 | |||
348 | hci_dev_lock(hdev); | ||
349 | hdev->auto_accept_delay = val; | ||
350 | hci_dev_unlock(hdev); | ||
351 | |||
352 | return 0; | ||
353 | } | ||
354 | |||
355 | static int auto_accept_delay_get(void *data, u64 *val) | ||
356 | { | ||
357 | struct hci_dev *hdev = data; | ||
358 | |||
359 | hci_dev_lock(hdev); | ||
360 | *val = hdev->auto_accept_delay; | ||
361 | hci_dev_unlock(hdev); | ||
362 | |||
363 | return 0; | ||
364 | } | ||
365 | |||
366 | DEFINE_SIMPLE_ATTRIBUTE(auto_accept_delay_fops, auto_accept_delay_get, | ||
367 | auto_accept_delay_set, "%llu\n"); | ||
368 | |||
369 | static int ssp_debug_mode_set(void *data, u64 val) | ||
370 | { | ||
371 | struct hci_dev *hdev = data; | ||
372 | struct sk_buff *skb; | ||
373 | __u8 mode; | ||
374 | int err; | ||
375 | |||
376 | if (val != 0 && val != 1) | ||
377 | return -EINVAL; | ||
378 | |||
379 | if (!test_bit(HCI_UP, &hdev->flags)) | ||
380 | return -ENETDOWN; | ||
381 | |||
382 | hci_req_lock(hdev); | ||
383 | mode = val; | ||
384 | skb = __hci_cmd_sync(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE, sizeof(mode), | ||
385 | &mode, HCI_CMD_TIMEOUT); | ||
386 | hci_req_unlock(hdev); | ||
387 | |||
388 | if (IS_ERR(skb)) | ||
389 | return PTR_ERR(skb); | ||
390 | |||
391 | err = -bt_to_errno(skb->data[0]); | ||
392 | kfree_skb(skb); | ||
393 | |||
394 | if (err < 0) | ||
395 | return err; | ||
396 | |||
397 | hci_dev_lock(hdev); | ||
398 | hdev->ssp_debug_mode = val; | ||
399 | hci_dev_unlock(hdev); | ||
400 | |||
401 | return 0; | ||
402 | } | ||
403 | |||
404 | static int ssp_debug_mode_get(void *data, u64 *val) | ||
405 | { | ||
406 | struct hci_dev *hdev = data; | ||
407 | |||
408 | hci_dev_lock(hdev); | ||
409 | *val = hdev->ssp_debug_mode; | ||
410 | hci_dev_unlock(hdev); | ||
411 | |||
412 | return 0; | ||
413 | } | ||
414 | |||
415 | DEFINE_SIMPLE_ATTRIBUTE(ssp_debug_mode_fops, ssp_debug_mode_get, | ||
416 | ssp_debug_mode_set, "%llu\n"); | ||
417 | |||
418 | static int idle_timeout_set(void *data, u64 val) | ||
419 | { | ||
420 | struct hci_dev *hdev = data; | ||
421 | |||
422 | if (val != 0 && (val < 500 || val > 3600000)) | ||
423 | return -EINVAL; | ||
424 | |||
425 | hci_dev_lock(hdev); | ||
426 | hdev->idle_timeout = val; | ||
427 | hci_dev_unlock(hdev); | ||
428 | |||
429 | return 0; | ||
430 | } | ||
431 | |||
432 | static int idle_timeout_get(void *data, u64 *val) | ||
433 | { | ||
434 | struct hci_dev *hdev = data; | ||
435 | |||
436 | hci_dev_lock(hdev); | ||
437 | *val = hdev->idle_timeout; | ||
438 | hci_dev_unlock(hdev); | ||
439 | |||
440 | return 0; | ||
441 | } | ||
442 | |||
443 | DEFINE_SIMPLE_ATTRIBUTE(idle_timeout_fops, idle_timeout_get, | ||
444 | idle_timeout_set, "%llu\n"); | ||
445 | |||
446 | static int sniff_min_interval_set(void *data, u64 val) | ||
447 | { | ||
448 | struct hci_dev *hdev = data; | ||
449 | |||
450 | if (val == 0 || val % 2 || val > hdev->sniff_max_interval) | ||
451 | return -EINVAL; | ||
452 | |||
453 | hci_dev_lock(hdev); | ||
454 | hdev->sniff_min_interval = val; | ||
455 | hci_dev_unlock(hdev); | ||
456 | |||
457 | return 0; | ||
458 | } | ||
459 | |||
460 | static int sniff_min_interval_get(void *data, u64 *val) | ||
461 | { | ||
462 | struct hci_dev *hdev = data; | ||
463 | |||
464 | hci_dev_lock(hdev); | ||
465 | *val = hdev->sniff_min_interval; | ||
466 | hci_dev_unlock(hdev); | ||
467 | |||
468 | return 0; | ||
469 | } | ||
470 | |||
471 | DEFINE_SIMPLE_ATTRIBUTE(sniff_min_interval_fops, sniff_min_interval_get, | ||
472 | sniff_min_interval_set, "%llu\n"); | ||
473 | |||
474 | static int sniff_max_interval_set(void *data, u64 val) | ||
475 | { | ||
476 | struct hci_dev *hdev = data; | ||
477 | |||
478 | if (val == 0 || val % 2 || val < hdev->sniff_min_interval) | ||
479 | return -EINVAL; | ||
480 | |||
481 | hci_dev_lock(hdev); | ||
482 | hdev->sniff_max_interval = val; | ||
483 | hci_dev_unlock(hdev); | ||
484 | |||
485 | return 0; | ||
486 | } | ||
487 | |||
488 | static int sniff_max_interval_get(void *data, u64 *val) | ||
489 | { | ||
490 | struct hci_dev *hdev = data; | ||
491 | |||
492 | hci_dev_lock(hdev); | ||
493 | *val = hdev->sniff_max_interval; | ||
494 | hci_dev_unlock(hdev); | ||
495 | |||
496 | return 0; | ||
497 | } | ||
498 | |||
499 | DEFINE_SIMPLE_ATTRIBUTE(sniff_max_interval_fops, sniff_max_interval_get, | ||
500 | sniff_max_interval_set, "%llu\n"); | ||
501 | |||
502 | static int static_address_show(struct seq_file *f, void *p) | ||
503 | { | ||
504 | struct hci_dev *hdev = f->private; | ||
505 | |||
506 | hci_dev_lock(hdev); | ||
507 | seq_printf(f, "%pMR\n", &hdev->static_addr); | ||
508 | hci_dev_unlock(hdev); | ||
509 | |||
510 | return 0; | ||
511 | } | ||
512 | |||
513 | static int static_address_open(struct inode *inode, struct file *file) | ||
514 | { | ||
515 | return single_open(file, static_address_show, inode->i_private); | ||
516 | } | ||
517 | |||
518 | static const struct file_operations static_address_fops = { | ||
519 | .open = static_address_open, | ||
520 | .read = seq_read, | ||
521 | .llseek = seq_lseek, | ||
522 | .release = single_release, | ||
523 | }; | ||
524 | |||
525 | static int own_address_type_set(void *data, u64 val) | ||
526 | { | ||
527 | struct hci_dev *hdev = data; | ||
528 | |||
529 | if (val != 0 && val != 1) | ||
530 | return -EINVAL; | ||
531 | |||
532 | hci_dev_lock(hdev); | ||
533 | hdev->own_addr_type = val; | ||
534 | hci_dev_unlock(hdev); | ||
535 | |||
536 | return 0; | ||
537 | } | ||
538 | |||
539 | static int own_address_type_get(void *data, u64 *val) | ||
540 | { | ||
541 | struct hci_dev *hdev = data; | ||
542 | |||
543 | hci_dev_lock(hdev); | ||
544 | *val = hdev->own_addr_type; | ||
545 | hci_dev_unlock(hdev); | ||
546 | |||
547 | return 0; | ||
548 | } | ||
549 | |||
550 | DEFINE_SIMPLE_ATTRIBUTE(own_address_type_fops, own_address_type_get, | ||
551 | own_address_type_set, "%llu\n"); | ||
552 | |||
553 | static int long_term_keys_show(struct seq_file *f, void *ptr) | ||
554 | { | ||
555 | struct hci_dev *hdev = f->private; | ||
556 | struct list_head *p, *n; | ||
557 | |||
558 | hci_dev_lock(hdev); | ||
559 | list_for_each_safe(p, n, &hdev->link_keys) { | ||
560 | struct smp_ltk *ltk = list_entry(p, struct smp_ltk, list); | ||
561 | seq_printf(f, "%pMR (type %u) %u %u %u %.4x %*phN %*phN\\n", | ||
562 | <k->bdaddr, ltk->bdaddr_type, ltk->authenticated, | ||
563 | ltk->type, ltk->enc_size, __le16_to_cpu(ltk->ediv), | ||
564 | 8, ltk->rand, 16, ltk->val); | ||
565 | } | ||
566 | hci_dev_unlock(hdev); | ||
567 | |||
568 | return 0; | ||
569 | } | ||
570 | |||
571 | static int long_term_keys_open(struct inode *inode, struct file *file) | ||
572 | { | ||
573 | return single_open(file, long_term_keys_show, inode->i_private); | ||
574 | } | ||
575 | |||
576 | static const struct file_operations long_term_keys_fops = { | ||
577 | .open = long_term_keys_open, | ||
578 | .read = seq_read, | ||
579 | .llseek = seq_lseek, | ||
580 | .release = single_release, | ||
581 | }; | ||
582 | |||
583 | static int conn_min_interval_set(void *data, u64 val) | ||
584 | { | ||
585 | struct hci_dev *hdev = data; | ||
586 | |||
587 | if (val < 0x0006 || val > 0x0c80 || val > hdev->le_conn_max_interval) | ||
588 | return -EINVAL; | ||
589 | |||
590 | hci_dev_lock(hdev); | ||
591 | hdev->le_conn_min_interval = val; | ||
592 | hci_dev_unlock(hdev); | ||
593 | |||
594 | return 0; | ||
595 | } | ||
596 | |||
597 | static int conn_min_interval_get(void *data, u64 *val) | ||
598 | { | ||
599 | struct hci_dev *hdev = data; | ||
600 | |||
601 | hci_dev_lock(hdev); | ||
602 | *val = hdev->le_conn_min_interval; | ||
603 | hci_dev_unlock(hdev); | ||
604 | |||
605 | return 0; | ||
606 | } | ||
607 | |||
608 | DEFINE_SIMPLE_ATTRIBUTE(conn_min_interval_fops, conn_min_interval_get, | ||
609 | conn_min_interval_set, "%llu\n"); | ||
610 | |||
611 | static int conn_max_interval_set(void *data, u64 val) | ||
612 | { | ||
613 | struct hci_dev *hdev = data; | ||
614 | |||
615 | if (val < 0x0006 || val > 0x0c80 || val < hdev->le_conn_min_interval) | ||
616 | return -EINVAL; | ||
617 | |||
618 | hci_dev_lock(hdev); | ||
619 | hdev->le_conn_max_interval = val; | ||
620 | hci_dev_unlock(hdev); | ||
621 | |||
622 | return 0; | ||
623 | } | ||
624 | |||
625 | static int conn_max_interval_get(void *data, u64 *val) | ||
626 | { | ||
627 | struct hci_dev *hdev = data; | ||
628 | |||
629 | hci_dev_lock(hdev); | ||
630 | *val = hdev->le_conn_max_interval; | ||
631 | hci_dev_unlock(hdev); | ||
632 | |||
633 | return 0; | ||
634 | } | ||
635 | |||
636 | DEFINE_SIMPLE_ATTRIBUTE(conn_max_interval_fops, conn_max_interval_get, | ||
637 | conn_max_interval_set, "%llu\n"); | ||
638 | |||
58 | /* ---- HCI requests ---- */ | 639 | /* ---- HCI requests ---- */ |
59 | 640 | ||
60 | static void hci_req_sync_complete(struct hci_dev *hdev, u8 result) | 641 | static void hci_req_sync_complete(struct hci_dev *hdev, u8 result) |
@@ -556,6 +1137,14 @@ static void hci_init2_req(struct hci_request *req, unsigned long opt) | |||
556 | hci_req_add(req, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); | 1137 | hci_req_add(req, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); |
557 | 1138 | ||
558 | if (lmp_ssp_capable(hdev)) { | 1139 | if (lmp_ssp_capable(hdev)) { |
1140 | /* When SSP is available, then the host features page | ||
1141 | * should also be available as well. However some | ||
1142 | * controllers list the max_page as 0 as long as SSP | ||
1143 | * has not been enabled. To achieve proper debugging | ||
1144 | * output, force the minimum max_page to 1 at least. | ||
1145 | */ | ||
1146 | hdev->max_page = 0x01; | ||
1147 | |||
559 | if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) { | 1148 | if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) { |
560 | u8 mode = 0x01; | 1149 | u8 mode = 0x01; |
561 | hci_req_add(req, HCI_OP_WRITE_SSP_MODE, | 1150 | hci_req_add(req, HCI_OP_WRITE_SSP_MODE, |
@@ -686,8 +1275,17 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt) | |||
686 | hci_setup_link_policy(req); | 1275 | hci_setup_link_policy(req); |
687 | 1276 | ||
688 | if (lmp_le_capable(hdev)) { | 1277 | if (lmp_le_capable(hdev)) { |
1278 | /* If the controller has a public BD_ADDR, then by | ||
1279 | * default use that one. If this is a LE only | ||
1280 | * controller without one, default to the random | ||
1281 | * address. | ||
1282 | */ | ||
1283 | if (bacmp(&hdev->bdaddr, BDADDR_ANY)) | ||
1284 | hdev->own_addr_type = ADDR_LE_DEV_PUBLIC; | ||
1285 | else | ||
1286 | hdev->own_addr_type = ADDR_LE_DEV_RANDOM; | ||
1287 | |||
689 | hci_set_le_support(req); | 1288 | hci_set_le_support(req); |
690 | hci_update_ad(req); | ||
691 | } | 1289 | } |
692 | 1290 | ||
693 | /* Read features beyond page 1 if available */ | 1291 | /* Read features beyond page 1 if available */ |
@@ -721,6 +1319,14 @@ static int __hci_init(struct hci_dev *hdev) | |||
721 | if (err < 0) | 1319 | if (err < 0) |
722 | return err; | 1320 | return err; |
723 | 1321 | ||
1322 | /* The Device Under Test (DUT) mode is special and available for | ||
1323 | * all controller types. So just create it early on. | ||
1324 | */ | ||
1325 | if (test_bit(HCI_SETUP, &hdev->dev_flags)) { | ||
1326 | debugfs_create_file("dut_mode", 0644, hdev->debugfs, hdev, | ||
1327 | &dut_mode_fops); | ||
1328 | } | ||
1329 | |||
724 | /* HCI_BREDR covers both single-mode LE, BR/EDR and dual-mode | 1330 | /* HCI_BREDR covers both single-mode LE, BR/EDR and dual-mode |
725 | * BR/EDR/LE type controllers. AMP controllers only need the | 1331 | * BR/EDR/LE type controllers. AMP controllers only need the |
726 | * first stage init. | 1332 | * first stage init. |
@@ -736,7 +1342,71 @@ static int __hci_init(struct hci_dev *hdev) | |||
736 | if (err < 0) | 1342 | if (err < 0) |
737 | return err; | 1343 | return err; |
738 | 1344 | ||
739 | return __hci_req_sync(hdev, hci_init4_req, 0, HCI_INIT_TIMEOUT); | 1345 | err = __hci_req_sync(hdev, hci_init4_req, 0, HCI_INIT_TIMEOUT); |
1346 | if (err < 0) | ||
1347 | return err; | ||
1348 | |||
1349 | /* Only create debugfs entries during the initial setup | ||
1350 | * phase and not every time the controller gets powered on. | ||
1351 | */ | ||
1352 | if (!test_bit(HCI_SETUP, &hdev->dev_flags)) | ||
1353 | return 0; | ||
1354 | |||
1355 | debugfs_create_file("features", 0444, hdev->debugfs, hdev, | ||
1356 | &features_fops); | ||
1357 | debugfs_create_u16("manufacturer", 0444, hdev->debugfs, | ||
1358 | &hdev->manufacturer); | ||
1359 | debugfs_create_u8("hci_version", 0444, hdev->debugfs, &hdev->hci_ver); | ||
1360 | debugfs_create_u16("hci_revision", 0444, hdev->debugfs, &hdev->hci_rev); | ||
1361 | debugfs_create_file("blacklist", 0444, hdev->debugfs, hdev, | ||
1362 | &blacklist_fops); | ||
1363 | debugfs_create_file("uuids", 0444, hdev->debugfs, hdev, &uuids_fops); | ||
1364 | |||
1365 | if (lmp_bredr_capable(hdev)) { | ||
1366 | debugfs_create_file("inquiry_cache", 0444, hdev->debugfs, | ||
1367 | hdev, &inquiry_cache_fops); | ||
1368 | debugfs_create_file("link_keys", 0400, hdev->debugfs, | ||
1369 | hdev, &link_keys_fops); | ||
1370 | debugfs_create_file("use_debug_keys", 0444, hdev->debugfs, | ||
1371 | hdev, &use_debug_keys_fops); | ||
1372 | debugfs_create_file("dev_class", 0444, hdev->debugfs, | ||
1373 | hdev, &dev_class_fops); | ||
1374 | debugfs_create_file("voice_setting", 0444, hdev->debugfs, | ||
1375 | hdev, &voice_setting_fops); | ||
1376 | } | ||
1377 | |||
1378 | if (lmp_ssp_capable(hdev)) { | ||
1379 | debugfs_create_file("auto_accept_delay", 0644, hdev->debugfs, | ||
1380 | hdev, &auto_accept_delay_fops); | ||
1381 | debugfs_create_file("ssp_debug_mode", 0644, hdev->debugfs, | ||
1382 | hdev, &ssp_debug_mode_fops); | ||
1383 | } | ||
1384 | |||
1385 | if (lmp_sniff_capable(hdev)) { | ||
1386 | debugfs_create_file("idle_timeout", 0644, hdev->debugfs, | ||
1387 | hdev, &idle_timeout_fops); | ||
1388 | debugfs_create_file("sniff_min_interval", 0644, hdev->debugfs, | ||
1389 | hdev, &sniff_min_interval_fops); | ||
1390 | debugfs_create_file("sniff_max_interval", 0644, hdev->debugfs, | ||
1391 | hdev, &sniff_max_interval_fops); | ||
1392 | } | ||
1393 | |||
1394 | if (lmp_le_capable(hdev)) { | ||
1395 | debugfs_create_u8("white_list_size", 0444, hdev->debugfs, | ||
1396 | &hdev->le_white_list_size); | ||
1397 | debugfs_create_file("static_address", 0444, hdev->debugfs, | ||
1398 | hdev, &static_address_fops); | ||
1399 | debugfs_create_file("own_address_type", 0644, hdev->debugfs, | ||
1400 | hdev, &own_address_type_fops); | ||
1401 | debugfs_create_file("long_term_keys", 0400, hdev->debugfs, | ||
1402 | hdev, &long_term_keys_fops); | ||
1403 | debugfs_create_file("conn_min_interval", 0644, hdev->debugfs, | ||
1404 | hdev, &conn_min_interval_fops); | ||
1405 | debugfs_create_file("conn_max_interval", 0644, hdev->debugfs, | ||
1406 | hdev, &conn_max_interval_fops); | ||
1407 | } | ||
1408 | |||
1409 | return 0; | ||
740 | } | 1410 | } |
741 | 1411 | ||
742 | static void hci_scan_req(struct hci_request *req, unsigned long opt) | 1412 | static void hci_scan_req(struct hci_request *req, unsigned long opt) |
@@ -1127,89 +1797,6 @@ done: | |||
1127 | return err; | 1797 | return err; |
1128 | } | 1798 | } |
1129 | 1799 | ||
1130 | static u8 create_ad(struct hci_dev *hdev, u8 *ptr) | ||
1131 | { | ||
1132 | u8 ad_len = 0, flags = 0; | ||
1133 | size_t name_len; | ||
1134 | |||
1135 | if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) | ||
1136 | flags |= LE_AD_GENERAL; | ||
1137 | |||
1138 | if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) { | ||
1139 | if (lmp_le_br_capable(hdev)) | ||
1140 | flags |= LE_AD_SIM_LE_BREDR_CTRL; | ||
1141 | if (lmp_host_le_br_capable(hdev)) | ||
1142 | flags |= LE_AD_SIM_LE_BREDR_HOST; | ||
1143 | } else { | ||
1144 | flags |= LE_AD_NO_BREDR; | ||
1145 | } | ||
1146 | |||
1147 | if (flags) { | ||
1148 | BT_DBG("adv flags 0x%02x", flags); | ||
1149 | |||
1150 | ptr[0] = 2; | ||
1151 | ptr[1] = EIR_FLAGS; | ||
1152 | ptr[2] = flags; | ||
1153 | |||
1154 | ad_len += 3; | ||
1155 | ptr += 3; | ||
1156 | } | ||
1157 | |||
1158 | if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) { | ||
1159 | ptr[0] = 2; | ||
1160 | ptr[1] = EIR_TX_POWER; | ||
1161 | ptr[2] = (u8) hdev->adv_tx_power; | ||
1162 | |||
1163 | ad_len += 3; | ||
1164 | ptr += 3; | ||
1165 | } | ||
1166 | |||
1167 | name_len = strlen(hdev->dev_name); | ||
1168 | if (name_len > 0) { | ||
1169 | size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2; | ||
1170 | |||
1171 | if (name_len > max_len) { | ||
1172 | name_len = max_len; | ||
1173 | ptr[1] = EIR_NAME_SHORT; | ||
1174 | } else | ||
1175 | ptr[1] = EIR_NAME_COMPLETE; | ||
1176 | |||
1177 | ptr[0] = name_len + 1; | ||
1178 | |||
1179 | memcpy(ptr + 2, hdev->dev_name, name_len); | ||
1180 | |||
1181 | ad_len += (name_len + 2); | ||
1182 | ptr += (name_len + 2); | ||
1183 | } | ||
1184 | |||
1185 | return ad_len; | ||
1186 | } | ||
1187 | |||
1188 | void hci_update_ad(struct hci_request *req) | ||
1189 | { | ||
1190 | struct hci_dev *hdev = req->hdev; | ||
1191 | struct hci_cp_le_set_adv_data cp; | ||
1192 | u8 len; | ||
1193 | |||
1194 | if (!lmp_le_capable(hdev)) | ||
1195 | return; | ||
1196 | |||
1197 | memset(&cp, 0, sizeof(cp)); | ||
1198 | |||
1199 | len = create_ad(hdev, cp.data); | ||
1200 | |||
1201 | if (hdev->adv_data_len == len && | ||
1202 | memcmp(cp.data, hdev->adv_data, len) == 0) | ||
1203 | return; | ||
1204 | |||
1205 | memcpy(hdev->adv_data, cp.data, sizeof(cp.data)); | ||
1206 | hdev->adv_data_len = len; | ||
1207 | |||
1208 | cp.length = len; | ||
1209 | |||
1210 | hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp); | ||
1211 | } | ||
1212 | |||
1213 | static int hci_dev_do_open(struct hci_dev *hdev) | 1800 | static int hci_dev_do_open(struct hci_dev *hdev) |
1214 | { | 1801 | { |
1215 | int ret = 0; | 1802 | int ret = 0; |
@@ -1367,6 +1954,7 @@ static int hci_dev_do_close(struct hci_dev *hdev) | |||
1367 | cancel_delayed_work(&hdev->discov_off); | 1954 | cancel_delayed_work(&hdev->discov_off); |
1368 | hdev->discov_timeout = 0; | 1955 | hdev->discov_timeout = 0; |
1369 | clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags); | 1956 | clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags); |
1957 | clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags); | ||
1370 | } | 1958 | } |
1371 | 1959 | ||
1372 | if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) | 1960 | if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) |
@@ -1789,19 +2377,12 @@ static void hci_power_off(struct work_struct *work) | |||
1789 | static void hci_discov_off(struct work_struct *work) | 2377 | static void hci_discov_off(struct work_struct *work) |
1790 | { | 2378 | { |
1791 | struct hci_dev *hdev; | 2379 | struct hci_dev *hdev; |
1792 | u8 scan = SCAN_PAGE; | ||
1793 | 2380 | ||
1794 | hdev = container_of(work, struct hci_dev, discov_off.work); | 2381 | hdev = container_of(work, struct hci_dev, discov_off.work); |
1795 | 2382 | ||
1796 | BT_DBG("%s", hdev->name); | 2383 | BT_DBG("%s", hdev->name); |
1797 | 2384 | ||
1798 | hci_dev_lock(hdev); | 2385 | mgmt_discoverable_timeout(hdev); |
1799 | |||
1800 | hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan); | ||
1801 | |||
1802 | hdev->discov_timeout = 0; | ||
1803 | |||
1804 | hci_dev_unlock(hdev); | ||
1805 | } | 2386 | } |
1806 | 2387 | ||
1807 | int hci_uuids_clear(struct hci_dev *hdev) | 2388 | int hci_uuids_clear(struct hci_dev *hdev) |
@@ -2124,13 +2705,15 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash, | |||
2124 | return 0; | 2705 | return 0; |
2125 | } | 2706 | } |
2126 | 2707 | ||
2127 | struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr) | 2708 | struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, |
2709 | bdaddr_t *bdaddr, u8 type) | ||
2128 | { | 2710 | { |
2129 | struct bdaddr_list *b; | 2711 | struct bdaddr_list *b; |
2130 | 2712 | ||
2131 | list_for_each_entry(b, &hdev->blacklist, list) | 2713 | list_for_each_entry(b, &hdev->blacklist, list) { |
2132 | if (bacmp(bdaddr, &b->bdaddr) == 0) | 2714 | if (!bacmp(&b->bdaddr, bdaddr) && b->bdaddr_type == type) |
2133 | return b; | 2715 | return b; |
2716 | } | ||
2134 | 2717 | ||
2135 | return NULL; | 2718 | return NULL; |
2136 | } | 2719 | } |
@@ -2140,9 +2723,7 @@ int hci_blacklist_clear(struct hci_dev *hdev) | |||
2140 | struct list_head *p, *n; | 2723 | struct list_head *p, *n; |
2141 | 2724 | ||
2142 | list_for_each_safe(p, n, &hdev->blacklist) { | 2725 | list_for_each_safe(p, n, &hdev->blacklist) { |
2143 | struct bdaddr_list *b; | 2726 | struct bdaddr_list *b = list_entry(p, struct bdaddr_list, list); |
2144 | |||
2145 | b = list_entry(p, struct bdaddr_list, list); | ||
2146 | 2727 | ||
2147 | list_del(p); | 2728 | list_del(p); |
2148 | kfree(b); | 2729 | kfree(b); |
@@ -2155,10 +2736,10 @@ int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) | |||
2155 | { | 2736 | { |
2156 | struct bdaddr_list *entry; | 2737 | struct bdaddr_list *entry; |
2157 | 2738 | ||
2158 | if (bacmp(bdaddr, BDADDR_ANY) == 0) | 2739 | if (!bacmp(bdaddr, BDADDR_ANY)) |
2159 | return -EBADF; | 2740 | return -EBADF; |
2160 | 2741 | ||
2161 | if (hci_blacklist_lookup(hdev, bdaddr)) | 2742 | if (hci_blacklist_lookup(hdev, bdaddr, type)) |
2162 | return -EEXIST; | 2743 | return -EEXIST; |
2163 | 2744 | ||
2164 | entry = kzalloc(sizeof(struct bdaddr_list), GFP_KERNEL); | 2745 | entry = kzalloc(sizeof(struct bdaddr_list), GFP_KERNEL); |
@@ -2166,6 +2747,7 @@ int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) | |||
2166 | return -ENOMEM; | 2747 | return -ENOMEM; |
2167 | 2748 | ||
2168 | bacpy(&entry->bdaddr, bdaddr); | 2749 | bacpy(&entry->bdaddr, bdaddr); |
2750 | entry->bdaddr_type = type; | ||
2169 | 2751 | ||
2170 | list_add(&entry->list, &hdev->blacklist); | 2752 | list_add(&entry->list, &hdev->blacklist); |
2171 | 2753 | ||
@@ -2176,10 +2758,10 @@ int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) | |||
2176 | { | 2758 | { |
2177 | struct bdaddr_list *entry; | 2759 | struct bdaddr_list *entry; |
2178 | 2760 | ||
2179 | if (bacmp(bdaddr, BDADDR_ANY) == 0) | 2761 | if (!bacmp(bdaddr, BDADDR_ANY)) |
2180 | return hci_blacklist_clear(hdev); | 2762 | return hci_blacklist_clear(hdev); |
2181 | 2763 | ||
2182 | entry = hci_blacklist_lookup(hdev, bdaddr); | 2764 | entry = hci_blacklist_lookup(hdev, bdaddr, type); |
2183 | if (!entry) | 2765 | if (!entry) |
2184 | return -ENOENT; | 2766 | return -ENOENT; |
2185 | 2767 | ||
@@ -2287,6 +2869,8 @@ struct hci_dev *hci_alloc_dev(void) | |||
2287 | 2869 | ||
2288 | hdev->le_scan_interval = 0x0060; | 2870 | hdev->le_scan_interval = 0x0060; |
2289 | hdev->le_scan_window = 0x0030; | 2871 | hdev->le_scan_window = 0x0030; |
2872 | hdev->le_conn_min_interval = 0x0028; | ||
2873 | hdev->le_conn_max_interval = 0x0038; | ||
2290 | 2874 | ||
2291 | mutex_init(&hdev->lock); | 2875 | mutex_init(&hdev->lock); |
2292 | mutex_init(&hdev->req_lock); | 2876 | mutex_init(&hdev->req_lock); |
@@ -2376,7 +2960,12 @@ int hci_register_dev(struct hci_dev *hdev) | |||
2376 | goto err; | 2960 | goto err; |
2377 | } | 2961 | } |
2378 | 2962 | ||
2379 | error = hci_add_sysfs(hdev); | 2963 | if (!IS_ERR_OR_NULL(bt_debugfs)) |
2964 | hdev->debugfs = debugfs_create_dir(hdev->name, bt_debugfs); | ||
2965 | |||
2966 | dev_set_name(&hdev->dev, "%s", hdev->name); | ||
2967 | |||
2968 | error = device_add(&hdev->dev); | ||
2380 | if (error < 0) | 2969 | if (error < 0) |
2381 | goto err_wqueue; | 2970 | goto err_wqueue; |
2382 | 2971 | ||
@@ -2464,7 +3053,9 @@ void hci_unregister_dev(struct hci_dev *hdev) | |||
2464 | rfkill_destroy(hdev->rfkill); | 3053 | rfkill_destroy(hdev->rfkill); |
2465 | } | 3054 | } |
2466 | 3055 | ||
2467 | hci_del_sysfs(hdev); | 3056 | device_del(&hdev->dev); |
3057 | |||
3058 | debugfs_remove_recursive(hdev->debugfs); | ||
2468 | 3059 | ||
2469 | destroy_workqueue(hdev->workqueue); | 3060 | destroy_workqueue(hdev->workqueue); |
2470 | destroy_workqueue(hdev->req_workqueue); | 3061 | destroy_workqueue(hdev->req_workqueue); |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 5391469ff1a5..5935f748c0f9 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -195,6 +195,11 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) | |||
195 | 195 | ||
196 | memset(hdev->adv_data, 0, sizeof(hdev->adv_data)); | 196 | memset(hdev->adv_data, 0, sizeof(hdev->adv_data)); |
197 | hdev->adv_data_len = 0; | 197 | hdev->adv_data_len = 0; |
198 | |||
199 | memset(hdev->scan_rsp_data, 0, sizeof(hdev->scan_rsp_data)); | ||
200 | hdev->scan_rsp_data_len = 0; | ||
201 | |||
202 | hdev->ssp_debug_mode = 0; | ||
198 | } | 203 | } |
199 | 204 | ||
200 | static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) | 205 | static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -310,11 +315,6 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) | |||
310 | set_bit(HCI_ISCAN, &hdev->flags); | 315 | set_bit(HCI_ISCAN, &hdev->flags); |
311 | if (!old_iscan) | 316 | if (!old_iscan) |
312 | mgmt_discoverable(hdev, 1); | 317 | mgmt_discoverable(hdev, 1); |
313 | if (hdev->discov_timeout > 0) { | ||
314 | int to = msecs_to_jiffies(hdev->discov_timeout * 1000); | ||
315 | queue_delayed_work(hdev->workqueue, &hdev->discov_off, | ||
316 | to); | ||
317 | } | ||
318 | } else if (old_iscan) | 318 | } else if (old_iscan) |
319 | mgmt_discoverable(hdev, 0); | 319 | mgmt_discoverable(hdev, 0); |
320 | 320 | ||
@@ -470,14 +470,13 @@ static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) | |||
470 | if (rp->status) | 470 | if (rp->status) |
471 | return; | 471 | return; |
472 | 472 | ||
473 | hdev->hci_ver = rp->hci_ver; | 473 | if (test_bit(HCI_SETUP, &hdev->dev_flags)) { |
474 | hdev->hci_rev = __le16_to_cpu(rp->hci_rev); | 474 | hdev->hci_ver = rp->hci_ver; |
475 | hdev->lmp_ver = rp->lmp_ver; | 475 | hdev->hci_rev = __le16_to_cpu(rp->hci_rev); |
476 | hdev->manufacturer = __le16_to_cpu(rp->manufacturer); | 476 | hdev->lmp_ver = rp->lmp_ver; |
477 | hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver); | 477 | hdev->manufacturer = __le16_to_cpu(rp->manufacturer); |
478 | 478 | hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver); | |
479 | BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name, | 479 | } |
480 | hdev->manufacturer, hdev->hci_ver, hdev->hci_rev); | ||
481 | } | 480 | } |
482 | 481 | ||
483 | static void hci_cc_read_local_commands(struct hci_dev *hdev, | 482 | static void hci_cc_read_local_commands(struct hci_dev *hdev, |
@@ -557,7 +556,8 @@ static void hci_cc_read_local_ext_features(struct hci_dev *hdev, | |||
557 | if (rp->status) | 556 | if (rp->status) |
558 | return; | 557 | return; |
559 | 558 | ||
560 | hdev->max_page = rp->max_page; | 559 | if (hdev->max_page < rp->max_page) |
560 | hdev->max_page = rp->max_page; | ||
561 | 561 | ||
562 | if (rp->page < HCI_MAX_PAGES) | 562 | if (rp->page < HCI_MAX_PAGES) |
563 | memcpy(hdev->features[rp->page], rp->features, 8); | 563 | memcpy(hdev->features[rp->page], rp->features, 8); |
@@ -939,14 +939,6 @@ static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb) | |||
939 | clear_bit(HCI_ADVERTISING, &hdev->dev_flags); | 939 | clear_bit(HCI_ADVERTISING, &hdev->dev_flags); |
940 | } | 940 | } |
941 | 941 | ||
942 | if (*sent && !test_bit(HCI_INIT, &hdev->flags)) { | ||
943 | struct hci_request req; | ||
944 | |||
945 | hci_req_init(&req, hdev); | ||
946 | hci_update_ad(&req); | ||
947 | hci_req_run(&req, NULL); | ||
948 | } | ||
949 | |||
950 | hci_dev_unlock(hdev); | 942 | hci_dev_unlock(hdev); |
951 | } | 943 | } |
952 | 944 | ||
@@ -1702,7 +1694,7 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
1702 | &flags); | 1694 | &flags); |
1703 | 1695 | ||
1704 | if ((mask & HCI_LM_ACCEPT) && | 1696 | if ((mask & HCI_LM_ACCEPT) && |
1705 | !hci_blacklist_lookup(hdev, &ev->bdaddr)) { | 1697 | !hci_blacklist_lookup(hdev, &ev->bdaddr, BDADDR_BREDR)) { |
1706 | /* Connection accepted */ | 1698 | /* Connection accepted */ |
1707 | struct inquiry_entry *ie; | 1699 | struct inquiry_entry *ie; |
1708 | struct hci_conn *conn; | 1700 | struct hci_conn *conn; |
@@ -2559,7 +2551,6 @@ static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2559 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); | 2551 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); |
2560 | if (conn) { | 2552 | if (conn) { |
2561 | conn->mode = ev->mode; | 2553 | conn->mode = ev->mode; |
2562 | conn->interval = __le16_to_cpu(ev->interval); | ||
2563 | 2554 | ||
2564 | if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, | 2555 | if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, |
2565 | &conn->flags)) { | 2556 | &conn->flags)) { |
@@ -2941,6 +2932,23 @@ unlock: | |||
2941 | hci_dev_unlock(hdev); | 2932 | hci_dev_unlock(hdev); |
2942 | } | 2933 | } |
2943 | 2934 | ||
2935 | static inline size_t eir_get_length(u8 *eir, size_t eir_len) | ||
2936 | { | ||
2937 | size_t parsed = 0; | ||
2938 | |||
2939 | while (parsed < eir_len) { | ||
2940 | u8 field_len = eir[0]; | ||
2941 | |||
2942 | if (field_len == 0) | ||
2943 | return parsed; | ||
2944 | |||
2945 | parsed += field_len + 1; | ||
2946 | eir += field_len + 1; | ||
2947 | } | ||
2948 | |||
2949 | return eir_len; | ||
2950 | } | ||
2951 | |||
2944 | static void hci_extended_inquiry_result_evt(struct hci_dev *hdev, | 2952 | static void hci_extended_inquiry_result_evt(struct hci_dev *hdev, |
2945 | struct sk_buff *skb) | 2953 | struct sk_buff *skb) |
2946 | { | 2954 | { |
@@ -3181,7 +3189,8 @@ static void hci_user_confirm_request_evt(struct hci_dev *hdev, | |||
3181 | 3189 | ||
3182 | if (hdev->auto_accept_delay > 0) { | 3190 | if (hdev->auto_accept_delay > 0) { |
3183 | int delay = msecs_to_jiffies(hdev->auto_accept_delay); | 3191 | int delay = msecs_to_jiffies(hdev->auto_accept_delay); |
3184 | mod_timer(&conn->auto_accept_timer, jiffies + delay); | 3192 | queue_delayed_work(conn->hdev->workqueue, |
3193 | &conn->auto_accept_work, delay); | ||
3185 | goto unlock; | 3194 | goto unlock; |
3186 | } | 3195 | } |
3187 | 3196 | ||
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 97f96ebdd56d..71f0be173080 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c | |||
@@ -481,7 +481,7 @@ static int hci_sock_blacklist_add(struct hci_dev *hdev, void __user *arg) | |||
481 | 481 | ||
482 | hci_dev_lock(hdev); | 482 | hci_dev_lock(hdev); |
483 | 483 | ||
484 | err = hci_blacklist_add(hdev, &bdaddr, 0); | 484 | err = hci_blacklist_add(hdev, &bdaddr, BDADDR_BREDR); |
485 | 485 | ||
486 | hci_dev_unlock(hdev); | 486 | hci_dev_unlock(hdev); |
487 | 487 | ||
@@ -498,7 +498,7 @@ static int hci_sock_blacklist_del(struct hci_dev *hdev, void __user *arg) | |||
498 | 498 | ||
499 | hci_dev_lock(hdev); | 499 | hci_dev_lock(hdev); |
500 | 500 | ||
501 | err = hci_blacklist_del(hdev, &bdaddr, 0); | 501 | err = hci_blacklist_del(hdev, &bdaddr, BDADDR_BREDR); |
502 | 502 | ||
503 | hci_dev_unlock(hdev); | 503 | hci_dev_unlock(hdev); |
504 | 504 | ||
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index edf623a29043..0b61250cfdf9 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c | |||
@@ -1,17 +1,12 @@ | |||
1 | /* Bluetooth HCI driver model support. */ | 1 | /* Bluetooth HCI driver model support. */ |
2 | 2 | ||
3 | #include <linux/debugfs.h> | ||
4 | #include <linux/module.h> | 3 | #include <linux/module.h> |
5 | #include <asm/unaligned.h> | ||
6 | 4 | ||
7 | #include <net/bluetooth/bluetooth.h> | 5 | #include <net/bluetooth/bluetooth.h> |
8 | #include <net/bluetooth/hci_core.h> | 6 | #include <net/bluetooth/hci_core.h> |
9 | 7 | ||
10 | static struct class *bt_class; | 8 | static struct class *bt_class; |
11 | 9 | ||
12 | struct dentry *bt_debugfs; | ||
13 | EXPORT_SYMBOL_GPL(bt_debugfs); | ||
14 | |||
15 | static inline char *link_typetostr(int type) | 10 | static inline char *link_typetostr(int type) |
16 | { | 11 | { |
17 | switch (type) { | 12 | switch (type) { |
@@ -42,29 +37,15 @@ static ssize_t show_link_address(struct device *dev, | |||
42 | return sprintf(buf, "%pMR\n", &conn->dst); | 37 | return sprintf(buf, "%pMR\n", &conn->dst); |
43 | } | 38 | } |
44 | 39 | ||
45 | static ssize_t show_link_features(struct device *dev, | ||
46 | struct device_attribute *attr, char *buf) | ||
47 | { | ||
48 | struct hci_conn *conn = to_hci_conn(dev); | ||
49 | |||
50 | return sprintf(buf, "0x%02x%02x%02x%02x%02x%02x%02x%02x\n", | ||
51 | conn->features[0][0], conn->features[0][1], | ||
52 | conn->features[0][2], conn->features[0][3], | ||
53 | conn->features[0][4], conn->features[0][5], | ||
54 | conn->features[0][6], conn->features[0][7]); | ||
55 | } | ||
56 | |||
57 | #define LINK_ATTR(_name, _mode, _show, _store) \ | 40 | #define LINK_ATTR(_name, _mode, _show, _store) \ |
58 | struct device_attribute link_attr_##_name = __ATTR(_name, _mode, _show, _store) | 41 | struct device_attribute link_attr_##_name = __ATTR(_name, _mode, _show, _store) |
59 | 42 | ||
60 | static LINK_ATTR(type, S_IRUGO, show_link_type, NULL); | 43 | static LINK_ATTR(type, S_IRUGO, show_link_type, NULL); |
61 | static LINK_ATTR(address, S_IRUGO, show_link_address, NULL); | 44 | static LINK_ATTR(address, S_IRUGO, show_link_address, NULL); |
62 | static LINK_ATTR(features, S_IRUGO, show_link_features, NULL); | ||
63 | 45 | ||
64 | static struct attribute *bt_link_attrs[] = { | 46 | static struct attribute *bt_link_attrs[] = { |
65 | &link_attr_type.attr, | 47 | &link_attr_type.attr, |
66 | &link_attr_address.attr, | 48 | &link_attr_address.attr, |
67 | &link_attr_features.attr, | ||
68 | NULL | 49 | NULL |
69 | }; | 50 | }; |
70 | 51 | ||
@@ -150,28 +131,6 @@ void hci_conn_del_sysfs(struct hci_conn *conn) | |||
150 | hci_dev_put(hdev); | 131 | hci_dev_put(hdev); |
151 | } | 132 | } |
152 | 133 | ||
153 | static inline char *host_bustostr(int bus) | ||
154 | { | ||
155 | switch (bus) { | ||
156 | case HCI_VIRTUAL: | ||
157 | return "VIRTUAL"; | ||
158 | case HCI_USB: | ||
159 | return "USB"; | ||
160 | case HCI_PCCARD: | ||
161 | return "PCCARD"; | ||
162 | case HCI_UART: | ||
163 | return "UART"; | ||
164 | case HCI_RS232: | ||
165 | return "RS232"; | ||
166 | case HCI_PCI: | ||
167 | return "PCI"; | ||
168 | case HCI_SDIO: | ||
169 | return "SDIO"; | ||
170 | default: | ||
171 | return "UNKNOWN"; | ||
172 | } | ||
173 | } | ||
174 | |||
175 | static inline char *host_typetostr(int type) | 134 | static inline char *host_typetostr(int type) |
176 | { | 135 | { |
177 | switch (type) { | 136 | switch (type) { |
@@ -184,13 +143,6 @@ static inline char *host_typetostr(int type) | |||
184 | } | 143 | } |
185 | } | 144 | } |
186 | 145 | ||
187 | static ssize_t show_bus(struct device *dev, | ||
188 | struct device_attribute *attr, char *buf) | ||
189 | { | ||
190 | struct hci_dev *hdev = to_hci_dev(dev); | ||
191 | return sprintf(buf, "%s\n", host_bustostr(hdev->bus)); | ||
192 | } | ||
193 | |||
194 | static ssize_t show_type(struct device *dev, | 146 | static ssize_t show_type(struct device *dev, |
195 | struct device_attribute *attr, char *buf) | 147 | struct device_attribute *attr, char *buf) |
196 | { | 148 | { |
@@ -212,14 +164,6 @@ static ssize_t show_name(struct device *dev, | |||
212 | return sprintf(buf, "%s\n", name); | 164 | return sprintf(buf, "%s\n", name); |
213 | } | 165 | } |
214 | 166 | ||
215 | static ssize_t show_class(struct device *dev, | ||
216 | struct device_attribute *attr, char *buf) | ||
217 | { | ||
218 | struct hci_dev *hdev = to_hci_dev(dev); | ||
219 | return sprintf(buf, "0x%.2x%.2x%.2x\n", hdev->dev_class[2], | ||
220 | hdev->dev_class[1], hdev->dev_class[0]); | ||
221 | } | ||
222 | |||
223 | static ssize_t show_address(struct device *dev, | 167 | static ssize_t show_address(struct device *dev, |
224 | struct device_attribute *attr, char *buf) | 168 | struct device_attribute *attr, char *buf) |
225 | { | 169 | { |
@@ -227,150 +171,14 @@ static ssize_t show_address(struct device *dev, | |||
227 | return sprintf(buf, "%pMR\n", &hdev->bdaddr); | 171 | return sprintf(buf, "%pMR\n", &hdev->bdaddr); |
228 | } | 172 | } |
229 | 173 | ||
230 | static ssize_t show_features(struct device *dev, | ||
231 | struct device_attribute *attr, char *buf) | ||
232 | { | ||
233 | struct hci_dev *hdev = to_hci_dev(dev); | ||
234 | |||
235 | return sprintf(buf, "0x%02x%02x%02x%02x%02x%02x%02x%02x\n", | ||
236 | hdev->features[0][0], hdev->features[0][1], | ||
237 | hdev->features[0][2], hdev->features[0][3], | ||
238 | hdev->features[0][4], hdev->features[0][5], | ||
239 | hdev->features[0][6], hdev->features[0][7]); | ||
240 | } | ||
241 | |||
242 | static ssize_t show_manufacturer(struct device *dev, | ||
243 | struct device_attribute *attr, char *buf) | ||
244 | { | ||
245 | struct hci_dev *hdev = to_hci_dev(dev); | ||
246 | return sprintf(buf, "%d\n", hdev->manufacturer); | ||
247 | } | ||
248 | |||
249 | static ssize_t show_hci_version(struct device *dev, | ||
250 | struct device_attribute *attr, char *buf) | ||
251 | { | ||
252 | struct hci_dev *hdev = to_hci_dev(dev); | ||
253 | return sprintf(buf, "%d\n", hdev->hci_ver); | ||
254 | } | ||
255 | |||
256 | static ssize_t show_hci_revision(struct device *dev, | ||
257 | struct device_attribute *attr, char *buf) | ||
258 | { | ||
259 | struct hci_dev *hdev = to_hci_dev(dev); | ||
260 | return sprintf(buf, "%d\n", hdev->hci_rev); | ||
261 | } | ||
262 | |||
263 | static ssize_t show_idle_timeout(struct device *dev, | ||
264 | struct device_attribute *attr, char *buf) | ||
265 | { | ||
266 | struct hci_dev *hdev = to_hci_dev(dev); | ||
267 | return sprintf(buf, "%d\n", hdev->idle_timeout); | ||
268 | } | ||
269 | |||
270 | static ssize_t store_idle_timeout(struct device *dev, | ||
271 | struct device_attribute *attr, | ||
272 | const char *buf, size_t count) | ||
273 | { | ||
274 | struct hci_dev *hdev = to_hci_dev(dev); | ||
275 | unsigned int val; | ||
276 | int rv; | ||
277 | |||
278 | rv = kstrtouint(buf, 0, &val); | ||
279 | if (rv < 0) | ||
280 | return rv; | ||
281 | |||
282 | if (val != 0 && (val < 500 || val > 3600000)) | ||
283 | return -EINVAL; | ||
284 | |||
285 | hdev->idle_timeout = val; | ||
286 | |||
287 | return count; | ||
288 | } | ||
289 | |||
290 | static ssize_t show_sniff_max_interval(struct device *dev, | ||
291 | struct device_attribute *attr, char *buf) | ||
292 | { | ||
293 | struct hci_dev *hdev = to_hci_dev(dev); | ||
294 | return sprintf(buf, "%d\n", hdev->sniff_max_interval); | ||
295 | } | ||
296 | |||
297 | static ssize_t store_sniff_max_interval(struct device *dev, | ||
298 | struct device_attribute *attr, | ||
299 | const char *buf, size_t count) | ||
300 | { | ||
301 | struct hci_dev *hdev = to_hci_dev(dev); | ||
302 | u16 val; | ||
303 | int rv; | ||
304 | |||
305 | rv = kstrtou16(buf, 0, &val); | ||
306 | if (rv < 0) | ||
307 | return rv; | ||
308 | |||
309 | if (val == 0 || val % 2 || val < hdev->sniff_min_interval) | ||
310 | return -EINVAL; | ||
311 | |||
312 | hdev->sniff_max_interval = val; | ||
313 | |||
314 | return count; | ||
315 | } | ||
316 | |||
317 | static ssize_t show_sniff_min_interval(struct device *dev, | ||
318 | struct device_attribute *attr, char *buf) | ||
319 | { | ||
320 | struct hci_dev *hdev = to_hci_dev(dev); | ||
321 | return sprintf(buf, "%d\n", hdev->sniff_min_interval); | ||
322 | } | ||
323 | |||
324 | static ssize_t store_sniff_min_interval(struct device *dev, | ||
325 | struct device_attribute *attr, | ||
326 | const char *buf, size_t count) | ||
327 | { | ||
328 | struct hci_dev *hdev = to_hci_dev(dev); | ||
329 | u16 val; | ||
330 | int rv; | ||
331 | |||
332 | rv = kstrtou16(buf, 0, &val); | ||
333 | if (rv < 0) | ||
334 | return rv; | ||
335 | |||
336 | if (val == 0 || val % 2 || val > hdev->sniff_max_interval) | ||
337 | return -EINVAL; | ||
338 | |||
339 | hdev->sniff_min_interval = val; | ||
340 | |||
341 | return count; | ||
342 | } | ||
343 | |||
344 | static DEVICE_ATTR(bus, S_IRUGO, show_bus, NULL); | ||
345 | static DEVICE_ATTR(type, S_IRUGO, show_type, NULL); | 174 | static DEVICE_ATTR(type, S_IRUGO, show_type, NULL); |
346 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | 175 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); |
347 | static DEVICE_ATTR(class, S_IRUGO, show_class, NULL); | ||
348 | static DEVICE_ATTR(address, S_IRUGO, show_address, NULL); | 176 | static DEVICE_ATTR(address, S_IRUGO, show_address, NULL); |
349 | static DEVICE_ATTR(features, S_IRUGO, show_features, NULL); | ||
350 | static DEVICE_ATTR(manufacturer, S_IRUGO, show_manufacturer, NULL); | ||
351 | static DEVICE_ATTR(hci_version, S_IRUGO, show_hci_version, NULL); | ||
352 | static DEVICE_ATTR(hci_revision, S_IRUGO, show_hci_revision, NULL); | ||
353 | |||
354 | static DEVICE_ATTR(idle_timeout, S_IRUGO | S_IWUSR, | ||
355 | show_idle_timeout, store_idle_timeout); | ||
356 | static DEVICE_ATTR(sniff_max_interval, S_IRUGO | S_IWUSR, | ||
357 | show_sniff_max_interval, store_sniff_max_interval); | ||
358 | static DEVICE_ATTR(sniff_min_interval, S_IRUGO | S_IWUSR, | ||
359 | show_sniff_min_interval, store_sniff_min_interval); | ||
360 | 177 | ||
361 | static struct attribute *bt_host_attrs[] = { | 178 | static struct attribute *bt_host_attrs[] = { |
362 | &dev_attr_bus.attr, | ||
363 | &dev_attr_type.attr, | 179 | &dev_attr_type.attr, |
364 | &dev_attr_name.attr, | 180 | &dev_attr_name.attr, |
365 | &dev_attr_class.attr, | ||
366 | &dev_attr_address.attr, | 181 | &dev_attr_address.attr, |
367 | &dev_attr_features.attr, | ||
368 | &dev_attr_manufacturer.attr, | ||
369 | &dev_attr_hci_version.attr, | ||
370 | &dev_attr_hci_revision.attr, | ||
371 | &dev_attr_idle_timeout.attr, | ||
372 | &dev_attr_sniff_max_interval.attr, | ||
373 | &dev_attr_sniff_min_interval.attr, | ||
374 | NULL | 182 | NULL |
375 | }; | 183 | }; |
376 | 184 | ||
@@ -396,141 +204,6 @@ static struct device_type bt_host = { | |||
396 | .release = bt_host_release, | 204 | .release = bt_host_release, |
397 | }; | 205 | }; |
398 | 206 | ||
399 | static int inquiry_cache_show(struct seq_file *f, void *p) | ||
400 | { | ||
401 | struct hci_dev *hdev = f->private; | ||
402 | struct discovery_state *cache = &hdev->discovery; | ||
403 | struct inquiry_entry *e; | ||
404 | |||
405 | hci_dev_lock(hdev); | ||
406 | |||
407 | list_for_each_entry(e, &cache->all, all) { | ||
408 | struct inquiry_data *data = &e->data; | ||
409 | seq_printf(f, "%pMR %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n", | ||
410 | &data->bdaddr, | ||
411 | data->pscan_rep_mode, data->pscan_period_mode, | ||
412 | data->pscan_mode, data->dev_class[2], | ||
413 | data->dev_class[1], data->dev_class[0], | ||
414 | __le16_to_cpu(data->clock_offset), | ||
415 | data->rssi, data->ssp_mode, e->timestamp); | ||
416 | } | ||
417 | |||
418 | hci_dev_unlock(hdev); | ||
419 | |||
420 | return 0; | ||
421 | } | ||
422 | |||
423 | static int inquiry_cache_open(struct inode *inode, struct file *file) | ||
424 | { | ||
425 | return single_open(file, inquiry_cache_show, inode->i_private); | ||
426 | } | ||
427 | |||
428 | static const struct file_operations inquiry_cache_fops = { | ||
429 | .open = inquiry_cache_open, | ||
430 | .read = seq_read, | ||
431 | .llseek = seq_lseek, | ||
432 | .release = single_release, | ||
433 | }; | ||
434 | |||
435 | static int blacklist_show(struct seq_file *f, void *p) | ||
436 | { | ||
437 | struct hci_dev *hdev = f->private; | ||
438 | struct bdaddr_list *b; | ||
439 | |||
440 | hci_dev_lock(hdev); | ||
441 | |||
442 | list_for_each_entry(b, &hdev->blacklist, list) | ||
443 | seq_printf(f, "%pMR\n", &b->bdaddr); | ||
444 | |||
445 | hci_dev_unlock(hdev); | ||
446 | |||
447 | return 0; | ||
448 | } | ||
449 | |||
450 | static int blacklist_open(struct inode *inode, struct file *file) | ||
451 | { | ||
452 | return single_open(file, blacklist_show, inode->i_private); | ||
453 | } | ||
454 | |||
455 | static const struct file_operations blacklist_fops = { | ||
456 | .open = blacklist_open, | ||
457 | .read = seq_read, | ||
458 | .llseek = seq_lseek, | ||
459 | .release = single_release, | ||
460 | }; | ||
461 | |||
462 | static void print_bt_uuid(struct seq_file *f, u8 *uuid) | ||
463 | { | ||
464 | u32 data0, data5; | ||
465 | u16 data1, data2, data3, data4; | ||
466 | |||
467 | data5 = get_unaligned_le32(uuid); | ||
468 | data4 = get_unaligned_le16(uuid + 4); | ||
469 | data3 = get_unaligned_le16(uuid + 6); | ||
470 | data2 = get_unaligned_le16(uuid + 8); | ||
471 | data1 = get_unaligned_le16(uuid + 10); | ||
472 | data0 = get_unaligned_le32(uuid + 12); | ||
473 | |||
474 | seq_printf(f, "%.8x-%.4x-%.4x-%.4x-%.4x%.8x\n", | ||
475 | data0, data1, data2, data3, data4, data5); | ||
476 | } | ||
477 | |||
478 | static int uuids_show(struct seq_file *f, void *p) | ||
479 | { | ||
480 | struct hci_dev *hdev = f->private; | ||
481 | struct bt_uuid *uuid; | ||
482 | |||
483 | hci_dev_lock(hdev); | ||
484 | |||
485 | list_for_each_entry(uuid, &hdev->uuids, list) | ||
486 | print_bt_uuid(f, uuid->uuid); | ||
487 | |||
488 | hci_dev_unlock(hdev); | ||
489 | |||
490 | return 0; | ||
491 | } | ||
492 | |||
493 | static int uuids_open(struct inode *inode, struct file *file) | ||
494 | { | ||
495 | return single_open(file, uuids_show, inode->i_private); | ||
496 | } | ||
497 | |||
498 | static const struct file_operations uuids_fops = { | ||
499 | .open = uuids_open, | ||
500 | .read = seq_read, | ||
501 | .llseek = seq_lseek, | ||
502 | .release = single_release, | ||
503 | }; | ||
504 | |||
505 | static int auto_accept_delay_set(void *data, u64 val) | ||
506 | { | ||
507 | struct hci_dev *hdev = data; | ||
508 | |||
509 | hci_dev_lock(hdev); | ||
510 | |||
511 | hdev->auto_accept_delay = val; | ||
512 | |||
513 | hci_dev_unlock(hdev); | ||
514 | |||
515 | return 0; | ||
516 | } | ||
517 | |||
518 | static int auto_accept_delay_get(void *data, u64 *val) | ||
519 | { | ||
520 | struct hci_dev *hdev = data; | ||
521 | |||
522 | hci_dev_lock(hdev); | ||
523 | |||
524 | *val = hdev->auto_accept_delay; | ||
525 | |||
526 | hci_dev_unlock(hdev); | ||
527 | |||
528 | return 0; | ||
529 | } | ||
530 | |||
531 | DEFINE_SIMPLE_ATTRIBUTE(auto_accept_delay_fops, auto_accept_delay_get, | ||
532 | auto_accept_delay_set, "%llu\n"); | ||
533 | |||
534 | void hci_init_sysfs(struct hci_dev *hdev) | 207 | void hci_init_sysfs(struct hci_dev *hdev) |
535 | { | 208 | { |
536 | struct device *dev = &hdev->dev; | 209 | struct device *dev = &hdev->dev; |
@@ -542,52 +215,8 @@ void hci_init_sysfs(struct hci_dev *hdev) | |||
542 | device_initialize(dev); | 215 | device_initialize(dev); |
543 | } | 216 | } |
544 | 217 | ||
545 | int hci_add_sysfs(struct hci_dev *hdev) | ||
546 | { | ||
547 | struct device *dev = &hdev->dev; | ||
548 | int err; | ||
549 | |||
550 | BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus); | ||
551 | |||
552 | dev_set_name(dev, "%s", hdev->name); | ||
553 | |||
554 | err = device_add(dev); | ||
555 | if (err < 0) | ||
556 | return err; | ||
557 | |||
558 | if (!bt_debugfs) | ||
559 | return 0; | ||
560 | |||
561 | hdev->debugfs = debugfs_create_dir(hdev->name, bt_debugfs); | ||
562 | if (!hdev->debugfs) | ||
563 | return 0; | ||
564 | |||
565 | debugfs_create_file("inquiry_cache", 0444, hdev->debugfs, | ||
566 | hdev, &inquiry_cache_fops); | ||
567 | |||
568 | debugfs_create_file("blacklist", 0444, hdev->debugfs, | ||
569 | hdev, &blacklist_fops); | ||
570 | |||
571 | debugfs_create_file("uuids", 0444, hdev->debugfs, hdev, &uuids_fops); | ||
572 | |||
573 | debugfs_create_file("auto_accept_delay", 0444, hdev->debugfs, hdev, | ||
574 | &auto_accept_delay_fops); | ||
575 | return 0; | ||
576 | } | ||
577 | |||
578 | void hci_del_sysfs(struct hci_dev *hdev) | ||
579 | { | ||
580 | BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus); | ||
581 | |||
582 | debugfs_remove_recursive(hdev->debugfs); | ||
583 | |||
584 | device_del(&hdev->dev); | ||
585 | } | ||
586 | |||
587 | int __init bt_sysfs_init(void) | 218 | int __init bt_sysfs_init(void) |
588 | { | 219 | { |
589 | bt_debugfs = debugfs_create_dir("bluetooth", NULL); | ||
590 | |||
591 | bt_class = class_create(THIS_MODULE, "bluetooth"); | 220 | bt_class = class_create(THIS_MODULE, "bluetooth"); |
592 | 221 | ||
593 | return PTR_ERR_OR_ZERO(bt_class); | 222 | return PTR_ERR_OR_ZERO(bt_class); |
@@ -596,6 +225,4 @@ int __init bt_sysfs_init(void) | |||
596 | void bt_sysfs_cleanup(void) | 225 | void bt_sysfs_cleanup(void) |
597 | { | 226 | { |
598 | class_destroy(bt_class); | 227 | class_destroy(bt_class); |
599 | |||
600 | debugfs_remove_recursive(bt_debugfs); | ||
601 | } | 228 | } |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 0c3446da1ec9..0cef67707838 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -223,38 +223,25 @@ static u16 l2cap_alloc_cid(struct l2cap_conn *conn) | |||
223 | return 0; | 223 | return 0; |
224 | } | 224 | } |
225 | 225 | ||
226 | static void __l2cap_state_change(struct l2cap_chan *chan, int state) | 226 | static void l2cap_state_change(struct l2cap_chan *chan, int state) |
227 | { | 227 | { |
228 | BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state), | 228 | BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state), |
229 | state_to_string(state)); | 229 | state_to_string(state)); |
230 | 230 | ||
231 | chan->state = state; | 231 | chan->state = state; |
232 | chan->ops->state_change(chan, state); | 232 | chan->ops->state_change(chan, state, 0); |
233 | } | 233 | } |
234 | 234 | ||
235 | static void l2cap_state_change(struct l2cap_chan *chan, int state) | 235 | static inline void l2cap_state_change_and_error(struct l2cap_chan *chan, |
236 | int state, int err) | ||
236 | { | 237 | { |
237 | struct sock *sk = chan->sk; | 238 | chan->state = state; |
238 | 239 | chan->ops->state_change(chan, chan->state, err); | |
239 | lock_sock(sk); | ||
240 | __l2cap_state_change(chan, state); | ||
241 | release_sock(sk); | ||
242 | } | ||
243 | |||
244 | static inline void __l2cap_chan_set_err(struct l2cap_chan *chan, int err) | ||
245 | { | ||
246 | struct sock *sk = chan->sk; | ||
247 | |||
248 | sk->sk_err = err; | ||
249 | } | 240 | } |
250 | 241 | ||
251 | static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err) | 242 | static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err) |
252 | { | 243 | { |
253 | struct sock *sk = chan->sk; | 244 | chan->ops->state_change(chan, chan->state, err); |
254 | |||
255 | lock_sock(sk); | ||
256 | __l2cap_chan_set_err(chan, err); | ||
257 | release_sock(sk); | ||
258 | } | 245 | } |
259 | 246 | ||
260 | static void __set_retrans_timer(struct l2cap_chan *chan) | 247 | static void __set_retrans_timer(struct l2cap_chan *chan) |
@@ -645,8 +632,7 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason) | |||
645 | case BT_CONFIG: | 632 | case BT_CONFIG: |
646 | if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && | 633 | if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && |
647 | conn->hcon->type == ACL_LINK) { | 634 | conn->hcon->type == ACL_LINK) { |
648 | struct sock *sk = chan->sk; | 635 | __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); |
649 | __set_chan_timer(chan, sk->sk_sndtimeo); | ||
650 | l2cap_send_disconn_req(chan, reason); | 636 | l2cap_send_disconn_req(chan, reason); |
651 | } else | 637 | } else |
652 | l2cap_chan_del(chan, reason); | 638 | l2cap_chan_del(chan, reason); |
@@ -1230,7 +1216,6 @@ static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask) | |||
1230 | 1216 | ||
1231 | static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err) | 1217 | static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err) |
1232 | { | 1218 | { |
1233 | struct sock *sk = chan->sk; | ||
1234 | struct l2cap_conn *conn = chan->conn; | 1219 | struct l2cap_conn *conn = chan->conn; |
1235 | struct l2cap_disconn_req req; | 1220 | struct l2cap_disconn_req req; |
1236 | 1221 | ||
@@ -1253,10 +1238,7 @@ static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err) | |||
1253 | l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_DISCONN_REQ, | 1238 | l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_DISCONN_REQ, |
1254 | sizeof(req), &req); | 1239 | sizeof(req), &req); |
1255 | 1240 | ||
1256 | lock_sock(sk); | 1241 | l2cap_state_change_and_error(chan, BT_DISCONN, err); |
1257 | __l2cap_state_change(chan, BT_DISCONN); | ||
1258 | __l2cap_chan_set_err(chan, err); | ||
1259 | release_sock(sk); | ||
1260 | } | 1242 | } |
1261 | 1243 | ||
1262 | /* ---- L2CAP connections ---- */ | 1244 | /* ---- L2CAP connections ---- */ |
@@ -1300,20 +1282,16 @@ static void l2cap_conn_start(struct l2cap_conn *conn) | |||
1300 | rsp.dcid = cpu_to_le16(chan->scid); | 1282 | rsp.dcid = cpu_to_le16(chan->scid); |
1301 | 1283 | ||
1302 | if (l2cap_chan_check_security(chan)) { | 1284 | if (l2cap_chan_check_security(chan)) { |
1303 | struct sock *sk = chan->sk; | ||
1304 | |||
1305 | lock_sock(sk); | ||
1306 | if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { | 1285 | if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { |
1307 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND); | 1286 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND); |
1308 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHOR_PEND); | 1287 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHOR_PEND); |
1309 | chan->ops->defer(chan); | 1288 | chan->ops->defer(chan); |
1310 | 1289 | ||
1311 | } else { | 1290 | } else { |
1312 | __l2cap_state_change(chan, BT_CONFIG); | 1291 | l2cap_state_change(chan, BT_CONFIG); |
1313 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); | 1292 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); |
1314 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); | 1293 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); |
1315 | } | 1294 | } |
1316 | release_sock(sk); | ||
1317 | } else { | 1295 | } else { |
1318 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND); | 1296 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND); |
1319 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHEN_PEND); | 1297 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHEN_PEND); |
@@ -1383,14 +1361,15 @@ static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid, | |||
1383 | 1361 | ||
1384 | static void l2cap_le_conn_ready(struct l2cap_conn *conn) | 1362 | static void l2cap_le_conn_ready(struct l2cap_conn *conn) |
1385 | { | 1363 | { |
1386 | struct sock *parent; | 1364 | struct hci_conn *hcon = conn->hcon; |
1387 | struct l2cap_chan *chan, *pchan; | 1365 | struct l2cap_chan *chan, *pchan; |
1366 | u8 dst_type; | ||
1388 | 1367 | ||
1389 | BT_DBG(""); | 1368 | BT_DBG(""); |
1390 | 1369 | ||
1391 | /* Check if we have socket listening on cid */ | 1370 | /* Check if we have socket listening on cid */ |
1392 | pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_ATT, | 1371 | pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_ATT, |
1393 | &conn->hcon->src, &conn->hcon->dst); | 1372 | &hcon->src, &hcon->dst); |
1394 | if (!pchan) | 1373 | if (!pchan) |
1395 | return; | 1374 | return; |
1396 | 1375 | ||
@@ -1398,9 +1377,13 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) | |||
1398 | if (__l2cap_get_chan_by_dcid(conn, L2CAP_CID_ATT)) | 1377 | if (__l2cap_get_chan_by_dcid(conn, L2CAP_CID_ATT)) |
1399 | return; | 1378 | return; |
1400 | 1379 | ||
1401 | parent = pchan->sk; | 1380 | dst_type = bdaddr_type(hcon, hcon->dst_type); |
1381 | |||
1382 | /* If device is blocked, do not create a channel for it */ | ||
1383 | if (hci_blacklist_lookup(hcon->hdev, &hcon->dst, dst_type)) | ||
1384 | return; | ||
1402 | 1385 | ||
1403 | lock_sock(parent); | 1386 | l2cap_chan_lock(pchan); |
1404 | 1387 | ||
1405 | chan = pchan->ops->new_connection(pchan); | 1388 | chan = pchan->ops->new_connection(pchan); |
1406 | if (!chan) | 1389 | if (!chan) |
@@ -1408,15 +1391,15 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) | |||
1408 | 1391 | ||
1409 | chan->dcid = L2CAP_CID_ATT; | 1392 | chan->dcid = L2CAP_CID_ATT; |
1410 | 1393 | ||
1411 | bacpy(&chan->src, &conn->hcon->src); | 1394 | bacpy(&chan->src, &hcon->src); |
1412 | bacpy(&chan->dst, &conn->hcon->dst); | 1395 | bacpy(&chan->dst, &hcon->dst); |
1413 | chan->src_type = bdaddr_type(conn->hcon, conn->hcon->src_type); | 1396 | chan->src_type = bdaddr_type(hcon, hcon->src_type); |
1414 | chan->dst_type = bdaddr_type(conn->hcon, conn->hcon->dst_type); | 1397 | chan->dst_type = dst_type; |
1415 | 1398 | ||
1416 | __l2cap_chan_add(conn, chan); | 1399 | __l2cap_chan_add(conn, chan); |
1417 | 1400 | ||
1418 | clean: | 1401 | clean: |
1419 | release_sock(parent); | 1402 | l2cap_chan_unlock(pchan); |
1420 | } | 1403 | } |
1421 | 1404 | ||
1422 | static void l2cap_conn_ready(struct l2cap_conn *conn) | 1405 | static void l2cap_conn_ready(struct l2cap_conn *conn) |
@@ -1451,12 +1434,7 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) | |||
1451 | l2cap_chan_ready(chan); | 1434 | l2cap_chan_ready(chan); |
1452 | 1435 | ||
1453 | } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { | 1436 | } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { |
1454 | struct sock *sk = chan->sk; | 1437 | l2cap_chan_ready(chan); |
1455 | __clear_chan_timer(chan); | ||
1456 | lock_sock(sk); | ||
1457 | __l2cap_state_change(chan, BT_CONNECTED); | ||
1458 | sk->sk_state_change(sk); | ||
1459 | release_sock(sk); | ||
1460 | 1438 | ||
1461 | } else if (chan->state == BT_CONNECT) { | 1439 | } else if (chan->state == BT_CONNECT) { |
1462 | l2cap_do_start(chan); | 1440 | l2cap_do_start(chan); |
@@ -1764,7 +1742,6 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, | |||
1764 | int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, | 1742 | int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, |
1765 | bdaddr_t *dst, u8 dst_type) | 1743 | bdaddr_t *dst, u8 dst_type) |
1766 | { | 1744 | { |
1767 | struct sock *sk = chan->sk; | ||
1768 | struct l2cap_conn *conn; | 1745 | struct l2cap_conn *conn; |
1769 | struct hci_conn *hcon; | 1746 | struct hci_conn *hcon; |
1770 | struct hci_dev *hdev; | 1747 | struct hci_dev *hdev; |
@@ -1876,7 +1853,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, | |||
1876 | hci_conn_drop(hcon); | 1853 | hci_conn_drop(hcon); |
1877 | 1854 | ||
1878 | l2cap_state_change(chan, BT_CONNECT); | 1855 | l2cap_state_change(chan, BT_CONNECT); |
1879 | __set_chan_timer(chan, sk->sk_sndtimeo); | 1856 | __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); |
1880 | 1857 | ||
1881 | if (hcon->state == BT_CONNECTED) { | 1858 | if (hcon->state == BT_CONNECTED) { |
1882 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { | 1859 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { |
@@ -1896,38 +1873,6 @@ done: | |||
1896 | return err; | 1873 | return err; |
1897 | } | 1874 | } |
1898 | 1875 | ||
1899 | int __l2cap_wait_ack(struct sock *sk) | ||
1900 | { | ||
1901 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; | ||
1902 | DECLARE_WAITQUEUE(wait, current); | ||
1903 | int err = 0; | ||
1904 | int timeo = HZ/5; | ||
1905 | |||
1906 | add_wait_queue(sk_sleep(sk), &wait); | ||
1907 | set_current_state(TASK_INTERRUPTIBLE); | ||
1908 | while (chan->unacked_frames > 0 && chan->conn) { | ||
1909 | if (!timeo) | ||
1910 | timeo = HZ/5; | ||
1911 | |||
1912 | if (signal_pending(current)) { | ||
1913 | err = sock_intr_errno(timeo); | ||
1914 | break; | ||
1915 | } | ||
1916 | |||
1917 | release_sock(sk); | ||
1918 | timeo = schedule_timeout(timeo); | ||
1919 | lock_sock(sk); | ||
1920 | set_current_state(TASK_INTERRUPTIBLE); | ||
1921 | |||
1922 | err = sock_error(sk); | ||
1923 | if (err) | ||
1924 | break; | ||
1925 | } | ||
1926 | set_current_state(TASK_RUNNING); | ||
1927 | remove_wait_queue(sk_sleep(sk), &wait); | ||
1928 | return err; | ||
1929 | } | ||
1930 | |||
1931 | static void l2cap_monitor_timeout(struct work_struct *work) | 1876 | static void l2cap_monitor_timeout(struct work_struct *work) |
1932 | { | 1877 | { |
1933 | struct l2cap_chan *chan = container_of(work, struct l2cap_chan, | 1878 | struct l2cap_chan *chan = container_of(work, struct l2cap_chan, |
@@ -2868,17 +2813,16 @@ static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) | |||
2868 | mutex_lock(&conn->chan_lock); | 2813 | mutex_lock(&conn->chan_lock); |
2869 | 2814 | ||
2870 | list_for_each_entry(chan, &conn->chan_l, list) { | 2815 | list_for_each_entry(chan, &conn->chan_l, list) { |
2871 | struct sock *sk = chan->sk; | ||
2872 | if (chan->chan_type != L2CAP_CHAN_RAW) | 2816 | if (chan->chan_type != L2CAP_CHAN_RAW) |
2873 | continue; | 2817 | continue; |
2874 | 2818 | ||
2875 | /* Don't send frame to the socket it came from */ | 2819 | /* Don't send frame to the channel it came from */ |
2876 | if (skb->sk == sk) | 2820 | if (bt_cb(skb)->chan == chan) |
2877 | continue; | 2821 | continue; |
2822 | |||
2878 | nskb = skb_clone(skb, GFP_KERNEL); | 2823 | nskb = skb_clone(skb, GFP_KERNEL); |
2879 | if (!nskb) | 2824 | if (!nskb) |
2880 | continue; | 2825 | continue; |
2881 | |||
2882 | if (chan->ops->recv(chan, nskb)) | 2826 | if (chan->ops->recv(chan, nskb)) |
2883 | kfree_skb(nskb); | 2827 | kfree_skb(nskb); |
2884 | } | 2828 | } |
@@ -3757,7 +3701,6 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, | |||
3757 | struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; | 3701 | struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; |
3758 | struct l2cap_conn_rsp rsp; | 3702 | struct l2cap_conn_rsp rsp; |
3759 | struct l2cap_chan *chan = NULL, *pchan; | 3703 | struct l2cap_chan *chan = NULL, *pchan; |
3760 | struct sock *parent, *sk = NULL; | ||
3761 | int result, status = L2CAP_CS_NO_INFO; | 3704 | int result, status = L2CAP_CS_NO_INFO; |
3762 | 3705 | ||
3763 | u16 dcid = 0, scid = __le16_to_cpu(req->scid); | 3706 | u16 dcid = 0, scid = __le16_to_cpu(req->scid); |
@@ -3773,10 +3716,8 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, | |||
3773 | goto sendresp; | 3716 | goto sendresp; |
3774 | } | 3717 | } |
3775 | 3718 | ||
3776 | parent = pchan->sk; | ||
3777 | |||
3778 | mutex_lock(&conn->chan_lock); | 3719 | mutex_lock(&conn->chan_lock); |
3779 | lock_sock(parent); | 3720 | l2cap_chan_lock(pchan); |
3780 | 3721 | ||
3781 | /* Check if the ACL is secure enough (if not SDP) */ | 3722 | /* Check if the ACL is secure enough (if not SDP) */ |
3782 | if (psm != __constant_cpu_to_le16(L2CAP_PSM_SDP) && | 3723 | if (psm != __constant_cpu_to_le16(L2CAP_PSM_SDP) && |
@@ -3796,8 +3737,6 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, | |||
3796 | if (!chan) | 3737 | if (!chan) |
3797 | goto response; | 3738 | goto response; |
3798 | 3739 | ||
3799 | sk = chan->sk; | ||
3800 | |||
3801 | /* For certain devices (ex: HID mouse), support for authentication, | 3740 | /* For certain devices (ex: HID mouse), support for authentication, |
3802 | * pairing and bonding is optional. For such devices, inorder to avoid | 3741 | * pairing and bonding is optional. For such devices, inorder to avoid |
3803 | * the ACL alive for too long after L2CAP disconnection, reset the ACL | 3742 | * the ACL alive for too long after L2CAP disconnection, reset the ACL |
@@ -3817,14 +3756,14 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, | |||
3817 | 3756 | ||
3818 | dcid = chan->scid; | 3757 | dcid = chan->scid; |
3819 | 3758 | ||
3820 | __set_chan_timer(chan, sk->sk_sndtimeo); | 3759 | __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); |
3821 | 3760 | ||
3822 | chan->ident = cmd->ident; | 3761 | chan->ident = cmd->ident; |
3823 | 3762 | ||
3824 | if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { | 3763 | if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { |
3825 | if (l2cap_chan_check_security(chan)) { | 3764 | if (l2cap_chan_check_security(chan)) { |
3826 | if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { | 3765 | if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { |
3827 | __l2cap_state_change(chan, BT_CONNECT2); | 3766 | l2cap_state_change(chan, BT_CONNECT2); |
3828 | result = L2CAP_CR_PEND; | 3767 | result = L2CAP_CR_PEND; |
3829 | status = L2CAP_CS_AUTHOR_PEND; | 3768 | status = L2CAP_CS_AUTHOR_PEND; |
3830 | chan->ops->defer(chan); | 3769 | chan->ops->defer(chan); |
@@ -3834,27 +3773,27 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, | |||
3834 | * physical link is up. | 3773 | * physical link is up. |
3835 | */ | 3774 | */ |
3836 | if (amp_id == AMP_ID_BREDR) { | 3775 | if (amp_id == AMP_ID_BREDR) { |
3837 | __l2cap_state_change(chan, BT_CONFIG); | 3776 | l2cap_state_change(chan, BT_CONFIG); |
3838 | result = L2CAP_CR_SUCCESS; | 3777 | result = L2CAP_CR_SUCCESS; |
3839 | } else { | 3778 | } else { |
3840 | __l2cap_state_change(chan, BT_CONNECT2); | 3779 | l2cap_state_change(chan, BT_CONNECT2); |
3841 | result = L2CAP_CR_PEND; | 3780 | result = L2CAP_CR_PEND; |
3842 | } | 3781 | } |
3843 | status = L2CAP_CS_NO_INFO; | 3782 | status = L2CAP_CS_NO_INFO; |
3844 | } | 3783 | } |
3845 | } else { | 3784 | } else { |
3846 | __l2cap_state_change(chan, BT_CONNECT2); | 3785 | l2cap_state_change(chan, BT_CONNECT2); |
3847 | result = L2CAP_CR_PEND; | 3786 | result = L2CAP_CR_PEND; |
3848 | status = L2CAP_CS_AUTHEN_PEND; | 3787 | status = L2CAP_CS_AUTHEN_PEND; |
3849 | } | 3788 | } |
3850 | } else { | 3789 | } else { |
3851 | __l2cap_state_change(chan, BT_CONNECT2); | 3790 | l2cap_state_change(chan, BT_CONNECT2); |
3852 | result = L2CAP_CR_PEND; | 3791 | result = L2CAP_CR_PEND; |
3853 | status = L2CAP_CS_NO_INFO; | 3792 | status = L2CAP_CS_NO_INFO; |
3854 | } | 3793 | } |
3855 | 3794 | ||
3856 | response: | 3795 | response: |
3857 | release_sock(parent); | 3796 | l2cap_chan_unlock(pchan); |
3858 | mutex_unlock(&conn->chan_lock); | 3797 | mutex_unlock(&conn->chan_lock); |
3859 | 3798 | ||
3860 | sendresp: | 3799 | sendresp: |
@@ -4010,6 +3949,18 @@ static void l2cap_send_efs_conf_rsp(struct l2cap_chan *chan, void *data, | |||
4010 | L2CAP_CONF_SUCCESS, flags), data); | 3949 | L2CAP_CONF_SUCCESS, flags), data); |
4011 | } | 3950 | } |
4012 | 3951 | ||
3952 | static void cmd_reject_invalid_cid(struct l2cap_conn *conn, u8 ident, | ||
3953 | u16 scid, u16 dcid) | ||
3954 | { | ||
3955 | struct l2cap_cmd_rej_cid rej; | ||
3956 | |||
3957 | rej.reason = __constant_cpu_to_le16(L2CAP_REJ_INVALID_CID); | ||
3958 | rej.scid = __cpu_to_le16(scid); | ||
3959 | rej.dcid = __cpu_to_le16(dcid); | ||
3960 | |||
3961 | l2cap_send_cmd(conn, ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej); | ||
3962 | } | ||
3963 | |||
4013 | static inline int l2cap_config_req(struct l2cap_conn *conn, | 3964 | static inline int l2cap_config_req(struct l2cap_conn *conn, |
4014 | struct l2cap_cmd_hdr *cmd, u16 cmd_len, | 3965 | struct l2cap_cmd_hdr *cmd, u16 cmd_len, |
4015 | u8 *data) | 3966 | u8 *data) |
@@ -4029,18 +3980,14 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, | |||
4029 | BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags); | 3980 | BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags); |
4030 | 3981 | ||
4031 | chan = l2cap_get_chan_by_scid(conn, dcid); | 3982 | chan = l2cap_get_chan_by_scid(conn, dcid); |
4032 | if (!chan) | 3983 | if (!chan) { |
4033 | return -EBADSLT; | 3984 | cmd_reject_invalid_cid(conn, cmd->ident, dcid, 0); |
3985 | return 0; | ||
3986 | } | ||
4034 | 3987 | ||
4035 | if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) { | 3988 | if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) { |
4036 | struct l2cap_cmd_rej_cid rej; | 3989 | cmd_reject_invalid_cid(conn, cmd->ident, chan->scid, |
4037 | 3990 | chan->dcid); | |
4038 | rej.reason = __constant_cpu_to_le16(L2CAP_REJ_INVALID_CID); | ||
4039 | rej.scid = cpu_to_le16(chan->scid); | ||
4040 | rej.dcid = cpu_to_le16(chan->dcid); | ||
4041 | |||
4042 | l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, | ||
4043 | sizeof(rej), &rej); | ||
4044 | goto unlock; | 3991 | goto unlock; |
4045 | } | 3992 | } |
4046 | 3993 | ||
@@ -4243,7 +4190,6 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, | |||
4243 | struct l2cap_disconn_rsp rsp; | 4190 | struct l2cap_disconn_rsp rsp; |
4244 | u16 dcid, scid; | 4191 | u16 dcid, scid; |
4245 | struct l2cap_chan *chan; | 4192 | struct l2cap_chan *chan; |
4246 | struct sock *sk; | ||
4247 | 4193 | ||
4248 | if (cmd_len != sizeof(*req)) | 4194 | if (cmd_len != sizeof(*req)) |
4249 | return -EPROTO; | 4195 | return -EPROTO; |
@@ -4258,20 +4204,17 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, | |||
4258 | chan = __l2cap_get_chan_by_scid(conn, dcid); | 4204 | chan = __l2cap_get_chan_by_scid(conn, dcid); |
4259 | if (!chan) { | 4205 | if (!chan) { |
4260 | mutex_unlock(&conn->chan_lock); | 4206 | mutex_unlock(&conn->chan_lock); |
4261 | return -EBADSLT; | 4207 | cmd_reject_invalid_cid(conn, cmd->ident, dcid, scid); |
4208 | return 0; | ||
4262 | } | 4209 | } |
4263 | 4210 | ||
4264 | l2cap_chan_lock(chan); | 4211 | l2cap_chan_lock(chan); |
4265 | 4212 | ||
4266 | sk = chan->sk; | ||
4267 | |||
4268 | rsp.dcid = cpu_to_le16(chan->scid); | 4213 | rsp.dcid = cpu_to_le16(chan->scid); |
4269 | rsp.scid = cpu_to_le16(chan->dcid); | 4214 | rsp.scid = cpu_to_le16(chan->dcid); |
4270 | l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp); | 4215 | l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp); |
4271 | 4216 | ||
4272 | lock_sock(sk); | 4217 | chan->ops->set_shutdown(chan); |
4273 | sk->sk_shutdown = SHUTDOWN_MASK; | ||
4274 | release_sock(sk); | ||
4275 | 4218 | ||
4276 | l2cap_chan_hold(chan); | 4219 | l2cap_chan_hold(chan); |
4277 | l2cap_chan_del(chan, ECONNRESET); | 4220 | l2cap_chan_del(chan, ECONNRESET); |
@@ -4491,7 +4434,9 @@ static int l2cap_create_channel_req(struct l2cap_conn *conn, | |||
4491 | &conn->hcon->dst); | 4434 | &conn->hcon->dst); |
4492 | if (!hs_hcon) { | 4435 | if (!hs_hcon) { |
4493 | hci_dev_put(hdev); | 4436 | hci_dev_put(hdev); |
4494 | return -EBADSLT; | 4437 | cmd_reject_invalid_cid(conn, cmd->ident, chan->scid, |
4438 | chan->dcid); | ||
4439 | return 0; | ||
4495 | } | 4440 | } |
4496 | 4441 | ||
4497 | BT_DBG("mgr %p bredr_chan %p hs_hcon %p", mgr, chan, hs_hcon); | 4442 | BT_DBG("mgr %p bredr_chan %p hs_hcon %p", mgr, chan, hs_hcon); |
@@ -4769,7 +4714,7 @@ static void l2cap_do_create(struct l2cap_chan *chan, int result, | |||
4769 | sizeof(rsp), &rsp); | 4714 | sizeof(rsp), &rsp); |
4770 | 4715 | ||
4771 | if (result == L2CAP_CR_SUCCESS) { | 4716 | if (result == L2CAP_CR_SUCCESS) { |
4772 | __l2cap_state_change(chan, BT_CONFIG); | 4717 | l2cap_state_change(chan, BT_CONFIG); |
4773 | set_bit(CONF_REQ_SENT, &chan->conf_state); | 4718 | set_bit(CONF_REQ_SENT, &chan->conf_state); |
4774 | l2cap_send_cmd(chan->conn, l2cap_get_ident(chan->conn), | 4719 | l2cap_send_cmd(chan->conn, l2cap_get_ident(chan->conn), |
4775 | L2CAP_CONF_REQ, | 4720 | L2CAP_CONF_REQ, |
@@ -5347,20 +5292,6 @@ static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn, | |||
5347 | } | 5292 | } |
5348 | } | 5293 | } |
5349 | 5294 | ||
5350 | static __le16 l2cap_err_to_reason(int err) | ||
5351 | { | ||
5352 | switch (err) { | ||
5353 | case -EBADSLT: | ||
5354 | return __constant_cpu_to_le16(L2CAP_REJ_INVALID_CID); | ||
5355 | case -EMSGSIZE: | ||
5356 | return __constant_cpu_to_le16(L2CAP_REJ_MTU_EXCEEDED); | ||
5357 | case -EINVAL: | ||
5358 | case -EPROTO: | ||
5359 | default: | ||
5360 | return __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); | ||
5361 | } | ||
5362 | } | ||
5363 | |||
5364 | static inline void l2cap_le_sig_channel(struct l2cap_conn *conn, | 5295 | static inline void l2cap_le_sig_channel(struct l2cap_conn *conn, |
5365 | struct sk_buff *skb) | 5296 | struct sk_buff *skb) |
5366 | { | 5297 | { |
@@ -5393,7 +5324,7 @@ static inline void l2cap_le_sig_channel(struct l2cap_conn *conn, | |||
5393 | 5324 | ||
5394 | BT_ERR("Wrong link type (%d)", err); | 5325 | BT_ERR("Wrong link type (%d)", err); |
5395 | 5326 | ||
5396 | rej.reason = l2cap_err_to_reason(err); | 5327 | rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); |
5397 | l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, | 5328 | l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, |
5398 | sizeof(rej), &rej); | 5329 | sizeof(rej), &rej); |
5399 | } | 5330 | } |
@@ -5438,7 +5369,7 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn, | |||
5438 | 5369 | ||
5439 | BT_ERR("Wrong link type (%d)", err); | 5370 | BT_ERR("Wrong link type (%d)", err); |
5440 | 5371 | ||
5441 | rej.reason = l2cap_err_to_reason(err); | 5372 | rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); |
5442 | l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, | 5373 | l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, |
5443 | sizeof(rej), &rej); | 5374 | sizeof(rej), &rej); |
5444 | } | 5375 | } |
@@ -6446,8 +6377,7 @@ static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, | |||
6446 | if (hcon->type != ACL_LINK) | 6377 | if (hcon->type != ACL_LINK) |
6447 | goto drop; | 6378 | goto drop; |
6448 | 6379 | ||
6449 | chan = l2cap_global_chan_by_psm(0, psm, &conn->hcon->src, | 6380 | chan = l2cap_global_chan_by_psm(0, psm, &hcon->src, &hcon->dst); |
6450 | &conn->hcon->dst); | ||
6451 | if (!chan) | 6381 | if (!chan) |
6452 | goto drop; | 6382 | goto drop; |
6453 | 6383 | ||
@@ -6460,7 +6390,7 @@ static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, | |||
6460 | goto drop; | 6390 | goto drop; |
6461 | 6391 | ||
6462 | /* Store remote BD_ADDR and PSM for msg_name */ | 6392 | /* Store remote BD_ADDR and PSM for msg_name */ |
6463 | bacpy(&bt_cb(skb)->bdaddr, &conn->hcon->dst); | 6393 | bacpy(&bt_cb(skb)->bdaddr, &hcon->dst); |
6464 | bt_cb(skb)->psm = psm; | 6394 | bt_cb(skb)->psm = psm; |
6465 | 6395 | ||
6466 | if (!chan->ops->recv(chan, skb)) | 6396 | if (!chan->ops->recv(chan, skb)) |
@@ -6480,12 +6410,15 @@ static void l2cap_att_channel(struct l2cap_conn *conn, | |||
6480 | goto drop; | 6410 | goto drop; |
6481 | 6411 | ||
6482 | chan = l2cap_global_chan_by_scid(BT_CONNECTED, L2CAP_CID_ATT, | 6412 | chan = l2cap_global_chan_by_scid(BT_CONNECTED, L2CAP_CID_ATT, |
6483 | &conn->hcon->src, &conn->hcon->dst); | 6413 | &hcon->src, &hcon->dst); |
6484 | if (!chan) | 6414 | if (!chan) |
6485 | goto drop; | 6415 | goto drop; |
6486 | 6416 | ||
6487 | BT_DBG("chan %p, len %d", chan, skb->len); | 6417 | BT_DBG("chan %p, len %d", chan, skb->len); |
6488 | 6418 | ||
6419 | if (hci_blacklist_lookup(hcon->hdev, &hcon->dst, hcon->dst_type)) | ||
6420 | goto drop; | ||
6421 | |||
6489 | if (chan->imtu < skb->len) | 6422 | if (chan->imtu < skb->len) |
6490 | goto drop; | 6423 | goto drop; |
6491 | 6424 | ||
@@ -6682,31 +6615,26 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) | |||
6682 | __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); | 6615 | __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); |
6683 | } | 6616 | } |
6684 | } else if (chan->state == BT_CONNECT2) { | 6617 | } else if (chan->state == BT_CONNECT2) { |
6685 | struct sock *sk = chan->sk; | ||
6686 | struct l2cap_conn_rsp rsp; | 6618 | struct l2cap_conn_rsp rsp; |
6687 | __u16 res, stat; | 6619 | __u16 res, stat; |
6688 | 6620 | ||
6689 | lock_sock(sk); | ||
6690 | |||
6691 | if (!status) { | 6621 | if (!status) { |
6692 | if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { | 6622 | if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { |
6693 | res = L2CAP_CR_PEND; | 6623 | res = L2CAP_CR_PEND; |
6694 | stat = L2CAP_CS_AUTHOR_PEND; | 6624 | stat = L2CAP_CS_AUTHOR_PEND; |
6695 | chan->ops->defer(chan); | 6625 | chan->ops->defer(chan); |
6696 | } else { | 6626 | } else { |
6697 | __l2cap_state_change(chan, BT_CONFIG); | 6627 | l2cap_state_change(chan, BT_CONFIG); |
6698 | res = L2CAP_CR_SUCCESS; | 6628 | res = L2CAP_CR_SUCCESS; |
6699 | stat = L2CAP_CS_NO_INFO; | 6629 | stat = L2CAP_CS_NO_INFO; |
6700 | } | 6630 | } |
6701 | } else { | 6631 | } else { |
6702 | __l2cap_state_change(chan, BT_DISCONN); | 6632 | l2cap_state_change(chan, BT_DISCONN); |
6703 | __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); | 6633 | __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); |
6704 | res = L2CAP_CR_SEC_BLOCK; | 6634 | res = L2CAP_CR_SEC_BLOCK; |
6705 | stat = L2CAP_CS_NO_INFO; | 6635 | stat = L2CAP_CS_NO_INFO; |
6706 | } | 6636 | } |
6707 | 6637 | ||
6708 | release_sock(sk); | ||
6709 | |||
6710 | rsp.scid = cpu_to_le16(chan->dcid); | 6638 | rsp.scid = cpu_to_le16(chan->dcid); |
6711 | rsp.dcid = cpu_to_le16(chan->scid); | 6639 | rsp.dcid = cpu_to_le16(chan->scid); |
6712 | rsp.result = cpu_to_le16(res); | 6640 | rsp.result = cpu_to_le16(res); |
@@ -6880,12 +6808,11 @@ int __init l2cap_init(void) | |||
6880 | if (err < 0) | 6808 | if (err < 0) |
6881 | return err; | 6809 | return err; |
6882 | 6810 | ||
6883 | if (bt_debugfs) { | 6811 | if (IS_ERR_OR_NULL(bt_debugfs)) |
6884 | l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs, | 6812 | return 0; |
6885 | NULL, &l2cap_debugfs_fops); | 6813 | |
6886 | if (!l2cap_debugfs) | 6814 | l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs, |
6887 | BT_ERR("Failed to create L2CAP debug file"); | 6815 | NULL, &l2cap_debugfs_fops); |
6888 | } | ||
6889 | 6816 | ||
6890 | return 0; | 6817 | return 0; |
6891 | } | 6818 | } |
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 5ffd75e20bde..7cc24d263caa 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -72,6 +72,15 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) | |||
72 | if (!bdaddr_type_is_valid(la.l2_bdaddr_type)) | 72 | if (!bdaddr_type_is_valid(la.l2_bdaddr_type)) |
73 | return -EINVAL; | 73 | return -EINVAL; |
74 | 74 | ||
75 | if (bdaddr_type_is_le(la.l2_bdaddr_type)) { | ||
76 | /* Connection oriented channels are not supported on LE */ | ||
77 | if (la.l2_psm) | ||
78 | return -EINVAL; | ||
79 | /* We only allow ATT user space socket */ | ||
80 | if (la.l2_cid != __constant_cpu_to_le16(L2CAP_CID_ATT)) | ||
81 | return -EINVAL; | ||
82 | } | ||
83 | |||
75 | lock_sock(sk); | 84 | lock_sock(sk); |
76 | 85 | ||
77 | if (sk->sk_state != BT_OPEN) { | 86 | if (sk->sk_state != BT_OPEN) { |
@@ -150,12 +159,44 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, | |||
150 | if (!bdaddr_type_is_valid(la.l2_bdaddr_type)) | 159 | if (!bdaddr_type_is_valid(la.l2_bdaddr_type)) |
151 | return -EINVAL; | 160 | return -EINVAL; |
152 | 161 | ||
153 | if (chan->src_type == BDADDR_BREDR && la.l2_bdaddr_type != BDADDR_BREDR) | 162 | /* Check that the socket wasn't bound to something that |
154 | return -EINVAL; | 163 | * conflicts with the address given to connect(). If chan->src |
164 | * is BDADDR_ANY it means bind() was never used, in which case | ||
165 | * chan->src_type and la.l2_bdaddr_type do not need to match. | ||
166 | */ | ||
167 | if (chan->src_type == BDADDR_BREDR && bacmp(&chan->src, BDADDR_ANY) && | ||
168 | bdaddr_type_is_le(la.l2_bdaddr_type)) { | ||
169 | /* Old user space versions will try to incorrectly bind | ||
170 | * the ATT socket using BDADDR_BREDR. We need to accept | ||
171 | * this and fix up the source address type only when | ||
172 | * both the source CID and destination CID indicate | ||
173 | * ATT. Anything else is an invalid combination. | ||
174 | */ | ||
175 | if (chan->scid != L2CAP_CID_ATT || | ||
176 | la.l2_cid != __constant_cpu_to_le16(L2CAP_CID_ATT)) | ||
177 | return -EINVAL; | ||
178 | |||
179 | /* We don't have the hdev available here to make a | ||
180 | * better decision on random vs public, but since all | ||
181 | * user space versions that exhibit this issue anyway do | ||
182 | * not support random local addresses assuming public | ||
183 | * here is good enough. | ||
184 | */ | ||
185 | chan->src_type = BDADDR_LE_PUBLIC; | ||
186 | } | ||
155 | 187 | ||
156 | if (chan->src_type != BDADDR_BREDR && la.l2_bdaddr_type == BDADDR_BREDR) | 188 | if (chan->src_type != BDADDR_BREDR && la.l2_bdaddr_type == BDADDR_BREDR) |
157 | return -EINVAL; | 189 | return -EINVAL; |
158 | 190 | ||
191 | if (bdaddr_type_is_le(la.l2_bdaddr_type)) { | ||
192 | /* Connection oriented channels are not supported on LE */ | ||
193 | if (la.l2_psm) | ||
194 | return -EINVAL; | ||
195 | /* We only allow ATT user space socket */ | ||
196 | if (la.l2_cid != __constant_cpu_to_le16(L2CAP_CID_ATT)) | ||
197 | return -EINVAL; | ||
198 | } | ||
199 | |||
159 | err = l2cap_chan_connect(chan, la.l2_psm, __le16_to_cpu(la.l2_cid), | 200 | err = l2cap_chan_connect(chan, la.l2_psm, __le16_to_cpu(la.l2_cid), |
160 | &la.l2_bdaddr, la.l2_bdaddr_type); | 201 | &la.l2_bdaddr, la.l2_bdaddr_type); |
161 | if (err) | 202 | if (err) |
@@ -879,6 +920,38 @@ static void l2cap_sock_kill(struct sock *sk) | |||
879 | sock_put(sk); | 920 | sock_put(sk); |
880 | } | 921 | } |
881 | 922 | ||
923 | static int __l2cap_wait_ack(struct sock *sk) | ||
924 | { | ||
925 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; | ||
926 | DECLARE_WAITQUEUE(wait, current); | ||
927 | int err = 0; | ||
928 | int timeo = HZ/5; | ||
929 | |||
930 | add_wait_queue(sk_sleep(sk), &wait); | ||
931 | set_current_state(TASK_INTERRUPTIBLE); | ||
932 | while (chan->unacked_frames > 0 && chan->conn) { | ||
933 | if (!timeo) | ||
934 | timeo = HZ/5; | ||
935 | |||
936 | if (signal_pending(current)) { | ||
937 | err = sock_intr_errno(timeo); | ||
938 | break; | ||
939 | } | ||
940 | |||
941 | release_sock(sk); | ||
942 | timeo = schedule_timeout(timeo); | ||
943 | lock_sock(sk); | ||
944 | set_current_state(TASK_INTERRUPTIBLE); | ||
945 | |||
946 | err = sock_error(sk); | ||
947 | if (err) | ||
948 | break; | ||
949 | } | ||
950 | set_current_state(TASK_RUNNING); | ||
951 | remove_wait_queue(sk_sleep(sk), &wait); | ||
952 | return err; | ||
953 | } | ||
954 | |||
882 | static int l2cap_sock_shutdown(struct socket *sock, int how) | 955 | static int l2cap_sock_shutdown(struct socket *sock, int how) |
883 | { | 956 | { |
884 | struct sock *sk = sock->sk; | 957 | struct sock *sk = sock->sk; |
@@ -969,6 +1042,8 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan) | |||
969 | { | 1042 | { |
970 | struct sock *sk, *parent = chan->data; | 1043 | struct sock *sk, *parent = chan->data; |
971 | 1044 | ||
1045 | lock_sock(parent); | ||
1046 | |||
972 | /* Check for backlog size */ | 1047 | /* Check for backlog size */ |
973 | if (sk_acceptq_is_full(parent)) { | 1048 | if (sk_acceptq_is_full(parent)) { |
974 | BT_DBG("backlog full %d", parent->sk_ack_backlog); | 1049 | BT_DBG("backlog full %d", parent->sk_ack_backlog); |
@@ -986,6 +1061,8 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan) | |||
986 | 1061 | ||
987 | bt_accept_enqueue(parent, sk); | 1062 | bt_accept_enqueue(parent, sk); |
988 | 1063 | ||
1064 | release_sock(parent); | ||
1065 | |||
989 | return l2cap_pi(sk)->chan; | 1066 | return l2cap_pi(sk)->chan; |
990 | } | 1067 | } |
991 | 1068 | ||
@@ -1072,26 +1149,33 @@ static void l2cap_sock_teardown_cb(struct l2cap_chan *chan, int err) | |||
1072 | release_sock(sk); | 1149 | release_sock(sk); |
1073 | } | 1150 | } |
1074 | 1151 | ||
1075 | static void l2cap_sock_state_change_cb(struct l2cap_chan *chan, int state) | 1152 | static void l2cap_sock_state_change_cb(struct l2cap_chan *chan, int state, |
1153 | int err) | ||
1076 | { | 1154 | { |
1077 | struct sock *sk = chan->data; | 1155 | struct sock *sk = chan->data; |
1078 | 1156 | ||
1079 | sk->sk_state = state; | 1157 | sk->sk_state = state; |
1158 | |||
1159 | if (err) | ||
1160 | sk->sk_err = err; | ||
1080 | } | 1161 | } |
1081 | 1162 | ||
1082 | static struct sk_buff *l2cap_sock_alloc_skb_cb(struct l2cap_chan *chan, | 1163 | static struct sk_buff *l2cap_sock_alloc_skb_cb(struct l2cap_chan *chan, |
1083 | unsigned long len, int nb) | 1164 | unsigned long len, int nb) |
1084 | { | 1165 | { |
1166 | struct sock *sk = chan->data; | ||
1085 | struct sk_buff *skb; | 1167 | struct sk_buff *skb; |
1086 | int err; | 1168 | int err; |
1087 | 1169 | ||
1088 | l2cap_chan_unlock(chan); | 1170 | l2cap_chan_unlock(chan); |
1089 | skb = bt_skb_send_alloc(chan->sk, len, nb, &err); | 1171 | skb = bt_skb_send_alloc(sk, len, nb, &err); |
1090 | l2cap_chan_lock(chan); | 1172 | l2cap_chan_lock(chan); |
1091 | 1173 | ||
1092 | if (!skb) | 1174 | if (!skb) |
1093 | return ERR_PTR(err); | 1175 | return ERR_PTR(err); |
1094 | 1176 | ||
1177 | bt_cb(skb)->chan = chan; | ||
1178 | |||
1095 | return skb; | 1179 | return skb; |
1096 | } | 1180 | } |
1097 | 1181 | ||
@@ -1117,11 +1201,15 @@ static void l2cap_sock_ready_cb(struct l2cap_chan *chan) | |||
1117 | 1201 | ||
1118 | static void l2cap_sock_defer_cb(struct l2cap_chan *chan) | 1202 | static void l2cap_sock_defer_cb(struct l2cap_chan *chan) |
1119 | { | 1203 | { |
1120 | struct sock *sk = chan->data; | 1204 | struct sock *parent, *sk = chan->data; |
1121 | struct sock *parent = bt_sk(sk)->parent; | 1205 | |
1206 | lock_sock(sk); | ||
1122 | 1207 | ||
1208 | parent = bt_sk(sk)->parent; | ||
1123 | if (parent) | 1209 | if (parent) |
1124 | parent->sk_data_ready(parent, 0); | 1210 | parent->sk_data_ready(parent, 0); |
1211 | |||
1212 | release_sock(sk); | ||
1125 | } | 1213 | } |
1126 | 1214 | ||
1127 | static void l2cap_sock_resume_cb(struct l2cap_chan *chan) | 1215 | static void l2cap_sock_resume_cb(struct l2cap_chan *chan) |
@@ -1132,6 +1220,22 @@ static void l2cap_sock_resume_cb(struct l2cap_chan *chan) | |||
1132 | sk->sk_state_change(sk); | 1220 | sk->sk_state_change(sk); |
1133 | } | 1221 | } |
1134 | 1222 | ||
1223 | static void l2cap_sock_set_shutdown_cb(struct l2cap_chan *chan) | ||
1224 | { | ||
1225 | struct sock *sk = chan->data; | ||
1226 | |||
1227 | lock_sock(sk); | ||
1228 | sk->sk_shutdown = SHUTDOWN_MASK; | ||
1229 | release_sock(sk); | ||
1230 | } | ||
1231 | |||
1232 | static long l2cap_sock_get_sndtimeo_cb(struct l2cap_chan *chan) | ||
1233 | { | ||
1234 | struct sock *sk = chan->data; | ||
1235 | |||
1236 | return sk->sk_sndtimeo; | ||
1237 | } | ||
1238 | |||
1135 | static struct l2cap_ops l2cap_chan_ops = { | 1239 | static struct l2cap_ops l2cap_chan_ops = { |
1136 | .name = "L2CAP Socket Interface", | 1240 | .name = "L2CAP Socket Interface", |
1137 | .new_connection = l2cap_sock_new_connection_cb, | 1241 | .new_connection = l2cap_sock_new_connection_cb, |
@@ -1142,6 +1246,8 @@ static struct l2cap_ops l2cap_chan_ops = { | |||
1142 | .ready = l2cap_sock_ready_cb, | 1246 | .ready = l2cap_sock_ready_cb, |
1143 | .defer = l2cap_sock_defer_cb, | 1247 | .defer = l2cap_sock_defer_cb, |
1144 | .resume = l2cap_sock_resume_cb, | 1248 | .resume = l2cap_sock_resume_cb, |
1249 | .set_shutdown = l2cap_sock_set_shutdown_cb, | ||
1250 | .get_sndtimeo = l2cap_sock_get_sndtimeo_cb, | ||
1145 | .alloc_skb = l2cap_sock_alloc_skb_cb, | 1251 | .alloc_skb = l2cap_sock_alloc_skb_cb, |
1146 | }; | 1252 | }; |
1147 | 1253 | ||
@@ -1268,8 +1374,6 @@ static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, | |||
1268 | 1374 | ||
1269 | l2cap_chan_hold(chan); | 1375 | l2cap_chan_hold(chan); |
1270 | 1376 | ||
1271 | chan->sk = sk; | ||
1272 | |||
1273 | l2cap_pi(sk)->chan = chan; | 1377 | l2cap_pi(sk)->chan = chan; |
1274 | 1378 | ||
1275 | return sk; | 1379 | return sk; |
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 861e389f4b4c..074d83690a41 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -536,6 +536,156 @@ static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len) | |||
536 | return ptr; | 536 | return ptr; |
537 | } | 537 | } |
538 | 538 | ||
539 | static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev) | ||
540 | { | ||
541 | struct pending_cmd *cmd; | ||
542 | |||
543 | list_for_each_entry(cmd, &hdev->mgmt_pending, list) { | ||
544 | if (cmd->opcode == opcode) | ||
545 | return cmd; | ||
546 | } | ||
547 | |||
548 | return NULL; | ||
549 | } | ||
550 | |||
551 | static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr) | ||
552 | { | ||
553 | u8 ad_len = 0; | ||
554 | size_t name_len; | ||
555 | |||
556 | name_len = strlen(hdev->dev_name); | ||
557 | if (name_len > 0) { | ||
558 | size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2; | ||
559 | |||
560 | if (name_len > max_len) { | ||
561 | name_len = max_len; | ||
562 | ptr[1] = EIR_NAME_SHORT; | ||
563 | } else | ||
564 | ptr[1] = EIR_NAME_COMPLETE; | ||
565 | |||
566 | ptr[0] = name_len + 1; | ||
567 | |||
568 | memcpy(ptr + 2, hdev->dev_name, name_len); | ||
569 | |||
570 | ad_len += (name_len + 2); | ||
571 | ptr += (name_len + 2); | ||
572 | } | ||
573 | |||
574 | return ad_len; | ||
575 | } | ||
576 | |||
577 | static void update_scan_rsp_data(struct hci_request *req) | ||
578 | { | ||
579 | struct hci_dev *hdev = req->hdev; | ||
580 | struct hci_cp_le_set_scan_rsp_data cp; | ||
581 | u8 len; | ||
582 | |||
583 | if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) | ||
584 | return; | ||
585 | |||
586 | memset(&cp, 0, sizeof(cp)); | ||
587 | |||
588 | len = create_scan_rsp_data(hdev, cp.data); | ||
589 | |||
590 | if (hdev->scan_rsp_data_len == len && | ||
591 | memcmp(cp.data, hdev->scan_rsp_data, len) == 0) | ||
592 | return; | ||
593 | |||
594 | memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data)); | ||
595 | hdev->scan_rsp_data_len = len; | ||
596 | |||
597 | cp.length = len; | ||
598 | |||
599 | hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp); | ||
600 | } | ||
601 | |||
602 | static u8 get_adv_discov_flags(struct hci_dev *hdev) | ||
603 | { | ||
604 | struct pending_cmd *cmd; | ||
605 | |||
606 | /* If there's a pending mgmt command the flags will not yet have | ||
607 | * their final values, so check for this first. | ||
608 | */ | ||
609 | cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev); | ||
610 | if (cmd) { | ||
611 | struct mgmt_mode *cp = cmd->param; | ||
612 | if (cp->val == 0x01) | ||
613 | return LE_AD_GENERAL; | ||
614 | else if (cp->val == 0x02) | ||
615 | return LE_AD_LIMITED; | ||
616 | } else { | ||
617 | if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags)) | ||
618 | return LE_AD_LIMITED; | ||
619 | else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) | ||
620 | return LE_AD_GENERAL; | ||
621 | } | ||
622 | |||
623 | return 0; | ||
624 | } | ||
625 | |||
626 | static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr) | ||
627 | { | ||
628 | u8 ad_len = 0, flags = 0; | ||
629 | |||
630 | flags |= get_adv_discov_flags(hdev); | ||
631 | |||
632 | if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) { | ||
633 | if (lmp_le_br_capable(hdev)) | ||
634 | flags |= LE_AD_SIM_LE_BREDR_CTRL; | ||
635 | if (lmp_host_le_br_capable(hdev)) | ||
636 | flags |= LE_AD_SIM_LE_BREDR_HOST; | ||
637 | } else { | ||
638 | flags |= LE_AD_NO_BREDR; | ||
639 | } | ||
640 | |||
641 | if (flags) { | ||
642 | BT_DBG("adv flags 0x%02x", flags); | ||
643 | |||
644 | ptr[0] = 2; | ||
645 | ptr[1] = EIR_FLAGS; | ||
646 | ptr[2] = flags; | ||
647 | |||
648 | ad_len += 3; | ||
649 | ptr += 3; | ||
650 | } | ||
651 | |||
652 | if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) { | ||
653 | ptr[0] = 2; | ||
654 | ptr[1] = EIR_TX_POWER; | ||
655 | ptr[2] = (u8) hdev->adv_tx_power; | ||
656 | |||
657 | ad_len += 3; | ||
658 | ptr += 3; | ||
659 | } | ||
660 | |||
661 | return ad_len; | ||
662 | } | ||
663 | |||
664 | static void update_adv_data(struct hci_request *req) | ||
665 | { | ||
666 | struct hci_dev *hdev = req->hdev; | ||
667 | struct hci_cp_le_set_adv_data cp; | ||
668 | u8 len; | ||
669 | |||
670 | if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) | ||
671 | return; | ||
672 | |||
673 | memset(&cp, 0, sizeof(cp)); | ||
674 | |||
675 | len = create_adv_data(hdev, cp.data); | ||
676 | |||
677 | if (hdev->adv_data_len == len && | ||
678 | memcmp(cp.data, hdev->adv_data, len) == 0) | ||
679 | return; | ||
680 | |||
681 | memcpy(hdev->adv_data, cp.data, sizeof(cp.data)); | ||
682 | hdev->adv_data_len = len; | ||
683 | |||
684 | cp.length = len; | ||
685 | |||
686 | hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp); | ||
687 | } | ||
688 | |||
539 | static void create_eir(struct hci_dev *hdev, u8 *data) | 689 | static void create_eir(struct hci_dev *hdev, u8 *data) |
540 | { | 690 | { |
541 | u8 *ptr = data; | 691 | u8 *ptr = data; |
@@ -634,6 +784,9 @@ static void update_class(struct hci_request *req) | |||
634 | if (!hdev_is_powered(hdev)) | 784 | if (!hdev_is_powered(hdev)) |
635 | return; | 785 | return; |
636 | 786 | ||
787 | if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) | ||
788 | return; | ||
789 | |||
637 | if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) | 790 | if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) |
638 | return; | 791 | return; |
639 | 792 | ||
@@ -641,6 +794,9 @@ static void update_class(struct hci_request *req) | |||
641 | cod[1] = hdev->major_class; | 794 | cod[1] = hdev->major_class; |
642 | cod[2] = get_service_classes(hdev); | 795 | cod[2] = get_service_classes(hdev); |
643 | 796 | ||
797 | if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags)) | ||
798 | cod[1] |= 0x20; | ||
799 | |||
644 | if (memcmp(cod, hdev->dev_class, 3) == 0) | 800 | if (memcmp(cod, hdev->dev_class, 3) == 0) |
645 | return; | 801 | return; |
646 | 802 | ||
@@ -765,18 +921,6 @@ static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev, | |||
765 | } | 921 | } |
766 | } | 922 | } |
767 | 923 | ||
768 | static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev) | ||
769 | { | ||
770 | struct pending_cmd *cmd; | ||
771 | |||
772 | list_for_each_entry(cmd, &hdev->mgmt_pending, list) { | ||
773 | if (cmd->opcode == opcode) | ||
774 | return cmd; | ||
775 | } | ||
776 | |||
777 | return NULL; | ||
778 | } | ||
779 | |||
780 | static void mgmt_pending_remove(struct pending_cmd *cmd) | 924 | static void mgmt_pending_remove(struct pending_cmd *cmd) |
781 | { | 925 | { |
782 | list_del(&cmd->list); | 926 | list_del(&cmd->list); |
@@ -939,6 +1083,7 @@ static void set_discoverable_complete(struct hci_dev *hdev, u8 status) | |||
939 | { | 1083 | { |
940 | struct pending_cmd *cmd; | 1084 | struct pending_cmd *cmd; |
941 | struct mgmt_mode *cp; | 1085 | struct mgmt_mode *cp; |
1086 | struct hci_request req; | ||
942 | bool changed; | 1087 | bool changed; |
943 | 1088 | ||
944 | BT_DBG("status 0x%02x", status); | 1089 | BT_DBG("status 0x%02x", status); |
@@ -952,22 +1097,38 @@ static void set_discoverable_complete(struct hci_dev *hdev, u8 status) | |||
952 | if (status) { | 1097 | if (status) { |
953 | u8 mgmt_err = mgmt_status(status); | 1098 | u8 mgmt_err = mgmt_status(status); |
954 | cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err); | 1099 | cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err); |
1100 | clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags); | ||
955 | goto remove_cmd; | 1101 | goto remove_cmd; |
956 | } | 1102 | } |
957 | 1103 | ||
958 | cp = cmd->param; | 1104 | cp = cmd->param; |
959 | if (cp->val) | 1105 | if (cp->val) { |
960 | changed = !test_and_set_bit(HCI_DISCOVERABLE, | 1106 | changed = !test_and_set_bit(HCI_DISCOVERABLE, |
961 | &hdev->dev_flags); | 1107 | &hdev->dev_flags); |
962 | else | 1108 | |
1109 | if (hdev->discov_timeout > 0) { | ||
1110 | int to = msecs_to_jiffies(hdev->discov_timeout * 1000); | ||
1111 | queue_delayed_work(hdev->workqueue, &hdev->discov_off, | ||
1112 | to); | ||
1113 | } | ||
1114 | } else { | ||
963 | changed = test_and_clear_bit(HCI_DISCOVERABLE, | 1115 | changed = test_and_clear_bit(HCI_DISCOVERABLE, |
964 | &hdev->dev_flags); | 1116 | &hdev->dev_flags); |
1117 | } | ||
965 | 1118 | ||
966 | send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev); | 1119 | send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev); |
967 | 1120 | ||
968 | if (changed) | 1121 | if (changed) |
969 | new_settings(hdev, cmd->sk); | 1122 | new_settings(hdev, cmd->sk); |
970 | 1123 | ||
1124 | /* When the discoverable mode gets changed, make sure | ||
1125 | * that class of device has the limited discoverable | ||
1126 | * bit correctly set. | ||
1127 | */ | ||
1128 | hci_req_init(&req, hdev); | ||
1129 | update_class(&req); | ||
1130 | hci_req_run(&req, NULL); | ||
1131 | |||
971 | remove_cmd: | 1132 | remove_cmd: |
972 | mgmt_pending_remove(cmd); | 1133 | mgmt_pending_remove(cmd); |
973 | 1134 | ||
@@ -982,22 +1143,27 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
982 | struct pending_cmd *cmd; | 1143 | struct pending_cmd *cmd; |
983 | struct hci_request req; | 1144 | struct hci_request req; |
984 | u16 timeout; | 1145 | u16 timeout; |
985 | u8 scan, status; | 1146 | u8 scan; |
986 | int err; | 1147 | int err; |
987 | 1148 | ||
988 | BT_DBG("request for %s", hdev->name); | 1149 | BT_DBG("request for %s", hdev->name); |
989 | 1150 | ||
990 | status = mgmt_bredr_support(hdev); | 1151 | if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) && |
991 | if (status) | 1152 | !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) |
992 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE, | 1153 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE, |
993 | status); | 1154 | MGMT_STATUS_REJECTED); |
994 | 1155 | ||
995 | if (cp->val != 0x00 && cp->val != 0x01) | 1156 | if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02) |
996 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE, | 1157 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE, |
997 | MGMT_STATUS_INVALID_PARAMS); | 1158 | MGMT_STATUS_INVALID_PARAMS); |
998 | 1159 | ||
999 | timeout = __le16_to_cpu(cp->timeout); | 1160 | timeout = __le16_to_cpu(cp->timeout); |
1000 | if (!cp->val && timeout > 0) | 1161 | |
1162 | /* Disabling discoverable requires that no timeout is set, | ||
1163 | * and enabling limited discoverable requires a timeout. | ||
1164 | */ | ||
1165 | if ((cp->val == 0x00 && timeout > 0) || | ||
1166 | (cp->val == 0x02 && timeout == 0)) | ||
1001 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE, | 1167 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE, |
1002 | MGMT_STATUS_INVALID_PARAMS); | 1168 | MGMT_STATUS_INVALID_PARAMS); |
1003 | 1169 | ||
@@ -1025,6 +1191,10 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1025 | if (!hdev_is_powered(hdev)) { | 1191 | if (!hdev_is_powered(hdev)) { |
1026 | bool changed = false; | 1192 | bool changed = false; |
1027 | 1193 | ||
1194 | /* Setting limited discoverable when powered off is | ||
1195 | * not a valid operation since it requires a timeout | ||
1196 | * and so no need to check HCI_LIMITED_DISCOVERABLE. | ||
1197 | */ | ||
1028 | if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) { | 1198 | if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) { |
1029 | change_bit(HCI_DISCOVERABLE, &hdev->dev_flags); | 1199 | change_bit(HCI_DISCOVERABLE, &hdev->dev_flags); |
1030 | changed = true; | 1200 | changed = true; |
@@ -1040,16 +1210,20 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1040 | goto failed; | 1210 | goto failed; |
1041 | } | 1211 | } |
1042 | 1212 | ||
1043 | if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) { | 1213 | /* If the current mode is the same, then just update the timeout |
1044 | if (hdev->discov_timeout > 0) { | 1214 | * value with the new value. And if only the timeout gets updated, |
1045 | cancel_delayed_work(&hdev->discov_off); | 1215 | * then no need for any HCI transactions. |
1046 | hdev->discov_timeout = 0; | 1216 | */ |
1047 | } | 1217 | if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) && |
1218 | (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE, | ||
1219 | &hdev->dev_flags)) { | ||
1220 | cancel_delayed_work(&hdev->discov_off); | ||
1221 | hdev->discov_timeout = timeout; | ||
1048 | 1222 | ||
1049 | if (cp->val && timeout > 0) { | 1223 | if (cp->val && hdev->discov_timeout > 0) { |
1050 | hdev->discov_timeout = timeout; | 1224 | int to = msecs_to_jiffies(hdev->discov_timeout * 1000); |
1051 | queue_delayed_work(hdev->workqueue, &hdev->discov_off, | 1225 | queue_delayed_work(hdev->workqueue, &hdev->discov_off, |
1052 | msecs_to_jiffies(hdev->discov_timeout * 1000)); | 1226 | to); |
1053 | } | 1227 | } |
1054 | 1228 | ||
1055 | err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev); | 1229 | err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev); |
@@ -1062,24 +1236,66 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1062 | goto failed; | 1236 | goto failed; |
1063 | } | 1237 | } |
1064 | 1238 | ||
1239 | /* Cancel any potential discoverable timeout that might be | ||
1240 | * still active and store new timeout value. The arming of | ||
1241 | * the timeout happens in the complete handler. | ||
1242 | */ | ||
1243 | cancel_delayed_work(&hdev->discov_off); | ||
1244 | hdev->discov_timeout = timeout; | ||
1245 | |||
1246 | /* Limited discoverable mode */ | ||
1247 | if (cp->val == 0x02) | ||
1248 | set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags); | ||
1249 | else | ||
1250 | clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags); | ||
1251 | |||
1065 | hci_req_init(&req, hdev); | 1252 | hci_req_init(&req, hdev); |
1066 | 1253 | ||
1254 | /* The procedure for LE-only controllers is much simpler - just | ||
1255 | * update the advertising data. | ||
1256 | */ | ||
1257 | if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) | ||
1258 | goto update_ad; | ||
1259 | |||
1067 | scan = SCAN_PAGE; | 1260 | scan = SCAN_PAGE; |
1068 | 1261 | ||
1069 | if (cp->val) | 1262 | if (cp->val) { |
1263 | struct hci_cp_write_current_iac_lap hci_cp; | ||
1264 | |||
1265 | if (cp->val == 0x02) { | ||
1266 | /* Limited discoverable mode */ | ||
1267 | hci_cp.num_iac = 2; | ||
1268 | hci_cp.iac_lap[0] = 0x00; /* LIAC */ | ||
1269 | hci_cp.iac_lap[1] = 0x8b; | ||
1270 | hci_cp.iac_lap[2] = 0x9e; | ||
1271 | hci_cp.iac_lap[3] = 0x33; /* GIAC */ | ||
1272 | hci_cp.iac_lap[4] = 0x8b; | ||
1273 | hci_cp.iac_lap[5] = 0x9e; | ||
1274 | } else { | ||
1275 | /* General discoverable mode */ | ||
1276 | hci_cp.num_iac = 1; | ||
1277 | hci_cp.iac_lap[0] = 0x33; /* GIAC */ | ||
1278 | hci_cp.iac_lap[1] = 0x8b; | ||
1279 | hci_cp.iac_lap[2] = 0x9e; | ||
1280 | } | ||
1281 | |||
1282 | hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP, | ||
1283 | (hci_cp.num_iac * 3) + 1, &hci_cp); | ||
1284 | |||
1070 | scan |= SCAN_INQUIRY; | 1285 | scan |= SCAN_INQUIRY; |
1071 | else | 1286 | } else { |
1072 | cancel_delayed_work(&hdev->discov_off); | 1287 | clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags); |
1288 | } | ||
1073 | 1289 | ||
1074 | hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); | 1290 | hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan); |
1291 | |||
1292 | update_ad: | ||
1293 | update_adv_data(&req); | ||
1075 | 1294 | ||
1076 | err = hci_req_run(&req, set_discoverable_complete); | 1295 | err = hci_req_run(&req, set_discoverable_complete); |
1077 | if (err < 0) | 1296 | if (err < 0) |
1078 | mgmt_pending_remove(cmd); | 1297 | mgmt_pending_remove(cmd); |
1079 | 1298 | ||
1080 | if (cp->val) | ||
1081 | hdev->discov_timeout = timeout; | ||
1082 | |||
1083 | failed: | 1299 | failed: |
1084 | hci_dev_unlock(hdev); | 1300 | hci_dev_unlock(hdev); |
1085 | return err; | 1301 | return err; |
@@ -1091,6 +1307,9 @@ static void write_fast_connectable(struct hci_request *req, bool enable) | |||
1091 | struct hci_cp_write_page_scan_activity acp; | 1307 | struct hci_cp_write_page_scan_activity acp; |
1092 | u8 type; | 1308 | u8 type; |
1093 | 1309 | ||
1310 | if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) | ||
1311 | return; | ||
1312 | |||
1094 | if (hdev->hci_ver < BLUETOOTH_VER_1_2) | 1313 | if (hdev->hci_ver < BLUETOOTH_VER_1_2) |
1095 | return; | 1314 | return; |
1096 | 1315 | ||
@@ -1146,10 +1365,7 @@ static void enable_advertising(struct hci_request *req) | |||
1146 | cp.min_interval = __constant_cpu_to_le16(0x0800); | 1365 | cp.min_interval = __constant_cpu_to_le16(0x0800); |
1147 | cp.max_interval = __constant_cpu_to_le16(0x0800); | 1366 | cp.max_interval = __constant_cpu_to_le16(0x0800); |
1148 | cp.type = get_adv_type(hdev); | 1367 | cp.type = get_adv_type(hdev); |
1149 | if (bacmp(&hdev->bdaddr, BDADDR_ANY)) | 1368 | cp.own_address_type = hdev->own_addr_type; |
1150 | cp.own_address_type = ADDR_LE_DEV_PUBLIC; | ||
1151 | else | ||
1152 | cp.own_address_type = ADDR_LE_DEV_RANDOM; | ||
1153 | cp.channel_map = 0x07; | 1369 | cp.channel_map = 0x07; |
1154 | 1370 | ||
1155 | hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp); | 1371 | hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp); |
@@ -1202,6 +1418,32 @@ unlock: | |||
1202 | hci_dev_unlock(hdev); | 1418 | hci_dev_unlock(hdev); |
1203 | } | 1419 | } |
1204 | 1420 | ||
1421 | static int set_connectable_update_settings(struct hci_dev *hdev, | ||
1422 | struct sock *sk, u8 val) | ||
1423 | { | ||
1424 | bool changed = false; | ||
1425 | int err; | ||
1426 | |||
1427 | if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) | ||
1428 | changed = true; | ||
1429 | |||
1430 | if (val) { | ||
1431 | set_bit(HCI_CONNECTABLE, &hdev->dev_flags); | ||
1432 | } else { | ||
1433 | clear_bit(HCI_CONNECTABLE, &hdev->dev_flags); | ||
1434 | clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags); | ||
1435 | } | ||
1436 | |||
1437 | err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev); | ||
1438 | if (err < 0) | ||
1439 | return err; | ||
1440 | |||
1441 | if (changed) | ||
1442 | return new_settings(hdev, sk); | ||
1443 | |||
1444 | return 0; | ||
1445 | } | ||
1446 | |||
1205 | static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, | 1447 | static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, |
1206 | u16 len) | 1448 | u16 len) |
1207 | { | 1449 | { |
@@ -1225,25 +1467,7 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1225 | hci_dev_lock(hdev); | 1467 | hci_dev_lock(hdev); |
1226 | 1468 | ||
1227 | if (!hdev_is_powered(hdev)) { | 1469 | if (!hdev_is_powered(hdev)) { |
1228 | bool changed = false; | 1470 | err = set_connectable_update_settings(hdev, sk, cp->val); |
1229 | |||
1230 | if (!!cp->val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) | ||
1231 | changed = true; | ||
1232 | |||
1233 | if (cp->val) { | ||
1234 | set_bit(HCI_CONNECTABLE, &hdev->dev_flags); | ||
1235 | } else { | ||
1236 | clear_bit(HCI_CONNECTABLE, &hdev->dev_flags); | ||
1237 | clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags); | ||
1238 | } | ||
1239 | |||
1240 | err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev); | ||
1241 | if (err < 0) | ||
1242 | goto failed; | ||
1243 | |||
1244 | if (changed) | ||
1245 | err = new_settings(hdev, sk); | ||
1246 | |||
1247 | goto failed; | 1471 | goto failed; |
1248 | } | 1472 | } |
1249 | 1473 | ||
@@ -1262,16 +1486,24 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1262 | 1486 | ||
1263 | hci_req_init(&req, hdev); | 1487 | hci_req_init(&req, hdev); |
1264 | 1488 | ||
1265 | if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) && | 1489 | /* If BR/EDR is not enabled and we disable advertising as a |
1266 | cp->val != test_bit(HCI_PSCAN, &hdev->flags)) { | 1490 | * by-product of disabling connectable, we need to update the |
1267 | 1491 | * advertising flags. | |
1492 | */ | ||
1493 | if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) { | ||
1494 | if (!cp->val) { | ||
1495 | clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags); | ||
1496 | clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags); | ||
1497 | } | ||
1498 | update_adv_data(&req); | ||
1499 | } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) { | ||
1268 | if (cp->val) { | 1500 | if (cp->val) { |
1269 | scan = SCAN_PAGE; | 1501 | scan = SCAN_PAGE; |
1270 | } else { | 1502 | } else { |
1271 | scan = 0; | 1503 | scan = 0; |
1272 | 1504 | ||
1273 | if (test_bit(HCI_ISCAN, &hdev->flags) && | 1505 | if (test_bit(HCI_ISCAN, &hdev->flags) && |
1274 | hdev->discov_timeout > 0) | 1506 | hdev->discov_timeout > 0) |
1275 | cancel_delayed_work(&hdev->discov_off); | 1507 | cancel_delayed_work(&hdev->discov_off); |
1276 | } | 1508 | } |
1277 | 1509 | ||
@@ -1297,8 +1529,8 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1297 | if (err < 0) { | 1529 | if (err < 0) { |
1298 | mgmt_pending_remove(cmd); | 1530 | mgmt_pending_remove(cmd); |
1299 | if (err == -ENODATA) | 1531 | if (err == -ENODATA) |
1300 | err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, | 1532 | err = set_connectable_update_settings(hdev, sk, |
1301 | hdev); | 1533 | cp->val); |
1302 | goto failed; | 1534 | goto failed; |
1303 | } | 1535 | } |
1304 | 1536 | ||
@@ -1556,6 +1788,24 @@ static void le_enable_complete(struct hci_dev *hdev, u8 status) | |||
1556 | 1788 | ||
1557 | if (match.sk) | 1789 | if (match.sk) |
1558 | sock_put(match.sk); | 1790 | sock_put(match.sk); |
1791 | |||
1792 | /* Make sure the controller has a good default for | ||
1793 | * advertising data. Restrict the update to when LE | ||
1794 | * has actually been enabled. During power on, the | ||
1795 | * update in powered_update_hci will take care of it. | ||
1796 | */ | ||
1797 | if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { | ||
1798 | struct hci_request req; | ||
1799 | |||
1800 | hci_dev_lock(hdev); | ||
1801 | |||
1802 | hci_req_init(&req, hdev); | ||
1803 | update_adv_data(&req); | ||
1804 | update_scan_rsp_data(&req); | ||
1805 | hci_req_run(&req, NULL); | ||
1806 | |||
1807 | hci_dev_unlock(hdev); | ||
1808 | } | ||
1559 | } | 1809 | } |
1560 | 1810 | ||
1561 | static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | 1811 | static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) |
@@ -1623,18 +1873,18 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
1623 | goto unlock; | 1873 | goto unlock; |
1624 | } | 1874 | } |
1625 | 1875 | ||
1876 | hci_req_init(&req, hdev); | ||
1877 | |||
1626 | memset(&hci_cp, 0, sizeof(hci_cp)); | 1878 | memset(&hci_cp, 0, sizeof(hci_cp)); |
1627 | 1879 | ||
1628 | if (val) { | 1880 | if (val) { |
1629 | hci_cp.le = val; | 1881 | hci_cp.le = val; |
1630 | hci_cp.simul = lmp_le_br_capable(hdev); | 1882 | hci_cp.simul = lmp_le_br_capable(hdev); |
1883 | } else { | ||
1884 | if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) | ||
1885 | disable_advertising(&req); | ||
1631 | } | 1886 | } |
1632 | 1887 | ||
1633 | hci_req_init(&req, hdev); | ||
1634 | |||
1635 | if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) && !val) | ||
1636 | disable_advertising(&req); | ||
1637 | |||
1638 | hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp), | 1888 | hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp), |
1639 | &hci_cp); | 1889 | &hci_cp); |
1640 | 1890 | ||
@@ -2772,8 +3022,11 @@ static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2772 | update_eir(&req); | 3022 | update_eir(&req); |
2773 | } | 3023 | } |
2774 | 3024 | ||
3025 | /* The name is stored in the scan response data and so | ||
3026 | * no need to udpate the advertising data here. | ||
3027 | */ | ||
2775 | if (lmp_le_capable(hdev)) | 3028 | if (lmp_le_capable(hdev)) |
2776 | hci_update_ad(&req); | 3029 | update_scan_rsp_data(&req); |
2777 | 3030 | ||
2778 | err = hci_req_run(&req, set_name_complete); | 3031 | err = hci_req_run(&req, set_name_complete); |
2779 | if (err < 0) | 3032 | if (err < 0) |
@@ -3038,10 +3291,7 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, | |||
3038 | param_cp.type = LE_SCAN_ACTIVE; | 3291 | param_cp.type = LE_SCAN_ACTIVE; |
3039 | param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT); | 3292 | param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT); |
3040 | param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN); | 3293 | param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN); |
3041 | if (bacmp(&hdev->bdaddr, BDADDR_ANY)) | 3294 | param_cp.own_address_type = hdev->own_addr_type; |
3042 | param_cp.own_address_type = ADDR_LE_DEV_PUBLIC; | ||
3043 | else | ||
3044 | param_cp.own_address_type = ADDR_LE_DEV_RANDOM; | ||
3045 | hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp), | 3295 | hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp), |
3046 | ¶m_cp); | 3296 | ¶m_cp); |
3047 | 3297 | ||
@@ -3725,7 +3975,7 @@ static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
3725 | goto unlock; | 3975 | goto unlock; |
3726 | } | 3976 | } |
3727 | 3977 | ||
3728 | /* We need to flip the bit already here so that hci_update_ad | 3978 | /* We need to flip the bit already here so that update_adv_data |
3729 | * generates the correct flags. | 3979 | * generates the correct flags. |
3730 | */ | 3980 | */ |
3731 | set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags); | 3981 | set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags); |
@@ -3735,7 +3985,10 @@ static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
3735 | if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) | 3985 | if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) |
3736 | set_bredr_scan(&req); | 3986 | set_bredr_scan(&req); |
3737 | 3987 | ||
3738 | hci_update_ad(&req); | 3988 | /* Since only the advertising data flags will change, there |
3989 | * is no need to update the scan response data. | ||
3990 | */ | ||
3991 | update_adv_data(&req); | ||
3739 | 3992 | ||
3740 | err = hci_req_run(&req, set_bredr_complete); | 3993 | err = hci_req_run(&req, set_bredr_complete); |
3741 | if (err < 0) | 3994 | if (err < 0) |
@@ -4036,9 +4289,6 @@ static int powered_update_hci(struct hci_dev *hdev) | |||
4036 | cp.simul != lmp_host_le_br_capable(hdev)) | 4289 | cp.simul != lmp_host_le_br_capable(hdev)) |
4037 | hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, | 4290 | hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, |
4038 | sizeof(cp), &cp); | 4291 | sizeof(cp), &cp); |
4039 | |||
4040 | /* In case BR/EDR was toggled during the AUTO_OFF phase */ | ||
4041 | hci_update_ad(&req); | ||
4042 | } | 4292 | } |
4043 | 4293 | ||
4044 | if (lmp_le_capable(hdev)) { | 4294 | if (lmp_le_capable(hdev)) { |
@@ -4047,6 +4297,15 @@ static int powered_update_hci(struct hci_dev *hdev) | |||
4047 | hci_req_add(&req, HCI_OP_LE_SET_RANDOM_ADDR, 6, | 4297 | hci_req_add(&req, HCI_OP_LE_SET_RANDOM_ADDR, 6, |
4048 | &hdev->static_addr); | 4298 | &hdev->static_addr); |
4049 | 4299 | ||
4300 | /* Make sure the controller has a good default for | ||
4301 | * advertising data. This also applies to the case | ||
4302 | * where BR/EDR was toggled during the AUTO_OFF phase. | ||
4303 | */ | ||
4304 | if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { | ||
4305 | update_adv_data(&req); | ||
4306 | update_scan_rsp_data(&req); | ||
4307 | } | ||
4308 | |||
4050 | if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) | 4309 | if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) |
4051 | enable_advertising(&req); | 4310 | enable_advertising(&req); |
4052 | } | 4311 | } |
@@ -4121,59 +4380,91 @@ void mgmt_set_powered_failed(struct hci_dev *hdev, int err) | |||
4121 | mgmt_pending_remove(cmd); | 4380 | mgmt_pending_remove(cmd); |
4122 | } | 4381 | } |
4123 | 4382 | ||
4124 | int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable) | 4383 | void mgmt_discoverable_timeout(struct hci_dev *hdev) |
4125 | { | 4384 | { |
4126 | bool changed = false; | 4385 | struct hci_request req; |
4127 | int err = 0; | 4386 | |
4387 | hci_dev_lock(hdev); | ||
4388 | |||
4389 | /* When discoverable timeout triggers, then just make sure | ||
4390 | * the limited discoverable flag is cleared. Even in the case | ||
4391 | * of a timeout triggered from general discoverable, it is | ||
4392 | * safe to unconditionally clear the flag. | ||
4393 | */ | ||
4394 | clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags); | ||
4395 | clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags); | ||
4396 | |||
4397 | hci_req_init(&req, hdev); | ||
4398 | if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) { | ||
4399 | u8 scan = SCAN_PAGE; | ||
4400 | hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, | ||
4401 | sizeof(scan), &scan); | ||
4402 | } | ||
4403 | update_class(&req); | ||
4404 | update_adv_data(&req); | ||
4405 | hci_req_run(&req, NULL); | ||
4406 | |||
4407 | hdev->discov_timeout = 0; | ||
4408 | |||
4409 | new_settings(hdev, NULL); | ||
4410 | |||
4411 | hci_dev_unlock(hdev); | ||
4412 | } | ||
4413 | |||
4414 | void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable) | ||
4415 | { | ||
4416 | bool changed; | ||
4128 | 4417 | ||
4129 | /* Nothing needed here if there's a pending command since that | 4418 | /* Nothing needed here if there's a pending command since that |
4130 | * commands request completion callback takes care of everything | 4419 | * commands request completion callback takes care of everything |
4131 | * necessary. | 4420 | * necessary. |
4132 | */ | 4421 | */ |
4133 | if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev)) | 4422 | if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev)) |
4134 | return 0; | 4423 | return; |
4135 | 4424 | ||
4136 | if (discoverable) { | 4425 | if (discoverable) { |
4137 | if (!test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) | 4426 | changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags); |
4138 | changed = true; | ||
4139 | } else { | 4427 | } else { |
4140 | if (test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) | 4428 | clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags); |
4141 | changed = true; | 4429 | changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags); |
4142 | } | 4430 | } |
4143 | 4431 | ||
4144 | if (changed) | 4432 | if (changed) { |
4145 | err = new_settings(hdev, NULL); | 4433 | struct hci_request req; |
4146 | 4434 | ||
4147 | return err; | 4435 | /* In case this change in discoverable was triggered by |
4436 | * a disabling of connectable there could be a need to | ||
4437 | * update the advertising flags. | ||
4438 | */ | ||
4439 | hci_req_init(&req, hdev); | ||
4440 | update_adv_data(&req); | ||
4441 | hci_req_run(&req, NULL); | ||
4442 | |||
4443 | new_settings(hdev, NULL); | ||
4444 | } | ||
4148 | } | 4445 | } |
4149 | 4446 | ||
4150 | int mgmt_connectable(struct hci_dev *hdev, u8 connectable) | 4447 | void mgmt_connectable(struct hci_dev *hdev, u8 connectable) |
4151 | { | 4448 | { |
4152 | bool changed = false; | 4449 | bool changed; |
4153 | int err = 0; | ||
4154 | 4450 | ||
4155 | /* Nothing needed here if there's a pending command since that | 4451 | /* Nothing needed here if there's a pending command since that |
4156 | * commands request completion callback takes care of everything | 4452 | * commands request completion callback takes care of everything |
4157 | * necessary. | 4453 | * necessary. |
4158 | */ | 4454 | */ |
4159 | if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) | 4455 | if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) |
4160 | return 0; | 4456 | return; |
4161 | 4457 | ||
4162 | if (connectable) { | 4458 | if (connectable) |
4163 | if (!test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags)) | 4459 | changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags); |
4164 | changed = true; | 4460 | else |
4165 | } else { | 4461 | changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags); |
4166 | if (test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags)) | ||
4167 | changed = true; | ||
4168 | } | ||
4169 | 4462 | ||
4170 | if (changed) | 4463 | if (changed) |
4171 | err = new_settings(hdev, NULL); | 4464 | new_settings(hdev, NULL); |
4172 | |||
4173 | return err; | ||
4174 | } | 4465 | } |
4175 | 4466 | ||
4176 | int mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status) | 4467 | void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status) |
4177 | { | 4468 | { |
4178 | u8 mgmt_err = mgmt_status(status); | 4469 | u8 mgmt_err = mgmt_status(status); |
4179 | 4470 | ||
@@ -4184,12 +4475,10 @@ int mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status) | |||
4184 | if (scan & SCAN_INQUIRY) | 4475 | if (scan & SCAN_INQUIRY) |
4185 | mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev, | 4476 | mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev, |
4186 | cmd_status_rsp, &mgmt_err); | 4477 | cmd_status_rsp, &mgmt_err); |
4187 | |||
4188 | return 0; | ||
4189 | } | 4478 | } |
4190 | 4479 | ||
4191 | int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, | 4480 | void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, |
4192 | bool persistent) | 4481 | bool persistent) |
4193 | { | 4482 | { |
4194 | struct mgmt_ev_new_link_key ev; | 4483 | struct mgmt_ev_new_link_key ev; |
4195 | 4484 | ||
@@ -4202,10 +4491,10 @@ int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, | |||
4202 | memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE); | 4491 | memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE); |
4203 | ev.key.pin_len = key->pin_len; | 4492 | ev.key.pin_len = key->pin_len; |
4204 | 4493 | ||
4205 | return mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL); | 4494 | mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL); |
4206 | } | 4495 | } |
4207 | 4496 | ||
4208 | int mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent) | 4497 | void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent) |
4209 | { | 4498 | { |
4210 | struct mgmt_ev_new_long_term_key ev; | 4499 | struct mgmt_ev_new_long_term_key ev; |
4211 | 4500 | ||
@@ -4224,8 +4513,18 @@ int mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent) | |||
4224 | memcpy(ev.key.rand, key->rand, sizeof(key->rand)); | 4513 | memcpy(ev.key.rand, key->rand, sizeof(key->rand)); |
4225 | memcpy(ev.key.val, key->val, sizeof(key->val)); | 4514 | memcpy(ev.key.val, key->val, sizeof(key->val)); |
4226 | 4515 | ||
4227 | return mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), | 4516 | mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL); |
4228 | NULL); | 4517 | } |
4518 | |||
4519 | static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data, | ||
4520 | u8 data_len) | ||
4521 | { | ||
4522 | eir[eir_len++] = sizeof(type) + data_len; | ||
4523 | eir[eir_len++] = type; | ||
4524 | memcpy(&eir[eir_len], data, data_len); | ||
4525 | eir_len += data_len; | ||
4526 | |||
4527 | return eir_len; | ||
4229 | } | 4528 | } |
4230 | 4529 | ||
4231 | void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | 4530 | void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, |
@@ -4345,7 +4644,7 @@ void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | |||
4345 | mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL); | 4644 | mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL); |
4346 | } | 4645 | } |
4347 | 4646 | ||
4348 | int mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure) | 4647 | void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure) |
4349 | { | 4648 | { |
4350 | struct mgmt_ev_pin_code_request ev; | 4649 | struct mgmt_ev_pin_code_request ev; |
4351 | 4650 | ||
@@ -4353,52 +4652,45 @@ int mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure) | |||
4353 | ev.addr.type = BDADDR_BREDR; | 4652 | ev.addr.type = BDADDR_BREDR; |
4354 | ev.secure = secure; | 4653 | ev.secure = secure; |
4355 | 4654 | ||
4356 | return mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), | 4655 | mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL); |
4357 | NULL); | ||
4358 | } | 4656 | } |
4359 | 4657 | ||
4360 | int mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, | 4658 | void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, |
4361 | u8 status) | 4659 | u8 status) |
4362 | { | 4660 | { |
4363 | struct pending_cmd *cmd; | 4661 | struct pending_cmd *cmd; |
4364 | struct mgmt_rp_pin_code_reply rp; | 4662 | struct mgmt_rp_pin_code_reply rp; |
4365 | int err; | ||
4366 | 4663 | ||
4367 | cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev); | 4664 | cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev); |
4368 | if (!cmd) | 4665 | if (!cmd) |
4369 | return -ENOENT; | 4666 | return; |
4370 | 4667 | ||
4371 | bacpy(&rp.addr.bdaddr, bdaddr); | 4668 | bacpy(&rp.addr.bdaddr, bdaddr); |
4372 | rp.addr.type = BDADDR_BREDR; | 4669 | rp.addr.type = BDADDR_BREDR; |
4373 | 4670 | ||
4374 | err = cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY, | 4671 | cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY, |
4375 | mgmt_status(status), &rp, sizeof(rp)); | 4672 | mgmt_status(status), &rp, sizeof(rp)); |
4376 | 4673 | ||
4377 | mgmt_pending_remove(cmd); | 4674 | mgmt_pending_remove(cmd); |
4378 | |||
4379 | return err; | ||
4380 | } | 4675 | } |
4381 | 4676 | ||
4382 | int mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, | 4677 | void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, |
4383 | u8 status) | 4678 | u8 status) |
4384 | { | 4679 | { |
4385 | struct pending_cmd *cmd; | 4680 | struct pending_cmd *cmd; |
4386 | struct mgmt_rp_pin_code_reply rp; | 4681 | struct mgmt_rp_pin_code_reply rp; |
4387 | int err; | ||
4388 | 4682 | ||
4389 | cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev); | 4683 | cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev); |
4390 | if (!cmd) | 4684 | if (!cmd) |
4391 | return -ENOENT; | 4685 | return; |
4392 | 4686 | ||
4393 | bacpy(&rp.addr.bdaddr, bdaddr); | 4687 | bacpy(&rp.addr.bdaddr, bdaddr); |
4394 | rp.addr.type = BDADDR_BREDR; | 4688 | rp.addr.type = BDADDR_BREDR; |
4395 | 4689 | ||
4396 | err = cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY, | 4690 | cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY, |
4397 | mgmt_status(status), &rp, sizeof(rp)); | 4691 | mgmt_status(status), &rp, sizeof(rp)); |
4398 | 4692 | ||
4399 | mgmt_pending_remove(cmd); | 4693 | mgmt_pending_remove(cmd); |
4400 | |||
4401 | return err; | ||
4402 | } | 4694 | } |
4403 | 4695 | ||
4404 | int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr, | 4696 | int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr, |
@@ -4500,8 +4792,8 @@ int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr, | |||
4500 | return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL); | 4792 | return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL); |
4501 | } | 4793 | } |
4502 | 4794 | ||
4503 | int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | 4795 | void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, |
4504 | u8 addr_type, u8 status) | 4796 | u8 addr_type, u8 status) |
4505 | { | 4797 | { |
4506 | struct mgmt_ev_auth_failed ev; | 4798 | struct mgmt_ev_auth_failed ev; |
4507 | 4799 | ||
@@ -4509,40 +4801,36 @@ int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | |||
4509 | ev.addr.type = link_to_bdaddr(link_type, addr_type); | 4801 | ev.addr.type = link_to_bdaddr(link_type, addr_type); |
4510 | ev.status = mgmt_status(status); | 4802 | ev.status = mgmt_status(status); |
4511 | 4803 | ||
4512 | return mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL); | 4804 | mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL); |
4513 | } | 4805 | } |
4514 | 4806 | ||
4515 | int mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status) | 4807 | void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status) |
4516 | { | 4808 | { |
4517 | struct cmd_lookup match = { NULL, hdev }; | 4809 | struct cmd_lookup match = { NULL, hdev }; |
4518 | bool changed = false; | 4810 | bool changed; |
4519 | int err = 0; | ||
4520 | 4811 | ||
4521 | if (status) { | 4812 | if (status) { |
4522 | u8 mgmt_err = mgmt_status(status); | 4813 | u8 mgmt_err = mgmt_status(status); |
4523 | mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, | 4814 | mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, |
4524 | cmd_status_rsp, &mgmt_err); | 4815 | cmd_status_rsp, &mgmt_err); |
4525 | return 0; | 4816 | return; |
4526 | } | 4817 | } |
4527 | 4818 | ||
4528 | if (test_bit(HCI_AUTH, &hdev->flags)) { | 4819 | if (test_bit(HCI_AUTH, &hdev->flags)) |
4529 | if (!test_and_set_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) | 4820 | changed = !test_and_set_bit(HCI_LINK_SECURITY, |
4530 | changed = true; | 4821 | &hdev->dev_flags); |
4531 | } else { | 4822 | else |
4532 | if (test_and_clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) | 4823 | changed = test_and_clear_bit(HCI_LINK_SECURITY, |
4533 | changed = true; | 4824 | &hdev->dev_flags); |
4534 | } | ||
4535 | 4825 | ||
4536 | mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp, | 4826 | mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp, |
4537 | &match); | 4827 | &match); |
4538 | 4828 | ||
4539 | if (changed) | 4829 | if (changed) |
4540 | err = new_settings(hdev, match.sk); | 4830 | new_settings(hdev, match.sk); |
4541 | 4831 | ||
4542 | if (match.sk) | 4832 | if (match.sk) |
4543 | sock_put(match.sk); | 4833 | sock_put(match.sk); |
4544 | |||
4545 | return err; | ||
4546 | } | 4834 | } |
4547 | 4835 | ||
4548 | static void clear_eir(struct hci_request *req) | 4836 | static void clear_eir(struct hci_request *req) |
@@ -4560,12 +4848,11 @@ static void clear_eir(struct hci_request *req) | |||
4560 | hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp); | 4848 | hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp); |
4561 | } | 4849 | } |
4562 | 4850 | ||
4563 | int mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status) | 4851 | void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status) |
4564 | { | 4852 | { |
4565 | struct cmd_lookup match = { NULL, hdev }; | 4853 | struct cmd_lookup match = { NULL, hdev }; |
4566 | struct hci_request req; | 4854 | struct hci_request req; |
4567 | bool changed = false; | 4855 | bool changed = false; |
4568 | int err = 0; | ||
4569 | 4856 | ||
4570 | if (status) { | 4857 | if (status) { |
4571 | u8 mgmt_err = mgmt_status(status); | 4858 | u8 mgmt_err = mgmt_status(status); |
@@ -4573,13 +4860,12 @@ int mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status) | |||
4573 | if (enable && test_and_clear_bit(HCI_SSP_ENABLED, | 4860 | if (enable && test_and_clear_bit(HCI_SSP_ENABLED, |
4574 | &hdev->dev_flags)) { | 4861 | &hdev->dev_flags)) { |
4575 | clear_bit(HCI_HS_ENABLED, &hdev->dev_flags); | 4862 | clear_bit(HCI_HS_ENABLED, &hdev->dev_flags); |
4576 | err = new_settings(hdev, NULL); | 4863 | new_settings(hdev, NULL); |
4577 | } | 4864 | } |
4578 | 4865 | ||
4579 | mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp, | 4866 | mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp, |
4580 | &mgmt_err); | 4867 | &mgmt_err); |
4581 | 4868 | return; | |
4582 | return err; | ||
4583 | } | 4869 | } |
4584 | 4870 | ||
4585 | if (enable) { | 4871 | if (enable) { |
@@ -4596,7 +4882,7 @@ int mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status) | |||
4596 | mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match); | 4882 | mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match); |
4597 | 4883 | ||
4598 | if (changed) | 4884 | if (changed) |
4599 | err = new_settings(hdev, match.sk); | 4885 | new_settings(hdev, match.sk); |
4600 | 4886 | ||
4601 | if (match.sk) | 4887 | if (match.sk) |
4602 | sock_put(match.sk); | 4888 | sock_put(match.sk); |
@@ -4609,8 +4895,6 @@ int mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status) | |||
4609 | clear_eir(&req); | 4895 | clear_eir(&req); |
4610 | 4896 | ||
4611 | hci_req_run(&req, NULL); | 4897 | hci_req_run(&req, NULL); |
4612 | |||
4613 | return err; | ||
4614 | } | 4898 | } |
4615 | 4899 | ||
4616 | static void sk_lookup(struct pending_cmd *cmd, void *data) | 4900 | static void sk_lookup(struct pending_cmd *cmd, void *data) |
@@ -4623,33 +4907,30 @@ static void sk_lookup(struct pending_cmd *cmd, void *data) | |||
4623 | } | 4907 | } |
4624 | } | 4908 | } |
4625 | 4909 | ||
4626 | int mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class, | 4910 | void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class, |
4627 | u8 status) | 4911 | u8 status) |
4628 | { | 4912 | { |
4629 | struct cmd_lookup match = { NULL, hdev, mgmt_status(status) }; | 4913 | struct cmd_lookup match = { NULL, hdev, mgmt_status(status) }; |
4630 | int err = 0; | ||
4631 | 4914 | ||
4632 | mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match); | 4915 | mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match); |
4633 | mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match); | 4916 | mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match); |
4634 | mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match); | 4917 | mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match); |
4635 | 4918 | ||
4636 | if (!status) | 4919 | if (!status) |
4637 | err = mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, | 4920 | mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3, |
4638 | 3, NULL); | 4921 | NULL); |
4639 | 4922 | ||
4640 | if (match.sk) | 4923 | if (match.sk) |
4641 | sock_put(match.sk); | 4924 | sock_put(match.sk); |
4642 | |||
4643 | return err; | ||
4644 | } | 4925 | } |
4645 | 4926 | ||
4646 | int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status) | 4927 | void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status) |
4647 | { | 4928 | { |
4648 | struct mgmt_cp_set_local_name ev; | 4929 | struct mgmt_cp_set_local_name ev; |
4649 | struct pending_cmd *cmd; | 4930 | struct pending_cmd *cmd; |
4650 | 4931 | ||
4651 | if (status) | 4932 | if (status) |
4652 | return 0; | 4933 | return; |
4653 | 4934 | ||
4654 | memset(&ev, 0, sizeof(ev)); | 4935 | memset(&ev, 0, sizeof(ev)); |
4655 | memcpy(ev.name, name, HCI_MAX_NAME_LENGTH); | 4936 | memcpy(ev.name, name, HCI_MAX_NAME_LENGTH); |
@@ -4663,42 +4944,38 @@ int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status) | |||
4663 | * HCI dev don't send any mgmt signals. | 4944 | * HCI dev don't send any mgmt signals. |
4664 | */ | 4945 | */ |
4665 | if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) | 4946 | if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) |
4666 | return 0; | 4947 | return; |
4667 | } | 4948 | } |
4668 | 4949 | ||
4669 | return mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev), | 4950 | mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev), |
4670 | cmd ? cmd->sk : NULL); | 4951 | cmd ? cmd->sk : NULL); |
4671 | } | 4952 | } |
4672 | 4953 | ||
4673 | int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash, | 4954 | void mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash, |
4674 | u8 *randomizer, u8 status) | 4955 | u8 *randomizer, u8 status) |
4675 | { | 4956 | { |
4676 | struct pending_cmd *cmd; | 4957 | struct pending_cmd *cmd; |
4677 | int err; | ||
4678 | 4958 | ||
4679 | BT_DBG("%s status %u", hdev->name, status); | 4959 | BT_DBG("%s status %u", hdev->name, status); |
4680 | 4960 | ||
4681 | cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev); | 4961 | cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev); |
4682 | if (!cmd) | 4962 | if (!cmd) |
4683 | return -ENOENT; | 4963 | return; |
4684 | 4964 | ||
4685 | if (status) { | 4965 | if (status) { |
4686 | err = cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA, | 4966 | cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA, |
4687 | mgmt_status(status)); | 4967 | mgmt_status(status)); |
4688 | } else { | 4968 | } else { |
4689 | struct mgmt_rp_read_local_oob_data rp; | 4969 | struct mgmt_rp_read_local_oob_data rp; |
4690 | 4970 | ||
4691 | memcpy(rp.hash, hash, sizeof(rp.hash)); | 4971 | memcpy(rp.hash, hash, sizeof(rp.hash)); |
4692 | memcpy(rp.randomizer, randomizer, sizeof(rp.randomizer)); | 4972 | memcpy(rp.randomizer, randomizer, sizeof(rp.randomizer)); |
4693 | 4973 | ||
4694 | err = cmd_complete(cmd->sk, hdev->id, | 4974 | cmd_complete(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA, |
4695 | MGMT_OP_READ_LOCAL_OOB_DATA, 0, &rp, | 4975 | 0, &rp, sizeof(rp)); |
4696 | sizeof(rp)); | ||
4697 | } | 4976 | } |
4698 | 4977 | ||
4699 | mgmt_pending_remove(cmd); | 4978 | mgmt_pending_remove(cmd); |
4700 | |||
4701 | return err; | ||
4702 | } | 4979 | } |
4703 | 4980 | ||
4704 | void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | 4981 | void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, |
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 27e936a7ddd9..94d06cbfbc18 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c | |||
@@ -2154,13 +2154,6 @@ static int __init rfcomm_init(void) | |||
2154 | goto unregister; | 2154 | goto unregister; |
2155 | } | 2155 | } |
2156 | 2156 | ||
2157 | if (bt_debugfs) { | ||
2158 | rfcomm_dlc_debugfs = debugfs_create_file("rfcomm_dlc", 0444, | ||
2159 | bt_debugfs, NULL, &rfcomm_dlc_debugfs_fops); | ||
2160 | if (!rfcomm_dlc_debugfs) | ||
2161 | BT_ERR("Failed to create RFCOMM debug file"); | ||
2162 | } | ||
2163 | |||
2164 | err = rfcomm_init_ttys(); | 2157 | err = rfcomm_init_ttys(); |
2165 | if (err < 0) | 2158 | if (err < 0) |
2166 | goto stop; | 2159 | goto stop; |
@@ -2171,6 +2164,13 @@ static int __init rfcomm_init(void) | |||
2171 | 2164 | ||
2172 | BT_INFO("RFCOMM ver %s", VERSION); | 2165 | BT_INFO("RFCOMM ver %s", VERSION); |
2173 | 2166 | ||
2167 | if (IS_ERR_OR_NULL(bt_debugfs)) | ||
2168 | return 0; | ||
2169 | |||
2170 | rfcomm_dlc_debugfs = debugfs_create_file("rfcomm_dlc", 0444, | ||
2171 | bt_debugfs, NULL, | ||
2172 | &rfcomm_dlc_debugfs_fops); | ||
2173 | |||
2174 | return 0; | 2174 | return 0; |
2175 | 2175 | ||
2176 | cleanup: | 2176 | cleanup: |
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index df17276eb32b..c4d3d423f89b 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c | |||
@@ -1051,15 +1051,15 @@ int __init rfcomm_init_sockets(void) | |||
1051 | goto error; | 1051 | goto error; |
1052 | } | 1052 | } |
1053 | 1053 | ||
1054 | if (bt_debugfs) { | ||
1055 | rfcomm_sock_debugfs = debugfs_create_file("rfcomm", 0444, | ||
1056 | bt_debugfs, NULL, &rfcomm_sock_debugfs_fops); | ||
1057 | if (!rfcomm_sock_debugfs) | ||
1058 | BT_ERR("Failed to create RFCOMM debug file"); | ||
1059 | } | ||
1060 | |||
1061 | BT_INFO("RFCOMM socket layer initialized"); | 1054 | BT_INFO("RFCOMM socket layer initialized"); |
1062 | 1055 | ||
1056 | if (IS_ERR_OR_NULL(bt_debugfs)) | ||
1057 | return 0; | ||
1058 | |||
1059 | rfcomm_sock_debugfs = debugfs_create_file("rfcomm", 0444, | ||
1060 | bt_debugfs, NULL, | ||
1061 | &rfcomm_sock_debugfs_fops); | ||
1062 | |||
1063 | return 0; | 1063 | return 0; |
1064 | 1064 | ||
1065 | error: | 1065 | error: |
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index a92aebac56ca..12a0e51e21e1 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c | |||
@@ -1177,15 +1177,14 @@ int __init sco_init(void) | |||
1177 | goto error; | 1177 | goto error; |
1178 | } | 1178 | } |
1179 | 1179 | ||
1180 | if (bt_debugfs) { | ||
1181 | sco_debugfs = debugfs_create_file("sco", 0444, bt_debugfs, | ||
1182 | NULL, &sco_debugfs_fops); | ||
1183 | if (!sco_debugfs) | ||
1184 | BT_ERR("Failed to create SCO debug file"); | ||
1185 | } | ||
1186 | |||
1187 | BT_INFO("SCO socket layer initialized"); | 1180 | BT_INFO("SCO socket layer initialized"); |
1188 | 1181 | ||
1182 | if (IS_ERR_OR_NULL(bt_debugfs)) | ||
1183 | return 0; | ||
1184 | |||
1185 | sco_debugfs = debugfs_create_file("sco", 0444, bt_debugfs, | ||
1186 | NULL, &sco_debugfs_fops); | ||
1187 | |||
1189 | return 0; | 1188 | return 0; |
1190 | 1189 | ||
1191 | error: | 1190 | error: |
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 463e50c58716..85a2796cac61 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c | |||
@@ -856,7 +856,7 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) | |||
856 | 856 | ||
857 | if (hcon->type != LE_LINK) { | 857 | if (hcon->type != LE_LINK) { |
858 | kfree_skb(skb); | 858 | kfree_skb(skb); |
859 | return -ENOTSUPP; | 859 | return 0; |
860 | } | 860 | } |
861 | 861 | ||
862 | if (skb->len < 1) { | 862 | if (skb->len < 1) { |
@@ -864,7 +864,7 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) | |||
864 | return -EILSEQ; | 864 | return -EILSEQ; |
865 | } | 865 | } |
866 | 866 | ||
867 | if (!test_bit(HCI_LE_ENABLED, &conn->hcon->hdev->dev_flags)) { | 867 | if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags)) { |
868 | err = -ENOTSUPP; | 868 | err = -ENOTSUPP; |
869 | reason = SMP_PAIRING_NOTSUPP; | 869 | reason = SMP_PAIRING_NOTSUPP; |
870 | goto done; | 870 | goto done; |
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index 62535fe9f570..97b5dcad5025 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig | |||
@@ -4,6 +4,7 @@ config MAC80211 | |||
4 | select CRYPTO | 4 | select CRYPTO |
5 | select CRYPTO_ARC4 | 5 | select CRYPTO_ARC4 |
6 | select CRYPTO_AES | 6 | select CRYPTO_AES |
7 | select CRYPTO_CCM | ||
7 | select CRC32 | 8 | select CRC32 |
8 | select AVERAGE | 9 | select AVERAGE |
9 | ---help--- | 10 | ---help--- |
@@ -258,6 +259,17 @@ config MAC80211_MESH_SYNC_DEBUG | |||
258 | 259 | ||
259 | Do not select this option. | 260 | Do not select this option. |
260 | 261 | ||
262 | config MAC80211_MESH_CSA_DEBUG | ||
263 | bool "Verbose mesh channel switch debugging" | ||
264 | depends on MAC80211_DEBUG_MENU | ||
265 | depends on MAC80211_MESH | ||
266 | ---help--- | ||
267 | Selecting this option causes mac80211 to print out very verbose mesh | ||
268 | channel switch debugging messages (when mac80211 is taking part in a | ||
269 | mesh network). | ||
270 | |||
271 | Do not select this option. | ||
272 | |||
261 | config MAC80211_MESH_PS_DEBUG | 273 | config MAC80211_MESH_PS_DEBUG |
262 | bool "Verbose mesh powersave debugging" | 274 | bool "Verbose mesh powersave debugging" |
263 | depends on MAC80211_DEBUG_MENU | 275 | depends on MAC80211_DEBUG_MENU |
diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c index be7614b9ed27..7c7df475a401 100644 --- a/net/mac80211/aes_ccm.c +++ b/net/mac80211/aes_ccm.c | |||
@@ -2,6 +2,8 @@ | |||
2 | * Copyright 2003-2004, Instant802 Networks, Inc. | 2 | * Copyright 2003-2004, Instant802 Networks, Inc. |
3 | * Copyright 2005-2006, Devicescape Software, Inc. | 3 | * Copyright 2005-2006, Devicescape Software, Inc. |
4 | * | 4 | * |
5 | * Rewrite: Copyright (C) 2013 Linaro Ltd <ard.biesheuvel@linaro.org> | ||
6 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
7 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
@@ -17,134 +19,75 @@ | |||
17 | #include "key.h" | 19 | #include "key.h" |
18 | #include "aes_ccm.h" | 20 | #include "aes_ccm.h" |
19 | 21 | ||
20 | static void aes_ccm_prepare(struct crypto_cipher *tfm, u8 *scratch, u8 *a) | 22 | void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, |
23 | u8 *data, size_t data_len, u8 *mic) | ||
21 | { | 24 | { |
22 | int i; | 25 | struct scatterlist assoc, pt, ct[2]; |
23 | u8 *b_0, *aad, *b, *s_0; | 26 | struct { |
24 | 27 | struct aead_request req; | |
25 | b_0 = scratch + 3 * AES_BLOCK_SIZE; | 28 | u8 priv[crypto_aead_reqsize(tfm)]; |
26 | aad = scratch + 4 * AES_BLOCK_SIZE; | 29 | } aead_req; |
27 | b = scratch; | ||
28 | s_0 = scratch + AES_BLOCK_SIZE; | ||
29 | |||
30 | crypto_cipher_encrypt_one(tfm, b, b_0); | ||
31 | 30 | ||
32 | /* Extra Authenticate-only data (always two AES blocks) */ | 31 | memset(&aead_req, 0, sizeof(aead_req)); |
33 | for (i = 0; i < AES_BLOCK_SIZE; i++) | ||
34 | aad[i] ^= b[i]; | ||
35 | crypto_cipher_encrypt_one(tfm, b, aad); | ||
36 | 32 | ||
37 | aad += AES_BLOCK_SIZE; | 33 | sg_init_one(&pt, data, data_len); |
34 | sg_init_one(&assoc, &aad[2], be16_to_cpup((__be16 *)aad)); | ||
35 | sg_init_table(ct, 2); | ||
36 | sg_set_buf(&ct[0], data, data_len); | ||
37 | sg_set_buf(&ct[1], mic, IEEE80211_CCMP_MIC_LEN); | ||
38 | 38 | ||
39 | for (i = 0; i < AES_BLOCK_SIZE; i++) | 39 | aead_request_set_tfm(&aead_req.req, tfm); |
40 | aad[i] ^= b[i]; | 40 | aead_request_set_assoc(&aead_req.req, &assoc, assoc.length); |
41 | crypto_cipher_encrypt_one(tfm, a, aad); | 41 | aead_request_set_crypt(&aead_req.req, &pt, ct, data_len, b_0); |
42 | 42 | ||
43 | /* Mask out bits from auth-only-b_0 */ | 43 | crypto_aead_encrypt(&aead_req.req); |
44 | b_0[0] &= 0x07; | ||
45 | |||
46 | /* S_0 is used to encrypt T (= MIC) */ | ||
47 | b_0[14] = 0; | ||
48 | b_0[15] = 0; | ||
49 | crypto_cipher_encrypt_one(tfm, s_0, b_0); | ||
50 | } | 44 | } |
51 | 45 | ||
52 | 46 | int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, | |
53 | void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch, | 47 | u8 *data, size_t data_len, u8 *mic) |
54 | u8 *data, size_t data_len, | ||
55 | u8 *cdata, u8 *mic) | ||
56 | { | 48 | { |
57 | int i, j, last_len, num_blocks; | 49 | struct scatterlist assoc, pt, ct[2]; |
58 | u8 *pos, *cpos, *b, *s_0, *e, *b_0; | 50 | struct { |
59 | 51 | struct aead_request req; | |
60 | b = scratch; | 52 | u8 priv[crypto_aead_reqsize(tfm)]; |
61 | s_0 = scratch + AES_BLOCK_SIZE; | 53 | } aead_req; |
62 | e = scratch + 2 * AES_BLOCK_SIZE; | 54 | |
63 | b_0 = scratch + 3 * AES_BLOCK_SIZE; | 55 | memset(&aead_req, 0, sizeof(aead_req)); |
64 | 56 | ||
65 | num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE); | 57 | sg_init_one(&pt, data, data_len); |
66 | last_len = data_len % AES_BLOCK_SIZE; | 58 | sg_init_one(&assoc, &aad[2], be16_to_cpup((__be16 *)aad)); |
67 | aes_ccm_prepare(tfm, scratch, b); | 59 | sg_init_table(ct, 2); |
68 | 60 | sg_set_buf(&ct[0], data, data_len); | |
69 | /* Process payload blocks */ | 61 | sg_set_buf(&ct[1], mic, IEEE80211_CCMP_MIC_LEN); |
70 | pos = data; | 62 | |
71 | cpos = cdata; | 63 | aead_request_set_tfm(&aead_req.req, tfm); |
72 | for (j = 1; j <= num_blocks; j++) { | 64 | aead_request_set_assoc(&aead_req.req, &assoc, assoc.length); |
73 | int blen = (j == num_blocks && last_len) ? | 65 | aead_request_set_crypt(&aead_req.req, ct, &pt, |
74 | last_len : AES_BLOCK_SIZE; | 66 | data_len + IEEE80211_CCMP_MIC_LEN, b_0); |
75 | 67 | ||
76 | /* Authentication followed by encryption */ | 68 | return crypto_aead_decrypt(&aead_req.req); |
77 | for (i = 0; i < blen; i++) | ||
78 | b[i] ^= pos[i]; | ||
79 | crypto_cipher_encrypt_one(tfm, b, b); | ||
80 | |||
81 | b_0[14] = (j >> 8) & 0xff; | ||
82 | b_0[15] = j & 0xff; | ||
83 | crypto_cipher_encrypt_one(tfm, e, b_0); | ||
84 | for (i = 0; i < blen; i++) | ||
85 | *cpos++ = *pos++ ^ e[i]; | ||
86 | } | ||
87 | |||
88 | for (i = 0; i < IEEE80211_CCMP_MIC_LEN; i++) | ||
89 | mic[i] = b[i] ^ s_0[i]; | ||
90 | } | 69 | } |
91 | 70 | ||
92 | 71 | struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[]) | |
93 | int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch, | ||
94 | u8 *cdata, size_t data_len, u8 *mic, u8 *data) | ||
95 | { | 72 | { |
96 | int i, j, last_len, num_blocks; | 73 | struct crypto_aead *tfm; |
97 | u8 *pos, *cpos, *b, *s_0, *a, *b_0; | 74 | int err; |
98 | |||
99 | b = scratch; | ||
100 | s_0 = scratch + AES_BLOCK_SIZE; | ||
101 | a = scratch + 2 * AES_BLOCK_SIZE; | ||
102 | b_0 = scratch + 3 * AES_BLOCK_SIZE; | ||
103 | |||
104 | num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE); | ||
105 | last_len = data_len % AES_BLOCK_SIZE; | ||
106 | aes_ccm_prepare(tfm, scratch, a); | ||
107 | |||
108 | /* Process payload blocks */ | ||
109 | cpos = cdata; | ||
110 | pos = data; | ||
111 | for (j = 1; j <= num_blocks; j++) { | ||
112 | int blen = (j == num_blocks && last_len) ? | ||
113 | last_len : AES_BLOCK_SIZE; | ||
114 | |||
115 | /* Decryption followed by authentication */ | ||
116 | b_0[14] = (j >> 8) & 0xff; | ||
117 | b_0[15] = j & 0xff; | ||
118 | crypto_cipher_encrypt_one(tfm, b, b_0); | ||
119 | for (i = 0; i < blen; i++) { | ||
120 | *pos = *cpos++ ^ b[i]; | ||
121 | a[i] ^= *pos++; | ||
122 | } | ||
123 | crypto_cipher_encrypt_one(tfm, a, a); | ||
124 | } | ||
125 | |||
126 | for (i = 0; i < IEEE80211_CCMP_MIC_LEN; i++) { | ||
127 | if ((mic[i] ^ s_0[i]) != a[i]) | ||
128 | return -1; | ||
129 | } | ||
130 | |||
131 | return 0; | ||
132 | } | ||
133 | 75 | ||
76 | tfm = crypto_alloc_aead("ccm(aes)", 0, CRYPTO_ALG_ASYNC); | ||
77 | if (IS_ERR(tfm)) | ||
78 | return tfm; | ||
134 | 79 | ||
135 | struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[]) | 80 | err = crypto_aead_setkey(tfm, key, WLAN_KEY_LEN_CCMP); |
136 | { | 81 | if (!err) |
137 | struct crypto_cipher *tfm; | 82 | err = crypto_aead_setauthsize(tfm, IEEE80211_CCMP_MIC_LEN); |
83 | if (!err) | ||
84 | return tfm; | ||
138 | 85 | ||
139 | tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); | 86 | crypto_free_aead(tfm); |
140 | if (!IS_ERR(tfm)) | 87 | return ERR_PTR(err); |
141 | crypto_cipher_setkey(tfm, key, WLAN_KEY_LEN_CCMP); | ||
142 | |||
143 | return tfm; | ||
144 | } | 88 | } |
145 | 89 | ||
146 | 90 | void ieee80211_aes_key_free(struct crypto_aead *tfm) | |
147 | void ieee80211_aes_key_free(struct crypto_cipher *tfm) | ||
148 | { | 91 | { |
149 | crypto_free_cipher(tfm); | 92 | crypto_free_aead(tfm); |
150 | } | 93 | } |
diff --git a/net/mac80211/aes_ccm.h b/net/mac80211/aes_ccm.h index 5b7d744e2370..2c7ab1948a2e 100644 --- a/net/mac80211/aes_ccm.h +++ b/net/mac80211/aes_ccm.h | |||
@@ -12,13 +12,11 @@ | |||
12 | 12 | ||
13 | #include <linux/crypto.h> | 13 | #include <linux/crypto.h> |
14 | 14 | ||
15 | struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[]); | 15 | struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[]); |
16 | void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch, | 16 | void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, |
17 | u8 *data, size_t data_len, | 17 | u8 *data, size_t data_len, u8 *mic); |
18 | u8 *cdata, u8 *mic); | 18 | int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, |
19 | int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch, | 19 | u8 *data, size_t data_len, u8 *mic); |
20 | u8 *cdata, size_t data_len, | 20 | void ieee80211_aes_key_free(struct crypto_aead *tfm); |
21 | u8 *mic, u8 *data); | ||
22 | void ieee80211_aes_key_free(struct crypto_cipher *tfm); | ||
23 | 21 | ||
24 | #endif /* AES_CCM_H */ | 22 | #endif /* AES_CCM_H */ |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index b0a651cc389f..95667b088c5b 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -1059,6 +1059,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
1059 | /* abort any running channel switch */ | 1059 | /* abort any running channel switch */ |
1060 | sdata->vif.csa_active = false; | 1060 | sdata->vif.csa_active = false; |
1061 | cancel_work_sync(&sdata->csa_finalize_work); | 1061 | cancel_work_sync(&sdata->csa_finalize_work); |
1062 | cancel_work_sync(&sdata->u.ap.request_smps_work); | ||
1062 | 1063 | ||
1063 | /* turn off carrier for this interface and dependent VLANs */ | 1064 | /* turn off carrier for this interface and dependent VLANs */ |
1064 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) | 1065 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) |
@@ -1342,8 +1343,8 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
1342 | sta->plink_state = params->plink_state; | 1343 | sta->plink_state = params->plink_state; |
1343 | 1344 | ||
1344 | ieee80211_mps_sta_status_update(sta); | 1345 | ieee80211_mps_sta_status_update(sta); |
1345 | changed |= | 1346 | changed |= ieee80211_mps_set_sta_local_pm(sta, |
1346 | ieee80211_mps_local_status_update(sdata); | 1347 | NL80211_MESH_POWER_UNKNOWN); |
1347 | break; | 1348 | break; |
1348 | default: | 1349 | default: |
1349 | /* nothing */ | 1350 | /* nothing */ |
@@ -1553,6 +1554,20 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
1553 | 1554 | ||
1554 | mutex_unlock(&local->sta_mtx); | 1555 | mutex_unlock(&local->sta_mtx); |
1555 | 1556 | ||
1557 | if ((sdata->vif.type == NL80211_IFTYPE_AP || | ||
1558 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && | ||
1559 | sta->known_smps_mode != sta->sdata->bss->req_smps && | ||
1560 | test_sta_flag(sta, WLAN_STA_AUTHORIZED) && | ||
1561 | sta_info_tx_streams(sta) != 1) { | ||
1562 | ht_dbg(sta->sdata, | ||
1563 | "%pM just authorized and MIMO capable - update SMPS\n", | ||
1564 | sta->sta.addr); | ||
1565 | ieee80211_send_smps_action(sta->sdata, | ||
1566 | sta->sdata->bss->req_smps, | ||
1567 | sta->sta.addr, | ||
1568 | sta->sdata->vif.bss_conf.bssid); | ||
1569 | } | ||
1570 | |||
1556 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | 1571 | if (sdata->vif.type == NL80211_IFTYPE_STATION && |
1557 | params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) { | 1572 | params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) { |
1558 | ieee80211_recalc_ps(local, -1); | 1573 | ieee80211_recalc_ps(local, -1); |
@@ -2337,8 +2352,92 @@ static int ieee80211_testmode_dump(struct wiphy *wiphy, | |||
2337 | } | 2352 | } |
2338 | #endif | 2353 | #endif |
2339 | 2354 | ||
2340 | int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, | 2355 | int __ieee80211_request_smps_ap(struct ieee80211_sub_if_data *sdata, |
2341 | enum ieee80211_smps_mode smps_mode) | 2356 | enum ieee80211_smps_mode smps_mode) |
2357 | { | ||
2358 | struct sta_info *sta; | ||
2359 | enum ieee80211_smps_mode old_req; | ||
2360 | int i; | ||
2361 | |||
2362 | if (WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_AP)) | ||
2363 | return -EINVAL; | ||
2364 | |||
2365 | if (sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT) | ||
2366 | return 0; | ||
2367 | |||
2368 | old_req = sdata->u.ap.req_smps; | ||
2369 | sdata->u.ap.req_smps = smps_mode; | ||
2370 | |||
2371 | /* AUTOMATIC doesn't mean much for AP - don't allow it */ | ||
2372 | if (old_req == smps_mode || | ||
2373 | smps_mode == IEEE80211_SMPS_AUTOMATIC) | ||
2374 | return 0; | ||
2375 | |||
2376 | /* If no associated stations, there's no need to do anything */ | ||
2377 | if (!atomic_read(&sdata->u.ap.num_mcast_sta)) { | ||
2378 | sdata->smps_mode = smps_mode; | ||
2379 | ieee80211_queue_work(&sdata->local->hw, &sdata->recalc_smps); | ||
2380 | return 0; | ||
2381 | } | ||
2382 | |||
2383 | ht_dbg(sdata, | ||
2384 | "SMSP %d requested in AP mode, sending Action frame to %d stations\n", | ||
2385 | smps_mode, atomic_read(&sdata->u.ap.num_mcast_sta)); | ||
2386 | |||
2387 | mutex_lock(&sdata->local->sta_mtx); | ||
2388 | for (i = 0; i < STA_HASH_SIZE; i++) { | ||
2389 | for (sta = rcu_dereference_protected(sdata->local->sta_hash[i], | ||
2390 | lockdep_is_held(&sdata->local->sta_mtx)); | ||
2391 | sta; | ||
2392 | sta = rcu_dereference_protected(sta->hnext, | ||
2393 | lockdep_is_held(&sdata->local->sta_mtx))) { | ||
2394 | /* | ||
2395 | * Only stations associated to our AP and | ||
2396 | * associated VLANs | ||
2397 | */ | ||
2398 | if (sta->sdata->bss != &sdata->u.ap) | ||
2399 | continue; | ||
2400 | |||
2401 | /* This station doesn't support MIMO - skip it */ | ||
2402 | if (sta_info_tx_streams(sta) == 1) | ||
2403 | continue; | ||
2404 | |||
2405 | /* | ||
2406 | * Don't wake up a STA just to send the action frame | ||
2407 | * unless we are getting more restrictive. | ||
2408 | */ | ||
2409 | if (test_sta_flag(sta, WLAN_STA_PS_STA) && | ||
2410 | !ieee80211_smps_is_restrictive(sta->known_smps_mode, | ||
2411 | smps_mode)) { | ||
2412 | ht_dbg(sdata, | ||
2413 | "Won't send SMPS to sleeping STA %pM\n", | ||
2414 | sta->sta.addr); | ||
2415 | continue; | ||
2416 | } | ||
2417 | |||
2418 | /* | ||
2419 | * If the STA is not authorized, wait until it gets | ||
2420 | * authorized and the action frame will be sent then. | ||
2421 | */ | ||
2422 | if (!test_sta_flag(sta, WLAN_STA_AUTHORIZED)) | ||
2423 | continue; | ||
2424 | |||
2425 | ht_dbg(sdata, "Sending SMPS to %pM\n", sta->sta.addr); | ||
2426 | ieee80211_send_smps_action(sdata, smps_mode, | ||
2427 | sta->sta.addr, | ||
2428 | sdata->vif.bss_conf.bssid); | ||
2429 | } | ||
2430 | } | ||
2431 | mutex_unlock(&sdata->local->sta_mtx); | ||
2432 | |||
2433 | sdata->smps_mode = smps_mode; | ||
2434 | ieee80211_queue_work(&sdata->local->hw, &sdata->recalc_smps); | ||
2435 | |||
2436 | return 0; | ||
2437 | } | ||
2438 | |||
2439 | int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata, | ||
2440 | enum ieee80211_smps_mode smps_mode) | ||
2342 | { | 2441 | { |
2343 | const u8 *ap; | 2442 | const u8 *ap; |
2344 | enum ieee80211_smps_mode old_req; | 2443 | enum ieee80211_smps_mode old_req; |
@@ -2346,6 +2445,9 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, | |||
2346 | 2445 | ||
2347 | lockdep_assert_held(&sdata->wdev.mtx); | 2446 | lockdep_assert_held(&sdata->wdev.mtx); |
2348 | 2447 | ||
2448 | if (WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION)) | ||
2449 | return -EINVAL; | ||
2450 | |||
2349 | old_req = sdata->u.mgd.req_smps; | 2451 | old_req = sdata->u.mgd.req_smps; |
2350 | sdata->u.mgd.req_smps = smps_mode; | 2452 | sdata->u.mgd.req_smps = smps_mode; |
2351 | 2453 | ||
@@ -2402,7 +2504,7 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, | |||
2402 | 2504 | ||
2403 | /* no change, but if automatic follow powersave */ | 2505 | /* no change, but if automatic follow powersave */ |
2404 | sdata_lock(sdata); | 2506 | sdata_lock(sdata); |
2405 | __ieee80211_request_smps(sdata, sdata->u.mgd.req_smps); | 2507 | __ieee80211_request_smps_mgd(sdata, sdata->u.mgd.req_smps); |
2406 | sdata_unlock(sdata); | 2508 | sdata_unlock(sdata); |
2407 | 2509 | ||
2408 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) | 2510 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) |
@@ -2860,7 +2962,7 @@ void ieee80211_csa_finalize_work(struct work_struct *work) | |||
2860 | container_of(work, struct ieee80211_sub_if_data, | 2962 | container_of(work, struct ieee80211_sub_if_data, |
2861 | csa_finalize_work); | 2963 | csa_finalize_work); |
2862 | struct ieee80211_local *local = sdata->local; | 2964 | struct ieee80211_local *local = sdata->local; |
2863 | int err, changed; | 2965 | int err, changed = 0; |
2864 | 2966 | ||
2865 | if (!ieee80211_sdata_running(sdata)) | 2967 | if (!ieee80211_sdata_running(sdata)) |
2866 | return; | 2968 | return; |
@@ -2892,6 +2994,13 @@ void ieee80211_csa_finalize_work(struct work_struct *work) | |||
2892 | case NL80211_IFTYPE_ADHOC: | 2994 | case NL80211_IFTYPE_ADHOC: |
2893 | ieee80211_ibss_finish_csa(sdata); | 2995 | ieee80211_ibss_finish_csa(sdata); |
2894 | break; | 2996 | break; |
2997 | #ifdef CONFIG_MAC80211_MESH | ||
2998 | case NL80211_IFTYPE_MESH_POINT: | ||
2999 | err = ieee80211_mesh_finish_csa(sdata); | ||
3000 | if (err < 0) | ||
3001 | return; | ||
3002 | break; | ||
3003 | #endif | ||
2895 | default: | 3004 | default: |
2896 | WARN_ON(1); | 3005 | WARN_ON(1); |
2897 | return; | 3006 | return; |
@@ -2912,6 +3021,7 @@ static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
2912 | struct ieee80211_local *local = sdata->local; | 3021 | struct ieee80211_local *local = sdata->local; |
2913 | struct ieee80211_chanctx_conf *chanctx_conf; | 3022 | struct ieee80211_chanctx_conf *chanctx_conf; |
2914 | struct ieee80211_chanctx *chanctx; | 3023 | struct ieee80211_chanctx *chanctx; |
3024 | struct ieee80211_if_mesh __maybe_unused *ifmsh; | ||
2915 | int err, num_chanctx; | 3025 | int err, num_chanctx; |
2916 | 3026 | ||
2917 | if (!list_empty(&local->roc_list) || local->scanning) | 3027 | if (!list_empty(&local->roc_list) || local->scanning) |
@@ -2995,6 +3105,26 @@ static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
2995 | if (err < 0) | 3105 | if (err < 0) |
2996 | return err; | 3106 | return err; |
2997 | break; | 3107 | break; |
3108 | #ifdef CONFIG_MAC80211_MESH | ||
3109 | case NL80211_IFTYPE_MESH_POINT: | ||
3110 | ifmsh = &sdata->u.mesh; | ||
3111 | |||
3112 | if (!ifmsh->mesh_id) | ||
3113 | return -EINVAL; | ||
3114 | |||
3115 | if (params->chandef.width != sdata->vif.bss_conf.chandef.width) | ||
3116 | return -EINVAL; | ||
3117 | |||
3118 | /* changes into another band are not supported */ | ||
3119 | if (sdata->vif.bss_conf.chandef.chan->band != | ||
3120 | params->chandef.chan->band) | ||
3121 | return -EINVAL; | ||
3122 | |||
3123 | err = ieee80211_mesh_csa_beacon(sdata, params, true); | ||
3124 | if (err < 0) | ||
3125 | return err; | ||
3126 | break; | ||
3127 | #endif | ||
2998 | default: | 3128 | default: |
2999 | return -EOPNOTSUPP; | 3129 | return -EOPNOTSUPP; |
3000 | } | 3130 | } |
diff --git a/net/mac80211/debug.h b/net/mac80211/debug.h index 4ccc5ed6237d..493d68061f0c 100644 --- a/net/mac80211/debug.h +++ b/net/mac80211/debug.h | |||
@@ -44,6 +44,12 @@ | |||
44 | #define MAC80211_MESH_SYNC_DEBUG 0 | 44 | #define MAC80211_MESH_SYNC_DEBUG 0 |
45 | #endif | 45 | #endif |
46 | 46 | ||
47 | #ifdef CONFIG_MAC80211_MESH_CSA_DEBUG | ||
48 | #define MAC80211_MESH_CSA_DEBUG 1 | ||
49 | #else | ||
50 | #define MAC80211_MESH_CSA_DEBUG 0 | ||
51 | #endif | ||
52 | |||
47 | #ifdef CONFIG_MAC80211_MESH_PS_DEBUG | 53 | #ifdef CONFIG_MAC80211_MESH_PS_DEBUG |
48 | #define MAC80211_MESH_PS_DEBUG 1 | 54 | #define MAC80211_MESH_PS_DEBUG 1 |
49 | #else | 55 | #else |
@@ -157,6 +163,10 @@ do { \ | |||
157 | _sdata_dbg(MAC80211_MESH_SYNC_DEBUG, \ | 163 | _sdata_dbg(MAC80211_MESH_SYNC_DEBUG, \ |
158 | sdata, fmt, ##__VA_ARGS__) | 164 | sdata, fmt, ##__VA_ARGS__) |
159 | 165 | ||
166 | #define mcsa_dbg(sdata, fmt, ...) \ | ||
167 | _sdata_dbg(MAC80211_MESH_CSA_DEBUG, \ | ||
168 | sdata, fmt, ##__VA_ARGS__) | ||
169 | |||
160 | #define mps_dbg(sdata, fmt, ...) \ | 170 | #define mps_dbg(sdata, fmt, ...) \ |
161 | _sdata_dbg(MAC80211_MESH_PS_DEBUG, \ | 171 | _sdata_dbg(MAC80211_MESH_PS_DEBUG, \ |
162 | sdata, fmt, ##__VA_ARGS__) | 172 | sdata, fmt, ##__VA_ARGS__) |
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index cafe614ef93d..04b5a14c8a05 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -224,12 +224,15 @@ static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata, | |||
224 | smps_mode == IEEE80211_SMPS_AUTOMATIC)) | 224 | smps_mode == IEEE80211_SMPS_AUTOMATIC)) |
225 | return -EINVAL; | 225 | return -EINVAL; |
226 | 226 | ||
227 | /* supported only on managed interfaces for now */ | 227 | if (sdata->vif.type != NL80211_IFTYPE_STATION && |
228 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 228 | sdata->vif.type != NL80211_IFTYPE_AP) |
229 | return -EOPNOTSUPP; | 229 | return -EOPNOTSUPP; |
230 | 230 | ||
231 | sdata_lock(sdata); | 231 | sdata_lock(sdata); |
232 | err = __ieee80211_request_smps(sdata, smps_mode); | 232 | if (sdata->vif.type == NL80211_IFTYPE_STATION) |
233 | err = __ieee80211_request_smps_mgd(sdata, smps_mode); | ||
234 | else | ||
235 | err = __ieee80211_request_smps_ap(sdata, smps_mode); | ||
233 | sdata_unlock(sdata); | 236 | sdata_unlock(sdata); |
234 | 237 | ||
235 | return err; | 238 | return err; |
@@ -245,12 +248,15 @@ static const char *smps_modes[IEEE80211_SMPS_NUM_MODES] = { | |||
245 | static ssize_t ieee80211_if_fmt_smps(const struct ieee80211_sub_if_data *sdata, | 248 | static ssize_t ieee80211_if_fmt_smps(const struct ieee80211_sub_if_data *sdata, |
246 | char *buf, int buflen) | 249 | char *buf, int buflen) |
247 | { | 250 | { |
248 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 251 | if (sdata->vif.type == NL80211_IFTYPE_STATION) |
249 | return -EOPNOTSUPP; | 252 | return snprintf(buf, buflen, "request: %s\nused: %s\n", |
250 | 253 | smps_modes[sdata->u.mgd.req_smps], | |
251 | return snprintf(buf, buflen, "request: %s\nused: %s\n", | 254 | smps_modes[sdata->smps_mode]); |
252 | smps_modes[sdata->u.mgd.req_smps], | 255 | if (sdata->vif.type == NL80211_IFTYPE_AP) |
253 | smps_modes[sdata->smps_mode]); | 256 | return snprintf(buf, buflen, "request: %s\nused: %s\n", |
257 | smps_modes[sdata->u.ap.req_smps], | ||
258 | smps_modes[sdata->smps_mode]); | ||
259 | return -EINVAL; | ||
254 | } | 260 | } |
255 | 261 | ||
256 | static ssize_t ieee80211_if_parse_smps(struct ieee80211_sub_if_data *sdata, | 262 | static ssize_t ieee80211_if_parse_smps(struct ieee80211_sub_if_data *sdata, |
@@ -563,6 +569,7 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata) | |||
563 | static void add_ap_files(struct ieee80211_sub_if_data *sdata) | 569 | static void add_ap_files(struct ieee80211_sub_if_data *sdata) |
564 | { | 570 | { |
565 | DEBUGFS_ADD(num_mcast_sta); | 571 | DEBUGFS_ADD(num_mcast_sta); |
572 | DEBUGFS_ADD_MODE(smps, 0600); | ||
566 | DEBUGFS_ADD(num_sta_ps); | 573 | DEBUGFS_ADD(num_sta_ps); |
567 | DEBUGFS_ADD(dtim_count); | 574 | DEBUGFS_ADD(dtim_count); |
568 | DEBUGFS_ADD(num_buffered_multicast); | 575 | DEBUGFS_ADD(num_buffered_multicast); |
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 529bf58bc145..9a8be8f69224 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -448,14 +448,25 @@ int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, | |||
448 | return 0; | 448 | return 0; |
449 | } | 449 | } |
450 | 450 | ||
451 | void ieee80211_request_smps_work(struct work_struct *work) | 451 | void ieee80211_request_smps_mgd_work(struct work_struct *work) |
452 | { | 452 | { |
453 | struct ieee80211_sub_if_data *sdata = | 453 | struct ieee80211_sub_if_data *sdata = |
454 | container_of(work, struct ieee80211_sub_if_data, | 454 | container_of(work, struct ieee80211_sub_if_data, |
455 | u.mgd.request_smps_work); | 455 | u.mgd.request_smps_work); |
456 | 456 | ||
457 | sdata_lock(sdata); | 457 | sdata_lock(sdata); |
458 | __ieee80211_request_smps(sdata, sdata->u.mgd.driver_smps_mode); | 458 | __ieee80211_request_smps_mgd(sdata, sdata->u.mgd.driver_smps_mode); |
459 | sdata_unlock(sdata); | ||
460 | } | ||
461 | |||
462 | void ieee80211_request_smps_ap_work(struct work_struct *work) | ||
463 | { | ||
464 | struct ieee80211_sub_if_data *sdata = | ||
465 | container_of(work, struct ieee80211_sub_if_data, | ||
466 | u.ap.request_smps_work); | ||
467 | |||
468 | sdata_lock(sdata); | ||
469 | __ieee80211_request_smps_ap(sdata, sdata->u.ap.driver_smps_mode); | ||
459 | sdata_unlock(sdata); | 470 | sdata_unlock(sdata); |
460 | } | 471 | } |
461 | 472 | ||
@@ -464,19 +475,29 @@ void ieee80211_request_smps(struct ieee80211_vif *vif, | |||
464 | { | 475 | { |
465 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | 476 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); |
466 | 477 | ||
467 | if (WARN_ON(vif->type != NL80211_IFTYPE_STATION)) | 478 | if (WARN_ON_ONCE(vif->type != NL80211_IFTYPE_STATION && |
479 | vif->type != NL80211_IFTYPE_AP)) | ||
468 | return; | 480 | return; |
469 | 481 | ||
470 | if (WARN_ON(smps_mode == IEEE80211_SMPS_OFF)) | 482 | if (WARN_ON(smps_mode == IEEE80211_SMPS_OFF)) |
471 | smps_mode = IEEE80211_SMPS_AUTOMATIC; | 483 | smps_mode = IEEE80211_SMPS_AUTOMATIC; |
472 | 484 | ||
473 | if (sdata->u.mgd.driver_smps_mode == smps_mode) | 485 | if (vif->type == NL80211_IFTYPE_STATION) { |
474 | return; | 486 | if (sdata->u.mgd.driver_smps_mode == smps_mode) |
475 | 487 | return; | |
476 | sdata->u.mgd.driver_smps_mode = smps_mode; | 488 | sdata->u.mgd.driver_smps_mode = smps_mode; |
477 | 489 | ieee80211_queue_work(&sdata->local->hw, | |
478 | ieee80211_queue_work(&sdata->local->hw, | 490 | &sdata->u.mgd.request_smps_work); |
479 | &sdata->u.mgd.request_smps_work); | 491 | } else { |
492 | /* AUTOMATIC is meaningless in AP mode */ | ||
493 | if (WARN_ON_ONCE(smps_mode == IEEE80211_SMPS_AUTOMATIC)) | ||
494 | return; | ||
495 | if (sdata->u.ap.driver_smps_mode == smps_mode) | ||
496 | return; | ||
497 | sdata->u.ap.driver_smps_mode = smps_mode; | ||
498 | ieee80211_queue_work(&sdata->local->hw, | ||
499 | &sdata->u.ap.request_smps_work); | ||
500 | } | ||
480 | } | 501 | } |
481 | /* this might change ... don't want non-open drivers using it */ | 502 | /* this might change ... don't want non-open drivers using it */ |
482 | EXPORT_SYMBOL_GPL(ieee80211_request_smps); | 503 | EXPORT_SYMBOL_GPL(ieee80211_request_smps); |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 21a0b8835cb3..531be040b9ae 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -229,6 +229,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
229 | struct beacon_data *presp; | 229 | struct beacon_data *presp; |
230 | enum nl80211_bss_scan_width scan_width; | 230 | enum nl80211_bss_scan_width scan_width; |
231 | bool have_higher_than_11mbit; | 231 | bool have_higher_than_11mbit; |
232 | bool radar_required = false; | ||
232 | int err; | 233 | int err; |
233 | 234 | ||
234 | sdata_assert_lock(sdata); | 235 | sdata_assert_lock(sdata); |
@@ -273,6 +274,23 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
273 | } | 274 | } |
274 | chandef.width = NL80211_CHAN_WIDTH_20; | 275 | chandef.width = NL80211_CHAN_WIDTH_20; |
275 | chandef.center_freq1 = chan->center_freq; | 276 | chandef.center_freq1 = chan->center_freq; |
277 | /* check again for downgraded chandef */ | ||
278 | if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef)) { | ||
279 | sdata_info(sdata, | ||
280 | "Failed to join IBSS, beacons forbidden\n"); | ||
281 | return; | ||
282 | } | ||
283 | } | ||
284 | |||
285 | err = cfg80211_chandef_dfs_required(sdata->local->hw.wiphy, | ||
286 | &chandef); | ||
287 | if (err > 0) { | ||
288 | if (!ifibss->userspace_handles_dfs) { | ||
289 | sdata_info(sdata, | ||
290 | "Failed to join IBSS, DFS channel without control program\n"); | ||
291 | return; | ||
292 | } | ||
293 | radar_required = true; | ||
276 | } | 294 | } |
277 | 295 | ||
278 | ieee80211_vif_release_channel(sdata); | 296 | ieee80211_vif_release_channel(sdata); |
@@ -297,6 +315,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
297 | rcu_assign_pointer(ifibss->presp, presp); | 315 | rcu_assign_pointer(ifibss->presp, presp); |
298 | mgmt = (void *)presp->head; | 316 | mgmt = (void *)presp->head; |
299 | 317 | ||
318 | sdata->radar_required = radar_required; | ||
300 | sdata->vif.bss_conf.enable_beacon = true; | 319 | sdata->vif.bss_conf.enable_beacon = true; |
301 | sdata->vif.bss_conf.beacon_int = beacon_int; | 320 | sdata->vif.bss_conf.beacon_int = beacon_int; |
302 | sdata->vif.bss_conf.basic_rates = basic_rates; | 321 | sdata->vif.bss_conf.basic_rates = basic_rates; |
@@ -445,60 +464,6 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
445 | tsf, false); | 464 | tsf, false); |
446 | } | 465 | } |
447 | 466 | ||
448 | static int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata, | ||
449 | struct cfg80211_csa_settings *csa_settings) | ||
450 | { | ||
451 | struct sk_buff *skb; | ||
452 | struct ieee80211_mgmt *mgmt; | ||
453 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | ||
454 | struct ieee80211_local *local = sdata->local; | ||
455 | int freq; | ||
456 | int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.chan_switch) + | ||
457 | sizeof(mgmt->u.action.u.chan_switch); | ||
458 | u8 *pos; | ||
459 | |||
460 | skb = dev_alloc_skb(local->tx_headroom + hdr_len + | ||
461 | 5 + /* channel switch announcement element */ | ||
462 | 3); /* secondary channel offset element */ | ||
463 | if (!skb) | ||
464 | return -1; | ||
465 | |||
466 | skb_reserve(skb, local->tx_headroom); | ||
467 | mgmt = (struct ieee80211_mgmt *)skb_put(skb, hdr_len); | ||
468 | memset(mgmt, 0, hdr_len); | ||
469 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
470 | IEEE80211_STYPE_ACTION); | ||
471 | |||
472 | eth_broadcast_addr(mgmt->da); | ||
473 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); | ||
474 | memcpy(mgmt->bssid, ifibss->bssid, ETH_ALEN); | ||
475 | mgmt->u.action.category = WLAN_CATEGORY_SPECTRUM_MGMT; | ||
476 | mgmt->u.action.u.chan_switch.action_code = WLAN_ACTION_SPCT_CHL_SWITCH; | ||
477 | pos = skb_put(skb, 5); | ||
478 | *pos++ = WLAN_EID_CHANNEL_SWITCH; /* EID */ | ||
479 | *pos++ = 3; /* IE length */ | ||
480 | *pos++ = csa_settings->block_tx ? 1 : 0; /* CSA mode */ | ||
481 | freq = csa_settings->chandef.chan->center_freq; | ||
482 | *pos++ = ieee80211_frequency_to_channel(freq); /* channel */ | ||
483 | *pos++ = csa_settings->count; /* count */ | ||
484 | |||
485 | if (csa_settings->chandef.width == NL80211_CHAN_WIDTH_40) { | ||
486 | enum nl80211_channel_type ch_type; | ||
487 | |||
488 | skb_put(skb, 3); | ||
489 | *pos++ = WLAN_EID_SECONDARY_CHANNEL_OFFSET; /* EID */ | ||
490 | *pos++ = 1; /* IE length */ | ||
491 | ch_type = cfg80211_get_chandef_type(&csa_settings->chandef); | ||
492 | if (ch_type == NL80211_CHAN_HT40PLUS) | ||
493 | *pos++ = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; | ||
494 | else | ||
495 | *pos++ = IEEE80211_HT_PARAM_CHA_SEC_BELOW; | ||
496 | } | ||
497 | |||
498 | ieee80211_tx_skb(sdata, skb); | ||
499 | return 0; | ||
500 | } | ||
501 | |||
502 | int ieee80211_ibss_csa_beacon(struct ieee80211_sub_if_data *sdata, | 467 | int ieee80211_ibss_csa_beacon(struct ieee80211_sub_if_data *sdata, |
503 | struct cfg80211_csa_settings *csa_settings) | 468 | struct cfg80211_csa_settings *csa_settings) |
504 | { | 469 | { |
@@ -796,19 +761,34 @@ static void ieee80211_csa_connection_drop_work(struct work_struct *work) | |||
796 | ieee80211_queue_work(&sdata->local->hw, &sdata->work); | 761 | ieee80211_queue_work(&sdata->local->hw, &sdata->work); |
797 | } | 762 | } |
798 | 763 | ||
764 | static void ieee80211_ibss_csa_mark_radar(struct ieee80211_sub_if_data *sdata) | ||
765 | { | ||
766 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | ||
767 | int err; | ||
768 | |||
769 | /* if the current channel is a DFS channel, mark the channel as | ||
770 | * unavailable. | ||
771 | */ | ||
772 | err = cfg80211_chandef_dfs_required(sdata->local->hw.wiphy, | ||
773 | &ifibss->chandef); | ||
774 | if (err > 0) | ||
775 | cfg80211_radar_event(sdata->local->hw.wiphy, &ifibss->chandef, | ||
776 | GFP_ATOMIC); | ||
777 | } | ||
778 | |||
799 | static bool | 779 | static bool |
800 | ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata, | 780 | ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata, |
801 | struct ieee802_11_elems *elems, | 781 | struct ieee802_11_elems *elems, |
802 | bool beacon) | 782 | bool beacon) |
803 | { | 783 | { |
804 | struct cfg80211_csa_settings params; | 784 | struct cfg80211_csa_settings params; |
785 | struct ieee80211_csa_ie csa_ie; | ||
805 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 786 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
806 | struct ieee80211_chanctx_conf *chanctx_conf; | 787 | struct ieee80211_chanctx_conf *chanctx_conf; |
807 | struct ieee80211_chanctx *chanctx; | 788 | struct ieee80211_chanctx *chanctx; |
808 | enum nl80211_channel_type ch_type; | 789 | enum nl80211_channel_type ch_type; |
809 | int err, num_chanctx; | 790 | int err, num_chanctx; |
810 | u32 sta_flags; | 791 | u32 sta_flags; |
811 | u8 mode; | ||
812 | 792 | ||
813 | if (sdata->vif.csa_active) | 793 | if (sdata->vif.csa_active) |
814 | return true; | 794 | return true; |
@@ -831,12 +811,10 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
831 | } | 811 | } |
832 | 812 | ||
833 | memset(¶ms, 0, sizeof(params)); | 813 | memset(¶ms, 0, sizeof(params)); |
814 | memset(&csa_ie, 0, sizeof(csa_ie)); | ||
834 | err = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, | 815 | err = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, |
835 | ifibss->chandef.chan->band, | 816 | ifibss->chandef.chan->band, |
836 | sta_flags, ifibss->bssid, | 817 | sta_flags, ifibss->bssid, &csa_ie); |
837 | ¶ms.count, &mode, | ||
838 | ¶ms.chandef); | ||
839 | |||
840 | /* can't switch to destination channel, fail */ | 818 | /* can't switch to destination channel, fail */ |
841 | if (err < 0) | 819 | if (err < 0) |
842 | goto disconnect; | 820 | goto disconnect; |
@@ -845,6 +823,9 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
845 | if (err) | 823 | if (err) |
846 | return false; | 824 | return false; |
847 | 825 | ||
826 | params.count = csa_ie.count; | ||
827 | params.chandef = csa_ie.chandef; | ||
828 | |||
848 | if (ifibss->chandef.chan->band != params.chandef.chan->band) | 829 | if (ifibss->chandef.chan->band != params.chandef.chan->band) |
849 | goto disconnect; | 830 | goto disconnect; |
850 | 831 | ||
@@ -880,8 +861,7 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
880 | goto disconnect; | 861 | goto disconnect; |
881 | } | 862 | } |
882 | 863 | ||
883 | if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, ¶ms.chandef, | 864 | if (!cfg80211_reg_can_beacon(sdata->local->hw.wiphy, ¶ms.chandef)) { |
884 | IEEE80211_CHAN_DISABLED)) { | ||
885 | sdata_info(sdata, | 865 | sdata_info(sdata, |
886 | "IBSS %pM switches to unsupported channel (%d MHz, width:%d, CF1/2: %d/%d MHz), disconnecting\n", | 866 | "IBSS %pM switches to unsupported channel (%d MHz, width:%d, CF1/2: %d/%d MHz), disconnecting\n", |
887 | ifibss->bssid, | 867 | ifibss->bssid, |
@@ -897,10 +877,11 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
897 | if (err < 0) | 877 | if (err < 0) |
898 | goto disconnect; | 878 | goto disconnect; |
899 | if (err) { | 879 | if (err) { |
900 | params.radar_required = true; | 880 | /* IBSS-DFS only allowed with a control program */ |
881 | if (!ifibss->userspace_handles_dfs) | ||
882 | goto disconnect; | ||
901 | 883 | ||
902 | /* TODO: IBSS-DFS not (yet) supported, disconnect. */ | 884 | params.radar_required = true; |
903 | goto disconnect; | ||
904 | } | 885 | } |
905 | 886 | ||
906 | rcu_read_lock(); | 887 | rcu_read_lock(); |
@@ -931,7 +912,7 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
931 | "received channel switch announcement to go to channel %d MHz\n", | 912 | "received channel switch announcement to go to channel %d MHz\n", |
932 | params.chandef.chan->center_freq); | 913 | params.chandef.chan->center_freq); |
933 | 914 | ||
934 | params.block_tx = !!mode; | 915 | params.block_tx = !!csa_ie.mode; |
935 | 916 | ||
936 | ieee80211_ibss_csa_beacon(sdata, ¶ms); | 917 | ieee80211_ibss_csa_beacon(sdata, ¶ms); |
937 | sdata->csa_radar_required = params.radar_required; | 918 | sdata->csa_radar_required = params.radar_required; |
@@ -947,12 +928,16 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
947 | ieee80211_bss_info_change_notify(sdata, err); | 928 | ieee80211_bss_info_change_notify(sdata, err); |
948 | drv_channel_switch_beacon(sdata, ¶ms.chandef); | 929 | drv_channel_switch_beacon(sdata, ¶ms.chandef); |
949 | 930 | ||
931 | ieee80211_ibss_csa_mark_radar(sdata); | ||
932 | |||
950 | return true; | 933 | return true; |
951 | disconnect: | 934 | disconnect: |
952 | ibss_dbg(sdata, "Can't handle channel switch, disconnect\n"); | 935 | ibss_dbg(sdata, "Can't handle channel switch, disconnect\n"); |
953 | ieee80211_queue_work(&sdata->local->hw, | 936 | ieee80211_queue_work(&sdata->local->hw, |
954 | &ifibss->csa_connection_drop_work); | 937 | &ifibss->csa_connection_drop_work); |
955 | 938 | ||
939 | ieee80211_ibss_csa_mark_radar(sdata); | ||
940 | |||
956 | return true; | 941 | return true; |
957 | } | 942 | } |
958 | 943 | ||
@@ -1688,6 +1673,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
1688 | 1673 | ||
1689 | sdata->u.ibss.privacy = params->privacy; | 1674 | sdata->u.ibss.privacy = params->privacy; |
1690 | sdata->u.ibss.control_port = params->control_port; | 1675 | sdata->u.ibss.control_port = params->control_port; |
1676 | sdata->u.ibss.userspace_handles_dfs = params->userspace_handles_dfs; | ||
1691 | sdata->u.ibss.basic_rates = params->basic_rates; | 1677 | sdata->u.ibss.basic_rates = params->basic_rates; |
1692 | 1678 | ||
1693 | /* fix basic_rates if channel does not support these rates */ | 1679 | /* fix basic_rates if channel does not support these rates */ |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index fe48b093d4dc..29dc505be125 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -262,6 +262,10 @@ struct ieee80211_if_ap { | |||
262 | 262 | ||
263 | struct ps_data ps; | 263 | struct ps_data ps; |
264 | atomic_t num_mcast_sta; /* number of stations receiving multicast */ | 264 | atomic_t num_mcast_sta; /* number of stations receiving multicast */ |
265 | enum ieee80211_smps_mode req_smps, /* requested smps mode */ | ||
266 | driver_smps_mode; /* smps mode request */ | ||
267 | |||
268 | struct work_struct request_smps_work; | ||
265 | }; | 269 | }; |
266 | 270 | ||
267 | struct ieee80211_if_wds { | 271 | struct ieee80211_if_wds { |
@@ -498,6 +502,7 @@ struct ieee80211_if_ibss { | |||
498 | bool privacy; | 502 | bool privacy; |
499 | 503 | ||
500 | bool control_port; | 504 | bool control_port; |
505 | bool userspace_handles_dfs; | ||
501 | 506 | ||
502 | u8 bssid[ETH_ALEN] __aligned(2); | 507 | u8 bssid[ETH_ALEN] __aligned(2); |
503 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | 508 | u8 ssid[IEEE80211_MAX_SSID_LEN]; |
@@ -539,6 +544,11 @@ struct ieee80211_mesh_sync_ops { | |||
539 | /* add other framework functions here */ | 544 | /* add other framework functions here */ |
540 | }; | 545 | }; |
541 | 546 | ||
547 | struct mesh_csa_settings { | ||
548 | struct rcu_head rcu_head; | ||
549 | struct cfg80211_csa_settings settings; | ||
550 | }; | ||
551 | |||
542 | struct ieee80211_if_mesh { | 552 | struct ieee80211_if_mesh { |
543 | struct timer_list housekeeping_timer; | 553 | struct timer_list housekeeping_timer; |
544 | struct timer_list mesh_path_timer; | 554 | struct timer_list mesh_path_timer; |
@@ -599,6 +609,11 @@ struct ieee80211_if_mesh { | |||
599 | int ps_peers_light_sleep; | 609 | int ps_peers_light_sleep; |
600 | int ps_peers_deep_sleep; | 610 | int ps_peers_deep_sleep; |
601 | struct ps_data ps; | 611 | struct ps_data ps; |
612 | /* Channel Switching Support */ | ||
613 | struct mesh_csa_settings __rcu *csa; | ||
614 | bool chsw_init; | ||
615 | u8 chsw_ttl; | ||
616 | u16 pre_value; | ||
602 | }; | 617 | }; |
603 | 618 | ||
604 | #ifdef CONFIG_MAC80211_MESH | 619 | #ifdef CONFIG_MAC80211_MESH |
@@ -1207,6 +1222,14 @@ struct ieee80211_ra_tid { | |||
1207 | u16 tid; | 1222 | u16 tid; |
1208 | }; | 1223 | }; |
1209 | 1224 | ||
1225 | /* this struct holds the value parsing from channel switch IE */ | ||
1226 | struct ieee80211_csa_ie { | ||
1227 | struct cfg80211_chan_def chandef; | ||
1228 | u8 mode; | ||
1229 | u8 count; | ||
1230 | u8 ttl; | ||
1231 | }; | ||
1232 | |||
1210 | /* Parsed Information Elements */ | 1233 | /* Parsed Information Elements */ |
1211 | struct ieee802_11_elems { | 1234 | struct ieee802_11_elems { |
1212 | const u8 *ie_start; | 1235 | const u8 *ie_start; |
@@ -1243,6 +1266,7 @@ struct ieee802_11_elems { | |||
1243 | const struct ieee80211_timeout_interval_ie *timeout_int; | 1266 | const struct ieee80211_timeout_interval_ie *timeout_int; |
1244 | const u8 *opmode_notif; | 1267 | const u8 *opmode_notif; |
1245 | const struct ieee80211_sec_chan_offs_ie *sec_chan_offs; | 1268 | const struct ieee80211_sec_chan_offs_ie *sec_chan_offs; |
1269 | const struct ieee80211_mesh_chansw_params_ie *mesh_chansw_params_ie; | ||
1246 | 1270 | ||
1247 | /* length of them, respectively */ | 1271 | /* length of them, respectively */ |
1248 | u8 ssid_len; | 1272 | u8 ssid_len; |
@@ -1343,6 +1367,10 @@ void ieee80211_ibss_stop(struct ieee80211_sub_if_data *sdata); | |||
1343 | void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata); | 1367 | void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata); |
1344 | void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | 1368 | void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, |
1345 | struct sk_buff *skb); | 1369 | struct sk_buff *skb); |
1370 | int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata, | ||
1371 | struct cfg80211_csa_settings *csa_settings, | ||
1372 | bool csa_action); | ||
1373 | int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata); | ||
1346 | 1374 | ||
1347 | /* scan/BSS handling */ | 1375 | /* scan/BSS handling */ |
1348 | void ieee80211_scan_work(struct work_struct *work); | 1376 | void ieee80211_scan_work(struct work_struct *work); |
@@ -1439,7 +1467,10 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, | |||
1439 | int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, | 1467 | int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, |
1440 | enum ieee80211_smps_mode smps, const u8 *da, | 1468 | enum ieee80211_smps_mode smps, const u8 *da, |
1441 | const u8 *bssid); | 1469 | const u8 *bssid); |
1442 | void ieee80211_request_smps_work(struct work_struct *work); | 1470 | void ieee80211_request_smps_ap_work(struct work_struct *work); |
1471 | void ieee80211_request_smps_mgd_work(struct work_struct *work); | ||
1472 | bool ieee80211_smps_is_restrictive(enum ieee80211_smps_mode smps_mode_old, | ||
1473 | enum ieee80211_smps_mode smps_mode_new); | ||
1443 | 1474 | ||
1444 | void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | 1475 | void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, |
1445 | u16 initiator, u16 reason, bool stop); | 1476 | u16 initiator, u16 reason, bool stop); |
@@ -1501,17 +1532,16 @@ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, | |||
1501 | * %IEEE80211_STA_DISABLE_HT, %IEEE80211_STA_DISABLE_VHT, | 1532 | * %IEEE80211_STA_DISABLE_HT, %IEEE80211_STA_DISABLE_VHT, |
1502 | * %IEEE80211_STA_DISABLE_40MHZ, %IEEE80211_STA_DISABLE_80P80MHZ, | 1533 | * %IEEE80211_STA_DISABLE_40MHZ, %IEEE80211_STA_DISABLE_80P80MHZ, |
1503 | * %IEEE80211_STA_DISABLE_160MHZ. | 1534 | * %IEEE80211_STA_DISABLE_160MHZ. |
1504 | * @count: to be filled with the counter until the switch (on success only) | ||
1505 | * @bssid: the currently connected bssid (for reporting) | 1535 | * @bssid: the currently connected bssid (for reporting) |
1506 | * @mode: to be filled with CSA mode (on success only) | 1536 | * @csa_ie: parsed 802.11 csa elements on count, mode, chandef and mesh ttl. |
1507 | * @new_chandef: to be filled with destination chandef (on success only) | 1537 | All of them will be filled with if success only. |
1508 | * Return: 0 on success, <0 on error and >0 if there is nothing to parse. | 1538 | * Return: 0 on success, <0 on error and >0 if there is nothing to parse. |
1509 | */ | 1539 | */ |
1510 | int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, | 1540 | int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, |
1511 | struct ieee802_11_elems *elems, bool beacon, | 1541 | struct ieee802_11_elems *elems, bool beacon, |
1512 | enum ieee80211_band current_band, | 1542 | enum ieee80211_band current_band, |
1513 | u32 sta_flags, u8 *bssid, u8 *count, u8 *mode, | 1543 | u32 sta_flags, u8 *bssid, |
1514 | struct cfg80211_chan_def *new_chandef); | 1544 | struct ieee80211_csa_ie *csa_ie); |
1515 | 1545 | ||
1516 | /* Suspend/resume and hw reconfiguration */ | 1546 | /* Suspend/resume and hw reconfiguration */ |
1517 | int ieee80211_reconfig(struct ieee80211_local *local); | 1547 | int ieee80211_reconfig(struct ieee80211_local *local); |
@@ -1657,8 +1687,10 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | |||
1657 | u32 ieee80211_sta_get_rates(struct ieee80211_sub_if_data *sdata, | 1687 | u32 ieee80211_sta_get_rates(struct ieee80211_sub_if_data *sdata, |
1658 | struct ieee802_11_elems *elems, | 1688 | struct ieee802_11_elems *elems, |
1659 | enum ieee80211_band band, u32 *basic_rates); | 1689 | enum ieee80211_band band, u32 *basic_rates); |
1660 | int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, | 1690 | int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata, |
1661 | enum ieee80211_smps_mode smps_mode); | 1691 | enum ieee80211_smps_mode smps_mode); |
1692 | int __ieee80211_request_smps_ap(struct ieee80211_sub_if_data *sdata, | ||
1693 | enum ieee80211_smps_mode smps_mode); | ||
1662 | void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata); | 1694 | void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata); |
1663 | 1695 | ||
1664 | size_t ieee80211_ie_split(const u8 *ies, size_t ielen, | 1696 | size_t ieee80211_ie_split(const u8 *ies, size_t ielen, |
@@ -1714,6 +1746,8 @@ void ieee80211_dfs_cac_timer(unsigned long data); | |||
1714 | void ieee80211_dfs_cac_timer_work(struct work_struct *work); | 1746 | void ieee80211_dfs_cac_timer_work(struct work_struct *work); |
1715 | void ieee80211_dfs_cac_cancel(struct ieee80211_local *local); | 1747 | void ieee80211_dfs_cac_cancel(struct ieee80211_local *local); |
1716 | void ieee80211_dfs_radar_detected_work(struct work_struct *work); | 1748 | void ieee80211_dfs_radar_detected_work(struct work_struct *work); |
1749 | int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata, | ||
1750 | struct cfg80211_csa_settings *csa_settings); | ||
1717 | 1751 | ||
1718 | #ifdef CONFIG_MAC80211_NOINLINE | 1752 | #ifdef CONFIG_MAC80211_NOINLINE |
1719 | #define debug_noinline noinline | 1753 | #define debug_noinline noinline |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index e48f103b9ade..ff101ea1d9ae 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -1293,7 +1293,10 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
1293 | case NL80211_IFTYPE_AP: | 1293 | case NL80211_IFTYPE_AP: |
1294 | skb_queue_head_init(&sdata->u.ap.ps.bc_buf); | 1294 | skb_queue_head_init(&sdata->u.ap.ps.bc_buf); |
1295 | INIT_LIST_HEAD(&sdata->u.ap.vlans); | 1295 | INIT_LIST_HEAD(&sdata->u.ap.vlans); |
1296 | INIT_WORK(&sdata->u.ap.request_smps_work, | ||
1297 | ieee80211_request_smps_ap_work); | ||
1296 | sdata->vif.bss_conf.bssid = sdata->vif.addr; | 1298 | sdata->vif.bss_conf.bssid = sdata->vif.addr; |
1299 | sdata->u.ap.req_smps = IEEE80211_SMPS_OFF; | ||
1297 | break; | 1300 | break; |
1298 | case NL80211_IFTYPE_P2P_CLIENT: | 1301 | case NL80211_IFTYPE_P2P_CLIENT: |
1299 | type = NL80211_IFTYPE_STATION; | 1302 | type = NL80211_IFTYPE_STATION; |
diff --git a/net/mac80211/key.h b/net/mac80211/key.h index 036d57e76a5e..aaae0ed37004 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h | |||
@@ -83,7 +83,7 @@ struct ieee80211_key { | |||
83 | * Management frames. | 83 | * Management frames. |
84 | */ | 84 | */ |
85 | u8 rx_pn[IEEE80211_NUM_TIDS + 1][IEEE80211_CCMP_PN_LEN]; | 85 | u8 rx_pn[IEEE80211_NUM_TIDS + 1][IEEE80211_CCMP_PN_LEN]; |
86 | struct crypto_cipher *tfm; | 86 | struct crypto_aead *tfm; |
87 | u32 replays; /* dot11RSNAStatsCCMPReplays */ | 87 | u32 replays; /* dot11RSNAStatsCCMPReplays */ |
88 | } ccmp; | 88 | } ccmp; |
89 | struct { | 89 | struct { |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 707ac61d63e5..896fe3bd599e 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <asm/unaligned.h> | 12 | #include <asm/unaligned.h> |
13 | #include "ieee80211_i.h" | 13 | #include "ieee80211_i.h" |
14 | #include "mesh.h" | 14 | #include "mesh.h" |
15 | #include "driver-ops.h" | ||
15 | 16 | ||
16 | static int mesh_allocated; | 17 | static int mesh_allocated; |
17 | static struct kmem_cache *rm_cache; | 18 | static struct kmem_cache *rm_cache; |
@@ -610,6 +611,7 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh) | |||
610 | struct sk_buff *skb; | 611 | struct sk_buff *skb; |
611 | struct ieee80211_mgmt *mgmt; | 612 | struct ieee80211_mgmt *mgmt; |
612 | struct ieee80211_chanctx_conf *chanctx_conf; | 613 | struct ieee80211_chanctx_conf *chanctx_conf; |
614 | struct mesh_csa_settings *csa; | ||
613 | enum ieee80211_band band; | 615 | enum ieee80211_band band; |
614 | u8 *pos; | 616 | u8 *pos; |
615 | struct ieee80211_sub_if_data *sdata; | 617 | struct ieee80211_sub_if_data *sdata; |
@@ -624,6 +626,10 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh) | |||
624 | 626 | ||
625 | head_len = hdr_len + | 627 | head_len = hdr_len + |
626 | 2 + /* NULL SSID */ | 628 | 2 + /* NULL SSID */ |
629 | /* Channel Switch Announcement */ | ||
630 | 2 + sizeof(struct ieee80211_channel_sw_ie) + | ||
631 | /* Mesh Channel Swith Parameters */ | ||
632 | 2 + sizeof(struct ieee80211_mesh_chansw_params_ie) + | ||
627 | 2 + 8 + /* supported rates */ | 633 | 2 + 8 + /* supported rates */ |
628 | 2 + 3; /* DS params */ | 634 | 2 + 3; /* DS params */ |
629 | tail_len = 2 + (IEEE80211_MAX_SUPP_RATES - 8) + | 635 | tail_len = 2 + (IEEE80211_MAX_SUPP_RATES - 8) + |
@@ -665,6 +671,38 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh) | |||
665 | *pos++ = WLAN_EID_SSID; | 671 | *pos++ = WLAN_EID_SSID; |
666 | *pos++ = 0x0; | 672 | *pos++ = 0x0; |
667 | 673 | ||
674 | rcu_read_lock(); | ||
675 | csa = rcu_dereference(ifmsh->csa); | ||
676 | if (csa) { | ||
677 | __le16 pre_value; | ||
678 | |||
679 | pos = skb_put(skb, 13); | ||
680 | memset(pos, 0, 13); | ||
681 | *pos++ = WLAN_EID_CHANNEL_SWITCH; | ||
682 | *pos++ = 3; | ||
683 | *pos++ = 0x0; | ||
684 | *pos++ = ieee80211_frequency_to_channel( | ||
685 | csa->settings.chandef.chan->center_freq); | ||
686 | sdata->csa_counter_offset_beacon = hdr_len + 6; | ||
687 | *pos++ = csa->settings.count; | ||
688 | *pos++ = WLAN_EID_CHAN_SWITCH_PARAM; | ||
689 | *pos++ = 6; | ||
690 | if (ifmsh->chsw_init) { | ||
691 | *pos++ = ifmsh->mshcfg.dot11MeshTTL; | ||
692 | *pos |= WLAN_EID_CHAN_SWITCH_PARAM_INITIATOR; | ||
693 | } else { | ||
694 | *pos++ = ifmsh->chsw_ttl; | ||
695 | } | ||
696 | *pos++ |= csa->settings.block_tx ? | ||
697 | WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT : 0x00; | ||
698 | put_unaligned_le16(WLAN_REASON_MESH_CHAN, pos); | ||
699 | pos += 2; | ||
700 | pre_value = cpu_to_le16(ifmsh->pre_value); | ||
701 | memcpy(pos, &pre_value, 2); | ||
702 | pos += 2; | ||
703 | } | ||
704 | rcu_read_unlock(); | ||
705 | |||
668 | if (ieee80211_add_srates_ie(sdata, skb, true, band) || | 706 | if (ieee80211_add_srates_ie(sdata, skb, true, band) || |
669 | mesh_add_ds_params_ie(sdata, skb)) | 707 | mesh_add_ds_params_ie(sdata, skb)) |
670 | goto out_free; | 708 | goto out_free; |
@@ -812,6 +850,127 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) | |||
812 | ieee80211_configure_filter(local); | 850 | ieee80211_configure_filter(local); |
813 | } | 851 | } |
814 | 852 | ||
853 | static bool | ||
854 | ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata, | ||
855 | struct ieee802_11_elems *elems, bool beacon) | ||
856 | { | ||
857 | struct cfg80211_csa_settings params; | ||
858 | struct ieee80211_csa_ie csa_ie; | ||
859 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
860 | struct ieee80211_chanctx *chanctx; | ||
861 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
862 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); | ||
863 | int err, num_chanctx; | ||
864 | u32 sta_flags; | ||
865 | |||
866 | if (sdata->vif.csa_active) | ||
867 | return true; | ||
868 | |||
869 | if (!ifmsh->mesh_id) | ||
870 | return false; | ||
871 | |||
872 | sta_flags = IEEE80211_STA_DISABLE_VHT; | ||
873 | switch (sdata->vif.bss_conf.chandef.width) { | ||
874 | case NL80211_CHAN_WIDTH_20_NOHT: | ||
875 | sta_flags |= IEEE80211_STA_DISABLE_HT; | ||
876 | case NL80211_CHAN_WIDTH_20: | ||
877 | sta_flags |= IEEE80211_STA_DISABLE_40MHZ; | ||
878 | break; | ||
879 | default: | ||
880 | break; | ||
881 | } | ||
882 | |||
883 | memset(¶ms, 0, sizeof(params)); | ||
884 | memset(&csa_ie, 0, sizeof(csa_ie)); | ||
885 | err = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, band, | ||
886 | sta_flags, sdata->vif.addr, | ||
887 | &csa_ie); | ||
888 | if (err < 0) | ||
889 | return false; | ||
890 | if (err) | ||
891 | return false; | ||
892 | |||
893 | params.chandef = csa_ie.chandef; | ||
894 | params.count = csa_ie.count; | ||
895 | |||
896 | if (sdata->vif.bss_conf.chandef.chan->band != | ||
897 | params.chandef.chan->band) | ||
898 | return false; | ||
899 | |||
900 | if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, ¶ms.chandef, | ||
901 | IEEE80211_CHAN_DISABLED)) { | ||
902 | sdata_info(sdata, | ||
903 | "mesh STA %pM switches to unsupported channel (%d MHz, width:%d, CF1/2: %d/%d MHz), aborting\n", | ||
904 | sdata->vif.addr, | ||
905 | params.chandef.chan->center_freq, | ||
906 | params.chandef.width, | ||
907 | params.chandef.center_freq1, | ||
908 | params.chandef.center_freq2); | ||
909 | return false; | ||
910 | } | ||
911 | |||
912 | err = cfg80211_chandef_dfs_required(sdata->local->hw.wiphy, | ||
913 | ¶ms.chandef); | ||
914 | if (err < 0) | ||
915 | return false; | ||
916 | if (err) { | ||
917 | params.radar_required = true; | ||
918 | /* TODO: DFS not (yet) supported */ | ||
919 | return false; | ||
920 | } | ||
921 | |||
922 | rcu_read_lock(); | ||
923 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
924 | if (!chanctx_conf) | ||
925 | goto failed_chswitch; | ||
926 | |||
927 | /* don't handle for multi-VIF cases */ | ||
928 | chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf); | ||
929 | if (chanctx->refcount > 1) | ||
930 | goto failed_chswitch; | ||
931 | |||
932 | num_chanctx = 0; | ||
933 | list_for_each_entry_rcu(chanctx, &sdata->local->chanctx_list, list) | ||
934 | num_chanctx++; | ||
935 | |||
936 | if (num_chanctx > 1) | ||
937 | goto failed_chswitch; | ||
938 | |||
939 | rcu_read_unlock(); | ||
940 | |||
941 | mcsa_dbg(sdata, | ||
942 | "received channel switch announcement to go to channel %d MHz\n", | ||
943 | params.chandef.chan->center_freq); | ||
944 | |||
945 | params.block_tx = csa_ie.mode & WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT; | ||
946 | if (beacon) | ||
947 | ifmsh->chsw_ttl = csa_ie.ttl - 1; | ||
948 | else | ||
949 | ifmsh->chsw_ttl = 0; | ||
950 | |||
951 | if (ifmsh->chsw_ttl > 0) | ||
952 | if (ieee80211_mesh_csa_beacon(sdata, ¶ms, false) < 0) | ||
953 | return false; | ||
954 | |||
955 | sdata->csa_radar_required = params.radar_required; | ||
956 | |||
957 | if (params.block_tx) | ||
958 | ieee80211_stop_queues_by_reason(&sdata->local->hw, | ||
959 | IEEE80211_MAX_QUEUE_MAP, | ||
960 | IEEE80211_QUEUE_STOP_REASON_CSA); | ||
961 | |||
962 | sdata->local->csa_chandef = params.chandef; | ||
963 | sdata->vif.csa_active = true; | ||
964 | |||
965 | ieee80211_bss_info_change_notify(sdata, err); | ||
966 | drv_channel_switch_beacon(sdata, ¶ms.chandef); | ||
967 | |||
968 | return true; | ||
969 | failed_chswitch: | ||
970 | rcu_read_unlock(); | ||
971 | return false; | ||
972 | } | ||
973 | |||
815 | static void | 974 | static void |
816 | ieee80211_mesh_rx_probe_req(struct ieee80211_sub_if_data *sdata, | 975 | ieee80211_mesh_rx_probe_req(struct ieee80211_sub_if_data *sdata, |
817 | struct ieee80211_mgmt *mgmt, size_t len) | 976 | struct ieee80211_mgmt *mgmt, size_t len) |
@@ -918,6 +1077,142 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | |||
918 | if (ifmsh->sync_ops) | 1077 | if (ifmsh->sync_ops) |
919 | ifmsh->sync_ops->rx_bcn_presp(sdata, | 1078 | ifmsh->sync_ops->rx_bcn_presp(sdata, |
920 | stype, mgmt, &elems, rx_status); | 1079 | stype, mgmt, &elems, rx_status); |
1080 | |||
1081 | if (!ifmsh->chsw_init) | ||
1082 | ieee80211_mesh_process_chnswitch(sdata, &elems, true); | ||
1083 | } | ||
1084 | |||
1085 | int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata) | ||
1086 | { | ||
1087 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
1088 | struct mesh_csa_settings *tmp_csa_settings; | ||
1089 | int ret = 0; | ||
1090 | |||
1091 | /* Reset the TTL value and Initiator flag */ | ||
1092 | ifmsh->chsw_init = false; | ||
1093 | ifmsh->chsw_ttl = 0; | ||
1094 | |||
1095 | /* Remove the CSA and MCSP elements from the beacon */ | ||
1096 | tmp_csa_settings = rcu_dereference(ifmsh->csa); | ||
1097 | rcu_assign_pointer(ifmsh->csa, NULL); | ||
1098 | kfree_rcu(tmp_csa_settings, rcu_head); | ||
1099 | ret = ieee80211_mesh_rebuild_beacon(sdata); | ||
1100 | if (ret) | ||
1101 | return -EINVAL; | ||
1102 | |||
1103 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); | ||
1104 | |||
1105 | mcsa_dbg(sdata, "complete switching to center freq %d MHz", | ||
1106 | sdata->vif.bss_conf.chandef.chan->center_freq); | ||
1107 | return 0; | ||
1108 | } | ||
1109 | |||
1110 | int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata, | ||
1111 | struct cfg80211_csa_settings *csa_settings, | ||
1112 | bool csa_action) | ||
1113 | { | ||
1114 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
1115 | struct mesh_csa_settings *tmp_csa_settings; | ||
1116 | int ret = 0; | ||
1117 | |||
1118 | tmp_csa_settings = kmalloc(sizeof(*tmp_csa_settings), | ||
1119 | GFP_ATOMIC); | ||
1120 | if (!tmp_csa_settings) | ||
1121 | return -ENOMEM; | ||
1122 | |||
1123 | memcpy(&tmp_csa_settings->settings, csa_settings, | ||
1124 | sizeof(struct cfg80211_csa_settings)); | ||
1125 | |||
1126 | rcu_assign_pointer(ifmsh->csa, tmp_csa_settings); | ||
1127 | |||
1128 | ret = ieee80211_mesh_rebuild_beacon(sdata); | ||
1129 | if (ret) { | ||
1130 | tmp_csa_settings = rcu_dereference(ifmsh->csa); | ||
1131 | rcu_assign_pointer(ifmsh->csa, NULL); | ||
1132 | kfree_rcu(tmp_csa_settings, rcu_head); | ||
1133 | return ret; | ||
1134 | } | ||
1135 | |||
1136 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); | ||
1137 | |||
1138 | if (csa_action) | ||
1139 | ieee80211_send_action_csa(sdata, csa_settings); | ||
1140 | |||
1141 | return 0; | ||
1142 | } | ||
1143 | |||
1144 | static int mesh_fwd_csa_frame(struct ieee80211_sub_if_data *sdata, | ||
1145 | struct ieee80211_mgmt *mgmt, size_t len) | ||
1146 | { | ||
1147 | struct ieee80211_mgmt *mgmt_fwd; | ||
1148 | struct sk_buff *skb; | ||
1149 | struct ieee80211_local *local = sdata->local; | ||
1150 | u8 *pos = mgmt->u.action.u.chan_switch.variable; | ||
1151 | size_t offset_ttl; | ||
1152 | |||
1153 | skb = dev_alloc_skb(local->tx_headroom + len); | ||
1154 | if (!skb) | ||
1155 | return -ENOMEM; | ||
1156 | skb_reserve(skb, local->tx_headroom); | ||
1157 | mgmt_fwd = (struct ieee80211_mgmt *) skb_put(skb, len); | ||
1158 | |||
1159 | /* offset_ttl is based on whether the secondary channel | ||
1160 | * offset is available or not. Substract 1 from the mesh TTL | ||
1161 | * and disable the initiator flag before forwarding. | ||
1162 | */ | ||
1163 | offset_ttl = (len < 42) ? 7 : 10; | ||
1164 | *(pos + offset_ttl) -= 1; | ||
1165 | *(pos + offset_ttl + 1) &= ~WLAN_EID_CHAN_SWITCH_PARAM_INITIATOR; | ||
1166 | sdata->u.mesh.chsw_ttl = *(pos + offset_ttl); | ||
1167 | |||
1168 | memcpy(mgmt_fwd, mgmt, len); | ||
1169 | eth_broadcast_addr(mgmt_fwd->da); | ||
1170 | memcpy(mgmt_fwd->sa, sdata->vif.addr, ETH_ALEN); | ||
1171 | memcpy(mgmt_fwd->bssid, sdata->vif.addr, ETH_ALEN); | ||
1172 | |||
1173 | ieee80211_tx_skb(sdata, skb); | ||
1174 | return 0; | ||
1175 | } | ||
1176 | |||
1177 | static void mesh_rx_csa_frame(struct ieee80211_sub_if_data *sdata, | ||
1178 | struct ieee80211_mgmt *mgmt, size_t len) | ||
1179 | { | ||
1180 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
1181 | struct ieee802_11_elems elems; | ||
1182 | u16 pre_value; | ||
1183 | bool fwd_csa = true; | ||
1184 | size_t baselen; | ||
1185 | u8 *pos, ttl; | ||
1186 | |||
1187 | if (mgmt->u.action.u.measurement.action_code != | ||
1188 | WLAN_ACTION_SPCT_CHL_SWITCH) | ||
1189 | return; | ||
1190 | |||
1191 | pos = mgmt->u.action.u.chan_switch.variable; | ||
1192 | baselen = offsetof(struct ieee80211_mgmt, | ||
1193 | u.action.u.chan_switch.variable); | ||
1194 | ieee802_11_parse_elems(pos, len - baselen, false, &elems); | ||
1195 | |||
1196 | ttl = elems.mesh_chansw_params_ie->mesh_ttl; | ||
1197 | if (!--ttl) | ||
1198 | fwd_csa = false; | ||
1199 | |||
1200 | pre_value = le16_to_cpu(elems.mesh_chansw_params_ie->mesh_pre_value); | ||
1201 | if (ifmsh->pre_value >= pre_value) | ||
1202 | return; | ||
1203 | |||
1204 | ifmsh->pre_value = pre_value; | ||
1205 | |||
1206 | if (!ieee80211_mesh_process_chnswitch(sdata, &elems, false)) { | ||
1207 | mcsa_dbg(sdata, "Failed to process CSA action frame"); | ||
1208 | return; | ||
1209 | } | ||
1210 | |||
1211 | /* forward or re-broadcast the CSA frame */ | ||
1212 | if (fwd_csa) { | ||
1213 | if (mesh_fwd_csa_frame(sdata, mgmt, len) < 0) | ||
1214 | mcsa_dbg(sdata, "Failed to forward the CSA frame"); | ||
1215 | } | ||
921 | } | 1216 | } |
922 | 1217 | ||
923 | static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, | 1218 | static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, |
@@ -939,6 +1234,9 @@ static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, | |||
939 | if (mesh_action_is_path_sel(mgmt)) | 1234 | if (mesh_action_is_path_sel(mgmt)) |
940 | mesh_rx_path_sel_frame(sdata, mgmt, len); | 1235 | mesh_rx_path_sel_frame(sdata, mgmt, len); |
941 | break; | 1236 | break; |
1237 | case WLAN_CATEGORY_SPECTRUM_MGMT: | ||
1238 | mesh_rx_csa_frame(sdata, mgmt, len); | ||
1239 | break; | ||
942 | } | 1240 | } |
943 | } | 1241 | } |
944 | 1242 | ||
@@ -1056,13 +1354,11 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) | |||
1056 | (unsigned long) sdata); | 1354 | (unsigned long) sdata); |
1057 | 1355 | ||
1058 | ifmsh->accepting_plinks = true; | 1356 | ifmsh->accepting_plinks = true; |
1059 | ifmsh->preq_id = 0; | ||
1060 | ifmsh->sn = 0; | ||
1061 | ifmsh->num_gates = 0; | ||
1062 | atomic_set(&ifmsh->mpaths, 0); | 1357 | atomic_set(&ifmsh->mpaths, 0); |
1063 | mesh_rmc_init(sdata); | 1358 | mesh_rmc_init(sdata); |
1064 | ifmsh->last_preq = jiffies; | 1359 | ifmsh->last_preq = jiffies; |
1065 | ifmsh->next_perr = jiffies; | 1360 | ifmsh->next_perr = jiffies; |
1361 | ifmsh->chsw_init = false; | ||
1066 | /* Allocate all mesh structures when creating the first mesh interface. */ | 1362 | /* Allocate all mesh structures when creating the first mesh interface. */ |
1067 | if (!mesh_allocated) | 1363 | if (!mesh_allocated) |
1068 | ieee80211s_init(); | 1364 | ieee80211s_init(); |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 6b65d5055f5b..4301aa5aa227 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -222,7 +222,8 @@ static u32 __mesh_plink_deactivate(struct sta_info *sta) | |||
222 | mesh_path_flush_by_nexthop(sta); | 222 | mesh_path_flush_by_nexthop(sta); |
223 | 223 | ||
224 | ieee80211_mps_sta_status_update(sta); | 224 | ieee80211_mps_sta_status_update(sta); |
225 | changed |= ieee80211_mps_local_status_update(sdata); | 225 | changed |= ieee80211_mps_set_sta_local_pm(sta, |
226 | NL80211_MESH_POWER_UNKNOWN); | ||
226 | 227 | ||
227 | return changed; | 228 | return changed; |
228 | } | 229 | } |
diff --git a/net/mac80211/mesh_ps.c b/net/mac80211/mesh_ps.c index 22290a929b94..0f79b78b5e86 100644 --- a/net/mac80211/mesh_ps.c +++ b/net/mac80211/mesh_ps.c | |||
@@ -152,6 +152,9 @@ u32 ieee80211_mps_set_sta_local_pm(struct sta_info *sta, | |||
152 | { | 152 | { |
153 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 153 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
154 | 154 | ||
155 | if (sta->local_pm == pm) | ||
156 | return 0; | ||
157 | |||
155 | mps_dbg(sdata, "local STA operates in mode %d with %pM\n", | 158 | mps_dbg(sdata, "local STA operates in mode %d with %pM\n", |
156 | pm, sta->sta.addr); | 159 | pm, sta->sta.addr); |
157 | 160 | ||
@@ -245,6 +248,14 @@ void ieee80211_mps_sta_status_update(struct sta_info *sta) | |||
245 | 248 | ||
246 | do_buffer = (pm != NL80211_MESH_POWER_ACTIVE); | 249 | do_buffer = (pm != NL80211_MESH_POWER_ACTIVE); |
247 | 250 | ||
251 | /* clear the MPSP flags for non-peers or active STA */ | ||
252 | if (sta->plink_state != NL80211_PLINK_ESTAB) { | ||
253 | clear_sta_flag(sta, WLAN_STA_MPSP_OWNER); | ||
254 | clear_sta_flag(sta, WLAN_STA_MPSP_RECIPIENT); | ||
255 | } else if (!do_buffer) { | ||
256 | clear_sta_flag(sta, WLAN_STA_MPSP_OWNER); | ||
257 | } | ||
258 | |||
248 | /* Don't let the same PS state be set twice */ | 259 | /* Don't let the same PS state be set twice */ |
249 | if (test_sta_flag(sta, WLAN_STA_PS_STA) == do_buffer) | 260 | if (test_sta_flag(sta, WLAN_STA_PS_STA) == do_buffer) |
250 | return; | 261 | return; |
@@ -257,14 +268,6 @@ void ieee80211_mps_sta_status_update(struct sta_info *sta) | |||
257 | } else { | 268 | } else { |
258 | ieee80211_sta_ps_deliver_wakeup(sta); | 269 | ieee80211_sta_ps_deliver_wakeup(sta); |
259 | } | 270 | } |
260 | |||
261 | /* clear the MPSP flags for non-peers or active STA */ | ||
262 | if (sta->plink_state != NL80211_PLINK_ESTAB) { | ||
263 | clear_sta_flag(sta, WLAN_STA_MPSP_OWNER); | ||
264 | clear_sta_flag(sta, WLAN_STA_MPSP_RECIPIENT); | ||
265 | } else if (!do_buffer) { | ||
266 | clear_sta_flag(sta, WLAN_STA_MPSP_OWNER); | ||
267 | } | ||
268 | } | 271 | } |
269 | 272 | ||
270 | static void mps_set_sta_peer_pm(struct sta_info *sta, | 273 | static void mps_set_sta_peer_pm(struct sta_info *sta, |
@@ -444,8 +447,7 @@ static void mpsp_qos_null_append(struct sta_info *sta, | |||
444 | */ | 447 | */ |
445 | static void mps_frame_deliver(struct sta_info *sta, int n_frames) | 448 | static void mps_frame_deliver(struct sta_info *sta, int n_frames) |
446 | { | 449 | { |
447 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 450 | struct ieee80211_local *local = sta->sdata->local; |
448 | struct ieee80211_local *local = sdata->local; | ||
449 | int ac; | 451 | int ac; |
450 | struct sk_buff_head frames; | 452 | struct sk_buff_head frames; |
451 | struct sk_buff *skb; | 453 | struct sk_buff *skb; |
@@ -558,10 +560,10 @@ void ieee80211_mpsp_trigger_process(u8 *qc, struct sta_info *sta, | |||
558 | } | 560 | } |
559 | 561 | ||
560 | /** | 562 | /** |
561 | * ieee80211_mps_frame_release - release buffered frames in response to beacon | 563 | * ieee80211_mps_frame_release - release frames buffered due to mesh power save |
562 | * | 564 | * |
563 | * @sta: mesh STA | 565 | * @sta: mesh STA |
564 | * @elems: beacon IEs | 566 | * @elems: IEs of beacon or probe response |
565 | * | 567 | * |
566 | * For peers if we have individually-addressed frames buffered or the peer | 568 | * For peers if we have individually-addressed frames buffered or the peer |
567 | * indicates buffered frames, send a corresponding MPSP trigger frame. Since | 569 | * indicates buffered frames, send a corresponding MPSP trigger frame. Since |
@@ -588,9 +590,10 @@ void ieee80211_mps_frame_release(struct sta_info *sta, | |||
588 | (!elems->awake_window || !le16_to_cpu(*elems->awake_window))) | 590 | (!elems->awake_window || !le16_to_cpu(*elems->awake_window))) |
589 | return; | 591 | return; |
590 | 592 | ||
591 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) | 593 | if (!test_sta_flag(sta, WLAN_STA_MPSP_OWNER)) |
592 | buffer_local += skb_queue_len(&sta->ps_tx_buf[ac]) + | 594 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) |
593 | skb_queue_len(&sta->tx_filtered[ac]); | 595 | buffer_local += skb_queue_len(&sta->ps_tx_buf[ac]) + |
596 | skb_queue_len(&sta->tx_filtered[ac]); | ||
594 | 597 | ||
595 | if (!has_buffered && !buffer_local) | 598 | if (!has_buffered && !buffer_local) |
596 | return; | 599 | return; |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index d7bdc4b97dde..d7504ab61a34 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -958,9 +958,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
958 | struct cfg80211_bss *cbss = ifmgd->associated; | 958 | struct cfg80211_bss *cbss = ifmgd->associated; |
959 | struct ieee80211_chanctx *chanctx; | 959 | struct ieee80211_chanctx *chanctx; |
960 | enum ieee80211_band current_band; | 960 | enum ieee80211_band current_band; |
961 | u8 count; | 961 | struct ieee80211_csa_ie csa_ie; |
962 | u8 mode; | ||
963 | struct cfg80211_chan_def new_chandef = {}; | ||
964 | int res; | 962 | int res; |
965 | 963 | ||
966 | sdata_assert_lock(sdata); | 964 | sdata_assert_lock(sdata); |
@@ -976,24 +974,24 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
976 | return; | 974 | return; |
977 | 975 | ||
978 | current_band = cbss->channel->band; | 976 | current_band = cbss->channel->band; |
977 | memset(&csa_ie, 0, sizeof(csa_ie)); | ||
979 | res = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, current_band, | 978 | res = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, current_band, |
980 | ifmgd->flags, | 979 | ifmgd->flags, |
981 | ifmgd->associated->bssid, &count, | 980 | ifmgd->associated->bssid, &csa_ie); |
982 | &mode, &new_chandef); | ||
983 | if (res < 0) | 981 | if (res < 0) |
984 | ieee80211_queue_work(&local->hw, | 982 | ieee80211_queue_work(&local->hw, |
985 | &ifmgd->csa_connection_drop_work); | 983 | &ifmgd->csa_connection_drop_work); |
986 | if (res) | 984 | if (res) |
987 | return; | 985 | return; |
988 | 986 | ||
989 | if (!cfg80211_chandef_usable(local->hw.wiphy, &new_chandef, | 987 | if (!cfg80211_chandef_usable(local->hw.wiphy, &csa_ie.chandef, |
990 | IEEE80211_CHAN_DISABLED)) { | 988 | IEEE80211_CHAN_DISABLED)) { |
991 | sdata_info(sdata, | 989 | sdata_info(sdata, |
992 | "AP %pM switches to unsupported channel (%d MHz, width:%d, CF1/2: %d/%d MHz), disconnecting\n", | 990 | "AP %pM switches to unsupported channel (%d MHz, width:%d, CF1/2: %d/%d MHz), disconnecting\n", |
993 | ifmgd->associated->bssid, | 991 | ifmgd->associated->bssid, |
994 | new_chandef.chan->center_freq, | 992 | csa_ie.chandef.chan->center_freq, |
995 | new_chandef.width, new_chandef.center_freq1, | 993 | csa_ie.chandef.width, csa_ie.chandef.center_freq1, |
996 | new_chandef.center_freq2); | 994 | csa_ie.chandef.center_freq2); |
997 | ieee80211_queue_work(&local->hw, | 995 | ieee80211_queue_work(&local->hw, |
998 | &ifmgd->csa_connection_drop_work); | 996 | &ifmgd->csa_connection_drop_work); |
999 | return; | 997 | return; |
@@ -1037,9 +1035,9 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
1037 | } | 1035 | } |
1038 | mutex_unlock(&local->chanctx_mtx); | 1036 | mutex_unlock(&local->chanctx_mtx); |
1039 | 1037 | ||
1040 | local->csa_chandef = new_chandef; | 1038 | local->csa_chandef = csa_ie.chandef; |
1041 | 1039 | ||
1042 | if (mode) | 1040 | if (csa_ie.mode) |
1043 | ieee80211_stop_queues_by_reason(&local->hw, | 1041 | ieee80211_stop_queues_by_reason(&local->hw, |
1044 | IEEE80211_MAX_QUEUE_MAP, | 1042 | IEEE80211_MAX_QUEUE_MAP, |
1045 | IEEE80211_QUEUE_STOP_REASON_CSA); | 1043 | IEEE80211_QUEUE_STOP_REASON_CSA); |
@@ -1048,9 +1046,9 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
1048 | /* use driver's channel switch callback */ | 1046 | /* use driver's channel switch callback */ |
1049 | struct ieee80211_channel_switch ch_switch = { | 1047 | struct ieee80211_channel_switch ch_switch = { |
1050 | .timestamp = timestamp, | 1048 | .timestamp = timestamp, |
1051 | .block_tx = mode, | 1049 | .block_tx = csa_ie.mode, |
1052 | .chandef = new_chandef, | 1050 | .chandef = csa_ie.chandef, |
1053 | .count = count, | 1051 | .count = csa_ie.count, |
1054 | }; | 1052 | }; |
1055 | 1053 | ||
1056 | drv_channel_switch(local, &ch_switch); | 1054 | drv_channel_switch(local, &ch_switch); |
@@ -1058,11 +1056,11 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
1058 | } | 1056 | } |
1059 | 1057 | ||
1060 | /* channel switch handled in software */ | 1058 | /* channel switch handled in software */ |
1061 | if (count <= 1) | 1059 | if (csa_ie.count <= 1) |
1062 | ieee80211_queue_work(&local->hw, &ifmgd->chswitch_work); | 1060 | ieee80211_queue_work(&local->hw, &ifmgd->chswitch_work); |
1063 | else | 1061 | else |
1064 | mod_timer(&ifmgd->chswitch_timer, | 1062 | mod_timer(&ifmgd->chswitch_timer, |
1065 | TU_TO_EXP_TIME(count * cbss->beacon_interval)); | 1063 | TU_TO_EXP_TIME(csa_ie.count * cbss->beacon_interval)); |
1066 | } | 1064 | } |
1067 | 1065 | ||
1068 | static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, | 1066 | static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, |
@@ -3500,7 +3498,7 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) | |||
3500 | ieee80211_beacon_connection_loss_work); | 3498 | ieee80211_beacon_connection_loss_work); |
3501 | INIT_WORK(&ifmgd->csa_connection_drop_work, | 3499 | INIT_WORK(&ifmgd->csa_connection_drop_work, |
3502 | ieee80211_csa_connection_drop_work); | 3500 | ieee80211_csa_connection_drop_work); |
3503 | INIT_WORK(&ifmgd->request_smps_work, ieee80211_request_smps_work); | 3501 | INIT_WORK(&ifmgd->request_smps_work, ieee80211_request_smps_mgd_work); |
3504 | setup_timer(&ifmgd->timer, ieee80211_sta_timer, | 3502 | setup_timer(&ifmgd->timer, ieee80211_sta_timer, |
3505 | (unsigned long) sdata); | 3503 | (unsigned long) sdata); |
3506 | setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer, | 3504 | setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer, |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 0011ac815097..caecef870c0e 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -2593,13 +2593,16 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2593 | break; | 2593 | break; |
2594 | 2594 | ||
2595 | if (sdata->vif.type != NL80211_IFTYPE_STATION && | 2595 | if (sdata->vif.type != NL80211_IFTYPE_STATION && |
2596 | sdata->vif.type != NL80211_IFTYPE_ADHOC) | 2596 | sdata->vif.type != NL80211_IFTYPE_ADHOC && |
2597 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT) | ||
2597 | break; | 2598 | break; |
2598 | 2599 | ||
2599 | if (sdata->vif.type == NL80211_IFTYPE_STATION) | 2600 | if (sdata->vif.type == NL80211_IFTYPE_STATION) |
2600 | bssid = sdata->u.mgd.bssid; | 2601 | bssid = sdata->u.mgd.bssid; |
2601 | else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | 2602 | else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) |
2602 | bssid = sdata->u.ibss.bssid; | 2603 | bssid = sdata->u.ibss.bssid; |
2604 | else if (sdata->vif.type == NL80211_IFTYPE_MESH_POINT) | ||
2605 | bssid = mgmt->sa; | ||
2603 | else | 2606 | else |
2604 | break; | 2607 | break; |
2605 | 2608 | ||
diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c index 921597e279a3..a40da20b32e0 100644 --- a/net/mac80211/spectmgmt.c +++ b/net/mac80211/spectmgmt.c | |||
@@ -24,8 +24,8 @@ | |||
24 | int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, | 24 | int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, |
25 | struct ieee802_11_elems *elems, bool beacon, | 25 | struct ieee802_11_elems *elems, bool beacon, |
26 | enum ieee80211_band current_band, | 26 | enum ieee80211_band current_band, |
27 | u32 sta_flags, u8 *bssid, u8 *count, u8 *mode, | 27 | u32 sta_flags, u8 *bssid, |
28 | struct cfg80211_chan_def *new_chandef) | 28 | struct ieee80211_csa_ie *csa_ie) |
29 | { | 29 | { |
30 | enum ieee80211_band new_band; | 30 | enum ieee80211_band new_band; |
31 | int new_freq; | 31 | int new_freq; |
@@ -62,18 +62,24 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, | |||
62 | return -EINVAL; | 62 | return -EINVAL; |
63 | } | 63 | } |
64 | new_chan_no = elems->ext_chansw_ie->new_ch_num; | 64 | new_chan_no = elems->ext_chansw_ie->new_ch_num; |
65 | *count = elems->ext_chansw_ie->count; | 65 | csa_ie->count = elems->ext_chansw_ie->count; |
66 | *mode = elems->ext_chansw_ie->mode; | 66 | csa_ie->mode = elems->ext_chansw_ie->mode; |
67 | } else if (elems->ch_switch_ie) { | 67 | } else if (elems->ch_switch_ie) { |
68 | new_band = current_band; | 68 | new_band = current_band; |
69 | new_chan_no = elems->ch_switch_ie->new_ch_num; | 69 | new_chan_no = elems->ch_switch_ie->new_ch_num; |
70 | *count = elems->ch_switch_ie->count; | 70 | csa_ie->count = elems->ch_switch_ie->count; |
71 | *mode = elems->ch_switch_ie->mode; | 71 | csa_ie->mode = elems->ch_switch_ie->mode; |
72 | } else { | 72 | } else { |
73 | /* nothing here we understand */ | 73 | /* nothing here we understand */ |
74 | return 1; | 74 | return 1; |
75 | } | 75 | } |
76 | 76 | ||
77 | /* Mesh Channel Switch Parameters Element */ | ||
78 | if (elems->mesh_chansw_params_ie) { | ||
79 | csa_ie->ttl = elems->mesh_chansw_params_ie->mesh_ttl; | ||
80 | csa_ie->mode = elems->mesh_chansw_params_ie->mesh_flags; | ||
81 | } | ||
82 | |||
77 | new_freq = ieee80211_channel_to_frequency(new_chan_no, new_band); | 83 | new_freq = ieee80211_channel_to_frequency(new_chan_no, new_band); |
78 | new_chan = ieee80211_get_channel(sdata->local->hw.wiphy, new_freq); | 84 | new_chan = ieee80211_get_channel(sdata->local->hw.wiphy, new_freq); |
79 | if (!new_chan || new_chan->flags & IEEE80211_CHAN_DISABLED) { | 85 | if (!new_chan || new_chan->flags & IEEE80211_CHAN_DISABLED) { |
@@ -103,25 +109,26 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, | |||
103 | default: | 109 | default: |
104 | /* secondary_channel_offset was present but is invalid */ | 110 | /* secondary_channel_offset was present but is invalid */ |
105 | case IEEE80211_HT_PARAM_CHA_SEC_NONE: | 111 | case IEEE80211_HT_PARAM_CHA_SEC_NONE: |
106 | cfg80211_chandef_create(new_chandef, new_chan, | 112 | cfg80211_chandef_create(&csa_ie->chandef, new_chan, |
107 | NL80211_CHAN_HT20); | 113 | NL80211_CHAN_HT20); |
108 | break; | 114 | break; |
109 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | 115 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: |
110 | cfg80211_chandef_create(new_chandef, new_chan, | 116 | cfg80211_chandef_create(&csa_ie->chandef, new_chan, |
111 | NL80211_CHAN_HT40PLUS); | 117 | NL80211_CHAN_HT40PLUS); |
112 | break; | 118 | break; |
113 | case IEEE80211_HT_PARAM_CHA_SEC_BELOW: | 119 | case IEEE80211_HT_PARAM_CHA_SEC_BELOW: |
114 | cfg80211_chandef_create(new_chandef, new_chan, | 120 | cfg80211_chandef_create(&csa_ie->chandef, new_chan, |
115 | NL80211_CHAN_HT40MINUS); | 121 | NL80211_CHAN_HT40MINUS); |
116 | break; | 122 | break; |
117 | case -1: | 123 | case -1: |
118 | cfg80211_chandef_create(new_chandef, new_chan, | 124 | cfg80211_chandef_create(&csa_ie->chandef, new_chan, |
119 | NL80211_CHAN_NO_HT); | 125 | NL80211_CHAN_NO_HT); |
120 | /* keep width for 5/10 MHz channels */ | 126 | /* keep width for 5/10 MHz channels */ |
121 | switch (sdata->vif.bss_conf.chandef.width) { | 127 | switch (sdata->vif.bss_conf.chandef.width) { |
122 | case NL80211_CHAN_WIDTH_5: | 128 | case NL80211_CHAN_WIDTH_5: |
123 | case NL80211_CHAN_WIDTH_10: | 129 | case NL80211_CHAN_WIDTH_10: |
124 | new_chandef->width = sdata->vif.bss_conf.chandef.width; | 130 | csa_ie->chandef.width = |
131 | sdata->vif.bss_conf.chandef.width; | ||
125 | break; | 132 | break; |
126 | default: | 133 | default: |
127 | break; | 134 | break; |
@@ -171,13 +178,13 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, | |||
171 | /* if VHT data is there validate & use it */ | 178 | /* if VHT data is there validate & use it */ |
172 | if (new_vht_chandef.chan) { | 179 | if (new_vht_chandef.chan) { |
173 | if (!cfg80211_chandef_compatible(&new_vht_chandef, | 180 | if (!cfg80211_chandef_compatible(&new_vht_chandef, |
174 | new_chandef)) { | 181 | &csa_ie->chandef)) { |
175 | sdata_info(sdata, | 182 | sdata_info(sdata, |
176 | "BSS %pM: CSA has inconsistent channel data, disconnecting\n", | 183 | "BSS %pM: CSA has inconsistent channel data, disconnecting\n", |
177 | bssid); | 184 | bssid); |
178 | return -EINVAL; | 185 | return -EINVAL; |
179 | } | 186 | } |
180 | *new_chandef = new_vht_chandef; | 187 | csa_ie->chandef = new_vht_chandef; |
181 | } | 188 | } |
182 | 189 | ||
183 | return 0; | 190 | return 0; |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index aeb967a0aeed..1eb66e26e49d 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -385,6 +385,30 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
385 | sta->last_seq_ctrl[i] = cpu_to_le16(USHRT_MAX); | 385 | sta->last_seq_ctrl[i] = cpu_to_le16(USHRT_MAX); |
386 | 386 | ||
387 | sta->sta.smps_mode = IEEE80211_SMPS_OFF; | 387 | sta->sta.smps_mode = IEEE80211_SMPS_OFF; |
388 | if (sdata->vif.type == NL80211_IFTYPE_AP || | ||
389 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { | ||
390 | struct ieee80211_supported_band *sband = | ||
391 | local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)]; | ||
392 | u8 smps = (sband->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >> | ||
393 | IEEE80211_HT_CAP_SM_PS_SHIFT; | ||
394 | /* | ||
395 | * Assume that hostapd advertises our caps in the beacon and | ||
396 | * this is the known_smps_mode for a station that just assciated | ||
397 | */ | ||
398 | switch (smps) { | ||
399 | case WLAN_HT_SMPS_CONTROL_DISABLED: | ||
400 | sta->known_smps_mode = IEEE80211_SMPS_OFF; | ||
401 | break; | ||
402 | case WLAN_HT_SMPS_CONTROL_STATIC: | ||
403 | sta->known_smps_mode = IEEE80211_SMPS_STATIC; | ||
404 | break; | ||
405 | case WLAN_HT_SMPS_CONTROL_DYNAMIC: | ||
406 | sta->known_smps_mode = IEEE80211_SMPS_DYNAMIC; | ||
407 | break; | ||
408 | default: | ||
409 | WARN_ON(1); | ||
410 | } | ||
411 | } | ||
388 | 412 | ||
389 | sta_dbg(sdata, "Allocated STA %pM\n", sta->sta.addr); | 413 | sta_dbg(sdata, "Allocated STA %pM\n", sta->sta.addr); |
390 | 414 | ||
@@ -1069,6 +1093,19 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) | |||
1069 | 1093 | ||
1070 | ieee80211_add_pending_skbs_fn(local, &pending, clear_sta_ps_flags, sta); | 1094 | ieee80211_add_pending_skbs_fn(local, &pending, clear_sta_ps_flags, sta); |
1071 | 1095 | ||
1096 | /* This station just woke up and isn't aware of our SMPS state */ | ||
1097 | if (!ieee80211_smps_is_restrictive(sta->known_smps_mode, | ||
1098 | sdata->smps_mode) && | ||
1099 | sta->known_smps_mode != sdata->bss->req_smps && | ||
1100 | sta_info_tx_streams(sta) != 1) { | ||
1101 | ht_dbg(sdata, | ||
1102 | "%pM just woke up and MIMO capable - update SMPS\n", | ||
1103 | sta->sta.addr); | ||
1104 | ieee80211_send_smps_action(sdata, sdata->bss->req_smps, | ||
1105 | sta->sta.addr, | ||
1106 | sdata->vif.bss_conf.bssid); | ||
1107 | } | ||
1108 | |||
1072 | local->total_ps_buffered -= buffered; | 1109 | local->total_ps_buffered -= buffered; |
1073 | 1110 | ||
1074 | sta_info_recalc_tim(sta); | 1111 | sta_info_recalc_tim(sta); |
@@ -1520,3 +1557,38 @@ int sta_info_move_state(struct sta_info *sta, | |||
1520 | 1557 | ||
1521 | return 0; | 1558 | return 0; |
1522 | } | 1559 | } |
1560 | |||
1561 | u8 sta_info_tx_streams(struct sta_info *sta) | ||
1562 | { | ||
1563 | struct ieee80211_sta_ht_cap *ht_cap = &sta->sta.ht_cap; | ||
1564 | u8 rx_streams; | ||
1565 | |||
1566 | if (!sta->sta.ht_cap.ht_supported) | ||
1567 | return 1; | ||
1568 | |||
1569 | if (sta->sta.vht_cap.vht_supported) { | ||
1570 | int i; | ||
1571 | u16 tx_mcs_map = | ||
1572 | le16_to_cpu(sta->sta.vht_cap.vht_mcs.tx_mcs_map); | ||
1573 | |||
1574 | for (i = 7; i >= 0; i--) | ||
1575 | if ((tx_mcs_map & (0x3 << (i * 2))) != | ||
1576 | IEEE80211_VHT_MCS_NOT_SUPPORTED) | ||
1577 | return i + 1; | ||
1578 | } | ||
1579 | |||
1580 | if (ht_cap->mcs.rx_mask[3]) | ||
1581 | rx_streams = 4; | ||
1582 | else if (ht_cap->mcs.rx_mask[2]) | ||
1583 | rx_streams = 3; | ||
1584 | else if (ht_cap->mcs.rx_mask[1]) | ||
1585 | rx_streams = 2; | ||
1586 | else | ||
1587 | rx_streams = 1; | ||
1588 | |||
1589 | if (!(ht_cap->mcs.tx_params & IEEE80211_HT_MCS_TX_RX_DIFF)) | ||
1590 | return rx_streams; | ||
1591 | |||
1592 | return ((ht_cap->mcs.tx_params & IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK) | ||
1593 | >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT) + 1; | ||
1594 | } | ||
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 4208dbd5861f..3ef06a26b9cb 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -301,6 +301,8 @@ struct sta_ampdu_mlme { | |||
301 | * @chains: chains ever used for RX from this station | 301 | * @chains: chains ever used for RX from this station |
302 | * @chain_signal_last: last signal (per chain) | 302 | * @chain_signal_last: last signal (per chain) |
303 | * @chain_signal_avg: signal average (per chain) | 303 | * @chain_signal_avg: signal average (per chain) |
304 | * @known_smps_mode: the smps_mode the client thinks we are in. Relevant for | ||
305 | * AP only. | ||
304 | */ | 306 | */ |
305 | struct sta_info { | 307 | struct sta_info { |
306 | /* General information, mostly static */ | 308 | /* General information, mostly static */ |
@@ -411,6 +413,8 @@ struct sta_info { | |||
411 | unsigned int lost_packets; | 413 | unsigned int lost_packets; |
412 | unsigned int beacon_loss_count; | 414 | unsigned int beacon_loss_count; |
413 | 415 | ||
416 | enum ieee80211_smps_mode known_smps_mode; | ||
417 | |||
414 | /* keep last! */ | 418 | /* keep last! */ |
415 | struct ieee80211_sta sta; | 419 | struct ieee80211_sta sta; |
416 | }; | 420 | }; |
@@ -613,6 +617,7 @@ void sta_set_rate_info_rx(struct sta_info *sta, | |||
613 | struct rate_info *rinfo); | 617 | struct rate_info *rinfo); |
614 | void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, | 618 | void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, |
615 | unsigned long exp_time); | 619 | unsigned long exp_time); |
620 | u8 sta_info_tx_streams(struct sta_info *sta); | ||
616 | 621 | ||
617 | void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta); | 622 | void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta); |
618 | void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta); | 623 | void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta); |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 78dc2e99027e..52a152b01b06 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -194,29 +194,36 @@ static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb) | |||
194 | if (ieee80211_is_action(mgmt->frame_control) && | 194 | if (ieee80211_is_action(mgmt->frame_control) && |
195 | mgmt->u.action.category == WLAN_CATEGORY_HT && | 195 | mgmt->u.action.category == WLAN_CATEGORY_HT && |
196 | mgmt->u.action.u.ht_smps.action == WLAN_HT_ACTION_SMPS && | 196 | mgmt->u.action.u.ht_smps.action == WLAN_HT_ACTION_SMPS && |
197 | sdata->vif.type == NL80211_IFTYPE_STATION && | ||
198 | ieee80211_sdata_running(sdata)) { | 197 | ieee80211_sdata_running(sdata)) { |
199 | /* | 198 | enum ieee80211_smps_mode smps_mode; |
200 | * This update looks racy, but isn't -- if we come | 199 | |
201 | * here we've definitely got a station that we're | ||
202 | * talking to, and on a managed interface that can | ||
203 | * only be the AP. And the only other place updating | ||
204 | * this variable in managed mode is before association. | ||
205 | */ | ||
206 | switch (mgmt->u.action.u.ht_smps.smps_control) { | 200 | switch (mgmt->u.action.u.ht_smps.smps_control) { |
207 | case WLAN_HT_SMPS_CONTROL_DYNAMIC: | 201 | case WLAN_HT_SMPS_CONTROL_DYNAMIC: |
208 | sdata->smps_mode = IEEE80211_SMPS_DYNAMIC; | 202 | smps_mode = IEEE80211_SMPS_DYNAMIC; |
209 | break; | 203 | break; |
210 | case WLAN_HT_SMPS_CONTROL_STATIC: | 204 | case WLAN_HT_SMPS_CONTROL_STATIC: |
211 | sdata->smps_mode = IEEE80211_SMPS_STATIC; | 205 | smps_mode = IEEE80211_SMPS_STATIC; |
212 | break; | 206 | break; |
213 | case WLAN_HT_SMPS_CONTROL_DISABLED: | 207 | case WLAN_HT_SMPS_CONTROL_DISABLED: |
214 | default: /* shouldn't happen since we don't send that */ | 208 | default: /* shouldn't happen since we don't send that */ |
215 | sdata->smps_mode = IEEE80211_SMPS_OFF; | 209 | smps_mode = IEEE80211_SMPS_OFF; |
216 | break; | 210 | break; |
217 | } | 211 | } |
218 | 212 | ||
219 | ieee80211_queue_work(&local->hw, &sdata->recalc_smps); | 213 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { |
214 | /* | ||
215 | * This update looks racy, but isn't -- if we come | ||
216 | * here we've definitely got a station that we're | ||
217 | * talking to, and on a managed interface that can | ||
218 | * only be the AP. And the only other place updating | ||
219 | * this variable in managed mode is before association. | ||
220 | */ | ||
221 | sdata->smps_mode = smps_mode; | ||
222 | ieee80211_queue_work(&local->hw, &sdata->recalc_smps); | ||
223 | } else if (sdata->vif.type == NL80211_IFTYPE_AP || | ||
224 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { | ||
225 | sta->known_smps_mode = smps_mode; | ||
226 | } | ||
220 | } | 227 | } |
221 | } | 228 | } |
222 | 229 | ||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 9993fcb19ecd..c558b246ef00 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1367,6 +1367,35 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx) | |||
1367 | return 0; | 1367 | return 0; |
1368 | } | 1368 | } |
1369 | 1369 | ||
1370 | bool ieee80211_tx_prepare_skb(struct ieee80211_hw *hw, | ||
1371 | struct ieee80211_vif *vif, struct sk_buff *skb, | ||
1372 | int band, struct ieee80211_sta **sta) | ||
1373 | { | ||
1374 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
1375 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
1376 | struct ieee80211_tx_data tx; | ||
1377 | |||
1378 | if (ieee80211_tx_prepare(sdata, &tx, skb) == TX_DROP) | ||
1379 | return false; | ||
1380 | |||
1381 | info->band = band; | ||
1382 | info->control.vif = vif; | ||
1383 | info->hw_queue = vif->hw_queue[skb_get_queue_mapping(skb)]; | ||
1384 | |||
1385 | if (invoke_tx_handlers(&tx)) | ||
1386 | return false; | ||
1387 | |||
1388 | if (sta) { | ||
1389 | if (tx.sta) | ||
1390 | *sta = &tx.sta->sta; | ||
1391 | else | ||
1392 | *sta = NULL; | ||
1393 | } | ||
1394 | |||
1395 | return true; | ||
1396 | } | ||
1397 | EXPORT_SYMBOL(ieee80211_tx_prepare_skb); | ||
1398 | |||
1370 | /* | 1399 | /* |
1371 | * Returns false if the frame couldn't be transmitted but was queued instead. | 1400 | * Returns false if the frame couldn't be transmitted but was queued instead. |
1372 | */ | 1401 | */ |
@@ -2370,6 +2399,10 @@ static void ieee80211_update_csa(struct ieee80211_sub_if_data *sdata, | |||
2370 | beacon_data = beacon->head; | 2399 | beacon_data = beacon->head; |
2371 | beacon_data_len = beacon->head_len; | 2400 | beacon_data_len = beacon->head_len; |
2372 | break; | 2401 | break; |
2402 | case NL80211_IFTYPE_MESH_POINT: | ||
2403 | beacon_data = beacon->head; | ||
2404 | beacon_data_len = beacon->head_len; | ||
2405 | break; | ||
2373 | default: | 2406 | default: |
2374 | return; | 2407 | return; |
2375 | } | 2408 | } |
@@ -2426,6 +2459,15 @@ bool ieee80211_csa_is_complete(struct ieee80211_vif *vif) | |||
2426 | 2459 | ||
2427 | beacon_data = beacon->head; | 2460 | beacon_data = beacon->head; |
2428 | beacon_data_len = beacon->head_len; | 2461 | beacon_data_len = beacon->head_len; |
2462 | } else if (vif->type == NL80211_IFTYPE_MESH_POINT) { | ||
2463 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
2464 | |||
2465 | beacon = rcu_dereference(ifmsh->beacon); | ||
2466 | if (!beacon) | ||
2467 | goto out; | ||
2468 | |||
2469 | beacon_data = beacon->head; | ||
2470 | beacon_data_len = beacon->head_len; | ||
2429 | } else { | 2471 | } else { |
2430 | WARN_ON(1); | 2472 | WARN_ON(1); |
2431 | goto out; | 2473 | goto out; |
@@ -2531,6 +2573,9 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2531 | if (!bcn) | 2573 | if (!bcn) |
2532 | goto out; | 2574 | goto out; |
2533 | 2575 | ||
2576 | if (sdata->vif.csa_active) | ||
2577 | ieee80211_update_csa(sdata, bcn); | ||
2578 | |||
2534 | if (ifmsh->sync_ops) | 2579 | if (ifmsh->sync_ops) |
2535 | ifmsh->sync_ops->adjust_tbtt( | 2580 | ifmsh->sync_ops->adjust_tbtt( |
2536 | sdata); | 2581 | sdata); |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index aefb9d5b9620..592a18171f95 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -300,9 +300,6 @@ void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue) | |||
300 | if (!sdata->dev) | 300 | if (!sdata->dev) |
301 | continue; | 301 | continue; |
302 | 302 | ||
303 | if (test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state)) | ||
304 | continue; | ||
305 | |||
306 | if (sdata->vif.cab_queue != IEEE80211_INVAL_HW_QUEUE && | 303 | if (sdata->vif.cab_queue != IEEE80211_INVAL_HW_QUEUE && |
307 | local->queue_stop_reasons[sdata->vif.cab_queue] != 0) | 304 | local->queue_stop_reasons[sdata->vif.cab_queue] != 0) |
308 | continue; | 305 | continue; |
@@ -743,6 +740,7 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, | |||
743 | case WLAN_EID_TIMEOUT_INTERVAL: | 740 | case WLAN_EID_TIMEOUT_INTERVAL: |
744 | case WLAN_EID_SECONDARY_CHANNEL_OFFSET: | 741 | case WLAN_EID_SECONDARY_CHANNEL_OFFSET: |
745 | case WLAN_EID_WIDE_BW_CHANNEL_SWITCH: | 742 | case WLAN_EID_WIDE_BW_CHANNEL_SWITCH: |
743 | case WLAN_EID_CHAN_SWITCH_PARAM: | ||
746 | /* | 744 | /* |
747 | * not listing WLAN_EID_CHANNEL_SWITCH_WRAPPER -- it seems possible | 745 | * not listing WLAN_EID_CHANNEL_SWITCH_WRAPPER -- it seems possible |
748 | * that if the content gets bigger it might be needed more than once | 746 | * that if the content gets bigger it might be needed more than once |
@@ -908,6 +906,14 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, | |||
908 | } | 906 | } |
909 | elems->sec_chan_offs = (void *)pos; | 907 | elems->sec_chan_offs = (void *)pos; |
910 | break; | 908 | break; |
909 | case WLAN_EID_CHAN_SWITCH_PARAM: | ||
910 | if (elen != | ||
911 | sizeof(*elems->mesh_chansw_params_ie)) { | ||
912 | elem_parse_failed = true; | ||
913 | break; | ||
914 | } | ||
915 | elems->mesh_chansw_params_ie = (void *)pos; | ||
916 | break; | ||
911 | case WLAN_EID_WIDE_BW_CHANNEL_SWITCH: | 917 | case WLAN_EID_WIDE_BW_CHANNEL_SWITCH: |
912 | if (!action || | 918 | if (!action || |
913 | elen != sizeof(*elems->wide_bw_chansw_ie)) { | 919 | elen != sizeof(*elems->wide_bw_chansw_ie)) { |
@@ -2354,3 +2360,115 @@ u32 ieee80211_chandef_downgrade(struct cfg80211_chan_def *c) | |||
2354 | 2360 | ||
2355 | return ret; | 2361 | return ret; |
2356 | } | 2362 | } |
2363 | |||
2364 | /* | ||
2365 | * Returns true if smps_mode_new is strictly more restrictive than | ||
2366 | * smps_mode_old. | ||
2367 | */ | ||
2368 | bool ieee80211_smps_is_restrictive(enum ieee80211_smps_mode smps_mode_old, | ||
2369 | enum ieee80211_smps_mode smps_mode_new) | ||
2370 | { | ||
2371 | if (WARN_ON_ONCE(smps_mode_old == IEEE80211_SMPS_AUTOMATIC || | ||
2372 | smps_mode_new == IEEE80211_SMPS_AUTOMATIC)) | ||
2373 | return false; | ||
2374 | |||
2375 | switch (smps_mode_old) { | ||
2376 | case IEEE80211_SMPS_STATIC: | ||
2377 | return false; | ||
2378 | case IEEE80211_SMPS_DYNAMIC: | ||
2379 | return smps_mode_new == IEEE80211_SMPS_STATIC; | ||
2380 | case IEEE80211_SMPS_OFF: | ||
2381 | return smps_mode_new != IEEE80211_SMPS_OFF; | ||
2382 | default: | ||
2383 | WARN_ON(1); | ||
2384 | } | ||
2385 | |||
2386 | return false; | ||
2387 | } | ||
2388 | |||
2389 | int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata, | ||
2390 | struct cfg80211_csa_settings *csa_settings) | ||
2391 | { | ||
2392 | struct sk_buff *skb; | ||
2393 | struct ieee80211_mgmt *mgmt; | ||
2394 | struct ieee80211_local *local = sdata->local; | ||
2395 | int freq; | ||
2396 | int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.chan_switch) + | ||
2397 | sizeof(mgmt->u.action.u.chan_switch); | ||
2398 | u8 *pos; | ||
2399 | |||
2400 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC && | ||
2401 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT) | ||
2402 | return -EOPNOTSUPP; | ||
2403 | |||
2404 | skb = dev_alloc_skb(local->tx_headroom + hdr_len + | ||
2405 | 5 + /* channel switch announcement element */ | ||
2406 | 3 + /* secondary channel offset element */ | ||
2407 | 8); /* mesh channel switch parameters element */ | ||
2408 | if (!skb) | ||
2409 | return -ENOMEM; | ||
2410 | |||
2411 | skb_reserve(skb, local->tx_headroom); | ||
2412 | mgmt = (struct ieee80211_mgmt *)skb_put(skb, hdr_len); | ||
2413 | memset(mgmt, 0, hdr_len); | ||
2414 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
2415 | IEEE80211_STYPE_ACTION); | ||
2416 | |||
2417 | eth_broadcast_addr(mgmt->da); | ||
2418 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); | ||
2419 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | ||
2420 | memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); | ||
2421 | } else { | ||
2422 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | ||
2423 | memcpy(mgmt->bssid, ifibss->bssid, ETH_ALEN); | ||
2424 | } | ||
2425 | mgmt->u.action.category = WLAN_CATEGORY_SPECTRUM_MGMT; | ||
2426 | mgmt->u.action.u.chan_switch.action_code = WLAN_ACTION_SPCT_CHL_SWITCH; | ||
2427 | pos = skb_put(skb, 5); | ||
2428 | *pos++ = WLAN_EID_CHANNEL_SWITCH; /* EID */ | ||
2429 | *pos++ = 3; /* IE length */ | ||
2430 | *pos++ = csa_settings->block_tx ? 1 : 0; /* CSA mode */ | ||
2431 | freq = csa_settings->chandef.chan->center_freq; | ||
2432 | *pos++ = ieee80211_frequency_to_channel(freq); /* channel */ | ||
2433 | *pos++ = csa_settings->count; /* count */ | ||
2434 | |||
2435 | if (csa_settings->chandef.width == NL80211_CHAN_WIDTH_40) { | ||
2436 | enum nl80211_channel_type ch_type; | ||
2437 | |||
2438 | skb_put(skb, 3); | ||
2439 | *pos++ = WLAN_EID_SECONDARY_CHANNEL_OFFSET; /* EID */ | ||
2440 | *pos++ = 1; /* IE length */ | ||
2441 | ch_type = cfg80211_get_chandef_type(&csa_settings->chandef); | ||
2442 | if (ch_type == NL80211_CHAN_HT40PLUS) | ||
2443 | *pos++ = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; | ||
2444 | else | ||
2445 | *pos++ = IEEE80211_HT_PARAM_CHA_SEC_BELOW; | ||
2446 | } | ||
2447 | |||
2448 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | ||
2449 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
2450 | __le16 pre_value; | ||
2451 | |||
2452 | skb_put(skb, 8); | ||
2453 | *pos++ = WLAN_EID_CHAN_SWITCH_PARAM; /* EID */ | ||
2454 | *pos++ = 6; /* IE length */ | ||
2455 | *pos++ = sdata->u.mesh.mshcfg.dot11MeshTTL; /* Mesh TTL */ | ||
2456 | *pos = 0x00; /* Mesh Flag: Tx Restrict, Initiator, Reason */ | ||
2457 | *pos |= WLAN_EID_CHAN_SWITCH_PARAM_INITIATOR; | ||
2458 | *pos++ |= csa_settings->block_tx ? | ||
2459 | WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT : 0x00; | ||
2460 | put_unaligned_le16(WLAN_REASON_MESH_CHAN, pos); /* Reason Cd */ | ||
2461 | pos += 2; | ||
2462 | if (!ifmsh->pre_value) | ||
2463 | ifmsh->pre_value = 1; | ||
2464 | else | ||
2465 | ifmsh->pre_value++; | ||
2466 | pre_value = cpu_to_le16(ifmsh->pre_value); | ||
2467 | memcpy(pos, &pre_value, 2); /* Precedence Value */ | ||
2468 | pos += 2; | ||
2469 | ifmsh->chsw_init = true; | ||
2470 | } | ||
2471 | |||
2472 | ieee80211_tx_skb(sdata, skb); | ||
2473 | return 0; | ||
2474 | } | ||
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index c9edfcb7a13b..d65728220763 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -301,22 +301,16 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) | |||
301 | } | 301 | } |
302 | 302 | ||
303 | 303 | ||
304 | static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch, | 304 | static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad, |
305 | int encrypted) | 305 | int encrypted) |
306 | { | 306 | { |
307 | __le16 mask_fc; | 307 | __le16 mask_fc; |
308 | int a4_included, mgmt; | 308 | int a4_included, mgmt; |
309 | u8 qos_tid; | 309 | u8 qos_tid; |
310 | u8 *b_0, *aad; | 310 | u16 len_a; |
311 | u16 data_len, len_a; | ||
312 | unsigned int hdrlen; | 311 | unsigned int hdrlen; |
313 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 312 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
314 | 313 | ||
315 | memset(scratch, 0, 6 * AES_BLOCK_SIZE); | ||
316 | |||
317 | b_0 = scratch + 3 * AES_BLOCK_SIZE; | ||
318 | aad = scratch + 4 * AES_BLOCK_SIZE; | ||
319 | |||
320 | /* | 314 | /* |
321 | * Mask FC: zero subtype b4 b5 b6 (if not mgmt) | 315 | * Mask FC: zero subtype b4 b5 b6 (if not mgmt) |
322 | * Retry, PwrMgt, MoreData; set Protected | 316 | * Retry, PwrMgt, MoreData; set Protected |
@@ -338,20 +332,21 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch, | |||
338 | else | 332 | else |
339 | qos_tid = 0; | 333 | qos_tid = 0; |
340 | 334 | ||
341 | data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN; | 335 | /* In CCM, the initial vectors (IV) used for CTR mode encryption and CBC |
342 | if (encrypted) | 336 | * mode authentication are not allowed to collide, yet both are derived |
343 | data_len -= IEEE80211_CCMP_MIC_LEN; | 337 | * from this vector b_0. We only set L := 1 here to indicate that the |
338 | * data size can be represented in (L+1) bytes. The CCM layer will take | ||
339 | * care of storing the data length in the top (L+1) bytes and setting | ||
340 | * and clearing the other bits as is required to derive the two IVs. | ||
341 | */ | ||
342 | b_0[0] = 0x1; | ||
344 | 343 | ||
345 | /* First block, b_0 */ | ||
346 | b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */ | ||
347 | /* Nonce: Nonce Flags | A2 | PN | 344 | /* Nonce: Nonce Flags | A2 | PN |
348 | * Nonce Flags: Priority (b0..b3) | Management (b4) | Reserved (b5..b7) | 345 | * Nonce Flags: Priority (b0..b3) | Management (b4) | Reserved (b5..b7) |
349 | */ | 346 | */ |
350 | b_0[1] = qos_tid | (mgmt << 4); | 347 | b_0[1] = qos_tid | (mgmt << 4); |
351 | memcpy(&b_0[2], hdr->addr2, ETH_ALEN); | 348 | memcpy(&b_0[2], hdr->addr2, ETH_ALEN); |
352 | memcpy(&b_0[8], pn, IEEE80211_CCMP_PN_LEN); | 349 | memcpy(&b_0[8], pn, IEEE80211_CCMP_PN_LEN); |
353 | /* l(m) */ | ||
354 | put_unaligned_be16(data_len, &b_0[14]); | ||
355 | 350 | ||
356 | /* AAD (extra authenticate-only data) / masked 802.11 header | 351 | /* AAD (extra authenticate-only data) / masked 802.11 header |
357 | * FC | A1 | A2 | A3 | SC | [A4] | [QC] */ | 352 | * FC | A1 | A2 | A3 | SC | [A4] | [QC] */ |
@@ -407,7 +402,8 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
407 | u8 *pos; | 402 | u8 *pos; |
408 | u8 pn[6]; | 403 | u8 pn[6]; |
409 | u64 pn64; | 404 | u64 pn64; |
410 | u8 scratch[6 * AES_BLOCK_SIZE]; | 405 | u8 aad[2 * AES_BLOCK_SIZE]; |
406 | u8 b_0[AES_BLOCK_SIZE]; | ||
411 | 407 | ||
412 | if (info->control.hw_key && | 408 | if (info->control.hw_key && |
413 | !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) && | 409 | !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) && |
@@ -460,9 +456,9 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
460 | return 0; | 456 | return 0; |
461 | 457 | ||
462 | pos += IEEE80211_CCMP_HDR_LEN; | 458 | pos += IEEE80211_CCMP_HDR_LEN; |
463 | ccmp_special_blocks(skb, pn, scratch, 0); | 459 | ccmp_special_blocks(skb, pn, b_0, aad, 0); |
464 | ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, scratch, pos, len, | 460 | ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len, |
465 | pos, skb_put(skb, IEEE80211_CCMP_MIC_LEN)); | 461 | skb_put(skb, IEEE80211_CCMP_MIC_LEN)); |
466 | 462 | ||
467 | return 0; | 463 | return 0; |
468 | } | 464 | } |
@@ -525,16 +521,16 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) | |||
525 | } | 521 | } |
526 | 522 | ||
527 | if (!(status->flag & RX_FLAG_DECRYPTED)) { | 523 | if (!(status->flag & RX_FLAG_DECRYPTED)) { |
528 | u8 scratch[6 * AES_BLOCK_SIZE]; | 524 | u8 aad[2 * AES_BLOCK_SIZE]; |
525 | u8 b_0[AES_BLOCK_SIZE]; | ||
529 | /* hardware didn't decrypt/verify MIC */ | 526 | /* hardware didn't decrypt/verify MIC */ |
530 | ccmp_special_blocks(skb, pn, scratch, 1); | 527 | ccmp_special_blocks(skb, pn, b_0, aad, 1); |
531 | 528 | ||
532 | if (ieee80211_aes_ccm_decrypt( | 529 | if (ieee80211_aes_ccm_decrypt( |
533 | key->u.ccmp.tfm, scratch, | 530 | key->u.ccmp.tfm, b_0, aad, |
534 | skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN, | 531 | skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN, |
535 | data_len, | 532 | data_len, |
536 | skb->data + skb->len - IEEE80211_CCMP_MIC_LEN, | 533 | skb->data + skb->len - IEEE80211_CCMP_MIC_LEN)) |
537 | skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN)) | ||
538 | return RX_DROP_UNUSABLE; | 534 | return RX_DROP_UNUSABLE; |
539 | } | 535 | } |
540 | 536 | ||
diff --git a/net/rfkill/Kconfig b/net/rfkill/Kconfig index 78efe895b663..4c10e7e6c9f6 100644 --- a/net/rfkill/Kconfig +++ b/net/rfkill/Kconfig | |||
@@ -36,7 +36,7 @@ config RFKILL_REGULATOR | |||
36 | 36 | ||
37 | config RFKILL_GPIO | 37 | config RFKILL_GPIO |
38 | tristate "GPIO RFKILL driver" | 38 | tristate "GPIO RFKILL driver" |
39 | depends on RFKILL && GPIOLIB && HAVE_CLK | 39 | depends on RFKILL && GPIOLIB |
40 | default n | 40 | default n |
41 | help | 41 | help |
42 | If you say yes here you get support of a generic gpio RFKILL | 42 | If you say yes here you get support of a generic gpio RFKILL |
diff --git a/net/rfkill/rfkill-gpio.c b/net/rfkill/rfkill-gpio.c index fb076cd6f808..5620d3c07479 100644 --- a/net/rfkill/rfkill-gpio.c +++ b/net/rfkill/rfkill-gpio.c | |||
@@ -24,27 +24,23 @@ | |||
24 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
25 | #include <linux/clk.h> | 25 | #include <linux/clk.h> |
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | #include <linux/acpi.h> | ||
28 | #include <linux/acpi_gpio.h> | ||
27 | 29 | ||
28 | #include <linux/rfkill-gpio.h> | 30 | #include <linux/rfkill-gpio.h> |
29 | 31 | ||
30 | enum rfkill_gpio_clk_state { | 32 | struct rfkill_gpio_data { |
31 | UNSPECIFIED = 0, | 33 | const char *name; |
32 | PWR_ENABLED, | 34 | enum rfkill_type type; |
33 | PWR_DISABLED | 35 | int reset_gpio; |
34 | }; | 36 | int shutdown_gpio; |
35 | 37 | ||
36 | #define PWR_CLK_SET(_RF, _EN) \ | 38 | struct rfkill *rfkill_dev; |
37 | ((_RF)->pwr_clk_enabled = (!(_EN) ? PWR_ENABLED : PWR_DISABLED)) | 39 | char *reset_name; |
38 | #define PWR_CLK_ENABLED(_RF) ((_RF)->pwr_clk_enabled == PWR_ENABLED) | 40 | char *shutdown_name; |
39 | #define PWR_CLK_DISABLED(_RF) ((_RF)->pwr_clk_enabled != PWR_ENABLED) | 41 | struct clk *clk; |
40 | 42 | ||
41 | struct rfkill_gpio_data { | 43 | bool clk_enabled; |
42 | struct rfkill_gpio_platform_data *pdata; | ||
43 | struct rfkill *rfkill_dev; | ||
44 | char *reset_name; | ||
45 | char *shutdown_name; | ||
46 | enum rfkill_gpio_clk_state pwr_clk_enabled; | ||
47 | struct clk *pwr_clk; | ||
48 | }; | 44 | }; |
49 | 45 | ||
50 | static int rfkill_gpio_set_power(void *data, bool blocked) | 46 | static int rfkill_gpio_set_power(void *data, bool blocked) |
@@ -52,23 +48,22 @@ static int rfkill_gpio_set_power(void *data, bool blocked) | |||
52 | struct rfkill_gpio_data *rfkill = data; | 48 | struct rfkill_gpio_data *rfkill = data; |
53 | 49 | ||
54 | if (blocked) { | 50 | if (blocked) { |
55 | if (gpio_is_valid(rfkill->pdata->shutdown_gpio)) | 51 | if (gpio_is_valid(rfkill->shutdown_gpio)) |
56 | gpio_direction_output(rfkill->pdata->shutdown_gpio, 0); | 52 | gpio_set_value(rfkill->shutdown_gpio, 0); |
57 | if (gpio_is_valid(rfkill->pdata->reset_gpio)) | 53 | if (gpio_is_valid(rfkill->reset_gpio)) |
58 | gpio_direction_output(rfkill->pdata->reset_gpio, 0); | 54 | gpio_set_value(rfkill->reset_gpio, 0); |
59 | if (rfkill->pwr_clk && PWR_CLK_ENABLED(rfkill)) | 55 | if (!IS_ERR(rfkill->clk) && rfkill->clk_enabled) |
60 | clk_disable(rfkill->pwr_clk); | 56 | clk_disable(rfkill->clk); |
61 | } else { | 57 | } else { |
62 | if (rfkill->pwr_clk && PWR_CLK_DISABLED(rfkill)) | 58 | if (!IS_ERR(rfkill->clk) && !rfkill->clk_enabled) |
63 | clk_enable(rfkill->pwr_clk); | 59 | clk_enable(rfkill->clk); |
64 | if (gpio_is_valid(rfkill->pdata->reset_gpio)) | 60 | if (gpio_is_valid(rfkill->reset_gpio)) |
65 | gpio_direction_output(rfkill->pdata->reset_gpio, 1); | 61 | gpio_set_value(rfkill->reset_gpio, 1); |
66 | if (gpio_is_valid(rfkill->pdata->shutdown_gpio)) | 62 | if (gpio_is_valid(rfkill->shutdown_gpio)) |
67 | gpio_direction_output(rfkill->pdata->shutdown_gpio, 1); | 63 | gpio_set_value(rfkill->shutdown_gpio, 1); |
68 | } | 64 | } |
69 | 65 | ||
70 | if (rfkill->pwr_clk) | 66 | rfkill->clk_enabled = blocked; |
71 | PWR_CLK_SET(rfkill, blocked); | ||
72 | 67 | ||
73 | return 0; | 68 | return 0; |
74 | } | 69 | } |
@@ -77,117 +72,112 @@ static const struct rfkill_ops rfkill_gpio_ops = { | |||
77 | .set_block = rfkill_gpio_set_power, | 72 | .set_block = rfkill_gpio_set_power, |
78 | }; | 73 | }; |
79 | 74 | ||
75 | static int rfkill_gpio_acpi_probe(struct device *dev, | ||
76 | struct rfkill_gpio_data *rfkill) | ||
77 | { | ||
78 | const struct acpi_device_id *id; | ||
79 | |||
80 | id = acpi_match_device(dev->driver->acpi_match_table, dev); | ||
81 | if (!id) | ||
82 | return -ENODEV; | ||
83 | |||
84 | rfkill->name = dev_name(dev); | ||
85 | rfkill->type = (unsigned)id->driver_data; | ||
86 | rfkill->reset_gpio = acpi_get_gpio_by_index(dev, 0, NULL); | ||
87 | rfkill->shutdown_gpio = acpi_get_gpio_by_index(dev, 1, NULL); | ||
88 | |||
89 | return 0; | ||
90 | } | ||
91 | |||
80 | static int rfkill_gpio_probe(struct platform_device *pdev) | 92 | static int rfkill_gpio_probe(struct platform_device *pdev) |
81 | { | 93 | { |
82 | struct rfkill_gpio_data *rfkill; | ||
83 | struct rfkill_gpio_platform_data *pdata = pdev->dev.platform_data; | 94 | struct rfkill_gpio_platform_data *pdata = pdev->dev.platform_data; |
95 | struct rfkill_gpio_data *rfkill; | ||
96 | const char *clk_name = NULL; | ||
84 | int ret = 0; | 97 | int ret = 0; |
85 | int len = 0; | 98 | int len = 0; |
86 | 99 | ||
87 | if (!pdata) { | 100 | rfkill = devm_kzalloc(&pdev->dev, sizeof(*rfkill), GFP_KERNEL); |
88 | pr_warn("%s: No platform data specified\n", __func__); | 101 | if (!rfkill) |
89 | return -EINVAL; | 102 | return -ENOMEM; |
103 | |||
104 | if (ACPI_HANDLE(&pdev->dev)) { | ||
105 | ret = rfkill_gpio_acpi_probe(&pdev->dev, rfkill); | ||
106 | if (ret) | ||
107 | return ret; | ||
108 | } else if (pdata) { | ||
109 | clk_name = pdata->power_clk_name; | ||
110 | rfkill->name = pdata->name; | ||
111 | rfkill->type = pdata->type; | ||
112 | rfkill->reset_gpio = pdata->reset_gpio; | ||
113 | rfkill->shutdown_gpio = pdata->shutdown_gpio; | ||
114 | } else { | ||
115 | return -ENODEV; | ||
90 | } | 116 | } |
91 | 117 | ||
92 | /* make sure at-least one of the GPIO is defined and that | 118 | /* make sure at-least one of the GPIO is defined and that |
93 | * a name is specified for this instance */ | 119 | * a name is specified for this instance */ |
94 | if (!pdata->name || (!gpio_is_valid(pdata->reset_gpio) && | 120 | if ((!gpio_is_valid(rfkill->reset_gpio) && |
95 | !gpio_is_valid(pdata->shutdown_gpio))) { | 121 | !gpio_is_valid(rfkill->shutdown_gpio)) || !rfkill->name) { |
96 | pr_warn("%s: invalid platform data\n", __func__); | 122 | pr_warn("%s: invalid platform data\n", __func__); |
97 | return -EINVAL; | 123 | return -EINVAL; |
98 | } | 124 | } |
99 | 125 | ||
100 | rfkill = kzalloc(sizeof(*rfkill), GFP_KERNEL); | 126 | if (pdata && pdata->gpio_runtime_setup) { |
101 | if (!rfkill) | ||
102 | return -ENOMEM; | ||
103 | |||
104 | if (pdata->gpio_runtime_setup) { | ||
105 | ret = pdata->gpio_runtime_setup(pdev); | 127 | ret = pdata->gpio_runtime_setup(pdev); |
106 | if (ret) { | 128 | if (ret) { |
107 | pr_warn("%s: can't set up gpio\n", __func__); | 129 | pr_warn("%s: can't set up gpio\n", __func__); |
108 | goto fail_alloc; | 130 | return ret; |
109 | } | 131 | } |
110 | } | 132 | } |
111 | 133 | ||
112 | rfkill->pdata = pdata; | 134 | len = strlen(rfkill->name); |
113 | 135 | rfkill->reset_name = devm_kzalloc(&pdev->dev, len + 7, GFP_KERNEL); | |
114 | len = strlen(pdata->name); | 136 | if (!rfkill->reset_name) |
115 | rfkill->reset_name = kzalloc(len + 7, GFP_KERNEL); | 137 | return -ENOMEM; |
116 | if (!rfkill->reset_name) { | ||
117 | ret = -ENOMEM; | ||
118 | goto fail_alloc; | ||
119 | } | ||
120 | 138 | ||
121 | rfkill->shutdown_name = kzalloc(len + 10, GFP_KERNEL); | 139 | rfkill->shutdown_name = devm_kzalloc(&pdev->dev, len + 10, GFP_KERNEL); |
122 | if (!rfkill->shutdown_name) { | 140 | if (!rfkill->shutdown_name) |
123 | ret = -ENOMEM; | 141 | return -ENOMEM; |
124 | goto fail_reset_name; | ||
125 | } | ||
126 | 142 | ||
127 | snprintf(rfkill->reset_name, len + 6 , "%s_reset", pdata->name); | 143 | snprintf(rfkill->reset_name, len + 6 , "%s_reset", rfkill->name); |
128 | snprintf(rfkill->shutdown_name, len + 9, "%s_shutdown", pdata->name); | 144 | snprintf(rfkill->shutdown_name, len + 9, "%s_shutdown", rfkill->name); |
129 | 145 | ||
130 | if (pdata->power_clk_name) { | 146 | rfkill->clk = devm_clk_get(&pdev->dev, clk_name); |
131 | rfkill->pwr_clk = clk_get(&pdev->dev, pdata->power_clk_name); | ||
132 | if (IS_ERR(rfkill->pwr_clk)) { | ||
133 | pr_warn("%s: can't find pwr_clk.\n", __func__); | ||
134 | ret = PTR_ERR(rfkill->pwr_clk); | ||
135 | goto fail_shutdown_name; | ||
136 | } | ||
137 | } | ||
138 | 147 | ||
139 | if (gpio_is_valid(pdata->reset_gpio)) { | 148 | if (gpio_is_valid(rfkill->reset_gpio)) { |
140 | ret = gpio_request(pdata->reset_gpio, rfkill->reset_name); | 149 | ret = devm_gpio_request_one(&pdev->dev, rfkill->reset_gpio, |
150 | 0, rfkill->reset_name); | ||
141 | if (ret) { | 151 | if (ret) { |
142 | pr_warn("%s: failed to get reset gpio.\n", __func__); | 152 | pr_warn("%s: failed to get reset gpio.\n", __func__); |
143 | goto fail_clock; | 153 | return ret; |
144 | } | 154 | } |
145 | } | 155 | } |
146 | 156 | ||
147 | if (gpio_is_valid(pdata->shutdown_gpio)) { | 157 | if (gpio_is_valid(rfkill->shutdown_gpio)) { |
148 | ret = gpio_request(pdata->shutdown_gpio, rfkill->shutdown_name); | 158 | ret = devm_gpio_request_one(&pdev->dev, rfkill->shutdown_gpio, |
159 | 0, rfkill->shutdown_name); | ||
149 | if (ret) { | 160 | if (ret) { |
150 | pr_warn("%s: failed to get shutdown gpio.\n", __func__); | 161 | pr_warn("%s: failed to get shutdown gpio.\n", __func__); |
151 | goto fail_reset; | 162 | return ret; |
152 | } | 163 | } |
153 | } | 164 | } |
154 | 165 | ||
155 | rfkill->rfkill_dev = rfkill_alloc(pdata->name, &pdev->dev, pdata->type, | 166 | rfkill->rfkill_dev = rfkill_alloc(rfkill->name, &pdev->dev, |
156 | &rfkill_gpio_ops, rfkill); | 167 | rfkill->type, &rfkill_gpio_ops, |
157 | if (!rfkill->rfkill_dev) { | 168 | rfkill); |
158 | ret = -ENOMEM; | 169 | if (!rfkill->rfkill_dev) |
159 | goto fail_shutdown; | 170 | return -ENOMEM; |
160 | } | ||
161 | 171 | ||
162 | ret = rfkill_register(rfkill->rfkill_dev); | 172 | ret = rfkill_register(rfkill->rfkill_dev); |
163 | if (ret < 0) | 173 | if (ret < 0) |
164 | goto fail_rfkill; | 174 | return ret; |
165 | 175 | ||
166 | platform_set_drvdata(pdev, rfkill); | 176 | platform_set_drvdata(pdev, rfkill); |
167 | 177 | ||
168 | dev_info(&pdev->dev, "%s device registered.\n", pdata->name); | 178 | dev_info(&pdev->dev, "%s device registered.\n", rfkill->name); |
169 | 179 | ||
170 | return 0; | 180 | return 0; |
171 | |||
172 | fail_rfkill: | ||
173 | rfkill_destroy(rfkill->rfkill_dev); | ||
174 | fail_shutdown: | ||
175 | if (gpio_is_valid(pdata->shutdown_gpio)) | ||
176 | gpio_free(pdata->shutdown_gpio); | ||
177 | fail_reset: | ||
178 | if (gpio_is_valid(pdata->reset_gpio)) | ||
179 | gpio_free(pdata->reset_gpio); | ||
180 | fail_clock: | ||
181 | if (rfkill->pwr_clk) | ||
182 | clk_put(rfkill->pwr_clk); | ||
183 | fail_shutdown_name: | ||
184 | kfree(rfkill->shutdown_name); | ||
185 | fail_reset_name: | ||
186 | kfree(rfkill->reset_name); | ||
187 | fail_alloc: | ||
188 | kfree(rfkill); | ||
189 | |||
190 | return ret; | ||
191 | } | 181 | } |
192 | 182 | ||
193 | static int rfkill_gpio_remove(struct platform_device *pdev) | 183 | static int rfkill_gpio_remove(struct platform_device *pdev) |
@@ -195,31 +185,26 @@ static int rfkill_gpio_remove(struct platform_device *pdev) | |||
195 | struct rfkill_gpio_data *rfkill = platform_get_drvdata(pdev); | 185 | struct rfkill_gpio_data *rfkill = platform_get_drvdata(pdev); |
196 | struct rfkill_gpio_platform_data *pdata = pdev->dev.platform_data; | 186 | struct rfkill_gpio_platform_data *pdata = pdev->dev.platform_data; |
197 | 187 | ||
198 | if (pdata->gpio_runtime_close) | 188 | if (pdata && pdata->gpio_runtime_close) |
199 | pdata->gpio_runtime_close(pdev); | 189 | pdata->gpio_runtime_close(pdev); |
200 | rfkill_unregister(rfkill->rfkill_dev); | 190 | rfkill_unregister(rfkill->rfkill_dev); |
201 | rfkill_destroy(rfkill->rfkill_dev); | 191 | rfkill_destroy(rfkill->rfkill_dev); |
202 | if (gpio_is_valid(rfkill->pdata->shutdown_gpio)) | ||
203 | gpio_free(rfkill->pdata->shutdown_gpio); | ||
204 | if (gpio_is_valid(rfkill->pdata->reset_gpio)) | ||
205 | gpio_free(rfkill->pdata->reset_gpio); | ||
206 | if (rfkill->pwr_clk && PWR_CLK_ENABLED(rfkill)) | ||
207 | clk_disable(rfkill->pwr_clk); | ||
208 | if (rfkill->pwr_clk) | ||
209 | clk_put(rfkill->pwr_clk); | ||
210 | kfree(rfkill->shutdown_name); | ||
211 | kfree(rfkill->reset_name); | ||
212 | kfree(rfkill); | ||
213 | 192 | ||
214 | return 0; | 193 | return 0; |
215 | } | 194 | } |
216 | 195 | ||
196 | static const struct acpi_device_id rfkill_acpi_match[] = { | ||
197 | { "BCM4752", RFKILL_TYPE_GPS }, | ||
198 | { }, | ||
199 | }; | ||
200 | |||
217 | static struct platform_driver rfkill_gpio_driver = { | 201 | static struct platform_driver rfkill_gpio_driver = { |
218 | .probe = rfkill_gpio_probe, | 202 | .probe = rfkill_gpio_probe, |
219 | .remove = rfkill_gpio_remove, | 203 | .remove = rfkill_gpio_remove, |
220 | .driver = { | 204 | .driver = { |
221 | .name = "rfkill_gpio", | 205 | .name = "rfkill_gpio", |
222 | .owner = THIS_MODULE, | 206 | .owner = THIS_MODULE, |
207 | .acpi_match_table = ACPI_PTR(rfkill_acpi_match), | ||
223 | }, | 208 | }, |
224 | }; | 209 | }; |
225 | 210 | ||
diff --git a/net/wireless/chan.c b/net/wireless/chan.c index 16f3c3a7b2c1..9b8cc877eb19 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c | |||
@@ -504,7 +504,8 @@ cfg80211_get_chan_state(struct wireless_dev *wdev, | |||
504 | case NL80211_IFTYPE_ADHOC: | 504 | case NL80211_IFTYPE_ADHOC: |
505 | if (wdev->current_bss) { | 505 | if (wdev->current_bss) { |
506 | *chan = wdev->current_bss->pub.channel; | 506 | *chan = wdev->current_bss->pub.channel; |
507 | *chanmode = wdev->ibss_fixed | 507 | *chanmode = (wdev->ibss_fixed && |
508 | !wdev->ibss_dfs_possible) | ||
508 | ? CHAN_MODE_SHARED | 509 | ? CHAN_MODE_SHARED |
509 | : CHAN_MODE_EXCLUSIVE; | 510 | : CHAN_MODE_EXCLUSIVE; |
510 | return; | 511 | return; |
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index 403fe29c024d..9d797df56649 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c | |||
@@ -83,6 +83,8 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, | |||
83 | struct cfg80211_cached_keys *connkeys) | 83 | struct cfg80211_cached_keys *connkeys) |
84 | { | 84 | { |
85 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 85 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
86 | struct ieee80211_channel *check_chan; | ||
87 | u8 radar_detect_width = 0; | ||
86 | int err; | 88 | int err; |
87 | 89 | ||
88 | ASSERT_WDEV_LOCK(wdev); | 90 | ASSERT_WDEV_LOCK(wdev); |
@@ -114,14 +116,28 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, | |||
114 | wdev->connect_keys = connkeys; | 116 | wdev->connect_keys = connkeys; |
115 | 117 | ||
116 | wdev->ibss_fixed = params->channel_fixed; | 118 | wdev->ibss_fixed = params->channel_fixed; |
119 | wdev->ibss_dfs_possible = params->userspace_handles_dfs; | ||
117 | #ifdef CONFIG_CFG80211_WEXT | 120 | #ifdef CONFIG_CFG80211_WEXT |
118 | wdev->wext.ibss.chandef = params->chandef; | 121 | wdev->wext.ibss.chandef = params->chandef; |
119 | #endif | 122 | #endif |
123 | check_chan = params->chandef.chan; | ||
124 | if (params->userspace_handles_dfs) { | ||
125 | /* use channel NULL to check for radar even if the current | ||
126 | * channel is not a radar channel - it might decide to change | ||
127 | * to DFS channel later. | ||
128 | */ | ||
129 | radar_detect_width = BIT(params->chandef.width); | ||
130 | check_chan = NULL; | ||
131 | } | ||
132 | |||
133 | err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype, | ||
134 | check_chan, | ||
135 | (params->channel_fixed && | ||
136 | !radar_detect_width) | ||
137 | ? CHAN_MODE_SHARED | ||
138 | : CHAN_MODE_EXCLUSIVE, | ||
139 | radar_detect_width); | ||
120 | 140 | ||
121 | err = cfg80211_can_use_chan(rdev, wdev, params->chandef.chan, | ||
122 | params->channel_fixed | ||
123 | ? CHAN_MODE_SHARED | ||
124 | : CHAN_MODE_EXCLUSIVE); | ||
125 | if (err) { | 141 | if (err) { |
126 | wdev->connect_keys = NULL; | 142 | wdev->connect_keys = NULL; |
127 | return err; | 143 | return err; |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 8d49c1ce3dea..6a6b1c8e907d 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -707,11 +707,13 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work) | |||
707 | if (c->dfs_state != NL80211_DFS_UNAVAILABLE) | 707 | if (c->dfs_state != NL80211_DFS_UNAVAILABLE) |
708 | continue; | 708 | continue; |
709 | 709 | ||
710 | timeout = c->dfs_state_entered + | 710 | timeout = c->dfs_state_entered + msecs_to_jiffies( |
711 | IEEE80211_DFS_MIN_NOP_TIME_MS; | 711 | IEEE80211_DFS_MIN_NOP_TIME_MS); |
712 | 712 | ||
713 | if (time_after_eq(jiffies, timeout)) { | 713 | if (time_after_eq(jiffies, timeout)) { |
714 | c->dfs_state = NL80211_DFS_USABLE; | 714 | c->dfs_state = NL80211_DFS_USABLE; |
715 | c->dfs_state_entered = jiffies; | ||
716 | |||
715 | cfg80211_chandef_create(&chandef, c, | 717 | cfg80211_chandef_create(&chandef, c, |
716 | NL80211_CHAN_NO_HT); | 718 | NL80211_CHAN_NO_HT); |
717 | 719 | ||
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index cbbef88a8ebd..a7f4e7902104 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -354,6 +354,9 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
354 | [NL80211_ATTR_CSA_IES] = { .type = NLA_NESTED }, | 354 | [NL80211_ATTR_CSA_IES] = { .type = NLA_NESTED }, |
355 | [NL80211_ATTR_CSA_C_OFF_BEACON] = { .type = NLA_U16 }, | 355 | [NL80211_ATTR_CSA_C_OFF_BEACON] = { .type = NLA_U16 }, |
356 | [NL80211_ATTR_CSA_C_OFF_PRESP] = { .type = NLA_U16 }, | 356 | [NL80211_ATTR_CSA_C_OFF_PRESP] = { .type = NLA_U16 }, |
357 | [NL80211_ATTR_STA_SUPPORTED_CHANNELS] = { .type = NLA_BINARY }, | ||
358 | [NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] = { .type = NLA_BINARY }, | ||
359 | [NL80211_ATTR_HANDLE_DFS] = { .type = NLA_FLAG }, | ||
357 | }; | 360 | }; |
358 | 361 | ||
359 | /* policy for the key attributes */ | 362 | /* policy for the key attributes */ |
@@ -3896,9 +3899,45 @@ static int nl80211_parse_sta_wme(struct genl_info *info, | |||
3896 | return 0; | 3899 | return 0; |
3897 | } | 3900 | } |
3898 | 3901 | ||
3902 | static int nl80211_parse_sta_channel_info(struct genl_info *info, | ||
3903 | struct station_parameters *params) | ||
3904 | { | ||
3905 | if (info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]) { | ||
3906 | params->supported_channels = | ||
3907 | nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]); | ||
3908 | params->supported_channels_len = | ||
3909 | nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]); | ||
3910 | /* | ||
3911 | * Need to include at least one (first channel, number of | ||
3912 | * channels) tuple for each subband, and must have proper | ||
3913 | * tuples for the rest of the data as well. | ||
3914 | */ | ||
3915 | if (params->supported_channels_len < 2) | ||
3916 | return -EINVAL; | ||
3917 | if (params->supported_channels_len % 2) | ||
3918 | return -EINVAL; | ||
3919 | } | ||
3920 | |||
3921 | if (info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]) { | ||
3922 | params->supported_oper_classes = | ||
3923 | nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]); | ||
3924 | params->supported_oper_classes_len = | ||
3925 | nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]); | ||
3926 | /* | ||
3927 | * The value of the Length field of the Supported Operating | ||
3928 | * Classes element is between 2 and 253. | ||
3929 | */ | ||
3930 | if (params->supported_oper_classes_len < 2 || | ||
3931 | params->supported_oper_classes_len > 253) | ||
3932 | return -EINVAL; | ||
3933 | } | ||
3934 | return 0; | ||
3935 | } | ||
3936 | |||
3899 | static int nl80211_set_station_tdls(struct genl_info *info, | 3937 | static int nl80211_set_station_tdls(struct genl_info *info, |
3900 | struct station_parameters *params) | 3938 | struct station_parameters *params) |
3901 | { | 3939 | { |
3940 | int err; | ||
3902 | /* Dummy STA entry gets updated once the peer capabilities are known */ | 3941 | /* Dummy STA entry gets updated once the peer capabilities are known */ |
3903 | if (info->attrs[NL80211_ATTR_PEER_AID]) | 3942 | if (info->attrs[NL80211_ATTR_PEER_AID]) |
3904 | params->aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]); | 3943 | params->aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]); |
@@ -3909,6 +3948,10 @@ static int nl80211_set_station_tdls(struct genl_info *info, | |||
3909 | params->vht_capa = | 3948 | params->vht_capa = |
3910 | nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]); | 3949 | nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]); |
3911 | 3950 | ||
3951 | err = nl80211_parse_sta_channel_info(info, params); | ||
3952 | if (err) | ||
3953 | return err; | ||
3954 | |||
3912 | return nl80211_parse_sta_wme(info, params); | 3955 | return nl80211_parse_sta_wme(info, params); |
3913 | } | 3956 | } |
3914 | 3957 | ||
@@ -4089,6 +4132,10 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
4089 | return -EINVAL; | 4132 | return -EINVAL; |
4090 | } | 4133 | } |
4091 | 4134 | ||
4135 | err = nl80211_parse_sta_channel_info(info, ¶ms); | ||
4136 | if (err) | ||
4137 | return err; | ||
4138 | |||
4092 | err = nl80211_parse_sta_wme(info, ¶ms); | 4139 | err = nl80211_parse_sta_wme(info, ¶ms); |
4093 | if (err) | 4140 | if (err) |
4094 | return err; | 4141 | return err; |
@@ -5653,6 +5700,7 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) | |||
5653 | return -EINVAL; | 5700 | return -EINVAL; |
5654 | break; | 5701 | break; |
5655 | case NL80211_IFTYPE_ADHOC: | 5702 | case NL80211_IFTYPE_ADHOC: |
5703 | case NL80211_IFTYPE_MESH_POINT: | ||
5656 | break; | 5704 | break; |
5657 | default: | 5705 | default: |
5658 | return -EOPNOTSUPP; | 5706 | return -EOPNOTSUPP; |
@@ -5665,9 +5713,7 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) | |||
5665 | return -EINVAL; | 5713 | return -EINVAL; |
5666 | 5714 | ||
5667 | /* only important for AP, IBSS and mesh create IEs internally */ | 5715 | /* only important for AP, IBSS and mesh create IEs internally */ |
5668 | if (need_new_beacon && | 5716 | if (need_new_beacon && !info->attrs[NL80211_ATTR_CSA_IES]) |
5669 | (!info->attrs[NL80211_ATTR_CSA_IES] || | ||
5670 | !info->attrs[NL80211_ATTR_CSA_C_OFF_BEACON])) | ||
5671 | return -EINVAL; | 5717 | return -EINVAL; |
5672 | 5718 | ||
5673 | params.count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]); | 5719 | params.count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]); |
@@ -5722,9 +5768,9 @@ skip_beacons: | |||
5722 | if (!cfg80211_reg_can_beacon(&rdev->wiphy, ¶ms.chandef)) | 5768 | if (!cfg80211_reg_can_beacon(&rdev->wiphy, ¶ms.chandef)) |
5723 | return -EINVAL; | 5769 | return -EINVAL; |
5724 | 5770 | ||
5725 | /* DFS channels are only supported for AP/P2P GO ... for now. */ | ||
5726 | if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP || | 5771 | if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP || |
5727 | dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) { | 5772 | dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO || |
5773 | dev->ieee80211_ptr->iftype == NL80211_IFTYPE_ADHOC) { | ||
5728 | err = cfg80211_chandef_dfs_required(wdev->wiphy, | 5774 | err = cfg80211_chandef_dfs_required(wdev->wiphy, |
5729 | ¶ms.chandef); | 5775 | ¶ms.chandef); |
5730 | if (err < 0) { | 5776 | if (err < 0) { |
@@ -6556,6 +6602,9 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) | |||
6556 | ibss.control_port = | 6602 | ibss.control_port = |
6557 | nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT]); | 6603 | nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT]); |
6558 | 6604 | ||
6605 | ibss.userspace_handles_dfs = | ||
6606 | nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS]); | ||
6607 | |||
6559 | err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys); | 6608 | err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys); |
6560 | if (err) | 6609 | if (err) |
6561 | kfree(connkeys); | 6610 | kfree(connkeys); |
@@ -10762,7 +10811,8 @@ void cfg80211_ch_switch_notify(struct net_device *dev, | |||
10762 | 10811 | ||
10763 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && | 10812 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && |
10764 | wdev->iftype != NL80211_IFTYPE_P2P_GO && | 10813 | wdev->iftype != NL80211_IFTYPE_P2P_GO && |
10765 | wdev->iftype != NL80211_IFTYPE_ADHOC)) | 10814 | wdev->iftype != NL80211_IFTYPE_ADHOC && |
10815 | wdev->iftype != NL80211_IFTYPE_MESH_POINT)) | ||
10766 | goto out; | 10816 | goto out; |
10767 | 10817 | ||
10768 | wdev->channel = chandef->chan; | 10818 | wdev->channel = chandef->chan; |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index a0ec143ba3dc..7da67fd0b418 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -787,7 +787,6 @@ const char *reg_initiator_name(enum nl80211_reg_initiator initiator) | |||
787 | EXPORT_SYMBOL(reg_initiator_name); | 787 | EXPORT_SYMBOL(reg_initiator_name); |
788 | 788 | ||
789 | #ifdef CONFIG_CFG80211_REG_DEBUG | 789 | #ifdef CONFIG_CFG80211_REG_DEBUG |
790 | |||
791 | static void chan_reg_rule_print_dbg(struct ieee80211_channel *chan, | 790 | static void chan_reg_rule_print_dbg(struct ieee80211_channel *chan, |
792 | const struct ieee80211_reg_rule *reg_rule) | 791 | const struct ieee80211_reg_rule *reg_rule) |
793 | { | 792 | { |
@@ -974,6 +973,13 @@ static bool reg_dev_ignore_cell_hint(struct wiphy *wiphy) | |||
974 | } | 973 | } |
975 | #endif | 974 | #endif |
976 | 975 | ||
976 | static bool wiphy_strict_alpha2_regd(struct wiphy *wiphy) | ||
977 | { | ||
978 | if (wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY && | ||
979 | !(wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY)) | ||
980 | return true; | ||
981 | return false; | ||
982 | } | ||
977 | 983 | ||
978 | static bool ignore_reg_update(struct wiphy *wiphy, | 984 | static bool ignore_reg_update(struct wiphy *wiphy, |
979 | enum nl80211_reg_initiator initiator) | 985 | enum nl80211_reg_initiator initiator) |
@@ -1000,7 +1006,7 @@ static bool ignore_reg_update(struct wiphy *wiphy, | |||
1000 | * wiphy->regd will be set once the device has its own | 1006 | * wiphy->regd will be set once the device has its own |
1001 | * desired regulatory domain set | 1007 | * desired regulatory domain set |
1002 | */ | 1008 | */ |
1003 | if (wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY && !wiphy->regd && | 1009 | if (wiphy_strict_alpha2_regd(wiphy) && !wiphy->regd && |
1004 | initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && | 1010 | initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && |
1005 | !is_world_regdom(lr->alpha2)) { | 1011 | !is_world_regdom(lr->alpha2)) { |
1006 | REG_DBG_PRINT("Ignoring regulatory request set by %s " | 1012 | REG_DBG_PRINT("Ignoring regulatory request set by %s " |
@@ -1706,8 +1712,8 @@ int regulatory_hint(struct wiphy *wiphy, const char *alpha2) | |||
1706 | } | 1712 | } |
1707 | EXPORT_SYMBOL(regulatory_hint); | 1713 | EXPORT_SYMBOL(regulatory_hint); |
1708 | 1714 | ||
1709 | void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band, | 1715 | void regulatory_hint_country_ie(struct wiphy *wiphy, enum ieee80211_band band, |
1710 | const u8 *country_ie, u8 country_ie_len) | 1716 | const u8 *country_ie, u8 country_ie_len) |
1711 | { | 1717 | { |
1712 | char alpha2[2]; | 1718 | char alpha2[2]; |
1713 | enum environment_cap env = ENVIRON_ANY; | 1719 | enum environment_cap env = ENVIRON_ANY; |
diff --git a/net/wireless/reg.h b/net/wireless/reg.h index af2d5f8a5d82..9677e3c13da9 100644 --- a/net/wireless/reg.h +++ b/net/wireless/reg.h | |||
@@ -58,7 +58,7 @@ int regulatory_hint_found_beacon(struct wiphy *wiphy, | |||
58 | gfp_t gfp); | 58 | gfp_t gfp); |
59 | 59 | ||
60 | /** | 60 | /** |
61 | * regulatory_hint_11d - hints a country IE as a regulatory domain | 61 | * regulatory_hint_country_ie - hints a country IE as a regulatory domain |
62 | * @wiphy: the wireless device giving the hint (used only for reporting | 62 | * @wiphy: the wireless device giving the hint (used only for reporting |
63 | * conflicts) | 63 | * conflicts) |
64 | * @band: the band on which the country IE was received on. This determines | 64 | * @band: the band on which the country IE was received on. This determines |
@@ -78,7 +78,7 @@ int regulatory_hint_found_beacon(struct wiphy *wiphy, | |||
78 | * not observed. For this reason if a triplet is seen with channel | 78 | * not observed. For this reason if a triplet is seen with channel |
79 | * information for a band the BSS is not present in it will be ignored. | 79 | * information for a band the BSS is not present in it will be ignored. |
80 | */ | 80 | */ |
81 | void regulatory_hint_11d(struct wiphy *wiphy, | 81 | void regulatory_hint_country_ie(struct wiphy *wiphy, |
82 | enum ieee80211_band band, | 82 | enum ieee80211_band band, |
83 | const u8 *country_ie, | 83 | const u8 *country_ie, |
84 | u8 country_ie_len); | 84 | u8 country_ie_len); |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index eeb71480f1af..d4397eba5408 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
@@ -254,10 +254,10 @@ void __cfg80211_sched_scan_results(struct work_struct *wk) | |||
254 | rdev = container_of(wk, struct cfg80211_registered_device, | 254 | rdev = container_of(wk, struct cfg80211_registered_device, |
255 | sched_scan_results_wk); | 255 | sched_scan_results_wk); |
256 | 256 | ||
257 | request = rdev->sched_scan_req; | ||
258 | |||
259 | rtnl_lock(); | 257 | rtnl_lock(); |
260 | 258 | ||
259 | request = rdev->sched_scan_req; | ||
260 | |||
261 | /* we don't have sched_scan_req anymore if the scan is stopping */ | 261 | /* we don't have sched_scan_req anymore if the scan is stopping */ |
262 | if (request) { | 262 | if (request) { |
263 | if (request->flags & NL80211_SCAN_FLAG_FLUSH) { | 263 | if (request->flags & NL80211_SCAN_FLAG_FLUSH) { |
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 20e86a95dc4e..65f800890d70 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
@@ -682,8 +682,8 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
682 | * - country_ie + 2, the start of the country ie data, and | 682 | * - country_ie + 2, the start of the country ie data, and |
683 | * - and country_ie[1] which is the IE length | 683 | * - and country_ie[1] which is the IE length |
684 | */ | 684 | */ |
685 | regulatory_hint_11d(wdev->wiphy, bss->channel->band, | 685 | regulatory_hint_country_ie(wdev->wiphy, bss->channel->band, |
686 | country_ie + 2, country_ie[1]); | 686 | country_ie + 2, country_ie[1]); |
687 | kfree(country_ie); | 687 | kfree(country_ie); |
688 | } | 688 | } |
689 | 689 | ||
diff --git a/net/wireless/util.c b/net/wireless/util.c index 3c8be6104ba4..935dea9485da 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -1249,7 +1249,7 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, | |||
1249 | enum cfg80211_chan_mode chmode; | 1249 | enum cfg80211_chan_mode chmode; |
1250 | int num_different_channels = 0; | 1250 | int num_different_channels = 0; |
1251 | int total = 1; | 1251 | int total = 1; |
1252 | bool radar_required; | 1252 | bool radar_required = false; |
1253 | int i, j; | 1253 | int i, j; |
1254 | 1254 | ||
1255 | ASSERT_RTNL(); | 1255 | ASSERT_RTNL(); |
@@ -1264,14 +1264,20 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, | |||
1264 | case NL80211_IFTYPE_MESH_POINT: | 1264 | case NL80211_IFTYPE_MESH_POINT: |
1265 | case NL80211_IFTYPE_P2P_GO: | 1265 | case NL80211_IFTYPE_P2P_GO: |
1266 | case NL80211_IFTYPE_WDS: | 1266 | case NL80211_IFTYPE_WDS: |
1267 | radar_required = !!(chan && | 1267 | /* if the interface could potentially choose a DFS channel, |
1268 | (chan->flags & IEEE80211_CHAN_RADAR)); | 1268 | * then mark DFS as required. |
1269 | */ | ||
1270 | if (!chan) { | ||
1271 | if (chanmode != CHAN_MODE_UNDEFINED && radar_detect) | ||
1272 | radar_required = true; | ||
1273 | break; | ||
1274 | } | ||
1275 | radar_required = !!(chan->flags & IEEE80211_CHAN_RADAR); | ||
1269 | break; | 1276 | break; |
1270 | case NL80211_IFTYPE_P2P_CLIENT: | 1277 | case NL80211_IFTYPE_P2P_CLIENT: |
1271 | case NL80211_IFTYPE_STATION: | 1278 | case NL80211_IFTYPE_STATION: |
1272 | case NL80211_IFTYPE_P2P_DEVICE: | 1279 | case NL80211_IFTYPE_P2P_DEVICE: |
1273 | case NL80211_IFTYPE_MONITOR: | 1280 | case NL80211_IFTYPE_MONITOR: |
1274 | radar_required = false; | ||
1275 | break; | 1281 | break; |
1276 | case NUM_NL80211_IFTYPES: | 1282 | case NUM_NL80211_IFTYPES: |
1277 | case NL80211_IFTYPE_UNSPECIFIED: | 1283 | case NL80211_IFTYPE_UNSPECIFIED: |