static struct wireless_dev *qtnf_add_virtual_intf(struct wiphy *wiphy, const char *name, unsigned char name_assign_t, enum nl80211_iftype type, struct vif_params *params) { struct qtnf_wmac *mac; struct qtnf_vif *vif; u8 *mac_addr = NULL; mac = wiphy_priv(wiphy); if (!mac) return ERR_PTR(-EFAULT); switch (type) { case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_AP: vif = qtnf_mac_get_free_vif(mac); if (!vif) { pr_err("MAC%u: no free VIF available\n", mac->macid); return ERR_PTR(-EFAULT); } eth_zero_addr(vif->mac_addr); vif->bss_priority = QTNF_DEF_BSS_PRIORITY; vif->wdev.wiphy = wiphy; vif->wdev.iftype = type; vif->sta_state = QTNF_STA_DISCONNECTED; break; default: pr_err("MAC%u: unsupported IF type %d\n", mac->macid, type); return ERR_PTR(-ENOTSUPP); } if (params) mac_addr = params->macaddr; if (qtnf_cmd_send_add_intf(vif, type, mac_addr)) { pr_err("VIF%u.%u: failed to add VIF\n", mac->macid, vif->vifid); goto err_cmd; } if (!is_valid_ether_addr(vif->mac_addr)) { pr_err("VIF%u.%u: FW reported bad MAC: %pM\n", mac->macid, vif->vifid, vif->mac_addr); goto err_mac; } if (qtnf_core_net_attach(mac, vif, name, name_assign_t, type)) { pr_err("VIF%u.%u: failed to attach netdev\n", mac->macid, vif->vifid); goto err_net; } vif->wdev.netdev = vif->netdev; return &vif->wdev; err_net: vif->netdev = NULL; err_mac: qtnf_cmd_send_del_intf(vif); err_cmd: vif->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED; return ERR_PTR(-EFAULT); }
static int qtnf_core_mac_attach(struct qtnf_bus *bus, unsigned int macid) { struct qtnf_wmac *mac; struct qtnf_vif *vif; int ret; if (!(bus->hw_info.mac_bitmap & BIT(macid))) { pr_info("MAC%u is not active in FW\n", macid); return 0; } mac = qtnf_core_mac_alloc(bus, macid); if (IS_ERR(mac)) { pr_err("MAC%u allocation failed\n", macid); return PTR_ERR(mac); } ret = qtnf_cmd_get_mac_info(mac); if (ret) { pr_err("MAC%u: failed to get info\n", macid); goto error; } vif = qtnf_mac_get_base_vif(mac); if (!vif) { pr_err("MAC%u: primary VIF is not ready\n", macid); ret = -EFAULT; goto error; } ret = qtnf_cmd_send_add_intf(vif, NL80211_IFTYPE_AP, vif->mac_addr); if (ret) { pr_err("MAC%u: failed to add VIF\n", macid); goto error; } ret = qtnf_cmd_send_get_phy_params(mac); if (ret) { pr_err("MAC%u: failed to get PHY settings\n", macid); goto error; } ret = qtnf_mac_init_bands(mac); if (ret) { pr_err("MAC%u: failed to init bands\n", macid); goto error; } ret = qtnf_wiphy_register(&bus->hw_info, mac); if (ret) { pr_err("MAC%u: wiphy registration failed\n", macid); goto error; } mac->wiphy_registered = 1; rtnl_lock(); ret = qtnf_core_net_attach(mac, vif, "wlan%d", NET_NAME_ENUM, NL80211_IFTYPE_AP); rtnl_unlock(); if (ret) { pr_err("MAC%u: failed to attach netdev\n", macid); vif->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED; vif->netdev = NULL; goto error; } pr_debug("MAC%u initialized\n", macid); return 0; error: qtnf_core_mac_detach(bus, macid); return ret; }