Esempio n. 1
0
/*
 *  create a new virtual interface with the given name
 */
struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy,
					    char *name,
					    enum nl80211_iftype type,
					    u32 *flags,
					    struct vif_params *params)
{
	struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
	struct mwifiex_private *priv;
	struct net_device *dev;
	void *mdev_priv;
	struct wireless_dev *wdev;

	if (!adapter)
		return ERR_PTR(-EFAULT);

	switch (type) {
	case NL80211_IFTYPE_UNSPECIFIED:
	case NL80211_IFTYPE_STATION:
	case NL80211_IFTYPE_ADHOC:
		priv = adapter->priv[MWIFIEX_BSS_TYPE_STA];
		if (priv->bss_mode) {
			wiphy_err(wiphy,
				  "cannot create multiple sta/adhoc ifaces\n");
			return ERR_PTR(-EINVAL);
		}

		wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
		if (!wdev)
			return ERR_PTR(-ENOMEM);

		wdev->wiphy = wiphy;
		priv->wdev = wdev;
		wdev->iftype = NL80211_IFTYPE_STATION;

		if (type == NL80211_IFTYPE_UNSPECIFIED)
			priv->bss_mode = NL80211_IFTYPE_STATION;
		else
			priv->bss_mode = type;

		priv->bss_type = MWIFIEX_BSS_TYPE_STA;
		priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II;
		priv->bss_priority = MWIFIEX_BSS_ROLE_STA;
		priv->bss_role = MWIFIEX_BSS_ROLE_STA;
		priv->bss_num = 0;

		break;
	case NL80211_IFTYPE_AP:
		priv = adapter->priv[MWIFIEX_BSS_TYPE_UAP];

		if (priv->bss_mode) {
			wiphy_err(wiphy, "Can't create multiple AP interfaces");
			return ERR_PTR(-EINVAL);
		}

		wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
		if (!wdev)
			return ERR_PTR(-ENOMEM);

		priv->wdev = wdev;
		wdev->wiphy = wiphy;
		wdev->iftype = NL80211_IFTYPE_AP;

		priv->bss_type = MWIFIEX_BSS_TYPE_UAP;
		priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II;
		priv->bss_priority = MWIFIEX_BSS_ROLE_UAP;
		priv->bss_role = MWIFIEX_BSS_ROLE_UAP;
		priv->bss_started = 0;
		priv->bss_num = 0;
		priv->bss_mode = type;

		break;
	default:
		wiphy_err(wiphy, "type not supported\n");
		return ERR_PTR(-EINVAL);
	}

	dev = alloc_netdev_mq(sizeof(struct mwifiex_private *), name,
			      ether_setup, 1);
	if (!dev) {
		wiphy_err(wiphy, "no memory available for netdevice\n");
		priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
		return ERR_PTR(-ENOMEM);
	}

	mwifiex_init_priv_params(priv, dev);
	priv->netdev = dev;

	mwifiex_setup_ht_caps(&wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap, priv);

	if (adapter->config_bands & BAND_A)
		mwifiex_setup_ht_caps(
			&wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap, priv);

	dev_net_set(dev, wiphy_net(wiphy));
	dev->ieee80211_ptr = priv->wdev;
	dev->ieee80211_ptr->iftype = priv->bss_mode;
	memcpy(dev->dev_addr, wiphy->perm_addr, ETH_ALEN);
	memcpy(dev->perm_addr, wiphy->perm_addr, ETH_ALEN);
	SET_NETDEV_DEV(dev, wiphy_dev(wiphy));

	dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
	dev->watchdog_timeo = MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT;
	dev->hard_header_len += MWIFIEX_MIN_DATA_HEADER_LEN;

	mdev_priv = netdev_priv(dev);
	*((unsigned long *) mdev_priv) = (unsigned long) priv;

	SET_NETDEV_DEV(dev, adapter->dev);

	/* Register network device */
	if (register_netdevice(dev)) {
		wiphy_err(wiphy, "cannot register virtual network device\n");
		free_netdev(dev);
		priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
		return ERR_PTR(-EFAULT);
	}

	sema_init(&priv->async_sem, 1);
	priv->scan_pending_on_block = false;

	dev_dbg(adapter->dev, "info: %s: Marvell 802.11 Adapter\n", dev->name);

#ifdef CONFIG_DEBUG_FS
	mwifiex_dev_debugfs_init(priv);
#endif
	return dev;
}
Esempio n. 2
0
/*
 *  create a new virtual interface with the given name
 */
struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy,
						char *name,
						enum nl80211_iftype type,
						u32 *flags,
						struct vif_params *params)
{
	struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy);
	struct mwifiex_adapter *adapter;
	struct net_device *dev;
	void *mdev_priv;

	if (!priv)
		return NULL;

	adapter = priv->adapter;
	if (!adapter)
		return NULL;

	switch (type) {
	case NL80211_IFTYPE_UNSPECIFIED:
	case NL80211_IFTYPE_STATION:
	case NL80211_IFTYPE_ADHOC:
		if (priv->bss_mode) {
			wiphy_err(wiphy, "cannot create multiple"
					" station/adhoc interfaces\n");
			return NULL;
		}

		if (type == NL80211_IFTYPE_UNSPECIFIED)
			priv->bss_mode = NL80211_IFTYPE_STATION;
		else
			priv->bss_mode = type;

		priv->bss_type = MWIFIEX_BSS_TYPE_STA;
		priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II;
		priv->bss_priority = 0;
		priv->bss_role = MWIFIEX_BSS_ROLE_STA;
		priv->bss_index = 0;
		priv->bss_num = 0;

		break;
	default:
		wiphy_err(wiphy, "type not supported\n");
		return NULL;
	}

	dev = alloc_netdev_mq(sizeof(struct mwifiex_private *), name,
			      ether_setup, 1);
	if (!dev) {
		wiphy_err(wiphy, "no memory available for netdevice\n");
		goto error;
	}

	dev_net_set(dev, wiphy_net(wiphy));
	dev->ieee80211_ptr = priv->wdev;
	dev->ieee80211_ptr->iftype = priv->bss_mode;
	memcpy(dev->dev_addr, wiphy->perm_addr, ETH_ALEN);
	memcpy(dev->perm_addr, wiphy->perm_addr, ETH_ALEN);
	SET_NETDEV_DEV(dev, wiphy_dev(wiphy));

	dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
	dev->watchdog_timeo = MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT;
	dev->hard_header_len += MWIFIEX_MIN_DATA_HEADER_LEN;

	mdev_priv = netdev_priv(dev);
	*((unsigned long *) mdev_priv) = (unsigned long) priv;

	priv->netdev = dev;
	mwifiex_init_priv_params(priv, dev);

	SET_NETDEV_DEV(dev, adapter->dev);

	/* Register network device */
	if (register_netdevice(dev)) {
		wiphy_err(wiphy, "cannot register virtual network device\n");
		goto error;
	}

	sema_init(&priv->async_sem, 1);
	priv->scan_pending_on_block = false;

	dev_dbg(adapter->dev, "info: %s: Marvell 802.11 Adapter\n", dev->name);

#ifdef CONFIG_DEBUG_FS
	mwifiex_dev_debugfs_init(priv);
#endif
	return dev;
error:
	if (dev && (dev->reg_state == NETREG_UNREGISTERED))
		free_netdev(dev);
	priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;

	return NULL;
}