diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2008-02-08 03:48:13 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-02-29 15:37:06 -0500 |
commit | 96d510566e4908f77f03ff1436c78ae7162a17d0 (patch) | |
tree | 76b9abb66bcaf870a3ec4ee71e00f20d668e712b /net/mac80211/ieee80211.c | |
parent | 4688be308f35f1e0099140a179d95c5e63b2319d (diff) |
mac80211: defer master netdev allocation to ieee80211_register_hw
When we want to go multiqueue, we will need to know the number of
queues the hardware has for registering the master netdev. This
number is only available in ieee80211_register_hw() rather than
ieee80211_alloc_hw(), so defer allocation of the master device to
ieee80211_register_hw().
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/ieee80211.c')
-rw-r--r-- | net/mac80211/ieee80211.c | 72 |
1 files changed, 38 insertions, 34 deletions
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c index 91f06c3f4a7c..7df14799e38b 100644 --- a/net/mac80211/ieee80211.c +++ b/net/mac80211/ieee80211.c | |||
@@ -1375,9 +1375,7 @@ EXPORT_SYMBOL(ieee80211_tx_status); | |||
1375 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | 1375 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, |
1376 | const struct ieee80211_ops *ops) | 1376 | const struct ieee80211_ops *ops) |
1377 | { | 1377 | { |
1378 | struct net_device *mdev; | ||
1379 | struct ieee80211_local *local; | 1378 | struct ieee80211_local *local; |
1380 | struct ieee80211_sub_if_data *sdata; | ||
1381 | int priv_size; | 1379 | int priv_size; |
1382 | struct wiphy *wiphy; | 1380 | struct wiphy *wiphy; |
1383 | 1381 | ||
@@ -1423,22 +1421,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
1423 | BUG_ON(!ops->configure_filter); | 1421 | BUG_ON(!ops->configure_filter); |
1424 | local->ops = ops; | 1422 | local->ops = ops; |
1425 | 1423 | ||
1426 | /* for now, mdev needs sub_if_data :/ */ | ||
1427 | mdev = alloc_netdev(sizeof(struct ieee80211_sub_if_data), | ||
1428 | "wmaster%d", ether_setup); | ||
1429 | if (!mdev) { | ||
1430 | wiphy_free(wiphy); | ||
1431 | return NULL; | ||
1432 | } | ||
1433 | |||
1434 | sdata = IEEE80211_DEV_TO_SUB_IF(mdev); | ||
1435 | mdev->ieee80211_ptr = &sdata->wdev; | ||
1436 | sdata->wdev.wiphy = wiphy; | ||
1437 | |||
1438 | local->hw.queues = 1; /* default */ | 1424 | local->hw.queues = 1; /* default */ |
1439 | 1425 | ||
1440 | local->mdev = mdev; | ||
1441 | |||
1442 | local->bridge_packets = 1; | 1426 | local->bridge_packets = 1; |
1443 | 1427 | ||
1444 | local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; | 1428 | local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; |
@@ -1450,26 +1434,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
1450 | INIT_LIST_HEAD(&local->interfaces); | 1434 | INIT_LIST_HEAD(&local->interfaces); |
1451 | 1435 | ||
1452 | INIT_DELAYED_WORK(&local->scan_work, ieee80211_sta_scan_work); | 1436 | INIT_DELAYED_WORK(&local->scan_work, ieee80211_sta_scan_work); |
1453 | ieee80211_rx_bss_list_init(mdev); | ||
1454 | 1437 | ||
1455 | sta_info_init(local); | 1438 | sta_info_init(local); |
1456 | 1439 | ||
1457 | mdev->hard_start_xmit = ieee80211_master_start_xmit; | ||
1458 | mdev->open = ieee80211_master_open; | ||
1459 | mdev->stop = ieee80211_master_stop; | ||
1460 | mdev->type = ARPHRD_IEEE80211; | ||
1461 | mdev->header_ops = &ieee80211_header_ops; | ||
1462 | mdev->set_multicast_list = ieee80211_master_set_multicast_list; | ||
1463 | |||
1464 | sdata->vif.type = IEEE80211_IF_TYPE_AP; | ||
1465 | sdata->dev = mdev; | ||
1466 | sdata->local = local; | ||
1467 | sdata->u.ap.force_unicast_rateidx = -1; | ||
1468 | sdata->u.ap.max_ratectrl_rateidx = -1; | ||
1469 | ieee80211_if_sdata_init(sdata); | ||
1470 | /* no RCU needed since we're still during init phase */ | ||
1471 | list_add_tail(&sdata->list, &local->interfaces); | ||
1472 | |||
1473 | tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending, | 1440 | tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending, |
1474 | (unsigned long)local); | 1441 | (unsigned long)local); |
1475 | tasklet_disable(&local->tx_pending_tasklet); | 1442 | tasklet_disable(&local->tx_pending_tasklet); |
@@ -1492,6 +1459,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1492 | const char *name; | 1459 | const char *name; |
1493 | int result; | 1460 | int result; |
1494 | enum ieee80211_band band; | 1461 | enum ieee80211_band band; |
1462 | struct net_device *mdev; | ||
1463 | struct ieee80211_sub_if_data *sdata; | ||
1495 | 1464 | ||
1496 | /* | 1465 | /* |
1497 | * generic code guarantees at least one band, | 1466 | * generic code guarantees at least one band, |
@@ -1515,6 +1484,37 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1515 | if (result < 0) | 1484 | if (result < 0) |
1516 | return result; | 1485 | return result; |
1517 | 1486 | ||
1487 | /* for now, mdev needs sub_if_data :/ */ | ||
1488 | mdev = alloc_netdev(sizeof(struct ieee80211_sub_if_data), | ||
1489 | "wmaster%d", ether_setup); | ||
1490 | if (!mdev) | ||
1491 | goto fail_mdev_alloc; | ||
1492 | |||
1493 | sdata = IEEE80211_DEV_TO_SUB_IF(mdev); | ||
1494 | mdev->ieee80211_ptr = &sdata->wdev; | ||
1495 | sdata->wdev.wiphy = local->hw.wiphy; | ||
1496 | |||
1497 | local->mdev = mdev; | ||
1498 | |||
1499 | ieee80211_rx_bss_list_init(mdev); | ||
1500 | |||
1501 | mdev->hard_start_xmit = ieee80211_master_start_xmit; | ||
1502 | mdev->open = ieee80211_master_open; | ||
1503 | mdev->stop = ieee80211_master_stop; | ||
1504 | mdev->type = ARPHRD_IEEE80211; | ||
1505 | mdev->header_ops = &ieee80211_header_ops; | ||
1506 | mdev->set_multicast_list = ieee80211_master_set_multicast_list; | ||
1507 | |||
1508 | sdata->vif.type = IEEE80211_IF_TYPE_AP; | ||
1509 | sdata->dev = mdev; | ||
1510 | sdata->local = local; | ||
1511 | sdata->u.ap.force_unicast_rateidx = -1; | ||
1512 | sdata->u.ap.max_ratectrl_rateidx = -1; | ||
1513 | ieee80211_if_sdata_init(sdata); | ||
1514 | |||
1515 | /* no RCU needed since we're still during init phase */ | ||
1516 | list_add_tail(&sdata->list, &local->interfaces); | ||
1517 | |||
1518 | name = wiphy_dev(local->hw.wiphy)->driver->name; | 1518 | name = wiphy_dev(local->hw.wiphy)->driver->name; |
1519 | local->hw.workqueue = create_singlethread_workqueue(name); | 1519 | local->hw.workqueue = create_singlethread_workqueue(name); |
1520 | if (!local->hw.workqueue) { | 1520 | if (!local->hw.workqueue) { |
@@ -1606,6 +1606,9 @@ fail_sta_info: | |||
1606 | debugfs_hw_del(local); | 1606 | debugfs_hw_del(local); |
1607 | destroy_workqueue(local->hw.workqueue); | 1607 | destroy_workqueue(local->hw.workqueue); |
1608 | fail_workqueue: | 1608 | fail_workqueue: |
1609 | ieee80211_if_free(local->mdev); | ||
1610 | local->mdev = NULL; | ||
1611 | fail_mdev_alloc: | ||
1609 | wiphy_unregister(local->hw.wiphy); | 1612 | wiphy_unregister(local->hw.wiphy); |
1610 | return result; | 1613 | return result; |
1611 | } | 1614 | } |
@@ -1666,6 +1669,8 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) | |||
1666 | wiphy_unregister(local->hw.wiphy); | 1669 | wiphy_unregister(local->hw.wiphy); |
1667 | ieee80211_wep_free(local); | 1670 | ieee80211_wep_free(local); |
1668 | ieee80211_led_exit(local); | 1671 | ieee80211_led_exit(local); |
1672 | ieee80211_if_free(local->mdev); | ||
1673 | local->mdev = NULL; | ||
1669 | } | 1674 | } |
1670 | EXPORT_SYMBOL(ieee80211_unregister_hw); | 1675 | EXPORT_SYMBOL(ieee80211_unregister_hw); |
1671 | 1676 | ||
@@ -1673,7 +1678,6 @@ void ieee80211_free_hw(struct ieee80211_hw *hw) | |||
1673 | { | 1678 | { |
1674 | struct ieee80211_local *local = hw_to_local(hw); | 1679 | struct ieee80211_local *local = hw_to_local(hw); |
1675 | 1680 | ||
1676 | ieee80211_if_free(local->mdev); | ||
1677 | wiphy_free(local->hw.wiphy); | 1681 | wiphy_free(local->hw.wiphy); |
1678 | } | 1682 | } |
1679 | EXPORT_SYMBOL(ieee80211_free_hw); | 1683 | EXPORT_SYMBOL(ieee80211_free_hw); |