Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f39c2bfa authored by Johannes Berg's avatar Johannes Berg
Browse files

mac80211_hwsim: refactor radio registration



In order to support dynamic radio registration in the future,
refactor the actual registration into a new function with only
minor cleanups. Since it had to change anyway, also clean up
the init error paths.

Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 3a8cc5e7
Loading
Loading
Loading
Loading
+225 −230
Original line number Diff line number Diff line
@@ -2122,70 +2122,27 @@ static const struct ieee80211_iface_combination hwsim_if_comb[] = {
	}
};

static int __init init_mac80211_hwsim(void)
static int __init mac80211_hwsim_create_radio(int idx)
{
	int i, err = 0;
	int err;
	u8 addr[ETH_ALEN];
	struct mac80211_hwsim_data *data;
	struct ieee80211_hw *hw;
	enum ieee80211_band band;
	const struct ieee80211_ops *ops;

	if (radios < 1 || radios > 100)
		return -EINVAL;

	if (channels < 1)
		return -EINVAL;

	mac80211_hwsim_mchan_ops = mac80211_hwsim_ops;
	mac80211_hwsim_mchan_ops.hw_scan = mac80211_hwsim_hw_scan;
	mac80211_hwsim_mchan_ops.cancel_hw_scan = mac80211_hwsim_cancel_hw_scan;
	mac80211_hwsim_mchan_ops.sw_scan_start = NULL;
	mac80211_hwsim_mchan_ops.sw_scan_complete = NULL;
	mac80211_hwsim_mchan_ops.remain_on_channel = mac80211_hwsim_roc;
	mac80211_hwsim_mchan_ops.cancel_remain_on_channel = mac80211_hwsim_croc;
	mac80211_hwsim_mchan_ops.add_chanctx = mac80211_hwsim_add_chanctx;
	mac80211_hwsim_mchan_ops.remove_chanctx = mac80211_hwsim_remove_chanctx;
	mac80211_hwsim_mchan_ops.change_chanctx = mac80211_hwsim_change_chanctx;
	mac80211_hwsim_mchan_ops.assign_vif_chanctx =
		mac80211_hwsim_assign_vif_chanctx;
	mac80211_hwsim_mchan_ops.unassign_vif_chanctx =
		mac80211_hwsim_unassign_vif_chanctx;
	const struct ieee80211_ops *ops = &mac80211_hwsim_ops;

	spin_lock_init(&hwsim_radio_lock);
	INIT_LIST_HEAD(&hwsim_radios);

	err = platform_driver_register(&mac80211_hwsim_driver);
	if (err)
		return err;

	hwsim_class = class_create(THIS_MODULE, "mac80211_hwsim");
	if (IS_ERR(hwsim_class)) {
		err = PTR_ERR(hwsim_class);
		goto failed_unregister_driver;
	}

	memset(addr, 0, ETH_ALEN);
	addr[0] = 0x02;

	for (i = 0; i < radios; i++) {
		printk(KERN_DEBUG "mac80211_hwsim: Initializing radio %d\n",
		       i);
		ops = &mac80211_hwsim_ops;
	if (channels > 1)
		ops = &mac80211_hwsim_mchan_ops;
	hw = ieee80211_alloc_hw(sizeof(*data), ops);
	if (!hw) {
			printk(KERN_DEBUG "mac80211_hwsim: ieee80211_alloc_hw "
			       "failed\n");
		printk(KERN_DEBUG "mac80211_hwsim: ieee80211_alloc_hw failed\n");
		err = -ENOMEM;
		goto failed;
	}
	data = hw->priv;
	data->hw = hw;

		data->dev = device_create(hwsim_class, NULL, 0, hw,
					  "hwsim%d", i);
	data->dev = device_create(hwsim_class, NULL, 0, hw, "hwsim%d", idx);
	if (IS_ERR(data->dev)) {
		printk(KERN_DEBUG
		       "mac80211_hwsim: device_create failed (%ld)\n",
@@ -2196,8 +2153,7 @@ static int __init init_mac80211_hwsim(void)
	data->dev->driver = &mac80211_hwsim_driver.driver;
	err = device_bind_driver(data->dev);
	if (err != 0) {
			printk(KERN_DEBUG
			       "mac80211_hwsim: device_bind_driver failed (%d)\n",
		printk(KERN_DEBUG "mac80211_hwsim: device_bind_driver failed (%d)\n",
		       err);
		goto failed_hw;
	}
@@ -2205,8 +2161,10 @@ static int __init init_mac80211_hwsim(void)
	skb_queue_head_init(&data->pending);

	SET_IEEE80211_DEV(hw, data->dev);
		addr[3] = i >> 8;
		addr[4] = i;
	memset(addr, 0, ETH_ALEN);
	addr[0] = 0x02;
	addr[3] = idx >> 8;
	addr[4] = idx;
	memcpy(data->addresses[0].addr, addr, ETH_ALEN);
	memcpy(data->addresses[1].addr, addr, ETH_ALEN);
	data->addresses[1].addr[0] |= 0x40;
@@ -2223,12 +2181,10 @@ static int __init init_mac80211_hwsim(void)
		hw->wiphy->n_iface_combinations = 1;
		hw->wiphy->iface_combinations = &data->if_combination;
		data->if_combination = hwsim_if_comb[0];
			data->if_combination.num_different_channels =
				data->channels;
		data->if_combination.num_different_channels = data->channels;
	} else {
		hw->wiphy->iface_combinations = hwsim_if_comb;
			hw->wiphy->n_iface_combinations =
				ARRAY_SIZE(hwsim_if_comb);
		hw->wiphy->n_iface_combinations = ARRAY_SIZE(hwsim_if_comb);
	}

	INIT_DELAYED_WORK(&data->roc_done, hw_roc_done);
@@ -2236,8 +2192,7 @@ static int __init init_mac80211_hwsim(void)

	hw->queues = 5;
	hw->offchannel_tx_hw_queue = 4;
		hw->wiphy->interface_modes =
			BIT(NL80211_IFTYPE_STATION) |
	hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
				     BIT(NL80211_IFTYPE_AP) |
				     BIT(NL80211_IFTYPE_P2P_CLIENT) |
				     BIT(NL80211_IFTYPE_P2P_GO) |
@@ -2277,15 +2232,13 @@ static int __init init_mac80211_hwsim(void)
		switch (band) {
		case IEEE80211_BAND_2GHZ:
			sband->channels = data->channels_2ghz;
				sband->n_channels =
					ARRAY_SIZE(hwsim_channels_2ghz);
			sband->n_channels = ARRAY_SIZE(hwsim_channels_2ghz);
			sband->bitrates = data->rates;
			sband->n_bitrates = ARRAY_SIZE(hwsim_rates);
			break;
		case IEEE80211_BAND_5GHZ:
			sband->channels = data->channels_5ghz;
				sband->n_channels =
					ARRAY_SIZE(hwsim_channels_5ghz);
			sband->n_channels = ARRAY_SIZE(hwsim_channels_5ghz);
			sband->bitrates = data->rates + 4;
			sband->n_bitrates = ARRAY_SIZE(hwsim_rates) - 4;
			break;
@@ -2334,7 +2287,8 @@ static int __init init_mac80211_hwsim(void)
		sband->vht_cap.vht_mcs.tx_mcs_map =
			sband->vht_cap.vht_mcs.rx_mcs_map;
	}
		/* By default all radios are belonging to the first group */

	/* By default all radios belong to the first group */
	data->group = 1;
	mutex_init(&data->mutex);

@@ -2344,21 +2298,18 @@ static int __init init_mac80211_hwsim(void)

	err = ieee80211_register_hw(hw);
	if (err < 0) {
			printk(KERN_DEBUG "mac80211_hwsim: "
			       "ieee80211_register_hw failed (%d)\n", err);
		printk(KERN_DEBUG "mac80211_hwsim: ieee80211_register_hw failed (%d)\n",
		       err);
		goto failed_hw;
	}

		wiphy_debug(hw->wiphy, "hwaddr %pm registered\n",
			    hw->wiphy->perm_addr);
	wiphy_debug(hw->wiphy, "hwaddr %pM registered\n", hw->wiphy->perm_addr);

		data->debugfs = debugfs_create_dir("hwsim",
						   hw->wiphy->debugfsdir);
		debugfs_create_file("ps", 0666, data->debugfs, data,
				    &hwsim_fops_ps);
	data->debugfs = debugfs_create_dir("hwsim", hw->wiphy->debugfsdir);
	debugfs_create_file("ps", 0666, data->debugfs, data, &hwsim_fops_ps);
	debugfs_create_file("group", 0666, data->debugfs, data,
			    &hwsim_fops_group);
		if (channels == 1)
	if (data->channels == 1)
		debugfs_create_file("dfs_simulate_radar", 0222,
				    data->debugfs,
				    data, &hwsim_simulate_radar);
@@ -2367,51 +2318,95 @@ static int __init init_mac80211_hwsim(void)
			     mac80211_hwsim_beacon,
			     CLOCK_MONOTONIC_RAW, HRTIMER_MODE_ABS);

	spin_lock_bh(&hwsim_radio_lock);
	list_add_tail(&data->list, &hwsim_radios);
	spin_unlock_bh(&hwsim_radio_lock);

	return 0;

failed_hw:
	device_unregister(data->dev);
failed_drvdata:
	ieee80211_free_hw(hw);
failed:
	return err;
}

static int __init init_mac80211_hwsim(void)
{
	int i, err;

	if (radios < 1 || radios > 100)
		return -EINVAL;

	if (channels < 1)
		return -EINVAL;

	mac80211_hwsim_mchan_ops = mac80211_hwsim_ops;
	mac80211_hwsim_mchan_ops.hw_scan = mac80211_hwsim_hw_scan;
	mac80211_hwsim_mchan_ops.cancel_hw_scan = mac80211_hwsim_cancel_hw_scan;
	mac80211_hwsim_mchan_ops.sw_scan_start = NULL;
	mac80211_hwsim_mchan_ops.sw_scan_complete = NULL;
	mac80211_hwsim_mchan_ops.remain_on_channel = mac80211_hwsim_roc;
	mac80211_hwsim_mchan_ops.cancel_remain_on_channel = mac80211_hwsim_croc;
	mac80211_hwsim_mchan_ops.add_chanctx = mac80211_hwsim_add_chanctx;
	mac80211_hwsim_mchan_ops.remove_chanctx = mac80211_hwsim_remove_chanctx;
	mac80211_hwsim_mchan_ops.change_chanctx = mac80211_hwsim_change_chanctx;
	mac80211_hwsim_mchan_ops.assign_vif_chanctx =
		mac80211_hwsim_assign_vif_chanctx;
	mac80211_hwsim_mchan_ops.unassign_vif_chanctx =
		mac80211_hwsim_unassign_vif_chanctx;

	spin_lock_init(&hwsim_radio_lock);
	INIT_LIST_HEAD(&hwsim_radios);

	err = platform_driver_register(&mac80211_hwsim_driver);
	if (err)
		return err;

	hwsim_class = class_create(THIS_MODULE, "mac80211_hwsim");
	if (IS_ERR(hwsim_class)) {
		err = PTR_ERR(hwsim_class);
		goto out_unregister_driver;
	}

	for (i = 0; i < radios; i++) {
		err = mac80211_hwsim_create_radio(i);
		if (err)
			goto out_free_radios;
	}

	hwsim_mon = alloc_netdev(0, "hwsim%d", hwsim_mon_setup);
	if (hwsim_mon == NULL) {
		err = -ENOMEM;
		goto failed;
		goto out_free_radios;
	}

	rtnl_lock();

	err = dev_alloc_name(hwsim_mon, hwsim_mon->name);
	if (err < 0)
		goto failed_mon;

	if (err < 0) {
		rtnl_unlock();
		goto out_free_radios;
	}

	err = register_netdevice(hwsim_mon);
	if (err < 0)
		goto failed_mon;

	if (err < 0) {
		rtnl_unlock();
		goto out_free_mon;
	}
	rtnl_unlock();

	err = hwsim_init_netlink();
	if (err < 0)
		goto failed_nl;
		goto out_free_mon;

	return 0;

failed_nl:
	printk(KERN_DEBUG "mac80211_hwsim: failed initializing netlink\n");
	return err;

failed_mon:
	rtnl_unlock();
out_free_mon:
	free_netdev(hwsim_mon);
out_free_radios:
	mac80211_hwsim_free();
	return err;

failed_hw:
	device_unregister(data->dev);
failed_drvdata:
	ieee80211_free_hw(hw);
failed:
	mac80211_hwsim_free();
failed_unregister_driver:
out_unregister_driver:
	platform_driver_unregister(&mac80211_hwsim_driver);
	return err;
}