Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fa1f2b61 authored by Sara Sharon's avatar Sara Sharon Committed by Luca Coelho
Browse files

iwlwifi: mvm: support change to a000 smem API



API was changed once more to support 2 LMACs.
Adapt to change while preserving current functionality.

Signed-off-by: default avatarSara Sharon <sara.sharon@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent f2758893
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -314,6 +314,8 @@
#define LMPM_SECURE_CPU1_HDR_MEM_SPACE		(0x420000)
#define LMPM_SECURE_CPU2_HDR_MEM_SPACE		(0x420400)

#define LMAC2_PRPH_OFFSET		(0x100000)

/* Rx FIFO */
#define RXF_SIZE_ADDR			(0xa00c88)
#define RXF_RD_D_SPACE			(0xa00c40)
+35 −6
Original line number Diff line number Diff line
@@ -2026,19 +2026,48 @@ struct iwl_shared_mem_cfg_v1 {
	__le32 internal_txfifo_size[TX_FIFO_INTERNAL_MAX_NUM];
} __packed; /* SHARED_MEM_ALLOC_API_S_VER_2 */

/**
 * struct iwl_shared_mem_lmac_cfg - LMAC shared memory configuration
 *
 * @txfifo_addr: start addr of TXF0 (excluding the context table 0.5KB)
 * @txfifo_size: size of TX FIFOs
 * @rxfifo1_addr: RXF1 addr
 * @rxfifo1_size: RXF1 size
 */
struct iwl_shared_mem_lmac_cfg {
	__le32 txfifo_addr;
	__le32 txfifo_size[TX_FIFO_MAX_NUM];
	__le32 rxfifo1_addr;
	__le32 rxfifo1_size;

} __packed; /* SHARED_MEM_ALLOC_LMAC_API_S_VER_1 */

/**
 * Shared memory configuration information from the FW
 *
 * @shared_mem_addr: shared memory address
 * @shared_mem_size: shared memory size
 * @sample_buff_addr: internal sample (mon/adc) buff addr
 * @sample_buff_size: internal sample buff size
 * @rxfifo2_addr: start addr of RXF2
 * @rxfifo2_size: size of RXF2
 * @page_buff_addr: used by UMAC and performance debug (page miss analysis),
 *	when paging is not supported this should be 0
 * @page_buff_size: size of %page_buff_addr
 * @lmac_num: number of LMACs (1 or 2)
 * @lmac_smem: per - LMAC smem data
 */
struct iwl_shared_mem_cfg {
	__le32 shared_mem_addr;
	__le32 shared_mem_size;
	__le32 sample_buff_addr;
	__le32 sample_buff_size;
	__le32 txfifo_addr;
	__le32 txfifo_size[TX_FIFO_MAX_NUM];
	__le32 rxfifo_size[RX_FIFO_MAX_NUM];
	__le32 rxfifo2_addr;
	__le32 rxfifo2_size;
	__le32 page_buff_addr;
	__le32 page_buff_size;
	__le32 rxfifo_addr;
	__le32 internal_txfifo_addr;
	__le32 internal_txfifo_size[TX_FIFO_INTERNAL_MAX_NUM];
	__le32 lmac_num;
	struct iwl_shared_mem_lmac_cfg lmac_smem[2];
} __packed; /* SHARED_MEM_ALLOC_API_S_VER_3 */

/**
+166 −121
Original line number Diff line number Diff line
@@ -7,7 +7,7 @@
 *
 * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
 * Copyright(c) 2015 - 2016 Intel Deutschland GmbH
 * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of version 2 of the GNU General Public License as
@@ -32,7 +32,7 @@
 *
 * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
 * Copyright(c) 2015 - 2016 Intel Deutschland GmbH
 * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
@@ -99,138 +99,169 @@ static void iwl_mvm_read_radio_reg(struct iwl_mvm *mvm,
	iwl_trans_release_nic_access(mvm->trans, &flags);
}

static void iwl_mvm_dump_fifos(struct iwl_mvm *mvm,
			       struct iwl_fw_error_dump_data **dump_data)
static void iwl_mvm_dump_rxf(struct iwl_mvm *mvm,
			     struct iwl_fw_error_dump_data **dump_data,
			     int size, u32 offset, int fifo_num)
{
	struct iwl_fw_error_dump_fifo *fifo_hdr;
	u32 *fifo_data;
	u32 fifo_len;
	unsigned long flags;
	int i, j;

	if (!iwl_trans_grab_nic_access(mvm->trans, &flags))
		return;

	/* Pull RXF data from all RXFs */
	for (i = 0; i < ARRAY_SIZE(mvm->shared_mem_cfg.rxfifo_size); i++) {
		/*
		 * Keep aside the additional offset that might be needed for
		 * next RXF
		 */
		u32 offset_diff = RXF_DIFF_FROM_PREV * i;
	int i;

	fifo_hdr = (void *)(*dump_data)->data;
	fifo_data = (void *)fifo_hdr->data;
		fifo_len = mvm->shared_mem_cfg.rxfifo_size[i];
	fifo_len = size;

	/* No need to try to read the data if the length is 0 */
	if (fifo_len == 0)
			continue;
		return;

	/* Add a TLV for the RXF */
	(*dump_data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_RXF);
	(*dump_data)->len = cpu_to_le32(fifo_len + sizeof(*fifo_hdr));

		fifo_hdr->fifo_num = cpu_to_le32(i);
	fifo_hdr->fifo_num = cpu_to_le32(fifo_num);
	fifo_hdr->available_bytes =
		cpu_to_le32(iwl_trans_read_prph(mvm->trans,
							RXF_RD_D_SPACE +
							offset_diff));
						RXF_RD_D_SPACE + offset));
	fifo_hdr->wr_ptr =
		cpu_to_le32(iwl_trans_read_prph(mvm->trans,
							RXF_RD_WR_PTR +
							offset_diff));
						RXF_RD_WR_PTR + offset));
	fifo_hdr->rd_ptr =
		cpu_to_le32(iwl_trans_read_prph(mvm->trans,
							RXF_RD_RD_PTR +
							offset_diff));
						RXF_RD_RD_PTR + offset));
	fifo_hdr->fence_ptr =
		cpu_to_le32(iwl_trans_read_prph(mvm->trans,
							RXF_RD_FENCE_PTR +
							offset_diff));
						RXF_RD_FENCE_PTR + offset));
	fifo_hdr->fence_mode =
		cpu_to_le32(iwl_trans_read_prph(mvm->trans,
							RXF_SET_FENCE_MODE +
							offset_diff));
						RXF_SET_FENCE_MODE + offset));

	/* Lock fence */
		iwl_trans_write_prph(mvm->trans,
				     RXF_SET_FENCE_MODE + offset_diff, 0x1);
	iwl_trans_write_prph(mvm->trans, RXF_SET_FENCE_MODE + offset, 0x1);
	/* Set fence pointer to the same place like WR pointer */
		iwl_trans_write_prph(mvm->trans,
				     RXF_LD_WR2FENCE + offset_diff, 0x1);
	iwl_trans_write_prph(mvm->trans, RXF_LD_WR2FENCE + offset, 0x1);
	/* Set fence offset */
	iwl_trans_write_prph(mvm->trans,
				     RXF_LD_FENCE_OFFSET_ADDR + offset_diff,
				     0x0);
			     RXF_LD_FENCE_OFFSET_ADDR + offset, 0x0);

	/* Read FIFO */
	fifo_len /= sizeof(u32); /* Size in DWORDS */
		for (j = 0; j < fifo_len; j++)
			fifo_data[j] = iwl_trans_read_prph(mvm->trans,
	for (i = 0; i < fifo_len; i++)
		fifo_data[i] = iwl_trans_read_prph(mvm->trans,
						 RXF_FIFO_RD_FENCE_INC +
							 offset_diff);
						 offset);
	*dump_data = iwl_fw_error_next_data(*dump_data);
}

	/* Pull TXF data from all TXFs */
	for (i = 0; i < ARRAY_SIZE(mvm->shared_mem_cfg.txfifo_size); i++) {
		/* Mark the number of TXF we're pulling now */
		iwl_trans_write_prph(mvm->trans, TXF_LARC_NUM, i);
static void iwl_mvm_dump_txf(struct iwl_mvm *mvm,
			     struct iwl_fw_error_dump_data **dump_data,
			     int size, u32 offset, int fifo_num)
{
	struct iwl_fw_error_dump_fifo *fifo_hdr;
	u32 *fifo_data;
	u32 fifo_len;
	int i;

	fifo_hdr = (void *)(*dump_data)->data;
	fifo_data = (void *)fifo_hdr->data;
		fifo_len = mvm->shared_mem_cfg.txfifo_size[i];
	fifo_len = size;

	/* No need to try to read the data if the length is 0 */
	if (fifo_len == 0)
			continue;
		return;

	/* Add a TLV for the FIFO */
	(*dump_data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_TXF);
	(*dump_data)->len = cpu_to_le32(fifo_len + sizeof(*fifo_hdr));

		fifo_hdr->fifo_num = cpu_to_le32(i);
	fifo_hdr->fifo_num = cpu_to_le32(fifo_num);
	fifo_hdr->available_bytes =
		cpu_to_le32(iwl_trans_read_prph(mvm->trans,
							TXF_FIFO_ITEM_CNT));
						TXF_FIFO_ITEM_CNT + offset));
	fifo_hdr->wr_ptr =
		cpu_to_le32(iwl_trans_read_prph(mvm->trans,
							TXF_WR_PTR));
						TXF_WR_PTR + offset));
	fifo_hdr->rd_ptr =
		cpu_to_le32(iwl_trans_read_prph(mvm->trans,
							TXF_RD_PTR));
						TXF_RD_PTR + offset));
	fifo_hdr->fence_ptr =
		cpu_to_le32(iwl_trans_read_prph(mvm->trans,
							TXF_FENCE_PTR));
						TXF_FENCE_PTR + offset));
	fifo_hdr->fence_mode =
		cpu_to_le32(iwl_trans_read_prph(mvm->trans,
							TXF_LOCK_FENCE));
						TXF_LOCK_FENCE + offset));

	/* Set the TXF_READ_MODIFY_ADDR to TXF_WR_PTR */
		iwl_trans_write_prph(mvm->trans, TXF_READ_MODIFY_ADDR,
				     TXF_WR_PTR);
	iwl_trans_write_prph(mvm->trans, TXF_READ_MODIFY_ADDR + offset,
			     TXF_WR_PTR + offset);

	/* Dummy-read to advance the read pointer to the head */
		iwl_trans_read_prph(mvm->trans, TXF_READ_MODIFY_DATA);
	iwl_trans_read_prph(mvm->trans, TXF_READ_MODIFY_DATA + offset);

	/* Read FIFO */
	fifo_len /= sizeof(u32); /* Size in DWORDS */
		for (j = 0; j < fifo_len; j++)
			fifo_data[j] = iwl_trans_read_prph(mvm->trans,
							  TXF_READ_MODIFY_DATA);
	for (i = 0; i < fifo_len; i++)
		fifo_data[i] = iwl_trans_read_prph(mvm->trans,
						  TXF_READ_MODIFY_DATA +
						  offset);
	*dump_data = iwl_fw_error_next_data(*dump_data);
}

static void iwl_mvm_dump_fifos(struct iwl_mvm *mvm,
			       struct iwl_fw_error_dump_data **dump_data)
{
	struct iwl_fw_error_dump_fifo *fifo_hdr;
	struct iwl_mvm_shared_mem_cfg *cfg = &mvm->smem_cfg;
	u32 *fifo_data;
	u32 fifo_len;
	unsigned long flags;
	int i, j;

	if (!iwl_trans_grab_nic_access(mvm->trans, &flags))
		return;

	/* Pull RXF1 */
	iwl_mvm_dump_rxf(mvm, dump_data, cfg->lmac[0].rxfifo1_size, 0, 0);
	/* Pull RXF2 */
	iwl_mvm_dump_rxf(mvm, dump_data, cfg->rxfifo2_size,
			 RXF_DIFF_FROM_PREV, 1);
	/* Pull LMAC2 RXF1 */
	if (mvm->smem_cfg.num_lmacs > 1)
		iwl_mvm_dump_rxf(mvm, dump_data, cfg->lmac[1].rxfifo1_size,
				 LMAC2_PRPH_OFFSET, 2);

	/* Pull TXF data from LMAC1 */
	for (i = 0; i < mvm->smem_cfg.num_txfifo_entries; i++) {
		/* Mark the number of TXF we're pulling now */
		iwl_trans_write_prph(mvm->trans, TXF_LARC_NUM, i);
		iwl_mvm_dump_txf(mvm, dump_data, cfg->lmac[0].txfifo_size[i],
				 0, i);
	}

	/* Pull TXF data from LMAC2 */
	if (mvm->smem_cfg.num_lmacs > 1) {
		for (i = 0; i < mvm->smem_cfg.num_txfifo_entries; i++) {
			/* Mark the number of TXF we're pulling now */
			iwl_trans_write_prph(mvm->trans,
					     TXF_LARC_NUM + LMAC2_PRPH_OFFSET,
					     i);
			iwl_mvm_dump_txf(mvm, dump_data,
					 cfg->lmac[1].txfifo_size[i],
					 LMAC2_PRPH_OFFSET,
					 i + cfg->num_txfifo_entries);
		}
	}

	if (fw_has_capa(&mvm->fw->ucode_capa,
			IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG)) {
		/* Pull UMAC internal TXF data from all TXFs */
		for (i = 0;
		     i < ARRAY_SIZE(mvm->shared_mem_cfg.internal_txfifo_size);
		     i < ARRAY_SIZE(mvm->smem_cfg.internal_txfifo_size);
		     i++) {
			fifo_hdr = (void *)(*dump_data)->data;
			fifo_data = (void *)fifo_hdr->data;
			fifo_len = mvm->shared_mem_cfg.internal_txfifo_size[i];
			fifo_len = mvm->smem_cfg.internal_txfifo_size[i];

			/* No need to try to read the data if the length is 0 */
			if (fifo_len == 0)
@@ -246,7 +277,7 @@ static void iwl_mvm_dump_fifos(struct iwl_mvm *mvm,

			/* Mark the number of TXF we're pulling now */
			iwl_trans_write_prph(mvm->trans, TXF_CPU2_NUM, i +
				ARRAY_SIZE(mvm->shared_mem_cfg.txfifo_size));
				mvm->smem_cfg.num_txfifo_entries);

			fifo_hdr->available_bytes =
				cpu_to_le32(iwl_trans_read_prph(mvm->trans,
@@ -553,30 +584,44 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)

	/* reading RXF/TXF sizes */
	if (test_bit(STATUS_FW_ERROR, &mvm->trans->status)) {
		struct iwl_mvm_shared_mem_cfg *mem_cfg = &mvm->shared_mem_cfg;
		struct iwl_mvm_shared_mem_cfg *mem_cfg = &mvm->smem_cfg;

		fifo_data_len = 0;

		/* Count RXF size */
		for (i = 0; i < ARRAY_SIZE(mem_cfg->rxfifo_size); i++) {
			if (!mem_cfg->rxfifo_size[i])
		/* Count RXF2 size */
		if (mem_cfg->rxfifo2_size) {
			/* Add header info */
			fifo_data_len += mem_cfg->rxfifo2_size +
					 sizeof(*dump_data) +
					 sizeof(struct iwl_fw_error_dump_fifo);
		}

		/* Count RXF1 sizes */
		for (i = 0; i < mem_cfg->num_lmacs; i++) {
			if (!mem_cfg->lmac[i].rxfifo1_size)
				continue;

			/* Add header info */
			fifo_data_len += mem_cfg->rxfifo_size[i] +
			fifo_data_len += mem_cfg->lmac[i].rxfifo1_size +
					 sizeof(*dump_data) +
					 sizeof(struct iwl_fw_error_dump_fifo);
		}

		for (i = 0; i < mem_cfg->num_txfifo_entries; i++) {
			if (!mem_cfg->txfifo_size[i])
		/* Count TXF sizes */
		for (i = 0; i < mem_cfg->num_lmacs; i++) {
			int j;

			for (j = 0; j < mem_cfg->num_txfifo_entries; j++) {
				if (!mem_cfg->lmac[i].txfifo_size[j])
					continue;

				/* Add header info */
			fifo_data_len += mem_cfg->txfifo_size[i] +
				fifo_data_len +=
					mem_cfg->lmac[i].txfifo_size[j] +
					sizeof(*dump_data) +
					sizeof(struct iwl_fw_error_dump_fifo);
			}
		}

		if (fw_has_capa(&mvm->fw->ucode_capa,
				IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG)) {
+29 −24
Original line number Diff line number Diff line
@@ -897,24 +897,27 @@ static void iwl_mvm_parse_shared_mem_a000(struct iwl_mvm *mvm,
					  struct iwl_rx_packet *pkt)
{
	struct iwl_shared_mem_cfg *mem_cfg = (void *)pkt->data;
	int i;
	int i, lmac;
	int lmac_num = le32_to_cpu(mem_cfg->lmac_num);

	mvm->shared_mem_cfg.num_txfifo_entries =
		ARRAY_SIZE(mvm->shared_mem_cfg.txfifo_size);
	for (i = 0; i < ARRAY_SIZE(mem_cfg->txfifo_size); i++)
		mvm->shared_mem_cfg.txfifo_size[i] =
			le32_to_cpu(mem_cfg->txfifo_size[i]);
	for (i = 0; i < ARRAY_SIZE(mvm->shared_mem_cfg.rxfifo_size); i++)
		mvm->shared_mem_cfg.rxfifo_size[i] =
			le32_to_cpu(mem_cfg->rxfifo_size[i]);
	if (WARN_ON(lmac_num > ARRAY_SIZE(mem_cfg->lmac_smem)))
		return;

	BUILD_BUG_ON(sizeof(mvm->shared_mem_cfg.internal_txfifo_size) !=
		     sizeof(mem_cfg->internal_txfifo_size));
	mvm->smem_cfg.num_lmacs = lmac_num;
	mvm->smem_cfg.num_txfifo_entries =
		ARRAY_SIZE(mem_cfg->lmac_smem[0].txfifo_size);
	mvm->smem_cfg.rxfifo2_size = le32_to_cpu(mem_cfg->rxfifo2_size);

	for (i = 0; i < ARRAY_SIZE(mvm->shared_mem_cfg.internal_txfifo_size);
	     i++)
		mvm->shared_mem_cfg.internal_txfifo_size[i] =
			le32_to_cpu(mem_cfg->internal_txfifo_size[i]);
	for (lmac = 0; lmac < lmac_num; lmac++) {
		struct iwl_shared_mem_lmac_cfg *lmac_cfg =
			&mem_cfg->lmac_smem[lmac];

		for (i = 0; i < ARRAY_SIZE(lmac_cfg->txfifo_size); i++)
			mvm->smem_cfg.lmac[lmac].txfifo_size[i] =
				le32_to_cpu(lmac_cfg->txfifo_size[i]);
		mvm->smem_cfg.lmac[lmac].rxfifo1_size =
			le32_to_cpu(lmac_cfg->rxfifo1_size);
	}
}

static void iwl_mvm_parse_shared_mem(struct iwl_mvm *mvm,
@@ -923,25 +926,27 @@ static void iwl_mvm_parse_shared_mem(struct iwl_mvm *mvm,
	struct iwl_shared_mem_cfg_v1 *mem_cfg = (void *)pkt->data;
	int i;

	mvm->shared_mem_cfg.num_txfifo_entries =
		ARRAY_SIZE(mvm->shared_mem_cfg.txfifo_size);
	mvm->smem_cfg.num_lmacs = 1;

	mvm->smem_cfg.num_txfifo_entries = ARRAY_SIZE(mem_cfg->txfifo_size);
	for (i = 0; i < ARRAY_SIZE(mem_cfg->txfifo_size); i++)
		mvm->shared_mem_cfg.txfifo_size[i] =
		mvm->smem_cfg.lmac[0].txfifo_size[i] =
			le32_to_cpu(mem_cfg->txfifo_size[i]);
	for (i = 0; i < ARRAY_SIZE(mvm->shared_mem_cfg.rxfifo_size); i++)
		mvm->shared_mem_cfg.rxfifo_size[i] =
			le32_to_cpu(mem_cfg->rxfifo_size[i]);

	mvm->smem_cfg.lmac[0].rxfifo1_size =
		le32_to_cpu(mem_cfg->rxfifo_size[0]);
	mvm->smem_cfg.rxfifo2_size = le32_to_cpu(mem_cfg->rxfifo_size[1]);

	/* new API has more data, from rxfifo_addr field and on */
	if (fw_has_capa(&mvm->fw->ucode_capa,
			IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG)) {
		BUILD_BUG_ON(sizeof(mvm->shared_mem_cfg.internal_txfifo_size) !=
		BUILD_BUG_ON(sizeof(mvm->smem_cfg.internal_txfifo_size) !=
			     sizeof(mem_cfg->internal_txfifo_size));

		for (i = 0;
		     i < ARRAY_SIZE(mvm->shared_mem_cfg.internal_txfifo_size);
		     i < ARRAY_SIZE(mvm->smem_cfg.internal_txfifo_size);
		     i++)
			mvm->shared_mem_cfg.internal_txfifo_size[i] =
			mvm->smem_cfg.internal_txfifo_size[i] =
				le32_to_cpu(mem_cfg->internal_txfifo_size[i]);
	}
}
+8 −3
Original line number Diff line number Diff line
@@ -604,10 +604,15 @@ enum iwl_mvm_tdls_cs_state {
	IWL_MVM_TDLS_SW_ACTIVE,
};

#define MAX_NUM_LMAC 2
struct iwl_mvm_shared_mem_cfg {
	int num_lmacs;
	int num_txfifo_entries;
	struct {
		u32 txfifo_size[TX_FIFO_MAX_NUM];
	u32 rxfifo_size[RX_FIFO_MAX_NUM];
		u32 rxfifo1_size;
	} lmac[MAX_NUM_LMAC];
	u32 rxfifo2_size;
	u32 internal_txfifo_addr;
	u32 internal_txfifo_size[TX_FIFO_INTERNAL_MAX_NUM];
};
@@ -1034,7 +1039,7 @@ struct iwl_mvm {
		} peer;
	} tdls_cs;

	struct iwl_mvm_shared_mem_cfg shared_mem_cfg;
	struct iwl_mvm_shared_mem_cfg smem_cfg;

	u32 ciphers[IWL_MVM_NUM_CIPHERS];
	struct ieee80211_cipher_scheme cs[IWL_UCODE_MAX_CS];
Loading