aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mac80211_hwsim.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/mac80211_hwsim.c')
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c103
1 files changed, 91 insertions, 12 deletions
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index d56b7859a437..d5c0a1af08b9 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -330,6 +330,83 @@ static const struct ieee80211_rate hwsim_rates[] = {
330 { .bitrate = 540 } 330 { .bitrate = 540 }
331}; 331};
332 332
333#define OUI_QCA 0x001374
334#define QCA_NL80211_SUBCMD_TEST 1
335enum qca_nl80211_vendor_subcmds {
336 QCA_WLAN_VENDOR_ATTR_TEST = 8,
337 QCA_WLAN_VENDOR_ATTR_MAX = QCA_WLAN_VENDOR_ATTR_TEST
338};
339
340static const struct nla_policy
341hwsim_vendor_test_policy[QCA_WLAN_VENDOR_ATTR_MAX + 1] = {
342 [QCA_WLAN_VENDOR_ATTR_MAX] = { .type = NLA_U32 },
343};
344
345static int mac80211_hwsim_vendor_cmd_test(struct wiphy *wiphy,
346 struct wireless_dev *wdev,
347 const void *data, int data_len)
348{
349 struct sk_buff *skb;
350 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
351 int err;
352 u32 val;
353
354 err = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
355 hwsim_vendor_test_policy);
356 if (err)
357 return err;
358 if (!tb[QCA_WLAN_VENDOR_ATTR_TEST])
359 return -EINVAL;
360 val = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_TEST]);
361 wiphy_debug(wiphy, "%s: test=%u\n", __func__, val);
362
363 /* Send a vendor event as a test. Note that this would not normally be
364 * done within a command handler, but rather, based on some other
365 * trigger. For simplicity, this command is used to trigger the event
366 * here.
367 *
368 * event_idx = 0 (index in mac80211_hwsim_vendor_commands)
369 */
370 skb = cfg80211_vendor_event_alloc(wiphy, wdev, 100, 0, GFP_KERNEL);
371 if (skb) {
372 /* skb_put() or nla_put() will fill up data within
373 * NL80211_ATTR_VENDOR_DATA.
374 */
375
376 /* Add vendor data */
377 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_TEST, val + 1);
378
379 /* Send the event - this will call nla_nest_end() */
380 cfg80211_vendor_event(skb, GFP_KERNEL);
381 }
382
383 /* Send a response to the command */
384 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, 10);
385 if (!skb)
386 return -ENOMEM;
387
388 /* skb_put() or nla_put() will fill up data within
389 * NL80211_ATTR_VENDOR_DATA
390 */
391 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_TEST, val + 2);
392
393 return cfg80211_vendor_cmd_reply(skb);
394}
395
396static struct wiphy_vendor_command mac80211_hwsim_vendor_commands[] = {
397 {
398 .info = { .vendor_id = OUI_QCA,
399 .subcmd = QCA_NL80211_SUBCMD_TEST },
400 .flags = WIPHY_VENDOR_CMD_NEED_NETDEV,
401 .doit = mac80211_hwsim_vendor_cmd_test,
402 }
403};
404
405/* Advertise support vendor specific events */
406static const struct nl80211_vendor_cmd_info mac80211_hwsim_vendor_events[] = {
407 { .vendor_id = OUI_QCA, .subcmd = 1 },
408};
409
333static const struct ieee80211_iface_limit hwsim_if_limits[] = { 410static const struct ieee80211_iface_limit hwsim_if_limits[] = {
334 { .max = 1, .types = BIT(NL80211_IFTYPE_ADHOC) }, 411 { .max = 1, .types = BIT(NL80211_IFTYPE_ADHOC) },
335 { .max = 2048, .types = BIT(NL80211_IFTYPE_STATION) | 412 { .max = 2048, .types = BIT(NL80211_IFTYPE_STATION) |
@@ -906,8 +983,7 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw,
906 goto nla_put_failure; 983 goto nla_put_failure;
907 } 984 }
908 985
909 if (nla_put(skb, HWSIM_ATTR_ADDR_TRANSMITTER, 986 if (nla_put(skb, HWSIM_ATTR_ADDR_TRANSMITTER, ETH_ALEN, hdr->addr2))
910 ETH_ALEN, data->addresses[1].addr))
911 goto nla_put_failure; 987 goto nla_put_failure;
912 988
913 /* We get the skb->data */ 989 /* We get the skb->data */
@@ -1522,21 +1598,16 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw,
1522 vp->aid = info->aid; 1598 vp->aid = info->aid;
1523 } 1599 }
1524 1600
1525 if (changed & BSS_CHANGED_BEACON_INT) {
1526 wiphy_debug(hw->wiphy, " BCNINT: %d\n", info->beacon_int);
1527 data->beacon_int = info->beacon_int * 1024;
1528 }
1529
1530 if (changed & BSS_CHANGED_BEACON_ENABLED) { 1601 if (changed & BSS_CHANGED_BEACON_ENABLED) {
1531 wiphy_debug(hw->wiphy, " BCN EN: %d\n", info->enable_beacon); 1602 wiphy_debug(hw->wiphy, " BCN EN: %d (BI=%u)\n",
1603 info->enable_beacon, info->beacon_int);
1532 vp->bcn_en = info->enable_beacon; 1604 vp->bcn_en = info->enable_beacon;
1533 if (data->started && 1605 if (data->started &&
1534 !hrtimer_is_queued(&data->beacon_timer.timer) && 1606 !hrtimer_is_queued(&data->beacon_timer.timer) &&
1535 info->enable_beacon) { 1607 info->enable_beacon) {
1536 u64 tsf, until_tbtt; 1608 u64 tsf, until_tbtt;
1537 u32 bcn_int; 1609 u32 bcn_int;
1538 if (WARN_ON(!data->beacon_int)) 1610 data->beacon_int = info->beacon_int * 1024;
1539 data->beacon_int = 1000 * 1024;
1540 tsf = mac80211_hwsim_get_tsf(hw, vif); 1611 tsf = mac80211_hwsim_get_tsf(hw, vif);
1541 bcn_int = data->beacon_int; 1612 bcn_int = data->beacon_int;
1542 until_tbtt = bcn_int - do_div(tsf, bcn_int); 1613 until_tbtt = bcn_int - do_div(tsf, bcn_int);
@@ -1550,8 +1621,10 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw,
1550 mac80211_hwsim_bcn_en_iter, &count); 1621 mac80211_hwsim_bcn_en_iter, &count);
1551 wiphy_debug(hw->wiphy, " beaconing vifs remaining: %u", 1622 wiphy_debug(hw->wiphy, " beaconing vifs remaining: %u",
1552 count); 1623 count);
1553 if (count == 0) 1624 if (count == 0) {
1554 tasklet_hrtimer_cancel(&data->beacon_timer); 1625 tasklet_hrtimer_cancel(&data->beacon_timer);
1626 data->beacon_int = 0;
1627 }
1555 } 1628 }
1556 } 1629 }
1557 1630
@@ -2420,6 +2493,12 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
2420 hw->max_rates = 4; 2493 hw->max_rates = 4;
2421 hw->max_rate_tries = 11; 2494 hw->max_rate_tries = 11;
2422 2495
2496 hw->wiphy->vendor_commands = mac80211_hwsim_vendor_commands;
2497 hw->wiphy->n_vendor_commands =
2498 ARRAY_SIZE(mac80211_hwsim_vendor_commands);
2499 hw->wiphy->vendor_events = mac80211_hwsim_vendor_events;
2500 hw->wiphy->n_vendor_events = ARRAY_SIZE(mac80211_hwsim_vendor_events);
2501
2423 if (param->reg_strict) 2502 if (param->reg_strict)
2424 hw->wiphy->regulatory_flags |= REGULATORY_STRICT_REG; 2503 hw->wiphy->regulatory_flags |= REGULATORY_STRICT_REG;
2425 if (param->regd) { 2504 if (param->regd) {
@@ -2611,7 +2690,7 @@ static struct mac80211_hwsim_data *get_hwsim_data_ref_from_addr(const u8 *addr)
2611 2690
2612 spin_lock_bh(&hwsim_radio_lock); 2691 spin_lock_bh(&hwsim_radio_lock);
2613 list_for_each_entry(data, &hwsim_radios, list) { 2692 list_for_each_entry(data, &hwsim_radios, list) {
2614 if (memcmp(data->addresses[1].addr, addr, ETH_ALEN) == 0) { 2693 if (mac80211_hwsim_addr_match(data, addr)) {
2615 _found = true; 2694 _found = true;
2616 break; 2695 break;
2617 } 2696 }