1ff233cb5SSergey Matyukevich /* SPDX-License-Identifier: GPL-2.0+ */ 2ff233cb5SSergey Matyukevich /* Copyright (c) 2015 Quantenna Communications. All rights reserved. */ 398f44cb0SIgor Mitsyanko 498f44cb0SIgor Mitsyanko #ifndef QTNFMAC_BUS_H 598f44cb0SIgor Mitsyanko #define QTNFMAC_BUS_H 698f44cb0SIgor Mitsyanko 798f44cb0SIgor Mitsyanko #include <linux/netdevice.h> 898f44cb0SIgor Mitsyanko #include <linux/workqueue.h> 998f44cb0SIgor Mitsyanko 105163309eSIgor Mitsyanko #include "trans.h" 115163309eSIgor Mitsyanko #include "core.h" 125163309eSIgor Mitsyanko 1398f44cb0SIgor Mitsyanko #define QTNF_MAX_MAC 3 1498f44cb0SIgor Mitsyanko 15904628d3SIgor Mitsyanko #define HBM_FRAME_META_MAGIC_PATTERN_S 0xAB 16904628d3SIgor Mitsyanko #define HBM_FRAME_META_MAGIC_PATTERN_E 0xBA 17904628d3SIgor Mitsyanko 18904628d3SIgor Mitsyanko struct qtnf_frame_meta_info { 19904628d3SIgor Mitsyanko u8 magic_s; 20904628d3SIgor Mitsyanko u8 ifidx; 21904628d3SIgor Mitsyanko u8 macid; 22904628d3SIgor Mitsyanko u8 magic_e; 23904628d3SIgor Mitsyanko } __packed; 24904628d3SIgor Mitsyanko 2598f44cb0SIgor Mitsyanko enum qtnf_fw_state { 2683b00f6eSSergey Matyukevich QTNF_FW_STATE_DETACHED, 2798f44cb0SIgor Mitsyanko QTNF_FW_STATE_BOOT_DONE, 2898f44cb0SIgor Mitsyanko QTNF_FW_STATE_ACTIVE, 2983b00f6eSSergey Matyukevich QTNF_FW_STATE_RUNNING, 3083b00f6eSSergey Matyukevich QTNF_FW_STATE_DEAD, 3198f44cb0SIgor Mitsyanko }; 3298f44cb0SIgor Mitsyanko 3398f44cb0SIgor Mitsyanko struct qtnf_bus; 3498f44cb0SIgor Mitsyanko 3598f44cb0SIgor Mitsyanko struct qtnf_bus_ops { 3698f44cb0SIgor Mitsyanko /* mgmt methods */ 3798f44cb0SIgor Mitsyanko int (*preinit)(struct qtnf_bus *); 3898f44cb0SIgor Mitsyanko void (*stop)(struct qtnf_bus *); 3998f44cb0SIgor Mitsyanko 4098f44cb0SIgor Mitsyanko /* control path methods */ 4198f44cb0SIgor Mitsyanko int (*control_tx)(struct qtnf_bus *, struct sk_buff *); 4298f44cb0SIgor Mitsyanko 4398f44cb0SIgor Mitsyanko /* data xfer methods */ 44904628d3SIgor Mitsyanko int (*data_tx)(struct qtnf_bus *bus, struct sk_buff *skb, 45904628d3SIgor Mitsyanko unsigned int macid, unsigned int vifid); 4698f44cb0SIgor Mitsyanko void (*data_tx_timeout)(struct qtnf_bus *, struct net_device *); 47904628d3SIgor Mitsyanko void (*data_tx_use_meta_set)(struct qtnf_bus *bus, bool use_meta); 4898f44cb0SIgor Mitsyanko void (*data_rx_start)(struct qtnf_bus *); 4998f44cb0SIgor Mitsyanko void (*data_rx_stop)(struct qtnf_bus *); 5098f44cb0SIgor Mitsyanko }; 5198f44cb0SIgor Mitsyanko 5298f44cb0SIgor Mitsyanko struct qtnf_bus { 5398f44cb0SIgor Mitsyanko struct device *dev; 5498f44cb0SIgor Mitsyanko enum qtnf_fw_state fw_state; 5598f44cb0SIgor Mitsyanko u32 chip; 5698f44cb0SIgor Mitsyanko u32 chiprev; 57904628d3SIgor Mitsyanko struct qtnf_bus_ops *bus_ops; 5898f44cb0SIgor Mitsyanko struct qtnf_wmac *mac[QTNF_MAX_MAC]; 5998f44cb0SIgor Mitsyanko struct qtnf_qlink_transport trans; 6098f44cb0SIgor Mitsyanko struct qtnf_hw_info hw_info; 6198f44cb0SIgor Mitsyanko struct napi_struct mux_napi; 6298f44cb0SIgor Mitsyanko struct net_device mux_dev; 6398f44cb0SIgor Mitsyanko struct workqueue_struct *workqueue; 64bc70732fSIgor Mitsyanko struct workqueue_struct *hprio_workqueue; 65c3b2f7caSSergey Matyukevich struct work_struct fw_work; 6698f44cb0SIgor Mitsyanko struct work_struct event_work; 6798f44cb0SIgor Mitsyanko struct mutex bus_lock; /* lock during command/event processing */ 6898f44cb0SIgor Mitsyanko struct dentry *dbg_dir; 69decfc5c7SIgor Mitsyanko struct notifier_block netdev_nb; 704e14e76cSIgor Mitsyanko u8 hw_id[ETH_ALEN]; 7198f44cb0SIgor Mitsyanko /* bus private data */ 72*55bb8a2bSGustavo A. R. Silva char bus_priv[] __aligned(sizeof(void *)); 7398f44cb0SIgor Mitsyanko }; 7498f44cb0SIgor Mitsyanko 7583b00f6eSSergey Matyukevich static inline bool qtnf_fw_is_up(struct qtnf_bus *bus) 7683b00f6eSSergey Matyukevich { 7783b00f6eSSergey Matyukevich enum qtnf_fw_state state = bus->fw_state; 7883b00f6eSSergey Matyukevich 7983b00f6eSSergey Matyukevich return ((state == QTNF_FW_STATE_ACTIVE) || 8083b00f6eSSergey Matyukevich (state == QTNF_FW_STATE_RUNNING)); 8183b00f6eSSergey Matyukevich } 8283b00f6eSSergey Matyukevich 8383b00f6eSSergey Matyukevich static inline bool qtnf_fw_is_attached(struct qtnf_bus *bus) 8483b00f6eSSergey Matyukevich { 8583b00f6eSSergey Matyukevich enum qtnf_fw_state state = bus->fw_state; 8683b00f6eSSergey Matyukevich 8783b00f6eSSergey Matyukevich return ((state == QTNF_FW_STATE_ACTIVE) || 8883b00f6eSSergey Matyukevich (state == QTNF_FW_STATE_RUNNING) || 8983b00f6eSSergey Matyukevich (state == QTNF_FW_STATE_DEAD)); 9083b00f6eSSergey Matyukevich } 9183b00f6eSSergey Matyukevich 9298f44cb0SIgor Mitsyanko static inline void *get_bus_priv(struct qtnf_bus *bus) 9398f44cb0SIgor Mitsyanko { 9498f44cb0SIgor Mitsyanko if (WARN(!bus, "qtnfmac: invalid bus pointer")) 9598f44cb0SIgor Mitsyanko return NULL; 9698f44cb0SIgor Mitsyanko 9798f44cb0SIgor Mitsyanko return &bus->bus_priv; 9898f44cb0SIgor Mitsyanko } 9998f44cb0SIgor Mitsyanko 10098f44cb0SIgor Mitsyanko /* callback wrappers */ 10198f44cb0SIgor Mitsyanko 10298f44cb0SIgor Mitsyanko static inline int qtnf_bus_preinit(struct qtnf_bus *bus) 10398f44cb0SIgor Mitsyanko { 10498f44cb0SIgor Mitsyanko if (!bus->bus_ops->preinit) 10598f44cb0SIgor Mitsyanko return 0; 10698f44cb0SIgor Mitsyanko return bus->bus_ops->preinit(bus); 10798f44cb0SIgor Mitsyanko } 10898f44cb0SIgor Mitsyanko 10998f44cb0SIgor Mitsyanko static inline void qtnf_bus_stop(struct qtnf_bus *bus) 11098f44cb0SIgor Mitsyanko { 11198f44cb0SIgor Mitsyanko if (!bus->bus_ops->stop) 11298f44cb0SIgor Mitsyanko return; 11398f44cb0SIgor Mitsyanko bus->bus_ops->stop(bus); 11498f44cb0SIgor Mitsyanko } 11598f44cb0SIgor Mitsyanko 116904628d3SIgor Mitsyanko static inline int qtnf_bus_data_tx(struct qtnf_bus *bus, struct sk_buff *skb, 117904628d3SIgor Mitsyanko unsigned int macid, unsigned int vifid) 11898f44cb0SIgor Mitsyanko { 119904628d3SIgor Mitsyanko return bus->bus_ops->data_tx(bus, skb, macid, vifid); 12098f44cb0SIgor Mitsyanko } 12198f44cb0SIgor Mitsyanko 12298f44cb0SIgor Mitsyanko static inline void 12398f44cb0SIgor Mitsyanko qtnf_bus_data_tx_timeout(struct qtnf_bus *bus, struct net_device *ndev) 12498f44cb0SIgor Mitsyanko { 12598f44cb0SIgor Mitsyanko return bus->bus_ops->data_tx_timeout(bus, ndev); 12698f44cb0SIgor Mitsyanko } 12798f44cb0SIgor Mitsyanko 12898f44cb0SIgor Mitsyanko static inline int qtnf_bus_control_tx(struct qtnf_bus *bus, struct sk_buff *skb) 12998f44cb0SIgor Mitsyanko { 13098f44cb0SIgor Mitsyanko return bus->bus_ops->control_tx(bus, skb); 13198f44cb0SIgor Mitsyanko } 13298f44cb0SIgor Mitsyanko 13398f44cb0SIgor Mitsyanko static inline void qtnf_bus_data_rx_start(struct qtnf_bus *bus) 13498f44cb0SIgor Mitsyanko { 13598f44cb0SIgor Mitsyanko return bus->bus_ops->data_rx_start(bus); 13698f44cb0SIgor Mitsyanko } 13798f44cb0SIgor Mitsyanko 13898f44cb0SIgor Mitsyanko static inline void qtnf_bus_data_rx_stop(struct qtnf_bus *bus) 13998f44cb0SIgor Mitsyanko { 14098f44cb0SIgor Mitsyanko return bus->bus_ops->data_rx_stop(bus); 14198f44cb0SIgor Mitsyanko } 14298f44cb0SIgor Mitsyanko 14398f44cb0SIgor Mitsyanko static __always_inline void qtnf_bus_lock(struct qtnf_bus *bus) 14498f44cb0SIgor Mitsyanko { 14598f44cb0SIgor Mitsyanko mutex_lock(&bus->bus_lock); 14698f44cb0SIgor Mitsyanko } 14798f44cb0SIgor Mitsyanko 14898f44cb0SIgor Mitsyanko static __always_inline void qtnf_bus_unlock(struct qtnf_bus *bus) 14998f44cb0SIgor Mitsyanko { 15098f44cb0SIgor Mitsyanko mutex_unlock(&bus->bus_lock); 15198f44cb0SIgor Mitsyanko } 15298f44cb0SIgor Mitsyanko 15398f44cb0SIgor Mitsyanko /* interface functions from common layer */ 15498f44cb0SIgor Mitsyanko 15598f44cb0SIgor Mitsyanko int qtnf_core_attach(struct qtnf_bus *bus); 15698f44cb0SIgor Mitsyanko void qtnf_core_detach(struct qtnf_bus *bus); 15798f44cb0SIgor Mitsyanko 15898f44cb0SIgor Mitsyanko #endif /* QTNFMAC_BUS_H */ 159