| /** |
| Copyright (c) 2008 - 2013 Quantenna Communications Inc |
| All Rights Reserved |
| |
| This program is free software; you can redistribute it and/or |
| modify it under the terms of the GNU General Public License |
| as published by the Free Software Foundation; either version 2 |
| of the License, or (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program; if not, write to the Free Software |
| Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
| |
| **/ |
| |
| #ifndef _QDRV_WLAN_H |
| #define _QDRV_WLAN_H |
| |
| #include <linux/version.h> |
| #include <linux/interrupt.h> |
| #include "../../../../net/bridge/br_public.h" |
| |
| /* Include the WLAN 802.11 layer here */ |
| #include <linux/skbuff.h> |
| #include <linux/netdevice.h> |
| #include <linux/i2c.h> |
| #include <linux/workqueue.h> |
| #include <net/ip.h> |
| #include <net80211/if_media.h> |
| #include <net80211/ieee80211_var.h> |
| #include "qdrv_comm.h" |
| #include "qdrv_debug.h" |
| #include "qtn/qtn_pcap.h" |
| #include "qdrv_bridge.h" |
| #include "qtn/muc_txrx_stats.h" |
| #include "qtn/muc_phy_stats.h" |
| #include "qtn/dsp_stats.h" |
| #include "qtn/auc_debug_stats.h" |
| #include "qtn/skb_recycle.h" |
| #include "qtn/qdrv_sch_data.h" |
| #include "qtn/iputil.h" |
| #ifdef CONFIG_QVSP |
| #include "qtn/qvsp.h" |
| #endif |
| #include "qtn/topaz_congest_queue.h" |
| #include <qtn/txbf_common.h> |
| #include <qtn/lhost_muc_comm.h> |
| |
| #define QNET_TXLIST_ENTRIES_DEFAULT 512 |
| #define QNET_TXLIST_ENTRIES_MAX 2048 |
| #define QNET_TXLIST_ENTRIES_MIN 1 |
| #define QNET_HLRING_ENTRIES 32 |
| #define QDRV_NUM_RF_STREAMS IEEE80211_QTN_NUM_RF_STREAMS |
| |
| #define RSSI_40M_TO_20M_DBM(x) (x - 3) |
| #define RSSI_20M_TO_40M_DBM(x) (x + 3) |
| #define RSSI_TOTAL_TO_PERCHAIN_DBM(x) (x - 6) |
| #define RSSI_PERCHAIN_TO_TOTAL_DBM(x) (x + 6) |
| #define LINK_MARGIN_INVALID (-127) |
| |
| enum qdrv_bld_type { |
| QDRV_BLD_TYPE_ENG = 1, |
| QDRV_BLD_TYPE_BENCH, |
| QDRV_BLD_TYPE_BUILDBOT, |
| QDRV_BLD_TYPE_REL, |
| QDRV_BLD_TYPE_SDK, |
| QDRV_BLD_TYPE_GPL |
| }; |
| |
| struct qdrv_vap; |
| |
| /* driver-specific node state */ |
| struct qdrv_node |
| { |
| struct ieee80211_node qn_node; /* Must be first for the 802.11 layer */ |
| struct kobject kobj; |
| TAILQ_ENTRY(qdrv_node) qn_next; |
| uint16_t qn_node_idx; /* a copy of ni_node_idx */ |
| }; |
| |
| #define MAX_MEMDEBUG_WATCHPTS 64 |
| struct qdrv_memdebug_watchpt { |
| uint32_t addr; |
| void *remap_addr; |
| size_t size; |
| }; |
| |
| #include "qdrv_slab_def.h" |
| |
| struct qdrv_meminfo { |
| struct kmem_cache *caches[QDRV_SLAB_IDX_MAX]; |
| }; |
| |
| struct qtn_auc_stat_field { |
| uintptr_t addr; |
| const char *name; |
| }; |
| |
| struct qdrv_auc_intr_stats { |
| uint32_t sleep; |
| uint32_t jiffies; |
| uint32_t aucirq[AUC_TID_NUM]; |
| }; |
| |
| struct qdrv_pktlogger_stats { |
| uint32_t pkt_queued; |
| uint32_t pkt_dropped; |
| uint32_t pkt_failed; |
| uint32_t pkt_requeued; |
| uint32_t queue_send; |
| }; |
| |
| struct qdrv_pktlogger { |
| struct qdrv_wlan *qw; |
| struct net_device *dev; |
| __be32 dst_ip; |
| __be32 src_ip; |
| __be16 dst_port; |
| __be16 src_port; |
| uint8_t dst_addr[IEEE80211_ADDR_LEN]; |
| uint8_t src_addr[IEEE80211_ADDR_LEN]; |
| uint8_t recv_addr[IEEE80211_ADDR_LEN]; |
| uint32_t maxfraglen; |
| uint32_t flag; |
| uint16_t ip_id; |
| |
| spinlock_t sendq_lock; |
| STAILQ_HEAD(,qdrv_pktlogger_data) sendq_head; |
| struct work_struct sendq_work; |
| int sendq_scheduled; |
| |
| struct sock *netlink_socket; |
| int netlink_ref; |
| |
| struct timer_list stats_timer; |
| struct timer_list mem_timer; |
| int mem_wp_index; |
| struct qdrv_memdebug_watchpt mem_wps[MAX_MEMDEBUG_WATCHPTS]; |
| |
| struct timer_list rate_timer; |
| struct timer_list sysmsg_timer; |
| struct timer_list flush_data; |
| |
| uint32_t *stats_uc_rx_ptr; |
| uint32_t *stats_uc_rx_rate_ptr; |
| uint32_t *stats_uc_rx_bf_ptr; |
| uint32_t *stats_uc_tx_ptr; |
| uint32_t *stats_uc_tx_rate_ptr; |
| uint32_t *stats_uc_su_rates_read_ptr; |
| uint32_t *stats_uc_mu_rates_read_ptr; |
| uint32_t *stats_uc_scs_cnt; |
| struct netdev_queue *netdev_q_ptr_w; |
| struct netdev_queue *netdev_q_ptr_e; |
| struct qdrv_meminfo qmeminfo; |
| uint32_t queue_len; |
| struct qdrv_pktlogger_stats stats; |
| |
| struct net_device *dev_emac0; |
| struct net_device *dev_emac1; |
| |
| uint32_t *stats_auc_sleep_p; |
| uint32_t *stats_auc_jiffies_p; |
| uint32_t *stats_auc_intr_p; |
| struct auc_dbg_counters *stats_auc_dbg_p; |
| |
| struct muc_rx_rates rx_rates[2]; |
| struct muc_rx_rates *rx_rate_pre; |
| struct muc_rx_rates *rx_rate_cur; |
| |
| struct muc_rx_rates rx_ratelog[2]; |
| struct muc_rx_rates *rx_ratelog_pre; |
| struct muc_rx_rates *rx_ratelog_cur; |
| struct timer_list phy_stats_timer; |
| struct timer_list dsp_stats_timer; |
| }; |
| |
| /**********/ |
| /** SCAN **/ |
| /**********/ |
| |
| struct host_scanif |
| { |
| struct workqueue_struct *workqueue; |
| u32 scan_sem_bit; |
| u32 tx_sem_bit; |
| volatile u32 *sc_res_mbox; |
| volatile u32 *sc_req_mbox; |
| }; |
| |
| /**********/ |
| /** RX **/ |
| /**********/ |
| |
| struct host_fifo_if |
| { |
| struct host_descfifo *fifo; |
| dma_addr_t fifo_dma; |
| struct host_rxdesc *pending; |
| struct host_rxdesc **descp; |
| int ring_size; |
| struct dma_pool *df_rxdesc_cache; |
| }; |
| |
| #define QNET_RXRING_ENTRIES 64 |
| #define QNET_MGMTRING_ENTRIES 4 |
| #define QNET_CTRLRING_ENTRIES 4 |
| #define QNET_ERRRING_ENTRIES 4 |
| |
| struct host_rxif |
| { |
| struct host_fifo_if rx; |
| u32 rx_sem_bit; |
| }; |
| |
| #define QNET_RXRING_SIZE (QNET_RXRING_ENTRIES*sizeof(struct host_rxdesc)) |
| #define QNET_RXBUF_SIZE (QNET_RXRING_ENTRIES*sizeof(struct host_buf)) |
| |
| /**********/ |
| /** TX **/ |
| /**********/ |
| |
| #define QDRV_TXDESC_DATA 0 |
| #define QDRV_TXDESC_MGMT 1 |
| #define QDRV_TXDESC_QUEUE_MAX 2 |
| |
| /* each node is always allowed this many descriptors */ |
| #define QDRV_TXDESC_THRESH_MAX_MIN 384 |
| /* re-enable a node queue when muc_queued is this much less than max per node */ |
| #define QDRV_TXDESC_THRESH_MIN_DIFF 32 |
| |
| struct host_txif |
| { |
| uint16_t txdesc_cnt[QDRV_TXDESC_QUEUE_MAX]; |
| uint16_t list_max_size; |
| uint16_t muc_thresh_high; |
| uint16_t muc_thresh_low; |
| struct tasklet_struct txdone_tasklet; |
| |
| struct host_ioctl *hl_ring; |
| struct host_ioctl *hl_first; |
| struct host_ioctl *hl_last; |
| dma_addr_t hl_ring_dma; |
| int hl_read; |
| int hl_write; |
| int hl_tosend; |
| u32 hl_count; |
| spinlock_t hl_flowlock; |
| |
| struct dma_pool *df_txdesc_cache; |
| |
| struct lhost_txdesc *df_txdesc_list_head; |
| struct lhost_txdesc *df_txdesc_list_tail; |
| |
| volatile u32 *tx_mbox; |
| }; |
| |
| #define QNET_HLRING_SIZE (QNET_HLRING_ENTRIES*sizeof(struct host_ioctl)) |
| |
| /**********/ |
| /** WLAN **/ |
| /**********/ |
| |
| #define HOST_TXD_VERSION 0x01 |
| #define CCA_TOKEN_INIT_VAL 0x50 |
| #define QTN_RATE_11N 0x80 /* Same bit setting as in MLME */ |
| |
| #define QTN_RATE_PHY_OFDM 0 |
| #define QTN_RATE_PHY_CCK 1 |
| #define QTN_RATE_PHY_HT 2 |
| |
| struct qtn_rateentry |
| { |
| u_int8_t re_ieeerate; /* IEEE rate:2*phyrate (for legacy MLME) |
| * or MCS index for 11n */ |
| u_int16_t re_rate; /* Rate in 100Kbps */ |
| u_int8_t re_ctrlrate; /* index in rate table of control |
| rate to use with this rate */ |
| u_int8_t re_shortpre:1; /* Must use short preamble */ |
| u_int8_t re_basicrate:1; /* Is this rate a basic rate */ |
| u_int8_t re_phytype:2; /* Phy type */ |
| } __packed; |
| |
| struct qtn_ratetable |
| { |
| u_int8_t rt_num; /* Number of entries (legacy + 11n) in the rate table */ |
| u_int8_t rt_legacy_num; /* Number of legacy entries in the rate table */ |
| struct qtn_rateentry *rt_entries; /* Array of entries */ |
| } __packed; |
| |
| struct qtn_channel |
| { |
| u_int16_t channel_number; /* IEEE channel number */ |
| u_int16_t channel_freq; /* Channel frequency */ |
| u_int32_t channel_flags; /* Channel flags */ |
| u_int16_t center_freq_40M; /* Channel Center Frequency for 40MHz */ |
| u_int16_t center_freq_80M; /* Channel Center Frequency for 80MHz */ |
| u_int16_t center_freq_160M; /* Channel Center Frequency for 160MHz */ |
| u_int32_t channel_ext_flags; /* Extra channel flags for 80MHZ mode */ |
| } __packed; |
| |
| #define QDRV_STAT(_qw, _is_tx, _member) do \ |
| { \ |
| if (_is_tx) { \ |
| _qw->tx_stats._member++; \ |
| } else { \ |
| _qw->rx_stats._member++; \ |
| } \ |
| } while (0) |
| |
| #define TXSTAT(qw, member) \ |
| (qw)->tx_stats.member += 1 |
| |
| #define TXSTAT_SET(qw, member, val) \ |
| (qw)->tx_stats.member = (val) |
| |
| #define RXSTAT(qw, member) \ |
| (qw)->rx_stats.member += 1 |
| |
| #define RXSTAT_SET(qw, member, val) \ |
| (qw)->rx_stats.member = (val) |
| |
| #define SMSTAT(qw, member) \ |
| (qw)->sm_stats.member += 1 |
| |
| /* #define QDRV_TX_DEBUG 1 */ |
| #ifdef QDRV_TX_DEBUG |
| |
| extern uint32_t qdrv_tx_ctr[]; |
| extern uint32_t qdrv_dbg_ctr[]; |
| #define QDRV_TX_CTR_INC(_x) qdrv_tx_ctr[_x]++; |
| |
| #define QDRV_TX_DBG(_i, _ni, _fmt, ...) do \ |
| { \ |
| struct ieee80211_node *__ni = _ni; \ |
| if (_i >= 0) { \ |
| if (qdrv_dbg_ctr[_i] == 0) { \ |
| break; \ |
| } \ |
| qdrv_dbg_ctr[_i]--; \ |
| } \ |
| if (__ni) { \ |
| printk("[%s]", ether_sprintf(__ni->ni_macaddr));\ |
| } \ |
| printk("%s " _fmt, \ |
| __func__, ##__VA_ARGS__); \ |
| } while (0) |
| |
| #else |
| |
| #define QDRV_TX_CTR_INC(_x) |
| #define QDRV_TX_DBG(_i, _ni, _fmt, ...) if (_ni) {} |
| |
| #endif /* QDRV_TX_DEBUG */ |
| |
| /** |
| * \defgroup LHOST_STATS Linux host generated stats |
| */ |
| /* @{ */ |
| |
| /** |
| * \brief 802.11 state machine statistics. |
| * |
| * These statistics are updated as 802.11 management packets are sent and received |
| * by both the AP and STA. |
| */ |
| struct qdrv_wlan_sm_stats { |
| /** |
| * The number of times that the state machine went from trying to authenticate |
| * directly back to scanning - i.e. the AUTH request timed out or was rejected. |
| */ |
| unsigned int sm_scan_auth_fail_scan_pend; |
| |
| /** |
| * The number of times that the state machine went from trying to associate |
| * directly back to scanning - i.e. the ASSOC request timed out or was rejected. |
| */ |
| unsigned int sm_scan_assoc_fail_scan_pend; |
| |
| /** |
| * The number of times that a scan has been triggered (excluding failure to connect). |
| */ |
| unsigned int sm_scan_pend; |
| |
| /** |
| * The number of times that an authentication request is sent, waiting on response. |
| */ |
| unsigned int sm_auth_pend; |
| |
| /** |
| * The number of times that a deauth sequence is sent (i.e. going from authenticated |
| * to disconnected state). |
| */ |
| unsigned int sm_run_deauth_auth_pend; |
| |
| /** |
| * The number of times that an association request is sent, waiting on response. |
| */ |
| unsigned int sm_assoc_pend; |
| |
| /** |
| * The number of times that a disassociate sequence is sent (i.e. going from |
| * associated to authenticated state). |
| */ |
| unsigned int sm_run_disassoc_assoc_pend; |
| |
| /** |
| * The number of times a node is authenticated - i.e. becomes ready to send data packets. |
| */ |
| unsigned int sm_nd_auth; |
| |
| /** |
| * The number of times a node is unauthenticated. |
| */ |
| unsigned int sm_nd_unauth; |
| |
| /** |
| * The total number of nodes that are currently authenticated. |
| */ |
| unsigned int sm_nd_auth_tot; |
| |
| /** |
| * The number of times a station goes into connected state - i.e. ready to send data |
| * packets. |
| */ |
| unsigned int sm_sta_associated; |
| |
| /** |
| * The state of the device - composite of flags indicating current operating mode and |
| * radar flags. |
| */ |
| unsigned int sm_state; |
| #define QDRV_WLAN_SM_STATE_AP 0x00000001 |
| #define QDRV_WLAN_SM_STATE_STA 0x00000002 |
| #define QDRV_WLAN_SM_STATE_RADAR_EN 0x00000004 |
| #define QDRV_WLAN_SM_STATE_RADAR_ACT 0x00000008 |
| #define QDRV_WLAN_SM_STATE_CAC_ACTIVE 0x00000010 |
| #define QDRV_SET_SM_FLAG(_stats, _flag) (_stats).sm_state |= (_flag) |
| #define QDRV_CLEAR_SM_FLAG(_stats, _flag) (_stats).sm_state &= ~(_flag) |
| }; |
| |
| /** |
| * \brief WLAN transmit statistics. |
| * |
| * These statistics are gathered within the WLAN driver on the LHost. |
| */ |
| struct qdrv_wlan_tx_stats { |
| /** |
| * The total number of management frames enqueued for transmission. |
| */ |
| unsigned int tx_enqueue_mgmt; |
| |
| /** |
| * The total number of driver-generated data frames enqueued for transmission. |
| */ |
| unsigned int tx_enqueue_80211_data; |
| |
| /** |
| * The total number of data packets enqueued for transmission. |
| */ |
| unsigned int tx_enqueue_data; |
| |
| /** |
| * The total number of packets enqueued to the MuC via the mailbox. |
| */ |
| unsigned int tx_muc_enqueue; |
| |
| /** |
| * The number of data packets enqueued to the MuC via the host mailbox (when no current |
| * packets are in the mailbox). |
| */ |
| unsigned int tx_muc_enqueue_mbox; |
| |
| /** |
| * The total number of keep-alive (NULL data) packets transmitted to clients |
| * associated to the AP. These packets are used to check the client is still |
| * connected and able to ACK the AP. |
| */ |
| unsigned int tx_null_data; |
| |
| /** |
| * The number of TX done interrupts received indicating the MuC is not ready. |
| * This figure should always read as zero. |
| */ |
| unsigned int tx_done_muc_ready_err; |
| |
| /** |
| * The number of packets successfully sent (all data, mgmt for all TIDs). |
| */ |
| unsigned int tx_done_success; |
| |
| /** |
| * The number of txdone interrupts received at the LHost. |
| */ |
| unsigned int tx_done_enable_queues; |
| |
| /** |
| * The number of times the transmit queue has stopped. |
| * Generally this is because the MuC backs up and causes backpressure to the |
| * LHost. |
| */ |
| unsigned int tx_queue_stop; |
| |
| /** |
| * The number of times a packet to the MuC was requeued. |
| */ |
| unsigned int tx_requeue; |
| |
| /** |
| * The number of times packet requeuing failed. |
| */ |
| unsigned int tx_requeue_err; |
| |
| /** |
| * The number of times the hardstart function is called. |
| */ |
| unsigned int tx_hardstart; |
| |
| /** |
| * The number of packets completed - marked as done by the MuC. |
| */ |
| unsigned int tx_complete; |
| |
| /** |
| * The size of the skb recycle list shared between the Ethernet and wireless drivers. |
| * |
| * This number will vary as traffic goes through the system. |
| */ |
| unsigned int tx_min_cl_cnt; |
| |
| /** |
| * The number of packets dropped in the driver during a configuration change. |
| */ |
| unsigned int tx_dropped_config; |
| |
| /** |
| * The number of packets dropped in the driver due to the MAC not being enabled. |
| */ |
| unsigned int tx_dropped_mac_dead; |
| |
| /** |
| * The current transmit channel. |
| */ |
| unsigned int tx_channel; |
| |
| /** |
| * The total number of IGMP packets for transmission. |
| */ |
| unsigned int tx_igmp; |
| |
| /** |
| * The number of packets for transmission to unknown destination MAC addresses. |
| */ |
| unsigned int tx_unknown; |
| |
| /** |
| * The number of ARP request packets sent in attempts to discover the location of |
| * unknown destinations. |
| */ |
| unsigned int tx_arp_req; |
| |
| /** |
| * The number of packets transmitted that lie inside the Local Network Control Block |
| * (LNCB), the range 224.0.0.0/24, sent as four address (reliable) multicast |
| * packets to Quantenna bridge stations. |
| */ |
| unsigned int tx_copy4_mc; |
| |
| /** |
| * The number of IGMP packets transmitted as 4 address reliable multicast packets |
| * to Quantenna bridge stations. |
| */ |
| unsigned int tx_copy4_igmp; |
| |
| /** |
| * The number of packets for unknown destination MAC addresses sent as 4 address |
| * reliable multicast packets to bridge stations. |
| */ |
| unsigned int tx_copy4_unknown; |
| |
| /** |
| * The total count of packet retransmissions as reliable, 4 address multicast frames. |
| */ |
| unsigned int tx_copy4; |
| |
| /** |
| * The number of times transmission of a copied packet failed due to lack of |
| * resources. |
| */ |
| unsigned int tx_copy_fail; |
| |
| /** |
| * The number of times transmission of a 4 address packet failed due to the tx |
| * queue being full. |
| */ |
| unsigned int tx_copy4_busy; |
| |
| /** |
| * The number of packets transmitted that lie inside the Local Network Control Block |
| * (LNCB), the range 224.0.0.0/24, sent as three address (unreliable) multicast |
| * packets (to third party clients). |
| */ |
| unsigned int tx_copy3_mc; |
| |
| /** |
| * The number of IGMP packets transmitted as 3 address unreliable multicast |
| * packets (to third party clients). |
| */ |
| unsigned int tx_copy3_igmp; |
| |
| /** |
| * The number of broadcast or multicast packets transmitted as unicast frames. |
| */ |
| unsigned int tx_copy_uc; |
| |
| /** |
| * The number of 3 address broadcast/multicast packets sent to third party STAs. |
| */ |
| unsigned int tx_copy3; |
| |
| /** |
| * The number of broadcast/multicast packets transmitted as group-addressed frames. |
| */ |
| unsigned int tx_copy_mc; |
| |
| /** |
| * The number of broadcast/multicast packets transmitted as group-addressed frames. |
| */ |
| unsigned int tx_copy_mc_enc; |
| |
| /** |
| * The number of broadcast/multicast packets transmitted as directed frames |
| */ |
| unsigned int tx_copy_mc_to_uc; |
| |
| /** |
| * The number of SSDP packets transmitted as directed frames |
| */ |
| unsigned int tx_copy_ssdp; |
| |
| /** |
| * The number of packets that were dropped because the destination station was not |
| * authorised. |
| */ |
| unsigned int tx_drop_auth; |
| |
| /** |
| * The number of packets that were dropped because the destination station had |
| * disassociated. |
| */ |
| unsigned int tx_drop_aid; |
| |
| /** |
| * The number of packets that were dropped because of buffer exhaustion. |
| */ |
| unsigned int tx_drop_nodesc; |
| |
| /** |
| * The number of packets that were dropped because the WDS peer was not |
| * associated. |
| */ |
| unsigned int tx_drop_wds; |
| |
| /** |
| * The number of packets that were dropped because of 3 address mode bridging |
| * rules. |
| */ |
| unsigned int tx_drop_3addr; |
| |
| /** |
| * The number of packets that were dropped because of Video Stream Protection. |
| */ |
| unsigned int tx_drop_vsp; |
| |
| /** |
| * The total count of packets dropped at the wireless interface. |
| */ |
| unsigned int tx_drop_total; |
| |
| /** |
| * The number of data frames forworded to L2 external filter |
| */ |
| unsigned int tx_l2_ext_filter; |
| |
| /** |
| * The number of data frames droped without forwording to L2 external filter |
| */ |
| unsigned int tx_drop_l2_ext_filter; |
| |
| /** |
| * Field for QCAT. |
| */ |
| unsigned int qcat_state; |
| |
| /** |
| * Ticks that DSP waits until wmac is ready before installing the qmatrix. |
| */ |
| unsigned int txbf_qmat_wait; |
| |
| /** |
| * Protocol counts |
| */ |
| unsigned int prot_ip_udp; |
| unsigned int prot_ip_tcp; |
| unsigned int prot_ip_icmp; |
| unsigned int prot_ip_igmp; |
| unsigned int prot_ip_other; |
| unsigned int prot_ipv6; |
| unsigned int prot_arp; |
| unsigned int prot_pae; |
| unsigned int prot_other; |
| }; |
| |
| /** |
| * \brief WLAN receive statistics. |
| * |
| * These statistics are gathered within the WLAN driver on the LHost. |
| */ |
| struct qdrv_wlan_rx_stats { |
| |
| /** |
| * The number of receive IRQs |
| */ |
| unsigned int rx_irq; |
| |
| /** |
| * The number of times the receive tasklet is scheduled based on the IRQ. |
| */ |
| unsigned int rx_irq_schedule; |
| |
| /** |
| * The number of beacons received. |
| */ |
| unsigned int rx_beacon; |
| |
| /** |
| * The number of non-beacon packets received (eg, other management, control |
| * and data packets combined). |
| */ |
| unsigned int rx_non_beacon; |
| |
| /** |
| * The number of packets received that were sent via the slow WLAN driver path, |
| * which have no node structure associated with them. |
| */ |
| unsigned int rx_input_all; |
| |
| /** |
| * The number of packets received for a specific node (slow WLAN driver path). |
| * The slow path is for management, control or fragmented data packets. |
| */ |
| unsigned int rx_input_node; |
| |
| /** |
| * The number of data packets received which are SNAP encapsulated. |
| */ |
| unsigned int rx_data_snap; |
| |
| /** |
| * The number of packets received with only the to DS bit set. |
| */ |
| unsigned int rx_data_tods; |
| |
| /** |
| * The number of packets received with none of the to/from DS bits set. |
| */ |
| unsigned int rx_data_nods; |
| |
| /** |
| * The number of packets received with only the from DS bit set. |
| */ |
| unsigned int rx_data_fromds; |
| |
| /** |
| * The number of packets received with both the to and from DS bits set. |
| * These are 4 address (bridged) packets. |
| */ |
| unsigned int rx_data_dstods; |
| |
| /** |
| * The number of packets received from unknown STAs - that is, the AP doesn't |
| * have an association with the STA. |
| */ |
| unsigned int rx_data_no_node; |
| |
| /** |
| * The number of packets received which have too short a length. These packets |
| * are dropped. |
| */ |
| unsigned int rx_data_too_short; |
| |
| /** |
| * The number of times the rx poll function is called. |
| */ |
| unsigned int rx_poll; |
| |
| /** |
| * The number of times that a poll is carried on from a previous poll - that is, |
| * the previous poll terminated early due to heavy RX load. |
| */ |
| unsigned int rx_poll_pending; |
| |
| /** |
| * The number of times rx poll terminated due to reaching the end of the received |
| * data chain. |
| */ |
| unsigned int rx_poll_empty; |
| |
| /** |
| * The number of times a poll to the receive mailbox has data available. |
| */ |
| unsigned int rx_poll_retrieving; |
| |
| /** |
| * The number of times that an AMSDU being decapsulated fails due to not having enough headroom |
| * in the packet. Eg, badly formatted AMSDU. |
| */ |
| unsigned int rx_poll_buffer_err; |
| |
| /** |
| * The number of times a receive descriptor allocate for an skb (when used for requeueing the RX descriptor |
| * for the next packet) fails. |
| */ |
| unsigned int rx_poll_skballoc_err; |
| |
| /** |
| * Whether the poll function for receive is currently running (1) or not (0). |
| */ |
| unsigned int rx_poll_stopped; |
| |
| /** |
| * The number of elements on the receive FIFO between the MuC and LHost. |
| */ |
| unsigned int rx_df_numelems; |
| |
| /** |
| * The number of Aggregate MSDUs received. |
| * |
| * This counter is incremented once per AMSDU, NOT once per subframe within |
| * the AMSDU. |
| */ |
| unsigned int rx_amsdu; |
| |
| /** |
| * The number of received packets (singletons, MPDUs or AMSDUs) in the LHost driver. |
| */ |
| unsigned int rx_packets; |
| |
| /** |
| * The number of received bytes (based on received packets counter above), including 802.2, 802.11 headers. |
| */ |
| unsigned int rx_bytes; |
| |
| /** |
| * The number of times chained receive descriptors are read in. |
| */ |
| unsigned int rx_poll_next; |
| |
| /** |
| * The number of times that the poll function completed processing all received packets before using |
| * it's entire budget. |
| */ |
| unsigned int rx_poll_complete; |
| |
| /** |
| * The number of times the receive poll function completes. |
| */ |
| unsigned int rx_poll_continue; |
| |
| /** |
| * The number of times packets received are from unauthenticated STAs. |
| */ |
| unsigned int rx_poll_vap_err; |
| |
| /** |
| * The number of received 802.11 fragmented packets. |
| * Fragmented packets are processed via the slow data path. |
| */ |
| unsigned int rx_frag; |
| |
| /** |
| * The number of packets received for STAs that are currently blacklisted (due to MAC address filtering). |
| */ |
| unsigned int rx_blacklist; |
| |
| /** |
| * The number of received LNCB packets in 4 address mode. |
| */ |
| unsigned int rx_lncb_4; |
| |
| /** |
| * The number of received IGMP packets. |
| */ |
| unsigned int rx_igmp; |
| |
| /** |
| * The number of received IGMP packets in 4 address mode. |
| */ |
| unsigned int rx_igmp_4; |
| |
| /** |
| * The number of IGMP packets dropped due to already receiving the IGMP packet |
| * as a reliable 4 address packet. |
| */ |
| unsigned int rx_igmp_3_drop; |
| |
| /** |
| * The number of received 3 address multicast packets dropped due to already |
| * receiving the same packet as a reliable 4 address packet. |
| */ |
| unsigned int rx_mc_3_drop; |
| |
| /** |
| * Protocol counts |
| */ |
| unsigned int prot_ip_udp; |
| unsigned int prot_ip_tcp; |
| unsigned int prot_ip_icmp; |
| unsigned int prot_ip_igmp; |
| unsigned int prot_ip_other; |
| unsigned int prot_ipv6; |
| unsigned int prot_arp; |
| unsigned int prot_pae; |
| unsigned int prot_other; |
| |
| /** |
| * Beamforming Statistics |
| */ |
| unsigned int rx_bf_success[QTN_STATS_NUM_BF_SLOTS]; |
| unsigned int rx_bf_rejected[QTN_STATS_NUM_BF_SLOTS]; |
| |
| unsigned int rx_rate_train_invalid; |
| unsigned int rx_mac_reserved; |
| unsigned int rx_coex_bw_action; |
| unsigned int rx_coex_bw_assoc; |
| unsigned int rx_coex_bw_scan; |
| }; |
| |
| struct qdrv_tqe_cgq_stats { |
| uint32_t congest_qlen[TOPAZ_CONGEST_QUEUE_NUM]; |
| uint32_t congest_enq_fail[TOPAZ_CONGEST_QUEUE_NUM]; |
| }; |
| /* @} */ |
| |
| /* |
| * This can be changed to an array if the stat_parser is enhanced to parse array syntax. |
| */ |
| struct qdrv_rx_evm_array { |
| unsigned int rx_evm_val[NUM_ANT]; |
| }; |
| |
| /** |
| * \brief Transmit power |
| * |
| * Each member of the array records transmit power of one Tx chain. |
| */ |
| struct qdrv_tx_pd_array { |
| /** |
| * Transmit power of chain 0-3. |
| */ |
| uint16_t tx_pd_vol[NUM_ANT]; |
| }; |
| |
| /** |
| * \brief Qdisc stats |
| * |
| * Queue statistics per-node |
| */ |
| struct qdrv_netdebug_nd_stats { |
| uint32_t sch_aid; |
| uint32_t sch_mac1; |
| uint32_t sch_mac2; |
| uint32_t sch_ref; |
| uint32_t sch_muc_queued; |
| uint32_t sch_tokens; |
| uint32_t sch_qlen; |
| uint32_t sch_low_rate; |
| uint32_t sch_depth[QDRV_SCH_BANDS]; |
| uint32_t sch_sent[QDRV_SCH_BANDS]; |
| uint32_t sch_dropped[QDRV_SCH_BANDS]; |
| uint32_t sch_victim[QDRV_SCH_BANDS]; |
| }; |
| |
| struct qdrv_sch_stats { |
| uint32_t sch_users; |
| uint32_t sch_tokens; |
| uint32_t sch_cnt; |
| }; |
| |
| /** |
| * \brief Linux memory statistics. |
| * |
| * This structure contains a sample of different statistics related to the Linux memory |
| * management subsystem. |
| */ |
| struct qdrv_mem_stats { |
| /** |
| * The number of free pages in the system. |
| */ |
| unsigned long mem_free; |
| /** |
| * The number of SLAB pages that can be freed up. |
| */ |
| unsigned long mem_slab_reclaimable; |
| /** |
| * The number of SLAB pages that can't be freed up. |
| */ |
| unsigned long mem_slab_unreclaimable; |
| /** |
| * |
| */ |
| unsigned long mem_anon; |
| unsigned long mem_mapped; |
| unsigned long mem_cached; |
| }; |
| |
| /** |
| * \brief Linux misc statistics |
| */ |
| struct qdrv_misc_stats { |
| /** |
| * CPU awake cycles. When CPU is at full load, this will be at |
| * CPU clock speed (Hz) / stats interval (s) |
| */ |
| unsigned long cpuawake; |
| }; |
| |
| /** |
| * \brief Statistics indicates the reason for a channel change |
| * |
| * Each member of this structure records times channel change caused by different reason. |
| */ |
| struct qdrv_csw_count_stats { |
| /** |
| * Channel change caused by SCS. |
| */ |
| uint16_t csw_by_scs; |
| /** |
| * Channel change caused by DFS. |
| */ |
| uint16_t csw_by_dfs; |
| /** |
| * Channel change caused by User configuration |
| */ |
| uint16_t csw_by_user; |
| /** |
| * Channel change when device does off-channel sampling. |
| */ |
| uint16_t csw_by_sampling; |
| /** |
| * Channel change when device does scan and sample. |
| */ |
| uint16_t csw_by_tdls; |
| /** |
| * Channel change when device does background scanning. |
| */ |
| uint16_t csw_by_bgscan; |
| /** |
| * Channel change after off-channel CAC is completed. |
| */ |
| uint16_t csw_by_ocac; |
| /** |
| * Channel change when off-channel CAC is running. |
| */ |
| uint16_t csw_by_ocac_run; |
| /** |
| * Channel change when received CSAIE from action frame or beacon |
| */ |
| uint16_t csw_by_csa; |
| /** |
| * Channel change when device does regular scanning. |
| */ |
| uint16_t csw_by_scan; |
| /** |
| * Channel change triggered due to pm level changes |
| */ |
| uint16_t csw_by_coc; |
| }; |
| |
| struct tx_power_cal |
| { |
| struct _temp_info { |
| int temp_index; |
| int real_temp; |
| u_int8_t num_zone; |
| } temp_info; |
| struct delayed_work bbrf_cal_work; |
| }; |
| |
| #define MAX_UNKNOWN_DP_PER_SECOND 5 /* Rate limit per sec for unknown data pkts */ |
| |
| /* Ext Flags in qdrv_wlan */ |
| #define QDRV_WLAN_MUC_KILLED 0x00000001 |
| #define QDRV_FLAG_3ADDR_BRIDGE_DISABLE 0x00000002 |
| #define QDRV_WLAN_DEBUG_TEST_LNCB 0x00000004 |
| #define QDRV_WLAN_FLAG_UNKNOWN_ARP 0x00000008 /* send ARP requests for unknown destinations */ |
| #define QDRV_WLAN_FLAG_UNKNOWN_FWD 0x00000010 /* send unknown dest pkt to all bridge STAs */ |
| #define QDRV_WLAN_FLAG_AUC_TX 0x00000020 /* enqueue tx packets to AuC, not MuC */ |
| |
| #define QDRV_WLAN_TX_USE_AUC(qw) ( qw->flags_ext & QDRV_WLAN_FLAG_AUC_TX ) |
| |
| #define QDRV_FLAG_3ADDR_BRIDGE_ENABLED() ((qw->flags_ext & QDRV_FLAG_3ADDR_BRIDGE_DISABLE) == 0) |
| |
| struct qtn_node_shared_stats_list { |
| /* Note: shared_pernode_stats should be the 1st field in the structure */ |
| struct qtn_node_shared_stats shared_pernode_stats; |
| TAILQ_ENTRY(qtn_node_shared_stats_list) next; |
| }; |
| |
| struct qdrv_wlan { |
| /* The 802.11 networking structure */ |
| struct ieee80211com ic; |
| int unit; |
| |
| struct work_struct scan_task; |
| |
| u32 flags_ext; |
| u16 flags; |
| u8 rf_chipid; |
| u8 rf_chip_verid; |
| struct qdrv_mac *mac;/* Interrupts per MAC so we need a back pointer */ |
| |
| /* Synchronization */ |
| spinlock_t lock; |
| |
| char semmap[HOST_NUM_HOSTIFQ]; |
| char txdoneirq; |
| int rxirq; |
| int scanirq; |
| |
| struct host_scanif scan_if; |
| |
| struct host_scanfifo *scan_fifo; /* For iounmap */ |
| |
| /* Tx to MuC */ |
| struct host_txif tx_if; |
| /* Rx from MuC */ |
| struct host_rxif rx_if; |
| |
| /* Registers */ |
| u32 host_sem; |
| struct qtn_ratetable qw_rates[IEEE80211_MODE_MAX];/* rate tables */ |
| struct qtn_ratetable *qw_currt; /* current rate table */ |
| enum ieee80211_phymode qw_curmode; |
| struct qdrv_wlan_tx_stats tx_stats; |
| struct qdrv_wlan_rx_stats rx_stats; |
| struct qdrv_csw_count_stats csw_stats; |
| struct qdrv_pktlogger pktlogger; |
| struct qdrv_wlan_sm_stats sm_stats; |
| |
| /*congest queue stats*/ |
| struct qdrv_tqe_cgq_stats cgq_stats; |
| |
| /* TX Beamforming support */ |
| void *txbf_state; |
| |
| /* Flow control */ |
| spinlock_t flowlock; |
| |
| struct net_device *br_dev; |
| |
| int unknown_dp_count; |
| unsigned long unknown_dp_jiffies; |
| |
| #ifdef CONFIG_QVSP |
| struct qvsp_s *qvsp; |
| struct qtn_vsp_stats *vsp_stats; |
| struct tasklet_struct vsp_tasklet; |
| struct timer_list vsp_ba_throt; |
| #if TOPAZ_QTM |
| uint32_t vsp_enabling; /* VSP is just enabled, need warm up for traffic stats */ |
| uint32_t vsp_check_intvl; /* in seconds */ |
| uint32_t vsp_sync_sched_remain; /* sched sync task before next vsp interrupt from MuC */ |
| /* |
| * Used to sync stream stats every second. Since VSP check interval is bigger than 1 second, |
| * we need to sched the sync work one less than the interval. And vsp tasklet will do 1 time. |
| */ |
| struct delayed_work vsp_sync_work; |
| #endif |
| #endif |
| |
| /* 3-address mode bridging */ |
| struct qdrv_br bridge_table; |
| int mcs_cap; |
| int mcs_odd_even; |
| int tx_restrict; |
| int tx_restrict_rts; |
| int tx_restrict_limit; |
| int tx_restrict_rate; |
| uint8_t tx_swretry_agg_max; |
| uint8_t tx_swretry_noagg_max; |
| uint8_t tx_swretry_suspend_xmit; |
| struct timer_list hr_timer; |
| struct timer_list cca_timer; |
| struct timer_list igmp_query_timer; |
| struct work_struct cca_wq; |
| struct work_struct meas_wq; |
| spinlock_t cca_lock; |
| struct work_struct scan_wq; |
| spinlock_t scan_lock; |
| void (*csa_callback)(const struct ieee80211_channel *, u_int64_t); |
| struct work_struct csa_wq; |
| spinlock_t csa_lock; |
| struct work_struct channel_work_wq; |
| int (*radar_detect_callback)(const struct ieee80211_channel *); |
| unsigned long arp_last_sent; |
| |
| struct work_struct remain_chan_wq; |
| |
| /* MuC per node stats pool */ |
| struct qtn_node_shared_stats_list *shared_pernode_stats_pool; |
| dma_addr_t shared_pernode_stats_phys; |
| TAILQ_HEAD(, qtn_node_shared_stats_list) shared_pernode_stats_head; |
| |
| struct notifier_block pm_notifier; |
| |
| #if QTN_GENPCAP |
| struct qtn_genpcap_args genpcap_args; |
| #endif |
| |
| struct qdrv_sch_shared_data *tx_sch_shared_data; |
| bool queue_enabled; |
| #define QDRV_BR_ISOLATE_NORMAL BIT(0) |
| #define QDRV_BR_ISOLATE_VLAN BIT(1) |
| uint16_t br_isolate; |
| uint16_t br_isolate_vid; |
| uint8_t restrict_wlan_ip; |
| struct i2c_client *se95_temp_sensor; |
| struct tx_power_cal tx_power_cal_data; |
| struct shared_params *sp; |
| uint32_t tx_mimomode; |
| }; |
| |
| /**************/ |
| /** Netdebug **/ |
| /**************/ |
| #define QDRV_NETDEBUG_NETPOLL_NAME "qdrv_netpoll" |
| #define QDRV_NETDEBUG_NETPOLL_DEV "eth1_0" |
| |
| #define QDRV_NETDEBUG_FLAGS_NO_STATS 0x1 |
| #define QDRV_NETDEBUG_FLAGS_TRUNCATED 0x2 |
| |
| #define QDRV_NETDEBUG_RADAR_MAXPULSE (175) |
| #define QDRV_NETDEBUG_RADAR_PULSESIZE (8) |
| |
| #define QDRV_NETDEBUG_TXBF_DATALEN 1024 |
| #define QDRV_NETDEBUG_IWEVENT_LENGTH 128 |
| #define QDRV_NETDEBUG_MEM_DATALEN 1024 |
| #define QDRV_NETDEBUG_SYSMSG_LENGTH 4096 |
| #define QDRV_NETDEBUG_BUILDSTRING_SIZE 32 |
| |
| /** |
| * \brief The common header for netdebug (packetlogger) packets. |
| */ |
| struct qdrv_pktlogger_hdr { |
| struct udphdr udpheader; |
| u_int8_t type; |
| u_int8_t opmode; |
| /** |
| * The source address (the bridge MAC address). |
| */ |
| unsigned char src[IEEE80211_ADDR_LEN]; |
| u_int32_t version; |
| u_int32_t builddate; |
| /** |
| * Identifying string to easily see in packet dumps that this is a packetlogger packet. |
| */ |
| char buildstring[QDRV_NETDEBUG_BUILDSTRING_SIZE]; |
| u_int8_t flags; |
| |
| /** |
| * Epoch timestamp. |
| */ |
| u_int32_t timestamp; |
| /** |
| * TSF timestamp low bytes. |
| */ |
| u_int32_t tsf_lo; |
| /** |
| * TSF timestamp high bytes. |
| */ |
| u_int32_t tsf_hi; |
| |
| u_int32_t platform; |
| u_int32_t stats_len; |
| char padding[3]; /* Word align data start */ |
| } __packed; |
| |
| /* Note: NDB tags are added to pktlogger structures. Do not remove these tags. */ |
| /* @NDB@: type=4 */ |
| struct qdrv_netdebug_txbf { |
| struct qdrv_pktlogger_hdr ndb_hdr; |
| u_int8_t stvec_data[QDRV_NETDEBUG_TXBF_DATALEN]; |
| } __packed; |
| |
| /* @NDB@: type=5,payload=iwevent_data,payloadtype=varstring */ |
| struct qdrv_netdebug_iwevent { |
| struct qdrv_pktlogger_hdr ndb_hdr; |
| char iwevent_data[QDRV_NETDEBUG_IWEVENT_LENGTH]; |
| } __packed; |
| |
| /* @NDB@: type=7 */ |
| struct qdrv_netdebug_mem { |
| struct qdrv_pktlogger_hdr ndb_hdr; |
| u_int8_t stvec_data[QDRV_NETDEBUG_MEM_DATALEN]; |
| } __packed; |
| |
| /* @NDB@: type=8 */ |
| struct qdrv_netdebug_rate { |
| struct qdrv_pktlogger_hdr ndb_hdr; |
| struct qtn_rate_su_tx_stats rate_su_tx_stats[RATES_STATS_NUM_ADAPTATIONS]; |
| struct qtn_rate_mu_tx_stats rate_mu_tx_stats[RATES_STATS_NUM_ADAPTATIONS]; |
| struct qtn_rate_gen_stats rate_gen_stats; |
| } __packed; |
| |
| /* @NDB@: type=3 */ |
| struct qdrv_radar_stats { |
| struct qdrv_pktlogger_hdr ndb_hdr; |
| u_int32_t numpulses; |
| u_int8_t pulseinfo[QDRV_NETDEBUG_RADAR_PULSESIZE * |
| QDRV_NETDEBUG_RADAR_MAXPULSE]; |
| } __packed; |
| |
| struct qdrv_muc_rx_rates { |
| u_int16_t rx_mcs[IEEE80211_HT_RATE_MAXSIZE]; |
| u_int16_t rx_mcs_pad; /* unique name for packet logger */ |
| } __packed; |
| |
| struct qdrv_muc_rx_11acrates { |
| u_int16_t rx_11ac_mcs[MUC_VHT_NUM_RATES]; |
| } __packed; |
| |
| /* @NDB@: type=6,payload=msg,payloadtype=varstring */ |
| struct qdrv_netdebug_sysmsg { |
| struct qdrv_pktlogger_hdr ndb_hdr; |
| char msg[QDRV_NETDEBUG_SYSMSG_LENGTH]; |
| } __packed; |
| |
| /** |
| * \brief Statistics on the traffic queueing discipline (qdisc). |
| * |
| * These statistics are used to track packets that are sent/dropped by the traffic |
| * policer on the Ethernet and wireless interfaces. |
| * |
| * The '_dropped' counters represent true packet loss, due to backpressure from lower |
| * parts of the system. |
| */ |
| struct qdrv_qdisc_stats { |
| /** |
| * The number of packets queued via the qdisc for the wireless interface. |
| */ |
| u_int32_t wifi_sent; |
| /** |
| * The number of packets dropped by the qdisc on the wireless interface. |
| */ |
| u_int32_t wifi_dropped; |
| /** |
| * The number of packets queued via the qdisc for the Ethernet interface. |
| */ |
| u_int32_t eth_sent; |
| /** |
| * The number of packets dropped by the qdisc on the Ethernet interface. |
| */ |
| u_int32_t eth_dropped; |
| }; |
| |
| /** |
| * \brief Statistics related to the EMAC. |
| * |
| * This structure contains statistic related to the EMAC block of the system. |
| */ |
| struct qdrv_emac_stats { |
| /** |
| * The number of packets lost due to no DMA buffers being available on |
| * receive. Each of these represents a genuine single packet loss on |
| * Ethernet receive. |
| */ |
| u_int32_t rx_emac0_dma_missed; |
| u_int32_t rx_emac1_dma_missed; |
| }; |
| |
| /* This struct must be kept in sync with qtn_scs_cnt*/ |
| struct qdrv_scs_cnt { |
| uint32_t scs_iotcl; |
| uint32_t scs_noqosnull; |
| uint32_t scs_1stcnflct; |
| uint32_t scs_qosnul_sntfail; |
| uint32_t scs_2ndcnflct; |
| uint32_t scs_low_dwell; |
| uint32_t scs_offch_scan; |
| uint32_t scs_sample_start; |
| uint32_t scs_sample_stop; |
| }; |
| |
| struct qdrv_tqe_stats { |
| uint32_t emac0_outc; |
| uint32_t emac1_outc; |
| uint32_t wmac_outc; |
| uint32_t lhost_outc; |
| uint32_t muc_outc; |
| uint32_t dsp_outc; |
| uint32_t auc_outc; |
| uint32_t pcie_outc; |
| uint32_t drop; |
| uint32_t emac0_drop; |
| uint32_t emac1_drop; |
| uint32_t wmac_drop; |
| uint32_t lhost_drop; |
| uint32_t muc_drop; |
| uint32_t dsp_drop; |
| uint32_t auc_drop; |
| uint32_t pcie_drop; |
| }; |
| |
| struct qdrv_hbm_stats { |
| uint32_t req_lhost[TOPAZ_HBM_POOL_COUNT]; |
| uint32_t req_muc[TOPAZ_HBM_POOL_COUNT]; |
| uint32_t req_emac0[TOPAZ_HBM_POOL_COUNT]; |
| uint32_t req_emac1[TOPAZ_HBM_POOL_COUNT]; |
| uint32_t req_wmac[TOPAZ_HBM_POOL_COUNT]; |
| uint32_t req_tqe[TOPAZ_HBM_POOL_COUNT]; |
| uint32_t req_auc[TOPAZ_HBM_POOL_COUNT]; |
| uint32_t req_dsp[TOPAZ_HBM_POOL_COUNT]; |
| uint32_t req_pcie[TOPAZ_HBM_POOL_COUNT]; |
| uint32_t rel_lhost[TOPAZ_HBM_POOL_COUNT]; |
| uint32_t rel_muc[TOPAZ_HBM_POOL_COUNT]; |
| uint32_t rel_emac0[TOPAZ_HBM_POOL_COUNT]; |
| uint32_t rel_emac1[TOPAZ_HBM_POOL_COUNT]; |
| uint32_t rel_wmac[TOPAZ_HBM_POOL_COUNT]; |
| uint32_t rel_tqe[TOPAZ_HBM_POOL_COUNT]; |
| uint32_t rel_auc[TOPAZ_HBM_POOL_COUNT]; |
| uint32_t rel_dsp[TOPAZ_HBM_POOL_COUNT]; |
| uint32_t rel_pcie[TOPAZ_HBM_POOL_COUNT]; |
| }; |
| |
| struct qdrv_hbm_stats_oth { |
| uint32_t hbm_req; |
| uint32_t hbm_rel; |
| uint32_t hbm_diff; |
| uint32_t hbm_overflow; |
| uint32_t hbm_underflow; |
| }; |
| |
| struct dsp_mu_stats { |
| uint32_t mu_u0_aid[QTN_MU_QMAT_MAX_SLOTS]; |
| uint32_t mu_u1_aid[QTN_MU_QMAT_MAX_SLOTS]; |
| int32_t mu_rank[QTN_MU_QMAT_MAX_SLOTS]; |
| }; |
| |
| /* @NDB@: type=1 */ |
| struct qdrv_netdebug_stats { |
| struct qdrv_pktlogger_hdr ndb_hdr; |
| struct muc_rx_stats stats_muc_rx; |
| struct qdrv_muc_rx_rates rates_muc_rx; |
| struct qdrv_muc_rx_11acrates rates_muc_rx_11ac; |
| struct muc_rx_bf_stats stats_muc_rx_bf; |
| struct muc_tx_stats stats_muc_tx; |
| struct qdrv_emac_stats stats_emac; |
| struct qdrv_qdisc_stats stats_qdisc; |
| |
| struct qdrv_wlan_rx_stats stats_wlan_rx; |
| struct qdrv_wlan_tx_stats stats_wlan_tx; |
| struct qdrv_wlan_sm_stats stats_wlan_sm; |
| |
| struct qtn_rx_stats stats_phy_rx; |
| struct qtn_tx_stats stats_phy_tx; |
| struct qdrv_mem_stats stats_mem; |
| struct qdrv_misc_stats stats_misc; |
| struct qdrv_rx_evm_array stats_evm; |
| struct qdrv_csw_count_stats stats_csw; |
| struct qdrv_tx_pd_array stats_pd_vol; |
| struct qdrv_slab_watch stats_slab; |
| struct qdrv_scs_cnt stats_scs_cnt; |
| struct qdrv_auc_intr_stats stats_auc_intr_count; |
| struct auc_dbg_counters stats_auc_debug_counts; |
| struct qdrv_tqe_stats stats_tqe; |
| struct qdrv_tqe_cgq_stats stats_cgq; |
| struct qdrv_hbm_stats stats_hbm; |
| struct qdrv_hbm_stats_oth stats_hbm_oth; |
| struct dsp_mu_stats stats_dsp_mu; |
| } __packed; |
| |
| /* TBD */ |
| #define QDRV_NETDEBUG_EVENT_STR_MAX 127 |
| struct qdrv_netdebug_event { |
| u_int8_t version; |
| u_int8_t type; |
| u_int8_t reserved[2]; /* Reserved for alignment */ |
| u_int32_t tstamp; |
| u_int8_t event_msg[QDRV_NETDEBUG_EVENT_STR_MAX + 1]; |
| }; |
| |
| struct qdrv_netdebug_per_node_phystats { |
| uint8_t node_macaddr[IEEE80211_ADDR_LEN]; |
| struct qtn_node_shared_stats per_node_phystats; |
| } __packed; |
| |
| /* |
| * We always have at least one per-node statistic (the board itself) |
| * For APs we can have more than one, so added variable length array at the end of structure |
| */ |
| /* @NDB@: type=10,payload=per_node_stats,payloadtype=vararray(per_node_stats_count) */ |
| struct qdrv_netdebug_phystats { |
| struct qdrv_pktlogger_hdr ndb_hdr; |
| struct qtn_stats stats; |
| u_int32_t per_node_stats_count; |
| struct qdrv_netdebug_per_node_phystats per_node_stats[1]; |
| } __packed; |
| |
| /* @NDB@: type=11 */ |
| struct qdrv_netdebug_dspstats { |
| struct qdrv_pktlogger_hdr ndb_hdr; |
| struct qtn_dsp_stats stats; |
| } __packed; |
| |
| /* @NDB@: type=12 */ |
| struct qdrv_netdebug_core_dump { |
| struct qdrv_pktlogger_hdr ndb_hdr; |
| char data[CONFIG_ARC_MUC_STACK_SIZE]; |
| } __packed; |
| |
| extern int g_triggers_on; |
| |
| int topaz_read_internal_temp_sens(int *temp); |
| void qdrv_halt_muc(void); |
| int get_temp_zone_from_tprofile(void); |
| int convert_temp_index(int temp); |
| |
| /* Support wlan modules */ |
| int qdrv_rx_poll(struct napi_struct *napi, int budget); |
| int qdrv_rx_start(struct qdrv_mac *mac); |
| int qdrv_rx_stop(struct qdrv_mac *mac); |
| int qdrv_rx_init(struct qdrv_wlan *qw, struct host_ioctl_hifinfo *hifinfo); |
| int qdrv_rx_exit(struct qdrv_wlan *qw); |
| |
| void qdrv_tx_done_flush_vap(struct qdrv_vap *qv); |
| int qdrv_tx_hardstart(struct sk_buff *skb, struct net_device *dev); |
| struct host_txdesc * qdrv_tx_get_mgt_txdesc(struct sk_buff *skb, struct net_device *dev); |
| void qdrv_tx_release_txdesc(struct qdrv_wlan *qw, struct lhost_txdesc* txdesc); |
| int qdrv_tx_start(struct qdrv_mac *mac); |
| int qdrv_tx_stop(struct qdrv_mac *mac); |
| int qdrv_tx_eth_pause_init(struct qdrv_wlan *qw); |
| int qdrv_tx_init(struct qdrv_mac *mac, struct host_ioctl_hifinfo *hifinfo, |
| u32 arg2); |
| int qdrv_tx_exit(struct qdrv_wlan *qw); |
| void qdrv_tx_ba_establish(struct qdrv_vap *qv, |
| struct ieee80211_node *ni, uint8_t tid); |
| |
| int qdrv_scan_start(struct qdrv_mac *mac); |
| int qdrv_scan_stop(struct qdrv_mac *mac); |
| int qdrv_scan_init(struct qdrv_wlan *qw, struct host_ioctl_hifinfo *hifinfo); |
| int qdrv_scan_exit(struct qdrv_wlan *qw); |
| int qdrv_async_cca_read(struct ieee80211com *ic, const struct ieee80211_channel *sample_channel, |
| u_int64_t start_tsf, u_int32_t sample_millis); |
| |
| int qdrv_ap_isolate_filter(struct ieee80211_node *ni, struct sk_buff *skb); |
| |
| int qdrv_hostlink_msg_cmd(struct qdrv_wlan *qw, u_int32_t cmd, u_int32_t arg); |
| int qdrv_hostlink_msg_create_vap(struct qdrv_wlan *qw, const char *name, const uint8_t *mac_addr, |
| int devid, int opmode, int flags); |
| int qdrv_hostlink_msg_delete_vap(struct qdrv_wlan *qw, struct net_device *vdev); |
| int qdrv_hostlink_start(struct qdrv_mac *mac); |
| int qdrv_hostlink_stop(struct qdrv_mac *mac); |
| int qdrv_hostlink_init(struct qdrv_wlan *qw, |
| struct host_ioctl_hifinfo *hifinfo); |
| int qdrv_hostlink_exit(struct qdrv_wlan *qw); |
| int qdrv_hostlink_store_txpow(struct qdrv_wlan *qw, u_int32_t txpower); |
| int qdrv_hostlink_setchan(struct qdrv_wlan *qw, uint32_t freq_band, uint32_t qtn_chan); |
| int qdrv_hostlink_sample_chan_cancel(struct qdrv_wlan *qw, struct qtn_samp_chan_info *); |
| int qdrv_hostlink_sample_chan(struct qdrv_wlan *qw, struct qtn_samp_chan_info *); |
| int qdrv_hostlink_remain_chan(struct qdrv_wlan *qw, struct qtn_remain_chan_info *remain_chan_bus); |
| int qdrv_hostlink_set_ocac(struct qdrv_wlan *qw, struct qtn_ocac_info *); |
| int qdrv_hostlink_suspend_off_chan(struct qdrv_wlan *qw, uint32_t suspend); |
| int qdrv_hostlink_meas_chan(struct qdrv_wlan *qw, struct qtn_meas_chan_info *meas_chan_bus); |
| int qdrv_hostlink_rxgain_params(struct qdrv_wlan *qw, uint32_t index, struct qtn_rf_rxgain_params *rx_gain_params); |
| #ifdef QTN_BG_SCAN |
| int qdrv_hostlink_bgscan_chan(struct qdrv_wlan *qw, struct qtn_scan_chan_info *); |
| #endif /* QTN_BG_SCAN */ |
| int qdrv_hostlink_setchan_deferred(struct qdrv_wlan *qw, struct qtn_csa_info*); |
| int qdrv_hostlink_setscanmode(struct qdrv_wlan *qw, u_int32_t scanmode); |
| int qdrv_hostlink_xmitctl(struct qdrv_wlan *qw, bool enable_xmit); |
| int qdrv_hostlink_msg_calcmd(struct qdrv_wlan *qw, int cmdlen, dma_addr_t cmd_dma); |
| //int qdrv_hostlink_do_txpwr_cal(struct qdrv_wlan *qw, int temp_idx, int pwr); |
| int qdrv_hostlink_msg_set_wifi_macaddr( struct qdrv_wlan *qw, u8 *new_macaddr ); |
| int qdrv_hlink_get_outstand_msgs(struct qdrv_wlan *qw); |
| int qdrv_hostlink_set_hrflags(struct qdrv_wlan *qw, u_int32_t flags); |
| int qdrv_hostlink_power_save(struct qdrv_wlan *qw, int param, int val); |
| int qdrv_hostlink_tx_airtime_control(struct qdrv_wlan *qw, uint32_t value); |
| int qdrv_hostlink_mu_group_update(struct qdrv_wlan *qw, struct qtn_mu_group_update_args *args); |
| void* qdrv_hostlink_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag); |
| void qdrv_hostlink_free_coherent(struct device *dev, size_t size, void *kvaddr, dma_addr_t dma_handle); |
| extern u_int8_t get_bootcfg_scancnt(void); |
| uint8_t get_bootcfg_two_by_four_configuration(void); |
| enum hw_opt_t get_bootcfg_bond_opt(void); |
| |
| #ifdef CONFIG_QVSP |
| int qdrv_hostlink_qvsp(struct qdrv_wlan *qw, uint32_t param, uint32_t value); |
| int qdrv_wlan_query_wds(struct ieee80211com *ic); |
| #endif |
| |
| int qdrv_hostlink_killmuc(struct qdrv_wlan *qw); |
| int qdrv_hostlink_use_rtscts(struct qdrv_wlan *qw, int rtscts_required); |
| int qdrv_hostlink_send_ioctl_args(struct qdrv_wlan *qw, uint32_t command, |
| uint32_t arg1, uint32_t arg2); |
| |
| void qdrv_dump_replace_db(struct qdrv_wlan *qw); |
| int qdrv_hostlink_enable_flush_data(struct qdrv_wlan *qw, int enable); |
| int qdrv_hostlink_update_ocac_state_ie(struct qdrv_wlan *qw, uint8_t state, uint8_t param); |
| |
| int qdrv_wlan_80211_set_bcn_scheme(struct ieee80211vap *vap, int param, int value); |
| int qdrv_hostlink_change_bcn_scheme(struct qdrv_vap *qv, int param, int value); |
| |
| /* Main wlan module */ |
| #if 0 |
| int qdrv_wlan_start(void *data, char *name); |
| #endif |
| int qdrv_wlan_stats(void *data); |
| int qdrv_wlan_start_vap(struct qdrv_wlan *qw, const char *name, |
| uint8_t *mac_addr, int devid, int opmode, int flags); |
| int qdrv_wlan_stop_vap(struct qdrv_mac *mac, struct net_device *vdev); |
| int qdrv_wlan_init(struct qdrv_mac *mac, struct host_ioctl_hifinfo *hifinfo, |
| u32 arg1, u32 arg2); |
| int qdrv_wlan_exit(struct qdrv_mac *mac); |
| int qdrv_wlan_get_assoc_queue_info(void *data); |
| int qdrv_wlan_get_assoc_info(void *data); |
| #ifdef CONFIG_NAC_MONITOR |
| int qdrv_wlan_get_nac_info(void *data); |
| #endif |
| int qdrv_wps_button_init(struct net_device *dev); |
| void qdrv_wps_button_exit(void); |
| struct net_device *qdrv_wps_button_get_dev(void); |
| int qdrv_wlan_tkip_mic_error(struct qdrv_mac *mac, int devid, int count); |
| int qdrv_wlan_ba_is_ok(struct ieee80211_node *ni, int tid, int direction); |
| void qdrv_wlan_igmp_query_timer_start(struct qdrv_wlan *qw); |
| void qdrv_wlan_igmp_timer_stop(struct qdrv_wlan *qw); |
| void qdrv_wlan_drop_ba(struct ieee80211_node *ni, int tid, int tx, int reason); |
| void qdrv_wlan_cleanup_before_reload(struct ieee80211com *ic); |
| int qdrv_get_br_ipaddr(struct qdrv_wlan *qw, __be32 *ipaddr); |
| int qdrv_is_bridge_ipaddr(struct qdrv_wlan *qw, __be32 ipaddr); |
| void qdrv_wlan_dump_ba(struct ieee80211_node *ni); |
| void qdrv_wlan_stats_prot(struct qdrv_wlan *qw, uint8_t is_tx, uint16_t ether_type, |
| uint8_t ip_proto); |
| int qdrv_proxy_arp(struct ieee80211vap *iv, |
| struct qdrv_wlan *qw, |
| struct ieee80211_node *ni_rx, |
| uint8_t *data_start); |
| #ifdef CONFIG_IPV6 |
| int qdrv_wlan_handle_neigh_msg(struct ieee80211vap *vap, struct qdrv_wlan *qw, |
| uint8_t *data_start, uint8_t in_tx, struct sk_buff *skb, |
| uint8_t ip_proto, void *proto_data); |
| #endif |
| #ifdef CONFIG_QVSP |
| int qdrv_wlan_vsp_3rdpt_init(struct qdrv_wlan *qw); |
| void qdrv_wlan_vsp_3rdpt_exit(struct qdrv_wlan *qw); |
| #endif |
| |
| void qdrv_wlan_vlan_enable(struct ieee80211com *ic, int enable); |
| int qdrv_hostlink_vlan_enable(struct qdrv_wlan *qw, int enable); |
| |
| void qdrv_tx_airtime_control(struct ieee80211vap *vap, uint32_t vaule); |
| |
| void qdrv_mu_grp_update(struct ieee80211com *ic, struct qtn_mu_group_update_args *args); |
| |
| static inline struct qdrv_wlan *qdrv_mac_get_wlan(struct qdrv_mac *mac) |
| { |
| return (struct qdrv_wlan*)mac->data; |
| } |
| |
| static inline int |
| qdrv_wlan_bc_should_forward(const struct ether_header *eh, |
| struct ieee80211vap *iv) |
| { |
| if (ieee80211_is_bcst(eh->ether_dhost) && iv->iv_reliable_bcst) { |
| return 1; |
| } |
| |
| return 0; |
| } |
| |
| static inline int |
| qdrv_wlan_mc_should_drop(const struct ether_header *eh, void *p_iphdr, |
| struct ieee80211vap *iv, bool is_vap_node, uint8_t ip_proto) |
| { |
| /* Make sure frames are not transmitted prior to CAC */ |
| if (IEEE80211_IS_MULTICAST(eh->ether_dhost) && |
| iv->iv_opmode == IEEE80211_M_HOSTAP && |
| iv->iv_ic->ic_sta_assoc == 0) { |
| return 1; |
| } |
| |
| if (IEEE80211_IS_MULTICAST(eh->ether_dhost) && |
| is_vap_node && |
| ip_proto != IPPROTO_ICMPV6 && |
| ip_proto != IPPROTO_IGMP && |
| !iv->iv_forward_unknown_mc && |
| iputil_is_mc_data(eh, p_iphdr)) { |
| return 1; |
| } |
| |
| return 0; |
| } |
| |
| static inline int |
| qdrv_wlan_mc_should_forward(const struct ether_header *eh, void *p_iphdr, |
| struct ieee80211vap *iv, bool is_vap_node) |
| { |
| if (iputil_eth_is_multicast(eh) && |
| is_vap_node && |
| iv->iv_forward_unknown_mc) { |
| return 1; |
| } |
| |
| return 0; |
| } |
| |
| static inline int qdrv_wlan_is_4addr_mc(const struct ether_header *eh, u_int8_t *data_start, |
| struct ieee80211vap *iv, bool is_vap_node) |
| { |
| if (unlikely(IEEE80211_IS_MULTICAST(eh->ether_dhost) && |
| (iputil_is_lncb(eh->ether_dhost, data_start) || |
| qdrv_wlan_mc_should_forward(eh, data_start, iv, is_vap_node) || |
| qdrv_wlan_bc_should_forward(eh, iv)))) { |
| return 1; |
| } |
| |
| return 0; |
| } |
| |
| #define IGMP_TYPE_QUERY 0x11 |
| #define IGMP_TYPE_MEMBERSHIP_REPORT1 0x12 |
| #define IGMP_TYPE_MEMBERSHIP_REPORT2 0x16 |
| #define IGMP_TYPE_LEAVE_GROUP 0x17 |
| #define IGMP_TYPE_MEMBERSHIP_REPORT3 0x22 |
| |
| static inline const char *qdrv_igmp_type_to_string(int igmp_type) |
| { |
| switch(igmp_type) { |
| case IGMP_TYPE_QUERY: |
| return "Query"; |
| case IGMP_TYPE_MEMBERSHIP_REPORT1: |
| return "Membership Report (v1)"; |
| case IGMP_TYPE_MEMBERSHIP_REPORT2: |
| return "Membership Report (v2)"; |
| case IGMP_TYPE_MEMBERSHIP_REPORT3: |
| return "Membership Report (v3)"; |
| case IGMP_TYPE_LEAVE_GROUP: |
| return "Leave Group"; |
| //default: |
| /* Fall through */ |
| } |
| return "Unknown"; |
| } |
| |
| static inline int qdrv_igmp_type(struct iphdr *p_iphdr, int len) |
| { |
| /* Incomplete, but enough for the field we're interested in. */ |
| struct igmphdr { |
| u_int8_t type; |
| }; |
| if (len > (sizeof(*p_iphdr) + sizeof(struct igmphdr))) { |
| if (p_iphdr->protocol == IPPROTO_IGMP) { |
| /* Size of IP header is in 4 byte words */ |
| int hlen = p_iphdr->ihl * (sizeof(u_int32_t)); |
| struct igmphdr *p_igmp = (struct igmphdr *)((u_int8_t *)p_iphdr + hlen); |
| return p_igmp->type; |
| } |
| } |
| return 0; |
| } |
| |
| /* Is this an IGMP query? */ |
| static inline int qdrv_is_igmp_query(struct iphdr *p_iphdr, int len) |
| { |
| if (qdrv_igmp_type(p_iphdr, len) == IGMP_TYPE_QUERY) { |
| return 1; |
| } |
| return 0; |
| } |
| |
| void qdrv_channel_switch_record(struct ieee80211com *ic, struct ieee80211_channel *new_chan, |
| uint32_t reason); |
| void qdrv_channel_switch_reason_record(struct ieee80211com *ic, int reason); |
| int8_t qdrv_get_local_tx_power(struct ieee80211com *ic); |
| int qdrv_get_local_link_margin(struct ieee80211_node *ni, int8_t *result); |
| int qdrv_wlan_get_shared_vap_stats(struct ieee80211vap *vap); |
| int qdrv_wlan_reset_shared_vap_stats(struct ieee80211vap *vap); |
| int qdrv_wlan_get_shared_node_stats(struct ieee80211_node *ni); |
| int qdrv_wlan_reset_shared_node_stats(struct ieee80211_node *ni); |
| int qdrv_rxgain_params(struct ieee80211com *ic, int index, struct qtn_rf_rxgain_params *params); |
| void qdrv_wlan_get_dscp2ac_map(const uint8_t vapid, uint8_t *dscp2ac); |
| void qdrv_wlan_set_dscp2ac_map(const uint8_t vapid, uint8_t *ip_dscp, uint8_t listlen, uint8_t ac); |
| void wowlan_wakeup_host(void); |
| /* |
| * Delete all bridge table entries for the peer. They would eventually |
| * age out, but in the mean time data will be directed to the wrong |
| * sub_port (node_idx) until the bridge entries are updated by upstream |
| * traffic from the endpoint. Multicast port entries for the sub_port |
| * are not aged and would hang around for ever, so they are also deleted. |
| */ |
| |
| |
| #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) |
| static inline void qdrv_remove_invalid_sub_port(struct ieee80211vap *vap, |
| uint32_t sub_port) |
| { |
| struct net_bridge_port *br_port = get_br_port(vap->iv_dev); |
| |
| DBGPRINTF(DBG_LL_DEBUG, QDRV_LF_BRIDGE, "Purge subport[0x%x]\n", sub_port); |
| #if (defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)) |
| if (br_fdb_delete_by_sub_port_hook && br_port) { |
| br_fdb_delete_by_sub_port_hook(br_port->br, |
| br_port, sub_port); |
| } |
| #endif |
| } |
| #else |
| static inline void qdrv_remove_invalid_sub_port(struct ieee80211vap *vap, |
| uint32_t sub_port) |
| { |
| DBGPRINTF(DBG_LL_DEBUG, QDRV_LF_BRIDGE, "Purge subport[0x%x]\n", sub_port); |
| #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) |
| if (br_fdb_delete_by_sub_port_hook && vap->iv_dev->br_port) { |
| br_fdb_delete_by_sub_port_hook(vap->iv_dev->br_port->br, |
| vap->iv_dev->br_port, sub_port); |
| } |
| #endif |
| } |
| #endif |
| |
| int qtn_tsensor_get_temperature(struct i2c_client *client, int *val); |
| |
| void qdrv_tqe_send_l2_ext_filter(struct qdrv_wlan *qw, struct sk_buff *skb); |
| |
| /* |
| * Called only if packet received has destination address as broadcast. |
| */ |
| static inline int check_if_exceeds_max_bcast_pps(struct bcast_pps_info *bcast_pps, int is_rx) |
| { |
| u_int16_t *bcast_counter; |
| unsigned long *start_time; |
| if (is_rx) { |
| bcast_counter = &bcast_pps->rx_bcast_counter; |
| start_time = &bcast_pps->rx_bcast_pps_start_time; |
| } else { |
| bcast_counter = &bcast_pps->tx_bcast_counter; |
| start_time = &bcast_pps->tx_bcast_pps_start_time; |
| } |
| if (time_after(jiffies, ((*start_time) + HZ))) { |
| *start_time = jiffies; |
| *bcast_counter = 0; |
| } |
| if (*bcast_counter >= bcast_pps->max_bcast_pps) { |
| return 1; |
| } |
| (*bcast_counter)++; |
| return 0; |
| } |
| |
| static inline int check_is_bcast_pps_exception(uint16_t ether_type, uint8_t ip_proto, |
| void *proto_data) |
| { |
| if (ether_type == __constant_htons(ETH_P_ARP)) { |
| return 1; |
| } |
| |
| if (ether_type == __constant_htons(ETH_P_IP) && |
| proto_data && |
| ip_proto == IPPROTO_UDP) { |
| struct udphdr *udph = proto_data; |
| |
| if ((udph->dest == __constant_htons(DHCPSERVER_PORT)) || |
| udph->dest == __constant_htons(DHCPCLIENT_PORT)) { |
| return 1; |
| } |
| } |
| return 0; |
| } |
| |
| static inline int bcast_pps_should_drop(const u8 *dst, struct bcast_pps_info *bcast_pps, |
| uint16_t eth_type, uint8_t ip_proto, void *proto_data, int is_rx) |
| { |
| if ((ieee80211_is_bcst(dst)) |
| && (bcast_pps->max_bcast_pps) |
| && (!check_is_bcast_pps_exception(eth_type, ip_proto, proto_data)) |
| && (check_if_exceeds_max_bcast_pps(bcast_pps, is_rx))) { |
| return 1; |
| } |
| return 0; |
| } |
| |
| #endif |