1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 /* 3 * Copyright (C) 2012-2014, 2018-2020 Intel Corporation 4 * Copyright (C) 2013-2015 Intel Mobile Communications GmbH 5 * Copyright (C) 2016-2017 Intel Deutschland GmbH 6 */ 7 #include "iwl-drv.h" 8 #include "runtime.h" 9 #include "fw/api/commands.h" 10 11 static void iwl_parse_shared_mem_22000(struct iwl_fw_runtime *fwrt, 12 struct iwl_rx_packet *pkt) 13 { 14 struct iwl_shared_mem_cfg *mem_cfg = (void *)pkt->data; 15 int i, lmac; 16 int lmac_num = le32_to_cpu(mem_cfg->lmac_num); 17 u8 api_ver = iwl_fw_lookup_notif_ver(fwrt->fw, SYSTEM_GROUP, 18 SHARED_MEM_CFG_CMD, 0); 19 20 if (WARN_ON(lmac_num > ARRAY_SIZE(mem_cfg->lmac_smem))) 21 return; 22 23 fwrt->smem_cfg.num_lmacs = lmac_num; 24 fwrt->smem_cfg.num_txfifo_entries = 25 ARRAY_SIZE(mem_cfg->lmac_smem[0].txfifo_size); 26 fwrt->smem_cfg.rxfifo2_size = le32_to_cpu(mem_cfg->rxfifo2_size); 27 28 if (api_ver >= 4 && 29 !WARN_ON_ONCE(iwl_rx_packet_payload_len(pkt) < sizeof(*mem_cfg))) { 30 fwrt->smem_cfg.rxfifo2_control_size = 31 le32_to_cpu(mem_cfg->rxfifo2_control_size); 32 } 33 34 for (lmac = 0; lmac < lmac_num; lmac++) { 35 struct iwl_shared_mem_lmac_cfg *lmac_cfg = 36 &mem_cfg->lmac_smem[lmac]; 37 38 for (i = 0; i < ARRAY_SIZE(lmac_cfg->txfifo_size); i++) 39 fwrt->smem_cfg.lmac[lmac].txfifo_size[i] = 40 le32_to_cpu(lmac_cfg->txfifo_size[i]); 41 fwrt->smem_cfg.lmac[lmac].rxfifo1_size = 42 le32_to_cpu(lmac_cfg->rxfifo1_size); 43 } 44 } 45 46 static void iwl_parse_shared_mem(struct iwl_fw_runtime *fwrt, 47 struct iwl_rx_packet *pkt) 48 { 49 struct iwl_shared_mem_cfg_v2 *mem_cfg = (void *)pkt->data; 50 int i; 51 52 fwrt->smem_cfg.num_lmacs = 1; 53 54 fwrt->smem_cfg.num_txfifo_entries = ARRAY_SIZE(mem_cfg->txfifo_size); 55 for (i = 0; i < ARRAY_SIZE(mem_cfg->txfifo_size); i++) 56 fwrt->smem_cfg.lmac[0].txfifo_size[i] = 57 le32_to_cpu(mem_cfg->txfifo_size[i]); 58 59 fwrt->smem_cfg.lmac[0].rxfifo1_size = 60 le32_to_cpu(mem_cfg->rxfifo_size[0]); 61 fwrt->smem_cfg.rxfifo2_size = le32_to_cpu(mem_cfg->rxfifo_size[1]); 62 63 /* new API has more data, from rxfifo_addr field and on */ 64 if (fw_has_capa(&fwrt->fw->ucode_capa, 65 IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG)) { 66 BUILD_BUG_ON(sizeof(fwrt->smem_cfg.internal_txfifo_size) != 67 sizeof(mem_cfg->internal_txfifo_size)); 68 69 fwrt->smem_cfg.internal_txfifo_addr = 70 le32_to_cpu(mem_cfg->internal_txfifo_addr); 71 72 for (i = 0; 73 i < ARRAY_SIZE(fwrt->smem_cfg.internal_txfifo_size); 74 i++) 75 fwrt->smem_cfg.internal_txfifo_size[i] = 76 le32_to_cpu(mem_cfg->internal_txfifo_size[i]); 77 } 78 } 79 80 void iwl_get_shared_mem_conf(struct iwl_fw_runtime *fwrt) 81 { 82 struct iwl_host_cmd cmd = { 83 .flags = CMD_WANT_SKB, 84 .data = { NULL, }, 85 .len = { 0, }, 86 }; 87 struct iwl_rx_packet *pkt; 88 int ret; 89 90 if (fw_has_capa(&fwrt->fw->ucode_capa, 91 IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG)) 92 cmd.id = iwl_cmd_id(SHARED_MEM_CFG_CMD, SYSTEM_GROUP, 0); 93 else 94 cmd.id = SHARED_MEM_CFG; 95 96 ret = iwl_trans_send_cmd(fwrt->trans, &cmd); 97 98 if (ret) { 99 WARN(ret != -ERFKILL, 100 "Could not send the SMEM command: %d\n", ret); 101 return; 102 } 103 104 pkt = cmd.resp_pkt; 105 if (fwrt->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000) 106 iwl_parse_shared_mem_22000(fwrt, pkt); 107 else 108 iwl_parse_shared_mem(fwrt, pkt); 109 110 IWL_DEBUG_INFO(fwrt, "SHARED MEM CFG: got memory offsets/sizes\n"); 111 112 iwl_free_resp(&cmd); 113 } 114 IWL_EXPORT_SYMBOL(iwl_get_shared_mem_conf); 115