18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0+ */ 28c2ecf20Sopenharmony_ci/* Copyright (c) 2015 Quantenna Communications. All rights reserved. */ 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci#ifndef QTNFMAC_BUS_H 58c2ecf20Sopenharmony_ci#define QTNFMAC_BUS_H 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <linux/netdevice.h> 88c2ecf20Sopenharmony_ci#include <linux/workqueue.h> 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include "trans.h" 118c2ecf20Sopenharmony_ci#include "core.h" 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#define QTNF_MAX_MAC 3 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#define HBM_FRAME_META_MAGIC_PATTERN_S 0xAB 168c2ecf20Sopenharmony_ci#define HBM_FRAME_META_MAGIC_PATTERN_E 0xBA 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_cistruct qtnf_frame_meta_info { 198c2ecf20Sopenharmony_ci u8 magic_s; 208c2ecf20Sopenharmony_ci u8 ifidx; 218c2ecf20Sopenharmony_ci u8 macid; 228c2ecf20Sopenharmony_ci u8 magic_e; 238c2ecf20Sopenharmony_ci} __packed; 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_cienum qtnf_fw_state { 268c2ecf20Sopenharmony_ci QTNF_FW_STATE_DETACHED, 278c2ecf20Sopenharmony_ci QTNF_FW_STATE_BOOT_DONE, 288c2ecf20Sopenharmony_ci QTNF_FW_STATE_ACTIVE, 298c2ecf20Sopenharmony_ci QTNF_FW_STATE_RUNNING, 308c2ecf20Sopenharmony_ci QTNF_FW_STATE_DEAD, 318c2ecf20Sopenharmony_ci}; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistruct qtnf_bus; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_cistruct qtnf_bus_ops { 368c2ecf20Sopenharmony_ci /* mgmt methods */ 378c2ecf20Sopenharmony_ci int (*preinit)(struct qtnf_bus *); 388c2ecf20Sopenharmony_ci void (*stop)(struct qtnf_bus *); 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci /* control path methods */ 418c2ecf20Sopenharmony_ci int (*control_tx)(struct qtnf_bus *, struct sk_buff *); 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci /* data xfer methods */ 448c2ecf20Sopenharmony_ci int (*data_tx)(struct qtnf_bus *bus, struct sk_buff *skb, 458c2ecf20Sopenharmony_ci unsigned int macid, unsigned int vifid); 468c2ecf20Sopenharmony_ci void (*data_tx_timeout)(struct qtnf_bus *, struct net_device *); 478c2ecf20Sopenharmony_ci void (*data_tx_use_meta_set)(struct qtnf_bus *bus, bool use_meta); 488c2ecf20Sopenharmony_ci void (*data_rx_start)(struct qtnf_bus *); 498c2ecf20Sopenharmony_ci void (*data_rx_stop)(struct qtnf_bus *); 508c2ecf20Sopenharmony_ci}; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_cistruct qtnf_bus { 538c2ecf20Sopenharmony_ci struct device *dev; 548c2ecf20Sopenharmony_ci enum qtnf_fw_state fw_state; 558c2ecf20Sopenharmony_ci u32 chip; 568c2ecf20Sopenharmony_ci u32 chiprev; 578c2ecf20Sopenharmony_ci struct qtnf_bus_ops *bus_ops; 588c2ecf20Sopenharmony_ci struct qtnf_wmac *mac[QTNF_MAX_MAC]; 598c2ecf20Sopenharmony_ci struct qtnf_qlink_transport trans; 608c2ecf20Sopenharmony_ci struct qtnf_hw_info hw_info; 618c2ecf20Sopenharmony_ci struct napi_struct mux_napi; 628c2ecf20Sopenharmony_ci struct net_device mux_dev; 638c2ecf20Sopenharmony_ci struct workqueue_struct *workqueue; 648c2ecf20Sopenharmony_ci struct workqueue_struct *hprio_workqueue; 658c2ecf20Sopenharmony_ci struct work_struct fw_work; 668c2ecf20Sopenharmony_ci struct work_struct event_work; 678c2ecf20Sopenharmony_ci struct mutex bus_lock; /* lock during command/event processing */ 688c2ecf20Sopenharmony_ci struct dentry *dbg_dir; 698c2ecf20Sopenharmony_ci struct notifier_block netdev_nb; 708c2ecf20Sopenharmony_ci u8 hw_id[ETH_ALEN]; 718c2ecf20Sopenharmony_ci /* bus private data */ 728c2ecf20Sopenharmony_ci char bus_priv[] __aligned(sizeof(void *)); 738c2ecf20Sopenharmony_ci}; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_cistatic inline bool qtnf_fw_is_up(struct qtnf_bus *bus) 768c2ecf20Sopenharmony_ci{ 778c2ecf20Sopenharmony_ci enum qtnf_fw_state state = bus->fw_state; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci return ((state == QTNF_FW_STATE_ACTIVE) || 808c2ecf20Sopenharmony_ci (state == QTNF_FW_STATE_RUNNING)); 818c2ecf20Sopenharmony_ci} 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_cistatic inline bool qtnf_fw_is_attached(struct qtnf_bus *bus) 848c2ecf20Sopenharmony_ci{ 858c2ecf20Sopenharmony_ci enum qtnf_fw_state state = bus->fw_state; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci return ((state == QTNF_FW_STATE_ACTIVE) || 888c2ecf20Sopenharmony_ci (state == QTNF_FW_STATE_RUNNING) || 898c2ecf20Sopenharmony_ci (state == QTNF_FW_STATE_DEAD)); 908c2ecf20Sopenharmony_ci} 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_cistatic inline void *get_bus_priv(struct qtnf_bus *bus) 938c2ecf20Sopenharmony_ci{ 948c2ecf20Sopenharmony_ci if (WARN(!bus, "qtnfmac: invalid bus pointer")) 958c2ecf20Sopenharmony_ci return NULL; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci return &bus->bus_priv; 988c2ecf20Sopenharmony_ci} 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci/* callback wrappers */ 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_cistatic inline int qtnf_bus_preinit(struct qtnf_bus *bus) 1038c2ecf20Sopenharmony_ci{ 1048c2ecf20Sopenharmony_ci if (!bus->bus_ops->preinit) 1058c2ecf20Sopenharmony_ci return 0; 1068c2ecf20Sopenharmony_ci return bus->bus_ops->preinit(bus); 1078c2ecf20Sopenharmony_ci} 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_cistatic inline void qtnf_bus_stop(struct qtnf_bus *bus) 1108c2ecf20Sopenharmony_ci{ 1118c2ecf20Sopenharmony_ci if (!bus->bus_ops->stop) 1128c2ecf20Sopenharmony_ci return; 1138c2ecf20Sopenharmony_ci bus->bus_ops->stop(bus); 1148c2ecf20Sopenharmony_ci} 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_cistatic inline int qtnf_bus_data_tx(struct qtnf_bus *bus, struct sk_buff *skb, 1178c2ecf20Sopenharmony_ci unsigned int macid, unsigned int vifid) 1188c2ecf20Sopenharmony_ci{ 1198c2ecf20Sopenharmony_ci return bus->bus_ops->data_tx(bus, skb, macid, vifid); 1208c2ecf20Sopenharmony_ci} 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_cistatic inline void 1238c2ecf20Sopenharmony_ciqtnf_bus_data_tx_timeout(struct qtnf_bus *bus, struct net_device *ndev) 1248c2ecf20Sopenharmony_ci{ 1258c2ecf20Sopenharmony_ci return bus->bus_ops->data_tx_timeout(bus, ndev); 1268c2ecf20Sopenharmony_ci} 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_cistatic inline int qtnf_bus_control_tx(struct qtnf_bus *bus, struct sk_buff *skb) 1298c2ecf20Sopenharmony_ci{ 1308c2ecf20Sopenharmony_ci return bus->bus_ops->control_tx(bus, skb); 1318c2ecf20Sopenharmony_ci} 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_cistatic inline void qtnf_bus_data_rx_start(struct qtnf_bus *bus) 1348c2ecf20Sopenharmony_ci{ 1358c2ecf20Sopenharmony_ci return bus->bus_ops->data_rx_start(bus); 1368c2ecf20Sopenharmony_ci} 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_cistatic inline void qtnf_bus_data_rx_stop(struct qtnf_bus *bus) 1398c2ecf20Sopenharmony_ci{ 1408c2ecf20Sopenharmony_ci return bus->bus_ops->data_rx_stop(bus); 1418c2ecf20Sopenharmony_ci} 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_cistatic __always_inline void qtnf_bus_lock(struct qtnf_bus *bus) 1448c2ecf20Sopenharmony_ci{ 1458c2ecf20Sopenharmony_ci mutex_lock(&bus->bus_lock); 1468c2ecf20Sopenharmony_ci} 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_cistatic __always_inline void qtnf_bus_unlock(struct qtnf_bus *bus) 1498c2ecf20Sopenharmony_ci{ 1508c2ecf20Sopenharmony_ci mutex_unlock(&bus->bus_lock); 1518c2ecf20Sopenharmony_ci} 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci/* interface functions from common layer */ 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ciint qtnf_core_attach(struct qtnf_bus *bus); 1568c2ecf20Sopenharmony_civoid qtnf_core_detach(struct qtnf_bus *bus); 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci#endif /* QTNFMAC_BUS_H */ 159