Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

wlcore: add p2p device support

When starting a p2p mgmt interface, enable its device role. This
allows us to keep the sta role disabled and scan on the dev role.

In general, p2p management interfaces cannot send vif-specific commands
to FW, as the vif role id is invalid. Only off-channel data and scans
happen on this vif, so most ops are not relevant.

If the vif is a p2p mgmt vif, block some mac80211 ops.

Configure rate policies for p2p mgmt interface, as
otherwise p2p packets come out with arbitrary rates.

Since wpa_supplicant currently doesn't support standalone
p2p device mode (without another attached managed interface),
add p2p device to the allowed interface combinations without
decreasing the allowed station count.

Moreover, increase the station count in some cases, as AP
mode usually starts as station interface, and the AP interface
is now different from the p2p management one).

Signed-off-by: Arik Nemtsov <arik@wizery.com>
Signed-off-by: Eliad Peller <eliad@wizery.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>

authored by

Eliad Peller and committed by
Kalle Valo
7845af35 c32e35f2

+136 -27
+5 -1
drivers/net/wireless/ti/wl12xx/scan.c
··· 118 118 if (passive) 119 119 scan_options |= WL1271_SCAN_OPT_PASSIVE; 120 120 121 - cmd->params.role_id = wlvif->role_id; 121 + /* scan on the dev role if the regular one is not started */ 122 + if (wlcore_is_p2p_mgmt(wlvif)) 123 + cmd->params.role_id = wlvif->dev_role_id; 124 + else 125 + cmd->params.role_id = wlvif->role_id; 122 126 123 127 if (WARN_ON(cmd->params.role_id == WL12XX_INVALID_ROLE_ID)) { 124 128 ret = -EINVAL;
+47 -1
drivers/net/wireless/ti/wl18xx/main.c
··· 1804 1804 1805 1805 static const struct ieee80211_iface_limit wl18xx_iface_limits[] = { 1806 1806 { 1807 - .max = 3, 1807 + .max = 2, 1808 1808 .types = BIT(NL80211_IFTYPE_STATION), 1809 1809 }, 1810 1810 { ··· 1813 1813 BIT(NL80211_IFTYPE_P2P_GO) | 1814 1814 BIT(NL80211_IFTYPE_P2P_CLIENT), 1815 1815 }, 1816 + { 1817 + .max = 1, 1818 + .types = BIT(NL80211_IFTYPE_P2P_DEVICE), 1819 + }, 1816 1820 }; 1817 1821 1818 1822 static const struct ieee80211_iface_limit wl18xx_iface_ap_limits[] = { 1819 1823 { 1820 1824 .max = 2, 1821 1825 .types = BIT(NL80211_IFTYPE_AP), 1826 + }, 1827 + { 1828 + .max = 1, 1829 + .types = BIT(NL80211_IFTYPE_P2P_DEVICE), 1830 + }, 1831 + }; 1832 + 1833 + static const struct ieee80211_iface_limit wl18xx_iface_ap_cl_limits[] = { 1834 + { 1835 + .max = 1, 1836 + .types = BIT(NL80211_IFTYPE_STATION), 1837 + }, 1838 + { 1839 + .max = 1, 1840 + .types = BIT(NL80211_IFTYPE_AP), 1841 + }, 1842 + { 1843 + .max = 1, 1844 + .types = BIT(NL80211_IFTYPE_P2P_CLIENT), 1845 + }, 1846 + { 1847 + .max = 1, 1848 + .types = BIT(NL80211_IFTYPE_P2P_DEVICE), 1849 + }, 1850 + }; 1851 + 1852 + static const struct ieee80211_iface_limit wl18xx_iface_ap_go_limits[] = { 1853 + { 1854 + .max = 1, 1855 + .types = BIT(NL80211_IFTYPE_STATION), 1856 + }, 1857 + { 1858 + .max = 1, 1859 + .types = BIT(NL80211_IFTYPE_AP), 1860 + }, 1861 + { 1862 + .max = 1, 1863 + .types = BIT(NL80211_IFTYPE_P2P_GO), 1864 + }, 1865 + { 1866 + .max = 1, 1867 + .types = BIT(NL80211_IFTYPE_P2P_DEVICE), 1822 1868 }, 1823 1869 }; 1824 1870
+5 -1
drivers/net/wireless/ti/wl18xx/scan.c
··· 51 51 goto out; 52 52 } 53 53 54 - cmd->role_id = wlvif->role_id; 54 + /* scan on the dev role if the regular one is not started */ 55 + if (wlcore_is_p2p_mgmt(wlvif)) 56 + cmd->role_id = wlvif->dev_role_id; 57 + else 58 + cmd->role_id = wlvif->role_id; 55 59 56 60 if (WARN_ON(cmd->role_id == WL12XX_INVALID_ROLE_ID)) { 57 61 ret = -EINVAL;
+16 -10
drivers/net/wireless/ti/wlcore/cmd.c
··· 2003 2003 wlvif->bss_type == BSS_TYPE_IBSS))) 2004 2004 return -EINVAL; 2005 2005 2006 - ret = wl12xx_cmd_role_enable(wl, 2007 - wl12xx_wlvif_to_vif(wlvif)->addr, 2008 - WL1271_ROLE_DEVICE, 2009 - &wlvif->dev_role_id); 2010 - if (ret < 0) 2011 - goto out; 2006 + /* the dev role is already started for p2p mgmt interfaces */ 2007 + if (!wlcore_is_p2p_mgmt(wlvif)) { 2008 + ret = wl12xx_cmd_role_enable(wl, 2009 + wl12xx_wlvif_to_vif(wlvif)->addr, 2010 + WL1271_ROLE_DEVICE, 2011 + &wlvif->dev_role_id); 2012 + if (ret < 0) 2013 + goto out; 2014 + } 2012 2015 2013 2016 ret = wl12xx_cmd_role_start_dev(wl, wlvif, band, channel); 2014 2017 if (ret < 0) ··· 2026 2023 out_stop: 2027 2024 wl12xx_cmd_role_stop_dev(wl, wlvif); 2028 2025 out_disable: 2029 - wl12xx_cmd_role_disable(wl, &wlvif->dev_role_id); 2026 + if (!wlcore_is_p2p_mgmt(wlvif)) 2027 + wl12xx_cmd_role_disable(wl, &wlvif->dev_role_id); 2030 2028 out: 2031 2029 return ret; 2032 2030 } ··· 2056 2052 if (ret < 0) 2057 2053 goto out; 2058 2054 2059 - ret = wl12xx_cmd_role_disable(wl, &wlvif->dev_role_id); 2060 - if (ret < 0) 2061 - goto out; 2055 + if (!wlcore_is_p2p_mgmt(wlvif)) { 2056 + ret = wl12xx_cmd_role_disable(wl, &wlvif->dev_role_id); 2057 + if (ret < 0) 2058 + goto out; 2059 + } 2062 2060 2063 2061 out: 2064 2062 return ret;
+1 -1
drivers/net/wireless/ti/wlcore/init.c
··· 348 348 } 349 349 350 350 /* generic sta initialization (non vif-specific) */ 351 - static int wl1271_sta_hw_init(struct wl1271 *wl, struct wl12xx_vif *wlvif) 351 + int wl1271_sta_hw_init(struct wl1271 *wl, struct wl12xx_vif *wlvif) 352 352 { 353 353 int ret; 354 354
+1
drivers/net/wireless/ti/wlcore/init.h
··· 35 35 int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif); 36 36 int wl1271_init_ap_rates(struct wl1271 *wl, struct wl12xx_vif *wlvif); 37 37 int wl1271_ap_init_templates(struct wl1271 *wl, struct ieee80211_vif *vif); 38 + int wl1271_sta_hw_init(struct wl1271 *wl, struct wl12xx_vif *wlvif); 38 39 39 40 #endif
+56 -13
drivers/net/wireless/ti/wlcore/main.c
··· 1792 1792 1793 1793 wl->wow_enabled = true; 1794 1794 wl12xx_for_each_wlvif(wl, wlvif) { 1795 + if (wlcore_is_p2p_mgmt(wlvif)) 1796 + continue; 1797 + 1795 1798 ret = wl1271_configure_suspend(wl, wlvif, wow); 1796 1799 if (ret < 0) { 1797 1800 mutex_unlock(&wl->mutex); ··· 1904 1901 goto out; 1905 1902 1906 1903 wl12xx_for_each_wlvif(wl, wlvif) { 1904 + if (wlcore_is_p2p_mgmt(wlvif)) 1905 + continue; 1906 + 1907 1907 wl1271_configure_resume(wl, wlvif); 1908 1908 } 1909 1909 ··· 2262 2256 wlvif->p2p = 1; 2263 2257 /* fall-through */ 2264 2258 case NL80211_IFTYPE_STATION: 2259 + case NL80211_IFTYPE_P2P_DEVICE: 2265 2260 wlvif->bss_type = BSS_TYPE_STA_BSS; 2266 2261 break; 2267 2262 case NL80211_IFTYPE_ADHOC: ··· 2484 2477 { 2485 2478 struct wlcore_hw_queue_iter_data *iter_data = data; 2486 2479 2487 - if (WARN_ON_ONCE(vif->hw_queue[0] == IEEE80211_INVAL_HW_QUEUE)) 2480 + if (vif->type == NL80211_IFTYPE_P2P_DEVICE || 2481 + WARN_ON_ONCE(vif->hw_queue[0] == IEEE80211_INVAL_HW_QUEUE)) 2488 2482 return; 2489 2483 2490 2484 if (iter_data->cur_running || vif == iter_data->vif) { ··· 2502 2494 struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); 2503 2495 struct wlcore_hw_queue_iter_data iter_data = {}; 2504 2496 int i, q_base; 2497 + 2498 + if (vif->type == NL80211_IFTYPE_P2P_DEVICE) { 2499 + vif->cab_queue = IEEE80211_INVAL_HW_QUEUE; 2500 + return 0; 2501 + } 2505 2502 2506 2503 iter_data.vif = vif; 2507 2504 ··· 2631 2618 goto out; 2632 2619 } 2633 2620 2634 - ret = wl12xx_cmd_role_enable(wl, vif->addr, 2635 - role_type, &wlvif->role_id); 2636 - if (ret < 0) 2637 - goto out; 2621 + if (!wlcore_is_p2p_mgmt(wlvif)) { 2622 + ret = wl12xx_cmd_role_enable(wl, vif->addr, 2623 + role_type, &wlvif->role_id); 2624 + if (ret < 0) 2625 + goto out; 2638 2626 2639 - ret = wl1271_init_vif_specific(wl, vif); 2640 - if (ret < 0) 2641 - goto out; 2627 + ret = wl1271_init_vif_specific(wl, vif); 2628 + if (ret < 0) 2629 + goto out; 2630 + 2631 + } else { 2632 + ret = wl12xx_cmd_role_enable(wl, vif->addr, WL1271_ROLE_DEVICE, 2633 + &wlvif->dev_role_id); 2634 + if (ret < 0) 2635 + goto out; 2636 + 2637 + /* needed mainly for configuring rate policies */ 2638 + ret = wl1271_sta_hw_init(wl, wlvif); 2639 + if (ret < 0) 2640 + goto out; 2641 + } 2642 2642 2643 2643 list_add(&wlvif->list, &wl->wlvif_list); 2644 2644 set_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags); ··· 2722 2696 wl12xx_stop_dev(wl, wlvif); 2723 2697 } 2724 2698 2725 - ret = wl12xx_cmd_role_disable(wl, &wlvif->role_id); 2726 - if (ret < 0) 2727 - goto deinit; 2699 + if (!wlcore_is_p2p_mgmt(wlvif)) { 2700 + ret = wl12xx_cmd_role_disable(wl, &wlvif->role_id); 2701 + if (ret < 0) 2702 + goto deinit; 2703 + } else { 2704 + ret = wl12xx_cmd_role_disable(wl, &wlvif->dev_role_id); 2705 + if (ret < 0) 2706 + goto deinit; 2707 + } 2728 2708 2729 2709 wl1271_ps_elp_sleep(wl); 2730 2710 } ··· 3120 3088 { 3121 3089 int ret; 3122 3090 3091 + if (wlcore_is_p2p_mgmt(wlvif)) 3092 + return 0; 3093 + 3123 3094 if (conf->power_level != wlvif->power_level) { 3124 3095 ret = wl1271_acx_tx_power(wl, wlvif, conf->power_level); 3125 3096 if (ret < 0) ··· 3242 3207 goto out; 3243 3208 3244 3209 wl12xx_for_each_wlvif(wl, wlvif) { 3210 + if (wlcore_is_p2p_mgmt(wlvif)) 3211 + continue; 3212 + 3245 3213 if (wlvif->bss_type != BSS_TYPE_AP_BSS) { 3246 3214 if (*total & FIF_ALLMULTI) 3247 3215 ret = wl1271_acx_group_address_tbl(wl, wlvif, ··· 4875 4837 u8 ps_scheme; 4876 4838 int ret = 0; 4877 4839 4840 + if (wlcore_is_p2p_mgmt(wlvif)) 4841 + return 0; 4842 + 4878 4843 mutex_lock(&wl->mutex); 4879 4844 4880 4845 wl1271_debug(DEBUG_MAC80211, "mac80211 conf tx %d", queue); ··· 6119 6078 wl->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); 6120 6079 6121 6080 wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | 6122 - BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP) | 6123 - BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO); 6081 + BIT(NL80211_IFTYPE_AP) | 6082 + BIT(NL80211_IFTYPE_P2P_DEVICE) | 6083 + BIT(NL80211_IFTYPE_P2P_CLIENT) | 6084 + BIT(NL80211_IFTYPE_P2P_GO); 6124 6085 wl->hw->wiphy->max_scan_ssids = 1; 6125 6086 wl->hw->wiphy->max_sched_scan_ssids = 16; 6126 6087 wl->hw->wiphy->max_match_sets = 16;
+5
drivers/net/wireless/ti/wlcore/wlcore_i.h
··· 503 503 return container_of((void *)wlvif, struct ieee80211_vif, drv_priv); 504 504 } 505 505 506 + static inline bool wlcore_is_p2p_mgmt(struct wl12xx_vif *wlvif) 507 + { 508 + return wl12xx_wlvif_to_vif(wlvif)->type == NL80211_IFTYPE_P2P_DEVICE; 509 + } 510 + 506 511 #define wl12xx_for_each_wlvif(wl, wlvif) \ 507 512 list_for_each_entry(wlvif, &wl->wlvif_list, list) 508 513