/*
* Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
{
struct wil6210_priv *wil = wiphy_to_wil(wiphy);
struct net_device *ndev = wil_to_ndev(wil);
+ struct wil6210_vif *vif;
struct wireless_dev *p2p_wdev;
wil_dbg_misc(wil, "add_iface\n");
return ERR_PTR(-EINVAL);
}
- p2p_wdev = kzalloc(sizeof(*p2p_wdev), GFP_KERNEL);
- if (!p2p_wdev)
+ vif = kzalloc(sizeof(*vif), GFP_KERNEL);
+ if (!vif)
return ERR_PTR(-ENOMEM);
+ p2p_wdev = &vif->wdev;
p2p_wdev->iftype = type;
p2p_wdev->wiphy = wiphy;
/* use our primary ethernet address */
#endif
}
-struct wireless_dev *wil_cfg80211_init(struct device *dev)
+struct wil6210_priv *wil_cfg80211_init(struct device *dev)
{
- int rc = 0;
- struct wireless_dev *wdev;
+ struct wiphy *wiphy;
+ struct wil6210_priv *wil;
+ struct ieee80211_channel *ch;
dev_dbg(dev, "%s()\n", __func__);
- wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
- if (!wdev)
+ /* Note: the wireless_dev structure is no longer allocated here.
+ * Instead, it is allocated as part of the net_device structure
+ * for main interface and each VIF.
+ */
+ wiphy = wiphy_new(&wil_cfg80211_ops, sizeof(struct wil6210_priv));
+ if (!wiphy)
return ERR_PTR(-ENOMEM);
- wdev->wiphy = wiphy_new(&wil_cfg80211_ops,
- sizeof(struct wil6210_priv));
- if (!wdev->wiphy) {
- rc = -ENOMEM;
- goto out;
- }
-
- set_wiphy_dev(wdev->wiphy, dev);
- wil_wiphy_init(wdev->wiphy);
+ set_wiphy_dev(wiphy, dev);
+ wil_wiphy_init(wiphy);
- return wdev;
+ wil = wiphy_to_wil(wiphy);
+ wil->wiphy = wiphy;
-out:
- kfree(wdev);
+ /* default monitor channel */
+ ch = wiphy->bands[NL80211_BAND_60GHZ]->channels;
+ cfg80211_chandef_create(&wil->monitor_chandef, ch, NL80211_CHAN_NO_HT);
- return ERR_PTR(rc);
+ return wil;
}
-void wil_wdev_free(struct wil6210_priv *wil)
+void wil_cfg80211_deinit(struct wil6210_priv *wil)
{
- struct wireless_dev *wdev = wil_to_wdev(wil);
+ struct wiphy *wiphy = wil_to_wiphy(wil);
dev_dbg(wil_to_dev(wil), "%s()\n", __func__);
- if (!wdev)
+ if (!wiphy)
return;
- wiphy_free(wdev->wiphy);
- kfree(wdev);
+ wiphy_free(wiphy);
+ /* do not access wil6210_priv after returning from here */
}
void wil_p2p_wdev_free(struct wil6210_priv *wil)
{
struct wireless_dev *p2p_wdev;
+ struct wil6210_vif *vif;
mutex_lock(&wil->p2p_wdev_mutex);
p2p_wdev = wil->p2p_wdev;
mutex_unlock(&wil->p2p_wdev_mutex);
if (p2p_wdev) {
cfg80211_unregister_wdev(p2p_wdev);
- kfree(p2p_wdev);
+ vif = wdev_to_vif(p2p_wdev);
+ kfree(vif);
}
}
/*
* Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
dev->tx_queue_len = WIL_TX_Q_LEN_DEFAULT;
}
-void *wil_if_alloc(struct device *dev)
+struct wil6210_vif *
+wil_vif_alloc(struct wil6210_priv *wil, const char *name,
+ unsigned char name_assign_type, enum nl80211_iftype iftype,
+ u8 mid)
{
struct net_device *ndev;
struct wireless_dev *wdev;
+ struct wil6210_vif *vif;
+
+ ndev = alloc_netdev(sizeof(*vif), name, name_assign_type,
+ wil_dev_setup);
+ if (!ndev) {
+ dev_err(wil_to_dev(wil), "alloc_netdev failed\n");
+ return ERR_PTR(-ENOMEM);
+ }
+ if (mid == 0)
+ wil->ndev = ndev;
+ vif = ndev_to_vif(ndev);
+ vif->wil = wil;
+ vif->mid = mid;
+
+ wdev = &vif->wdev;
+ wdev->wiphy = wil->wiphy;
+ wdev->iftype = iftype;
+
+ ndev->netdev_ops = &wil_netdev_ops;
+ wil_set_ethtoolops(ndev);
+ ndev->ieee80211_ptr = wdev;
+ ndev->hw_features = NETIF_F_HW_CSUM | NETIF_F_RXCSUM |
+ NETIF_F_SG | NETIF_F_GRO |
+ NETIF_F_TSO | NETIF_F_TSO6 |
+ NETIF_F_RXHASH;
+
+ ndev->features |= ndev->hw_features;
+ SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
+ wdev->netdev = ndev;
+ return vif;
+}
+
+void *wil_if_alloc(struct device *dev)
+{
+ struct wireless_dev *wdev;
struct wil6210_priv *wil;
- struct ieee80211_channel *ch;
+ struct wil6210_vif *vif;
int rc = 0;
- wdev = wil_cfg80211_init(dev);
- if (IS_ERR(wdev)) {
+ wil = wil_cfg80211_init(dev);
+ if (IS_ERR(wil)) {
dev_err(dev, "wil_cfg80211_init failed\n");
- return wdev;
+ return wil;
}
- wil = wdev_to_wil(wdev);
- wil->wdev = wdev;
- wil->radio_wdev = wdev;
-
- wil_dbg_misc(wil, "if_alloc\n");
-
rc = wil_priv_init(wil);
if (rc) {
dev_err(dev, "wil_priv_init failed\n");
- goto out_wdev;
+ goto out_cfg;
}
- wdev->iftype = NL80211_IFTYPE_STATION; /* TODO */
- /* default monitor channel */
- ch = wdev->wiphy->bands[NL80211_BAND_60GHZ]->channels;
- cfg80211_chandef_create(&wil->monitor_chandef, ch, NL80211_CHAN_NO_HT);
+ wil_dbg_misc(wil, "if_alloc\n");
- ndev = alloc_netdev(0, "wlan%d", NET_NAME_UNKNOWN, wil_dev_setup);
- if (!ndev) {
- dev_err(dev, "alloc_netdev_mqs failed\n");
+ vif = wil_vif_alloc(wil, "wlan%d", NET_NAME_UNKNOWN,
+ NL80211_IFTYPE_STATION, 0);
+ if (IS_ERR(vif)) {
+ dev_err(dev, "wil_vif_alloc failed\n");
rc = -ENOMEM;
goto out_priv;
}
- ndev->netdev_ops = &wil_netdev_ops;
- wil_set_ethtoolops(ndev);
- ndev->ieee80211_ptr = wdev;
- ndev->hw_features = NETIF_F_HW_CSUM | NETIF_F_RXCSUM |
- NETIF_F_SG | NETIF_F_GRO |
- NETIF_F_TSO | NETIF_F_TSO6 |
- NETIF_F_RXHASH;
-
- ndev->features |= ndev->hw_features;
- SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
- wdev->netdev = ndev;
+ wdev = &vif->wdev;
+ wil->wdev = wdev;
+ wil->radio_wdev = wdev;
return wil;
- out_priv:
+out_priv:
wil_priv_deinit(wil);
- out_wdev:
- wil_wdev_free(wil);
+out_cfg:
+ wil_cfg80211_deinit(wil);
return ERR_PTR(rc);
}
wil_to_ndev(wil) = NULL;
free_netdev(ndev);
- wil_wdev_free(wil);
+ wil_cfg80211_deinit(wil);
}
int wil_if_add(struct wil6210_priv *wil)
{
struct wireless_dev *wdev = wil_to_wdev(wil);
- struct wiphy *wiphy = wdev->wiphy;
+ struct wiphy *wiphy = wil->wiphy;
struct net_device *ndev = wil_to_ndev(wil);
int rc;
extern u8 led_id;
extern u8 led_polarity;
+struct wil6210_vif {
+ struct wireless_dev wdev;
+ struct wil6210_priv *wil;
+ u8 mid;
+};
+
struct wil6210_priv {
struct pci_dev *pdev;
u32 bar_size;
+ struct wiphy *wiphy;
struct wireless_dev *wdev;
+ struct net_device *ndev;
void __iomem *csr;
DECLARE_BITMAP(status, wil_status_last);
u8 fw_version[ETHTOOL_FWVERS_LEN];
u32 iccm_base;
};
-#define wil_to_wiphy(i) (i->wdev->wiphy)
+#define wil_to_wiphy(i) (i->wiphy)
#define wil_to_dev(i) (wiphy_dev(wil_to_wiphy(i)))
#define wiphy_to_wil(w) (struct wil6210_priv *)(wiphy_priv(w))
#define wil_to_wdev(i) (i->wdev)
#define wdev_to_wil(w) (struct wil6210_priv *)(wdev_priv(w))
-#define wil_to_ndev(i) (wil_to_wdev(i)->netdev)
+#define wil_to_ndev(i) (i->ndev)
#define ndev_to_wil(n) (wdev_to_wil(n->ieee80211_ptr))
+#define ndev_to_vif(n) (struct wil6210_vif *)(netdev_priv(n))
+#define wdev_to_vif(w) (container_of(w, struct wil6210_vif, wdev))
__printf(2, 3)
void wil_dbg_trace(struct wil6210_priv *wil, const char *fmt, ...);
void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src,
size_t count);
+struct wil6210_vif *
+wil_vif_alloc(struct wil6210_priv *wil, const char *name,
+ unsigned char name_assign_type, enum nl80211_iftype iftype,
+ u8 mid);
void *wil_if_alloc(struct device *dev);
void wil_if_free(struct wil6210_priv *wil);
int wil_if_add(struct wil6210_priv *wil);
int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid,
struct station_info *sinfo);
-struct wireless_dev *wil_cfg80211_init(struct device *dev);
-void wil_wdev_free(struct wil6210_priv *wil);
+struct wil6210_priv *wil_cfg80211_init(struct device *dev);
+void wil_cfg80211_deinit(struct wil6210_priv *wil);
void wil_p2p_wdev_free(struct wil6210_priv *wil);
int wmi_set_mac_address(struct wil6210_priv *wil, void *addr);