aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
diff options
context:
space:
mode:
authorArend van Spriel <arend@broadcom.com>2013-04-05 04:57:50 -0400
committerJohn W. Linville <linville@tuxdriver.com>2013-04-08 15:28:46 -0400
commit27f10e380ad912c7928e08c4d04b246e66022cc4 (patch)
tree93f8f52d32db0e78e5821e1dedfabb234b17d9e4 /drivers/net/wireless/brcm80211/brcmfmac/p2p.c
parenta0f472aca2ff1d241afc5ac1e804b50b5f3be6a4 (diff)
brcmfmac: support creation of P2P_DEVICE through user-space
The current driver code creates a P2P_DEVICE through a module parameter. This device has a dummy netdevice which is not how this interface type is intended. This patch add proper support for the P2P_DEVICE interface type. This requires a wpa_supplicant with such support as well. Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> Reviewed-by: Piotr Haber <phaber@broadcom.com> Reviewed-by: Hante Meuleman <meuleman@broadcom.com> Signed-off-by: Arend van Spriel <arend@broadcom.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmfmac/p2p.c')
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/p2p.c148
1 files changed, 139 insertions, 9 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
index e587dfb5d256..5d5d1e48a383 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
@@ -15,6 +15,7 @@
15 */ 15 */
16#include <linux/slab.h> 16#include <linux/slab.h>
17#include <linux/netdevice.h> 17#include <linux/netdevice.h>
18#include <linux/etherdevice.h>
18#include <net/cfg80211.h> 19#include <net/cfg80211.h>
19 20
20#include <brcmu_wifi.h> 21#include <brcmu_wifi.h>
@@ -455,7 +456,9 @@ static int brcmf_p2p_set_firmware(struct brcmf_if *ifp, u8 *p2p_mac)
455{ 456{
456 s32 ret = 0; 457 s32 ret = 0;
457 458
459 brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1);
458 brcmf_fil_iovar_int_set(ifp, "apsta", 1); 460 brcmf_fil_iovar_int_set(ifp, "apsta", 1);
461 brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1);
459 462
460 /* In case of COB type, firmware has default mac address 463 /* In case of COB type, firmware has default mac address
461 * After Initializing firmware, we have to set current mac address to 464 * After Initializing firmware, we have to set current mac address to
@@ -473,21 +476,29 @@ static int brcmf_p2p_set_firmware(struct brcmf_if *ifp, u8 *p2p_mac)
473 * brcmf_p2p_generate_bss_mac() - derive mac addresses for P2P. 476 * brcmf_p2p_generate_bss_mac() - derive mac addresses for P2P.
474 * 477 *
475 * @p2p: P2P specific data. 478 * @p2p: P2P specific data.
479 * @dev_addr: optional device address.
476 * 480 *
477 * P2P needs mac addresses for P2P device and interface. These are 481 * P2P needs mac addresses for P2P device and interface. If no device
478 * derived from the primary net device, ie. the permanent ethernet 482 * address it specified, these are derived from the primary net device, ie.
479 * address of the device. 483 * the permanent ethernet address of the device.
480 */ 484 */
481static void brcmf_p2p_generate_bss_mac(struct brcmf_p2p_info *p2p) 485static void brcmf_p2p_generate_bss_mac(struct brcmf_p2p_info *p2p, u8 *dev_addr)
482{ 486{
483 struct brcmf_if *pri_ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; 487 struct brcmf_if *pri_ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp;
484 struct brcmf_if *p2p_ifp = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif->ifp; 488 struct brcmf_if *p2p_ifp = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif->ifp;
489 bool local_admin = false;
490
491 if (!dev_addr || is_zero_ether_addr(dev_addr)) {
492 dev_addr = pri_ifp->mac_addr;
493 local_admin = true;
494 }
485 495
486 /* Generate the P2P Device Address. This consists of the device's 496 /* Generate the P2P Device Address. This consists of the device's
487 * primary MAC address with the locally administered bit set. 497 * primary MAC address with the locally administered bit set.
488 */ 498 */
489 memcpy(p2p->dev_addr, pri_ifp->mac_addr, ETH_ALEN); 499 memcpy(p2p->dev_addr, dev_addr, ETH_ALEN);
490 p2p->dev_addr[0] |= 0x02; 500 if (local_admin)
501 p2p->dev_addr[0] |= 0x02;
491 memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN); 502 memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN);
492 503
493 /* Generate the P2P Interface Address. If the discovery and connection 504 /* Generate the P2P Interface Address. If the discovery and connection
@@ -495,6 +506,7 @@ static void brcmf_p2p_generate_bss_mac(struct brcmf_p2p_info *p2p)
495 * different from the P2P Device Address, but also locally administered. 506 * different from the P2P Device Address, but also locally administered.
496 */ 507 */
497 memcpy(p2p->int_addr, p2p->dev_addr, ETH_ALEN); 508 memcpy(p2p->int_addr, p2p->dev_addr, ETH_ALEN);
509 p2p->int_addr[0] |= 0x02;
498 p2p->int_addr[4] ^= 0x80; 510 p2p->int_addr[4] ^= 0x80;
499} 511}
500 512
@@ -1935,7 +1947,7 @@ s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg)
1935 1947
1936 p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif; 1948 p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif;
1937 1949
1938 brcmf_p2p_generate_bss_mac(p2p); 1950 brcmf_p2p_generate_bss_mac(p2p, NULL);
1939 brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr); 1951 brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr);
1940 1952
1941 /* Initialize P2P Discovery in the firmware */ 1953 /* Initialize P2P Discovery in the firmware */
@@ -2125,13 +2137,96 @@ static int brcmf_p2p_release_p2p_if(struct brcmf_cfg80211_vif *vif)
2125} 2137}
2126 2138
2127/** 2139/**
2140 * brcmf_p2p_create_p2pdev() - create a P2P_DEVICE virtual interface.
2141 *
2142 * @p2p: P2P specific data.
2143 * @wiphy: wiphy device of new interface.
2144 * @addr: mac address for this new interface.
2145 */
2146static struct wireless_dev *brcmf_p2p_create_p2pdev(struct brcmf_p2p_info *p2p,
2147 struct wiphy *wiphy,
2148 u8 *addr)
2149{
2150 struct brcmf_cfg80211_vif *p2p_vif;
2151 struct brcmf_if *p2p_ifp;
2152 struct brcmf_if *pri_ifp;
2153 int err;
2154 u32 bssidx;
2155
2156 if (p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif)
2157 return ERR_PTR(-ENOSPC);
2158
2159 p2p_vif = brcmf_alloc_vif(p2p->cfg, NL80211_IFTYPE_P2P_DEVICE,
2160 false);
2161 if (IS_ERR(p2p_vif)) {
2162 brcmf_err("could not create discovery vif\n");
2163 return (struct wireless_dev *)p2p_vif;
2164 }
2165
2166 /* create ifp here */
2167 p2p_ifp = kzalloc(sizeof(*p2p_ifp), GFP_KERNEL);
2168 if (!p2p_ifp)
2169 return ERR_PTR(-ENOMEM);
2170
2171 p2p_vif->ifp = p2p_ifp;
2172 p2p_ifp->vif = p2p_vif;
2173
2174 p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif;
2175 brcmf_p2p_generate_bss_mac(p2p, addr);
2176 memcpy(&p2p_vif->wdev.address, p2p->dev_addr, sizeof(p2p->dev_addr));
2177
2178 pri_ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp;
2179 brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr);
2180
2181 /* Initialize P2P Discovery in the firmware */
2182 err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1);
2183 if (err < 0) {
2184 brcmf_err("set p2p_disc error\n");
2185 brcmf_free_vif(p2p_vif);
2186 return ERR_PTR(err);
2187 }
2188 /* obtain bsscfg index for P2P discovery */
2189 err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx);
2190 if (err < 0) {
2191 brcmf_err("retrieving discover bsscfg index failed\n");
2192 brcmf_free_vif(p2p_vif);
2193 return ERR_PTR(err);
2194 }
2195
2196 p2p_ifp->drvr = p2p->cfg->pub;
2197 p2p_ifp->bssidx = bssidx;
2198
2199 init_completion(&p2p->send_af_done);
2200 INIT_WORK(&p2p->afx_hdl.afx_work, brcmf_p2p_afx_handler);
2201 init_completion(&p2p->afx_hdl.act_frm_scan);
2202 init_completion(&p2p->wait_next_af);
2203
2204 return &p2p_vif->wdev;
2205}
2206
2207/**
2208 * brcmf_p2p_delete_p2pdev() - delete P2P_DEVICE virtual interface.
2209 *
2210 * @vif: virtual interface object to delete.
2211 */
2212static void brcmf_p2p_delete_p2pdev(struct brcmf_cfg80211_vif *vif)
2213{
2214 struct brcmf_p2p_info *p2p = &vif->ifp->drvr->config->p2p;
2215
2216 cfg80211_unregister_wdev(&vif->wdev);
2217 p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
2218 kfree(vif->ifp);
2219 brcmf_free_vif(vif);
2220}
2221
2222/**
2128 * brcmf_p2p_add_vif() - create a new P2P virtual interface. 2223 * brcmf_p2p_add_vif() - create a new P2P virtual interface.
2129 * 2224 *
2130 * @wiphy: wiphy device of new interface. 2225 * @wiphy: wiphy device of new interface.
2131 * @name: name of the new interface. 2226 * @name: name of the new interface.
2132 * @type: nl80211 interface type. 2227 * @type: nl80211 interface type.
2133 * @flags: TBD 2228 * @flags: not used.
2134 * @params: TBD 2229 * @params: contains mac address for P2P device.
2135 */ 2230 */
2136struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name, 2231struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name,
2137 enum nl80211_iftype type, u32 *flags, 2232 enum nl80211_iftype type, u32 *flags,
@@ -2158,6 +2253,9 @@ struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name,
2158 iftype = BRCMF_FIL_P2P_IF_GO; 2253 iftype = BRCMF_FIL_P2P_IF_GO;
2159 mode = WL_MODE_AP; 2254 mode = WL_MODE_AP;
2160 break; 2255 break;
2256 case NL80211_IFTYPE_P2P_DEVICE:
2257 return brcmf_p2p_create_p2pdev(&cfg->p2p, wiphy,
2258 params->macaddr);
2161 default: 2259 default:
2162 return ERR_PTR(-EOPNOTSUPP); 2260 return ERR_PTR(-EOPNOTSUPP);
2163 } 2261 }
@@ -2245,6 +2343,8 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
2245 break; 2343 break;
2246 2344
2247 case NL80211_IFTYPE_P2P_DEVICE: 2345 case NL80211_IFTYPE_P2P_DEVICE:
2346 brcmf_p2p_delete_p2pdev(vif);
2347 return 0;
2248 default: 2348 default:
2249 return -ENOTSUPP; 2349 return -ENOTSUPP;
2250 break; 2350 break;
@@ -2276,3 +2376,33 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
2276 2376
2277 return err; 2377 return err;
2278} 2378}
2379
2380int brcmf_p2p_start_device(struct wiphy *wiphy, struct wireless_dev *wdev)
2381{
2382 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
2383 struct brcmf_p2p_info *p2p = &cfg->p2p;
2384 struct brcmf_cfg80211_vif *vif;
2385 int err;
2386
2387 vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
2388 mutex_lock(&cfg->usr_sync);
2389 err = brcmf_p2p_enable_discovery(p2p);
2390 if (!err)
2391 set_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state);
2392 mutex_unlock(&cfg->usr_sync);
2393 return err;
2394}
2395
2396void brcmf_p2p_stop_device(struct wiphy *wiphy, struct wireless_dev *wdev)
2397{
2398 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
2399 struct brcmf_p2p_info *p2p = &cfg->p2p;
2400 struct brcmf_cfg80211_vif *vif;
2401
2402 vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
2403 mutex_lock(&cfg->usr_sync);
2404 (void)brcmf_p2p_deinit_discovery(p2p);
2405 brcmf_abort_scanning(cfg);
2406 clear_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state);
2407 mutex_unlock(&cfg->usr_sync);
2408}