2020-02-13 11:46:33

by Sergey Matyukevich

[permalink] [raw]
Subject: [PATCH 4/5] qtnfmac: assign each wiphy to its own virtual platform device

Quantenna Pearl device exposes multiple (up to 3) radio interfaces under
single PCIe function. So far all the wiphy devices were attached to the
same pcie device. As a result, all different wireless network devices
were reported under the same sysfs directory for pcie device, e.g.:

$ ls /sys/class/net/wlan0/device/net/
wlan0 wlan1

It turns out that such behavior may confuse various users of wireless
subsystem. For instance, it turned out to be the case for:
- Linux init systems, e.g. for renaming based on parent device
- OpenWRT configuration scripts

Suggested solution is to add an intermediate virtual platform device
for each radio interface.

Signed-off-by: Sergey Matyukevich <[email protected]>
---
drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 8 ++++++--
drivers/net/wireless/quantenna/qtnfmac/core.c | 18 ++++++++++++++----
drivers/net/wireless/quantenna/qtnfmac/core.h | 5 ++++-
3 files changed, 24 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 722d5caefe3c..018d3ed75fda 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -1061,7 +1061,8 @@ static void qtnf_cfg80211_reg_notifier(struct wiphy *wiphy,
}
}

-struct wiphy *qtnf_wiphy_allocate(struct qtnf_bus *bus)
+struct wiphy *qtnf_wiphy_allocate(struct qtnf_bus *bus,
+ struct platform_device *pdev)
{
struct wiphy *wiphy;

@@ -1076,7 +1077,10 @@ struct wiphy *qtnf_wiphy_allocate(struct qtnf_bus *bus)
if (!wiphy)
return NULL;

- set_wiphy_dev(wiphy, bus->dev);
+ if (pdev)
+ set_wiphy_dev(wiphy, &pdev->dev);
+ else
+ set_wiphy_dev(wiphy, bus->dev);

return wiphy;
}
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.c b/drivers/net/wireless/quantenna/qtnfmac/core.c
index 9e666fac8b5f..eea777f8acea 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.c
@@ -431,18 +431,28 @@ static void qtnf_vif_send_data_high_pri(struct work_struct *work)
static struct qtnf_wmac *qtnf_core_mac_alloc(struct qtnf_bus *bus,
unsigned int macid)
{
+ struct platform_device *pdev = NULL;
+ struct qtnf_wmac *mac;
struct qtnf_vif *vif;
struct wiphy *wiphy;
- struct qtnf_wmac *mac;
unsigned int i;

- wiphy = qtnf_wiphy_allocate(bus);
+ if (bus->hw_info.num_mac > 1) {
+ pdev = platform_device_register_data(bus->dev,
+ dev_name(bus->dev),
+ macid, NULL, 0);
+ if (IS_ERR(pdev))
+ return ERR_PTR(-EINVAL);
+ }
+
+ wiphy = qtnf_wiphy_allocate(bus, pdev);
if (!wiphy)
return ERR_PTR(-ENOMEM);

mac = wiphy_priv(wiphy);

mac->macid = macid;
+ mac->pdev = pdev;
mac->bus = bus;
mutex_init(&mac->mac_lock);
INIT_DELAYED_WORK(&mac->scan_timeout, qtnf_mac_scan_timeout);
@@ -493,7 +503,6 @@ int qtnf_core_net_attach(struct qtnf_wmac *mac, struct qtnf_vif *vif,
dev_net_set(dev, wiphy_net(wiphy));
dev->ieee80211_ptr = &vif->wdev;
ether_addr_copy(dev->dev_addr, vif->mac_addr);
- SET_NETDEV_DEV(dev, wiphy_dev(wiphy));
dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
dev->watchdog_timeo = QTNF_DEF_WDOG_TIMEOUT;
dev->tx_queue_len = 100;
@@ -505,7 +514,7 @@ int qtnf_core_net_attach(struct qtnf_wmac *mac, struct qtnf_vif *vif,
qdev_vif = netdev_priv(dev);
*((void **)qdev_vif) = vif;

- SET_NETDEV_DEV(dev, mac->bus->dev);
+ SET_NETDEV_DEV(dev, wiphy_dev(wiphy));

ret = register_netdevice(dev);
if (ret) {
@@ -561,6 +570,7 @@ static void qtnf_core_mac_detach(struct qtnf_bus *bus, unsigned int macid)
wiphy->bands[band] = NULL;
}

+ platform_device_unregister(mac->pdev);
qtnf_mac_iface_comb_free(mac);
qtnf_mac_ext_caps_free(mac);
kfree(mac->macinfo.wowlan);
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h b/drivers/net/wireless/quantenna/qtnfmac/core.h
index b993f9ca14c5..269ce12cf8bf 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.h
@@ -20,6 +20,7 @@
#include <linux/ctype.h>
#include <linux/workqueue.h>
#include <linux/slab.h>
+#include <linux/platform_device.h>

#include "qlink.h"
#include "trans.h"
@@ -107,6 +108,7 @@ struct qtnf_wmac {
struct mutex mac_lock; /* lock during wmac speicific ops */
struct delayed_work scan_timeout;
struct ieee80211_regdomain *rd;
+ struct platform_device *pdev;
};

struct qtnf_hw_info {
@@ -127,7 +129,8 @@ void qtnf_mac_iface_comb_free(struct qtnf_wmac *mac);
void qtnf_mac_ext_caps_free(struct qtnf_wmac *mac);
bool qtnf_slave_radar_get(void);
bool qtnf_dfs_offload_get(void);
-struct wiphy *qtnf_wiphy_allocate(struct qtnf_bus *bus);
+struct wiphy *qtnf_wiphy_allocate(struct qtnf_bus *bus,
+ struct platform_device *pdev);
int qtnf_core_net_attach(struct qtnf_wmac *mac, struct qtnf_vif *priv,
const char *name, unsigned char name_assign_type);
void qtnf_main_work_queue(struct work_struct *work);
--
2.11.0