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