diff options
Diffstat (limited to 'net')
35 files changed, 899 insertions, 492 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 6a77d4c910f9..677d65929780 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -336,6 +336,20 @@ static void rate_idx_to_bitrate(struct rate_info *rate, struct sta_info *sta, in | |||
336 | rate->mcs = idx; | 336 | rate->mcs = idx; |
337 | } | 337 | } |
338 | 338 | ||
339 | void sta_set_rate_info_tx(struct sta_info *sta, | ||
340 | const struct ieee80211_tx_rate *rate, | ||
341 | struct rate_info *rinfo) | ||
342 | { | ||
343 | rinfo->flags = 0; | ||
344 | if (rate->flags & IEEE80211_TX_RC_MCS) | ||
345 | rinfo->flags |= RATE_INFO_FLAGS_MCS; | ||
346 | if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) | ||
347 | rinfo->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | ||
348 | if (rate->flags & IEEE80211_TX_RC_SHORT_GI) | ||
349 | rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI; | ||
350 | rate_idx_to_bitrate(rinfo, sta, rate->idx); | ||
351 | } | ||
352 | |||
339 | static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | 353 | static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) |
340 | { | 354 | { |
341 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 355 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
@@ -378,14 +392,7 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
378 | sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal); | 392 | sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal); |
379 | } | 393 | } |
380 | 394 | ||
381 | sinfo->txrate.flags = 0; | 395 | sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate); |
382 | if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS) | ||
383 | sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; | ||
384 | if (sta->last_tx_rate.flags & IEEE80211_TX_RC_40_MHZ_WIDTH) | ||
385 | sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | ||
386 | if (sta->last_tx_rate.flags & IEEE80211_TX_RC_SHORT_GI) | ||
387 | sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; | ||
388 | rate_idx_to_bitrate(&sinfo->txrate, sta, sta->last_tx_rate.idx); | ||
389 | 396 | ||
390 | sinfo->rxrate.flags = 0; | 397 | sinfo->rxrate.flags = 0; |
391 | if (sta->last_rx_rate_flag & RX_FLAG_HT) | 398 | if (sta->last_rx_rate_flag & RX_FLAG_HT) |
@@ -1314,6 +1321,14 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy, | |||
1314 | } | 1321 | } |
1315 | if (_chg_mesh_attr(NL80211_MESHCONF_FORWARDING, mask)) | 1322 | if (_chg_mesh_attr(NL80211_MESHCONF_FORWARDING, mask)) |
1316 | conf->dot11MeshForwarding = nconf->dot11MeshForwarding; | 1323 | conf->dot11MeshForwarding = nconf->dot11MeshForwarding; |
1324 | if (_chg_mesh_attr(NL80211_MESHCONF_RSSI_THRESHOLD, mask)) { | ||
1325 | /* our RSSI threshold implementation is supported only for | ||
1326 | * devices that report signal in dBm. | ||
1327 | */ | ||
1328 | if (!(sdata->local->hw.flags & IEEE80211_HW_SIGNAL_DBM)) | ||
1329 | return -ENOTSUPP; | ||
1330 | conf->rssi_threshold = nconf->rssi_threshold; | ||
1331 | } | ||
1317 | return 0; | 1332 | return 0; |
1318 | } | 1333 | } |
1319 | 1334 | ||
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 510ed1dab3c7..f6de8a65f402 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -443,6 +443,7 @@ IEEE80211_IF_FILE(dot11MeshGateAnnouncementProtocol, | |||
443 | IEEE80211_IF_FILE(dot11MeshHWMPRannInterval, | 443 | IEEE80211_IF_FILE(dot11MeshHWMPRannInterval, |
444 | u.mesh.mshcfg.dot11MeshHWMPRannInterval, DEC); | 444 | u.mesh.mshcfg.dot11MeshHWMPRannInterval, DEC); |
445 | IEEE80211_IF_FILE(dot11MeshForwarding, u.mesh.mshcfg.dot11MeshForwarding, DEC); | 445 | IEEE80211_IF_FILE(dot11MeshForwarding, u.mesh.mshcfg.dot11MeshForwarding, DEC); |
446 | IEEE80211_IF_FILE(rssi_threshold, u.mesh.mshcfg.rssi_threshold, DEC); | ||
446 | #endif | 447 | #endif |
447 | 448 | ||
448 | 449 | ||
@@ -537,11 +538,15 @@ static void add_monitor_files(struct ieee80211_sub_if_data *sdata) | |||
537 | 538 | ||
538 | #ifdef CONFIG_MAC80211_MESH | 539 | #ifdef CONFIG_MAC80211_MESH |
539 | 540 | ||
541 | static void add_mesh_files(struct ieee80211_sub_if_data *sdata) | ||
542 | { | ||
543 | DEBUGFS_ADD_MODE(tsf, 0600); | ||
544 | } | ||
545 | |||
540 | static void add_mesh_stats(struct ieee80211_sub_if_data *sdata) | 546 | static void add_mesh_stats(struct ieee80211_sub_if_data *sdata) |
541 | { | 547 | { |
542 | struct dentry *dir = debugfs_create_dir("mesh_stats", | 548 | struct dentry *dir = debugfs_create_dir("mesh_stats", |
543 | sdata->debugfs.dir); | 549 | sdata->debugfs.dir); |
544 | |||
545 | #define MESHSTATS_ADD(name)\ | 550 | #define MESHSTATS_ADD(name)\ |
546 | debugfs_create_file(#name, 0400, dir, sdata, &name##_ops); | 551 | debugfs_create_file(#name, 0400, dir, sdata, &name##_ops); |
547 | 552 | ||
@@ -581,6 +586,7 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata) | |||
581 | MESHPARAMS_ADD(dot11MeshHWMPRootMode); | 586 | MESHPARAMS_ADD(dot11MeshHWMPRootMode); |
582 | MESHPARAMS_ADD(dot11MeshHWMPRannInterval); | 587 | MESHPARAMS_ADD(dot11MeshHWMPRannInterval); |
583 | MESHPARAMS_ADD(dot11MeshGateAnnouncementProtocol); | 588 | MESHPARAMS_ADD(dot11MeshGateAnnouncementProtocol); |
589 | MESHPARAMS_ADD(rssi_threshold); | ||
584 | #undef MESHPARAMS_ADD | 590 | #undef MESHPARAMS_ADD |
585 | } | 591 | } |
586 | #endif | 592 | #endif |
@@ -593,6 +599,7 @@ static void add_files(struct ieee80211_sub_if_data *sdata) | |||
593 | switch (sdata->vif.type) { | 599 | switch (sdata->vif.type) { |
594 | case NL80211_IFTYPE_MESH_POINT: | 600 | case NL80211_IFTYPE_MESH_POINT: |
595 | #ifdef CONFIG_MAC80211_MESH | 601 | #ifdef CONFIG_MAC80211_MESH |
602 | add_mesh_files(sdata); | ||
596 | add_mesh_stats(sdata); | 603 | add_mesh_stats(sdata); |
597 | add_mesh_config(sdata); | 604 | add_mesh_config(sdata); |
598 | #endif | 605 | #endif |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 7f9ac577600a..33fd8d9f714e 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -66,7 +66,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
66 | skb_reset_tail_pointer(skb); | 66 | skb_reset_tail_pointer(skb); |
67 | skb_reserve(skb, sdata->local->hw.extra_tx_headroom); | 67 | skb_reserve(skb, sdata->local->hw.extra_tx_headroom); |
68 | 68 | ||
69 | if (memcmp(ifibss->bssid, bssid, ETH_ALEN)) | 69 | if (compare_ether_addr(ifibss->bssid, bssid)) |
70 | sta_info_flush(sdata->local, sdata); | 70 | sta_info_flush(sdata->local, sdata); |
71 | 71 | ||
72 | /* if merging, indicate to driver that we leave the old IBSS */ | 72 | /* if merging, indicate to driver that we leave the old IBSS */ |
@@ -403,7 +403,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
403 | return; | 403 | return; |
404 | 404 | ||
405 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && | 405 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && |
406 | memcmp(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN) == 0) { | 406 | compare_ether_addr(mgmt->bssid, sdata->u.ibss.bssid) == 0) { |
407 | 407 | ||
408 | rcu_read_lock(); | 408 | rcu_read_lock(); |
409 | sta = sta_info_get(sdata, mgmt->sa); | 409 | sta = sta_info_get(sdata, mgmt->sa); |
@@ -508,7 +508,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
508 | goto put_bss; | 508 | goto put_bss; |
509 | 509 | ||
510 | /* same BSSID */ | 510 | /* same BSSID */ |
511 | if (memcmp(cbss->bssid, sdata->u.ibss.bssid, ETH_ALEN) == 0) | 511 | if (compare_ether_addr(cbss->bssid, sdata->u.ibss.bssid) == 0) |
512 | goto put_bss; | 512 | goto put_bss; |
513 | 513 | ||
514 | if (rx_status->flag & RX_FLAG_MACTIME_MPDU) { | 514 | if (rx_status->flag & RX_FLAG_MACTIME_MPDU) { |
@@ -831,8 +831,8 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, | |||
831 | if (!tx_last_beacon && is_multicast_ether_addr(mgmt->da)) | 831 | if (!tx_last_beacon && is_multicast_ether_addr(mgmt->da)) |
832 | return; | 832 | return; |
833 | 833 | ||
834 | if (memcmp(mgmt->bssid, ifibss->bssid, ETH_ALEN) != 0 && | 834 | if (compare_ether_addr(mgmt->bssid, ifibss->bssid) != 0 && |
835 | memcmp(mgmt->bssid, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) != 0) | 835 | !is_broadcast_ether_addr(mgmt->bssid)) |
836 | return; | 836 | return; |
837 | 837 | ||
838 | end = ((u8 *) mgmt) + len; | 838 | end = ((u8 *) mgmt) + len; |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index cee0c7493fd0..796b13bfc953 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -105,6 +105,44 @@ struct ieee80211_bss { | |||
105 | */ | 105 | */ |
106 | bool has_erp_value; | 106 | bool has_erp_value; |
107 | u8 erp_value; | 107 | u8 erp_value; |
108 | |||
109 | /* Keep track of the corruption of the last beacon/probe response. */ | ||
110 | u8 corrupt_data; | ||
111 | |||
112 | /* Keep track of what bits of information we have valid info for. */ | ||
113 | u8 valid_data; | ||
114 | }; | ||
115 | |||
116 | /** | ||
117 | * enum ieee80211_corrupt_data_flags - BSS data corruption flags | ||
118 | * @IEEE80211_BSS_CORRUPT_BEACON: last beacon frame received was corrupted | ||
119 | * @IEEE80211_BSS_CORRUPT_PROBE_RESP: last probe response received was corrupted | ||
120 | * | ||
121 | * These are bss flags that are attached to a bss in the | ||
122 | * @corrupt_data field of &struct ieee80211_bss. | ||
123 | */ | ||
124 | enum ieee80211_bss_corrupt_data_flags { | ||
125 | IEEE80211_BSS_CORRUPT_BEACON = BIT(0), | ||
126 | IEEE80211_BSS_CORRUPT_PROBE_RESP = BIT(1) | ||
127 | }; | ||
128 | |||
129 | /** | ||
130 | * enum ieee80211_valid_data_flags - BSS valid data flags | ||
131 | * @IEEE80211_BSS_VALID_DTIM: DTIM data was gathered from non-corrupt IE | ||
132 | * @IEEE80211_BSS_VALID_WMM: WMM/UAPSD data was gathered from non-corrupt IE | ||
133 | * @IEEE80211_BSS_VALID_RATES: Supported rates were gathered from non-corrupt IE | ||
134 | * @IEEE80211_BSS_VALID_ERP: ERP flag was gathered from non-corrupt IE | ||
135 | * | ||
136 | * These are bss flags that are attached to a bss in the | ||
137 | * @valid_data field of &struct ieee80211_bss. They show which parts | ||
138 | * of the data structure were recieved as a result of an un-corrupted | ||
139 | * beacon/probe response. | ||
140 | */ | ||
141 | enum ieee80211_bss_valid_data_flags { | ||
142 | IEEE80211_BSS_VALID_DTIM = BIT(0), | ||
143 | IEEE80211_BSS_VALID_WMM = BIT(1), | ||
144 | IEEE80211_BSS_VALID_RATES = BIT(2), | ||
145 | IEEE80211_BSS_VALID_ERP = BIT(3) | ||
108 | }; | 146 | }; |
109 | 147 | ||
110 | static inline u8 *bss_mesh_cfg(struct ieee80211_bss *bss) | 148 | static inline u8 *bss_mesh_cfg(struct ieee80211_bss *bss) |
@@ -480,7 +518,7 @@ struct ieee80211_if_ibss { | |||
480 | 518 | ||
481 | bool control_port; | 519 | bool control_port; |
482 | 520 | ||
483 | u8 bssid[ETH_ALEN]; | 521 | u8 bssid[ETH_ALEN] __aligned(2); |
484 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | 522 | u8 ssid[IEEE80211_MAX_SSID_LEN]; |
485 | u8 ssid_len, ie_len; | 523 | u8 ssid_len, ie_len; |
486 | u8 *ie; | 524 | u8 *ie; |
@@ -1120,6 +1158,9 @@ struct ieee802_11_elems { | |||
1120 | u8 quiet_elem_len; | 1158 | u8 quiet_elem_len; |
1121 | u8 num_of_quiet_elem; /* can be more the one */ | 1159 | u8 num_of_quiet_elem; /* can be more the one */ |
1122 | u8 timeout_int_len; | 1160 | u8 timeout_int_len; |
1161 | |||
1162 | /* whether a parse error occurred while retrieving these elements */ | ||
1163 | bool parse_error; | ||
1123 | }; | 1164 | }; |
1124 | 1165 | ||
1125 | static inline struct ieee80211_local *hw_to_local( | 1166 | static inline struct ieee80211_local *hw_to_local( |
@@ -1348,7 +1389,8 @@ int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, | |||
1348 | void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx, | 1389 | void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx, |
1349 | struct ieee80211_hdr *hdr, const u8 *tsc, | 1390 | struct ieee80211_hdr *hdr, const u8 *tsc, |
1350 | gfp_t gfp); | 1391 | gfp_t gfp); |
1351 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata); | 1392 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, |
1393 | bool bss_notify); | ||
1352 | void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); | 1394 | void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); |
1353 | 1395 | ||
1354 | void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata, | 1396 | void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 620ca8d2ad42..401c01f0731e 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -304,7 +304,7 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
304 | * need to initialise the hardware if the hardware | 304 | * need to initialise the hardware if the hardware |
305 | * doesn't start up with sane defaults | 305 | * doesn't start up with sane defaults |
306 | */ | 306 | */ |
307 | ieee80211_set_wmm_default(sdata); | 307 | ieee80211_set_wmm_default(sdata, true); |
308 | } | 308 | } |
309 | 309 | ||
310 | set_bit(SDATA_STATE_RUNNING, &sdata->state); | 310 | set_bit(SDATA_STATE_RUNNING, &sdata->state); |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index c707c8bf6d2c..e5fbb7cf3562 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -204,7 +204,7 @@ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, | |||
204 | kmem_cache_free(rm_cache, p); | 204 | kmem_cache_free(rm_cache, p); |
205 | --entries; | 205 | --entries; |
206 | } else if ((seqnum == p->seqnum) && | 206 | } else if ((seqnum == p->seqnum) && |
207 | (memcmp(sa, p->sa, ETH_ALEN) == 0)) | 207 | (compare_ether_addr(sa, p->sa) == 0)) |
208 | return -1; | 208 | return -1; |
209 | } | 209 | } |
210 | 210 | ||
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index c7e5c49471e5..8d53b71378e3 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -85,6 +85,8 @@ enum mesh_deferred_task_flags { | |||
85 | * @state_lock: mesh path state lock used to protect changes to the | 85 | * @state_lock: mesh path state lock used to protect changes to the |
86 | * mpath itself. No need to take this lock when adding or removing | 86 | * mpath itself. No need to take this lock when adding or removing |
87 | * an mpath to a hash bucket on a path table. | 87 | * an mpath to a hash bucket on a path table. |
88 | * @rann_snd_addr: the RANN sender address | ||
89 | * @is_root: the destination station of this path is a root node | ||
88 | * @is_gate: the destination station of this path is a mesh gate | 90 | * @is_gate: the destination station of this path is a mesh gate |
89 | * | 91 | * |
90 | * | 92 | * |
@@ -109,6 +111,8 @@ struct mesh_path { | |||
109 | u8 discovery_retries; | 111 | u8 discovery_retries; |
110 | enum mesh_path_flags flags; | 112 | enum mesh_path_flags flags; |
111 | spinlock_t state_lock; | 113 | spinlock_t state_lock; |
114 | u8 rann_snd_addr[ETH_ALEN]; | ||
115 | bool is_root; | ||
112 | bool is_gate; | 116 | bool is_gate; |
113 | }; | 117 | }; |
114 | 118 | ||
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 31bc762f209d..1c6f3d02aebf 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -8,6 +8,7 @@ | |||
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
11 | #include <linux/etherdevice.h> | ||
11 | #include <asm/unaligned.h> | 12 | #include <asm/unaligned.h> |
12 | #include "wme.h" | 13 | #include "wme.h" |
13 | #include "mesh.h" | 14 | #include "mesh.h" |
@@ -323,6 +324,7 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local, | |||
323 | struct sta_info *sta) | 324 | struct sta_info *sta) |
324 | { | 325 | { |
325 | struct ieee80211_supported_band *sband; | 326 | struct ieee80211_supported_band *sband; |
327 | struct rate_info rinfo; | ||
326 | /* This should be adjusted for each device */ | 328 | /* This should be adjusted for each device */ |
327 | int device_constant = 1 << ARITH_SHIFT; | 329 | int device_constant = 1 << ARITH_SHIFT; |
328 | int test_frame_len = TEST_FRAME_LEN << ARITH_SHIFT; | 330 | int test_frame_len = TEST_FRAME_LEN << ARITH_SHIFT; |
@@ -336,7 +338,9 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local, | |||
336 | if (sta->fail_avg >= 100) | 338 | if (sta->fail_avg >= 100) |
337 | return MAX_METRIC; | 339 | return MAX_METRIC; |
338 | 340 | ||
339 | if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS) | 341 | sta_set_rate_info_tx(sta, &sta->last_tx_rate, &rinfo); |
342 | rate = cfg80211_calculate_bitrate(&rinfo); | ||
343 | if (WARN_ON(!rate)) | ||
340 | return MAX_METRIC; | 344 | return MAX_METRIC; |
341 | 345 | ||
342 | err = (sta->fail_avg << ARITH_SHIFT) / 100; | 346 | err = (sta->fail_avg << ARITH_SHIFT) / 100; |
@@ -344,7 +348,6 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local, | |||
344 | /* bitrate is in units of 100 Kbps, while we need rate in units of | 348 | /* bitrate is in units of 100 Kbps, while we need rate in units of |
345 | * 1Mbps. This will be corrected on tx_time computation. | 349 | * 1Mbps. This will be corrected on tx_time computation. |
346 | */ | 350 | */ |
347 | rate = sband->bitrates[sta->last_tx_rate.idx].bitrate; | ||
348 | tx_time = (device_constant + 10 * test_frame_len / rate); | 351 | tx_time = (device_constant + 10 * test_frame_len / rate); |
349 | estimated_retx = ((1 << (2 * ARITH_SHIFT)) / (s_unit - err)); | 352 | estimated_retx = ((1 << (2 * ARITH_SHIFT)) / (s_unit - err)); |
350 | result = (tx_time * estimated_retx) >> (2 * ARITH_SHIFT) ; | 353 | result = (tx_time * estimated_retx) >> (2 * ARITH_SHIFT) ; |
@@ -419,7 +422,7 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, | |||
419 | new_metric = MAX_METRIC; | 422 | new_metric = MAX_METRIC; |
420 | exp_time = TU_TO_EXP_TIME(orig_lifetime); | 423 | exp_time = TU_TO_EXP_TIME(orig_lifetime); |
421 | 424 | ||
422 | if (memcmp(orig_addr, sdata->vif.addr, ETH_ALEN) == 0) { | 425 | if (compare_ether_addr(orig_addr, sdata->vif.addr) == 0) { |
423 | /* This MP is the originator, we are not interested in this | 426 | /* This MP is the originator, we are not interested in this |
424 | * frame, except for updating transmitter's path info. | 427 | * frame, except for updating transmitter's path info. |
425 | */ | 428 | */ |
@@ -469,7 +472,7 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, | |||
469 | 472 | ||
470 | /* Update and check transmitter routing info */ | 473 | /* Update and check transmitter routing info */ |
471 | ta = mgmt->sa; | 474 | ta = mgmt->sa; |
472 | if (memcmp(orig_addr, ta, ETH_ALEN) == 0) | 475 | if (compare_ether_addr(orig_addr, ta) == 0) |
473 | fresh_info = false; | 476 | fresh_info = false; |
474 | else { | 477 | else { |
475 | fresh_info = true; | 478 | fresh_info = true; |
@@ -513,8 +516,9 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, | |||
513 | u8 *preq_elem, u32 metric) | 516 | u8 *preq_elem, u32 metric) |
514 | { | 517 | { |
515 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 518 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
516 | struct mesh_path *mpath; | 519 | struct mesh_path *mpath = NULL; |
517 | u8 *target_addr, *orig_addr; | 520 | u8 *target_addr, *orig_addr; |
521 | const u8 *da; | ||
518 | u8 target_flags, ttl; | 522 | u8 target_flags, ttl; |
519 | u32 orig_sn, target_sn, lifetime; | 523 | u32 orig_sn, target_sn, lifetime; |
520 | bool reply = false; | 524 | bool reply = false; |
@@ -529,7 +533,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, | |||
529 | 533 | ||
530 | mhwmp_dbg("received PREQ from %pM", orig_addr); | 534 | mhwmp_dbg("received PREQ from %pM", orig_addr); |
531 | 535 | ||
532 | if (memcmp(target_addr, sdata->vif.addr, ETH_ALEN) == 0) { | 536 | if (compare_ether_addr(target_addr, sdata->vif.addr) == 0) { |
533 | mhwmp_dbg("PREQ is for us"); | 537 | mhwmp_dbg("PREQ is for us"); |
534 | forward = false; | 538 | forward = false; |
535 | reply = true; | 539 | reply = true; |
@@ -591,9 +595,11 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, | |||
591 | flags = PREQ_IE_FLAGS(preq_elem); | 595 | flags = PREQ_IE_FLAGS(preq_elem); |
592 | preq_id = PREQ_IE_PREQ_ID(preq_elem); | 596 | preq_id = PREQ_IE_PREQ_ID(preq_elem); |
593 | hopcount = PREQ_IE_HOPCOUNT(preq_elem) + 1; | 597 | hopcount = PREQ_IE_HOPCOUNT(preq_elem) + 1; |
598 | da = (mpath && mpath->is_root) ? | ||
599 | mpath->rann_snd_addr : broadcast_addr; | ||
594 | mesh_path_sel_frame_tx(MPATH_PREQ, flags, orig_addr, | 600 | mesh_path_sel_frame_tx(MPATH_PREQ, flags, orig_addr, |
595 | cpu_to_le32(orig_sn), target_flags, target_addr, | 601 | cpu_to_le32(orig_sn), target_flags, target_addr, |
596 | cpu_to_le32(target_sn), broadcast_addr, | 602 | cpu_to_le32(target_sn), da, |
597 | hopcount, ttl, cpu_to_le32(lifetime), | 603 | hopcount, ttl, cpu_to_le32(lifetime), |
598 | cpu_to_le32(metric), cpu_to_le32(preq_id), | 604 | cpu_to_le32(metric), cpu_to_le32(preq_id), |
599 | sdata); | 605 | sdata); |
@@ -615,6 +621,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, | |||
615 | struct ieee80211_mgmt *mgmt, | 621 | struct ieee80211_mgmt *mgmt, |
616 | u8 *prep_elem, u32 metric) | 622 | u8 *prep_elem, u32 metric) |
617 | { | 623 | { |
624 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
618 | struct mesh_path *mpath; | 625 | struct mesh_path *mpath; |
619 | u8 *target_addr, *orig_addr; | 626 | u8 *target_addr, *orig_addr; |
620 | u8 ttl, hopcount, flags; | 627 | u8 ttl, hopcount, flags; |
@@ -624,10 +631,13 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, | |||
624 | mhwmp_dbg("received PREP from %pM", PREP_IE_ORIG_ADDR(prep_elem)); | 631 | mhwmp_dbg("received PREP from %pM", PREP_IE_ORIG_ADDR(prep_elem)); |
625 | 632 | ||
626 | orig_addr = PREP_IE_ORIG_ADDR(prep_elem); | 633 | orig_addr = PREP_IE_ORIG_ADDR(prep_elem); |
627 | if (memcmp(orig_addr, sdata->vif.addr, ETH_ALEN) == 0) | 634 | if (compare_ether_addr(orig_addr, sdata->vif.addr) == 0) |
628 | /* destination, no forwarding required */ | 635 | /* destination, no forwarding required */ |
629 | return; | 636 | return; |
630 | 637 | ||
638 | if (!ifmsh->mshcfg.dot11MeshForwarding) | ||
639 | return; | ||
640 | |||
631 | ttl = PREP_IE_TTL(prep_elem); | 641 | ttl = PREP_IE_TTL(prep_elem); |
632 | if (ttl <= 1) { | 642 | if (ttl <= 1) { |
633 | sdata->u.mesh.mshstats.dropped_frames_ttl++; | 643 | sdata->u.mesh.mshstats.dropped_frames_ttl++; |
@@ -694,21 +704,26 @@ static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata, | |||
694 | rcu_read_lock(); | 704 | rcu_read_lock(); |
695 | mpath = mesh_path_lookup(target_addr, sdata); | 705 | mpath = mesh_path_lookup(target_addr, sdata); |
696 | if (mpath) { | 706 | if (mpath) { |
707 | struct sta_info *sta; | ||
708 | |||
697 | spin_lock_bh(&mpath->state_lock); | 709 | spin_lock_bh(&mpath->state_lock); |
710 | sta = next_hop_deref_protected(mpath); | ||
698 | if (mpath->flags & MESH_PATH_ACTIVE && | 711 | if (mpath->flags & MESH_PATH_ACTIVE && |
699 | memcmp(ta, next_hop_deref_protected(mpath)->sta.addr, | 712 | compare_ether_addr(ta, sta->sta.addr) == 0 && |
700 | ETH_ALEN) == 0 && | ||
701 | (!(mpath->flags & MESH_PATH_SN_VALID) || | 713 | (!(mpath->flags & MESH_PATH_SN_VALID) || |
702 | SN_GT(target_sn, mpath->sn))) { | 714 | SN_GT(target_sn, mpath->sn))) { |
703 | mpath->flags &= ~MESH_PATH_ACTIVE; | 715 | mpath->flags &= ~MESH_PATH_ACTIVE; |
704 | mpath->sn = target_sn; | 716 | mpath->sn = target_sn; |
705 | spin_unlock_bh(&mpath->state_lock); | 717 | spin_unlock_bh(&mpath->state_lock); |
718 | if (!ifmsh->mshcfg.dot11MeshForwarding) | ||
719 | goto endperr; | ||
706 | mesh_path_error_tx(ttl, target_addr, cpu_to_le32(target_sn), | 720 | mesh_path_error_tx(ttl, target_addr, cpu_to_le32(target_sn), |
707 | cpu_to_le16(target_rcode), | 721 | cpu_to_le16(target_rcode), |
708 | broadcast_addr, sdata); | 722 | broadcast_addr, sdata); |
709 | } else | 723 | } else |
710 | spin_unlock_bh(&mpath->state_lock); | 724 | spin_unlock_bh(&mpath->state_lock); |
711 | } | 725 | } |
726 | endperr: | ||
712 | rcu_read_unlock(); | 727 | rcu_read_unlock(); |
713 | } | 728 | } |
714 | 729 | ||
@@ -739,11 +754,11 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, | |||
739 | metric = rann->rann_metric; | 754 | metric = rann->rann_metric; |
740 | 755 | ||
741 | /* Ignore our own RANNs */ | 756 | /* Ignore our own RANNs */ |
742 | if (memcmp(orig_addr, sdata->vif.addr, ETH_ALEN) == 0) | 757 | if (compare_ether_addr(orig_addr, sdata->vif.addr) == 0) |
743 | return; | 758 | return; |
744 | 759 | ||
745 | mhwmp_dbg("received RANN from %pM (is_gate=%d)", orig_addr, | 760 | mhwmp_dbg("received RANN from %pM via neighbour %pM (is_gate=%d)", |
746 | root_is_gate); | 761 | orig_addr, mgmt->sa, root_is_gate); |
747 | 762 | ||
748 | rcu_read_lock(); | 763 | rcu_read_lock(); |
749 | mpath = mesh_path_lookup(orig_addr, sdata); | 764 | mpath = mesh_path_lookup(orig_addr, sdata); |
@@ -765,7 +780,7 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, | |||
765 | mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH); | 780 | mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH); |
766 | } | 781 | } |
767 | 782 | ||
768 | if (mpath->sn < orig_sn) { | 783 | if (mpath->sn < orig_sn && ifmsh->mshcfg.dot11MeshForwarding) { |
769 | mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr, | 784 | mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr, |
770 | cpu_to_le32(orig_sn), | 785 | cpu_to_le32(orig_sn), |
771 | 0, NULL, 0, broadcast_addr, | 786 | 0, NULL, 0, broadcast_addr, |
@@ -774,6 +789,11 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, | |||
774 | 0, sdata); | 789 | 0, sdata); |
775 | mpath->sn = orig_sn; | 790 | mpath->sn = orig_sn; |
776 | } | 791 | } |
792 | |||
793 | /* Using individually addressed PREQ for root node */ | ||
794 | memcpy(mpath->rann_snd_addr, mgmt->sa, ETH_ALEN); | ||
795 | mpath->is_root = true; | ||
796 | |||
777 | if (root_is_gate) | 797 | if (root_is_gate) |
778 | mesh_path_add_gate(mpath); | 798 | mesh_path_add_gate(mpath); |
779 | 799 | ||
@@ -909,6 +929,7 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata) | |||
909 | struct mesh_preq_queue *preq_node; | 929 | struct mesh_preq_queue *preq_node; |
910 | struct mesh_path *mpath; | 930 | struct mesh_path *mpath; |
911 | u8 ttl, target_flags; | 931 | u8 ttl, target_flags; |
932 | const u8 *da; | ||
912 | u32 lifetime; | 933 | u32 lifetime; |
913 | 934 | ||
914 | spin_lock_bh(&ifmsh->mesh_preq_queue_lock); | 935 | spin_lock_bh(&ifmsh->mesh_preq_queue_lock); |
@@ -971,9 +992,10 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata) | |||
971 | target_flags = MP_F_RF; | 992 | target_flags = MP_F_RF; |
972 | 993 | ||
973 | spin_unlock_bh(&mpath->state_lock); | 994 | spin_unlock_bh(&mpath->state_lock); |
995 | da = (mpath->is_root) ? mpath->rann_snd_addr : broadcast_addr; | ||
974 | mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->vif.addr, | 996 | mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->vif.addr, |
975 | cpu_to_le32(ifmsh->sn), target_flags, mpath->dst, | 997 | cpu_to_le32(ifmsh->sn), target_flags, mpath->dst, |
976 | cpu_to_le32(mpath->sn), broadcast_addr, 0, | 998 | cpu_to_le32(mpath->sn), da, 0, |
977 | ttl, cpu_to_le32(lifetime), 0, | 999 | ttl, cpu_to_le32(lifetime), 0, |
978 | cpu_to_le32(ifmsh->preq_id++), sdata); | 1000 | cpu_to_le32(ifmsh->preq_id++), sdata); |
979 | mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout); | 1001 | mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout); |
@@ -1064,7 +1086,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb, | |||
1064 | if (time_after(jiffies, | 1086 | if (time_after(jiffies, |
1065 | mpath->exp_time - | 1087 | mpath->exp_time - |
1066 | msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) && | 1088 | msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) && |
1067 | !memcmp(sdata->vif.addr, hdr->addr4, ETH_ALEN) && | 1089 | !compare_ether_addr(sdata->vif.addr, hdr->addr4) && |
1068 | !(mpath->flags & MESH_PATH_RESOLVING) && | 1090 | !(mpath->flags & MESH_PATH_RESOLVING) && |
1069 | !(mpath->flags & MESH_PATH_FIXED)) | 1091 | !(mpath->flags & MESH_PATH_FIXED)) |
1070 | mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH); | 1092 | mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH); |
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index dc51669e67d8..be1361b5f7ad 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c | |||
@@ -348,7 +348,7 @@ static struct mesh_path *mpath_lookup(struct mesh_table *tbl, u8 *dst, | |||
348 | hlist_for_each_entry_rcu(node, n, bucket, list) { | 348 | hlist_for_each_entry_rcu(node, n, bucket, list) { |
349 | mpath = node->mpath; | 349 | mpath = node->mpath; |
350 | if (mpath->sdata == sdata && | 350 | if (mpath->sdata == sdata && |
351 | memcmp(dst, mpath->dst, ETH_ALEN) == 0) { | 351 | compare_ether_addr(dst, mpath->dst) == 0) { |
352 | if (MPATH_EXPIRED(mpath)) { | 352 | if (MPATH_EXPIRED(mpath)) { |
353 | spin_lock_bh(&mpath->state_lock); | 353 | spin_lock_bh(&mpath->state_lock); |
354 | mpath->flags &= ~MESH_PATH_ACTIVE; | 354 | mpath->flags &= ~MESH_PATH_ACTIVE; |
@@ -523,7 +523,7 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata) | |||
523 | int err = 0; | 523 | int err = 0; |
524 | u32 hash_idx; | 524 | u32 hash_idx; |
525 | 525 | ||
526 | if (memcmp(dst, sdata->vif.addr, ETH_ALEN) == 0) | 526 | if (compare_ether_addr(dst, sdata->vif.addr) == 0) |
527 | /* never add ourselves as neighbours */ | 527 | /* never add ourselves as neighbours */ |
528 | return -ENOTSUPP; | 528 | return -ENOTSUPP; |
529 | 529 | ||
@@ -559,12 +559,13 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata) | |||
559 | hash_idx = mesh_table_hash(dst, sdata, tbl); | 559 | hash_idx = mesh_table_hash(dst, sdata, tbl); |
560 | bucket = &tbl->hash_buckets[hash_idx]; | 560 | bucket = &tbl->hash_buckets[hash_idx]; |
561 | 561 | ||
562 | spin_lock_bh(&tbl->hashwlock[hash_idx]); | 562 | spin_lock(&tbl->hashwlock[hash_idx]); |
563 | 563 | ||
564 | err = -EEXIST; | 564 | err = -EEXIST; |
565 | hlist_for_each_entry(node, n, bucket, list) { | 565 | hlist_for_each_entry(node, n, bucket, list) { |
566 | mpath = node->mpath; | 566 | mpath = node->mpath; |
567 | if (mpath->sdata == sdata && memcmp(dst, mpath->dst, ETH_ALEN) == 0) | 567 | if (mpath->sdata == sdata && |
568 | compare_ether_addr(dst, mpath->dst) == 0) | ||
568 | goto err_exists; | 569 | goto err_exists; |
569 | } | 570 | } |
570 | 571 | ||
@@ -575,7 +576,7 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata) | |||
575 | 576 | ||
576 | mesh_paths_generation++; | 577 | mesh_paths_generation++; |
577 | 578 | ||
578 | spin_unlock_bh(&tbl->hashwlock[hash_idx]); | 579 | spin_unlock(&tbl->hashwlock[hash_idx]); |
579 | read_unlock_bh(&pathtbl_resize_lock); | 580 | read_unlock_bh(&pathtbl_resize_lock); |
580 | if (grow) { | 581 | if (grow) { |
581 | set_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags); | 582 | set_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags); |
@@ -584,7 +585,7 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata) | |||
584 | return 0; | 585 | return 0; |
585 | 586 | ||
586 | err_exists: | 587 | err_exists: |
587 | spin_unlock_bh(&tbl->hashwlock[hash_idx]); | 588 | spin_unlock(&tbl->hashwlock[hash_idx]); |
588 | read_unlock_bh(&pathtbl_resize_lock); | 589 | read_unlock_bh(&pathtbl_resize_lock); |
589 | kfree(new_node); | 590 | kfree(new_node); |
590 | err_node_alloc: | 591 | err_node_alloc: |
@@ -655,7 +656,7 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata) | |||
655 | int err = 0; | 656 | int err = 0; |
656 | u32 hash_idx; | 657 | u32 hash_idx; |
657 | 658 | ||
658 | if (memcmp(dst, sdata->vif.addr, ETH_ALEN) == 0) | 659 | if (compare_ether_addr(dst, sdata->vif.addr) == 0) |
659 | /* never add ourselves as neighbours */ | 660 | /* never add ourselves as neighbours */ |
660 | return -ENOTSUPP; | 661 | return -ENOTSUPP; |
661 | 662 | ||
@@ -687,12 +688,13 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata) | |||
687 | hash_idx = mesh_table_hash(dst, sdata, tbl); | 688 | hash_idx = mesh_table_hash(dst, sdata, tbl); |
688 | bucket = &tbl->hash_buckets[hash_idx]; | 689 | bucket = &tbl->hash_buckets[hash_idx]; |
689 | 690 | ||
690 | spin_lock_bh(&tbl->hashwlock[hash_idx]); | 691 | spin_lock(&tbl->hashwlock[hash_idx]); |
691 | 692 | ||
692 | err = -EEXIST; | 693 | err = -EEXIST; |
693 | hlist_for_each_entry(node, n, bucket, list) { | 694 | hlist_for_each_entry(node, n, bucket, list) { |
694 | mpath = node->mpath; | 695 | mpath = node->mpath; |
695 | if (mpath->sdata == sdata && memcmp(dst, mpath->dst, ETH_ALEN) == 0) | 696 | if (mpath->sdata == sdata && |
697 | compare_ether_addr(dst, mpath->dst) == 0) | ||
696 | goto err_exists; | 698 | goto err_exists; |
697 | } | 699 | } |
698 | 700 | ||
@@ -701,7 +703,7 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata) | |||
701 | tbl->mean_chain_len * (tbl->hash_mask + 1)) | 703 | tbl->mean_chain_len * (tbl->hash_mask + 1)) |
702 | grow = 1; | 704 | grow = 1; |
703 | 705 | ||
704 | spin_unlock_bh(&tbl->hashwlock[hash_idx]); | 706 | spin_unlock(&tbl->hashwlock[hash_idx]); |
705 | read_unlock_bh(&pathtbl_resize_lock); | 707 | read_unlock_bh(&pathtbl_resize_lock); |
706 | if (grow) { | 708 | if (grow) { |
707 | set_bit(MESH_WORK_GROW_MPP_TABLE, &ifmsh->wrkq_flags); | 709 | set_bit(MESH_WORK_GROW_MPP_TABLE, &ifmsh->wrkq_flags); |
@@ -710,7 +712,7 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata) | |||
710 | return 0; | 712 | return 0; |
711 | 713 | ||
712 | err_exists: | 714 | err_exists: |
713 | spin_unlock_bh(&tbl->hashwlock[hash_idx]); | 715 | spin_unlock(&tbl->hashwlock[hash_idx]); |
714 | read_unlock_bh(&pathtbl_resize_lock); | 716 | read_unlock_bh(&pathtbl_resize_lock); |
715 | kfree(new_node); | 717 | kfree(new_node); |
716 | err_node_alloc: | 718 | err_node_alloc: |
@@ -809,9 +811,9 @@ void mesh_path_flush_by_nexthop(struct sta_info *sta) | |||
809 | for_each_mesh_entry(tbl, p, node, i) { | 811 | for_each_mesh_entry(tbl, p, node, i) { |
810 | mpath = node->mpath; | 812 | mpath = node->mpath; |
811 | if (rcu_dereference(mpath->next_hop) == sta) { | 813 | if (rcu_dereference(mpath->next_hop) == sta) { |
812 | spin_lock_bh(&tbl->hashwlock[i]); | 814 | spin_lock(&tbl->hashwlock[i]); |
813 | __mesh_path_del(tbl, node); | 815 | __mesh_path_del(tbl, node); |
814 | spin_unlock_bh(&tbl->hashwlock[i]); | 816 | spin_unlock(&tbl->hashwlock[i]); |
815 | } | 817 | } |
816 | } | 818 | } |
817 | read_unlock_bh(&pathtbl_resize_lock); | 819 | read_unlock_bh(&pathtbl_resize_lock); |
@@ -882,11 +884,11 @@ int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata) | |||
882 | hash_idx = mesh_table_hash(addr, sdata, tbl); | 884 | hash_idx = mesh_table_hash(addr, sdata, tbl); |
883 | bucket = &tbl->hash_buckets[hash_idx]; | 885 | bucket = &tbl->hash_buckets[hash_idx]; |
884 | 886 | ||
885 | spin_lock_bh(&tbl->hashwlock[hash_idx]); | 887 | spin_lock(&tbl->hashwlock[hash_idx]); |
886 | hlist_for_each_entry(node, n, bucket, list) { | 888 | hlist_for_each_entry(node, n, bucket, list) { |
887 | mpath = node->mpath; | 889 | mpath = node->mpath; |
888 | if (mpath->sdata == sdata && | 890 | if (mpath->sdata == sdata && |
889 | memcmp(addr, mpath->dst, ETH_ALEN) == 0) { | 891 | compare_ether_addr(addr, mpath->dst) == 0) { |
890 | __mesh_path_del(tbl, node); | 892 | __mesh_path_del(tbl, node); |
891 | goto enddel; | 893 | goto enddel; |
892 | } | 894 | } |
@@ -895,7 +897,7 @@ int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata) | |||
895 | err = -ENXIO; | 897 | err = -ENXIO; |
896 | enddel: | 898 | enddel: |
897 | mesh_paths_generation++; | 899 | mesh_paths_generation++; |
898 | spin_unlock_bh(&tbl->hashwlock[hash_idx]); | 900 | spin_unlock(&tbl->hashwlock[hash_idx]); |
899 | read_unlock_bh(&pathtbl_resize_lock); | 901 | read_unlock_bh(&pathtbl_resize_lock); |
900 | return err; | 902 | return err; |
901 | } | 903 | } |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 8806e5ef8ffe..4e53c4cbca9e 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -31,6 +31,12 @@ | |||
31 | #define dot11MeshHoldingTimeout(s) (s->u.mesh.mshcfg.dot11MeshHoldingTimeout) | 31 | #define dot11MeshHoldingTimeout(s) (s->u.mesh.mshcfg.dot11MeshHoldingTimeout) |
32 | #define dot11MeshMaxPeerLinks(s) (s->u.mesh.mshcfg.dot11MeshMaxPeerLinks) | 32 | #define dot11MeshMaxPeerLinks(s) (s->u.mesh.mshcfg.dot11MeshMaxPeerLinks) |
33 | 33 | ||
34 | /* We only need a valid sta if user configured a minimum rssi_threshold. */ | ||
35 | #define rssi_threshold_check(sta, sdata) \ | ||
36 | (sdata->u.mesh.mshcfg.rssi_threshold == 0 ||\ | ||
37 | (sta && (s8) -ewma_read(&sta->avg_signal) > \ | ||
38 | sdata->u.mesh.mshcfg.rssi_threshold)) | ||
39 | |||
34 | enum plink_event { | 40 | enum plink_event { |
35 | PLINK_UNDEFINED, | 41 | PLINK_UNDEFINED, |
36 | OPN_ACPT, | 42 | OPN_ACPT, |
@@ -301,7 +307,8 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates, | |||
301 | if (mesh_peer_accepts_plinks(elems) && | 307 | if (mesh_peer_accepts_plinks(elems) && |
302 | sta->plink_state == NL80211_PLINK_LISTEN && | 308 | sta->plink_state == NL80211_PLINK_LISTEN && |
303 | sdata->u.mesh.accepting_plinks && | 309 | sdata->u.mesh.accepting_plinks && |
304 | sdata->u.mesh.mshcfg.auto_open_plinks) | 310 | sdata->u.mesh.mshcfg.auto_open_plinks && |
311 | rssi_threshold_check(sta, sdata)) | ||
305 | mesh_plink_open(sta); | 312 | mesh_plink_open(sta); |
306 | 313 | ||
307 | rcu_read_unlock(); | 314 | rcu_read_unlock(); |
@@ -531,6 +538,14 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
531 | return; | 538 | return; |
532 | } | 539 | } |
533 | 540 | ||
541 | if (ftype == WLAN_SP_MESH_PEERING_OPEN && | ||
542 | !rssi_threshold_check(sta, sdata)) { | ||
543 | mpl_dbg("Mesh plink: %pM does not meet rssi threshold\n", | ||
544 | mgmt->sa); | ||
545 | rcu_read_unlock(); | ||
546 | return; | ||
547 | } | ||
548 | |||
534 | if (sta && !test_sta_flag(sta, WLAN_STA_AUTH)) { | 549 | if (sta && !test_sta_flag(sta, WLAN_STA_AUTH)) { |
535 | mpl_dbg("Mesh plink: Action frame from non-authed peer\n"); | 550 | mpl_dbg("Mesh plink: Action frame from non-authed peer\n"); |
536 | rcu_read_unlock(); | 551 | rcu_read_unlock(); |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index caf97f5a2937..c08924aeac00 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -1277,7 +1277,6 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
1277 | 1277 | ||
1278 | /* enable WMM or activate new settings */ | 1278 | /* enable WMM or activate new settings */ |
1279 | sdata->vif.bss_conf.qos = true; | 1279 | sdata->vif.bss_conf.qos = true; |
1280 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_QOS); | ||
1281 | } | 1280 | } |
1282 | 1281 | ||
1283 | static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, | 1282 | static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, |
@@ -1455,8 +1454,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1455 | changed |= BSS_CHANGED_ASSOC; | 1454 | changed |= BSS_CHANGED_ASSOC; |
1456 | sdata->vif.bss_conf.assoc = false; | 1455 | sdata->vif.bss_conf.assoc = false; |
1457 | 1456 | ||
1458 | ieee80211_set_wmm_default(sdata); | ||
1459 | |||
1460 | /* channel(_type) changes are handled by ieee80211_hw_config */ | 1457 | /* channel(_type) changes are handled by ieee80211_hw_config */ |
1461 | WARN_ON(!ieee80211_set_channel_type(local, sdata, NL80211_CHAN_NO_HT)); | 1458 | WARN_ON(!ieee80211_set_channel_type(local, sdata, NL80211_CHAN_NO_HT)); |
1462 | 1459 | ||
@@ -1484,10 +1481,16 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1484 | changed |= BSS_CHANGED_ARP_FILTER; | 1481 | changed |= BSS_CHANGED_ARP_FILTER; |
1485 | } | 1482 | } |
1486 | 1483 | ||
1484 | sdata->vif.bss_conf.qos = false; | ||
1485 | changed |= BSS_CHANGED_QOS; | ||
1486 | |||
1487 | /* The BSSID (not really interesting) and HT changed */ | 1487 | /* The BSSID (not really interesting) and HT changed */ |
1488 | changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT; | 1488 | changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT; |
1489 | ieee80211_bss_info_change_notify(sdata, changed); | 1489 | ieee80211_bss_info_change_notify(sdata, changed); |
1490 | 1490 | ||
1491 | /* disassociated - set to defaults now */ | ||
1492 | ieee80211_set_wmm_default(sdata, false); | ||
1493 | |||
1491 | del_timer_sync(&sdata->u.mgd.conn_mon_timer); | 1494 | del_timer_sync(&sdata->u.mgd.conn_mon_timer); |
1492 | del_timer_sync(&sdata->u.mgd.bcn_mon_timer); | 1495 | del_timer_sync(&sdata->u.mgd.bcn_mon_timer); |
1493 | del_timer_sync(&sdata->u.mgd.timer); | 1496 | del_timer_sync(&sdata->u.mgd.timer); |
@@ -1822,7 +1825,7 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, | |||
1822 | 1825 | ||
1823 | memcpy(bssid, ifmgd->auth_data->bss->bssid, ETH_ALEN); | 1826 | memcpy(bssid, ifmgd->auth_data->bss->bssid, ETH_ALEN); |
1824 | 1827 | ||
1825 | if (memcmp(bssid, mgmt->bssid, ETH_ALEN)) | 1828 | if (compare_ether_addr(bssid, mgmt->bssid)) |
1826 | return RX_MGMT_NONE; | 1829 | return RX_MGMT_NONE; |
1827 | 1830 | ||
1828 | auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg); | 1831 | auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg); |
@@ -1903,7 +1906,7 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, | |||
1903 | return RX_MGMT_NONE; | 1906 | return RX_MGMT_NONE; |
1904 | 1907 | ||
1905 | if (!ifmgd->associated || | 1908 | if (!ifmgd->associated || |
1906 | memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN)) | 1909 | compare_ether_addr(mgmt->bssid, ifmgd->associated->bssid)) |
1907 | return RX_MGMT_NONE; | 1910 | return RX_MGMT_NONE; |
1908 | 1911 | ||
1909 | bssid = ifmgd->associated->bssid; | 1912 | bssid = ifmgd->associated->bssid; |
@@ -1936,7 +1939,7 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1936 | return RX_MGMT_NONE; | 1939 | return RX_MGMT_NONE; |
1937 | 1940 | ||
1938 | if (!ifmgd->associated || | 1941 | if (!ifmgd->associated || |
1939 | memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN)) | 1942 | compare_ether_addr(mgmt->bssid, ifmgd->associated->bssid)) |
1940 | return RX_MGMT_NONE; | 1943 | return RX_MGMT_NONE; |
1941 | 1944 | ||
1942 | reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); | 1945 | reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); |
@@ -2155,7 +2158,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
2155 | ieee80211_sta_wmm_params(local, sdata, elems.wmm_param, | 2158 | ieee80211_sta_wmm_params(local, sdata, elems.wmm_param, |
2156 | elems.wmm_param_len); | 2159 | elems.wmm_param_len); |
2157 | else | 2160 | else |
2158 | ieee80211_set_wmm_default(sdata); | 2161 | ieee80211_set_wmm_default(sdata, false); |
2162 | changed |= BSS_CHANGED_QOS; | ||
2159 | 2163 | ||
2160 | if (elems.ht_info_elem && elems.wmm_param && | 2164 | if (elems.ht_info_elem && elems.wmm_param && |
2161 | (sdata->local->hw.queues >= 4) && | 2165 | (sdata->local->hw.queues >= 4) && |
@@ -2203,7 +2207,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2203 | 2207 | ||
2204 | if (!assoc_data) | 2208 | if (!assoc_data) |
2205 | return RX_MGMT_NONE; | 2209 | return RX_MGMT_NONE; |
2206 | if (memcmp(assoc_data->bss->bssid, mgmt->bssid, ETH_ALEN)) | 2210 | if (compare_ether_addr(assoc_data->bss->bssid, mgmt->bssid)) |
2207 | return RX_MGMT_NONE; | 2211 | return RX_MGMT_NONE; |
2208 | 2212 | ||
2209 | /* | 2213 | /* |
@@ -2291,8 +2295,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
2291 | bool need_ps = false; | 2295 | bool need_ps = false; |
2292 | 2296 | ||
2293 | if (sdata->u.mgd.associated && | 2297 | if (sdata->u.mgd.associated && |
2294 | memcmp(mgmt->bssid, sdata->u.mgd.associated->bssid, | 2298 | compare_ether_addr(mgmt->bssid, sdata->u.mgd.associated->bssid) |
2295 | ETH_ALEN) == 0) { | 2299 | == 0) { |
2296 | bss = (void *)sdata->u.mgd.associated->priv; | 2300 | bss = (void *)sdata->u.mgd.associated->priv; |
2297 | /* not previously set so we may need to recalc */ | 2301 | /* not previously set so we may need to recalc */ |
2298 | need_ps = !bss->dtim_period; | 2302 | need_ps = !bss->dtim_period; |
@@ -2347,7 +2351,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, | |||
2347 | 2351 | ||
2348 | ASSERT_MGD_MTX(ifmgd); | 2352 | ASSERT_MGD_MTX(ifmgd); |
2349 | 2353 | ||
2350 | if (memcmp(mgmt->da, sdata->vif.addr, ETH_ALEN)) | 2354 | if (compare_ether_addr(mgmt->da, sdata->vif.addr)) |
2351 | return; /* ignore ProbeResp to foreign address */ | 2355 | return; /* ignore ProbeResp to foreign address */ |
2352 | 2356 | ||
2353 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; | 2357 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; |
@@ -2360,11 +2364,12 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, | |||
2360 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false); | 2364 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false); |
2361 | 2365 | ||
2362 | if (ifmgd->associated && | 2366 | if (ifmgd->associated && |
2363 | memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN) == 0) | 2367 | compare_ether_addr(mgmt->bssid, ifmgd->associated->bssid) == 0) |
2364 | ieee80211_reset_ap_probe(sdata); | 2368 | ieee80211_reset_ap_probe(sdata); |
2365 | 2369 | ||
2366 | if (ifmgd->auth_data && !ifmgd->auth_data->bss->proberesp_ies && | 2370 | if (ifmgd->auth_data && !ifmgd->auth_data->bss->proberesp_ies && |
2367 | memcmp(mgmt->bssid, ifmgd->auth_data->bss->bssid, ETH_ALEN) == 0) { | 2371 | compare_ether_addr(mgmt->bssid, ifmgd->auth_data->bss->bssid) |
2372 | == 0) { | ||
2368 | /* got probe response, continue with auth */ | 2373 | /* got probe response, continue with auth */ |
2369 | printk(KERN_DEBUG "%s: direct probe responded\n", sdata->name); | 2374 | printk(KERN_DEBUG "%s: direct probe responded\n", sdata->name); |
2370 | ifmgd->auth_data->tries = 0; | 2375 | ifmgd->auth_data->tries = 0; |
@@ -2421,7 +2426,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
2421 | return; | 2426 | return; |
2422 | 2427 | ||
2423 | if (ifmgd->assoc_data && !ifmgd->assoc_data->have_beacon && | 2428 | if (ifmgd->assoc_data && !ifmgd->assoc_data->have_beacon && |
2424 | memcmp(mgmt->bssid, ifmgd->assoc_data->bss->bssid, ETH_ALEN) == 0) { | 2429 | compare_ether_addr(mgmt->bssid, ifmgd->assoc_data->bss->bssid) |
2430 | == 0) { | ||
2425 | ieee802_11_parse_elems(mgmt->u.beacon.variable, | 2431 | ieee802_11_parse_elems(mgmt->u.beacon.variable, |
2426 | len - baselen, &elems); | 2432 | len - baselen, &elems); |
2427 | 2433 | ||
@@ -2436,7 +2442,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
2436 | } | 2442 | } |
2437 | 2443 | ||
2438 | if (!ifmgd->associated || | 2444 | if (!ifmgd->associated || |
2439 | memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN)) | 2445 | compare_ether_addr(mgmt->bssid, ifmgd->associated->bssid)) |
2440 | return; | 2446 | return; |
2441 | bssid = ifmgd->associated->bssid; | 2447 | bssid = ifmgd->associated->bssid; |
2442 | 2448 | ||
@@ -3299,7 +3305,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3299 | bool match; | 3305 | bool match; |
3300 | 3306 | ||
3301 | /* keep sta info, bssid if matching */ | 3307 | /* keep sta info, bssid if matching */ |
3302 | match = memcmp(ifmgd->bssid, req->bss->bssid, ETH_ALEN) == 0; | 3308 | match = compare_ether_addr(ifmgd->bssid, req->bss->bssid) == 0; |
3303 | ieee80211_destroy_auth_data(sdata, match); | 3309 | ieee80211_destroy_auth_data(sdata, match); |
3304 | } | 3310 | } |
3305 | 3311 | ||
@@ -3421,7 +3427,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3421 | goto err_clear; | 3427 | goto err_clear; |
3422 | } | 3428 | } |
3423 | } else | 3429 | } else |
3424 | WARN_ON_ONCE(memcmp(ifmgd->bssid, req->bss->bssid, ETH_ALEN)); | 3430 | WARN_ON_ONCE(compare_ether_addr(ifmgd->bssid, req->bss->bssid)); |
3425 | 3431 | ||
3426 | if (!bss->dtim_period && | 3432 | if (!bss->dtim_period && |
3427 | sdata->local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) { | 3433 | sdata->local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) { |
@@ -3440,6 +3446,20 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3440 | } | 3446 | } |
3441 | run_again(ifmgd, assoc_data->timeout); | 3447 | run_again(ifmgd, assoc_data->timeout); |
3442 | 3448 | ||
3449 | if (bss->corrupt_data) { | ||
3450 | char *corrupt_type = "data"; | ||
3451 | if (bss->corrupt_data & IEEE80211_BSS_CORRUPT_BEACON) { | ||
3452 | if (bss->corrupt_data & | ||
3453 | IEEE80211_BSS_CORRUPT_PROBE_RESP) | ||
3454 | corrupt_type = "beacon and probe response"; | ||
3455 | else | ||
3456 | corrupt_type = "beacon"; | ||
3457 | } else if (bss->corrupt_data & IEEE80211_BSS_CORRUPT_PROBE_RESP) | ||
3458 | corrupt_type = "probe response"; | ||
3459 | printk(KERN_DEBUG "%s: associating with AP with corrupt %s\n", | ||
3460 | sdata->name, corrupt_type); | ||
3461 | } | ||
3462 | |||
3443 | err = 0; | 3463 | err = 0; |
3444 | goto out; | 3464 | goto out; |
3445 | err_clear: | 3465 | err_clear: |
@@ -3471,7 +3491,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
3471 | sdata->name, req->bssid, req->reason_code); | 3491 | sdata->name, req->bssid, req->reason_code); |
3472 | 3492 | ||
3473 | if (ifmgd->associated && | 3493 | if (ifmgd->associated && |
3474 | memcmp(ifmgd->associated->bssid, req->bssid, ETH_ALEN) == 0) | 3494 | compare_ether_addr(ifmgd->associated->bssid, req->bssid) == 0) |
3475 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, | 3495 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, |
3476 | req->reason_code, true, frame_buf); | 3496 | req->reason_code, true, frame_buf); |
3477 | else | 3497 | else |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 7a4ff02af261..5f6e32ca0858 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -177,7 +177,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
177 | pos += 2; | 177 | pos += 2; |
178 | 178 | ||
179 | /* IEEE80211_RADIOTAP_DBM_ANTSIGNAL */ | 179 | /* IEEE80211_RADIOTAP_DBM_ANTSIGNAL */ |
180 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) { | 180 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM && |
181 | !(status->flag & RX_FLAG_NO_SIGNAL_VAL)) { | ||
181 | *pos = status->signal; | 182 | *pos = status->signal; |
182 | rthdr->it_present |= | 183 | rthdr->it_present |= |
183 | cpu_to_le32(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL); | 184 | cpu_to_le32(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL); |
@@ -227,7 +228,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, | |||
227 | { | 228 | { |
228 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(origskb); | 229 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(origskb); |
229 | struct ieee80211_sub_if_data *sdata; | 230 | struct ieee80211_sub_if_data *sdata; |
230 | int needed_headroom = 0; | 231 | int needed_headroom; |
231 | struct sk_buff *skb, *skb2; | 232 | struct sk_buff *skb, *skb2; |
232 | struct net_device *prev_dev = NULL; | 233 | struct net_device *prev_dev = NULL; |
233 | int present_fcs_len = 0; | 234 | int present_fcs_len = 0; |
@@ -489,12 +490,12 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) | |||
489 | if (ieee80211_has_tods(hdr->frame_control) || | 490 | if (ieee80211_has_tods(hdr->frame_control) || |
490 | !ieee80211_has_fromds(hdr->frame_control)) | 491 | !ieee80211_has_fromds(hdr->frame_control)) |
491 | return RX_DROP_MONITOR; | 492 | return RX_DROP_MONITOR; |
492 | if (memcmp(hdr->addr3, dev_addr, ETH_ALEN) == 0) | 493 | if (compare_ether_addr(hdr->addr3, dev_addr) == 0) |
493 | return RX_DROP_MONITOR; | 494 | return RX_DROP_MONITOR; |
494 | } else { | 495 | } else { |
495 | if (!ieee80211_has_a4(hdr->frame_control)) | 496 | if (!ieee80211_has_a4(hdr->frame_control)) |
496 | return RX_DROP_MONITOR; | 497 | return RX_DROP_MONITOR; |
497 | if (memcmp(hdr->addr4, dev_addr, ETH_ALEN) == 0) | 498 | if (compare_ether_addr(hdr->addr4, dev_addr) == 0) |
498 | return RX_DROP_MONITOR; | 499 | return RX_DROP_MONITOR; |
499 | } | 500 | } |
500 | } | 501 | } |
@@ -1309,8 +1310,10 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
1309 | 1310 | ||
1310 | sta->rx_fragments++; | 1311 | sta->rx_fragments++; |
1311 | sta->rx_bytes += rx->skb->len; | 1312 | sta->rx_bytes += rx->skb->len; |
1312 | sta->last_signal = status->signal; | 1313 | if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) { |
1313 | ewma_add(&sta->avg_signal, -status->signal); | 1314 | sta->last_signal = status->signal; |
1315 | ewma_add(&sta->avg_signal, -status->signal); | ||
1316 | } | ||
1314 | 1317 | ||
1315 | /* | 1318 | /* |
1316 | * Change STA power saving mode only at the end of a frame | 1319 | * Change STA power saving mode only at the end of a frame |
@@ -1957,6 +1960,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1957 | return RX_DROP_MONITOR; | 1960 | return RX_DROP_MONITOR; |
1958 | } | 1961 | } |
1959 | 1962 | ||
1963 | if (!ifmsh->mshcfg.dot11MeshForwarding) | ||
1964 | goto out; | ||
1965 | |||
1960 | fwd_skb = skb_copy(skb, GFP_ATOMIC); | 1966 | fwd_skb = skb_copy(skb, GFP_ATOMIC); |
1961 | if (!fwd_skb) { | 1967 | if (!fwd_skb) { |
1962 | if (net_ratelimit()) | 1968 | if (net_ratelimit()) |
@@ -2182,9 +2188,14 @@ ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx) | |||
2182 | if (rx->sdata->vif.type == NL80211_IFTYPE_AP && | 2188 | if (rx->sdata->vif.type == NL80211_IFTYPE_AP && |
2183 | ieee80211_is_beacon(mgmt->frame_control) && | 2189 | ieee80211_is_beacon(mgmt->frame_control) && |
2184 | !(rx->flags & IEEE80211_RX_BEACON_REPORTED)) { | 2190 | !(rx->flags & IEEE80211_RX_BEACON_REPORTED)) { |
2191 | int sig = 0; | ||
2192 | |||
2193 | if (rx->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) | ||
2194 | sig = status->signal; | ||
2195 | |||
2185 | cfg80211_report_obss_beacon(rx->local->hw.wiphy, | 2196 | cfg80211_report_obss_beacon(rx->local->hw.wiphy, |
2186 | rx->skb->data, rx->skb->len, | 2197 | rx->skb->data, rx->skb->len, |
2187 | status->freq, GFP_ATOMIC); | 2198 | status->freq, sig, GFP_ATOMIC); |
2188 | rx->flags |= IEEE80211_RX_BEACON_REPORTED; | 2199 | rx->flags |= IEEE80211_RX_BEACON_REPORTED; |
2189 | } | 2200 | } |
2190 | 2201 | ||
@@ -2336,7 +2347,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2336 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 2347 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
2337 | break; | 2348 | break; |
2338 | 2349 | ||
2339 | if (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN)) | 2350 | if (compare_ether_addr(mgmt->bssid, sdata->u.mgd.bssid)) |
2340 | break; | 2351 | break; |
2341 | 2352 | ||
2342 | goto queue; | 2353 | goto queue; |
@@ -2408,6 +2419,7 @@ static ieee80211_rx_result debug_noinline | |||
2408 | ieee80211_rx_h_userspace_mgmt(struct ieee80211_rx_data *rx) | 2419 | ieee80211_rx_h_userspace_mgmt(struct ieee80211_rx_data *rx) |
2409 | { | 2420 | { |
2410 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); | 2421 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); |
2422 | int sig = 0; | ||
2411 | 2423 | ||
2412 | /* skip known-bad action frames and return them in the next handler */ | 2424 | /* skip known-bad action frames and return them in the next handler */ |
2413 | if (status->rx_flags & IEEE80211_RX_MALFORMED_ACTION_FRM) | 2425 | if (status->rx_flags & IEEE80211_RX_MALFORMED_ACTION_FRM) |
@@ -2420,7 +2432,10 @@ ieee80211_rx_h_userspace_mgmt(struct ieee80211_rx_data *rx) | |||
2420 | * it transmitted were processed or returned. | 2432 | * it transmitted were processed or returned. |
2421 | */ | 2433 | */ |
2422 | 2434 | ||
2423 | if (cfg80211_rx_mgmt(rx->sdata->dev, status->freq, | 2435 | if (rx->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) |
2436 | sig = status->signal; | ||
2437 | |||
2438 | if (cfg80211_rx_mgmt(rx->sdata->dev, status->freq, sig, | ||
2424 | rx->skb->data, rx->skb->len, | 2439 | rx->skb->data, rx->skb->len, |
2425 | GFP_ATOMIC)) { | 2440 | GFP_ATOMIC)) { |
2426 | if (rx->sta) | 2441 | if (rx->sta) |
@@ -2538,16 +2553,10 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx, | |||
2538 | { | 2553 | { |
2539 | struct ieee80211_sub_if_data *sdata; | 2554 | struct ieee80211_sub_if_data *sdata; |
2540 | struct ieee80211_local *local = rx->local; | 2555 | struct ieee80211_local *local = rx->local; |
2541 | struct ieee80211_rtap_hdr { | ||
2542 | struct ieee80211_radiotap_header hdr; | ||
2543 | u8 flags; | ||
2544 | u8 rate_or_pad; | ||
2545 | __le16 chan_freq; | ||
2546 | __le16 chan_flags; | ||
2547 | } __packed *rthdr; | ||
2548 | struct sk_buff *skb = rx->skb, *skb2; | 2556 | struct sk_buff *skb = rx->skb, *skb2; |
2549 | struct net_device *prev_dev = NULL; | 2557 | struct net_device *prev_dev = NULL; |
2550 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 2558 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
2559 | int needed_headroom; | ||
2551 | 2560 | ||
2552 | /* | 2561 | /* |
2553 | * If cooked monitor has been processed already, then | 2562 | * If cooked monitor has been processed already, then |
@@ -2561,30 +2570,15 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx, | |||
2561 | if (!local->cooked_mntrs) | 2570 | if (!local->cooked_mntrs) |
2562 | goto out_free_skb; | 2571 | goto out_free_skb; |
2563 | 2572 | ||
2564 | if (skb_headroom(skb) < sizeof(*rthdr) && | 2573 | /* room for the radiotap header based on driver features */ |
2565 | pskb_expand_head(skb, sizeof(*rthdr), 0, GFP_ATOMIC)) | 2574 | needed_headroom = ieee80211_rx_radiotap_len(local, status); |
2566 | goto out_free_skb; | ||
2567 | |||
2568 | rthdr = (void *)skb_push(skb, sizeof(*rthdr)); | ||
2569 | memset(rthdr, 0, sizeof(*rthdr)); | ||
2570 | rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr)); | ||
2571 | rthdr->hdr.it_present = | ||
2572 | cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) | | ||
2573 | (1 << IEEE80211_RADIOTAP_CHANNEL)); | ||
2574 | 2575 | ||
2575 | if (rate) { | 2576 | if (skb_headroom(skb) < needed_headroom && |
2576 | rthdr->rate_or_pad = rate->bitrate / 5; | 2577 | pskb_expand_head(skb, needed_headroom, 0, GFP_ATOMIC)) |
2577 | rthdr->hdr.it_present |= | 2578 | goto out_free_skb; |
2578 | cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE); | ||
2579 | } | ||
2580 | rthdr->chan_freq = cpu_to_le16(status->freq); | ||
2581 | 2579 | ||
2582 | if (status->band == IEEE80211_BAND_5GHZ) | 2580 | /* prepend radiotap information */ |
2583 | rthdr->chan_flags = cpu_to_le16(IEEE80211_CHAN_OFDM | | 2581 | ieee80211_add_rx_radiotap_header(local, skb, rate, needed_headroom); |
2584 | IEEE80211_CHAN_5GHZ); | ||
2585 | else | ||
2586 | rthdr->chan_flags = cpu_to_le16(IEEE80211_CHAN_DYN | | ||
2587 | IEEE80211_CHAN_2GHZ); | ||
2588 | 2582 | ||
2589 | skb_set_mac_header(skb, 0); | 2583 | skb_set_mac_header(skb, 0); |
2590 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 2584 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 9270771702fe..33cd16901378 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -13,6 +13,7 @@ | |||
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/if_arp.h> | 15 | #include <linux/if_arp.h> |
16 | #include <linux/etherdevice.h> | ||
16 | #include <linux/rtnetlink.h> | 17 | #include <linux/rtnetlink.h> |
17 | #include <linux/pm_qos.h> | 18 | #include <linux/pm_qos.h> |
18 | #include <net/sch_generic.h> | 19 | #include <net/sch_generic.h> |
@@ -103,16 +104,35 @@ ieee80211_bss_info_update(struct ieee80211_local *local, | |||
103 | cbss->free_priv = ieee80211_rx_bss_free; | 104 | cbss->free_priv = ieee80211_rx_bss_free; |
104 | bss = (void *)cbss->priv; | 105 | bss = (void *)cbss->priv; |
105 | 106 | ||
107 | if (elems->parse_error) { | ||
108 | if (beacon) | ||
109 | bss->corrupt_data |= IEEE80211_BSS_CORRUPT_BEACON; | ||
110 | else | ||
111 | bss->corrupt_data |= IEEE80211_BSS_CORRUPT_PROBE_RESP; | ||
112 | } else { | ||
113 | if (beacon) | ||
114 | bss->corrupt_data &= ~IEEE80211_BSS_CORRUPT_BEACON; | ||
115 | else | ||
116 | bss->corrupt_data &= ~IEEE80211_BSS_CORRUPT_PROBE_RESP; | ||
117 | } | ||
118 | |||
106 | /* save the ERP value so that it is available at association time */ | 119 | /* save the ERP value so that it is available at association time */ |
107 | if (elems->erp_info && elems->erp_info_len >= 1) { | 120 | if (elems->erp_info && elems->erp_info_len >= 1 && |
121 | (!elems->parse_error || | ||
122 | !(bss->valid_data & IEEE80211_BSS_VALID_ERP))) { | ||
108 | bss->erp_value = elems->erp_info[0]; | 123 | bss->erp_value = elems->erp_info[0]; |
109 | bss->has_erp_value = true; | 124 | bss->has_erp_value = true; |
125 | if (!elems->parse_error) | ||
126 | bss->valid_data |= IEEE80211_BSS_VALID_ERP; | ||
110 | } | 127 | } |
111 | 128 | ||
112 | if (elems->tim) { | 129 | if (elems->tim && (!elems->parse_error || |
130 | !(bss->valid_data & IEEE80211_BSS_VALID_DTIM))) { | ||
113 | struct ieee80211_tim_ie *tim_ie = | 131 | struct ieee80211_tim_ie *tim_ie = |
114 | (struct ieee80211_tim_ie *)elems->tim; | 132 | (struct ieee80211_tim_ie *)elems->tim; |
115 | bss->dtim_period = tim_ie->dtim_period; | 133 | bss->dtim_period = tim_ie->dtim_period; |
134 | if (!elems->parse_error) | ||
135 | bss->valid_data |= IEEE80211_BSS_VALID_DTIM; | ||
116 | } | 136 | } |
117 | 137 | ||
118 | /* If the beacon had no TIM IE, or it was invalid, use 1 */ | 138 | /* If the beacon had no TIM IE, or it was invalid, use 1 */ |
@@ -120,26 +140,38 @@ ieee80211_bss_info_update(struct ieee80211_local *local, | |||
120 | bss->dtim_period = 1; | 140 | bss->dtim_period = 1; |
121 | 141 | ||
122 | /* replace old supported rates if we get new values */ | 142 | /* replace old supported rates if we get new values */ |
123 | srlen = 0; | 143 | if (!elems->parse_error || |
124 | if (elems->supp_rates) { | 144 | !(bss->valid_data & IEEE80211_BSS_VALID_RATES)) { |
125 | clen = IEEE80211_MAX_SUPP_RATES; | 145 | srlen = 0; |
126 | if (clen > elems->supp_rates_len) | 146 | if (elems->supp_rates) { |
127 | clen = elems->supp_rates_len; | 147 | clen = IEEE80211_MAX_SUPP_RATES; |
128 | memcpy(bss->supp_rates, elems->supp_rates, clen); | 148 | if (clen > elems->supp_rates_len) |
129 | srlen += clen; | 149 | clen = elems->supp_rates_len; |
130 | } | 150 | memcpy(bss->supp_rates, elems->supp_rates, clen); |
131 | if (elems->ext_supp_rates) { | 151 | srlen += clen; |
132 | clen = IEEE80211_MAX_SUPP_RATES - srlen; | 152 | } |
133 | if (clen > elems->ext_supp_rates_len) | 153 | if (elems->ext_supp_rates) { |
134 | clen = elems->ext_supp_rates_len; | 154 | clen = IEEE80211_MAX_SUPP_RATES - srlen; |
135 | memcpy(bss->supp_rates + srlen, elems->ext_supp_rates, clen); | 155 | if (clen > elems->ext_supp_rates_len) |
136 | srlen += clen; | 156 | clen = elems->ext_supp_rates_len; |
157 | memcpy(bss->supp_rates + srlen, elems->ext_supp_rates, | ||
158 | clen); | ||
159 | srlen += clen; | ||
160 | } | ||
161 | if (srlen) { | ||
162 | bss->supp_rates_len = srlen; | ||
163 | if (!elems->parse_error) | ||
164 | bss->valid_data |= IEEE80211_BSS_VALID_RATES; | ||
165 | } | ||
137 | } | 166 | } |
138 | if (srlen) | ||
139 | bss->supp_rates_len = srlen; | ||
140 | 167 | ||
141 | bss->wmm_used = elems->wmm_param || elems->wmm_info; | 168 | if (!elems->parse_error || |
142 | bss->uapsd_supported = is_uapsd_supported(elems); | 169 | !(bss->valid_data & IEEE80211_BSS_VALID_WMM)) { |
170 | bss->wmm_used = elems->wmm_param || elems->wmm_info; | ||
171 | bss->uapsd_supported = is_uapsd_supported(elems); | ||
172 | if (!elems->parse_error) | ||
173 | bss->valid_data |= IEEE80211_BSS_VALID_WMM; | ||
174 | } | ||
143 | 175 | ||
144 | if (!beacon) | 176 | if (!beacon) |
145 | bss->last_probe_resp = jiffies; | 177 | bss->last_probe_resp = jiffies; |
@@ -176,7 +208,7 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | |||
176 | presp = ieee80211_is_probe_resp(fc); | 208 | presp = ieee80211_is_probe_resp(fc); |
177 | if (presp) { | 209 | if (presp) { |
178 | /* ignore ProbeResp to foreign address */ | 210 | /* ignore ProbeResp to foreign address */ |
179 | if (memcmp(mgmt->da, sdata->vif.addr, ETH_ALEN)) | 211 | if (compare_ether_addr(mgmt->da, sdata->vif.addr)) |
180 | return RX_DROP_MONITOR; | 212 | return RX_DROP_MONITOR; |
181 | 213 | ||
182 | presp = true; | 214 | presp = true; |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index cd0f265f42e5..38137cb5f6f0 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -9,6 +9,7 @@ | |||
9 | 9 | ||
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <linux/etherdevice.h> | ||
12 | #include <linux/netdevice.h> | 13 | #include <linux/netdevice.h> |
13 | #include <linux/types.h> | 14 | #include <linux/types.h> |
14 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
@@ -101,7 +102,7 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, | |||
101 | lockdep_is_held(&local->sta_mtx)); | 102 | lockdep_is_held(&local->sta_mtx)); |
102 | while (sta) { | 103 | while (sta) { |
103 | if (sta->sdata == sdata && | 104 | if (sta->sdata == sdata && |
104 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | 105 | compare_ether_addr(sta->sta.addr, addr) == 0) |
105 | break; | 106 | break; |
106 | sta = rcu_dereference_check(sta->hnext, | 107 | sta = rcu_dereference_check(sta->hnext, |
107 | lockdep_is_held(&local->sta_mtx)); | 108 | lockdep_is_held(&local->sta_mtx)); |
@@ -124,7 +125,7 @@ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, | |||
124 | while (sta) { | 125 | while (sta) { |
125 | if ((sta->sdata == sdata || | 126 | if ((sta->sdata == sdata || |
126 | (sta->sdata->bss && sta->sdata->bss == sdata->bss)) && | 127 | (sta->sdata->bss && sta->sdata->bss == sdata->bss)) && |
127 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | 128 | compare_ether_addr(sta->sta.addr, addr) == 0) |
128 | break; | 129 | break; |
129 | sta = rcu_dereference_check(sta->hnext, | 130 | sta = rcu_dereference_check(sta->hnext, |
130 | lockdep_is_held(&local->sta_mtx)); | 131 | lockdep_is_held(&local->sta_mtx)); |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 23a97c9dc042..ab0576827baf 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/if_ether.h> | 14 | #include <linux/if_ether.h> |
15 | #include <linux/workqueue.h> | 15 | #include <linux/workqueue.h> |
16 | #include <linux/average.h> | 16 | #include <linux/average.h> |
17 | #include <linux/etherdevice.h> | ||
17 | #include "key.h" | 18 | #include "key.h" |
18 | 19 | ||
19 | /** | 20 | /** |
@@ -489,7 +490,7 @@ void for_each_sta_info_type_check(struct ieee80211_local *local, | |||
489 | nxt = _sta ? rcu_dereference(_sta->hnext) : NULL \ | 490 | nxt = _sta ? rcu_dereference(_sta->hnext) : NULL \ |
490 | ) \ | 491 | ) \ |
491 | /* compare address and run code only if it matches */ \ | 492 | /* compare address and run code only if it matches */ \ |
492 | if (memcmp(_sta->sta.addr, (_addr), ETH_ALEN) == 0) | 493 | if (compare_ether_addr(_sta->sta.addr, (_addr)) == 0) |
493 | 494 | ||
494 | /* | 495 | /* |
495 | * Get STA info by index, BROKEN! | 496 | * Get STA info by index, BROKEN! |
@@ -528,6 +529,9 @@ void sta_info_init(struct ieee80211_local *local); | |||
528 | void sta_info_stop(struct ieee80211_local *local); | 529 | void sta_info_stop(struct ieee80211_local *local); |
529 | int sta_info_flush(struct ieee80211_local *local, | 530 | int sta_info_flush(struct ieee80211_local *local, |
530 | struct ieee80211_sub_if_data *sdata); | 531 | struct ieee80211_sub_if_data *sdata); |
532 | void sta_set_rate_info_tx(struct sta_info *sta, | ||
533 | const struct ieee80211_tx_rate *rate, | ||
534 | struct rate_info *rinfo); | ||
531 | void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, | 535 | void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, |
532 | unsigned long exp_time); | 536 | unsigned long exp_time); |
533 | 537 | ||
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index c928e4a4effd..5f8f89e89d6b 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -10,6 +10,7 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/export.h> | 12 | #include <linux/export.h> |
13 | #include <linux/etherdevice.h> | ||
13 | #include <net/mac80211.h> | 14 | #include <net/mac80211.h> |
14 | #include <asm/unaligned.h> | 15 | #include <asm/unaligned.h> |
15 | #include "ieee80211_i.h" | 16 | #include "ieee80211_i.h" |
@@ -377,7 +378,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
377 | 378 | ||
378 | for_each_sta_info(local, hdr->addr1, sta, tmp) { | 379 | for_each_sta_info(local, hdr->addr1, sta, tmp) { |
379 | /* skip wrong virtual interface */ | 380 | /* skip wrong virtual interface */ |
380 | if (memcmp(hdr->addr2, sta->sdata->vif.addr, ETH_ALEN)) | 381 | if (compare_ether_addr(hdr->addr2, sta->sdata->vif.addr)) |
381 | continue; | 382 | continue; |
382 | 383 | ||
383 | if (info->flags & IEEE80211_TX_STATUS_EOSP) | 384 | if (info->flags & IEEE80211_TX_STATUS_EOSP) |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index f6e4cef92021..32f7a3b3d43c 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -572,24 +572,40 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | |||
572 | size_t left = len; | 572 | size_t left = len; |
573 | u8 *pos = start; | 573 | u8 *pos = start; |
574 | bool calc_crc = filter != 0; | 574 | bool calc_crc = filter != 0; |
575 | DECLARE_BITMAP(seen_elems, 256); | ||
575 | 576 | ||
577 | bitmap_zero(seen_elems, 256); | ||
576 | memset(elems, 0, sizeof(*elems)); | 578 | memset(elems, 0, sizeof(*elems)); |
577 | elems->ie_start = start; | 579 | elems->ie_start = start; |
578 | elems->total_len = len; | 580 | elems->total_len = len; |
579 | 581 | ||
580 | while (left >= 2) { | 582 | while (left >= 2) { |
581 | u8 id, elen; | 583 | u8 id, elen; |
584 | bool elem_parse_failed; | ||
582 | 585 | ||
583 | id = *pos++; | 586 | id = *pos++; |
584 | elen = *pos++; | 587 | elen = *pos++; |
585 | left -= 2; | 588 | left -= 2; |
586 | 589 | ||
587 | if (elen > left) | 590 | if (elen > left) { |
591 | elems->parse_error = true; | ||
588 | break; | 592 | break; |
593 | } | ||
594 | |||
595 | if (id != WLAN_EID_VENDOR_SPECIFIC && | ||
596 | id != WLAN_EID_QUIET && | ||
597 | test_bit(id, seen_elems)) { | ||
598 | elems->parse_error = true; | ||
599 | left -= elen; | ||
600 | pos += elen; | ||
601 | continue; | ||
602 | } | ||
589 | 603 | ||
590 | if (calc_crc && id < 64 && (filter & (1ULL << id))) | 604 | if (calc_crc && id < 64 && (filter & (1ULL << id))) |
591 | crc = crc32_be(crc, pos - 2, elen + 2); | 605 | crc = crc32_be(crc, pos - 2, elen + 2); |
592 | 606 | ||
607 | elem_parse_failed = false; | ||
608 | |||
593 | switch (id) { | 609 | switch (id) { |
594 | case WLAN_EID_SSID: | 610 | case WLAN_EID_SSID: |
595 | elems->ssid = pos; | 611 | elems->ssid = pos; |
@@ -615,7 +631,8 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | |||
615 | if (elen >= sizeof(struct ieee80211_tim_ie)) { | 631 | if (elen >= sizeof(struct ieee80211_tim_ie)) { |
616 | elems->tim = (void *)pos; | 632 | elems->tim = (void *)pos; |
617 | elems->tim_len = elen; | 633 | elems->tim_len = elen; |
618 | } | 634 | } else |
635 | elem_parse_failed = true; | ||
619 | break; | 636 | break; |
620 | case WLAN_EID_IBSS_PARAMS: | 637 | case WLAN_EID_IBSS_PARAMS: |
621 | elems->ibss_params = pos; | 638 | elems->ibss_params = pos; |
@@ -664,10 +681,14 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | |||
664 | case WLAN_EID_HT_CAPABILITY: | 681 | case WLAN_EID_HT_CAPABILITY: |
665 | if (elen >= sizeof(struct ieee80211_ht_cap)) | 682 | if (elen >= sizeof(struct ieee80211_ht_cap)) |
666 | elems->ht_cap_elem = (void *)pos; | 683 | elems->ht_cap_elem = (void *)pos; |
684 | else | ||
685 | elem_parse_failed = true; | ||
667 | break; | 686 | break; |
668 | case WLAN_EID_HT_INFORMATION: | 687 | case WLAN_EID_HT_INFORMATION: |
669 | if (elen >= sizeof(struct ieee80211_ht_info)) | 688 | if (elen >= sizeof(struct ieee80211_ht_info)) |
670 | elems->ht_info_elem = (void *)pos; | 689 | elems->ht_info_elem = (void *)pos; |
690 | else | ||
691 | elem_parse_failed = true; | ||
671 | break; | 692 | break; |
672 | case WLAN_EID_MESH_ID: | 693 | case WLAN_EID_MESH_ID: |
673 | elems->mesh_id = pos; | 694 | elems->mesh_id = pos; |
@@ -676,6 +697,8 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | |||
676 | case WLAN_EID_MESH_CONFIG: | 697 | case WLAN_EID_MESH_CONFIG: |
677 | if (elen >= sizeof(struct ieee80211_meshconf_ie)) | 698 | if (elen >= sizeof(struct ieee80211_meshconf_ie)) |
678 | elems->mesh_config = (void *)pos; | 699 | elems->mesh_config = (void *)pos; |
700 | else | ||
701 | elem_parse_failed = true; | ||
679 | break; | 702 | break; |
680 | case WLAN_EID_PEER_MGMT: | 703 | case WLAN_EID_PEER_MGMT: |
681 | elems->peering = pos; | 704 | elems->peering = pos; |
@@ -696,6 +719,8 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | |||
696 | case WLAN_EID_RANN: | 719 | case WLAN_EID_RANN: |
697 | if (elen >= sizeof(struct ieee80211_rann_ie)) | 720 | if (elen >= sizeof(struct ieee80211_rann_ie)) |
698 | elems->rann = (void *)pos; | 721 | elems->rann = (void *)pos; |
722 | else | ||
723 | elem_parse_failed = true; | ||
699 | break; | 724 | break; |
700 | case WLAN_EID_CHANNEL_SWITCH: | 725 | case WLAN_EID_CHANNEL_SWITCH: |
701 | elems->ch_switch_elem = pos; | 726 | elems->ch_switch_elem = pos; |
@@ -724,10 +749,18 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | |||
724 | break; | 749 | break; |
725 | } | 750 | } |
726 | 751 | ||
752 | if (elem_parse_failed) | ||
753 | elems->parse_error = true; | ||
754 | else | ||
755 | set_bit(id, seen_elems); | ||
756 | |||
727 | left -= elen; | 757 | left -= elen; |
728 | pos += elen; | 758 | pos += elen; |
729 | } | 759 | } |
730 | 760 | ||
761 | if (left != 0) | ||
762 | elems->parse_error = true; | ||
763 | |||
731 | return crc; | 764 | return crc; |
732 | } | 765 | } |
733 | 766 | ||
@@ -737,7 +770,8 @@ void ieee802_11_parse_elems(u8 *start, size_t len, | |||
737 | ieee802_11_parse_elems_crc(start, len, elems, 0, 0); | 770 | ieee802_11_parse_elems_crc(start, len, elems, 0, 0); |
738 | } | 771 | } |
739 | 772 | ||
740 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) | 773 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, |
774 | bool bss_notify) | ||
741 | { | 775 | { |
742 | struct ieee80211_local *local = sdata->local; | 776 | struct ieee80211_local *local = sdata->local; |
743 | struct ieee80211_tx_queue_params qparam; | 777 | struct ieee80211_tx_queue_params qparam; |
@@ -807,7 +841,9 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) | |||
807 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { | 841 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { |
808 | sdata->vif.bss_conf.qos = | 842 | sdata->vif.bss_conf.qos = |
809 | sdata->vif.type != NL80211_IFTYPE_STATION; | 843 | sdata->vif.type != NL80211_IFTYPE_STATION; |
810 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_QOS); | 844 | if (bss_notify) |
845 | ieee80211_bss_info_change_notify(sdata, | ||
846 | BSS_CHANGED_QOS); | ||
811 | } | 847 | } |
812 | } | 848 | } |
813 | 849 | ||
@@ -829,7 +865,7 @@ void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, | |||
829 | else | 865 | else |
830 | sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; | 866 | sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; |
831 | 867 | ||
832 | ieee80211_set_wmm_default(sdata); | 868 | ieee80211_set_wmm_default(sdata, true); |
833 | } | 869 | } |
834 | 870 | ||
835 | u32 ieee80211_mandatory_rates(struct ieee80211_local *local, | 871 | u32 ieee80211_mandatory_rates(struct ieee80211_local *local, |
diff --git a/net/nfc/af_nfc.c b/net/nfc/af_nfc.c index da67756425ce..9d68441e2a5a 100644 --- a/net/nfc/af_nfc.c +++ b/net/nfc/af_nfc.c | |||
@@ -30,7 +30,7 @@ static DEFINE_RWLOCK(proto_tab_lock); | |||
30 | static const struct nfc_protocol *proto_tab[NFC_SOCKPROTO_MAX]; | 30 | static const struct nfc_protocol *proto_tab[NFC_SOCKPROTO_MAX]; |
31 | 31 | ||
32 | static int nfc_sock_create(struct net *net, struct socket *sock, int proto, | 32 | static int nfc_sock_create(struct net *net, struct socket *sock, int proto, |
33 | int kern) | 33 | int kern) |
34 | { | 34 | { |
35 | int rc = -EPROTONOSUPPORT; | 35 | int rc = -EPROTONOSUPPORT; |
36 | 36 | ||
diff --git a/net/nfc/core.c b/net/nfc/core.c index 6089aca67b14..295d129864d2 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c | |||
@@ -181,13 +181,13 @@ error: | |||
181 | return rc; | 181 | return rc; |
182 | } | 182 | } |
183 | 183 | ||
184 | int nfc_dep_link_up(struct nfc_dev *dev, int target_index, | 184 | int nfc_dep_link_up(struct nfc_dev *dev, int target_index, u8 comm_mode) |
185 | u8 comm_mode, u8 rf_mode) | ||
186 | { | 185 | { |
187 | int rc = 0; | 186 | int rc = 0; |
187 | u8 *gb; | ||
188 | size_t gb_len; | ||
188 | 189 | ||
189 | pr_debug("dev_name=%s comm:%d rf:%d\n", | 190 | pr_debug("dev_name=%s comm %d\n", dev_name(&dev->dev), comm_mode); |
190 | dev_name(&dev->dev), comm_mode, rf_mode); | ||
191 | 191 | ||
192 | if (!dev->ops->dep_link_up) | 192 | if (!dev->ops->dep_link_up) |
193 | return -EOPNOTSUPP; | 193 | return -EOPNOTSUPP; |
@@ -204,7 +204,13 @@ int nfc_dep_link_up(struct nfc_dev *dev, int target_index, | |||
204 | goto error; | 204 | goto error; |
205 | } | 205 | } |
206 | 206 | ||
207 | rc = dev->ops->dep_link_up(dev, target_index, comm_mode, rf_mode); | 207 | gb = nfc_llcp_general_bytes(dev, &gb_len); |
208 | if (gb_len > NFC_MAX_GT_LEN) { | ||
209 | rc = -EINVAL; | ||
210 | goto error; | ||
211 | } | ||
212 | |||
213 | rc = dev->ops->dep_link_up(dev, target_index, comm_mode, gb, gb_len); | ||
208 | 214 | ||
209 | error: | 215 | error: |
210 | device_unlock(&dev->dev); | 216 | device_unlock(&dev->dev); |
@@ -250,7 +256,7 @@ error: | |||
250 | } | 256 | } |
251 | 257 | ||
252 | int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx, | 258 | int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx, |
253 | u8 comm_mode, u8 rf_mode) | 259 | u8 comm_mode, u8 rf_mode) |
254 | { | 260 | { |
255 | dev->dep_link_up = true; | 261 | dev->dep_link_up = true; |
256 | dev->dep_rf_mode = rf_mode; | 262 | dev->dep_rf_mode = rf_mode; |
@@ -330,10 +336,8 @@ error: | |||
330 | * | 336 | * |
331 | * The user must wait for the callback before calling this function again. | 337 | * The user must wait for the callback before calling this function again. |
332 | */ | 338 | */ |
333 | int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx, | 339 | int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx, struct sk_buff *skb, |
334 | struct sk_buff *skb, | 340 | data_exchange_cb_t cb, void *cb_context) |
335 | data_exchange_cb_t cb, | ||
336 | void *cb_context) | ||
337 | { | 341 | { |
338 | int rc; | 342 | int rc; |
339 | 343 | ||
@@ -357,8 +361,7 @@ error: | |||
357 | 361 | ||
358 | int nfc_set_remote_general_bytes(struct nfc_dev *dev, u8 *gb, u8 gb_len) | 362 | int nfc_set_remote_general_bytes(struct nfc_dev *dev, u8 *gb, u8 gb_len) |
359 | { | 363 | { |
360 | pr_debug("dev_name=%s gb_len=%d\n", | 364 | pr_debug("dev_name=%s gb_len=%d\n", dev_name(&dev->dev), gb_len); |
361 | dev_name(&dev->dev), gb_len); | ||
362 | 365 | ||
363 | if (gb_len > NFC_MAX_GT_LEN) | 366 | if (gb_len > NFC_MAX_GT_LEN) |
364 | return -EINVAL; | 367 | return -EINVAL; |
@@ -367,12 +370,6 @@ int nfc_set_remote_general_bytes(struct nfc_dev *dev, u8 *gb, u8 gb_len) | |||
367 | } | 370 | } |
368 | EXPORT_SYMBOL(nfc_set_remote_general_bytes); | 371 | EXPORT_SYMBOL(nfc_set_remote_general_bytes); |
369 | 372 | ||
370 | u8 *nfc_get_local_general_bytes(struct nfc_dev *dev, u8 *gt_len) | ||
371 | { | ||
372 | return nfc_llcp_general_bytes(dev, gt_len); | ||
373 | } | ||
374 | EXPORT_SYMBOL(nfc_get_local_general_bytes); | ||
375 | |||
376 | /** | 373 | /** |
377 | * nfc_alloc_send_skb - allocate a skb for data exchange responses | 374 | * nfc_alloc_send_skb - allocate a skb for data exchange responses |
378 | * | 375 | * |
@@ -380,8 +377,8 @@ EXPORT_SYMBOL(nfc_get_local_general_bytes); | |||
380 | * @gfp: gfp flags | 377 | * @gfp: gfp flags |
381 | */ | 378 | */ |
382 | struct sk_buff *nfc_alloc_send_skb(struct nfc_dev *dev, struct sock *sk, | 379 | struct sk_buff *nfc_alloc_send_skb(struct nfc_dev *dev, struct sock *sk, |
383 | unsigned int flags, unsigned int size, | 380 | unsigned int flags, unsigned int size, |
384 | unsigned int *err) | 381 | unsigned int *err) |
385 | { | 382 | { |
386 | struct sk_buff *skb; | 383 | struct sk_buff *skb; |
387 | unsigned int total_size; | 384 | unsigned int total_size; |
@@ -428,8 +425,8 @@ EXPORT_SYMBOL(nfc_alloc_recv_skb); | |||
428 | * are found. After calling this function, the device driver must stop | 425 | * are found. After calling this function, the device driver must stop |
429 | * polling for targets. | 426 | * polling for targets. |
430 | */ | 427 | */ |
431 | int nfc_targets_found(struct nfc_dev *dev, struct nfc_target *targets, | 428 | int nfc_targets_found(struct nfc_dev *dev, |
432 | int n_targets) | 429 | struct nfc_target *targets, int n_targets) |
433 | { | 430 | { |
434 | pr_debug("dev_name=%s n_targets=%d\n", dev_name(&dev->dev), n_targets); | 431 | pr_debug("dev_name=%s n_targets=%d\n", dev_name(&dev->dev), n_targets); |
435 | 432 | ||
@@ -441,7 +438,7 @@ int nfc_targets_found(struct nfc_dev *dev, struct nfc_target *targets, | |||
441 | 438 | ||
442 | kfree(dev->targets); | 439 | kfree(dev->targets); |
443 | dev->targets = kmemdup(targets, n_targets * sizeof(struct nfc_target), | 440 | dev->targets = kmemdup(targets, n_targets * sizeof(struct nfc_target), |
444 | GFP_ATOMIC); | 441 | GFP_ATOMIC); |
445 | 442 | ||
446 | if (!dev->targets) { | 443 | if (!dev->targets) { |
447 | dev->n_targets = 0; | 444 | dev->n_targets = 0; |
@@ -501,15 +498,14 @@ struct nfc_dev *nfc_get_device(unsigned idx) | |||
501 | * @supported_protocols: NFC protocols supported by the device | 498 | * @supported_protocols: NFC protocols supported by the device |
502 | */ | 499 | */ |
503 | struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, | 500 | struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, |
504 | u32 supported_protocols, | 501 | u32 supported_protocols, |
505 | int tx_headroom, | 502 | int tx_headroom, int tx_tailroom) |
506 | int tx_tailroom) | ||
507 | { | 503 | { |
508 | static atomic_t dev_no = ATOMIC_INIT(0); | 504 | static atomic_t dev_no = ATOMIC_INIT(0); |
509 | struct nfc_dev *dev; | 505 | struct nfc_dev *dev; |
510 | 506 | ||
511 | if (!ops->start_poll || !ops->stop_poll || !ops->activate_target || | 507 | if (!ops->start_poll || !ops->stop_poll || !ops->activate_target || |
512 | !ops->deactivate_target || !ops->data_exchange) | 508 | !ops->deactivate_target || !ops->data_exchange) |
513 | return NULL; | 509 | return NULL; |
514 | 510 | ||
515 | if (!supported_protocols) | 511 | if (!supported_protocols) |
diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c index 151f2ef429c4..7b76eb7192f3 100644 --- a/net/nfc/llcp/commands.c +++ b/net/nfc/llcp/commands.c | |||
@@ -118,7 +118,7 @@ u8 *nfc_llcp_build_tlv(u8 type, u8 *value, u8 value_length, u8 *tlv_length) | |||
118 | } | 118 | } |
119 | 119 | ||
120 | int nfc_llcp_parse_tlv(struct nfc_llcp_local *local, | 120 | int nfc_llcp_parse_tlv(struct nfc_llcp_local *local, |
121 | u8 *tlv_array, u16 tlv_array_len) | 121 | u8 *tlv_array, u16 tlv_array_len) |
122 | { | 122 | { |
123 | u8 *tlv = tlv_array, type, length, offset = 0; | 123 | u8 *tlv = tlv_array, type, length, offset = 0; |
124 | 124 | ||
@@ -152,6 +152,8 @@ int nfc_llcp_parse_tlv(struct nfc_llcp_local *local, | |||
152 | case LLCP_TLV_RW: | 152 | case LLCP_TLV_RW: |
153 | local->remote_rw = llcp_tlv_rw(tlv); | 153 | local->remote_rw = llcp_tlv_rw(tlv); |
154 | break; | 154 | break; |
155 | case LLCP_TLV_SN: | ||
156 | break; | ||
155 | default: | 157 | default: |
156 | pr_err("Invalid gt tlv value 0x%x\n", type); | 158 | pr_err("Invalid gt tlv value 0x%x\n", type); |
157 | break; | 159 | break; |
@@ -162,15 +164,15 @@ int nfc_llcp_parse_tlv(struct nfc_llcp_local *local, | |||
162 | } | 164 | } |
163 | 165 | ||
164 | pr_debug("version 0x%x miu %d lto %d opt 0x%x wks 0x%x rw %d\n", | 166 | pr_debug("version 0x%x miu %d lto %d opt 0x%x wks 0x%x rw %d\n", |
165 | local->remote_version, local->remote_miu, | 167 | local->remote_version, local->remote_miu, |
166 | local->remote_lto, local->remote_opt, | 168 | local->remote_lto, local->remote_opt, |
167 | local->remote_wks, local->remote_rw); | 169 | local->remote_wks, local->remote_rw); |
168 | 170 | ||
169 | return 0; | 171 | return 0; |
170 | } | 172 | } |
171 | 173 | ||
172 | static struct sk_buff *llcp_add_header(struct sk_buff *pdu, | 174 | static struct sk_buff *llcp_add_header(struct sk_buff *pdu, |
173 | u8 dsap, u8 ssap, u8 ptype) | 175 | u8 dsap, u8 ssap, u8 ptype) |
174 | { | 176 | { |
175 | u8 header[2]; | 177 | u8 header[2]; |
176 | 178 | ||
@@ -186,7 +188,8 @@ static struct sk_buff *llcp_add_header(struct sk_buff *pdu, | |||
186 | return pdu; | 188 | return pdu; |
187 | } | 189 | } |
188 | 190 | ||
189 | static struct sk_buff *llcp_add_tlv(struct sk_buff *pdu, u8 *tlv, u8 tlv_length) | 191 | static struct sk_buff *llcp_add_tlv(struct sk_buff *pdu, u8 *tlv, |
192 | u8 tlv_length) | ||
190 | { | 193 | { |
191 | /* XXX Add an skb length check */ | 194 | /* XXX Add an skb length check */ |
192 | 195 | ||
@@ -199,7 +202,7 @@ static struct sk_buff *llcp_add_tlv(struct sk_buff *pdu, u8 *tlv, u8 tlv_length) | |||
199 | } | 202 | } |
200 | 203 | ||
201 | static struct sk_buff *llcp_allocate_pdu(struct nfc_llcp_sock *sock, | 204 | static struct sk_buff *llcp_allocate_pdu(struct nfc_llcp_sock *sock, |
202 | u8 cmd, u16 size) | 205 | u8 cmd, u16 size) |
203 | { | 206 | { |
204 | struct sk_buff *skb; | 207 | struct sk_buff *skb; |
205 | int err; | 208 | int err; |
@@ -208,7 +211,7 @@ static struct sk_buff *llcp_allocate_pdu(struct nfc_llcp_sock *sock, | |||
208 | return NULL; | 211 | return NULL; |
209 | 212 | ||
210 | skb = nfc_alloc_send_skb(sock->dev, &sock->sk, MSG_DONTWAIT, | 213 | skb = nfc_alloc_send_skb(sock->dev, &sock->sk, MSG_DONTWAIT, |
211 | size + LLCP_HEADER_SIZE, &err); | 214 | size + LLCP_HEADER_SIZE, &err); |
212 | if (skb == NULL) { | 215 | if (skb == NULL) { |
213 | pr_err("Could not allocate PDU\n"); | 216 | pr_err("Could not allocate PDU\n"); |
214 | return NULL; | 217 | return NULL; |
@@ -276,7 +279,7 @@ int nfc_llcp_send_symm(struct nfc_dev *dev) | |||
276 | skb = llcp_add_header(skb, 0, 0, LLCP_PDU_SYMM); | 279 | skb = llcp_add_header(skb, 0, 0, LLCP_PDU_SYMM); |
277 | 280 | ||
278 | return nfc_data_exchange(dev, local->target_idx, skb, | 281 | return nfc_data_exchange(dev, local->target_idx, skb, |
279 | nfc_llcp_recv, local); | 282 | nfc_llcp_recv, local); |
280 | } | 283 | } |
281 | 284 | ||
282 | int nfc_llcp_send_connect(struct nfc_llcp_sock *sock) | 285 | int nfc_llcp_send_connect(struct nfc_llcp_sock *sock) |
@@ -284,6 +287,9 @@ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock) | |||
284 | struct nfc_llcp_local *local; | 287 | struct nfc_llcp_local *local; |
285 | struct sk_buff *skb; | 288 | struct sk_buff *skb; |
286 | u8 *service_name_tlv = NULL, service_name_tlv_length; | 289 | u8 *service_name_tlv = NULL, service_name_tlv_length; |
290 | u8 *miux_tlv = NULL, miux_tlv_length; | ||
291 | u8 *rw_tlv = NULL, rw_tlv_length, rw; | ||
292 | __be16 miux; | ||
287 | int err; | 293 | int err; |
288 | u16 size = 0; | 294 | u16 size = 0; |
289 | 295 | ||
@@ -295,12 +301,21 @@ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock) | |||
295 | 301 | ||
296 | if (sock->service_name != NULL) { | 302 | if (sock->service_name != NULL) { |
297 | service_name_tlv = nfc_llcp_build_tlv(LLCP_TLV_SN, | 303 | service_name_tlv = nfc_llcp_build_tlv(LLCP_TLV_SN, |
298 | sock->service_name, | 304 | sock->service_name, |
299 | sock->service_name_len, | 305 | sock->service_name_len, |
300 | &service_name_tlv_length); | 306 | &service_name_tlv_length); |
301 | size += service_name_tlv_length; | 307 | size += service_name_tlv_length; |
302 | } | 308 | } |
303 | 309 | ||
310 | miux = cpu_to_be16(LLCP_MAX_MIUX); | ||
311 | miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0, | ||
312 | &miux_tlv_length); | ||
313 | size += miux_tlv_length; | ||
314 | |||
315 | rw = LLCP_MAX_RW; | ||
316 | rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &rw, 0, &rw_tlv_length); | ||
317 | size += rw_tlv_length; | ||
318 | |||
304 | pr_debug("SKB size %d SN length %zu\n", size, sock->service_name_len); | 319 | pr_debug("SKB size %d SN length %zu\n", size, sock->service_name_len); |
305 | 320 | ||
306 | skb = llcp_allocate_pdu(sock, LLCP_PDU_CONNECT, size); | 321 | skb = llcp_allocate_pdu(sock, LLCP_PDU_CONNECT, size); |
@@ -311,7 +326,10 @@ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock) | |||
311 | 326 | ||
312 | if (service_name_tlv != NULL) | 327 | if (service_name_tlv != NULL) |
313 | skb = llcp_add_tlv(skb, service_name_tlv, | 328 | skb = llcp_add_tlv(skb, service_name_tlv, |
314 | service_name_tlv_length); | 329 | service_name_tlv_length); |
330 | |||
331 | skb = llcp_add_tlv(skb, miux_tlv, miux_tlv_length); | ||
332 | skb = llcp_add_tlv(skb, rw_tlv, rw_tlv_length); | ||
315 | 333 | ||
316 | skb_queue_tail(&local->tx_queue, skb); | 334 | skb_queue_tail(&local->tx_queue, skb); |
317 | 335 | ||
@@ -321,6 +339,8 @@ error_tlv: | |||
321 | pr_err("error %d\n", err); | 339 | pr_err("error %d\n", err); |
322 | 340 | ||
323 | kfree(service_name_tlv); | 341 | kfree(service_name_tlv); |
342 | kfree(miux_tlv); | ||
343 | kfree(rw_tlv); | ||
324 | 344 | ||
325 | return err; | 345 | return err; |
326 | } | 346 | } |
@@ -329,6 +349,11 @@ int nfc_llcp_send_cc(struct nfc_llcp_sock *sock) | |||
329 | { | 349 | { |
330 | struct nfc_llcp_local *local; | 350 | struct nfc_llcp_local *local; |
331 | struct sk_buff *skb; | 351 | struct sk_buff *skb; |
352 | u8 *miux_tlv = NULL, miux_tlv_length; | ||
353 | u8 *rw_tlv = NULL, rw_tlv_length, rw; | ||
354 | __be16 miux; | ||
355 | int err; | ||
356 | u16 size = 0; | ||
332 | 357 | ||
333 | pr_debug("Sending CC\n"); | 358 | pr_debug("Sending CC\n"); |
334 | 359 | ||
@@ -336,13 +361,35 @@ int nfc_llcp_send_cc(struct nfc_llcp_sock *sock) | |||
336 | if (local == NULL) | 361 | if (local == NULL) |
337 | return -ENODEV; | 362 | return -ENODEV; |
338 | 363 | ||
339 | skb = llcp_allocate_pdu(sock, LLCP_PDU_CC, 0); | 364 | miux = cpu_to_be16(LLCP_MAX_MIUX); |
340 | if (skb == NULL) | 365 | miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0, |
341 | return -ENOMEM; | 366 | &miux_tlv_length); |
367 | size += miux_tlv_length; | ||
368 | |||
369 | rw = LLCP_MAX_RW; | ||
370 | rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &rw, 0, &rw_tlv_length); | ||
371 | size += rw_tlv_length; | ||
372 | |||
373 | skb = llcp_allocate_pdu(sock, LLCP_PDU_CC, size); | ||
374 | if (skb == NULL) { | ||
375 | err = -ENOMEM; | ||
376 | goto error_tlv; | ||
377 | } | ||
378 | |||
379 | skb = llcp_add_tlv(skb, miux_tlv, miux_tlv_length); | ||
380 | skb = llcp_add_tlv(skb, rw_tlv, rw_tlv_length); | ||
342 | 381 | ||
343 | skb_queue_tail(&local->tx_queue, skb); | 382 | skb_queue_tail(&local->tx_queue, skb); |
344 | 383 | ||
345 | return 0; | 384 | return 0; |
385 | |||
386 | error_tlv: | ||
387 | pr_err("error %d\n", err); | ||
388 | |||
389 | kfree(miux_tlv); | ||
390 | kfree(rw_tlv); | ||
391 | |||
392 | return err; | ||
346 | } | 393 | } |
347 | 394 | ||
348 | int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason) | 395 | int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason) |
@@ -397,3 +444,87 @@ int nfc_llcp_send_disconnect(struct nfc_llcp_sock *sock) | |||
397 | 444 | ||
398 | return 0; | 445 | return 0; |
399 | } | 446 | } |
447 | |||
448 | int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock, | ||
449 | struct msghdr *msg, size_t len) | ||
450 | { | ||
451 | struct sk_buff *pdu; | ||
452 | struct sock *sk = &sock->sk; | ||
453 | struct nfc_llcp_local *local; | ||
454 | size_t frag_len = 0, remaining_len; | ||
455 | u8 *msg_data, *msg_ptr; | ||
456 | |||
457 | pr_debug("Send I frame len %zd\n", len); | ||
458 | |||
459 | local = sock->local; | ||
460 | if (local == NULL) | ||
461 | return -ENODEV; | ||
462 | |||
463 | msg_data = kzalloc(len, GFP_KERNEL); | ||
464 | if (msg_data == NULL) | ||
465 | return -ENOMEM; | ||
466 | |||
467 | if (memcpy_fromiovec(msg_data, msg->msg_iov, len)) { | ||
468 | kfree(msg_data); | ||
469 | return -EFAULT; | ||
470 | } | ||
471 | |||
472 | remaining_len = len; | ||
473 | msg_ptr = msg_data; | ||
474 | |||
475 | while (remaining_len > 0) { | ||
476 | |||
477 | frag_len = min_t(u16, local->remote_miu, remaining_len); | ||
478 | |||
479 | pr_debug("Fragment %zd bytes remaining %zd", | ||
480 | frag_len, remaining_len); | ||
481 | |||
482 | pdu = llcp_allocate_pdu(sock, LLCP_PDU_I, | ||
483 | frag_len + LLCP_SEQUENCE_SIZE); | ||
484 | if (pdu == NULL) | ||
485 | return -ENOMEM; | ||
486 | |||
487 | skb_put(pdu, LLCP_SEQUENCE_SIZE); | ||
488 | |||
489 | memcpy(skb_put(pdu, frag_len), msg_ptr, frag_len); | ||
490 | |||
491 | skb_queue_head(&sock->tx_queue, pdu); | ||
492 | |||
493 | lock_sock(sk); | ||
494 | |||
495 | nfc_llcp_queue_i_frames(sock); | ||
496 | |||
497 | release_sock(sk); | ||
498 | |||
499 | remaining_len -= frag_len; | ||
500 | msg_ptr += len; | ||
501 | } | ||
502 | |||
503 | kfree(msg_data); | ||
504 | |||
505 | return 0; | ||
506 | } | ||
507 | |||
508 | int nfc_llcp_send_rr(struct nfc_llcp_sock *sock) | ||
509 | { | ||
510 | struct sk_buff *skb; | ||
511 | struct nfc_llcp_local *local; | ||
512 | |||
513 | pr_debug("Send rr nr %d\n", sock->recv_n); | ||
514 | |||
515 | local = sock->local; | ||
516 | if (local == NULL) | ||
517 | return -ENODEV; | ||
518 | |||
519 | skb = llcp_allocate_pdu(sock, LLCP_PDU_RR, LLCP_SEQUENCE_SIZE); | ||
520 | if (skb == NULL) | ||
521 | return -ENOMEM; | ||
522 | |||
523 | skb_put(skb, LLCP_SEQUENCE_SIZE); | ||
524 | |||
525 | skb->data[2] = sock->recv_n % 16; | ||
526 | |||
527 | skb_queue_head(&local->tx_queue, skb); | ||
528 | |||
529 | return 0; | ||
530 | } | ||
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c index 1d32680807d6..17a578f641f1 100644 --- a/net/nfc/llcp/llcp.c +++ b/net/nfc/llcp/llcp.c | |||
@@ -37,7 +37,6 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local) | |||
37 | struct sock *sk, *parent_sk; | 37 | struct sock *sk, *parent_sk; |
38 | int i; | 38 | int i; |
39 | 39 | ||
40 | |||
41 | mutex_lock(&local->socket_lock); | 40 | mutex_lock(&local->socket_lock); |
42 | 41 | ||
43 | for (i = 0; i < LLCP_MAX_SAP; i++) { | 42 | for (i = 0; i < LLCP_MAX_SAP; i++) { |
@@ -47,7 +46,7 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local) | |||
47 | 46 | ||
48 | /* Release all child sockets */ | 47 | /* Release all child sockets */ |
49 | list_for_each_entry_safe(s, n, &parent->list, list) { | 48 | list_for_each_entry_safe(s, n, &parent->list, list) { |
50 | list_del(&s->list); | 49 | list_del_init(&s->list); |
51 | sk = &s->sk; | 50 | sk = &s->sk; |
52 | 51 | ||
53 | lock_sock(sk); | 52 | lock_sock(sk); |
@@ -56,9 +55,12 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local) | |||
56 | nfc_put_device(s->dev); | 55 | nfc_put_device(s->dev); |
57 | 56 | ||
58 | sk->sk_state = LLCP_CLOSED; | 57 | sk->sk_state = LLCP_CLOSED; |
59 | sock_set_flag(sk, SOCK_DEAD); | ||
60 | 58 | ||
61 | release_sock(sk); | 59 | release_sock(sk); |
60 | |||
61 | sock_orphan(sk); | ||
62 | |||
63 | s->local = NULL; | ||
62 | } | 64 | } |
63 | 65 | ||
64 | parent_sk = &parent->sk; | 66 | parent_sk = &parent->sk; |
@@ -70,18 +72,19 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local) | |||
70 | struct sock *accept_sk; | 72 | struct sock *accept_sk; |
71 | 73 | ||
72 | list_for_each_entry_safe(lsk, n, &parent->accept_queue, | 74 | list_for_each_entry_safe(lsk, n, &parent->accept_queue, |
73 | accept_queue) { | 75 | accept_queue) { |
74 | accept_sk = &lsk->sk; | 76 | accept_sk = &lsk->sk; |
75 | lock_sock(accept_sk); | 77 | lock_sock(accept_sk); |
76 | 78 | ||
77 | nfc_llcp_accept_unlink(accept_sk); | 79 | nfc_llcp_accept_unlink(accept_sk); |
78 | 80 | ||
79 | accept_sk->sk_state = LLCP_CLOSED; | 81 | accept_sk->sk_state = LLCP_CLOSED; |
80 | sock_set_flag(accept_sk, SOCK_DEAD); | ||
81 | 82 | ||
82 | release_sock(accept_sk); | 83 | release_sock(accept_sk); |
83 | 84 | ||
84 | sock_orphan(accept_sk); | 85 | sock_orphan(accept_sk); |
86 | |||
87 | lsk->local = NULL; | ||
85 | } | 88 | } |
86 | } | 89 | } |
87 | 90 | ||
@@ -89,18 +92,32 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local) | |||
89 | nfc_put_device(parent->dev); | 92 | nfc_put_device(parent->dev); |
90 | 93 | ||
91 | parent_sk->sk_state = LLCP_CLOSED; | 94 | parent_sk->sk_state = LLCP_CLOSED; |
92 | sock_set_flag(parent_sk, SOCK_DEAD); | ||
93 | 95 | ||
94 | release_sock(parent_sk); | 96 | release_sock(parent_sk); |
97 | |||
98 | sock_orphan(parent_sk); | ||
99 | |||
100 | parent->local = NULL; | ||
95 | } | 101 | } |
96 | 102 | ||
97 | mutex_unlock(&local->socket_lock); | 103 | mutex_unlock(&local->socket_lock); |
98 | } | 104 | } |
99 | 105 | ||
106 | static void nfc_llcp_clear_sdp(struct nfc_llcp_local *local) | ||
107 | { | ||
108 | mutex_lock(&local->sdp_lock); | ||
109 | |||
110 | local->local_wks = 0; | ||
111 | local->local_sdp = 0; | ||
112 | local->local_sap = 0; | ||
113 | |||
114 | mutex_unlock(&local->sdp_lock); | ||
115 | } | ||
116 | |||
100 | static void nfc_llcp_timeout_work(struct work_struct *work) | 117 | static void nfc_llcp_timeout_work(struct work_struct *work) |
101 | { | 118 | { |
102 | struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, | 119 | struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, |
103 | timeout_work); | 120 | timeout_work); |
104 | 121 | ||
105 | nfc_dep_link_down(local->dev); | 122 | nfc_dep_link_down(local->dev); |
106 | } | 123 | } |
@@ -146,7 +163,7 @@ static int nfc_llcp_wks_sap(char *service_name, size_t service_name_len) | |||
146 | 163 | ||
147 | num_wks = ARRAY_SIZE(wks); | 164 | num_wks = ARRAY_SIZE(wks); |
148 | 165 | ||
149 | for (sap = 0 ; sap < num_wks; sap++) { | 166 | for (sap = 0; sap < num_wks; sap++) { |
150 | if (wks[sap] == NULL) | 167 | if (wks[sap] == NULL) |
151 | continue; | 168 | continue; |
152 | 169 | ||
@@ -158,13 +175,13 @@ static int nfc_llcp_wks_sap(char *service_name, size_t service_name_len) | |||
158 | } | 175 | } |
159 | 176 | ||
160 | u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local, | 177 | u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local, |
161 | struct nfc_llcp_sock *sock) | 178 | struct nfc_llcp_sock *sock) |
162 | { | 179 | { |
163 | mutex_lock(&local->sdp_lock); | 180 | mutex_lock(&local->sdp_lock); |
164 | 181 | ||
165 | if (sock->service_name != NULL && sock->service_name_len > 0) { | 182 | if (sock->service_name != NULL && sock->service_name_len > 0) { |
166 | int ssap = nfc_llcp_wks_sap(sock->service_name, | 183 | int ssap = nfc_llcp_wks_sap(sock->service_name, |
167 | sock->service_name_len); | 184 | sock->service_name_len); |
168 | 185 | ||
169 | if (ssap > 0) { | 186 | if (ssap > 0) { |
170 | pr_debug("WKS %d\n", ssap); | 187 | pr_debug("WKS %d\n", ssap); |
@@ -176,7 +193,7 @@ u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local, | |||
176 | return LLCP_SAP_MAX; | 193 | return LLCP_SAP_MAX; |
177 | } | 194 | } |
178 | 195 | ||
179 | set_bit(BIT(ssap), &local->local_wks); | 196 | set_bit(ssap, &local->local_wks); |
180 | mutex_unlock(&local->sdp_lock); | 197 | mutex_unlock(&local->sdp_lock); |
181 | 198 | ||
182 | return ssap; | 199 | return ssap; |
@@ -195,25 +212,25 @@ u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local, | |||
195 | 212 | ||
196 | pr_debug("SDP ssap %d\n", LLCP_WKS_NUM_SAP + ssap); | 213 | pr_debug("SDP ssap %d\n", LLCP_WKS_NUM_SAP + ssap); |
197 | 214 | ||
198 | set_bit(BIT(ssap), &local->local_sdp); | 215 | set_bit(ssap, &local->local_sdp); |
199 | mutex_unlock(&local->sdp_lock); | 216 | mutex_unlock(&local->sdp_lock); |
200 | 217 | ||
201 | return LLCP_WKS_NUM_SAP + ssap; | 218 | return LLCP_WKS_NUM_SAP + ssap; |
202 | 219 | ||
203 | } else if (sock->ssap != 0) { | 220 | } else if (sock->ssap != 0) { |
204 | if (sock->ssap < LLCP_WKS_NUM_SAP) { | 221 | if (sock->ssap < LLCP_WKS_NUM_SAP) { |
205 | if (!(local->local_wks & BIT(sock->ssap))) { | 222 | if (!test_bit(sock->ssap, &local->local_wks)) { |
206 | set_bit(BIT(sock->ssap), &local->local_wks); | 223 | set_bit(sock->ssap, &local->local_wks); |
207 | mutex_unlock(&local->sdp_lock); | 224 | mutex_unlock(&local->sdp_lock); |
208 | 225 | ||
209 | return sock->ssap; | 226 | return sock->ssap; |
210 | } | 227 | } |
211 | 228 | ||
212 | } else if (sock->ssap < LLCP_SDP_NUM_SAP) { | 229 | } else if (sock->ssap < LLCP_SDP_NUM_SAP) { |
213 | if (!(local->local_sdp & | 230 | if (!test_bit(sock->ssap - LLCP_WKS_NUM_SAP, |
214 | BIT(sock->ssap - LLCP_WKS_NUM_SAP))) { | 231 | &local->local_sdp)) { |
215 | set_bit(BIT(sock->ssap - LLCP_WKS_NUM_SAP), | 232 | set_bit(sock->ssap - LLCP_WKS_NUM_SAP, |
216 | &local->local_sdp); | 233 | &local->local_sdp); |
217 | mutex_unlock(&local->sdp_lock); | 234 | mutex_unlock(&local->sdp_lock); |
218 | 235 | ||
219 | return sock->ssap; | 236 | return sock->ssap; |
@@ -238,7 +255,7 @@ u8 nfc_llcp_get_local_ssap(struct nfc_llcp_local *local) | |||
238 | return LLCP_SAP_MAX; | 255 | return LLCP_SAP_MAX; |
239 | } | 256 | } |
240 | 257 | ||
241 | set_bit(BIT(local_ssap), &local->local_sap); | 258 | set_bit(local_ssap, &local->local_sap); |
242 | 259 | ||
243 | mutex_unlock(&local->sdp_lock); | 260 | mutex_unlock(&local->sdp_lock); |
244 | 261 | ||
@@ -265,12 +282,12 @@ void nfc_llcp_put_ssap(struct nfc_llcp_local *local, u8 ssap) | |||
265 | 282 | ||
266 | mutex_lock(&local->sdp_lock); | 283 | mutex_lock(&local->sdp_lock); |
267 | 284 | ||
268 | clear_bit(1 << local_ssap, sdp); | 285 | clear_bit(local_ssap, sdp); |
269 | 286 | ||
270 | mutex_unlock(&local->sdp_lock); | 287 | mutex_unlock(&local->sdp_lock); |
271 | } | 288 | } |
272 | 289 | ||
273 | u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, u8 *general_bytes_len) | 290 | u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len) |
274 | { | 291 | { |
275 | struct nfc_llcp_local *local; | 292 | struct nfc_llcp_local *local; |
276 | 293 | ||
@@ -294,7 +311,7 @@ static int nfc_llcp_build_gb(struct nfc_llcp_local *local) | |||
294 | 311 | ||
295 | version = LLCP_VERSION_11; | 312 | version = LLCP_VERSION_11; |
296 | version_tlv = nfc_llcp_build_tlv(LLCP_TLV_VERSION, &version, | 313 | version_tlv = nfc_llcp_build_tlv(LLCP_TLV_VERSION, &version, |
297 | 1, &version_length); | 314 | 1, &version_length); |
298 | gb_len += version_length; | 315 | gb_len += version_length; |
299 | 316 | ||
300 | /* 1500 ms */ | 317 | /* 1500 ms */ |
@@ -304,7 +321,7 @@ static int nfc_llcp_build_gb(struct nfc_llcp_local *local) | |||
304 | 321 | ||
305 | pr_debug("Local wks 0x%lx\n", local->local_wks); | 322 | pr_debug("Local wks 0x%lx\n", local->local_wks); |
306 | wks_tlv = nfc_llcp_build_tlv(LLCP_TLV_WKS, (u8 *)&local->local_wks, 2, | 323 | wks_tlv = nfc_llcp_build_tlv(LLCP_TLV_WKS, (u8 *)&local->local_wks, 2, |
307 | &wks_length); | 324 | &wks_length); |
308 | gb_len += wks_length; | 325 | gb_len += wks_length; |
309 | 326 | ||
310 | gb_len += ARRAY_SIZE(llcp_magic); | 327 | gb_len += ARRAY_SIZE(llcp_magic); |
@@ -349,8 +366,7 @@ int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len) | |||
349 | memcpy(local->remote_gb, gb, gb_len); | 366 | memcpy(local->remote_gb, gb, gb_len); |
350 | local->remote_gb_len = gb_len; | 367 | local->remote_gb_len = gb_len; |
351 | 368 | ||
352 | if (local->remote_gb == NULL || | 369 | if (local->remote_gb == NULL || local->remote_gb_len == 0) |
353 | local->remote_gb_len == 0) | ||
354 | return -ENODEV; | 370 | return -ENODEV; |
355 | 371 | ||
356 | if (memcmp(local->remote_gb, llcp_magic, 3)) { | 372 | if (memcmp(local->remote_gb, llcp_magic, 3)) { |
@@ -359,26 +375,27 @@ int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len) | |||
359 | } | 375 | } |
360 | 376 | ||
361 | return nfc_llcp_parse_tlv(local, | 377 | return nfc_llcp_parse_tlv(local, |
362 | &local->remote_gb[3], local->remote_gb_len - 3); | 378 | &local->remote_gb[3], |
379 | local->remote_gb_len - 3); | ||
363 | } | 380 | } |
364 | 381 | ||
365 | static void nfc_llcp_tx_work(struct work_struct *work) | 382 | static void nfc_llcp_tx_work(struct work_struct *work) |
366 | { | 383 | { |
367 | struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, | 384 | struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, |
368 | tx_work); | 385 | tx_work); |
369 | struct sk_buff *skb; | 386 | struct sk_buff *skb; |
370 | 387 | ||
371 | skb = skb_dequeue(&local->tx_queue); | 388 | skb = skb_dequeue(&local->tx_queue); |
372 | if (skb != NULL) { | 389 | if (skb != NULL) { |
373 | pr_debug("Sending pending skb\n"); | 390 | pr_debug("Sending pending skb\n"); |
374 | nfc_data_exchange(local->dev, local->target_idx, | 391 | nfc_data_exchange(local->dev, local->target_idx, |
375 | skb, nfc_llcp_recv, local); | 392 | skb, nfc_llcp_recv, local); |
376 | } else { | 393 | } else { |
377 | nfc_llcp_send_symm(local->dev); | 394 | nfc_llcp_send_symm(local->dev); |
378 | } | 395 | } |
379 | 396 | ||
380 | mod_timer(&local->link_timer, | 397 | mod_timer(&local->link_timer, |
381 | jiffies + msecs_to_jiffies(local->remote_lto)); | 398 | jiffies + msecs_to_jiffies(local->remote_lto)); |
382 | } | 399 | } |
383 | 400 | ||
384 | static u8 nfc_llcp_dsap(struct sk_buff *pdu) | 401 | static u8 nfc_llcp_dsap(struct sk_buff *pdu) |
@@ -408,13 +425,13 @@ static u8 nfc_llcp_nr(struct sk_buff *pdu) | |||
408 | 425 | ||
409 | static void nfc_llcp_set_nrns(struct nfc_llcp_sock *sock, struct sk_buff *pdu) | 426 | static void nfc_llcp_set_nrns(struct nfc_llcp_sock *sock, struct sk_buff *pdu) |
410 | { | 427 | { |
411 | pdu->data[2] = (sock->send_n << 4) | ((sock->recv_n - 1) % 16); | 428 | pdu->data[2] = (sock->send_n << 4) | (sock->recv_n % 16); |
412 | sock->send_n = (sock->send_n + 1) % 16; | 429 | sock->send_n = (sock->send_n + 1) % 16; |
413 | sock->recv_ack_n = (sock->recv_n - 1) % 16; | 430 | sock->recv_ack_n = (sock->recv_n - 1) % 16; |
414 | } | 431 | } |
415 | 432 | ||
416 | static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local, | 433 | static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local, |
417 | u8 ssap, u8 dsap) | 434 | u8 ssap, u8 dsap) |
418 | { | 435 | { |
419 | struct nfc_llcp_sock *sock, *llcp_sock, *n; | 436 | struct nfc_llcp_sock *sock, *llcp_sock, *n; |
420 | 437 | ||
@@ -438,7 +455,7 @@ static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local, | |||
438 | 455 | ||
439 | list_for_each_entry_safe(llcp_sock, n, &sock->list, list) { | 456 | list_for_each_entry_safe(llcp_sock, n, &sock->list, list) { |
440 | pr_debug("llcp_sock %p sk %p dsap %d\n", llcp_sock, | 457 | pr_debug("llcp_sock %p sk %p dsap %d\n", llcp_sock, |
441 | &llcp_sock->sk, llcp_sock->dsap); | 458 | &llcp_sock->sk, llcp_sock->dsap); |
442 | if (llcp_sock->dsap == dsap) { | 459 | if (llcp_sock->dsap == dsap) { |
443 | sock_hold(&llcp_sock->sk); | 460 | sock_hold(&llcp_sock->sk); |
444 | mutex_unlock(&local->socket_lock); | 461 | mutex_unlock(&local->socket_lock); |
@@ -482,7 +499,7 @@ static u8 *nfc_llcp_connect_sn(struct sk_buff *skb, size_t *sn_len) | |||
482 | } | 499 | } |
483 | 500 | ||
484 | static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, | 501 | static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, |
485 | struct sk_buff *skb) | 502 | struct sk_buff *skb) |
486 | { | 503 | { |
487 | struct sock *new_sk, *parent; | 504 | struct sock *new_sk, *parent; |
488 | struct nfc_llcp_sock *sock, *new_sock; | 505 | struct nfc_llcp_sock *sock, *new_sock; |
@@ -494,7 +511,7 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, | |||
494 | pr_debug("%d %d\n", dsap, ssap); | 511 | pr_debug("%d %d\n", dsap, ssap); |
495 | 512 | ||
496 | nfc_llcp_parse_tlv(local, &skb->data[LLCP_HEADER_SIZE], | 513 | nfc_llcp_parse_tlv(local, &skb->data[LLCP_HEADER_SIZE], |
497 | skb->len - LLCP_HEADER_SIZE); | 514 | skb->len - LLCP_HEADER_SIZE); |
498 | 515 | ||
499 | if (dsap != LLCP_SAP_SDP) { | 516 | if (dsap != LLCP_SAP_SDP) { |
500 | bound_sap = dsap; | 517 | bound_sap = dsap; |
@@ -513,7 +530,7 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, | |||
513 | lock_sock(&sock->sk); | 530 | lock_sock(&sock->sk); |
514 | 531 | ||
515 | if (sock->dsap == LLCP_SAP_SDP && | 532 | if (sock->dsap == LLCP_SAP_SDP && |
516 | sock->sk.sk_state == LLCP_LISTEN) | 533 | sock->sk.sk_state == LLCP_LISTEN) |
517 | goto enqueue; | 534 | goto enqueue; |
518 | } else { | 535 | } else { |
519 | u8 *sn; | 536 | u8 *sn; |
@@ -529,23 +546,23 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, | |||
529 | 546 | ||
530 | mutex_lock(&local->socket_lock); | 547 | mutex_lock(&local->socket_lock); |
531 | for (bound_sap = 0; bound_sap < LLCP_LOCAL_SAP_OFFSET; | 548 | for (bound_sap = 0; bound_sap < LLCP_LOCAL_SAP_OFFSET; |
532 | bound_sap++) { | 549 | bound_sap++) { |
533 | sock = local->sockets[bound_sap]; | 550 | sock = local->sockets[bound_sap]; |
534 | if (sock == NULL) | 551 | if (sock == NULL) |
535 | continue; | 552 | continue; |
536 | 553 | ||
537 | if (sock->service_name == NULL || | 554 | if (sock->service_name == NULL || |
538 | sock->service_name_len == 0) | 555 | sock->service_name_len == 0) |
539 | continue; | 556 | continue; |
540 | 557 | ||
541 | if (sock->service_name_len != sn_len) | 558 | if (sock->service_name_len != sn_len) |
542 | continue; | 559 | continue; |
543 | 560 | ||
544 | if (sock->dsap == LLCP_SAP_SDP && | 561 | if (sock->dsap == LLCP_SAP_SDP && |
545 | sock->sk.sk_state == LLCP_LISTEN && | 562 | sock->sk.sk_state == LLCP_LISTEN && |
546 | !memcmp(sn, sock->service_name, sn_len)) { | 563 | !memcmp(sn, sock->service_name, sn_len)) { |
547 | pr_debug("Found service name at SAP %d\n", | 564 | pr_debug("Found service name at SAP %d\n", |
548 | bound_sap); | 565 | bound_sap); |
549 | sock_hold(&sock->sk); | 566 | sock_hold(&sock->sk); |
550 | mutex_unlock(&local->socket_lock); | 567 | mutex_unlock(&local->socket_lock); |
551 | 568 | ||
@@ -570,8 +587,7 @@ enqueue: | |||
570 | goto fail; | 587 | goto fail; |
571 | } | 588 | } |
572 | 589 | ||
573 | new_sk = nfc_llcp_sock_alloc(NULL, parent->sk_type, | 590 | new_sk = nfc_llcp_sock_alloc(NULL, parent->sk_type, GFP_ATOMIC); |
574 | GFP_ATOMIC); | ||
575 | if (new_sk == NULL) { | 591 | if (new_sk == NULL) { |
576 | reason = LLCP_DM_REJ; | 592 | reason = LLCP_DM_REJ; |
577 | release_sock(&sock->sk); | 593 | release_sock(&sock->sk); |
@@ -616,8 +632,39 @@ fail: | |||
616 | 632 | ||
617 | } | 633 | } |
618 | 634 | ||
635 | int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock) | ||
636 | { | ||
637 | int nr_frames = 0; | ||
638 | struct nfc_llcp_local *local = sock->local; | ||
639 | |||
640 | pr_debug("Remote ready %d tx queue len %d remote rw %d", | ||
641 | sock->remote_ready, skb_queue_len(&sock->tx_pending_queue), | ||
642 | local->remote_rw); | ||
643 | |||
644 | /* Try to queue some I frames for transmission */ | ||
645 | while (sock->remote_ready && | ||
646 | skb_queue_len(&sock->tx_pending_queue) < local->remote_rw) { | ||
647 | struct sk_buff *pdu, *pending_pdu; | ||
648 | |||
649 | pdu = skb_dequeue(&sock->tx_queue); | ||
650 | if (pdu == NULL) | ||
651 | break; | ||
652 | |||
653 | /* Update N(S)/N(R) */ | ||
654 | nfc_llcp_set_nrns(sock, pdu); | ||
655 | |||
656 | pending_pdu = skb_clone(pdu, GFP_KERNEL); | ||
657 | |||
658 | skb_queue_tail(&local->tx_queue, pdu); | ||
659 | skb_queue_tail(&sock->tx_pending_queue, pending_pdu); | ||
660 | nr_frames++; | ||
661 | } | ||
662 | |||
663 | return nr_frames; | ||
664 | } | ||
665 | |||
619 | static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local, | 666 | static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local, |
620 | struct sk_buff *skb) | 667 | struct sk_buff *skb) |
621 | { | 668 | { |
622 | struct nfc_llcp_sock *llcp_sock; | 669 | struct nfc_llcp_sock *llcp_sock; |
623 | struct sock *sk; | 670 | struct sock *sk; |
@@ -644,15 +691,15 @@ static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local, | |||
644 | nfc_llcp_sock_put(llcp_sock); | 691 | nfc_llcp_sock_put(llcp_sock); |
645 | } | 692 | } |
646 | 693 | ||
647 | if (ns == llcp_sock->recv_n) | ||
648 | llcp_sock->recv_n = (llcp_sock->recv_n + 1) % 16; | ||
649 | else | ||
650 | pr_err("Received out of sequence I PDU\n"); | ||
651 | |||
652 | /* Pass the payload upstream */ | 694 | /* Pass the payload upstream */ |
653 | if (ptype == LLCP_PDU_I) { | 695 | if (ptype == LLCP_PDU_I) { |
654 | pr_debug("I frame, queueing on %p\n", &llcp_sock->sk); | 696 | pr_debug("I frame, queueing on %p\n", &llcp_sock->sk); |
655 | 697 | ||
698 | if (ns == llcp_sock->recv_n) | ||
699 | llcp_sock->recv_n = (llcp_sock->recv_n + 1) % 16; | ||
700 | else | ||
701 | pr_err("Received out of sequence I PDU\n"); | ||
702 | |||
656 | skb_pull(skb, LLCP_HEADER_SIZE + LLCP_SEQUENCE_SIZE); | 703 | skb_pull(skb, LLCP_HEADER_SIZE + LLCP_SEQUENCE_SIZE); |
657 | if (sock_queue_rcv_skb(&llcp_sock->sk, skb)) { | 704 | if (sock_queue_rcv_skb(&llcp_sock->sk, skb)) { |
658 | pr_err("receive queue is full\n"); | 705 | pr_err("receive queue is full\n"); |
@@ -673,30 +720,20 @@ static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local, | |||
673 | } | 720 | } |
674 | } | 721 | } |
675 | 722 | ||
676 | /* Queue some I frames for transmission */ | 723 | if (ptype == LLCP_PDU_RR) |
677 | while (llcp_sock->remote_ready && | 724 | llcp_sock->remote_ready = true; |
678 | skb_queue_len(&llcp_sock->tx_pending_queue) <= local->remote_rw) { | 725 | else if (ptype == LLCP_PDU_RNR) |
679 | struct sk_buff *pdu, *pending_pdu; | 726 | llcp_sock->remote_ready = false; |
680 | |||
681 | pdu = skb_dequeue(&llcp_sock->tx_queue); | ||
682 | if (pdu == NULL) | ||
683 | break; | ||
684 | |||
685 | /* Update N(S)/N(R) */ | ||
686 | nfc_llcp_set_nrns(llcp_sock, pdu); | ||
687 | 727 | ||
688 | pending_pdu = skb_clone(pdu, GFP_KERNEL); | 728 | if (nfc_llcp_queue_i_frames(llcp_sock) == 0) |
689 | 729 | nfc_llcp_send_rr(llcp_sock); | |
690 | skb_queue_tail(&local->tx_queue, pdu); | ||
691 | skb_queue_tail(&llcp_sock->tx_pending_queue, pending_pdu); | ||
692 | } | ||
693 | 730 | ||
694 | release_sock(sk); | 731 | release_sock(sk); |
695 | nfc_llcp_sock_put(llcp_sock); | 732 | nfc_llcp_sock_put(llcp_sock); |
696 | } | 733 | } |
697 | 734 | ||
698 | static void nfc_llcp_recv_disc(struct nfc_llcp_local *local, | 735 | static void nfc_llcp_recv_disc(struct nfc_llcp_local *local, |
699 | struct sk_buff *skb) | 736 | struct sk_buff *skb) |
700 | { | 737 | { |
701 | struct nfc_llcp_sock *llcp_sock; | 738 | struct nfc_llcp_sock *llcp_sock; |
702 | struct sock *sk; | 739 | struct sock *sk; |
@@ -718,7 +755,6 @@ static void nfc_llcp_recv_disc(struct nfc_llcp_local *local, | |||
718 | nfc_llcp_sock_put(llcp_sock); | 755 | nfc_llcp_sock_put(llcp_sock); |
719 | } | 756 | } |
720 | 757 | ||
721 | |||
722 | if (sk->sk_state == LLCP_CONNECTED) { | 758 | if (sk->sk_state == LLCP_CONNECTED) { |
723 | nfc_put_device(local->dev); | 759 | nfc_put_device(local->dev); |
724 | sk->sk_state = LLCP_CLOSED; | 760 | sk->sk_state = LLCP_CLOSED; |
@@ -731,13 +767,11 @@ static void nfc_llcp_recv_disc(struct nfc_llcp_local *local, | |||
731 | nfc_llcp_sock_put(llcp_sock); | 767 | nfc_llcp_sock_put(llcp_sock); |
732 | } | 768 | } |
733 | 769 | ||
734 | static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, | 770 | static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, struct sk_buff *skb) |
735 | struct sk_buff *skb) | ||
736 | { | 771 | { |
737 | struct nfc_llcp_sock *llcp_sock; | 772 | struct nfc_llcp_sock *llcp_sock; |
738 | u8 dsap, ssap; | 773 | u8 dsap, ssap; |
739 | 774 | ||
740 | |||
741 | dsap = nfc_llcp_dsap(skb); | 775 | dsap = nfc_llcp_dsap(skb); |
742 | ssap = nfc_llcp_ssap(skb); | 776 | ssap = nfc_llcp_ssap(skb); |
743 | 777 | ||
@@ -756,7 +790,7 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, | |||
756 | llcp_sock->dsap = ssap; | 790 | llcp_sock->dsap = ssap; |
757 | 791 | ||
758 | nfc_llcp_parse_tlv(local, &skb->data[LLCP_HEADER_SIZE], | 792 | nfc_llcp_parse_tlv(local, &skb->data[LLCP_HEADER_SIZE], |
759 | skb->len - LLCP_HEADER_SIZE); | 793 | skb->len - LLCP_HEADER_SIZE); |
760 | 794 | ||
761 | nfc_llcp_sock_put(llcp_sock); | 795 | nfc_llcp_sock_put(llcp_sock); |
762 | } | 796 | } |
@@ -764,7 +798,7 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, | |||
764 | static void nfc_llcp_rx_work(struct work_struct *work) | 798 | static void nfc_llcp_rx_work(struct work_struct *work) |
765 | { | 799 | { |
766 | struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, | 800 | struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, |
767 | rx_work); | 801 | rx_work); |
768 | u8 dsap, ssap, ptype; | 802 | u8 dsap, ssap, ptype; |
769 | struct sk_buff *skb; | 803 | struct sk_buff *skb; |
770 | 804 | ||
@@ -802,6 +836,7 @@ static void nfc_llcp_rx_work(struct work_struct *work) | |||
802 | 836 | ||
803 | case LLCP_PDU_I: | 837 | case LLCP_PDU_I: |
804 | case LLCP_PDU_RR: | 838 | case LLCP_PDU_RR: |
839 | case LLCP_PDU_RNR: | ||
805 | pr_debug("I frame\n"); | 840 | pr_debug("I frame\n"); |
806 | nfc_llcp_recv_hdlc(local, skb); | 841 | nfc_llcp_recv_hdlc(local, skb); |
807 | break; | 842 | break; |
@@ -821,7 +856,7 @@ void nfc_llcp_recv(void *data, struct sk_buff *skb, int err) | |||
821 | 856 | ||
822 | pr_debug("Received an LLCP PDU\n"); | 857 | pr_debug("Received an LLCP PDU\n"); |
823 | if (err < 0) { | 858 | if (err < 0) { |
824 | pr_err("err %d", err); | 859 | pr_err("err %d\n", err); |
825 | return; | 860 | return; |
826 | } | 861 | } |
827 | 862 | ||
@@ -840,6 +875,8 @@ void nfc_llcp_mac_is_down(struct nfc_dev *dev) | |||
840 | if (local == NULL) | 875 | if (local == NULL) |
841 | return; | 876 | return; |
842 | 877 | ||
878 | nfc_llcp_clear_sdp(local); | ||
879 | |||
843 | /* Close and purge all existing sockets */ | 880 | /* Close and purge all existing sockets */ |
844 | nfc_llcp_socket_release(local); | 881 | nfc_llcp_socket_release(local); |
845 | } | 882 | } |
@@ -865,7 +902,7 @@ void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx, | |||
865 | queue_work(local->tx_wq, &local->tx_work); | 902 | queue_work(local->tx_wq, &local->tx_work); |
866 | } else { | 903 | } else { |
867 | mod_timer(&local->link_timer, | 904 | mod_timer(&local->link_timer, |
868 | jiffies + msecs_to_jiffies(local->remote_lto)); | 905 | jiffies + msecs_to_jiffies(local->remote_lto)); |
869 | } | 906 | } |
870 | } | 907 | } |
871 | 908 | ||
@@ -891,8 +928,10 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) | |||
891 | skb_queue_head_init(&local->tx_queue); | 928 | skb_queue_head_init(&local->tx_queue); |
892 | INIT_WORK(&local->tx_work, nfc_llcp_tx_work); | 929 | INIT_WORK(&local->tx_work, nfc_llcp_tx_work); |
893 | snprintf(name, sizeof(name), "%s_llcp_tx_wq", dev_name(dev)); | 930 | snprintf(name, sizeof(name), "%s_llcp_tx_wq", dev_name(dev)); |
894 | local->tx_wq = alloc_workqueue(name, | 931 | local->tx_wq = |
895 | WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM, 1); | 932 | alloc_workqueue(name, |
933 | WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM, | ||
934 | 1); | ||
896 | if (local->tx_wq == NULL) { | 935 | if (local->tx_wq == NULL) { |
897 | err = -ENOMEM; | 936 | err = -ENOMEM; |
898 | goto err_local; | 937 | goto err_local; |
@@ -901,8 +940,10 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) | |||
901 | local->rx_pending = NULL; | 940 | local->rx_pending = NULL; |
902 | INIT_WORK(&local->rx_work, nfc_llcp_rx_work); | 941 | INIT_WORK(&local->rx_work, nfc_llcp_rx_work); |
903 | snprintf(name, sizeof(name), "%s_llcp_rx_wq", dev_name(dev)); | 942 | snprintf(name, sizeof(name), "%s_llcp_rx_wq", dev_name(dev)); |
904 | local->rx_wq = alloc_workqueue(name, | 943 | local->rx_wq = |
905 | WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM, 1); | 944 | alloc_workqueue(name, |
945 | WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM, | ||
946 | 1); | ||
906 | if (local->rx_wq == NULL) { | 947 | if (local->rx_wq == NULL) { |
907 | err = -ENOMEM; | 948 | err = -ENOMEM; |
908 | goto err_tx_wq; | 949 | goto err_tx_wq; |
@@ -910,8 +951,10 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) | |||
910 | 951 | ||
911 | INIT_WORK(&local->timeout_work, nfc_llcp_timeout_work); | 952 | INIT_WORK(&local->timeout_work, nfc_llcp_timeout_work); |
912 | snprintf(name, sizeof(name), "%s_llcp_timeout_wq", dev_name(dev)); | 953 | snprintf(name, sizeof(name), "%s_llcp_timeout_wq", dev_name(dev)); |
913 | local->timeout_wq = alloc_workqueue(name, | 954 | local->timeout_wq = |
914 | WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM, 1); | 955 | alloc_workqueue(name, |
956 | WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM, | ||
957 | 1); | ||
915 | if (local->timeout_wq == NULL) { | 958 | if (local->timeout_wq == NULL) { |
916 | err = -ENOMEM; | 959 | err = -ENOMEM; |
917 | goto err_rx_wq; | 960 | goto err_rx_wq; |
diff --git a/net/nfc/llcp/llcp.h b/net/nfc/llcp/llcp.h index 0ad2e3361584..50680ce5ae43 100644 --- a/net/nfc/llcp/llcp.h +++ b/net/nfc/llcp/llcp.h | |||
@@ -28,6 +28,10 @@ enum llcp_state { | |||
28 | #define LLCP_DEFAULT_RW 1 | 28 | #define LLCP_DEFAULT_RW 1 |
29 | #define LLCP_DEFAULT_MIU 128 | 29 | #define LLCP_DEFAULT_MIU 128 |
30 | 30 | ||
31 | #define LLCP_MAX_LTO 0xff | ||
32 | #define LLCP_MAX_RW 15 | ||
33 | #define LLCP_MAX_MIUX 0x7ff | ||
34 | |||
31 | #define LLCP_WKS_NUM_SAP 16 | 35 | #define LLCP_WKS_NUM_SAP 16 |
32 | #define LLCP_SDP_NUM_SAP 16 | 36 | #define LLCP_SDP_NUM_SAP 16 |
33 | #define LLCP_LOCAL_NUM_SAP 32 | 37 | #define LLCP_LOCAL_NUM_SAP 32 |
@@ -162,9 +166,10 @@ struct nfc_llcp_sock { | |||
162 | 166 | ||
163 | struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev); | 167 | struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev); |
164 | u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local, | 168 | u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local, |
165 | struct nfc_llcp_sock *sock); | 169 | struct nfc_llcp_sock *sock); |
166 | u8 nfc_llcp_get_local_ssap(struct nfc_llcp_local *local); | 170 | u8 nfc_llcp_get_local_ssap(struct nfc_llcp_local *local); |
167 | void nfc_llcp_put_ssap(struct nfc_llcp_local *local, u8 ssap); | 171 | void nfc_llcp_put_ssap(struct nfc_llcp_local *local, u8 ssap); |
172 | int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock); | ||
168 | 173 | ||
169 | /* Sock API */ | 174 | /* Sock API */ |
170 | struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp); | 175 | struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp); |
@@ -175,7 +180,7 @@ struct sock *nfc_llcp_accept_dequeue(struct sock *sk, struct socket *newsock); | |||
175 | 180 | ||
176 | /* TLV API */ | 181 | /* TLV API */ |
177 | int nfc_llcp_parse_tlv(struct nfc_llcp_local *local, | 182 | int nfc_llcp_parse_tlv(struct nfc_llcp_local *local, |
178 | u8 *tlv_array, u16 tlv_array_len); | 183 | u8 *tlv_array, u16 tlv_array_len); |
179 | 184 | ||
180 | /* Commands API */ | 185 | /* Commands API */ |
181 | void nfc_llcp_recv(void *data, struct sk_buff *skb, int err); | 186 | void nfc_llcp_recv(void *data, struct sk_buff *skb, int err); |
@@ -187,6 +192,9 @@ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock); | |||
187 | int nfc_llcp_send_cc(struct nfc_llcp_sock *sock); | 192 | int nfc_llcp_send_cc(struct nfc_llcp_sock *sock); |
188 | int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason); | 193 | int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason); |
189 | int nfc_llcp_send_disconnect(struct nfc_llcp_sock *sock); | 194 | int nfc_llcp_send_disconnect(struct nfc_llcp_sock *sock); |
195 | int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock, | ||
196 | struct msghdr *msg, size_t len); | ||
197 | int nfc_llcp_send_rr(struct nfc_llcp_sock *sock); | ||
190 | 198 | ||
191 | /* Socket API */ | 199 | /* Socket API */ |
192 | int __init nfc_llcp_sock_init(void); | 200 | int __init nfc_llcp_sock_init(void); |
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c index f738ccd535f1..c13e02ebdef9 100644 --- a/net/nfc/llcp/sock.c +++ b/net/nfc/llcp/sock.c | |||
@@ -78,9 +78,11 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) | |||
78 | llcp_sock->local = local; | 78 | llcp_sock->local = local; |
79 | llcp_sock->nfc_protocol = llcp_addr.nfc_protocol; | 79 | llcp_sock->nfc_protocol = llcp_addr.nfc_protocol; |
80 | llcp_sock->service_name_len = min_t(unsigned int, | 80 | llcp_sock->service_name_len = min_t(unsigned int, |
81 | llcp_addr.service_name_len, NFC_LLCP_MAX_SERVICE_NAME); | 81 | llcp_addr.service_name_len, |
82 | NFC_LLCP_MAX_SERVICE_NAME); | ||
82 | llcp_sock->service_name = kmemdup(llcp_addr.service_name, | 83 | llcp_sock->service_name = kmemdup(llcp_addr.service_name, |
83 | llcp_sock->service_name_len, GFP_KERNEL); | 84 | llcp_sock->service_name_len, |
85 | GFP_KERNEL); | ||
84 | 86 | ||
85 | llcp_sock->ssap = nfc_llcp_get_sdp_ssap(local, llcp_sock); | 87 | llcp_sock->ssap = nfc_llcp_get_sdp_ssap(local, llcp_sock); |
86 | if (llcp_sock->ssap == LLCP_MAX_SAP) | 88 | if (llcp_sock->ssap == LLCP_MAX_SAP) |
@@ -110,7 +112,7 @@ static int llcp_sock_listen(struct socket *sock, int backlog) | |||
110 | lock_sock(sk); | 112 | lock_sock(sk); |
111 | 113 | ||
112 | if ((sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM) | 114 | if ((sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM) |
113 | || sk->sk_state != LLCP_BOUND) { | 115 | || sk->sk_state != LLCP_BOUND) { |
114 | ret = -EBADFD; | 116 | ret = -EBADFD; |
115 | goto error; | 117 | goto error; |
116 | } | 118 | } |
@@ -149,13 +151,13 @@ void nfc_llcp_accept_enqueue(struct sock *parent, struct sock *sk) | |||
149 | sock_hold(sk); | 151 | sock_hold(sk); |
150 | 152 | ||
151 | list_add_tail(&llcp_sock->accept_queue, | 153 | list_add_tail(&llcp_sock->accept_queue, |
152 | &llcp_sock_parent->accept_queue); | 154 | &llcp_sock_parent->accept_queue); |
153 | llcp_sock->parent = parent; | 155 | llcp_sock->parent = parent; |
154 | sk_acceptq_added(parent); | 156 | sk_acceptq_added(parent); |
155 | } | 157 | } |
156 | 158 | ||
157 | struct sock *nfc_llcp_accept_dequeue(struct sock *parent, | 159 | struct sock *nfc_llcp_accept_dequeue(struct sock *parent, |
158 | struct socket *newsock) | 160 | struct socket *newsock) |
159 | { | 161 | { |
160 | struct nfc_llcp_sock *lsk, *n, *llcp_parent; | 162 | struct nfc_llcp_sock *lsk, *n, *llcp_parent; |
161 | struct sock *sk; | 163 | struct sock *sk; |
@@ -163,7 +165,7 @@ struct sock *nfc_llcp_accept_dequeue(struct sock *parent, | |||
163 | llcp_parent = nfc_llcp_sock(parent); | 165 | llcp_parent = nfc_llcp_sock(parent); |
164 | 166 | ||
165 | list_for_each_entry_safe(lsk, n, &llcp_parent->accept_queue, | 167 | list_for_each_entry_safe(lsk, n, &llcp_parent->accept_queue, |
166 | accept_queue) { | 168 | accept_queue) { |
167 | sk = &lsk->sk; | 169 | sk = &lsk->sk; |
168 | lock_sock(sk); | 170 | lock_sock(sk); |
169 | 171 | ||
@@ -192,7 +194,7 @@ struct sock *nfc_llcp_accept_dequeue(struct sock *parent, | |||
192 | } | 194 | } |
193 | 195 | ||
194 | static int llcp_sock_accept(struct socket *sock, struct socket *newsock, | 196 | static int llcp_sock_accept(struct socket *sock, struct socket *newsock, |
195 | int flags) | 197 | int flags) |
196 | { | 198 | { |
197 | DECLARE_WAITQUEUE(wait, current); | 199 | DECLARE_WAITQUEUE(wait, current); |
198 | struct sock *sk = sock->sk, *new_sk; | 200 | struct sock *sk = sock->sk, *new_sk; |
@@ -248,7 +250,7 @@ error: | |||
248 | static int llcp_sock_getname(struct socket *sock, struct sockaddr *addr, | 250 | static int llcp_sock_getname(struct socket *sock, struct sockaddr *addr, |
249 | int *len, int peer) | 251 | int *len, int peer) |
250 | { | 252 | { |
251 | struct sockaddr_nfc_llcp *llcp_addr = (struct sockaddr_nfc_llcp *) addr; | 253 | struct sockaddr_nfc_llcp *llcp_addr = (struct sockaddr_nfc_llcp *)addr; |
252 | struct sock *sk = sock->sk; | 254 | struct sock *sk = sock->sk; |
253 | struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); | 255 | struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); |
254 | 256 | ||
@@ -262,7 +264,7 @@ static int llcp_sock_getname(struct socket *sock, struct sockaddr *addr, | |||
262 | llcp_addr->ssap = llcp_sock->ssap; | 264 | llcp_addr->ssap = llcp_sock->ssap; |
263 | llcp_addr->service_name_len = llcp_sock->service_name_len; | 265 | llcp_addr->service_name_len = llcp_sock->service_name_len; |
264 | memcpy(llcp_addr->service_name, llcp_sock->service_name, | 266 | memcpy(llcp_addr->service_name, llcp_sock->service_name, |
265 | llcp_addr->service_name_len); | 267 | llcp_addr->service_name_len); |
266 | 268 | ||
267 | return 0; | 269 | return 0; |
268 | } | 270 | } |
@@ -275,7 +277,7 @@ static inline unsigned int llcp_accept_poll(struct sock *parent) | |||
275 | parent_sock = nfc_llcp_sock(parent); | 277 | parent_sock = nfc_llcp_sock(parent); |
276 | 278 | ||
277 | list_for_each_entry_safe(llcp_sock, n, &parent_sock->accept_queue, | 279 | list_for_each_entry_safe(llcp_sock, n, &parent_sock->accept_queue, |
278 | accept_queue) { | 280 | accept_queue) { |
279 | sk = &llcp_sock->sk; | 281 | sk = &llcp_sock->sk; |
280 | 282 | ||
281 | if (sk->sk_state == LLCP_CONNECTED) | 283 | if (sk->sk_state == LLCP_CONNECTED) |
@@ -286,7 +288,7 @@ static inline unsigned int llcp_accept_poll(struct sock *parent) | |||
286 | } | 288 | } |
287 | 289 | ||
288 | static unsigned int llcp_sock_poll(struct file *file, struct socket *sock, | 290 | static unsigned int llcp_sock_poll(struct file *file, struct socket *sock, |
289 | poll_table *wait) | 291 | poll_table *wait) |
290 | { | 292 | { |
291 | struct sock *sk = sock->sk; | 293 | struct sock *sk = sock->sk; |
292 | unsigned int mask = 0; | 294 | unsigned int mask = 0; |
@@ -315,6 +317,7 @@ static int llcp_sock_release(struct socket *sock) | |||
315 | struct sock *sk = sock->sk; | 317 | struct sock *sk = sock->sk; |
316 | struct nfc_llcp_local *local; | 318 | struct nfc_llcp_local *local; |
317 | struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); | 319 | struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); |
320 | int err = 0; | ||
318 | 321 | ||
319 | if (!sk) | 322 | if (!sk) |
320 | return 0; | 323 | return 0; |
@@ -322,25 +325,17 @@ static int llcp_sock_release(struct socket *sock) | |||
322 | pr_debug("%p\n", sk); | 325 | pr_debug("%p\n", sk); |
323 | 326 | ||
324 | local = llcp_sock->local; | 327 | local = llcp_sock->local; |
325 | if (local == NULL) | 328 | if (local == NULL) { |
326 | return -ENODEV; | 329 | err = -ENODEV; |
330 | goto out; | ||
331 | } | ||
327 | 332 | ||
328 | mutex_lock(&local->socket_lock); | 333 | mutex_lock(&local->socket_lock); |
329 | 334 | ||
330 | if (llcp_sock == local->sockets[llcp_sock->ssap]) { | 335 | if (llcp_sock == local->sockets[llcp_sock->ssap]) |
331 | local->sockets[llcp_sock->ssap] = NULL; | 336 | local->sockets[llcp_sock->ssap] = NULL; |
332 | } else { | 337 | else |
333 | struct nfc_llcp_sock *parent, *s, *n; | 338 | list_del_init(&llcp_sock->list); |
334 | |||
335 | parent = local->sockets[llcp_sock->ssap]; | ||
336 | |||
337 | list_for_each_entry_safe(s, n, &parent->list, list) | ||
338 | if (llcp_sock == s) { | ||
339 | list_del(&s->list); | ||
340 | break; | ||
341 | } | ||
342 | |||
343 | } | ||
344 | 339 | ||
345 | mutex_unlock(&local->socket_lock); | 340 | mutex_unlock(&local->socket_lock); |
346 | 341 | ||
@@ -355,7 +350,7 @@ static int llcp_sock_release(struct socket *sock) | |||
355 | struct sock *accept_sk; | 350 | struct sock *accept_sk; |
356 | 351 | ||
357 | list_for_each_entry_safe(lsk, n, &llcp_sock->accept_queue, | 352 | list_for_each_entry_safe(lsk, n, &llcp_sock->accept_queue, |
358 | accept_queue) { | 353 | accept_queue) { |
359 | accept_sk = &lsk->sk; | 354 | accept_sk = &lsk->sk; |
360 | lock_sock(accept_sk); | 355 | lock_sock(accept_sk); |
361 | 356 | ||
@@ -364,31 +359,27 @@ static int llcp_sock_release(struct socket *sock) | |||
364 | 359 | ||
365 | release_sock(accept_sk); | 360 | release_sock(accept_sk); |
366 | 361 | ||
367 | sock_set_flag(sk, SOCK_DEAD); | ||
368 | sock_orphan(accept_sk); | 362 | sock_orphan(accept_sk); |
369 | sock_put(accept_sk); | ||
370 | } | 363 | } |
371 | } | 364 | } |
372 | 365 | ||
373 | /* Freeing the SAP */ | 366 | /* Freeing the SAP */ |
374 | if ((sk->sk_state == LLCP_CONNECTED | 367 | if ((sk->sk_state == LLCP_CONNECTED |
375 | && llcp_sock->ssap > LLCP_LOCAL_SAP_OFFSET) || | 368 | && llcp_sock->ssap > LLCP_LOCAL_SAP_OFFSET) || |
376 | sk->sk_state == LLCP_BOUND || | 369 | sk->sk_state == LLCP_BOUND || sk->sk_state == LLCP_LISTEN) |
377 | sk->sk_state == LLCP_LISTEN) | ||
378 | nfc_llcp_put_ssap(llcp_sock->local, llcp_sock->ssap); | 370 | nfc_llcp_put_ssap(llcp_sock->local, llcp_sock->ssap); |
379 | 371 | ||
380 | sock_set_flag(sk, SOCK_DEAD); | ||
381 | |||
382 | release_sock(sk); | 372 | release_sock(sk); |
383 | 373 | ||
374 | out: | ||
384 | sock_orphan(sk); | 375 | sock_orphan(sk); |
385 | sock_put(sk); | 376 | sock_put(sk); |
386 | 377 | ||
387 | return 0; | 378 | return err; |
388 | } | 379 | } |
389 | 380 | ||
390 | static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, | 381 | static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, |
391 | int len, int flags) | 382 | int len, int flags) |
392 | { | 383 | { |
393 | struct sock *sk = sock->sk; | 384 | struct sock *sk = sock->sk; |
394 | struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); | 385 | struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); |
@@ -400,7 +391,7 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, | |||
400 | pr_debug("sock %p sk %p flags 0x%x\n", sock, sk, flags); | 391 | pr_debug("sock %p sk %p flags 0x%x\n", sock, sk, flags); |
401 | 392 | ||
402 | if (!addr || len < sizeof(struct sockaddr_nfc) || | 393 | if (!addr || len < sizeof(struct sockaddr_nfc) || |
403 | addr->sa_family != AF_NFC) { | 394 | addr->sa_family != AF_NFC) { |
404 | pr_err("Invalid socket\n"); | 395 | pr_err("Invalid socket\n"); |
405 | return -EINVAL; | 396 | return -EINVAL; |
406 | } | 397 | } |
@@ -411,7 +402,7 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, | |||
411 | } | 402 | } |
412 | 403 | ||
413 | pr_debug("addr dev_idx=%u target_idx=%u protocol=%u\n", addr->dev_idx, | 404 | pr_debug("addr dev_idx=%u target_idx=%u protocol=%u\n", addr->dev_idx, |
414 | addr->target_idx, addr->nfc_protocol); | 405 | addr->target_idx, addr->nfc_protocol); |
415 | 406 | ||
416 | lock_sock(sk); | 407 | lock_sock(sk); |
417 | 408 | ||
@@ -441,7 +432,7 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, | |||
441 | device_unlock(&dev->dev); | 432 | device_unlock(&dev->dev); |
442 | 433 | ||
443 | if (local->rf_mode == NFC_RF_INITIATOR && | 434 | if (local->rf_mode == NFC_RF_INITIATOR && |
444 | addr->target_idx != local->target_idx) { | 435 | addr->target_idx != local->target_idx) { |
445 | ret = -ENOLINK; | 436 | ret = -ENOLINK; |
446 | goto put_dev; | 437 | goto put_dev; |
447 | } | 438 | } |
@@ -459,9 +450,11 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, | |||
459 | llcp_sock->dsap = LLCP_SAP_SDP; | 450 | llcp_sock->dsap = LLCP_SAP_SDP; |
460 | llcp_sock->nfc_protocol = addr->nfc_protocol; | 451 | llcp_sock->nfc_protocol = addr->nfc_protocol; |
461 | llcp_sock->service_name_len = min_t(unsigned int, | 452 | llcp_sock->service_name_len = min_t(unsigned int, |
462 | addr->service_name_len, NFC_LLCP_MAX_SERVICE_NAME); | 453 | addr->service_name_len, |
454 | NFC_LLCP_MAX_SERVICE_NAME); | ||
463 | llcp_sock->service_name = kmemdup(addr->service_name, | 455 | llcp_sock->service_name = kmemdup(addr->service_name, |
464 | llcp_sock->service_name_len, GFP_KERNEL); | 456 | llcp_sock->service_name_len, |
457 | GFP_KERNEL); | ||
465 | 458 | ||
466 | local->sockets[llcp_sock->ssap] = llcp_sock; | 459 | local->sockets[llcp_sock->ssap] = llcp_sock; |
467 | 460 | ||
@@ -482,6 +475,34 @@ error: | |||
482 | return ret; | 475 | return ret; |
483 | } | 476 | } |
484 | 477 | ||
478 | static int llcp_sock_sendmsg(struct kiocb *iocb, struct socket *sock, | ||
479 | struct msghdr *msg, size_t len) | ||
480 | { | ||
481 | struct sock *sk = sock->sk; | ||
482 | struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); | ||
483 | int ret; | ||
484 | |||
485 | pr_debug("sock %p sk %p", sock, sk); | ||
486 | |||
487 | ret = sock_error(sk); | ||
488 | if (ret) | ||
489 | return ret; | ||
490 | |||
491 | if (msg->msg_flags & MSG_OOB) | ||
492 | return -EOPNOTSUPP; | ||
493 | |||
494 | lock_sock(sk); | ||
495 | |||
496 | if (sk->sk_state != LLCP_CONNECTED) { | ||
497 | release_sock(sk); | ||
498 | return -ENOTCONN; | ||
499 | } | ||
500 | |||
501 | release_sock(sk); | ||
502 | |||
503 | return nfc_llcp_send_i_frame(llcp_sock, msg, len); | ||
504 | } | ||
505 | |||
485 | static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock, | 506 | static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock, |
486 | struct msghdr *msg, size_t len, int flags) | 507 | struct msghdr *msg, size_t len, int flags) |
487 | { | 508 | { |
@@ -496,7 +517,7 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
496 | lock_sock(sk); | 517 | lock_sock(sk); |
497 | 518 | ||
498 | if (sk->sk_state == LLCP_CLOSED && | 519 | if (sk->sk_state == LLCP_CLOSED && |
499 | skb_queue_empty(&sk->sk_receive_queue)) { | 520 | skb_queue_empty(&sk->sk_receive_queue)) { |
500 | release_sock(sk); | 521 | release_sock(sk); |
501 | return 0; | 522 | return 0; |
502 | } | 523 | } |
@@ -509,7 +530,7 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
509 | skb = skb_recv_datagram(sk, flags, noblock, &err); | 530 | skb = skb_recv_datagram(sk, flags, noblock, &err); |
510 | if (!skb) { | 531 | if (!skb) { |
511 | pr_err("Recv datagram failed state %d %d %d", | 532 | pr_err("Recv datagram failed state %d %d %d", |
512 | sk->sk_state, err, sock_error(sk)); | 533 | sk->sk_state, err, sock_error(sk)); |
513 | 534 | ||
514 | if (sk->sk_shutdown & RCV_SHUTDOWN) | 535 | if (sk->sk_shutdown & RCV_SHUTDOWN) |
515 | return 0; | 536 | return 0; |
@@ -517,7 +538,7 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
517 | return err; | 538 | return err; |
518 | } | 539 | } |
519 | 540 | ||
520 | rlen = skb->len; /* real length of skb */ | 541 | rlen = skb->len; /* real length of skb */ |
521 | copied = min_t(unsigned int, rlen, len); | 542 | copied = min_t(unsigned int, rlen, len); |
522 | 543 | ||
523 | cskb = skb; | 544 | cskb = skb; |
@@ -567,7 +588,7 @@ static const struct proto_ops llcp_sock_ops = { | |||
567 | .shutdown = sock_no_shutdown, | 588 | .shutdown = sock_no_shutdown, |
568 | .setsockopt = sock_no_setsockopt, | 589 | .setsockopt = sock_no_setsockopt, |
569 | .getsockopt = sock_no_getsockopt, | 590 | .getsockopt = sock_no_getsockopt, |
570 | .sendmsg = sock_no_sendmsg, | 591 | .sendmsg = llcp_sock_sendmsg, |
571 | .recvmsg = llcp_sock_recvmsg, | 592 | .recvmsg = llcp_sock_recvmsg, |
572 | .mmap = sock_no_mmap, | 593 | .mmap = sock_no_mmap, |
573 | }; | 594 | }; |
@@ -627,6 +648,8 @@ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp) | |||
627 | 648 | ||
628 | void nfc_llcp_sock_free(struct nfc_llcp_sock *sock) | 649 | void nfc_llcp_sock_free(struct nfc_llcp_sock *sock) |
629 | { | 650 | { |
651 | struct nfc_llcp_local *local = sock->local; | ||
652 | |||
630 | kfree(sock->service_name); | 653 | kfree(sock->service_name); |
631 | 654 | ||
632 | skb_queue_purge(&sock->tx_queue); | 655 | skb_queue_purge(&sock->tx_queue); |
@@ -635,11 +658,16 @@ void nfc_llcp_sock_free(struct nfc_llcp_sock *sock) | |||
635 | 658 | ||
636 | list_del_init(&sock->accept_queue); | 659 | list_del_init(&sock->accept_queue); |
637 | 660 | ||
661 | if (local != NULL && sock == local->sockets[sock->ssap]) | ||
662 | local->sockets[sock->ssap] = NULL; | ||
663 | else | ||
664 | list_del_init(&sock->list); | ||
665 | |||
638 | sock->parent = NULL; | 666 | sock->parent = NULL; |
639 | } | 667 | } |
640 | 668 | ||
641 | static int llcp_sock_create(struct net *net, struct socket *sock, | 669 | static int llcp_sock_create(struct net *net, struct socket *sock, |
642 | const struct nfc_protocol *nfc_proto) | 670 | const struct nfc_protocol *nfc_proto) |
643 | { | 671 | { |
644 | struct sock *sk; | 672 | struct sock *sk; |
645 | 673 | ||
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c index a47e90c7d9d1..9ec065bb9ee1 100644 --- a/net/nfc/nci/core.c +++ b/net/nfc/nci/core.c | |||
@@ -66,9 +66,8 @@ static void nci_req_cancel(struct nci_dev *ndev, int err) | |||
66 | 66 | ||
67 | /* Execute request and wait for completion. */ | 67 | /* Execute request and wait for completion. */ |
68 | static int __nci_request(struct nci_dev *ndev, | 68 | static int __nci_request(struct nci_dev *ndev, |
69 | void (*req)(struct nci_dev *ndev, unsigned long opt), | 69 | void (*req)(struct nci_dev *ndev, unsigned long opt), |
70 | unsigned long opt, | 70 | unsigned long opt, __u32 timeout) |
71 | __u32 timeout) | ||
72 | { | 71 | { |
73 | int rc = 0; | 72 | int rc = 0; |
74 | long completion_rc; | 73 | long completion_rc; |
@@ -77,9 +76,9 @@ static int __nci_request(struct nci_dev *ndev, | |||
77 | 76 | ||
78 | init_completion(&ndev->req_completion); | 77 | init_completion(&ndev->req_completion); |
79 | req(ndev, opt); | 78 | req(ndev, opt); |
80 | completion_rc = wait_for_completion_interruptible_timeout( | 79 | completion_rc = |
81 | &ndev->req_completion, | 80 | wait_for_completion_interruptible_timeout(&ndev->req_completion, |
82 | timeout); | 81 | timeout); |
83 | 82 | ||
84 | pr_debug("wait_for_completion return %ld\n", completion_rc); | 83 | pr_debug("wait_for_completion return %ld\n", completion_rc); |
85 | 84 | ||
@@ -110,8 +109,9 @@ static int __nci_request(struct nci_dev *ndev, | |||
110 | } | 109 | } |
111 | 110 | ||
112 | static inline int nci_request(struct nci_dev *ndev, | 111 | static inline int nci_request(struct nci_dev *ndev, |
113 | void (*req)(struct nci_dev *ndev, unsigned long opt), | 112 | void (*req)(struct nci_dev *ndev, |
114 | unsigned long opt, __u32 timeout) | 113 | unsigned long opt), |
114 | unsigned long opt, __u32 timeout) | ||
115 | { | 115 | { |
116 | int rc; | 116 | int rc; |
117 | 117 | ||
@@ -152,14 +152,14 @@ static void nci_init_complete_req(struct nci_dev *ndev, unsigned long opt) | |||
152 | /* by default mapping is set to NCI_RF_INTERFACE_FRAME */ | 152 | /* by default mapping is set to NCI_RF_INTERFACE_FRAME */ |
153 | for (i = 0; i < ndev->num_supported_rf_interfaces; i++) { | 153 | for (i = 0; i < ndev->num_supported_rf_interfaces; i++) { |
154 | if (ndev->supported_rf_interfaces[i] == | 154 | if (ndev->supported_rf_interfaces[i] == |
155 | NCI_RF_INTERFACE_ISO_DEP) { | 155 | NCI_RF_INTERFACE_ISO_DEP) { |
156 | cfg[*num].rf_protocol = NCI_RF_PROTOCOL_ISO_DEP; | 156 | cfg[*num].rf_protocol = NCI_RF_PROTOCOL_ISO_DEP; |
157 | cfg[*num].mode = NCI_DISC_MAP_MODE_POLL | | 157 | cfg[*num].mode = NCI_DISC_MAP_MODE_POLL | |
158 | NCI_DISC_MAP_MODE_LISTEN; | 158 | NCI_DISC_MAP_MODE_LISTEN; |
159 | cfg[*num].rf_interface = NCI_RF_INTERFACE_ISO_DEP; | 159 | cfg[*num].rf_interface = NCI_RF_INTERFACE_ISO_DEP; |
160 | (*num)++; | 160 | (*num)++; |
161 | } else if (ndev->supported_rf_interfaces[i] == | 161 | } else if (ndev->supported_rf_interfaces[i] == |
162 | NCI_RF_INTERFACE_NFC_DEP) { | 162 | NCI_RF_INTERFACE_NFC_DEP) { |
163 | cfg[*num].rf_protocol = NCI_RF_PROTOCOL_NFC_DEP; | 163 | cfg[*num].rf_protocol = NCI_RF_PROTOCOL_NFC_DEP; |
164 | cfg[*num].mode = NCI_DISC_MAP_MODE_POLL | | 164 | cfg[*num].mode = NCI_DISC_MAP_MODE_POLL | |
165 | NCI_DISC_MAP_MODE_LISTEN; | 165 | NCI_DISC_MAP_MODE_LISTEN; |
@@ -172,8 +172,7 @@ static void nci_init_complete_req(struct nci_dev *ndev, unsigned long opt) | |||
172 | } | 172 | } |
173 | 173 | ||
174 | nci_send_cmd(ndev, NCI_OP_RF_DISCOVER_MAP_CMD, | 174 | nci_send_cmd(ndev, NCI_OP_RF_DISCOVER_MAP_CMD, |
175 | (1 + ((*num)*sizeof(struct disc_map_config))), | 175 | (1 + ((*num) * sizeof(struct disc_map_config))), &cmd); |
176 | &cmd); | ||
177 | } | 176 | } |
178 | 177 | ||
179 | static void nci_rf_discover_req(struct nci_dev *ndev, unsigned long opt) | 178 | static void nci_rf_discover_req(struct nci_dev *ndev, unsigned long opt) |
@@ -184,36 +183,36 @@ static void nci_rf_discover_req(struct nci_dev *ndev, unsigned long opt) | |||
184 | cmd.num_disc_configs = 0; | 183 | cmd.num_disc_configs = 0; |
185 | 184 | ||
186 | if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) && | 185 | if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) && |
187 | (protocols & NFC_PROTO_JEWEL_MASK | 186 | (protocols & NFC_PROTO_JEWEL_MASK |
188 | || protocols & NFC_PROTO_MIFARE_MASK | 187 | || protocols & NFC_PROTO_MIFARE_MASK |
189 | || protocols & NFC_PROTO_ISO14443_MASK | 188 | || protocols & NFC_PROTO_ISO14443_MASK |
190 | || protocols & NFC_PROTO_NFC_DEP_MASK)) { | 189 | || protocols & NFC_PROTO_NFC_DEP_MASK)) { |
191 | cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode = | 190 | cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode = |
192 | NCI_NFC_A_PASSIVE_POLL_MODE; | 191 | NCI_NFC_A_PASSIVE_POLL_MODE; |
193 | cmd.disc_configs[cmd.num_disc_configs].frequency = 1; | 192 | cmd.disc_configs[cmd.num_disc_configs].frequency = 1; |
194 | cmd.num_disc_configs++; | 193 | cmd.num_disc_configs++; |
195 | } | 194 | } |
196 | 195 | ||
197 | if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) && | 196 | if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) && |
198 | (protocols & NFC_PROTO_ISO14443_MASK)) { | 197 | (protocols & NFC_PROTO_ISO14443_MASK)) { |
199 | cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode = | 198 | cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode = |
200 | NCI_NFC_B_PASSIVE_POLL_MODE; | 199 | NCI_NFC_B_PASSIVE_POLL_MODE; |
201 | cmd.disc_configs[cmd.num_disc_configs].frequency = 1; | 200 | cmd.disc_configs[cmd.num_disc_configs].frequency = 1; |
202 | cmd.num_disc_configs++; | 201 | cmd.num_disc_configs++; |
203 | } | 202 | } |
204 | 203 | ||
205 | if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) && | 204 | if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) && |
206 | (protocols & NFC_PROTO_FELICA_MASK | 205 | (protocols & NFC_PROTO_FELICA_MASK |
207 | || protocols & NFC_PROTO_NFC_DEP_MASK)) { | 206 | || protocols & NFC_PROTO_NFC_DEP_MASK)) { |
208 | cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode = | 207 | cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode = |
209 | NCI_NFC_F_PASSIVE_POLL_MODE; | 208 | NCI_NFC_F_PASSIVE_POLL_MODE; |
210 | cmd.disc_configs[cmd.num_disc_configs].frequency = 1; | 209 | cmd.disc_configs[cmd.num_disc_configs].frequency = 1; |
211 | cmd.num_disc_configs++; | 210 | cmd.num_disc_configs++; |
212 | } | 211 | } |
213 | 212 | ||
214 | nci_send_cmd(ndev, NCI_OP_RF_DISCOVER_CMD, | 213 | nci_send_cmd(ndev, NCI_OP_RF_DISCOVER_CMD, |
215 | (1 + (cmd.num_disc_configs*sizeof(struct disc_config))), | 214 | (1 + (cmd.num_disc_configs * sizeof(struct disc_config))), |
216 | &cmd); | 215 | &cmd); |
217 | } | 216 | } |
218 | 217 | ||
219 | struct nci_rf_discover_select_param { | 218 | struct nci_rf_discover_select_param { |
@@ -224,7 +223,7 @@ struct nci_rf_discover_select_param { | |||
224 | static void nci_rf_discover_select_req(struct nci_dev *ndev, unsigned long opt) | 223 | static void nci_rf_discover_select_req(struct nci_dev *ndev, unsigned long opt) |
225 | { | 224 | { |
226 | struct nci_rf_discover_select_param *param = | 225 | struct nci_rf_discover_select_param *param = |
227 | (struct nci_rf_discover_select_param *)opt; | 226 | (struct nci_rf_discover_select_param *)opt; |
228 | struct nci_rf_discover_select_cmd cmd; | 227 | struct nci_rf_discover_select_cmd cmd; |
229 | 228 | ||
230 | cmd.rf_discovery_id = param->rf_discovery_id; | 229 | cmd.rf_discovery_id = param->rf_discovery_id; |
@@ -245,8 +244,7 @@ static void nci_rf_discover_select_req(struct nci_dev *ndev, unsigned long opt) | |||
245 | } | 244 | } |
246 | 245 | ||
247 | nci_send_cmd(ndev, NCI_OP_RF_DISCOVER_SELECT_CMD, | 246 | nci_send_cmd(ndev, NCI_OP_RF_DISCOVER_SELECT_CMD, |
248 | sizeof(struct nci_rf_discover_select_cmd), | 247 | sizeof(struct nci_rf_discover_select_cmd), &cmd); |
249 | &cmd); | ||
250 | } | 248 | } |
251 | 249 | ||
252 | static void nci_rf_deactivate_req(struct nci_dev *ndev, unsigned long opt) | 250 | static void nci_rf_deactivate_req(struct nci_dev *ndev, unsigned long opt) |
@@ -256,8 +254,7 @@ static void nci_rf_deactivate_req(struct nci_dev *ndev, unsigned long opt) | |||
256 | cmd.type = NCI_DEACTIVATE_TYPE_IDLE_MODE; | 254 | cmd.type = NCI_DEACTIVATE_TYPE_IDLE_MODE; |
257 | 255 | ||
258 | nci_send_cmd(ndev, NCI_OP_RF_DEACTIVATE_CMD, | 256 | nci_send_cmd(ndev, NCI_OP_RF_DEACTIVATE_CMD, |
259 | sizeof(struct nci_rf_deactivate_cmd), | 257 | sizeof(struct nci_rf_deactivate_cmd), &cmd); |
260 | &cmd); | ||
261 | } | 258 | } |
262 | 259 | ||
263 | static int nci_open_device(struct nci_dev *ndev) | 260 | static int nci_open_device(struct nci_dev *ndev) |
@@ -281,16 +278,16 @@ static int nci_open_device(struct nci_dev *ndev) | |||
281 | set_bit(NCI_INIT, &ndev->flags); | 278 | set_bit(NCI_INIT, &ndev->flags); |
282 | 279 | ||
283 | rc = __nci_request(ndev, nci_reset_req, 0, | 280 | rc = __nci_request(ndev, nci_reset_req, 0, |
284 | msecs_to_jiffies(NCI_RESET_TIMEOUT)); | 281 | msecs_to_jiffies(NCI_RESET_TIMEOUT)); |
285 | 282 | ||
286 | if (!rc) { | 283 | if (!rc) { |
287 | rc = __nci_request(ndev, nci_init_req, 0, | 284 | rc = __nci_request(ndev, nci_init_req, 0, |
288 | msecs_to_jiffies(NCI_INIT_TIMEOUT)); | 285 | msecs_to_jiffies(NCI_INIT_TIMEOUT)); |
289 | } | 286 | } |
290 | 287 | ||
291 | if (!rc) { | 288 | if (!rc) { |
292 | rc = __nci_request(ndev, nci_init_complete_req, 0, | 289 | rc = __nci_request(ndev, nci_init_complete_req, 0, |
293 | msecs_to_jiffies(NCI_INIT_TIMEOUT)); | 290 | msecs_to_jiffies(NCI_INIT_TIMEOUT)); |
294 | } | 291 | } |
295 | 292 | ||
296 | clear_bit(NCI_INIT, &ndev->flags); | 293 | clear_bit(NCI_INIT, &ndev->flags); |
@@ -340,7 +337,7 @@ static int nci_close_device(struct nci_dev *ndev) | |||
340 | 337 | ||
341 | set_bit(NCI_INIT, &ndev->flags); | 338 | set_bit(NCI_INIT, &ndev->flags); |
342 | __nci_request(ndev, nci_reset_req, 0, | 339 | __nci_request(ndev, nci_reset_req, 0, |
343 | msecs_to_jiffies(NCI_RESET_TIMEOUT)); | 340 | msecs_to_jiffies(NCI_RESET_TIMEOUT)); |
344 | clear_bit(NCI_INIT, &ndev->flags); | 341 | clear_bit(NCI_INIT, &ndev->flags); |
345 | 342 | ||
346 | /* Flush cmd wq */ | 343 | /* Flush cmd wq */ |
@@ -396,7 +393,7 @@ static int nci_start_poll(struct nfc_dev *nfc_dev, __u32 protocols) | |||
396 | int rc; | 393 | int rc; |
397 | 394 | ||
398 | if ((atomic_read(&ndev->state) == NCI_DISCOVERY) || | 395 | if ((atomic_read(&ndev->state) == NCI_DISCOVERY) || |
399 | (atomic_read(&ndev->state) == NCI_W4_ALL_DISCOVERIES)) { | 396 | (atomic_read(&ndev->state) == NCI_W4_ALL_DISCOVERIES)) { |
400 | pr_err("unable to start poll, since poll is already active\n"); | 397 | pr_err("unable to start poll, since poll is already active\n"); |
401 | return -EBUSY; | 398 | return -EBUSY; |
402 | } | 399 | } |
@@ -407,17 +404,17 @@ static int nci_start_poll(struct nfc_dev *nfc_dev, __u32 protocols) | |||
407 | } | 404 | } |
408 | 405 | ||
409 | if ((atomic_read(&ndev->state) == NCI_W4_HOST_SELECT) || | 406 | if ((atomic_read(&ndev->state) == NCI_W4_HOST_SELECT) || |
410 | (atomic_read(&ndev->state) == NCI_POLL_ACTIVE)) { | 407 | (atomic_read(&ndev->state) == NCI_POLL_ACTIVE)) { |
411 | pr_debug("target active or w4 select, implicitly deactivate\n"); | 408 | pr_debug("target active or w4 select, implicitly deactivate\n"); |
412 | 409 | ||
413 | rc = nci_request(ndev, nci_rf_deactivate_req, 0, | 410 | rc = nci_request(ndev, nci_rf_deactivate_req, 0, |
414 | msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT)); | 411 | msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT)); |
415 | if (rc) | 412 | if (rc) |
416 | return -EBUSY; | 413 | return -EBUSY; |
417 | } | 414 | } |
418 | 415 | ||
419 | rc = nci_request(ndev, nci_rf_discover_req, protocols, | 416 | rc = nci_request(ndev, nci_rf_discover_req, protocols, |
420 | msecs_to_jiffies(NCI_RF_DISC_TIMEOUT)); | 417 | msecs_to_jiffies(NCI_RF_DISC_TIMEOUT)); |
421 | 418 | ||
422 | if (!rc) | 419 | if (!rc) |
423 | ndev->poll_prots = protocols; | 420 | ndev->poll_prots = protocols; |
@@ -430,17 +427,17 @@ static void nci_stop_poll(struct nfc_dev *nfc_dev) | |||
430 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); | 427 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); |
431 | 428 | ||
432 | if ((atomic_read(&ndev->state) != NCI_DISCOVERY) && | 429 | if ((atomic_read(&ndev->state) != NCI_DISCOVERY) && |
433 | (atomic_read(&ndev->state) != NCI_W4_ALL_DISCOVERIES)) { | 430 | (atomic_read(&ndev->state) != NCI_W4_ALL_DISCOVERIES)) { |
434 | pr_err("unable to stop poll, since poll is not active\n"); | 431 | pr_err("unable to stop poll, since poll is not active\n"); |
435 | return; | 432 | return; |
436 | } | 433 | } |
437 | 434 | ||
438 | nci_request(ndev, nci_rf_deactivate_req, 0, | 435 | nci_request(ndev, nci_rf_deactivate_req, 0, |
439 | msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT)); | 436 | msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT)); |
440 | } | 437 | } |
441 | 438 | ||
442 | static int nci_activate_target(struct nfc_dev *nfc_dev, __u32 target_idx, | 439 | static int nci_activate_target(struct nfc_dev *nfc_dev, __u32 target_idx, |
443 | __u32 protocol) | 440 | __u32 protocol) |
444 | { | 441 | { |
445 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); | 442 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); |
446 | struct nci_rf_discover_select_param param; | 443 | struct nci_rf_discover_select_param param; |
@@ -451,7 +448,7 @@ static int nci_activate_target(struct nfc_dev *nfc_dev, __u32 target_idx, | |||
451 | pr_debug("target_idx %d, protocol 0x%x\n", target_idx, protocol); | 448 | pr_debug("target_idx %d, protocol 0x%x\n", target_idx, protocol); |
452 | 449 | ||
453 | if ((atomic_read(&ndev->state) != NCI_W4_HOST_SELECT) && | 450 | if ((atomic_read(&ndev->state) != NCI_W4_HOST_SELECT) && |
454 | (atomic_read(&ndev->state) != NCI_POLL_ACTIVE)) { | 451 | (atomic_read(&ndev->state) != NCI_POLL_ACTIVE)) { |
455 | pr_err("there is no available target to activate\n"); | 452 | pr_err("there is no available target to activate\n"); |
456 | return -EINVAL; | 453 | return -EINVAL; |
457 | } | 454 | } |
@@ -494,8 +491,8 @@ static int nci_activate_target(struct nfc_dev *nfc_dev, __u32 target_idx, | |||
494 | param.rf_protocol = NCI_RF_PROTOCOL_NFC_DEP; | 491 | param.rf_protocol = NCI_RF_PROTOCOL_NFC_DEP; |
495 | 492 | ||
496 | rc = nci_request(ndev, nci_rf_discover_select_req, | 493 | rc = nci_request(ndev, nci_rf_discover_select_req, |
497 | (unsigned long)¶m, | 494 | (unsigned long)¶m, |
498 | msecs_to_jiffies(NCI_RF_DISC_SELECT_TIMEOUT)); | 495 | msecs_to_jiffies(NCI_RF_DISC_SELECT_TIMEOUT)); |
499 | } | 496 | } |
500 | 497 | ||
501 | if (!rc) | 498 | if (!rc) |
@@ -519,14 +516,13 @@ static void nci_deactivate_target(struct nfc_dev *nfc_dev, __u32 target_idx) | |||
519 | 516 | ||
520 | if (atomic_read(&ndev->state) == NCI_POLL_ACTIVE) { | 517 | if (atomic_read(&ndev->state) == NCI_POLL_ACTIVE) { |
521 | nci_request(ndev, nci_rf_deactivate_req, 0, | 518 | nci_request(ndev, nci_rf_deactivate_req, 0, |
522 | msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT)); | 519 | msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT)); |
523 | } | 520 | } |
524 | } | 521 | } |
525 | 522 | ||
526 | static int nci_data_exchange(struct nfc_dev *nfc_dev, __u32 target_idx, | 523 | static int nci_data_exchange(struct nfc_dev *nfc_dev, __u32 target_idx, |
527 | struct sk_buff *skb, | 524 | struct sk_buff *skb, |
528 | data_exchange_cb_t cb, | 525 | data_exchange_cb_t cb, void *cb_context) |
529 | void *cb_context) | ||
530 | { | 526 | { |
531 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); | 527 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); |
532 | int rc; | 528 | int rc; |
@@ -571,9 +567,8 @@ static struct nfc_ops nci_nfc_ops = { | |||
571 | * @supported_protocols: NFC protocols supported by the device | 567 | * @supported_protocols: NFC protocols supported by the device |
572 | */ | 568 | */ |
573 | struct nci_dev *nci_allocate_device(struct nci_ops *ops, | 569 | struct nci_dev *nci_allocate_device(struct nci_ops *ops, |
574 | __u32 supported_protocols, | 570 | __u32 supported_protocols, |
575 | int tx_headroom, | 571 | int tx_headroom, int tx_tailroom) |
576 | int tx_tailroom) | ||
577 | { | 572 | { |
578 | struct nci_dev *ndev; | 573 | struct nci_dev *ndev; |
579 | 574 | ||
@@ -594,9 +589,9 @@ struct nci_dev *nci_allocate_device(struct nci_ops *ops, | |||
594 | ndev->tx_tailroom = tx_tailroom; | 589 | ndev->tx_tailroom = tx_tailroom; |
595 | 590 | ||
596 | ndev->nfc_dev = nfc_allocate_device(&nci_nfc_ops, | 591 | ndev->nfc_dev = nfc_allocate_device(&nci_nfc_ops, |
597 | supported_protocols, | 592 | supported_protocols, |
598 | tx_headroom + NCI_DATA_HDR_SIZE, | 593 | tx_headroom + NCI_DATA_HDR_SIZE, |
599 | tx_tailroom); | 594 | tx_tailroom); |
600 | if (!ndev->nfc_dev) | 595 | if (!ndev->nfc_dev) |
601 | goto free_exit; | 596 | goto free_exit; |
602 | 597 | ||
@@ -668,9 +663,9 @@ int nci_register_device(struct nci_dev *ndev) | |||
668 | skb_queue_head_init(&ndev->tx_q); | 663 | skb_queue_head_init(&ndev->tx_q); |
669 | 664 | ||
670 | setup_timer(&ndev->cmd_timer, nci_cmd_timer, | 665 | setup_timer(&ndev->cmd_timer, nci_cmd_timer, |
671 | (unsigned long) ndev); | 666 | (unsigned long) ndev); |
672 | setup_timer(&ndev->data_timer, nci_data_timer, | 667 | setup_timer(&ndev->data_timer, nci_data_timer, |
673 | (unsigned long) ndev); | 668 | (unsigned long) ndev); |
674 | 669 | ||
675 | mutex_init(&ndev->req_lock); | 670 | mutex_init(&ndev->req_lock); |
676 | 671 | ||
@@ -719,7 +714,7 @@ int nci_recv_frame(struct sk_buff *skb) | |||
719 | pr_debug("len %d\n", skb->len); | 714 | pr_debug("len %d\n", skb->len); |
720 | 715 | ||
721 | if (!ndev || (!test_bit(NCI_UP, &ndev->flags) | 716 | if (!ndev || (!test_bit(NCI_UP, &ndev->flags) |
722 | && !test_bit(NCI_INIT, &ndev->flags))) { | 717 | && !test_bit(NCI_INIT, &ndev->flags))) { |
723 | kfree_skb(skb); | 718 | kfree_skb(skb); |
724 | return -ENXIO; | 719 | return -ENXIO; |
725 | } | 720 | } |
@@ -799,7 +794,7 @@ static void nci_tx_work(struct work_struct *work) | |||
799 | 794 | ||
800 | /* Check if data flow control is used */ | 795 | /* Check if data flow control is used */ |
801 | if (atomic_read(&ndev->credits_cnt) != | 796 | if (atomic_read(&ndev->credits_cnt) != |
802 | NCI_DATA_FLOW_CONTROL_NOT_USED) | 797 | NCI_DATA_FLOW_CONTROL_NOT_USED) |
803 | atomic_dec(&ndev->credits_cnt); | 798 | atomic_dec(&ndev->credits_cnt); |
804 | 799 | ||
805 | pr_debug("NCI TX: MT=data, PBF=%d, conn_id=%d, plen=%d\n", | 800 | pr_debug("NCI TX: MT=data, PBF=%d, conn_id=%d, plen=%d\n", |
@@ -810,7 +805,7 @@ static void nci_tx_work(struct work_struct *work) | |||
810 | nci_send_frame(skb); | 805 | nci_send_frame(skb); |
811 | 806 | ||
812 | mod_timer(&ndev->data_timer, | 807 | mod_timer(&ndev->data_timer, |
813 | jiffies + msecs_to_jiffies(NCI_DATA_TIMEOUT)); | 808 | jiffies + msecs_to_jiffies(NCI_DATA_TIMEOUT)); |
814 | } | 809 | } |
815 | } | 810 | } |
816 | 811 | ||
@@ -879,6 +874,6 @@ static void nci_cmd_work(struct work_struct *work) | |||
879 | nci_send_frame(skb); | 874 | nci_send_frame(skb); |
880 | 875 | ||
881 | mod_timer(&ndev->cmd_timer, | 876 | mod_timer(&ndev->cmd_timer, |
882 | jiffies + msecs_to_jiffies(NCI_CMD_TIMEOUT)); | 877 | jiffies + msecs_to_jiffies(NCI_CMD_TIMEOUT)); |
883 | } | 878 | } |
884 | } | 879 | } |
diff --git a/net/nfc/nci/data.c b/net/nfc/nci/data.c index 7880ae924d5e..a0bc326308a5 100644 --- a/net/nfc/nci/data.c +++ b/net/nfc/nci/data.c | |||
@@ -35,8 +35,7 @@ | |||
35 | #include <linux/nfc.h> | 35 | #include <linux/nfc.h> |
36 | 36 | ||
37 | /* Complete data exchange transaction and forward skb to nfc core */ | 37 | /* Complete data exchange transaction and forward skb to nfc core */ |
38 | void nci_data_exchange_complete(struct nci_dev *ndev, | 38 | void nci_data_exchange_complete(struct nci_dev *ndev, struct sk_buff *skb, |
39 | struct sk_buff *skb, | ||
40 | int err) | 39 | int err) |
41 | { | 40 | { |
42 | data_exchange_cb_t cb = ndev->data_exchange_cb; | 41 | data_exchange_cb_t cb = ndev->data_exchange_cb; |
@@ -67,9 +66,9 @@ void nci_data_exchange_complete(struct nci_dev *ndev, | |||
67 | /* ----------------- NCI TX Data ----------------- */ | 66 | /* ----------------- NCI TX Data ----------------- */ |
68 | 67 | ||
69 | static inline void nci_push_data_hdr(struct nci_dev *ndev, | 68 | static inline void nci_push_data_hdr(struct nci_dev *ndev, |
70 | __u8 conn_id, | 69 | __u8 conn_id, |
71 | struct sk_buff *skb, | 70 | struct sk_buff *skb, |
72 | __u8 pbf) | 71 | __u8 pbf) |
73 | { | 72 | { |
74 | struct nci_data_hdr *hdr; | 73 | struct nci_data_hdr *hdr; |
75 | int plen = skb->len; | 74 | int plen = skb->len; |
@@ -86,8 +85,8 @@ static inline void nci_push_data_hdr(struct nci_dev *ndev, | |||
86 | } | 85 | } |
87 | 86 | ||
88 | static int nci_queue_tx_data_frags(struct nci_dev *ndev, | 87 | static int nci_queue_tx_data_frags(struct nci_dev *ndev, |
89 | __u8 conn_id, | 88 | __u8 conn_id, |
90 | struct sk_buff *skb) { | 89 | struct sk_buff *skb) { |
91 | int total_len = skb->len; | 90 | int total_len = skb->len; |
92 | unsigned char *data = skb->data; | 91 | unsigned char *data = skb->data; |
93 | unsigned long flags; | 92 | unsigned long flags; |
@@ -105,8 +104,8 @@ static int nci_queue_tx_data_frags(struct nci_dev *ndev, | |||
105 | min_t(int, total_len, ndev->max_data_pkt_payload_size); | 104 | min_t(int, total_len, ndev->max_data_pkt_payload_size); |
106 | 105 | ||
107 | skb_frag = nci_skb_alloc(ndev, | 106 | skb_frag = nci_skb_alloc(ndev, |
108 | (NCI_DATA_HDR_SIZE + frag_len), | 107 | (NCI_DATA_HDR_SIZE + frag_len), |
109 | GFP_KERNEL); | 108 | GFP_KERNEL); |
110 | if (skb_frag == NULL) { | 109 | if (skb_frag == NULL) { |
111 | rc = -ENOMEM; | 110 | rc = -ENOMEM; |
112 | goto free_exit; | 111 | goto free_exit; |
@@ -118,7 +117,8 @@ static int nci_queue_tx_data_frags(struct nci_dev *ndev, | |||
118 | 117 | ||
119 | /* second, set the header */ | 118 | /* second, set the header */ |
120 | nci_push_data_hdr(ndev, conn_id, skb_frag, | 119 | nci_push_data_hdr(ndev, conn_id, skb_frag, |
121 | ((total_len == frag_len) ? (NCI_PBF_LAST) : (NCI_PBF_CONT))); | 120 | ((total_len == frag_len) ? |
121 | (NCI_PBF_LAST) : (NCI_PBF_CONT))); | ||
122 | 122 | ||
123 | __skb_queue_tail(&frags_q, skb_frag); | 123 | __skb_queue_tail(&frags_q, skb_frag); |
124 | 124 | ||
@@ -186,8 +186,8 @@ exit: | |||
186 | /* ----------------- NCI RX Data ----------------- */ | 186 | /* ----------------- NCI RX Data ----------------- */ |
187 | 187 | ||
188 | static void nci_add_rx_data_frag(struct nci_dev *ndev, | 188 | static void nci_add_rx_data_frag(struct nci_dev *ndev, |
189 | struct sk_buff *skb, | 189 | struct sk_buff *skb, |
190 | __u8 pbf) | 190 | __u8 pbf) |
191 | { | 191 | { |
192 | int reassembly_len; | 192 | int reassembly_len; |
193 | int err = 0; | 193 | int err = 0; |
@@ -211,8 +211,8 @@ static void nci_add_rx_data_frag(struct nci_dev *ndev, | |||
211 | 211 | ||
212 | /* second, combine the two fragments */ | 212 | /* second, combine the two fragments */ |
213 | memcpy(skb_push(skb, reassembly_len), | 213 | memcpy(skb_push(skb, reassembly_len), |
214 | ndev->rx_data_reassembly->data, | 214 | ndev->rx_data_reassembly->data, |
215 | reassembly_len); | 215 | reassembly_len); |
216 | 216 | ||
217 | /* third, free old reassembly */ | 217 | /* third, free old reassembly */ |
218 | kfree_skb(ndev->rx_data_reassembly); | 218 | kfree_skb(ndev->rx_data_reassembly); |
diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c index 03e7b4626a3e..2e3dee42196d 100644 --- a/net/nfc/nci/ntf.c +++ b/net/nfc/nci/ntf.c | |||
@@ -40,7 +40,7 @@ | |||
40 | /* Handle NCI Notification packets */ | 40 | /* Handle NCI Notification packets */ |
41 | 41 | ||
42 | static void nci_core_conn_credits_ntf_packet(struct nci_dev *ndev, | 42 | static void nci_core_conn_credits_ntf_packet(struct nci_dev *ndev, |
43 | struct sk_buff *skb) | 43 | struct sk_buff *skb) |
44 | { | 44 | { |
45 | struct nci_core_conn_credit_ntf *ntf = (void *) skb->data; | 45 | struct nci_core_conn_credit_ntf *ntf = (void *) skb->data; |
46 | int i; | 46 | int i; |
@@ -62,7 +62,7 @@ static void nci_core_conn_credits_ntf_packet(struct nci_dev *ndev, | |||
62 | if (ntf->conn_entries[i].conn_id == NCI_STATIC_RF_CONN_ID) { | 62 | if (ntf->conn_entries[i].conn_id == NCI_STATIC_RF_CONN_ID) { |
63 | /* found static rf connection */ | 63 | /* found static rf connection */ |
64 | atomic_add(ntf->conn_entries[i].credits, | 64 | atomic_add(ntf->conn_entries[i].credits, |
65 | &ndev->credits_cnt); | 65 | &ndev->credits_cnt); |
66 | } | 66 | } |
67 | } | 67 | } |
68 | 68 | ||
@@ -72,7 +72,7 @@ static void nci_core_conn_credits_ntf_packet(struct nci_dev *ndev, | |||
72 | } | 72 | } |
73 | 73 | ||
74 | static void nci_core_generic_error_ntf_packet(struct nci_dev *ndev, | 74 | static void nci_core_generic_error_ntf_packet(struct nci_dev *ndev, |
75 | struct sk_buff *skb) | 75 | struct sk_buff *skb) |
76 | { | 76 | { |
77 | __u8 status = skb->data[0]; | 77 | __u8 status = skb->data[0]; |
78 | 78 | ||
@@ -80,7 +80,7 @@ static void nci_core_generic_error_ntf_packet(struct nci_dev *ndev, | |||
80 | 80 | ||
81 | if (atomic_read(&ndev->state) == NCI_W4_HOST_SELECT) { | 81 | if (atomic_read(&ndev->state) == NCI_W4_HOST_SELECT) { |
82 | /* Activation failed, so complete the request | 82 | /* Activation failed, so complete the request |
83 | (the state remains the same) */ | 83 | (the state remains the same) */ |
84 | nci_req_complete(ndev, status); | 84 | nci_req_complete(ndev, status); |
85 | } | 85 | } |
86 | } | 86 | } |
@@ -101,7 +101,7 @@ static void nci_core_conn_intf_error_ntf_packet(struct nci_dev *ndev, | |||
101 | 101 | ||
102 | static __u8 *nci_extract_rf_params_nfca_passive_poll(struct nci_dev *ndev, | 102 | static __u8 *nci_extract_rf_params_nfca_passive_poll(struct nci_dev *ndev, |
103 | struct rf_tech_specific_params_nfca_poll *nfca_poll, | 103 | struct rf_tech_specific_params_nfca_poll *nfca_poll, |
104 | __u8 *data) | 104 | __u8 *data) |
105 | { | 105 | { |
106 | nfca_poll->sens_res = __le16_to_cpu(*((__u16 *)data)); | 106 | nfca_poll->sens_res = __le16_to_cpu(*((__u16 *)data)); |
107 | data += 2; | 107 | data += 2; |
@@ -128,7 +128,7 @@ static __u8 *nci_extract_rf_params_nfca_passive_poll(struct nci_dev *ndev, | |||
128 | 128 | ||
129 | static __u8 *nci_extract_rf_params_nfcb_passive_poll(struct nci_dev *ndev, | 129 | static __u8 *nci_extract_rf_params_nfcb_passive_poll(struct nci_dev *ndev, |
130 | struct rf_tech_specific_params_nfcb_poll *nfcb_poll, | 130 | struct rf_tech_specific_params_nfcb_poll *nfcb_poll, |
131 | __u8 *data) | 131 | __u8 *data) |
132 | { | 132 | { |
133 | nfcb_poll->sensb_res_len = *data++; | 133 | nfcb_poll->sensb_res_len = *data++; |
134 | 134 | ||
@@ -142,13 +142,13 @@ static __u8 *nci_extract_rf_params_nfcb_passive_poll(struct nci_dev *ndev, | |||
142 | 142 | ||
143 | static __u8 *nci_extract_rf_params_nfcf_passive_poll(struct nci_dev *ndev, | 143 | static __u8 *nci_extract_rf_params_nfcf_passive_poll(struct nci_dev *ndev, |
144 | struct rf_tech_specific_params_nfcf_poll *nfcf_poll, | 144 | struct rf_tech_specific_params_nfcf_poll *nfcf_poll, |
145 | __u8 *data) | 145 | __u8 *data) |
146 | { | 146 | { |
147 | nfcf_poll->bit_rate = *data++; | 147 | nfcf_poll->bit_rate = *data++; |
148 | nfcf_poll->sensf_res_len = *data++; | 148 | nfcf_poll->sensf_res_len = *data++; |
149 | 149 | ||
150 | pr_debug("bit_rate %d, sensf_res_len %d\n", | 150 | pr_debug("bit_rate %d, sensf_res_len %d\n", |
151 | nfcf_poll->bit_rate, nfcf_poll->sensf_res_len); | 151 | nfcf_poll->bit_rate, nfcf_poll->sensf_res_len); |
152 | 152 | ||
153 | memcpy(nfcf_poll->sensf_res, data, nfcf_poll->sensf_res_len); | 153 | memcpy(nfcf_poll->sensf_res, data, nfcf_poll->sensf_res_len); |
154 | data += nfcf_poll->sensf_res_len; | 154 | data += nfcf_poll->sensf_res_len; |
@@ -189,7 +189,7 @@ static int nci_add_new_protocol(struct nci_dev *ndev, | |||
189 | target->nfcid1_len = nfca_poll->nfcid1_len; | 189 | target->nfcid1_len = nfca_poll->nfcid1_len; |
190 | if (target->nfcid1_len > 0) { | 190 | if (target->nfcid1_len > 0) { |
191 | memcpy(target->nfcid1, nfca_poll->nfcid1, | 191 | memcpy(target->nfcid1, nfca_poll->nfcid1, |
192 | target->nfcid1_len); | 192 | target->nfcid1_len); |
193 | } | 193 | } |
194 | } else if (rf_tech_and_mode == NCI_NFC_B_PASSIVE_POLL_MODE) { | 194 | } else if (rf_tech_and_mode == NCI_NFC_B_PASSIVE_POLL_MODE) { |
195 | nfcb_poll = (struct rf_tech_specific_params_nfcb_poll *)params; | 195 | nfcb_poll = (struct rf_tech_specific_params_nfcb_poll *)params; |
@@ -197,7 +197,7 @@ static int nci_add_new_protocol(struct nci_dev *ndev, | |||
197 | target->sensb_res_len = nfcb_poll->sensb_res_len; | 197 | target->sensb_res_len = nfcb_poll->sensb_res_len; |
198 | if (target->sensb_res_len > 0) { | 198 | if (target->sensb_res_len > 0) { |
199 | memcpy(target->sensb_res, nfcb_poll->sensb_res, | 199 | memcpy(target->sensb_res, nfcb_poll->sensb_res, |
200 | target->sensb_res_len); | 200 | target->sensb_res_len); |
201 | } | 201 | } |
202 | } else if (rf_tech_and_mode == NCI_NFC_F_PASSIVE_POLL_MODE) { | 202 | } else if (rf_tech_and_mode == NCI_NFC_F_PASSIVE_POLL_MODE) { |
203 | nfcf_poll = (struct rf_tech_specific_params_nfcf_poll *)params; | 203 | nfcf_poll = (struct rf_tech_specific_params_nfcf_poll *)params; |
@@ -205,7 +205,7 @@ static int nci_add_new_protocol(struct nci_dev *ndev, | |||
205 | target->sensf_res_len = nfcf_poll->sensf_res_len; | 205 | target->sensf_res_len = nfcf_poll->sensf_res_len; |
206 | if (target->sensf_res_len > 0) { | 206 | if (target->sensf_res_len > 0) { |
207 | memcpy(target->sensf_res, nfcf_poll->sensf_res, | 207 | memcpy(target->sensf_res, nfcf_poll->sensf_res, |
208 | target->sensf_res_len); | 208 | target->sensf_res_len); |
209 | } | 209 | } |
210 | } else { | 210 | } else { |
211 | pr_err("unsupported rf_tech_and_mode 0x%x\n", rf_tech_and_mode); | 211 | pr_err("unsupported rf_tech_and_mode 0x%x\n", rf_tech_and_mode); |
@@ -220,7 +220,7 @@ static int nci_add_new_protocol(struct nci_dev *ndev, | |||
220 | } | 220 | } |
221 | 221 | ||
222 | static void nci_add_new_target(struct nci_dev *ndev, | 222 | static void nci_add_new_target(struct nci_dev *ndev, |
223 | struct nci_rf_discover_ntf *ntf) | 223 | struct nci_rf_discover_ntf *ntf) |
224 | { | 224 | { |
225 | struct nfc_target *target; | 225 | struct nfc_target *target; |
226 | int i, rc; | 226 | int i, rc; |
@@ -230,8 +230,8 @@ static void nci_add_new_target(struct nci_dev *ndev, | |||
230 | if (target->idx == ntf->rf_discovery_id) { | 230 | if (target->idx == ntf->rf_discovery_id) { |
231 | /* This target already exists, add the new protocol */ | 231 | /* This target already exists, add the new protocol */ |
232 | nci_add_new_protocol(ndev, target, ntf->rf_protocol, | 232 | nci_add_new_protocol(ndev, target, ntf->rf_protocol, |
233 | ntf->rf_tech_and_mode, | 233 | ntf->rf_tech_and_mode, |
234 | &ntf->rf_tech_specific_params); | 234 | &ntf->rf_tech_specific_params); |
235 | return; | 235 | return; |
236 | } | 236 | } |
237 | } | 237 | } |
@@ -245,27 +245,27 @@ static void nci_add_new_target(struct nci_dev *ndev, | |||
245 | target = &ndev->targets[ndev->n_targets]; | 245 | target = &ndev->targets[ndev->n_targets]; |
246 | 246 | ||
247 | rc = nci_add_new_protocol(ndev, target, ntf->rf_protocol, | 247 | rc = nci_add_new_protocol(ndev, target, ntf->rf_protocol, |
248 | ntf->rf_tech_and_mode, | 248 | ntf->rf_tech_and_mode, |
249 | &ntf->rf_tech_specific_params); | 249 | &ntf->rf_tech_specific_params); |
250 | if (!rc) { | 250 | if (!rc) { |
251 | target->idx = ntf->rf_discovery_id; | 251 | target->idx = ntf->rf_discovery_id; |
252 | ndev->n_targets++; | 252 | ndev->n_targets++; |
253 | 253 | ||
254 | pr_debug("target_idx %d, n_targets %d\n", target->idx, | 254 | pr_debug("target_idx %d, n_targets %d\n", target->idx, |
255 | ndev->n_targets); | 255 | ndev->n_targets); |
256 | } | 256 | } |
257 | } | 257 | } |
258 | 258 | ||
259 | void nci_clear_target_list(struct nci_dev *ndev) | 259 | void nci_clear_target_list(struct nci_dev *ndev) |
260 | { | 260 | { |
261 | memset(ndev->targets, 0, | 261 | memset(ndev->targets, 0, |
262 | (sizeof(struct nfc_target)*NCI_MAX_DISCOVERED_TARGETS)); | 262 | (sizeof(struct nfc_target)*NCI_MAX_DISCOVERED_TARGETS)); |
263 | 263 | ||
264 | ndev->n_targets = 0; | 264 | ndev->n_targets = 0; |
265 | } | 265 | } |
266 | 266 | ||
267 | static void nci_rf_discover_ntf_packet(struct nci_dev *ndev, | 267 | static void nci_rf_discover_ntf_packet(struct nci_dev *ndev, |
268 | struct sk_buff *skb) | 268 | struct sk_buff *skb) |
269 | { | 269 | { |
270 | struct nci_rf_discover_ntf ntf; | 270 | struct nci_rf_discover_ntf ntf; |
271 | __u8 *data = skb->data; | 271 | __u8 *data = skb->data; |
@@ -280,7 +280,7 @@ static void nci_rf_discover_ntf_packet(struct nci_dev *ndev, | |||
280 | pr_debug("rf_protocol 0x%x\n", ntf.rf_protocol); | 280 | pr_debug("rf_protocol 0x%x\n", ntf.rf_protocol); |
281 | pr_debug("rf_tech_and_mode 0x%x\n", ntf.rf_tech_and_mode); | 281 | pr_debug("rf_tech_and_mode 0x%x\n", ntf.rf_tech_and_mode); |
282 | pr_debug("rf_tech_specific_params_len %d\n", | 282 | pr_debug("rf_tech_specific_params_len %d\n", |
283 | ntf.rf_tech_specific_params_len); | 283 | ntf.rf_tech_specific_params_len); |
284 | 284 | ||
285 | if (ntf.rf_tech_specific_params_len > 0) { | 285 | if (ntf.rf_tech_specific_params_len > 0) { |
286 | switch (ntf.rf_tech_and_mode) { | 286 | switch (ntf.rf_tech_and_mode) { |
@@ -318,7 +318,7 @@ static void nci_rf_discover_ntf_packet(struct nci_dev *ndev, | |||
318 | } else { | 318 | } else { |
319 | atomic_set(&ndev->state, NCI_W4_HOST_SELECT); | 319 | atomic_set(&ndev->state, NCI_W4_HOST_SELECT); |
320 | nfc_targets_found(ndev->nfc_dev, ndev->targets, | 320 | nfc_targets_found(ndev->nfc_dev, ndev->targets, |
321 | ndev->n_targets); | 321 | ndev->n_targets); |
322 | } | 322 | } |
323 | } | 323 | } |
324 | 324 | ||
@@ -335,20 +335,17 @@ static int nci_extract_activation_params_iso_dep(struct nci_dev *ndev, | |||
335 | pr_debug("rats_res_len %d\n", nfca_poll->rats_res_len); | 335 | pr_debug("rats_res_len %d\n", nfca_poll->rats_res_len); |
336 | if (nfca_poll->rats_res_len > 0) { | 336 | if (nfca_poll->rats_res_len > 0) { |
337 | memcpy(nfca_poll->rats_res, | 337 | memcpy(nfca_poll->rats_res, |
338 | data, | 338 | data, nfca_poll->rats_res_len); |
339 | nfca_poll->rats_res_len); | ||
340 | } | 339 | } |
341 | break; | 340 | break; |
342 | 341 | ||
343 | case NCI_NFC_B_PASSIVE_POLL_MODE: | 342 | case NCI_NFC_B_PASSIVE_POLL_MODE: |
344 | nfcb_poll = &ntf->activation_params.nfcb_poll_iso_dep; | 343 | nfcb_poll = &ntf->activation_params.nfcb_poll_iso_dep; |
345 | nfcb_poll->attrib_res_len = *data++; | 344 | nfcb_poll->attrib_res_len = *data++; |
346 | pr_debug("attrib_res_len %d\n", | 345 | pr_debug("attrib_res_len %d\n", nfcb_poll->attrib_res_len); |
347 | nfcb_poll->attrib_res_len); | ||
348 | if (nfcb_poll->attrib_res_len > 0) { | 346 | if (nfcb_poll->attrib_res_len > 0) { |
349 | memcpy(nfcb_poll->attrib_res, | 347 | memcpy(nfcb_poll->attrib_res, |
350 | data, | 348 | data, nfcb_poll->attrib_res_len); |
351 | nfcb_poll->attrib_res_len); | ||
352 | } | 349 | } |
353 | break; | 350 | break; |
354 | 351 | ||
@@ -362,7 +359,7 @@ static int nci_extract_activation_params_iso_dep(struct nci_dev *ndev, | |||
362 | } | 359 | } |
363 | 360 | ||
364 | static void nci_target_auto_activated(struct nci_dev *ndev, | 361 | static void nci_target_auto_activated(struct nci_dev *ndev, |
365 | struct nci_rf_intf_activated_ntf *ntf) | 362 | struct nci_rf_intf_activated_ntf *ntf) |
366 | { | 363 | { |
367 | struct nfc_target *target; | 364 | struct nfc_target *target; |
368 | int rc; | 365 | int rc; |
@@ -370,8 +367,8 @@ static void nci_target_auto_activated(struct nci_dev *ndev, | |||
370 | target = &ndev->targets[ndev->n_targets]; | 367 | target = &ndev->targets[ndev->n_targets]; |
371 | 368 | ||
372 | rc = nci_add_new_protocol(ndev, target, ntf->rf_protocol, | 369 | rc = nci_add_new_protocol(ndev, target, ntf->rf_protocol, |
373 | ntf->activation_rf_tech_and_mode, | 370 | ntf->activation_rf_tech_and_mode, |
374 | &ntf->rf_tech_specific_params); | 371 | &ntf->rf_tech_specific_params); |
375 | if (rc) | 372 | if (rc) |
376 | return; | 373 | return; |
377 | 374 | ||
@@ -384,7 +381,7 @@ static void nci_target_auto_activated(struct nci_dev *ndev, | |||
384 | } | 381 | } |
385 | 382 | ||
386 | static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev, | 383 | static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev, |
387 | struct sk_buff *skb) | 384 | struct sk_buff *skb) |
388 | { | 385 | { |
389 | struct nci_rf_intf_activated_ntf ntf; | 386 | struct nci_rf_intf_activated_ntf ntf; |
390 | __u8 *data = skb->data; | 387 | __u8 *data = skb->data; |
@@ -405,7 +402,8 @@ static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev, | |||
405 | ntf.activation_rf_tech_and_mode); | 402 | ntf.activation_rf_tech_and_mode); |
406 | pr_debug("max_data_pkt_payload_size 0x%x\n", | 403 | pr_debug("max_data_pkt_payload_size 0x%x\n", |
407 | ntf.max_data_pkt_payload_size); | 404 | ntf.max_data_pkt_payload_size); |
408 | pr_debug("initial_num_credits 0x%x\n", ntf.initial_num_credits); | 405 | pr_debug("initial_num_credits 0x%x\n", |
406 | ntf.initial_num_credits); | ||
409 | pr_debug("rf_tech_specific_params_len %d\n", | 407 | pr_debug("rf_tech_specific_params_len %d\n", |
410 | ntf.rf_tech_specific_params_len); | 408 | ntf.rf_tech_specific_params_len); |
411 | 409 | ||
@@ -441,18 +439,15 @@ static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev, | |||
441 | 439 | ||
442 | pr_debug("data_exch_rf_tech_and_mode 0x%x\n", | 440 | pr_debug("data_exch_rf_tech_and_mode 0x%x\n", |
443 | ntf.data_exch_rf_tech_and_mode); | 441 | ntf.data_exch_rf_tech_and_mode); |
444 | pr_debug("data_exch_tx_bit_rate 0x%x\n", | 442 | pr_debug("data_exch_tx_bit_rate 0x%x\n", ntf.data_exch_tx_bit_rate); |
445 | ntf.data_exch_tx_bit_rate); | 443 | pr_debug("data_exch_rx_bit_rate 0x%x\n", ntf.data_exch_rx_bit_rate); |
446 | pr_debug("data_exch_rx_bit_rate 0x%x\n", | 444 | pr_debug("activation_params_len %d\n", ntf.activation_params_len); |
447 | ntf.data_exch_rx_bit_rate); | ||
448 | pr_debug("activation_params_len %d\n", | ||
449 | ntf.activation_params_len); | ||
450 | 445 | ||
451 | if (ntf.activation_params_len > 0) { | 446 | if (ntf.activation_params_len > 0) { |
452 | switch (ntf.rf_interface) { | 447 | switch (ntf.rf_interface) { |
453 | case NCI_RF_INTERFACE_ISO_DEP: | 448 | case NCI_RF_INTERFACE_ISO_DEP: |
454 | err = nci_extract_activation_params_iso_dep(ndev, | 449 | err = nci_extract_activation_params_iso_dep(ndev, |
455 | &ntf, data); | 450 | &ntf, data); |
456 | break; | 451 | break; |
457 | 452 | ||
458 | case NCI_RF_INTERFACE_FRAME: | 453 | case NCI_RF_INTERFACE_FRAME: |
@@ -489,7 +484,7 @@ exit: | |||
489 | } | 484 | } |
490 | 485 | ||
491 | static void nci_rf_deactivate_ntf_packet(struct nci_dev *ndev, | 486 | static void nci_rf_deactivate_ntf_packet(struct nci_dev *ndev, |
492 | struct sk_buff *skb) | 487 | struct sk_buff *skb) |
493 | { | 488 | { |
494 | struct nci_rf_deactivate_ntf *ntf = (void *) skb->data; | 489 | struct nci_rf_deactivate_ntf *ntf = (void *) skb->data; |
495 | 490 | ||
diff --git a/net/nfc/nci/rsp.c b/net/nfc/nci/rsp.c index aa63b1e99188..3003c3390e49 100644 --- a/net/nfc/nci/rsp.c +++ b/net/nfc/nci/rsp.c | |||
@@ -67,19 +67,18 @@ static void nci_core_init_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb) | |||
67 | ndev->num_supported_rf_interfaces = rsp_1->num_supported_rf_interfaces; | 67 | ndev->num_supported_rf_interfaces = rsp_1->num_supported_rf_interfaces; |
68 | 68 | ||
69 | if (ndev->num_supported_rf_interfaces > | 69 | if (ndev->num_supported_rf_interfaces > |
70 | NCI_MAX_SUPPORTED_RF_INTERFACES) { | 70 | NCI_MAX_SUPPORTED_RF_INTERFACES) { |
71 | ndev->num_supported_rf_interfaces = | 71 | ndev->num_supported_rf_interfaces = |
72 | NCI_MAX_SUPPORTED_RF_INTERFACES; | 72 | NCI_MAX_SUPPORTED_RF_INTERFACES; |
73 | } | 73 | } |
74 | 74 | ||
75 | memcpy(ndev->supported_rf_interfaces, | 75 | memcpy(ndev->supported_rf_interfaces, |
76 | rsp_1->supported_rf_interfaces, | 76 | rsp_1->supported_rf_interfaces, |
77 | ndev->num_supported_rf_interfaces); | 77 | ndev->num_supported_rf_interfaces); |
78 | 78 | ||
79 | rsp_2 = (void *) (skb->data + 6 + rsp_1->num_supported_rf_interfaces); | 79 | rsp_2 = (void *) (skb->data + 6 + rsp_1->num_supported_rf_interfaces); |
80 | 80 | ||
81 | ndev->max_logical_connections = | 81 | ndev->max_logical_connections = rsp_2->max_logical_connections; |
82 | rsp_2->max_logical_connections; | ||
83 | ndev->max_routing_table_size = | 82 | ndev->max_routing_table_size = |
84 | __le16_to_cpu(rsp_2->max_routing_table_size); | 83 | __le16_to_cpu(rsp_2->max_routing_table_size); |
85 | ndev->max_ctrl_pkt_payload_len = | 84 | ndev->max_ctrl_pkt_payload_len = |
@@ -121,7 +120,7 @@ exit: | |||
121 | } | 120 | } |
122 | 121 | ||
123 | static void nci_rf_disc_map_rsp_packet(struct nci_dev *ndev, | 122 | static void nci_rf_disc_map_rsp_packet(struct nci_dev *ndev, |
124 | struct sk_buff *skb) | 123 | struct sk_buff *skb) |
125 | { | 124 | { |
126 | __u8 status = skb->data[0]; | 125 | __u8 status = skb->data[0]; |
127 | 126 | ||
@@ -143,7 +142,7 @@ static void nci_rf_disc_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb) | |||
143 | } | 142 | } |
144 | 143 | ||
145 | static void nci_rf_disc_select_rsp_packet(struct nci_dev *ndev, | 144 | static void nci_rf_disc_select_rsp_packet(struct nci_dev *ndev, |
146 | struct sk_buff *skb) | 145 | struct sk_buff *skb) |
147 | { | 146 | { |
148 | __u8 status = skb->data[0]; | 147 | __u8 status = skb->data[0]; |
149 | 148 | ||
@@ -155,7 +154,7 @@ static void nci_rf_disc_select_rsp_packet(struct nci_dev *ndev, | |||
155 | } | 154 | } |
156 | 155 | ||
157 | static void nci_rf_deactivate_rsp_packet(struct nci_dev *ndev, | 156 | static void nci_rf_deactivate_rsp_packet(struct nci_dev *ndev, |
158 | struct sk_buff *skb) | 157 | struct sk_buff *skb) |
159 | { | 158 | { |
160 | __u8 status = skb->data[0]; | 159 | __u8 status = skb->data[0]; |
161 | 160 | ||
@@ -163,7 +162,7 @@ static void nci_rf_deactivate_rsp_packet(struct nci_dev *ndev, | |||
163 | 162 | ||
164 | /* If target was active, complete the request only in deactivate_ntf */ | 163 | /* If target was active, complete the request only in deactivate_ntf */ |
165 | if ((status != NCI_STATUS_OK) || | 164 | if ((status != NCI_STATUS_OK) || |
166 | (atomic_read(&ndev->state) != NCI_POLL_ACTIVE)) { | 165 | (atomic_read(&ndev->state) != NCI_POLL_ACTIVE)) { |
167 | nci_clear_target_list(ndev); | 166 | nci_clear_target_list(ndev); |
168 | atomic_set(&ndev->state, NCI_IDLE); | 167 | atomic_set(&ndev->state, NCI_IDLE); |
169 | nci_req_complete(ndev, status); | 168 | nci_req_complete(ndev, status); |
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index 07f0348aabf5..6404052d6c07 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c | |||
@@ -48,34 +48,34 @@ static const struct nla_policy nfc_genl_policy[NFC_ATTR_MAX + 1] = { | |||
48 | [NFC_ATTR_PROTOCOLS] = { .type = NLA_U32 }, | 48 | [NFC_ATTR_PROTOCOLS] = { .type = NLA_U32 }, |
49 | [NFC_ATTR_COMM_MODE] = { .type = NLA_U8 }, | 49 | [NFC_ATTR_COMM_MODE] = { .type = NLA_U8 }, |
50 | [NFC_ATTR_RF_MODE] = { .type = NLA_U8 }, | 50 | [NFC_ATTR_RF_MODE] = { .type = NLA_U8 }, |
51 | [NFC_ATTR_DEVICE_POWERED] = { .type = NLA_U8 }, | ||
51 | }; | 52 | }; |
52 | 53 | ||
53 | static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target, | 54 | static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target, |
54 | struct netlink_callback *cb, int flags) | 55 | struct netlink_callback *cb, int flags) |
55 | { | 56 | { |
56 | void *hdr; | 57 | void *hdr; |
57 | 58 | ||
58 | hdr = genlmsg_put(msg, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, | 59 | hdr = genlmsg_put(msg, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, |
59 | &nfc_genl_family, flags, NFC_CMD_GET_TARGET); | 60 | &nfc_genl_family, flags, NFC_CMD_GET_TARGET); |
60 | if (!hdr) | 61 | if (!hdr) |
61 | return -EMSGSIZE; | 62 | return -EMSGSIZE; |
62 | 63 | ||
63 | genl_dump_check_consistent(cb, hdr, &nfc_genl_family); | 64 | genl_dump_check_consistent(cb, hdr, &nfc_genl_family); |
64 | 65 | ||
65 | NLA_PUT_U32(msg, NFC_ATTR_TARGET_INDEX, target->idx); | 66 | NLA_PUT_U32(msg, NFC_ATTR_TARGET_INDEX, target->idx); |
66 | NLA_PUT_U32(msg, NFC_ATTR_PROTOCOLS, | 67 | NLA_PUT_U32(msg, NFC_ATTR_PROTOCOLS, target->supported_protocols); |
67 | target->supported_protocols); | ||
68 | NLA_PUT_U16(msg, NFC_ATTR_TARGET_SENS_RES, target->sens_res); | 68 | NLA_PUT_U16(msg, NFC_ATTR_TARGET_SENS_RES, target->sens_res); |
69 | NLA_PUT_U8(msg, NFC_ATTR_TARGET_SEL_RES, target->sel_res); | 69 | NLA_PUT_U8(msg, NFC_ATTR_TARGET_SEL_RES, target->sel_res); |
70 | if (target->nfcid1_len > 0) | 70 | if (target->nfcid1_len > 0) |
71 | NLA_PUT(msg, NFC_ATTR_TARGET_NFCID1, target->nfcid1_len, | 71 | NLA_PUT(msg, NFC_ATTR_TARGET_NFCID1, target->nfcid1_len, |
72 | target->nfcid1); | 72 | target->nfcid1); |
73 | if (target->sensb_res_len > 0) | 73 | if (target->sensb_res_len > 0) |
74 | NLA_PUT(msg, NFC_ATTR_TARGET_SENSB_RES, target->sensb_res_len, | 74 | NLA_PUT(msg, NFC_ATTR_TARGET_SENSB_RES, target->sensb_res_len, |
75 | target->sensb_res); | 75 | target->sensb_res); |
76 | if (target->sensf_res_len > 0) | 76 | if (target->sensf_res_len > 0) |
77 | NLA_PUT(msg, NFC_ATTR_TARGET_SENSF_RES, target->sensf_res_len, | 77 | NLA_PUT(msg, NFC_ATTR_TARGET_SENSF_RES, target->sensf_res_len, |
78 | target->sensf_res); | 78 | target->sensf_res); |
79 | 79 | ||
80 | return genlmsg_end(msg, hdr); | 80 | return genlmsg_end(msg, hdr); |
81 | 81 | ||
@@ -91,9 +91,9 @@ static struct nfc_dev *__get_device_from_cb(struct netlink_callback *cb) | |||
91 | u32 idx; | 91 | u32 idx; |
92 | 92 | ||
93 | rc = nlmsg_parse(cb->nlh, GENL_HDRLEN + nfc_genl_family.hdrsize, | 93 | rc = nlmsg_parse(cb->nlh, GENL_HDRLEN + nfc_genl_family.hdrsize, |
94 | nfc_genl_family.attrbuf, | 94 | nfc_genl_family.attrbuf, |
95 | nfc_genl_family.maxattr, | 95 | nfc_genl_family.maxattr, |
96 | nfc_genl_policy); | 96 | nfc_genl_policy); |
97 | if (rc < 0) | 97 | if (rc < 0) |
98 | return ERR_PTR(rc); | 98 | return ERR_PTR(rc); |
99 | 99 | ||
@@ -110,7 +110,7 @@ static struct nfc_dev *__get_device_from_cb(struct netlink_callback *cb) | |||
110 | } | 110 | } |
111 | 111 | ||
112 | static int nfc_genl_dump_targets(struct sk_buff *skb, | 112 | static int nfc_genl_dump_targets(struct sk_buff *skb, |
113 | struct netlink_callback *cb) | 113 | struct netlink_callback *cb) |
114 | { | 114 | { |
115 | int i = cb->args[0]; | 115 | int i = cb->args[0]; |
116 | struct nfc_dev *dev = (struct nfc_dev *) cb->args[1]; | 116 | struct nfc_dev *dev = (struct nfc_dev *) cb->args[1]; |
@@ -130,7 +130,7 @@ static int nfc_genl_dump_targets(struct sk_buff *skb, | |||
130 | 130 | ||
131 | while (i < dev->n_targets) { | 131 | while (i < dev->n_targets) { |
132 | rc = nfc_genl_send_target(skb, &dev->targets[i], cb, | 132 | rc = nfc_genl_send_target(skb, &dev->targets[i], cb, |
133 | NLM_F_MULTI); | 133 | NLM_F_MULTI); |
134 | if (rc < 0) | 134 | if (rc < 0) |
135 | break; | 135 | break; |
136 | 136 | ||
@@ -166,7 +166,7 @@ int nfc_genl_targets_found(struct nfc_dev *dev) | |||
166 | return -ENOMEM; | 166 | return -ENOMEM; |
167 | 167 | ||
168 | hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, | 168 | hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, |
169 | NFC_EVENT_TARGETS_FOUND); | 169 | NFC_EVENT_TARGETS_FOUND); |
170 | if (!hdr) | 170 | if (!hdr) |
171 | goto free_msg; | 171 | goto free_msg; |
172 | 172 | ||
@@ -193,13 +193,14 @@ int nfc_genl_device_added(struct nfc_dev *dev) | |||
193 | return -ENOMEM; | 193 | return -ENOMEM; |
194 | 194 | ||
195 | hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, | 195 | hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, |
196 | NFC_EVENT_DEVICE_ADDED); | 196 | NFC_EVENT_DEVICE_ADDED); |
197 | if (!hdr) | 197 | if (!hdr) |
198 | goto free_msg; | 198 | goto free_msg; |
199 | 199 | ||
200 | NLA_PUT_STRING(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev)); | 200 | NLA_PUT_STRING(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev)); |
201 | NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx); | 201 | NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx); |
202 | NLA_PUT_U32(msg, NFC_ATTR_PROTOCOLS, dev->supported_protocols); | 202 | NLA_PUT_U32(msg, NFC_ATTR_PROTOCOLS, dev->supported_protocols); |
203 | NLA_PUT_U8(msg, NFC_ATTR_DEVICE_POWERED, dev->dev_up); | ||
203 | 204 | ||
204 | genlmsg_end(msg, hdr); | 205 | genlmsg_end(msg, hdr); |
205 | 206 | ||
@@ -224,7 +225,7 @@ int nfc_genl_device_removed(struct nfc_dev *dev) | |||
224 | return -ENOMEM; | 225 | return -ENOMEM; |
225 | 226 | ||
226 | hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, | 227 | hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, |
227 | NFC_EVENT_DEVICE_REMOVED); | 228 | NFC_EVENT_DEVICE_REMOVED); |
228 | if (!hdr) | 229 | if (!hdr) |
229 | goto free_msg; | 230 | goto free_msg; |
230 | 231 | ||
@@ -244,14 +245,14 @@ free_msg: | |||
244 | } | 245 | } |
245 | 246 | ||
246 | static int nfc_genl_send_device(struct sk_buff *msg, struct nfc_dev *dev, | 247 | static int nfc_genl_send_device(struct sk_buff *msg, struct nfc_dev *dev, |
247 | u32 pid, u32 seq, | 248 | u32 pid, u32 seq, |
248 | struct netlink_callback *cb, | 249 | struct netlink_callback *cb, |
249 | int flags) | 250 | int flags) |
250 | { | 251 | { |
251 | void *hdr; | 252 | void *hdr; |
252 | 253 | ||
253 | hdr = genlmsg_put(msg, pid, seq, &nfc_genl_family, flags, | 254 | hdr = genlmsg_put(msg, pid, seq, &nfc_genl_family, flags, |
254 | NFC_CMD_GET_DEVICE); | 255 | NFC_CMD_GET_DEVICE); |
255 | if (!hdr) | 256 | if (!hdr) |
256 | return -EMSGSIZE; | 257 | return -EMSGSIZE; |
257 | 258 | ||
@@ -261,6 +262,7 @@ static int nfc_genl_send_device(struct sk_buff *msg, struct nfc_dev *dev, | |||
261 | NLA_PUT_STRING(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev)); | 262 | NLA_PUT_STRING(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev)); |
262 | NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx); | 263 | NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx); |
263 | NLA_PUT_U32(msg, NFC_ATTR_PROTOCOLS, dev->supported_protocols); | 264 | NLA_PUT_U32(msg, NFC_ATTR_PROTOCOLS, dev->supported_protocols); |
265 | NLA_PUT_U8(msg, NFC_ATTR_DEVICE_POWERED, dev->dev_up); | ||
264 | 266 | ||
265 | return genlmsg_end(msg, hdr); | 267 | return genlmsg_end(msg, hdr); |
266 | 268 | ||
@@ -270,7 +272,7 @@ nla_put_failure: | |||
270 | } | 272 | } |
271 | 273 | ||
272 | static int nfc_genl_dump_devices(struct sk_buff *skb, | 274 | static int nfc_genl_dump_devices(struct sk_buff *skb, |
273 | struct netlink_callback *cb) | 275 | struct netlink_callback *cb) |
274 | { | 276 | { |
275 | struct class_dev_iter *iter = (struct class_dev_iter *) cb->args[0]; | 277 | struct class_dev_iter *iter = (struct class_dev_iter *) cb->args[0]; |
276 | struct nfc_dev *dev = (struct nfc_dev *) cb->args[1]; | 278 | struct nfc_dev *dev = (struct nfc_dev *) cb->args[1]; |
@@ -297,8 +299,7 @@ static int nfc_genl_dump_devices(struct sk_buff *skb, | |||
297 | int rc; | 299 | int rc; |
298 | 300 | ||
299 | rc = nfc_genl_send_device(skb, dev, NETLINK_CB(cb->skb).pid, | 301 | rc = nfc_genl_send_device(skb, dev, NETLINK_CB(cb->skb).pid, |
300 | cb->nlh->nlmsg_seq, | 302 | cb->nlh->nlmsg_seq, cb, NLM_F_MULTI); |
301 | cb, NLM_F_MULTI); | ||
302 | if (rc < 0) | 303 | if (rc < 0) |
303 | break; | 304 | break; |
304 | 305 | ||
@@ -323,7 +324,7 @@ static int nfc_genl_dump_devices_done(struct netlink_callback *cb) | |||
323 | } | 324 | } |
324 | 325 | ||
325 | int nfc_genl_dep_link_up_event(struct nfc_dev *dev, u32 target_idx, | 326 | int nfc_genl_dep_link_up_event(struct nfc_dev *dev, u32 target_idx, |
326 | u8 comm_mode, u8 rf_mode) | 327 | u8 comm_mode, u8 rf_mode) |
327 | { | 328 | { |
328 | struct sk_buff *msg; | 329 | struct sk_buff *msg; |
329 | void *hdr; | 330 | void *hdr; |
@@ -334,8 +335,7 @@ int nfc_genl_dep_link_up_event(struct nfc_dev *dev, u32 target_idx, | |||
334 | if (!msg) | 335 | if (!msg) |
335 | return -ENOMEM; | 336 | return -ENOMEM; |
336 | 337 | ||
337 | hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, | 338 | hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, NFC_CMD_DEP_LINK_UP); |
338 | NFC_CMD_DEP_LINK_UP); | ||
339 | if (!hdr) | 339 | if (!hdr) |
340 | goto free_msg; | 340 | goto free_msg; |
341 | 341 | ||
@@ -372,7 +372,7 @@ int nfc_genl_dep_link_down_event(struct nfc_dev *dev) | |||
372 | return -ENOMEM; | 372 | return -ENOMEM; |
373 | 373 | ||
374 | hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, | 374 | hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, |
375 | NFC_CMD_DEP_LINK_DOWN); | 375 | NFC_CMD_DEP_LINK_DOWN); |
376 | if (!hdr) | 376 | if (!hdr) |
377 | goto free_msg; | 377 | goto free_msg; |
378 | 378 | ||
@@ -414,7 +414,7 @@ static int nfc_genl_get_device(struct sk_buff *skb, struct genl_info *info) | |||
414 | } | 414 | } |
415 | 415 | ||
416 | rc = nfc_genl_send_device(msg, dev, info->snd_pid, info->snd_seq, | 416 | rc = nfc_genl_send_device(msg, dev, info->snd_pid, info->snd_seq, |
417 | NULL, 0); | 417 | NULL, 0); |
418 | if (rc < 0) | 418 | if (rc < 0) |
419 | goto out_free; | 419 | goto out_free; |
420 | 420 | ||
@@ -481,7 +481,7 @@ static int nfc_genl_start_poll(struct sk_buff *skb, struct genl_info *info) | |||
481 | pr_debug("Poll start\n"); | 481 | pr_debug("Poll start\n"); |
482 | 482 | ||
483 | if (!info->attrs[NFC_ATTR_DEVICE_INDEX] || | 483 | if (!info->attrs[NFC_ATTR_DEVICE_INDEX] || |
484 | !info->attrs[NFC_ATTR_PROTOCOLS]) | 484 | !info->attrs[NFC_ATTR_PROTOCOLS]) |
485 | return -EINVAL; | 485 | return -EINVAL; |
486 | 486 | ||
487 | idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); | 487 | idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); |
@@ -539,13 +539,12 @@ static int nfc_genl_dep_link_up(struct sk_buff *skb, struct genl_info *info) | |||
539 | struct nfc_dev *dev; | 539 | struct nfc_dev *dev; |
540 | int rc, tgt_idx; | 540 | int rc, tgt_idx; |
541 | u32 idx; | 541 | u32 idx; |
542 | u8 comm, rf; | 542 | u8 comm; |
543 | 543 | ||
544 | pr_debug("DEP link up\n"); | 544 | pr_debug("DEP link up\n"); |
545 | 545 | ||
546 | if (!info->attrs[NFC_ATTR_DEVICE_INDEX] || | 546 | if (!info->attrs[NFC_ATTR_DEVICE_INDEX] || |
547 | !info->attrs[NFC_ATTR_COMM_MODE] || | 547 | !info->attrs[NFC_ATTR_COMM_MODE]) |
548 | !info->attrs[NFC_ATTR_RF_MODE]) | ||
549 | return -EINVAL; | 548 | return -EINVAL; |
550 | 549 | ||
551 | idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); | 550 | idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); |
@@ -555,19 +554,15 @@ static int nfc_genl_dep_link_up(struct sk_buff *skb, struct genl_info *info) | |||
555 | tgt_idx = nla_get_u32(info->attrs[NFC_ATTR_TARGET_INDEX]); | 554 | tgt_idx = nla_get_u32(info->attrs[NFC_ATTR_TARGET_INDEX]); |
556 | 555 | ||
557 | comm = nla_get_u8(info->attrs[NFC_ATTR_COMM_MODE]); | 556 | comm = nla_get_u8(info->attrs[NFC_ATTR_COMM_MODE]); |
558 | rf = nla_get_u8(info->attrs[NFC_ATTR_RF_MODE]); | ||
559 | 557 | ||
560 | if (comm != NFC_COMM_ACTIVE && comm != NFC_COMM_PASSIVE) | 558 | if (comm != NFC_COMM_ACTIVE && comm != NFC_COMM_PASSIVE) |
561 | return -EINVAL; | 559 | return -EINVAL; |
562 | 560 | ||
563 | if (rf != NFC_RF_INITIATOR && comm != NFC_RF_TARGET) | ||
564 | return -EINVAL; | ||
565 | |||
566 | dev = nfc_get_device(idx); | 561 | dev = nfc_get_device(idx); |
567 | if (!dev) | 562 | if (!dev) |
568 | return -ENODEV; | 563 | return -ENODEV; |
569 | 564 | ||
570 | rc = nfc_dep_link_up(dev, tgt_idx, comm, rf); | 565 | rc = nfc_dep_link_up(dev, tgt_idx, comm); |
571 | 566 | ||
572 | nfc_put_device(dev); | 567 | nfc_put_device(dev); |
573 | 568 | ||
@@ -642,7 +637,7 @@ static struct genl_ops nfc_genl_ops[] = { | |||
642 | }; | 637 | }; |
643 | 638 | ||
644 | static int nfc_genl_rcv_nl_event(struct notifier_block *this, | 639 | static int nfc_genl_rcv_nl_event(struct notifier_block *this, |
645 | unsigned long event, void *ptr) | 640 | unsigned long event, void *ptr) |
646 | { | 641 | { |
647 | struct netlink_notify *n = ptr; | 642 | struct netlink_notify *n = ptr; |
648 | struct class_dev_iter iter; | 643 | struct class_dev_iter iter; |
@@ -695,7 +690,7 @@ int __init nfc_genl_init(void) | |||
695 | int rc; | 690 | int rc; |
696 | 691 | ||
697 | rc = genl_register_family_with_ops(&nfc_genl_family, nfc_genl_ops, | 692 | rc = genl_register_family_with_ops(&nfc_genl_family, nfc_genl_ops, |
698 | ARRAY_SIZE(nfc_genl_ops)); | 693 | ARRAY_SIZE(nfc_genl_ops)); |
699 | if (rc) | 694 | if (rc) |
700 | return rc; | 695 | return rc; |
701 | 696 | ||
diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h index 6d28d75995b0..ec8794c1099c 100644 --- a/net/nfc/nfc.h +++ b/net/nfc/nfc.h | |||
@@ -32,7 +32,7 @@ struct nfc_protocol { | |||
32 | struct proto *proto; | 32 | struct proto *proto; |
33 | struct module *owner; | 33 | struct module *owner; |
34 | int (*create)(struct net *net, struct socket *sock, | 34 | int (*create)(struct net *net, struct socket *sock, |
35 | const struct nfc_protocol *nfc_proto); | 35 | const struct nfc_protocol *nfc_proto); |
36 | }; | 36 | }; |
37 | 37 | ||
38 | struct nfc_rawsock { | 38 | struct nfc_rawsock { |
@@ -54,7 +54,7 @@ void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx, | |||
54 | int nfc_llcp_register_device(struct nfc_dev *dev); | 54 | int nfc_llcp_register_device(struct nfc_dev *dev); |
55 | void nfc_llcp_unregister_device(struct nfc_dev *dev); | 55 | void nfc_llcp_unregister_device(struct nfc_dev *dev); |
56 | int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len); | 56 | int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len); |
57 | u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, u8 *general_bytes_len); | 57 | u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len); |
58 | int __init nfc_llcp_init(void); | 58 | int __init nfc_llcp_init(void); |
59 | void nfc_llcp_exit(void); | 59 | void nfc_llcp_exit(void); |
60 | 60 | ||
@@ -65,7 +65,7 @@ static inline void nfc_llcp_mac_is_down(struct nfc_dev *dev) | |||
65 | } | 65 | } |
66 | 66 | ||
67 | static inline void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx, | 67 | static inline void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx, |
68 | u8 comm_mode, u8 rf_mode) | 68 | u8 comm_mode, u8 rf_mode) |
69 | { | 69 | { |
70 | } | 70 | } |
71 | 71 | ||
@@ -78,7 +78,8 @@ static inline void nfc_llcp_unregister_device(struct nfc_dev *dev) | |||
78 | { | 78 | { |
79 | } | 79 | } |
80 | 80 | ||
81 | static inline int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len) | 81 | static inline int nfc_llcp_set_remote_gb(struct nfc_dev *dev, |
82 | u8 *gb, u8 gb_len) | ||
82 | { | 83 | { |
83 | return 0; | 84 | return 0; |
84 | } | 85 | } |
@@ -160,8 +161,7 @@ int nfc_start_poll(struct nfc_dev *dev, u32 protocols); | |||
160 | 161 | ||
161 | int nfc_stop_poll(struct nfc_dev *dev); | 162 | int nfc_stop_poll(struct nfc_dev *dev); |
162 | 163 | ||
163 | int nfc_dep_link_up(struct nfc_dev *dev, int target_idx, | 164 | int nfc_dep_link_up(struct nfc_dev *dev, int target_idx, u8 comm_mode); |
164 | u8 comm_mode, u8 rf_mode); | ||
165 | 165 | ||
166 | int nfc_dep_link_down(struct nfc_dev *dev); | 166 | int nfc_dep_link_down(struct nfc_dev *dev); |
167 | 167 | ||
@@ -169,9 +169,7 @@ int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol); | |||
169 | 169 | ||
170 | int nfc_deactivate_target(struct nfc_dev *dev, u32 target_idx); | 170 | int nfc_deactivate_target(struct nfc_dev *dev, u32 target_idx); |
171 | 171 | ||
172 | int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx, | 172 | int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx, struct sk_buff *skb, |
173 | struct sk_buff *skb, | 173 | data_exchange_cb_t cb, void *cb_context); |
174 | data_exchange_cb_t cb, | ||
175 | void *cb_context); | ||
176 | 174 | ||
177 | #endif /* __LOCAL_NFC_H */ | 175 | #endif /* __LOCAL_NFC_H */ |
diff --git a/net/nfc/rawsock.c b/net/nfc/rawsock.c index 5325439b0c60..5a839ceb2e82 100644 --- a/net/nfc/rawsock.c +++ b/net/nfc/rawsock.c | |||
@@ -63,7 +63,7 @@ static int rawsock_release(struct socket *sock) | |||
63 | } | 63 | } |
64 | 64 | ||
65 | static int rawsock_connect(struct socket *sock, struct sockaddr *_addr, | 65 | static int rawsock_connect(struct socket *sock, struct sockaddr *_addr, |
66 | int len, int flags) | 66 | int len, int flags) |
67 | { | 67 | { |
68 | struct sock *sk = sock->sk; | 68 | struct sock *sk = sock->sk; |
69 | struct sockaddr_nfc *addr = (struct sockaddr_nfc *)_addr; | 69 | struct sockaddr_nfc *addr = (struct sockaddr_nfc *)_addr; |
@@ -73,7 +73,7 @@ static int rawsock_connect(struct socket *sock, struct sockaddr *_addr, | |||
73 | pr_debug("sock=%p sk=%p flags=%d\n", sock, sk, flags); | 73 | pr_debug("sock=%p sk=%p flags=%d\n", sock, sk, flags); |
74 | 74 | ||
75 | if (!addr || len < sizeof(struct sockaddr_nfc) || | 75 | if (!addr || len < sizeof(struct sockaddr_nfc) || |
76 | addr->sa_family != AF_NFC) | 76 | addr->sa_family != AF_NFC) |
77 | return -EINVAL; | 77 | return -EINVAL; |
78 | 78 | ||
79 | pr_debug("addr dev_idx=%u target_idx=%u protocol=%u\n", | 79 | pr_debug("addr dev_idx=%u target_idx=%u protocol=%u\n", |
@@ -120,7 +120,7 @@ static int rawsock_add_header(struct sk_buff *skb) | |||
120 | } | 120 | } |
121 | 121 | ||
122 | static void rawsock_data_exchange_complete(void *context, struct sk_buff *skb, | 122 | static void rawsock_data_exchange_complete(void *context, struct sk_buff *skb, |
123 | int err) | 123 | int err) |
124 | { | 124 | { |
125 | struct sock *sk = (struct sock *) context; | 125 | struct sock *sk = (struct sock *) context; |
126 | 126 | ||
@@ -173,7 +173,7 @@ static void rawsock_tx_work(struct work_struct *work) | |||
173 | 173 | ||
174 | sock_hold(sk); | 174 | sock_hold(sk); |
175 | rc = nfc_data_exchange(dev, target_idx, skb, | 175 | rc = nfc_data_exchange(dev, target_idx, skb, |
176 | rawsock_data_exchange_complete, sk); | 176 | rawsock_data_exchange_complete, sk); |
177 | if (rc) { | 177 | if (rc) { |
178 | rawsock_report_error(sk, rc); | 178 | rawsock_report_error(sk, rc); |
179 | sock_put(sk); | 179 | sock_put(sk); |
@@ -181,7 +181,7 @@ static void rawsock_tx_work(struct work_struct *work) | |||
181 | } | 181 | } |
182 | 182 | ||
183 | static int rawsock_sendmsg(struct kiocb *iocb, struct socket *sock, | 183 | static int rawsock_sendmsg(struct kiocb *iocb, struct socket *sock, |
184 | struct msghdr *msg, size_t len) | 184 | struct msghdr *msg, size_t len) |
185 | { | 185 | { |
186 | struct sock *sk = sock->sk; | 186 | struct sock *sk = sock->sk; |
187 | struct nfc_dev *dev = nfc_rawsock(sk)->dev; | 187 | struct nfc_dev *dev = nfc_rawsock(sk)->dev; |
@@ -218,7 +218,7 @@ static int rawsock_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
218 | } | 218 | } |
219 | 219 | ||
220 | static int rawsock_recvmsg(struct kiocb *iocb, struct socket *sock, | 220 | static int rawsock_recvmsg(struct kiocb *iocb, struct socket *sock, |
221 | struct msghdr *msg, size_t len, int flags) | 221 | struct msghdr *msg, size_t len, int flags) |
222 | { | 222 | { |
223 | int noblock = flags & MSG_DONTWAIT; | 223 | int noblock = flags & MSG_DONTWAIT; |
224 | struct sock *sk = sock->sk; | 224 | struct sock *sk = sock->sk; |
@@ -274,7 +274,7 @@ static void rawsock_destruct(struct sock *sk) | |||
274 | 274 | ||
275 | if (sk->sk_state == TCP_ESTABLISHED) { | 275 | if (sk->sk_state == TCP_ESTABLISHED) { |
276 | nfc_deactivate_target(nfc_rawsock(sk)->dev, | 276 | nfc_deactivate_target(nfc_rawsock(sk)->dev, |
277 | nfc_rawsock(sk)->target_idx); | 277 | nfc_rawsock(sk)->target_idx); |
278 | nfc_put_device(nfc_rawsock(sk)->dev); | 278 | nfc_put_device(nfc_rawsock(sk)->dev); |
279 | } | 279 | } |
280 | 280 | ||
@@ -287,7 +287,7 @@ static void rawsock_destruct(struct sock *sk) | |||
287 | } | 287 | } |
288 | 288 | ||
289 | static int rawsock_create(struct net *net, struct socket *sock, | 289 | static int rawsock_create(struct net *net, struct socket *sock, |
290 | const struct nfc_protocol *nfc_proto) | 290 | const struct nfc_protocol *nfc_proto) |
291 | { | 291 | { |
292 | struct sock *sk; | 292 | struct sock *sk; |
293 | 293 | ||
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index 9d3e3b6bfcf4..ba21ab22187b 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c | |||
@@ -23,6 +23,8 @@ | |||
23 | #define MESH_PERR_MIN_INT 100 | 23 | #define MESH_PERR_MIN_INT 100 |
24 | #define MESH_DIAM_TRAVERSAL_TIME 50 | 24 | #define MESH_DIAM_TRAVERSAL_TIME 50 |
25 | 25 | ||
26 | #define MESH_RSSI_THRESHOLD 0 | ||
27 | |||
26 | /* | 28 | /* |
27 | * A path will be refreshed if it is used PATH_REFRESH_TIME milliseconds | 29 | * A path will be refreshed if it is used PATH_REFRESH_TIME milliseconds |
28 | * before timing out. This way it will remain ACTIVE and no data frames | 30 | * before timing out. This way it will remain ACTIVE and no data frames |
@@ -56,6 +58,7 @@ const struct mesh_config default_mesh_config = { | |||
56 | .dot11MeshHWMPRannInterval = MESH_RANN_INTERVAL, | 58 | .dot11MeshHWMPRannInterval = MESH_RANN_INTERVAL, |
57 | .dot11MeshGateAnnouncementProtocol = false, | 59 | .dot11MeshGateAnnouncementProtocol = false, |
58 | .dot11MeshForwarding = true, | 60 | .dot11MeshForwarding = true, |
61 | .rssi_threshold = MESH_RSSI_THRESHOLD, | ||
59 | }; | 62 | }; |
60 | 63 | ||
61 | const struct mesh_setup default_mesh_setup = { | 64 | const struct mesh_setup default_mesh_setup = { |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index fb1e72179117..f5a7ac3a0939 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -814,8 +814,8 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, | |||
814 | cookie); | 814 | cookie); |
815 | } | 815 | } |
816 | 816 | ||
817 | bool cfg80211_rx_mgmt(struct net_device *dev, int freq, const u8 *buf, | 817 | bool cfg80211_rx_mgmt(struct net_device *dev, int freq, int sig_mbm, |
818 | size_t len, gfp_t gfp) | 818 | const u8 *buf, size_t len, gfp_t gfp) |
819 | { | 819 | { |
820 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 820 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
821 | struct wiphy *wiphy = wdev->wiphy; | 821 | struct wiphy *wiphy = wdev->wiphy; |
@@ -854,7 +854,8 @@ bool cfg80211_rx_mgmt(struct net_device *dev, int freq, const u8 *buf, | |||
854 | /* found match! */ | 854 | /* found match! */ |
855 | 855 | ||
856 | /* Indicate the received Action frame to user space */ | 856 | /* Indicate the received Action frame to user space */ |
857 | if (nl80211_send_mgmt(rdev, dev, reg->nlpid, freq, | 857 | if (nl80211_send_mgmt(rdev, dev, reg->nlpid, |
858 | freq, sig_mbm, | ||
858 | buf, len, gfp)) | 859 | buf, len, gfp)) |
859 | continue; | 860 | continue; |
860 | 861 | ||
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 1998c3682774..39dbdf2adb12 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -204,6 +204,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
204 | .len = NL80211_HT_CAPABILITY_LEN | 204 | .len = NL80211_HT_CAPABILITY_LEN |
205 | }, | 205 | }, |
206 | [NL80211_ATTR_NOACK_MAP] = { .type = NLA_U16 }, | 206 | [NL80211_ATTR_NOACK_MAP] = { .type = NLA_U16 }, |
207 | [NL80211_ATTR_INACTIVITY_TIMEOUT] = { .type = NLA_U16 }, | ||
207 | }; | 208 | }; |
208 | 209 | ||
209 | /* policy for the key attributes */ | 210 | /* policy for the key attributes */ |
@@ -2214,6 +2215,13 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) | |||
2214 | if (err) | 2215 | if (err) |
2215 | return err; | 2216 | return err; |
2216 | 2217 | ||
2218 | if (info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]) { | ||
2219 | if (!(rdev->wiphy.features & NL80211_FEATURE_INACTIVITY_TIMER)) | ||
2220 | return -EOPNOTSUPP; | ||
2221 | params.inactivity_timeout = nla_get_u16( | ||
2222 | info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]); | ||
2223 | } | ||
2224 | |||
2217 | err = rdev->ops->start_ap(&rdev->wiphy, dev, ¶ms); | 2225 | err = rdev->ops->start_ap(&rdev->wiphy, dev, ¶ms); |
2218 | if (!err) | 2226 | if (!err) |
2219 | wdev->beacon_interval = params.beacon_interval; | 2227 | wdev->beacon_interval = params.beacon_interval; |
@@ -3290,6 +3298,8 @@ static int nl80211_get_mesh_config(struct sk_buff *skb, | |||
3290 | cur_params.dot11MeshGateAnnouncementProtocol); | 3298 | cur_params.dot11MeshGateAnnouncementProtocol); |
3291 | NLA_PUT_U8(msg, NL80211_MESHCONF_FORWARDING, | 3299 | NLA_PUT_U8(msg, NL80211_MESHCONF_FORWARDING, |
3292 | cur_params.dot11MeshForwarding); | 3300 | cur_params.dot11MeshForwarding); |
3301 | NLA_PUT_U32(msg, NL80211_MESHCONF_RSSI_THRESHOLD, | ||
3302 | cur_params.rssi_threshold); | ||
3293 | nla_nest_end(msg, pinfoattr); | 3303 | nla_nest_end(msg, pinfoattr); |
3294 | genlmsg_end(msg, hdr); | 3304 | genlmsg_end(msg, hdr); |
3295 | return genlmsg_reply(msg, info); | 3305 | return genlmsg_reply(msg, info); |
@@ -3322,6 +3332,7 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A | |||
3322 | [NL80211_MESHCONF_HWMP_RANN_INTERVAL] = { .type = NLA_U16 }, | 3332 | [NL80211_MESHCONF_HWMP_RANN_INTERVAL] = { .type = NLA_U16 }, |
3323 | [NL80211_MESHCONF_GATE_ANNOUNCEMENTS] = { .type = NLA_U8 }, | 3333 | [NL80211_MESHCONF_GATE_ANNOUNCEMENTS] = { .type = NLA_U8 }, |
3324 | [NL80211_MESHCONF_FORWARDING] = { .type = NLA_U8 }, | 3334 | [NL80211_MESHCONF_FORWARDING] = { .type = NLA_U8 }, |
3335 | [NL80211_MESHCONF_RSSI_THRESHOLD] = { .type = NLA_U32}, | ||
3325 | }; | 3336 | }; |
3326 | 3337 | ||
3327 | static const struct nla_policy | 3338 | static const struct nla_policy |
@@ -3413,6 +3424,8 @@ do {\ | |||
3413 | nla_get_u8); | 3424 | nla_get_u8); |
3414 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding, | 3425 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding, |
3415 | mask, NL80211_MESHCONF_FORWARDING, nla_get_u8); | 3426 | mask, NL80211_MESHCONF_FORWARDING, nla_get_u8); |
3427 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold, | ||
3428 | mask, NL80211_MESHCONF_RSSI_THRESHOLD, nla_get_u32); | ||
3416 | if (mask_out) | 3429 | if (mask_out) |
3417 | *mask_out = mask; | 3430 | *mask_out = mask; |
3418 | 3431 | ||
@@ -7673,7 +7686,8 @@ bool nl80211_unexpected_4addr_frame(struct net_device *dev, | |||
7673 | 7686 | ||
7674 | int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, | 7687 | int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, |
7675 | struct net_device *netdev, u32 nlpid, | 7688 | struct net_device *netdev, u32 nlpid, |
7676 | int freq, const u8 *buf, size_t len, gfp_t gfp) | 7689 | int freq, int sig_dbm, |
7690 | const u8 *buf, size_t len, gfp_t gfp) | ||
7677 | { | 7691 | { |
7678 | struct sk_buff *msg; | 7692 | struct sk_buff *msg; |
7679 | void *hdr; | 7693 | void *hdr; |
@@ -7691,6 +7705,8 @@ int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, | |||
7691 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); | 7705 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); |
7692 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); | 7706 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); |
7693 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq); | 7707 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq); |
7708 | if (sig_dbm) | ||
7709 | NLA_PUT_U32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm); | ||
7694 | NLA_PUT(msg, NL80211_ATTR_FRAME, len, buf); | 7710 | NLA_PUT(msg, NL80211_ATTR_FRAME, len, buf); |
7695 | 7711 | ||
7696 | genlmsg_end(msg, hdr); | 7712 | genlmsg_end(msg, hdr); |
@@ -7952,7 +7968,7 @@ EXPORT_SYMBOL(cfg80211_probe_status); | |||
7952 | 7968 | ||
7953 | void cfg80211_report_obss_beacon(struct wiphy *wiphy, | 7969 | void cfg80211_report_obss_beacon(struct wiphy *wiphy, |
7954 | const u8 *frame, size_t len, | 7970 | const u8 *frame, size_t len, |
7955 | int freq, gfp_t gfp) | 7971 | int freq, int sig_dbm, gfp_t gfp) |
7956 | { | 7972 | { |
7957 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | 7973 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); |
7958 | struct sk_buff *msg; | 7974 | struct sk_buff *msg; |
@@ -7975,6 +7991,8 @@ void cfg80211_report_obss_beacon(struct wiphy *wiphy, | |||
7975 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); | 7991 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); |
7976 | if (freq) | 7992 | if (freq) |
7977 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq); | 7993 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq); |
7994 | if (sig_dbm) | ||
7995 | NLA_PUT_U32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm); | ||
7978 | NLA_PUT(msg, NL80211_ATTR_FRAME, len, frame); | 7996 | NLA_PUT(msg, NL80211_ATTR_FRAME, len, frame); |
7979 | 7997 | ||
7980 | genlmsg_end(msg, hdr); | 7998 | genlmsg_end(msg, hdr); |
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index 12bf4d185abe..4ffe50df9f31 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h | |||
@@ -92,7 +92,8 @@ void nl80211_send_sta_del_event(struct cfg80211_registered_device *rdev, | |||
92 | gfp_t gfp); | 92 | gfp_t gfp); |
93 | 93 | ||
94 | int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, | 94 | int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, |
95 | struct net_device *netdev, u32 nlpid, int freq, | 95 | struct net_device *netdev, u32 nlpid, |
96 | int freq, int sig_dbm, | ||
96 | const u8 *buf, size_t len, gfp_t gfp); | 97 | const u8 *buf, size_t len, gfp_t gfp); |
97 | void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev, | 98 | void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev, |
98 | struct net_device *netdev, u64 cookie, | 99 | struct net_device *netdev, u64 cookie, |
diff --git a/net/wireless/util.c b/net/wireless/util.c index 9aa9db6c8141..1b7a08df933c 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -904,6 +904,7 @@ u16 cfg80211_calculate_bitrate(struct rate_info *rate) | |||
904 | /* do NOT round down here */ | 904 | /* do NOT round down here */ |
905 | return (bitrate + 50000) / 100000; | 905 | return (bitrate + 50000) / 100000; |
906 | } | 906 | } |
907 | EXPORT_SYMBOL(cfg80211_calculate_bitrate); | ||
907 | 908 | ||
908 | int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, | 909 | int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, |
909 | u32 beacon_int) | 910 | u32 beacon_int) |