wiphy->bands[band] = kzalloc(sizeof(*wiphy->bands[band]), GFP_KERNEL); if (!wiphy->bands[band]) return -ENOMEM;
wiphy->bands[band]->band = band;
ret = qtnf_cmd_band_info_get(mac, wiphy->bands[band]); if (ret) {
pr_err("MAC%u: band %u: failed to get chans info: %d\n",
mac->macid, band, ret); return ret;
}
qtnf_band_init_rates(wiphy->bands[band]);
return0;
}
staticint qtnf_mac_init_bands(struct qtnf_wmac *mac)
{ struct wiphy *wiphy = priv_to_wiphy(mac); int ret = 0;
if (mac->macinfo.bands_cap & QLINK_BAND_2GHZ) {
ret = qtnf_mac_init_single_band(wiphy, mac, NL80211_BAND_2GHZ); if (ret) goto out;
}
if (mac->macinfo.bands_cap & QLINK_BAND_5GHZ) {
ret = qtnf_mac_init_single_band(wiphy, mac, NL80211_BAND_5GHZ); if (ret) goto out;
}
if (mac->macinfo.bands_cap & QLINK_BAND_60GHZ)
ret = qtnf_mac_init_single_band(wiphy, mac, NL80211_BAND_60GHZ);
if (vif->wdev.iftype == NL80211_IFTYPE_UNSPECIFIED) return NULL;
return vif;
}
void qtnf_mac_iface_comb_free(struct qtnf_wmac *mac)
{ struct ieee80211_iface_combination *comb; int i;
if (mac->macinfo.if_comb) { for (i = 0; i < mac->macinfo.n_if_comb; i++) {
comb = &mac->macinfo.if_comb[i];
kfree(comb->limits);
comb->limits = NULL;
}
if (!(bus->hw_info.mac_bitmap & BIT(macid))) {
pr_info("MAC%u is not active in FW\n", macid); return0;
}
mac = qtnf_core_mac_alloc(bus, macid); if (IS_ERR(mac)) {
pr_err("MAC%u allocation failed\n", macid); return PTR_ERR(mac);
}
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, vif->wdev.iftype,
vif->wdev.use_4addr, vif->mac_addr); if (ret) {
pr_err("MAC%u: failed to add VIF\n", macid); goto error;
}
ret = qtnf_cmd_get_mac_info(mac); if (ret) {
pr_err("MAC%u: failed to get MAC info\n", macid); goto error_del_vif;
}
/* Use MAC address of the first active radio as a unique device ID */ if (is_zero_ether_addr(mac->bus->hw_id))
ether_addr_copy(mac->bus->hw_id, mac->macaddr);
ret = qtnf_mac_init_bands(mac); if (ret) {
pr_err("MAC%u: failed to init bands\n", macid); goto error_del_vif;
}
ret = qtnf_wiphy_register(&bus->hw_info, mac); if (ret) {
pr_err("MAC%u: wiphy registration failed\n", macid); goto error_del_vif;
}
mac->wiphy_registered = 1;
rtnl_lock();
wiphy_lock(priv_to_wiphy(mac));
ret = qtnf_core_net_attach(mac, vif, "wlan%d", NET_NAME_ENUM);
wiphy_unlock(priv_to_wiphy(mac));
rtnl_unlock();
if (ret) {
pr_err("MAC%u: failed to attach netdev\n", macid); goto error_del_vif;
}
if (qtnf_hwcap_is_set(&bus->hw_info, QLINK_HW_CAPAB_HW_BRIDGE)) {
ret = qtnf_cmd_netdev_changeupper(vif, vif->netdev->ifindex); if (ret) goto error;
}
bus->workqueue = alloc_ordered_workqueue("QTNF_BUS", 0); if (!bus->workqueue) {
pr_err("failed to alloc main workqueue\n");
ret = -ENOMEM; goto error;
}
bus->hprio_workqueue = alloc_workqueue("QTNF_HPRI", WQ_HIGHPRI, 0); if (!bus->hprio_workqueue) {
pr_err("failed to alloc high prio workqueue\n");
ret = -ENOMEM; goto error;
}
ret = qtnf_cmd_send_init_fw(bus); if (ret) {
pr_err("failed to init FW: %d\n", ret); goto error;
}
if (QLINK_VER_MAJOR(bus->hw_info.ql_proto_ver) !=
QLINK_PROTO_VER_MAJOR) {
pr_err("qlink driver vs FW version mismatch: %u vs %u\n",
QLINK_PROTO_VER_MAJOR,
QLINK_VER_MAJOR(bus->hw_info.ql_proto_ver));
ret = -EPROTONOSUPPORT; goto error;
}
bus->fw_state = QTNF_FW_STATE_ACTIVE;
ret = qtnf_cmd_get_hw_info(bus); if (ret) {
pr_err("failed to get HW info: %d\n", ret); goto error;
}
if (qtnf_hwcap_is_set(&bus->hw_info, QLINK_HW_CAPAB_HW_BRIDGE) &&
bus->bus_ops->data_tx_use_meta_set)
bus->bus_ops->data_tx_use_meta_set(bus, true);
if (bus->hw_info.num_mac > QTNF_MAX_MAC) {
pr_err("no support for number of MACs=%u\n",
bus->hw_info.num_mac);
ret = -ERANGE; goto error;
}
for (i = 0; i < bus->hw_info.num_mac; i++) {
ret = qtnf_core_mac_attach(bus, i);
if (ret) {
pr_err("MAC%u: attach failed: %d\n", i, ret); goto error;
}
}
bus->netdev_nb.notifier_call = qtnf_core_netdevice_event;
ret = register_netdevice_notifier(&bus->netdev_nb); if (ret) {
pr_err("failed to register netdev notifier: %d\n", ret); goto error;
}
void qtnf_wake_all_queues(struct net_device *ndev)
{ struct qtnf_vif *vif = qtnf_netdev_get_priv(ndev); struct qtnf_wmac *mac; struct qtnf_bus *bus; int macid; int i;
if (unlikely(!vif || !vif->mac || !vif->mac->bus)) return;
bus = vif->mac->bus;
for (macid = 0; macid < QTNF_MAX_MAC; macid++) { if (!(bus->hw_info.mac_bitmap & BIT(macid))) continue;
mac = bus->mac[macid]; for (i = 0; i < QTNF_MAX_INTF; i++) {
vif = &mac->iflist[i]; if (vif->netdev && netif_queue_stopped(vif->netdev))
netif_tx_wake_all_queues(vif->netdev);
}
}
}
EXPORT_SYMBOL_GPL(qtnf_wake_all_queues);
MODULE_AUTHOR("Quantenna Communications");
MODULE_DESCRIPTION("Quantenna 802.11 wireless LAN FullMAC driver.");
MODULE_LICENSE("GPL");
Messung V0.5 in Prozent
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.7Bemerkung:
(vorverarbeitet am 2026-10-03)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.