diff options
author | Avinash Patil <patila@marvell.com> | 2012-05-08 21:30:15 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-05-16 12:46:34 -0400 |
commit | d6bffe8bb520bc1ce3333d05ce67f36dab9a61aa (patch) | |
tree | ce098372b8453a433ac5b27aa7136f16d12d6915 /drivers/net/wireless/mwifiex/cfg80211.c | |
parent | 03785387e1c6b236a04d595f98b014b78e585202 (diff) |
mwifiex: support for creation of AP interface
1. wiphy structure is per device; hence moved it to mwifiex_adapter
mwifiex_register_cfg80211 takes mwifiex_adapter as parameter.
This function only registers wiphy with cfg80211.
2. Creation of interfaces is moved to cfg80211 add_virtual_interface
handler.
3. Create 2 interfaces by default: station and AP
Signed-off-by: Avinash Patil <patila@marvell.com>
Signed-off-by: Yogesh Ashok Powar <yogeshp@marvell.com>
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Kiran Divekar <dkiran@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/mwifiex/cfg80211.c')
-rw-r--r-- | drivers/net/wireless/mwifiex/cfg80211.c | 142 |
1 files changed, 83 insertions, 59 deletions
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index c78ea873a63a..38d51910d13c 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -1287,6 +1287,7 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
1287 | struct mwifiex_adapter *adapter; | 1287 | struct mwifiex_adapter *adapter; |
1288 | struct net_device *dev; | 1288 | struct net_device *dev; |
1289 | void *mdev_priv; | 1289 | void *mdev_priv; |
1290 | struct wireless_dev *wdev; | ||
1290 | 1291 | ||
1291 | if (!priv) | 1292 | if (!priv) |
1292 | return NULL; | 1293 | return NULL; |
@@ -1299,12 +1300,21 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
1299 | case NL80211_IFTYPE_UNSPECIFIED: | 1300 | case NL80211_IFTYPE_UNSPECIFIED: |
1300 | case NL80211_IFTYPE_STATION: | 1301 | case NL80211_IFTYPE_STATION: |
1301 | case NL80211_IFTYPE_ADHOC: | 1302 | case NL80211_IFTYPE_ADHOC: |
1303 | priv = adapter->priv[MWIFIEX_BSS_TYPE_STA]; | ||
1302 | if (priv->bss_mode) { | 1304 | if (priv->bss_mode) { |
1303 | wiphy_err(wiphy, "cannot create multiple" | 1305 | wiphy_err(wiphy, |
1304 | " station/adhoc interfaces\n"); | 1306 | "cannot create multiple sta/adhoc ifaces\n"); |
1305 | return NULL; | 1307 | return NULL; |
1306 | } | 1308 | } |
1307 | 1309 | ||
1310 | wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); | ||
1311 | if (!wdev) | ||
1312 | return NULL; | ||
1313 | |||
1314 | wdev->wiphy = wiphy; | ||
1315 | priv->wdev = wdev; | ||
1316 | wdev->iftype = NL80211_IFTYPE_STATION; | ||
1317 | |||
1308 | if (type == NL80211_IFTYPE_UNSPECIFIED) | 1318 | if (type == NL80211_IFTYPE_UNSPECIFIED) |
1309 | priv->bss_mode = NL80211_IFTYPE_STATION; | 1319 | priv->bss_mode = NL80211_IFTYPE_STATION; |
1310 | else | 1320 | else |
@@ -1312,11 +1322,36 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
1312 | 1322 | ||
1313 | priv->bss_type = MWIFIEX_BSS_TYPE_STA; | 1323 | priv->bss_type = MWIFIEX_BSS_TYPE_STA; |
1314 | priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II; | 1324 | priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II; |
1315 | priv->bss_priority = 0; | 1325 | priv->bss_priority = MWIFIEX_BSS_ROLE_STA; |
1316 | priv->bss_role = MWIFIEX_BSS_ROLE_STA; | 1326 | priv->bss_role = MWIFIEX_BSS_ROLE_STA; |
1317 | priv->bss_num = 0; | 1327 | priv->bss_num = 0; |
1318 | 1328 | ||
1319 | break; | 1329 | break; |
1330 | case NL80211_IFTYPE_AP: | ||
1331 | priv = adapter->priv[MWIFIEX_BSS_TYPE_UAP]; | ||
1332 | |||
1333 | if (priv->bss_mode) { | ||
1334 | wiphy_err(wiphy, "Can't create multiple AP interfaces"); | ||
1335 | return NULL; | ||
1336 | } | ||
1337 | |||
1338 | wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); | ||
1339 | if (!wdev) | ||
1340 | return NULL; | ||
1341 | |||
1342 | priv->wdev = wdev; | ||
1343 | wdev->wiphy = wiphy; | ||
1344 | wdev->iftype = NL80211_IFTYPE_AP; | ||
1345 | |||
1346 | priv->bss_type = MWIFIEX_BSS_TYPE_UAP; | ||
1347 | priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II; | ||
1348 | priv->bss_priority = MWIFIEX_BSS_ROLE_UAP; | ||
1349 | priv->bss_role = MWIFIEX_BSS_ROLE_UAP; | ||
1350 | priv->bss_started = 0; | ||
1351 | priv->bss_num = 0; | ||
1352 | priv->bss_mode = type; | ||
1353 | |||
1354 | break; | ||
1320 | default: | 1355 | default: |
1321 | wiphy_err(wiphy, "type not supported\n"); | 1356 | wiphy_err(wiphy, "type not supported\n"); |
1322 | return NULL; | 1357 | return NULL; |
@@ -1329,6 +1364,15 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
1329 | goto error; | 1364 | goto error; |
1330 | } | 1365 | } |
1331 | 1366 | ||
1367 | mwifiex_init_priv_params(priv, dev); | ||
1368 | priv->netdev = dev; | ||
1369 | |||
1370 | mwifiex_setup_ht_caps(&wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap, priv); | ||
1371 | |||
1372 | if (adapter->config_bands & BAND_A) | ||
1373 | mwifiex_setup_ht_caps( | ||
1374 | &wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap, priv); | ||
1375 | |||
1332 | dev_net_set(dev, wiphy_net(wiphy)); | 1376 | dev_net_set(dev, wiphy_net(wiphy)); |
1333 | dev->ieee80211_ptr = priv->wdev; | 1377 | dev->ieee80211_ptr = priv->wdev; |
1334 | dev->ieee80211_ptr->iftype = priv->bss_mode; | 1378 | dev->ieee80211_ptr->iftype = priv->bss_mode; |
@@ -1343,9 +1387,6 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
1343 | mdev_priv = netdev_priv(dev); | 1387 | mdev_priv = netdev_priv(dev); |
1344 | *((unsigned long *) mdev_priv) = (unsigned long) priv; | 1388 | *((unsigned long *) mdev_priv) = (unsigned long) priv; |
1345 | 1389 | ||
1346 | priv->netdev = dev; | ||
1347 | mwifiex_init_priv_params(priv, dev); | ||
1348 | |||
1349 | SET_NETDEV_DEV(dev, adapter->dev); | 1390 | SET_NETDEV_DEV(dev, adapter->dev); |
1350 | 1391 | ||
1351 | /* Register network device */ | 1392 | /* Register network device */ |
@@ -1436,82 +1477,65 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { | |||
1436 | * default parameters and handler function pointers, and finally | 1477 | * default parameters and handler function pointers, and finally |
1437 | * registers the device. | 1478 | * registers the device. |
1438 | */ | 1479 | */ |
1439 | int mwifiex_register_cfg80211(struct mwifiex_private *priv) | 1480 | |
1481 | int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) | ||
1440 | { | 1482 | { |
1441 | int ret; | 1483 | int ret; |
1442 | void *wdev_priv; | 1484 | void *wdev_priv; |
1443 | struct wireless_dev *wdev; | 1485 | struct wiphy *wiphy; |
1444 | struct ieee80211_sta_ht_cap *ht_info; | 1486 | struct mwifiex_private *priv = adapter->priv[MWIFIEX_BSS_TYPE_STA]; |
1445 | u8 *country_code; | 1487 | u8 *country_code; |
1446 | 1488 | ||
1447 | wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); | 1489 | /* create a new wiphy for use with cfg80211 */ |
1448 | if (!wdev) { | 1490 | wiphy = wiphy_new(&mwifiex_cfg80211_ops, |
1449 | dev_err(priv->adapter->dev, "%s: allocating wireless device\n", | 1491 | sizeof(struct mwifiex_adapter *)); |
1450 | __func__); | 1492 | if (!wiphy) { |
1493 | dev_err(adapter->dev, "%s: creating new wiphy\n", __func__); | ||
1451 | return -ENOMEM; | 1494 | return -ENOMEM; |
1452 | } | 1495 | } |
1453 | wdev->wiphy = | 1496 | wiphy->max_scan_ssids = MWIFIEX_MAX_SSID_LIST_LENGTH; |
1454 | wiphy_new(&mwifiex_cfg80211_ops, | 1497 | wiphy->max_scan_ie_len = MWIFIEX_MAX_VSIE_LEN; |
1455 | sizeof(struct mwifiex_private *)); | 1498 | wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
1456 | if (!wdev->wiphy) { | 1499 | BIT(NL80211_IFTYPE_ADHOC) | |
1457 | kfree(wdev); | 1500 | BIT(NL80211_IFTYPE_AP); |
1458 | return -ENOMEM; | 1501 | |
1459 | } | 1502 | wiphy->bands[IEEE80211_BAND_2GHZ] = &mwifiex_band_2ghz; |
1460 | wdev->iftype = NL80211_IFTYPE_STATION; | 1503 | if (adapter->config_bands & BAND_A) |
1461 | wdev->wiphy->max_scan_ssids = 10; | 1504 | wiphy->bands[IEEE80211_BAND_5GHZ] = &mwifiex_band_5ghz; |
1462 | wdev->wiphy->max_scan_ie_len = MWIFIEX_MAX_VSIE_LEN; | 1505 | else |
1463 | wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | 1506 | wiphy->bands[IEEE80211_BAND_5GHZ] = NULL; |
1464 | BIT(NL80211_IFTYPE_ADHOC); | ||
1465 | |||
1466 | wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &mwifiex_band_2ghz; | ||
1467 | ht_info = &wdev->wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap; | ||
1468 | mwifiex_setup_ht_caps(ht_info, priv); | ||
1469 | |||
1470 | if (priv->adapter->config_bands & BAND_A) { | ||
1471 | wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &mwifiex_band_5ghz; | ||
1472 | ht_info = &wdev->wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap; | ||
1473 | mwifiex_setup_ht_caps(ht_info, priv); | ||
1474 | } else { | ||
1475 | wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL; | ||
1476 | } | ||
1477 | 1507 | ||
1478 | /* Initialize cipher suits */ | 1508 | /* Initialize cipher suits */ |
1479 | wdev->wiphy->cipher_suites = mwifiex_cipher_suites; | 1509 | wiphy->cipher_suites = mwifiex_cipher_suites; |
1480 | wdev->wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites); | 1510 | wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites); |
1481 | 1511 | ||
1482 | memcpy(wdev->wiphy->perm_addr, priv->curr_addr, ETH_ALEN); | 1512 | memcpy(wiphy->perm_addr, priv->curr_addr, ETH_ALEN); |
1483 | wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | 1513 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; |
1514 | wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | WIPHY_FLAG_CUSTOM_REGULATORY; | ||
1484 | 1515 | ||
1485 | /* Reserve space for mwifiex specific private data for BSS */ | 1516 | /* Reserve space for mwifiex specific private data for BSS */ |
1486 | wdev->wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv); | 1517 | wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv); |
1487 | 1518 | ||
1488 | wdev->wiphy->reg_notifier = mwifiex_reg_notifier; | 1519 | wiphy->reg_notifier = mwifiex_reg_notifier; |
1489 | 1520 | ||
1490 | /* Set struct mwifiex_private pointer in wiphy_priv */ | 1521 | /* Set struct mwifiex_private pointer in wiphy_priv */ |
1491 | wdev_priv = wiphy_priv(wdev->wiphy); | 1522 | wdev_priv = wiphy_priv(wiphy); |
1492 | 1523 | ||
1493 | *(unsigned long *) wdev_priv = (unsigned long) priv; | 1524 | *(unsigned long *) wdev_priv = (unsigned long) priv; |
1494 | 1525 | ||
1495 | set_wiphy_dev(wdev->wiphy, (struct device *) priv->adapter->dev); | 1526 | set_wiphy_dev(wiphy, (struct device *)priv->adapter->dev); |
1496 | 1527 | ||
1497 | ret = wiphy_register(wdev->wiphy); | 1528 | ret = wiphy_register(wiphy); |
1498 | if (ret < 0) { | 1529 | if (ret < 0) { |
1499 | dev_err(priv->adapter->dev, "%s: registering cfg80211 device\n", | 1530 | dev_err(adapter->dev, |
1500 | __func__); | 1531 | "%s: wiphy_register failed: %d\n", __func__, ret); |
1501 | wiphy_free(wdev->wiphy); | 1532 | wiphy_free(wiphy); |
1502 | kfree(wdev); | ||
1503 | return ret; | 1533 | return ret; |
1504 | } else { | ||
1505 | dev_dbg(priv->adapter->dev, | ||
1506 | "info: successfully registered wiphy device\n"); | ||
1507 | } | 1534 | } |
1508 | |||
1509 | country_code = mwifiex_11d_code_2_region(priv->adapter->region_code); | 1535 | country_code = mwifiex_11d_code_2_region(priv->adapter->region_code); |
1510 | if (country_code && regulatory_hint(wdev->wiphy, country_code)) | 1536 | if (country_code && regulatory_hint(wiphy, country_code)) |
1511 | dev_err(priv->adapter->dev, | 1537 | dev_err(adapter->dev, "regulatory_hint() failed\n"); |
1512 | "%s: regulatory_hint failed\n", __func__); | ||
1513 | |||
1514 | priv->wdev = wdev; | ||
1515 | 1538 | ||
1539 | adapter->wiphy = wiphy; | ||
1516 | return ret; | 1540 | return ret; |
1517 | } | 1541 | } |