18c2ecf20Sopenharmony_ci/******************************************************************************
28c2ecf20Sopenharmony_ci *
38c2ecf20Sopenharmony_ci * This file is provided under a dual BSD/GPLv2 license.  When using or
48c2ecf20Sopenharmony_ci * redistributing this file, you may do so under either license.
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * GPL LICENSE SUMMARY
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * Copyright(c) 2003 - 2015 Intel Corporation. All rights reserved.
98c2ecf20Sopenharmony_ci * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
108c2ecf20Sopenharmony_ci * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
118c2ecf20Sopenharmony_ci * Copyright(c) 2018 - 2019 Intel Corporation
128c2ecf20Sopenharmony_ci *
138c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or modify it
148c2ecf20Sopenharmony_ci * under the terms of version 2 of the GNU General Public License as
158c2ecf20Sopenharmony_ci * published by the Free Software Foundation.
168c2ecf20Sopenharmony_ci *
178c2ecf20Sopenharmony_ci * This program is distributed in the hope that it will be useful, but WITHOUT
188c2ecf20Sopenharmony_ci * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
198c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
208c2ecf20Sopenharmony_ci * more details.
218c2ecf20Sopenharmony_ci *
228c2ecf20Sopenharmony_ci * The full GNU General Public License is included in this distribution in the
238c2ecf20Sopenharmony_ci * file called COPYING.
248c2ecf20Sopenharmony_ci *
258c2ecf20Sopenharmony_ci * Contact Information:
268c2ecf20Sopenharmony_ci *  Intel Linux Wireless <linuxwifi@intel.com>
278c2ecf20Sopenharmony_ci * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
288c2ecf20Sopenharmony_ci *
298c2ecf20Sopenharmony_ci * BSD LICENSE
308c2ecf20Sopenharmony_ci *
318c2ecf20Sopenharmony_ci * Copyright(c) 2003 - 2015 Intel Corporation. All rights reserved.
328c2ecf20Sopenharmony_ci * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
338c2ecf20Sopenharmony_ci * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
348c2ecf20Sopenharmony_ci * Copyright(c) 2018 - 2019 Intel Corporation
358c2ecf20Sopenharmony_ci * All rights reserved.
368c2ecf20Sopenharmony_ci *
378c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without
388c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions
398c2ecf20Sopenharmony_ci * are met:
408c2ecf20Sopenharmony_ci *
418c2ecf20Sopenharmony_ci *  * Redistributions of source code must retain the above copyright
428c2ecf20Sopenharmony_ci *    notice, this list of conditions and the following disclaimer.
438c2ecf20Sopenharmony_ci *  * Redistributions in binary form must reproduce the above copyright
448c2ecf20Sopenharmony_ci *    notice, this list of conditions and the following disclaimer in
458c2ecf20Sopenharmony_ci *    the documentation and/or other materials provided with the
468c2ecf20Sopenharmony_ci *    distribution.
478c2ecf20Sopenharmony_ci *  * Neither the name Intel Corporation nor the names of its
488c2ecf20Sopenharmony_ci *    contributors may be used to endorse or promote products derived
498c2ecf20Sopenharmony_ci *    from this software without specific prior written permission.
508c2ecf20Sopenharmony_ci *
518c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
528c2ecf20Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
538c2ecf20Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
548c2ecf20Sopenharmony_ci * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
558c2ecf20Sopenharmony_ci * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
568c2ecf20Sopenharmony_ci * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
578c2ecf20Sopenharmony_ci * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
588c2ecf20Sopenharmony_ci * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
598c2ecf20Sopenharmony_ci * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
608c2ecf20Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
618c2ecf20Sopenharmony_ci * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
628c2ecf20Sopenharmony_ci *
638c2ecf20Sopenharmony_ci *****************************************************************************/
648c2ecf20Sopenharmony_ci#ifndef __iwl_trans_int_pcie_h__
658c2ecf20Sopenharmony_ci#define __iwl_trans_int_pcie_h__
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci#include <linux/spinlock.h>
688c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
698c2ecf20Sopenharmony_ci#include <linux/skbuff.h>
708c2ecf20Sopenharmony_ci#include <linux/wait.h>
718c2ecf20Sopenharmony_ci#include <linux/pci.h>
728c2ecf20Sopenharmony_ci#include <linux/timer.h>
738c2ecf20Sopenharmony_ci#include <linux/cpu.h>
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci#include "iwl-fh.h"
768c2ecf20Sopenharmony_ci#include "iwl-csr.h"
778c2ecf20Sopenharmony_ci#include "iwl-trans.h"
788c2ecf20Sopenharmony_ci#include "iwl-debug.h"
798c2ecf20Sopenharmony_ci#include "iwl-io.h"
808c2ecf20Sopenharmony_ci#include "iwl-op-mode.h"
818c2ecf20Sopenharmony_ci#include "iwl-drv.h"
828c2ecf20Sopenharmony_ci#include "queue/tx.h"
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci/*
858c2ecf20Sopenharmony_ci * RX related structures and functions
868c2ecf20Sopenharmony_ci */
878c2ecf20Sopenharmony_ci#define RX_NUM_QUEUES 1
888c2ecf20Sopenharmony_ci#define RX_POST_REQ_ALLOC 2
898c2ecf20Sopenharmony_ci#define RX_CLAIM_REQ_ALLOC 8
908c2ecf20Sopenharmony_ci#define RX_PENDING_WATERMARK 16
918c2ecf20Sopenharmony_ci#define FIRST_RX_QUEUE 512
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_cistruct iwl_host_cmd;
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci/*This file includes the declaration that are internal to the
968c2ecf20Sopenharmony_ci * trans_pcie layer */
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci/**
998c2ecf20Sopenharmony_ci * struct iwl_rx_mem_buffer
1008c2ecf20Sopenharmony_ci * @page_dma: bus address of rxb page
1018c2ecf20Sopenharmony_ci * @page: driver's pointer to the rxb page
1028c2ecf20Sopenharmony_ci * @invalid: rxb is in driver ownership - not owned by HW
1038c2ecf20Sopenharmony_ci * @vid: index of this rxb in the global table
1048c2ecf20Sopenharmony_ci * @offset: indicates which offset of the page (in bytes)
1058c2ecf20Sopenharmony_ci *	this buffer uses (if multiple RBs fit into one page)
1068c2ecf20Sopenharmony_ci */
1078c2ecf20Sopenharmony_cistruct iwl_rx_mem_buffer {
1088c2ecf20Sopenharmony_ci	dma_addr_t page_dma;
1098c2ecf20Sopenharmony_ci	struct page *page;
1108c2ecf20Sopenharmony_ci	u16 vid;
1118c2ecf20Sopenharmony_ci	bool invalid;
1128c2ecf20Sopenharmony_ci	struct list_head list;
1138c2ecf20Sopenharmony_ci	u32 offset;
1148c2ecf20Sopenharmony_ci};
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci/**
1178c2ecf20Sopenharmony_ci * struct isr_statistics - interrupt statistics
1188c2ecf20Sopenharmony_ci *
1198c2ecf20Sopenharmony_ci */
1208c2ecf20Sopenharmony_cistruct isr_statistics {
1218c2ecf20Sopenharmony_ci	u32 hw;
1228c2ecf20Sopenharmony_ci	u32 sw;
1238c2ecf20Sopenharmony_ci	u32 err_code;
1248c2ecf20Sopenharmony_ci	u32 sch;
1258c2ecf20Sopenharmony_ci	u32 alive;
1268c2ecf20Sopenharmony_ci	u32 rfkill;
1278c2ecf20Sopenharmony_ci	u32 ctkill;
1288c2ecf20Sopenharmony_ci	u32 wakeup;
1298c2ecf20Sopenharmony_ci	u32 rx;
1308c2ecf20Sopenharmony_ci	u32 tx;
1318c2ecf20Sopenharmony_ci	u32 unhandled;
1328c2ecf20Sopenharmony_ci};
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci/**
1358c2ecf20Sopenharmony_ci * struct iwl_rx_transfer_desc - transfer descriptor
1368c2ecf20Sopenharmony_ci * @addr: ptr to free buffer start address
1378c2ecf20Sopenharmony_ci * @rbid: unique tag of the buffer
1388c2ecf20Sopenharmony_ci * @reserved: reserved
1398c2ecf20Sopenharmony_ci */
1408c2ecf20Sopenharmony_cistruct iwl_rx_transfer_desc {
1418c2ecf20Sopenharmony_ci	__le16 rbid;
1428c2ecf20Sopenharmony_ci	__le16 reserved[3];
1438c2ecf20Sopenharmony_ci	__le64 addr;
1448c2ecf20Sopenharmony_ci} __packed;
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci#define IWL_RX_CD_FLAGS_FRAGMENTED	BIT(0)
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci/**
1498c2ecf20Sopenharmony_ci * struct iwl_rx_completion_desc - completion descriptor
1508c2ecf20Sopenharmony_ci * @reserved1: reserved
1518c2ecf20Sopenharmony_ci * @rbid: unique tag of the received buffer
1528c2ecf20Sopenharmony_ci * @flags: flags (0: fragmented, all others: reserved)
1538c2ecf20Sopenharmony_ci * @reserved2: reserved
1548c2ecf20Sopenharmony_ci */
1558c2ecf20Sopenharmony_cistruct iwl_rx_completion_desc {
1568c2ecf20Sopenharmony_ci	__le32 reserved1;
1578c2ecf20Sopenharmony_ci	__le16 rbid;
1588c2ecf20Sopenharmony_ci	u8 flags;
1598c2ecf20Sopenharmony_ci	u8 reserved2[25];
1608c2ecf20Sopenharmony_ci} __packed;
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci/**
1638c2ecf20Sopenharmony_ci * struct iwl_rxq - Rx queue
1648c2ecf20Sopenharmony_ci * @id: queue index
1658c2ecf20Sopenharmony_ci * @bd: driver's pointer to buffer of receive buffer descriptors (rbd).
1668c2ecf20Sopenharmony_ci *	Address size is 32 bit in pre-9000 devices and 64 bit in 9000 devices.
1678c2ecf20Sopenharmony_ci *	In AX210 devices it is a pointer to a list of iwl_rx_transfer_desc's
1688c2ecf20Sopenharmony_ci * @bd_dma: bus address of buffer of receive buffer descriptors (rbd)
1698c2ecf20Sopenharmony_ci * @ubd: driver's pointer to buffer of used receive buffer descriptors (rbd)
1708c2ecf20Sopenharmony_ci * @ubd_dma: physical address of buffer of used receive buffer descriptors (rbd)
1718c2ecf20Sopenharmony_ci * @tr_tail: driver's pointer to the transmission ring tail buffer
1728c2ecf20Sopenharmony_ci * @tr_tail_dma: physical address of the buffer for the transmission ring tail
1738c2ecf20Sopenharmony_ci * @cr_tail: driver's pointer to the completion ring tail buffer
1748c2ecf20Sopenharmony_ci * @cr_tail_dma: physical address of the buffer for the completion ring tail
1758c2ecf20Sopenharmony_ci * @read: Shared index to newest available Rx buffer
1768c2ecf20Sopenharmony_ci * @write: Shared index to oldest written Rx packet
1778c2ecf20Sopenharmony_ci * @free_count: Number of pre-allocated buffers in rx_free
1788c2ecf20Sopenharmony_ci * @used_count: Number of RBDs handled to allocator to use for allocation
1798c2ecf20Sopenharmony_ci * @write_actual:
1808c2ecf20Sopenharmony_ci * @rx_free: list of RBDs with allocated RB ready for use
1818c2ecf20Sopenharmony_ci * @rx_used: list of RBDs with no RB attached
1828c2ecf20Sopenharmony_ci * @need_update: flag to indicate we need to update read/write index
1838c2ecf20Sopenharmony_ci * @rb_stts: driver's pointer to receive buffer status
1848c2ecf20Sopenharmony_ci * @rb_stts_dma: bus address of receive buffer status
1858c2ecf20Sopenharmony_ci * @lock:
1868c2ecf20Sopenharmony_ci * @queue: actual rx queue. Not used for multi-rx queue.
1878c2ecf20Sopenharmony_ci * @next_rb_is_fragment: indicates that the previous RB that we handled set
1888c2ecf20Sopenharmony_ci *	the fragmented flag, so the next one is still another fragment
1898c2ecf20Sopenharmony_ci *
1908c2ecf20Sopenharmony_ci * NOTE:  rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers
1918c2ecf20Sopenharmony_ci */
1928c2ecf20Sopenharmony_cistruct iwl_rxq {
1938c2ecf20Sopenharmony_ci	int id;
1948c2ecf20Sopenharmony_ci	void *bd;
1958c2ecf20Sopenharmony_ci	dma_addr_t bd_dma;
1968c2ecf20Sopenharmony_ci	union {
1978c2ecf20Sopenharmony_ci		void *used_bd;
1988c2ecf20Sopenharmony_ci		__le32 *bd_32;
1998c2ecf20Sopenharmony_ci		struct iwl_rx_completion_desc *cd;
2008c2ecf20Sopenharmony_ci	};
2018c2ecf20Sopenharmony_ci	dma_addr_t used_bd_dma;
2028c2ecf20Sopenharmony_ci	__le16 *tr_tail;
2038c2ecf20Sopenharmony_ci	dma_addr_t tr_tail_dma;
2048c2ecf20Sopenharmony_ci	__le16 *cr_tail;
2058c2ecf20Sopenharmony_ci	dma_addr_t cr_tail_dma;
2068c2ecf20Sopenharmony_ci	u32 read;
2078c2ecf20Sopenharmony_ci	u32 write;
2088c2ecf20Sopenharmony_ci	u32 free_count;
2098c2ecf20Sopenharmony_ci	u32 used_count;
2108c2ecf20Sopenharmony_ci	u32 write_actual;
2118c2ecf20Sopenharmony_ci	u32 queue_size;
2128c2ecf20Sopenharmony_ci	struct list_head rx_free;
2138c2ecf20Sopenharmony_ci	struct list_head rx_used;
2148c2ecf20Sopenharmony_ci	bool need_update, next_rb_is_fragment;
2158c2ecf20Sopenharmony_ci	void *rb_stts;
2168c2ecf20Sopenharmony_ci	dma_addr_t rb_stts_dma;
2178c2ecf20Sopenharmony_ci	spinlock_t lock;
2188c2ecf20Sopenharmony_ci	struct napi_struct napi;
2198c2ecf20Sopenharmony_ci	struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE];
2208c2ecf20Sopenharmony_ci};
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci/**
2238c2ecf20Sopenharmony_ci * struct iwl_rb_allocator - Rx allocator
2248c2ecf20Sopenharmony_ci * @req_pending: number of requests the allcator had not processed yet
2258c2ecf20Sopenharmony_ci * @req_ready: number of requests honored and ready for claiming
2268c2ecf20Sopenharmony_ci * @rbd_allocated: RBDs with pages allocated and ready to be handled to
2278c2ecf20Sopenharmony_ci *	the queue. This is a list of &struct iwl_rx_mem_buffer
2288c2ecf20Sopenharmony_ci * @rbd_empty: RBDs with no page attached for allocator use. This is a list
2298c2ecf20Sopenharmony_ci *	of &struct iwl_rx_mem_buffer
2308c2ecf20Sopenharmony_ci * @lock: protects the rbd_allocated and rbd_empty lists
2318c2ecf20Sopenharmony_ci * @alloc_wq: work queue for background calls
2328c2ecf20Sopenharmony_ci * @rx_alloc: work struct for background calls
2338c2ecf20Sopenharmony_ci */
2348c2ecf20Sopenharmony_cistruct iwl_rb_allocator {
2358c2ecf20Sopenharmony_ci	atomic_t req_pending;
2368c2ecf20Sopenharmony_ci	atomic_t req_ready;
2378c2ecf20Sopenharmony_ci	struct list_head rbd_allocated;
2388c2ecf20Sopenharmony_ci	struct list_head rbd_empty;
2398c2ecf20Sopenharmony_ci	spinlock_t lock;
2408c2ecf20Sopenharmony_ci	struct workqueue_struct *alloc_wq;
2418c2ecf20Sopenharmony_ci	struct work_struct rx_alloc;
2428c2ecf20Sopenharmony_ci};
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci/**
2458c2ecf20Sopenharmony_ci * iwl_get_closed_rb_stts - get closed rb stts from different structs
2468c2ecf20Sopenharmony_ci * @rxq - the rxq to get the rb stts from
2478c2ecf20Sopenharmony_ci */
2488c2ecf20Sopenharmony_cistatic inline __le16 iwl_get_closed_rb_stts(struct iwl_trans *trans,
2498c2ecf20Sopenharmony_ci					    struct iwl_rxq *rxq)
2508c2ecf20Sopenharmony_ci{
2518c2ecf20Sopenharmony_ci	if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
2528c2ecf20Sopenharmony_ci		__le16 *rb_stts = rxq->rb_stts;
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci		return READ_ONCE(*rb_stts);
2558c2ecf20Sopenharmony_ci	} else {
2568c2ecf20Sopenharmony_ci		struct iwl_rb_status *rb_stts = rxq->rb_stts;
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci		return READ_ONCE(rb_stts->closed_rb_num);
2598c2ecf20Sopenharmony_ci	}
2608c2ecf20Sopenharmony_ci}
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci#ifdef CONFIG_IWLWIFI_DEBUGFS
2638c2ecf20Sopenharmony_ci/**
2648c2ecf20Sopenharmony_ci * enum iwl_fw_mon_dbgfs_state - the different states of the monitor_data
2658c2ecf20Sopenharmony_ci * debugfs file
2668c2ecf20Sopenharmony_ci *
2678c2ecf20Sopenharmony_ci * @IWL_FW_MON_DBGFS_STATE_CLOSED: the file is closed.
2688c2ecf20Sopenharmony_ci * @IWL_FW_MON_DBGFS_STATE_OPEN: the file is open.
2698c2ecf20Sopenharmony_ci * @IWL_FW_MON_DBGFS_STATE_DISABLED: the file is disabled, once this state is
2708c2ecf20Sopenharmony_ci *	set the file can no longer be used.
2718c2ecf20Sopenharmony_ci */
2728c2ecf20Sopenharmony_cienum iwl_fw_mon_dbgfs_state {
2738c2ecf20Sopenharmony_ci	IWL_FW_MON_DBGFS_STATE_CLOSED,
2748c2ecf20Sopenharmony_ci	IWL_FW_MON_DBGFS_STATE_OPEN,
2758c2ecf20Sopenharmony_ci	IWL_FW_MON_DBGFS_STATE_DISABLED,
2768c2ecf20Sopenharmony_ci};
2778c2ecf20Sopenharmony_ci#endif
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci/**
2808c2ecf20Sopenharmony_ci * enum iwl_shared_irq_flags - level of sharing for irq
2818c2ecf20Sopenharmony_ci * @IWL_SHARED_IRQ_NON_RX: interrupt vector serves non rx causes.
2828c2ecf20Sopenharmony_ci * @IWL_SHARED_IRQ_FIRST_RSS: interrupt vector serves first RSS queue.
2838c2ecf20Sopenharmony_ci */
2848c2ecf20Sopenharmony_cienum iwl_shared_irq_flags {
2858c2ecf20Sopenharmony_ci	IWL_SHARED_IRQ_NON_RX		= BIT(0),
2868c2ecf20Sopenharmony_ci	IWL_SHARED_IRQ_FIRST_RSS	= BIT(1),
2878c2ecf20Sopenharmony_ci};
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci/**
2908c2ecf20Sopenharmony_ci * enum iwl_image_response_code - image response values
2918c2ecf20Sopenharmony_ci * @IWL_IMAGE_RESP_DEF: the default value of the register
2928c2ecf20Sopenharmony_ci * @IWL_IMAGE_RESP_SUCCESS: iml was read successfully
2938c2ecf20Sopenharmony_ci * @IWL_IMAGE_RESP_FAIL: iml reading failed
2948c2ecf20Sopenharmony_ci */
2958c2ecf20Sopenharmony_cienum iwl_image_response_code {
2968c2ecf20Sopenharmony_ci	IWL_IMAGE_RESP_DEF		= 0,
2978c2ecf20Sopenharmony_ci	IWL_IMAGE_RESP_SUCCESS		= 1,
2988c2ecf20Sopenharmony_ci	IWL_IMAGE_RESP_FAIL		= 2,
2998c2ecf20Sopenharmony_ci};
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ci/**
3028c2ecf20Sopenharmony_ci * struct cont_rec: continuous recording data structure
3038c2ecf20Sopenharmony_ci * @prev_wr_ptr: the last address that was read in monitor_data
3048c2ecf20Sopenharmony_ci *	debugfs file
3058c2ecf20Sopenharmony_ci * @prev_wrap_cnt: the wrap count that was used during the last read in
3068c2ecf20Sopenharmony_ci *	monitor_data debugfs file
3078c2ecf20Sopenharmony_ci * @state: the state of monitor_data debugfs file as described
3088c2ecf20Sopenharmony_ci *	in &iwl_fw_mon_dbgfs_state enum
3098c2ecf20Sopenharmony_ci * @mutex: locked while reading from monitor_data debugfs file
3108c2ecf20Sopenharmony_ci */
3118c2ecf20Sopenharmony_ci#ifdef CONFIG_IWLWIFI_DEBUGFS
3128c2ecf20Sopenharmony_cistruct cont_rec {
3138c2ecf20Sopenharmony_ci	u32 prev_wr_ptr;
3148c2ecf20Sopenharmony_ci	u32 prev_wrap_cnt;
3158c2ecf20Sopenharmony_ci	u8  state;
3168c2ecf20Sopenharmony_ci	/* Used to sync monitor_data debugfs file with driver unload flow */
3178c2ecf20Sopenharmony_ci	struct mutex mutex;
3188c2ecf20Sopenharmony_ci};
3198c2ecf20Sopenharmony_ci#endif
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci/**
3228c2ecf20Sopenharmony_ci * struct iwl_trans_pcie - PCIe transport specific data
3238c2ecf20Sopenharmony_ci * @rxq: all the RX queue data
3248c2ecf20Sopenharmony_ci * @rx_pool: initial pool of iwl_rx_mem_buffer for all the queues
3258c2ecf20Sopenharmony_ci * @global_table: table mapping received VID from hw to rxb
3268c2ecf20Sopenharmony_ci * @rba: allocator for RX replenishing
3278c2ecf20Sopenharmony_ci * @ctxt_info: context information for FW self init
3288c2ecf20Sopenharmony_ci * @ctxt_info_gen3: context information for gen3 devices
3298c2ecf20Sopenharmony_ci * @prph_info: prph info for self init
3308c2ecf20Sopenharmony_ci * @prph_scratch: prph scratch for self init
3318c2ecf20Sopenharmony_ci * @ctxt_info_dma_addr: dma addr of context information
3328c2ecf20Sopenharmony_ci * @prph_info_dma_addr: dma addr of prph info
3338c2ecf20Sopenharmony_ci * @prph_scratch_dma_addr: dma addr of prph scratch
3348c2ecf20Sopenharmony_ci * @ctxt_info_dma_addr: dma addr of context information
3358c2ecf20Sopenharmony_ci * @init_dram: DRAM data of firmware image (including paging).
3368c2ecf20Sopenharmony_ci *	Context information addresses will be taken from here.
3378c2ecf20Sopenharmony_ci *	This is driver's local copy for keeping track of size and
3388c2ecf20Sopenharmony_ci *	count for allocating and freeing the memory.
3398c2ecf20Sopenharmony_ci * @iml: image loader image virtual address
3408c2ecf20Sopenharmony_ci * @iml_dma_addr: image loader image DMA address
3418c2ecf20Sopenharmony_ci * @trans: pointer to the generic transport area
3428c2ecf20Sopenharmony_ci * @scd_base_addr: scheduler sram base address in SRAM
3438c2ecf20Sopenharmony_ci * @kw: keep warm address
3448c2ecf20Sopenharmony_ci * @pnvm_dram: DRAM area that contains the PNVM data
3458c2ecf20Sopenharmony_ci * @pci_dev: basic pci-network driver stuff
3468c2ecf20Sopenharmony_ci * @hw_base: pci hardware address support
3478c2ecf20Sopenharmony_ci * @ucode_write_complete: indicates that the ucode has been copied.
3488c2ecf20Sopenharmony_ci * @ucode_write_waitq: wait queue for uCode load
3498c2ecf20Sopenharmony_ci * @cmd_queue - command queue number
3508c2ecf20Sopenharmony_ci * @def_rx_queue - default rx queue number
3518c2ecf20Sopenharmony_ci * @rx_buf_size: Rx buffer size
3528c2ecf20Sopenharmony_ci * @scd_set_active: should the transport configure the SCD for HCMD queue
3538c2ecf20Sopenharmony_ci * @sw_csum_tx: if true, then the transport will compute the csum of the TXed
3548c2ecf20Sopenharmony_ci *	frame.
3558c2ecf20Sopenharmony_ci * @rx_page_order: page order for receive buffer size
3568c2ecf20Sopenharmony_ci * @rx_buf_bytes: RX buffer (RB) size in bytes
3578c2ecf20Sopenharmony_ci * @reg_lock: protect hw register access
3588c2ecf20Sopenharmony_ci * @mutex: to protect stop_device / start_fw / start_hw
3598c2ecf20Sopenharmony_ci * @cmd_in_flight: true when we have a host command in flight
3608c2ecf20Sopenharmony_ci#ifdef CONFIG_IWLWIFI_DEBUGFS
3618c2ecf20Sopenharmony_ci * @fw_mon_data: fw continuous recording data
3628c2ecf20Sopenharmony_ci#endif
3638c2ecf20Sopenharmony_ci * @msix_entries: array of MSI-X entries
3648c2ecf20Sopenharmony_ci * @msix_enabled: true if managed to enable MSI-X
3658c2ecf20Sopenharmony_ci * @shared_vec_mask: the type of causes the shared vector handles
3668c2ecf20Sopenharmony_ci *	(see iwl_shared_irq_flags).
3678c2ecf20Sopenharmony_ci * @alloc_vecs: the number of interrupt vectors allocated by the OS
3688c2ecf20Sopenharmony_ci * @def_irq: default irq for non rx causes
3698c2ecf20Sopenharmony_ci * @fh_init_mask: initial unmasked fh causes
3708c2ecf20Sopenharmony_ci * @hw_init_mask: initial unmasked hw causes
3718c2ecf20Sopenharmony_ci * @fh_mask: current unmasked fh causes
3728c2ecf20Sopenharmony_ci * @hw_mask: current unmasked hw causes
3738c2ecf20Sopenharmony_ci * @in_rescan: true if we have triggered a device rescan
3748c2ecf20Sopenharmony_ci * @base_rb_stts: base virtual address of receive buffer status for all queues
3758c2ecf20Sopenharmony_ci * @base_rb_stts_dma: base physical address of receive buffer status
3768c2ecf20Sopenharmony_ci * @supported_dma_mask: DMA mask to validate the actual address against,
3778c2ecf20Sopenharmony_ci *	will be DMA_BIT_MASK(11) or DMA_BIT_MASK(12) depending on the device
3788c2ecf20Sopenharmony_ci * @alloc_page_lock: spinlock for the page allocator
3798c2ecf20Sopenharmony_ci * @alloc_page: allocated page to still use parts of
3808c2ecf20Sopenharmony_ci * @alloc_page_used: how much of the allocated page was already used (bytes)
3818c2ecf20Sopenharmony_ci */
3828c2ecf20Sopenharmony_cistruct iwl_trans_pcie {
3838c2ecf20Sopenharmony_ci	struct iwl_rxq *rxq;
3848c2ecf20Sopenharmony_ci	struct iwl_rx_mem_buffer *rx_pool;
3858c2ecf20Sopenharmony_ci	struct iwl_rx_mem_buffer **global_table;
3868c2ecf20Sopenharmony_ci	struct iwl_rb_allocator rba;
3878c2ecf20Sopenharmony_ci	union {
3888c2ecf20Sopenharmony_ci		struct iwl_context_info *ctxt_info;
3898c2ecf20Sopenharmony_ci		struct iwl_context_info_gen3 *ctxt_info_gen3;
3908c2ecf20Sopenharmony_ci	};
3918c2ecf20Sopenharmony_ci	struct iwl_prph_info *prph_info;
3928c2ecf20Sopenharmony_ci	struct iwl_prph_scratch *prph_scratch;
3938c2ecf20Sopenharmony_ci	void *iml;
3948c2ecf20Sopenharmony_ci	dma_addr_t ctxt_info_dma_addr;
3958c2ecf20Sopenharmony_ci	dma_addr_t prph_info_dma_addr;
3968c2ecf20Sopenharmony_ci	dma_addr_t prph_scratch_dma_addr;
3978c2ecf20Sopenharmony_ci	dma_addr_t iml_dma_addr;
3988c2ecf20Sopenharmony_ci	struct iwl_trans *trans;
3998c2ecf20Sopenharmony_ci
4008c2ecf20Sopenharmony_ci	struct net_device napi_dev;
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci	/* INT ICT Table */
4038c2ecf20Sopenharmony_ci	__le32 *ict_tbl;
4048c2ecf20Sopenharmony_ci	dma_addr_t ict_tbl_dma;
4058c2ecf20Sopenharmony_ci	int ict_index;
4068c2ecf20Sopenharmony_ci	bool use_ict;
4078c2ecf20Sopenharmony_ci	bool is_down, opmode_down;
4088c2ecf20Sopenharmony_ci	s8 debug_rfkill;
4098c2ecf20Sopenharmony_ci	struct isr_statistics isr_stats;
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci	spinlock_t irq_lock;
4128c2ecf20Sopenharmony_ci	struct mutex mutex;
4138c2ecf20Sopenharmony_ci	u32 inta_mask;
4148c2ecf20Sopenharmony_ci	u32 scd_base_addr;
4158c2ecf20Sopenharmony_ci	struct iwl_dma_ptr kw;
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_ci	struct iwl_dram_data pnvm_dram;
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci	struct iwl_txq *txq_memory;
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ci	/* PCI bus related data */
4228c2ecf20Sopenharmony_ci	struct pci_dev *pci_dev;
4238c2ecf20Sopenharmony_ci	void __iomem *hw_base;
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_ci	bool ucode_write_complete;
4268c2ecf20Sopenharmony_ci	bool sx_complete;
4278c2ecf20Sopenharmony_ci	wait_queue_head_t ucode_write_waitq;
4288c2ecf20Sopenharmony_ci	wait_queue_head_t wait_command_queue;
4298c2ecf20Sopenharmony_ci	wait_queue_head_t sx_waitq;
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_ci	u8 def_rx_queue;
4328c2ecf20Sopenharmony_ci	u8 n_no_reclaim_cmds;
4338c2ecf20Sopenharmony_ci	u8 no_reclaim_cmds[MAX_NO_RECLAIM_CMDS];
4348c2ecf20Sopenharmony_ci	u16 num_rx_bufs;
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_ci	enum iwl_amsdu_size rx_buf_size;
4378c2ecf20Sopenharmony_ci	bool scd_set_active;
4388c2ecf20Sopenharmony_ci	bool sw_csum_tx;
4398c2ecf20Sopenharmony_ci	bool pcie_dbg_dumped_once;
4408c2ecf20Sopenharmony_ci	u32 rx_page_order;
4418c2ecf20Sopenharmony_ci	u32 rx_buf_bytes;
4428c2ecf20Sopenharmony_ci	u32 supported_dma_mask;
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci	/* allocator lock for the two values below */
4458c2ecf20Sopenharmony_ci	spinlock_t alloc_page_lock;
4468c2ecf20Sopenharmony_ci	struct page *alloc_page;
4478c2ecf20Sopenharmony_ci	u32 alloc_page_used;
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_ci	/*protect hw register */
4508c2ecf20Sopenharmony_ci	spinlock_t reg_lock;
4518c2ecf20Sopenharmony_ci	bool cmd_hold_nic_awake;
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci#ifdef CONFIG_IWLWIFI_DEBUGFS
4548c2ecf20Sopenharmony_ci	struct cont_rec fw_mon_data;
4558c2ecf20Sopenharmony_ci#endif
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci	struct msix_entry msix_entries[IWL_MAX_RX_HW_QUEUES];
4588c2ecf20Sopenharmony_ci	bool msix_enabled;
4598c2ecf20Sopenharmony_ci	u8 shared_vec_mask;
4608c2ecf20Sopenharmony_ci	u32 alloc_vecs;
4618c2ecf20Sopenharmony_ci	u32 def_irq;
4628c2ecf20Sopenharmony_ci	u32 fh_init_mask;
4638c2ecf20Sopenharmony_ci	u32 hw_init_mask;
4648c2ecf20Sopenharmony_ci	u32 fh_mask;
4658c2ecf20Sopenharmony_ci	u32 hw_mask;
4668c2ecf20Sopenharmony_ci	cpumask_t affinity_mask[IWL_MAX_RX_HW_QUEUES];
4678c2ecf20Sopenharmony_ci	u16 tx_cmd_queue_size;
4688c2ecf20Sopenharmony_ci	bool in_rescan;
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_ci	void *base_rb_stts;
4718c2ecf20Sopenharmony_ci	dma_addr_t base_rb_stts_dma;
4728c2ecf20Sopenharmony_ci};
4738c2ecf20Sopenharmony_ci
4748c2ecf20Sopenharmony_cistatic inline struct iwl_trans_pcie *
4758c2ecf20Sopenharmony_ciIWL_TRANS_GET_PCIE_TRANS(struct iwl_trans *trans)
4768c2ecf20Sopenharmony_ci{
4778c2ecf20Sopenharmony_ci	return (void *)trans->trans_specific;
4788c2ecf20Sopenharmony_ci}
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_cistatic inline void iwl_pcie_clear_irq(struct iwl_trans *trans,
4818c2ecf20Sopenharmony_ci				      struct msix_entry *entry)
4828c2ecf20Sopenharmony_ci{
4838c2ecf20Sopenharmony_ci	/*
4848c2ecf20Sopenharmony_ci	 * Before sending the interrupt the HW disables it to prevent
4858c2ecf20Sopenharmony_ci	 * a nested interrupt. This is done by writing 1 to the corresponding
4868c2ecf20Sopenharmony_ci	 * bit in the mask register. After handling the interrupt, it should be
4878c2ecf20Sopenharmony_ci	 * re-enabled by clearing this bit. This register is defined as
4888c2ecf20Sopenharmony_ci	 * write 1 clear (W1C) register, meaning that it's being clear
4898c2ecf20Sopenharmony_ci	 * by writing 1 to the bit.
4908c2ecf20Sopenharmony_ci	 */
4918c2ecf20Sopenharmony_ci	iwl_write32(trans, CSR_MSIX_AUTOMASK_ST_AD, BIT(entry->entry));
4928c2ecf20Sopenharmony_ci}
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_cistatic inline struct iwl_trans *
4958c2ecf20Sopenharmony_ciiwl_trans_pcie_get_trans(struct iwl_trans_pcie *trans_pcie)
4968c2ecf20Sopenharmony_ci{
4978c2ecf20Sopenharmony_ci	return container_of((void *)trans_pcie, struct iwl_trans,
4988c2ecf20Sopenharmony_ci			    trans_specific);
4998c2ecf20Sopenharmony_ci}
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_ci/*
5028c2ecf20Sopenharmony_ci * Convention: trans API functions: iwl_trans_pcie_XXX
5038c2ecf20Sopenharmony_ci *	Other functions: iwl_pcie_XXX
5048c2ecf20Sopenharmony_ci */
5058c2ecf20Sopenharmony_cistruct iwl_trans
5068c2ecf20Sopenharmony_ci*iwl_trans_pcie_alloc(struct pci_dev *pdev,
5078c2ecf20Sopenharmony_ci		      const struct pci_device_id *ent,
5088c2ecf20Sopenharmony_ci		      const struct iwl_cfg_trans_params *cfg_trans);
5098c2ecf20Sopenharmony_civoid iwl_trans_pcie_free(struct iwl_trans *trans);
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_ci/*****************************************************
5128c2ecf20Sopenharmony_ci* RX
5138c2ecf20Sopenharmony_ci******************************************************/
5148c2ecf20Sopenharmony_ciint iwl_pcie_rx_init(struct iwl_trans *trans);
5158c2ecf20Sopenharmony_ciint iwl_pcie_gen2_rx_init(struct iwl_trans *trans);
5168c2ecf20Sopenharmony_ciirqreturn_t iwl_pcie_msix_isr(int irq, void *data);
5178c2ecf20Sopenharmony_ciirqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id);
5188c2ecf20Sopenharmony_ciirqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id);
5198c2ecf20Sopenharmony_ciirqreturn_t iwl_pcie_irq_rx_msix_handler(int irq, void *dev_id);
5208c2ecf20Sopenharmony_ciint iwl_pcie_rx_stop(struct iwl_trans *trans);
5218c2ecf20Sopenharmony_civoid iwl_pcie_rx_free(struct iwl_trans *trans);
5228c2ecf20Sopenharmony_civoid iwl_pcie_free_rbs_pool(struct iwl_trans *trans);
5238c2ecf20Sopenharmony_civoid iwl_pcie_rx_init_rxb_lists(struct iwl_rxq *rxq);
5248c2ecf20Sopenharmony_ciint iwl_pcie_dummy_napi_poll(struct napi_struct *napi, int budget);
5258c2ecf20Sopenharmony_civoid iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority,
5268c2ecf20Sopenharmony_ci			    struct iwl_rxq *rxq);
5278c2ecf20Sopenharmony_ci
5288c2ecf20Sopenharmony_ci/*****************************************************
5298c2ecf20Sopenharmony_ci* ICT - interrupt handling
5308c2ecf20Sopenharmony_ci******************************************************/
5318c2ecf20Sopenharmony_ciirqreturn_t iwl_pcie_isr(int irq, void *data);
5328c2ecf20Sopenharmony_ciint iwl_pcie_alloc_ict(struct iwl_trans *trans);
5338c2ecf20Sopenharmony_civoid iwl_pcie_free_ict(struct iwl_trans *trans);
5348c2ecf20Sopenharmony_civoid iwl_pcie_reset_ict(struct iwl_trans *trans);
5358c2ecf20Sopenharmony_civoid iwl_pcie_disable_ict(struct iwl_trans *trans);
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_ci/*****************************************************
5388c2ecf20Sopenharmony_ci* TX / HCMD
5398c2ecf20Sopenharmony_ci******************************************************/
5408c2ecf20Sopenharmony_ciint iwl_pcie_tx_init(struct iwl_trans *trans);
5418c2ecf20Sopenharmony_civoid iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr);
5428c2ecf20Sopenharmony_ciint iwl_pcie_tx_stop(struct iwl_trans *trans);
5438c2ecf20Sopenharmony_civoid iwl_pcie_tx_free(struct iwl_trans *trans);
5448c2ecf20Sopenharmony_cibool iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int queue, u16 ssn,
5458c2ecf20Sopenharmony_ci			       const struct iwl_trans_txq_scd_cfg *cfg,
5468c2ecf20Sopenharmony_ci			       unsigned int wdg_timeout);
5478c2ecf20Sopenharmony_civoid iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int queue,
5488c2ecf20Sopenharmony_ci				bool configure_scd);
5498c2ecf20Sopenharmony_civoid iwl_trans_pcie_txq_set_shared_mode(struct iwl_trans *trans, u32 txq_id,
5508c2ecf20Sopenharmony_ci					bool shared_mode);
5518c2ecf20Sopenharmony_ciint iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
5528c2ecf20Sopenharmony_ci		      struct iwl_device_tx_cmd *dev_cmd, int txq_id);
5538c2ecf20Sopenharmony_civoid iwl_pcie_txq_check_wrptrs(struct iwl_trans *trans);
5548c2ecf20Sopenharmony_ciint iwl_trans_pcie_send_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd);
5558c2ecf20Sopenharmony_civoid iwl_pcie_hcmd_complete(struct iwl_trans *trans,
5568c2ecf20Sopenharmony_ci			    struct iwl_rx_cmd_buffer *rxb);
5578c2ecf20Sopenharmony_civoid iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
5588c2ecf20Sopenharmony_ci			    struct sk_buff_head *skbs);
5598c2ecf20Sopenharmony_civoid iwl_trans_pcie_set_q_ptrs(struct iwl_trans *trans, int txq_id, int ptr);
5608c2ecf20Sopenharmony_civoid iwl_trans_pcie_tx_reset(struct iwl_trans *trans);
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ci/*****************************************************
5638c2ecf20Sopenharmony_ci* Error handling
5648c2ecf20Sopenharmony_ci******************************************************/
5658c2ecf20Sopenharmony_civoid iwl_pcie_dump_csr(struct iwl_trans *trans);
5668c2ecf20Sopenharmony_ci
5678c2ecf20Sopenharmony_ci/*****************************************************
5688c2ecf20Sopenharmony_ci* Helpers
5698c2ecf20Sopenharmony_ci******************************************************/
5708c2ecf20Sopenharmony_cistatic inline void _iwl_disable_interrupts(struct iwl_trans *trans)
5718c2ecf20Sopenharmony_ci{
5728c2ecf20Sopenharmony_ci	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_ci	clear_bit(STATUS_INT_ENABLED, &trans->status);
5758c2ecf20Sopenharmony_ci	if (!trans_pcie->msix_enabled) {
5768c2ecf20Sopenharmony_ci		/* disable interrupts from uCode/NIC to host */
5778c2ecf20Sopenharmony_ci		iwl_write32(trans, CSR_INT_MASK, 0x00000000);
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_ci		/* acknowledge/clear/reset any interrupts still pending
5808c2ecf20Sopenharmony_ci		 * from uCode or flow handler (Rx/Tx DMA) */
5818c2ecf20Sopenharmony_ci		iwl_write32(trans, CSR_INT, 0xffffffff);
5828c2ecf20Sopenharmony_ci		iwl_write32(trans, CSR_FH_INT_STATUS, 0xffffffff);
5838c2ecf20Sopenharmony_ci	} else {
5848c2ecf20Sopenharmony_ci		/* disable all the interrupt we might use */
5858c2ecf20Sopenharmony_ci		iwl_write32(trans, CSR_MSIX_FH_INT_MASK_AD,
5868c2ecf20Sopenharmony_ci			    trans_pcie->fh_init_mask);
5878c2ecf20Sopenharmony_ci		iwl_write32(trans, CSR_MSIX_HW_INT_MASK_AD,
5888c2ecf20Sopenharmony_ci			    trans_pcie->hw_init_mask);
5898c2ecf20Sopenharmony_ci	}
5908c2ecf20Sopenharmony_ci	IWL_DEBUG_ISR(trans, "Disabled interrupts\n");
5918c2ecf20Sopenharmony_ci}
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_ci#define IWL_NUM_OF_COMPLETION_RINGS	31
5948c2ecf20Sopenharmony_ci#define IWL_NUM_OF_TRANSFER_RINGS	527
5958c2ecf20Sopenharmony_ci
5968c2ecf20Sopenharmony_cistatic inline int iwl_pcie_get_num_sections(const struct fw_img *fw,
5978c2ecf20Sopenharmony_ci					    int start)
5988c2ecf20Sopenharmony_ci{
5998c2ecf20Sopenharmony_ci	int i = 0;
6008c2ecf20Sopenharmony_ci
6018c2ecf20Sopenharmony_ci	while (start < fw->num_sec &&
6028c2ecf20Sopenharmony_ci	       fw->sec[start].offset != CPU1_CPU2_SEPARATOR_SECTION &&
6038c2ecf20Sopenharmony_ci	       fw->sec[start].offset != PAGING_SEPARATOR_SECTION) {
6048c2ecf20Sopenharmony_ci		start++;
6058c2ecf20Sopenharmony_ci		i++;
6068c2ecf20Sopenharmony_ci	}
6078c2ecf20Sopenharmony_ci
6088c2ecf20Sopenharmony_ci	return i;
6098c2ecf20Sopenharmony_ci}
6108c2ecf20Sopenharmony_ci
6118c2ecf20Sopenharmony_cistatic inline void iwl_pcie_ctxt_info_free_fw_img(struct iwl_trans *trans)
6128c2ecf20Sopenharmony_ci{
6138c2ecf20Sopenharmony_ci	struct iwl_self_init_dram *dram = &trans->init_dram;
6148c2ecf20Sopenharmony_ci	int i;
6158c2ecf20Sopenharmony_ci
6168c2ecf20Sopenharmony_ci	if (!dram->fw) {
6178c2ecf20Sopenharmony_ci		WARN_ON(dram->fw_cnt);
6188c2ecf20Sopenharmony_ci		return;
6198c2ecf20Sopenharmony_ci	}
6208c2ecf20Sopenharmony_ci
6218c2ecf20Sopenharmony_ci	for (i = 0; i < dram->fw_cnt; i++)
6228c2ecf20Sopenharmony_ci		dma_free_coherent(trans->dev, dram->fw[i].size,
6238c2ecf20Sopenharmony_ci				  dram->fw[i].block, dram->fw[i].physical);
6248c2ecf20Sopenharmony_ci
6258c2ecf20Sopenharmony_ci	kfree(dram->fw);
6268c2ecf20Sopenharmony_ci	dram->fw_cnt = 0;
6278c2ecf20Sopenharmony_ci	dram->fw = NULL;
6288c2ecf20Sopenharmony_ci}
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_cistatic inline void iwl_disable_interrupts(struct iwl_trans *trans)
6318c2ecf20Sopenharmony_ci{
6328c2ecf20Sopenharmony_ci	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_ci	spin_lock(&trans_pcie->irq_lock);
6358c2ecf20Sopenharmony_ci	_iwl_disable_interrupts(trans);
6368c2ecf20Sopenharmony_ci	spin_unlock(&trans_pcie->irq_lock);
6378c2ecf20Sopenharmony_ci}
6388c2ecf20Sopenharmony_ci
6398c2ecf20Sopenharmony_cistatic inline void _iwl_enable_interrupts(struct iwl_trans *trans)
6408c2ecf20Sopenharmony_ci{
6418c2ecf20Sopenharmony_ci	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
6428c2ecf20Sopenharmony_ci
6438c2ecf20Sopenharmony_ci	IWL_DEBUG_ISR(trans, "Enabling interrupts\n");
6448c2ecf20Sopenharmony_ci	set_bit(STATUS_INT_ENABLED, &trans->status);
6458c2ecf20Sopenharmony_ci	if (!trans_pcie->msix_enabled) {
6468c2ecf20Sopenharmony_ci		trans_pcie->inta_mask = CSR_INI_SET_MASK;
6478c2ecf20Sopenharmony_ci		iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask);
6488c2ecf20Sopenharmony_ci	} else {
6498c2ecf20Sopenharmony_ci		/*
6508c2ecf20Sopenharmony_ci		 * fh/hw_mask keeps all the unmasked causes.
6518c2ecf20Sopenharmony_ci		 * Unlike msi, in msix cause is enabled when it is unset.
6528c2ecf20Sopenharmony_ci		 */
6538c2ecf20Sopenharmony_ci		trans_pcie->hw_mask = trans_pcie->hw_init_mask;
6548c2ecf20Sopenharmony_ci		trans_pcie->fh_mask = trans_pcie->fh_init_mask;
6558c2ecf20Sopenharmony_ci		iwl_write32(trans, CSR_MSIX_FH_INT_MASK_AD,
6568c2ecf20Sopenharmony_ci			    ~trans_pcie->fh_mask);
6578c2ecf20Sopenharmony_ci		iwl_write32(trans, CSR_MSIX_HW_INT_MASK_AD,
6588c2ecf20Sopenharmony_ci			    ~trans_pcie->hw_mask);
6598c2ecf20Sopenharmony_ci	}
6608c2ecf20Sopenharmony_ci}
6618c2ecf20Sopenharmony_ci
6628c2ecf20Sopenharmony_cistatic inline void iwl_enable_interrupts(struct iwl_trans *trans)
6638c2ecf20Sopenharmony_ci{
6648c2ecf20Sopenharmony_ci	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_ci	spin_lock(&trans_pcie->irq_lock);
6678c2ecf20Sopenharmony_ci	_iwl_enable_interrupts(trans);
6688c2ecf20Sopenharmony_ci	spin_unlock(&trans_pcie->irq_lock);
6698c2ecf20Sopenharmony_ci}
6708c2ecf20Sopenharmony_cistatic inline void iwl_enable_hw_int_msk_msix(struct iwl_trans *trans, u32 msk)
6718c2ecf20Sopenharmony_ci{
6728c2ecf20Sopenharmony_ci	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
6738c2ecf20Sopenharmony_ci
6748c2ecf20Sopenharmony_ci	iwl_write32(trans, CSR_MSIX_HW_INT_MASK_AD, ~msk);
6758c2ecf20Sopenharmony_ci	trans_pcie->hw_mask = msk;
6768c2ecf20Sopenharmony_ci}
6778c2ecf20Sopenharmony_ci
6788c2ecf20Sopenharmony_cistatic inline void iwl_enable_fh_int_msk_msix(struct iwl_trans *trans, u32 msk)
6798c2ecf20Sopenharmony_ci{
6808c2ecf20Sopenharmony_ci	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
6818c2ecf20Sopenharmony_ci
6828c2ecf20Sopenharmony_ci	iwl_write32(trans, CSR_MSIX_FH_INT_MASK_AD, ~msk);
6838c2ecf20Sopenharmony_ci	trans_pcie->fh_mask = msk;
6848c2ecf20Sopenharmony_ci}
6858c2ecf20Sopenharmony_ci
6868c2ecf20Sopenharmony_cistatic inline void iwl_enable_fw_load_int(struct iwl_trans *trans)
6878c2ecf20Sopenharmony_ci{
6888c2ecf20Sopenharmony_ci	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
6898c2ecf20Sopenharmony_ci
6908c2ecf20Sopenharmony_ci	IWL_DEBUG_ISR(trans, "Enabling FW load interrupt\n");
6918c2ecf20Sopenharmony_ci	if (!trans_pcie->msix_enabled) {
6928c2ecf20Sopenharmony_ci		trans_pcie->inta_mask = CSR_INT_BIT_FH_TX;
6938c2ecf20Sopenharmony_ci		iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask);
6948c2ecf20Sopenharmony_ci	} else {
6958c2ecf20Sopenharmony_ci		iwl_write32(trans, CSR_MSIX_HW_INT_MASK_AD,
6968c2ecf20Sopenharmony_ci			    trans_pcie->hw_init_mask);
6978c2ecf20Sopenharmony_ci		iwl_enable_fh_int_msk_msix(trans,
6988c2ecf20Sopenharmony_ci					   MSIX_FH_INT_CAUSES_D2S_CH0_NUM);
6998c2ecf20Sopenharmony_ci	}
7008c2ecf20Sopenharmony_ci}
7018c2ecf20Sopenharmony_ci
7028c2ecf20Sopenharmony_cistatic inline void iwl_enable_fw_load_int_ctx_info(struct iwl_trans *trans)
7038c2ecf20Sopenharmony_ci{
7048c2ecf20Sopenharmony_ci	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
7058c2ecf20Sopenharmony_ci
7068c2ecf20Sopenharmony_ci	IWL_DEBUG_ISR(trans, "Enabling ALIVE interrupt only\n");
7078c2ecf20Sopenharmony_ci
7088c2ecf20Sopenharmony_ci	if (!trans_pcie->msix_enabled) {
7098c2ecf20Sopenharmony_ci		/*
7108c2ecf20Sopenharmony_ci		 * When we'll receive the ALIVE interrupt, the ISR will call
7118c2ecf20Sopenharmony_ci		 * iwl_enable_fw_load_int_ctx_info again to set the ALIVE
7128c2ecf20Sopenharmony_ci		 * interrupt (which is not really needed anymore) but also the
7138c2ecf20Sopenharmony_ci		 * RX interrupt which will allow us to receive the ALIVE
7148c2ecf20Sopenharmony_ci		 * notification (which is Rx) and continue the flow.
7158c2ecf20Sopenharmony_ci		 */
7168c2ecf20Sopenharmony_ci		trans_pcie->inta_mask =  CSR_INT_BIT_ALIVE | CSR_INT_BIT_FH_RX;
7178c2ecf20Sopenharmony_ci		iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask);
7188c2ecf20Sopenharmony_ci	} else {
7198c2ecf20Sopenharmony_ci		iwl_enable_hw_int_msk_msix(trans,
7208c2ecf20Sopenharmony_ci					   MSIX_HW_INT_CAUSES_REG_ALIVE);
7218c2ecf20Sopenharmony_ci		/*
7228c2ecf20Sopenharmony_ci		 * Leave all the FH causes enabled to get the ALIVE
7238c2ecf20Sopenharmony_ci		 * notification.
7248c2ecf20Sopenharmony_ci		 */
7258c2ecf20Sopenharmony_ci		iwl_enable_fh_int_msk_msix(trans, trans_pcie->fh_init_mask);
7268c2ecf20Sopenharmony_ci	}
7278c2ecf20Sopenharmony_ci}
7288c2ecf20Sopenharmony_ci
7298c2ecf20Sopenharmony_cistatic inline const char *queue_name(struct device *dev,
7308c2ecf20Sopenharmony_ci				     struct iwl_trans_pcie *trans_p, int i)
7318c2ecf20Sopenharmony_ci{
7328c2ecf20Sopenharmony_ci	if (trans_p->shared_vec_mask) {
7338c2ecf20Sopenharmony_ci		int vec = trans_p->shared_vec_mask &
7348c2ecf20Sopenharmony_ci			  IWL_SHARED_IRQ_FIRST_RSS ? 1 : 0;
7358c2ecf20Sopenharmony_ci
7368c2ecf20Sopenharmony_ci		if (i == 0)
7378c2ecf20Sopenharmony_ci			return DRV_NAME ": shared IRQ";
7388c2ecf20Sopenharmony_ci
7398c2ecf20Sopenharmony_ci		return devm_kasprintf(dev, GFP_KERNEL,
7408c2ecf20Sopenharmony_ci				      DRV_NAME ": queue %d", i + vec);
7418c2ecf20Sopenharmony_ci	}
7428c2ecf20Sopenharmony_ci	if (i == 0)
7438c2ecf20Sopenharmony_ci		return DRV_NAME ": default queue";
7448c2ecf20Sopenharmony_ci
7458c2ecf20Sopenharmony_ci	if (i == trans_p->alloc_vecs - 1)
7468c2ecf20Sopenharmony_ci		return DRV_NAME ": exception";
7478c2ecf20Sopenharmony_ci
7488c2ecf20Sopenharmony_ci	return devm_kasprintf(dev, GFP_KERNEL,
7498c2ecf20Sopenharmony_ci			      DRV_NAME  ": queue %d", i);
7508c2ecf20Sopenharmony_ci}
7518c2ecf20Sopenharmony_ci
7528c2ecf20Sopenharmony_cistatic inline void iwl_enable_rfkill_int(struct iwl_trans *trans)
7538c2ecf20Sopenharmony_ci{
7548c2ecf20Sopenharmony_ci	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
7558c2ecf20Sopenharmony_ci
7568c2ecf20Sopenharmony_ci	IWL_DEBUG_ISR(trans, "Enabling rfkill interrupt\n");
7578c2ecf20Sopenharmony_ci	if (!trans_pcie->msix_enabled) {
7588c2ecf20Sopenharmony_ci		trans_pcie->inta_mask = CSR_INT_BIT_RF_KILL;
7598c2ecf20Sopenharmony_ci		iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask);
7608c2ecf20Sopenharmony_ci	} else {
7618c2ecf20Sopenharmony_ci		iwl_write32(trans, CSR_MSIX_FH_INT_MASK_AD,
7628c2ecf20Sopenharmony_ci			    trans_pcie->fh_init_mask);
7638c2ecf20Sopenharmony_ci		iwl_enable_hw_int_msk_msix(trans,
7648c2ecf20Sopenharmony_ci					   MSIX_HW_INT_CAUSES_REG_RF_KILL);
7658c2ecf20Sopenharmony_ci	}
7668c2ecf20Sopenharmony_ci
7678c2ecf20Sopenharmony_ci	if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_9000) {
7688c2ecf20Sopenharmony_ci		/*
7698c2ecf20Sopenharmony_ci		 * On 9000-series devices this bit isn't enabled by default, so
7708c2ecf20Sopenharmony_ci		 * when we power down the device we need set the bit to allow it
7718c2ecf20Sopenharmony_ci		 * to wake up the PCI-E bus for RF-kill interrupts.
7728c2ecf20Sopenharmony_ci		 */
7738c2ecf20Sopenharmony_ci		iwl_set_bit(trans, CSR_GP_CNTRL,
7748c2ecf20Sopenharmony_ci			    CSR_GP_CNTRL_REG_FLAG_RFKILL_WAKE_L1A_EN);
7758c2ecf20Sopenharmony_ci	}
7768c2ecf20Sopenharmony_ci}
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_civoid iwl_pcie_handle_rfkill_irq(struct iwl_trans *trans);
7798c2ecf20Sopenharmony_ci
7808c2ecf20Sopenharmony_cistatic inline bool iwl_is_rfkill_set(struct iwl_trans *trans)
7818c2ecf20Sopenharmony_ci{
7828c2ecf20Sopenharmony_ci	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
7838c2ecf20Sopenharmony_ci
7848c2ecf20Sopenharmony_ci	lockdep_assert_held(&trans_pcie->mutex);
7858c2ecf20Sopenharmony_ci
7868c2ecf20Sopenharmony_ci	if (trans_pcie->debug_rfkill == 1)
7878c2ecf20Sopenharmony_ci		return true;
7888c2ecf20Sopenharmony_ci
7898c2ecf20Sopenharmony_ci	return !(iwl_read32(trans, CSR_GP_CNTRL) &
7908c2ecf20Sopenharmony_ci		CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW);
7918c2ecf20Sopenharmony_ci}
7928c2ecf20Sopenharmony_ci
7938c2ecf20Sopenharmony_cistatic inline void __iwl_trans_pcie_set_bits_mask(struct iwl_trans *trans,
7948c2ecf20Sopenharmony_ci						  u32 reg, u32 mask, u32 value)
7958c2ecf20Sopenharmony_ci{
7968c2ecf20Sopenharmony_ci	u32 v;
7978c2ecf20Sopenharmony_ci
7988c2ecf20Sopenharmony_ci#ifdef CONFIG_IWLWIFI_DEBUG
7998c2ecf20Sopenharmony_ci	WARN_ON_ONCE(value & ~mask);
8008c2ecf20Sopenharmony_ci#endif
8018c2ecf20Sopenharmony_ci
8028c2ecf20Sopenharmony_ci	v = iwl_read32(trans, reg);
8038c2ecf20Sopenharmony_ci	v &= ~mask;
8048c2ecf20Sopenharmony_ci	v |= value;
8058c2ecf20Sopenharmony_ci	iwl_write32(trans, reg, v);
8068c2ecf20Sopenharmony_ci}
8078c2ecf20Sopenharmony_ci
8088c2ecf20Sopenharmony_cistatic inline void __iwl_trans_pcie_clear_bit(struct iwl_trans *trans,
8098c2ecf20Sopenharmony_ci					      u32 reg, u32 mask)
8108c2ecf20Sopenharmony_ci{
8118c2ecf20Sopenharmony_ci	__iwl_trans_pcie_set_bits_mask(trans, reg, mask, 0);
8128c2ecf20Sopenharmony_ci}
8138c2ecf20Sopenharmony_ci
8148c2ecf20Sopenharmony_cistatic inline void __iwl_trans_pcie_set_bit(struct iwl_trans *trans,
8158c2ecf20Sopenharmony_ci					    u32 reg, u32 mask)
8168c2ecf20Sopenharmony_ci{
8178c2ecf20Sopenharmony_ci	__iwl_trans_pcie_set_bits_mask(trans, reg, mask, mask);
8188c2ecf20Sopenharmony_ci}
8198c2ecf20Sopenharmony_ci
8208c2ecf20Sopenharmony_cistatic inline bool iwl_pcie_dbg_on(struct iwl_trans *trans)
8218c2ecf20Sopenharmony_ci{
8228c2ecf20Sopenharmony_ci	return (trans->dbg.dest_tlv || iwl_trans_dbg_ini_valid(trans));
8238c2ecf20Sopenharmony_ci}
8248c2ecf20Sopenharmony_ci
8258c2ecf20Sopenharmony_civoid iwl_trans_pcie_rf_kill(struct iwl_trans *trans, bool state);
8268c2ecf20Sopenharmony_civoid iwl_trans_pcie_dump_regs(struct iwl_trans *trans);
8278c2ecf20Sopenharmony_civoid iwl_trans_pcie_sync_nmi(struct iwl_trans *trans);
8288c2ecf20Sopenharmony_ci
8298c2ecf20Sopenharmony_ci#ifdef CONFIG_IWLWIFI_DEBUGFS
8308c2ecf20Sopenharmony_civoid iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans);
8318c2ecf20Sopenharmony_ci#else
8328c2ecf20Sopenharmony_cistatic inline void iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans) { }
8338c2ecf20Sopenharmony_ci#endif
8348c2ecf20Sopenharmony_ci
8358c2ecf20Sopenharmony_civoid iwl_pcie_rx_allocator_work(struct work_struct *data);
8368c2ecf20Sopenharmony_ci
8378c2ecf20Sopenharmony_ci/* common functions that are used by gen2 transport */
8388c2ecf20Sopenharmony_ciint iwl_pcie_gen2_apm_init(struct iwl_trans *trans);
8398c2ecf20Sopenharmony_civoid iwl_pcie_apm_config(struct iwl_trans *trans);
8408c2ecf20Sopenharmony_ciint iwl_pcie_prepare_card_hw(struct iwl_trans *trans);
8418c2ecf20Sopenharmony_civoid iwl_pcie_synchronize_irqs(struct iwl_trans *trans);
8428c2ecf20Sopenharmony_cibool iwl_pcie_check_hw_rf_kill(struct iwl_trans *trans);
8438c2ecf20Sopenharmony_civoid iwl_trans_pcie_handle_stop_rfkill(struct iwl_trans *trans,
8448c2ecf20Sopenharmony_ci				       bool was_in_rfkill);
8458c2ecf20Sopenharmony_civoid iwl_pcie_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq);
8468c2ecf20Sopenharmony_civoid iwl_pcie_apm_stop_master(struct iwl_trans *trans);
8478c2ecf20Sopenharmony_civoid iwl_pcie_conf_msix_hw(struct iwl_trans_pcie *trans_pcie);
8488c2ecf20Sopenharmony_ciint iwl_pcie_alloc_dma_ptr(struct iwl_trans *trans,
8498c2ecf20Sopenharmony_ci			   struct iwl_dma_ptr *ptr, size_t size);
8508c2ecf20Sopenharmony_civoid iwl_pcie_free_dma_ptr(struct iwl_trans *trans, struct iwl_dma_ptr *ptr);
8518c2ecf20Sopenharmony_civoid iwl_pcie_apply_destination(struct iwl_trans *trans);
8528c2ecf20Sopenharmony_ci
8538c2ecf20Sopenharmony_ci/* common functions that are used by gen3 transport */
8548c2ecf20Sopenharmony_civoid iwl_pcie_alloc_fw_monitor(struct iwl_trans *trans, u8 max_power);
8558c2ecf20Sopenharmony_ci
8568c2ecf20Sopenharmony_ci/* transport gen 2 exported functions */
8578c2ecf20Sopenharmony_ciint iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans,
8588c2ecf20Sopenharmony_ci				 const struct fw_img *fw, bool run_in_rfkill);
8598c2ecf20Sopenharmony_civoid iwl_trans_pcie_gen2_fw_alive(struct iwl_trans *trans, u32 scd_addr);
8608c2ecf20Sopenharmony_ciint iwl_trans_pcie_gen2_send_hcmd(struct iwl_trans *trans,
8618c2ecf20Sopenharmony_ci				  struct iwl_host_cmd *cmd);
8628c2ecf20Sopenharmony_civoid iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans);
8638c2ecf20Sopenharmony_civoid _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans);
8648c2ecf20Sopenharmony_civoid iwl_pcie_d3_complete_suspend(struct iwl_trans *trans,
8658c2ecf20Sopenharmony_ci				  bool test, bool reset);
8668c2ecf20Sopenharmony_ci#endif /* __iwl_trans_int_pcie_h__ */
867