linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Stephen Rothwell <sfr@canb.auug.org.au>
To: Kalle Valo <kvalo@codeaurora.org>,
	Wireless <linux-wireless@vger.kernel.org>
Cc: Linux-Next Mailing List <linux-next@vger.kernel.org>,
	Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
	Haim Dreyfuss <haim.dreyfuss@intel.com>,
	Shaul Triebitz <shaul.triebitz@intel.com>
Subject: linux-next: manual merge of the wireless-drivers-next tree with the wireless-drivers tree
Date: Thu, 26 Apr 2018 11:09:17 +1000	[thread overview]
Message-ID: <20180426110917.446204af@canb.auug.org.au> (raw)

[-- Attachment #1: Type: text/plain, Size: 11178 bytes --]

Hi all,

Today's linux-next merge of the wireless-drivers-next tree got a
conflict in:

  drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c

between commit:

  77e30e10ee28 ("iwlwifi: mvm: query regdb for wmm rule if needed")

from the wireless-drivers tree and commits:

  9c4f7d512740 ("iwlwifi: move all NVM parsing code to the common files")
  4c625c564ba2 ("iwlwifi: get rid of fw/nvm.c")

from the wireless-drivers-next tree.

I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging.  You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.

-- 
Cheers,
Stephen Rothwell

diff --cc drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
index ca0174680af9,6d33c14579d9..000000000000
--- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
@@@ -978,42 -943,302 +990,333 @@@ iwl_parse_nvm_mcc_info(struct device *d
  	}
  
  	regd->n_reg_rules = valid_rules;
 +	regd->n_wmm_rules = n_wmms;
  
 -	/* set alpha2 from FW. */
 -	regd->alpha2[0] = fw_mcc >> 8;
 -	regd->alpha2[1] = fw_mcc & 0xff;
 +	/*
 +	 * Narrow down regdom for unused regulatory rules to prevent hole
 +	 * between reg rules to wmm rules.
 +	 */
 +	regd_to_copy = sizeof(struct ieee80211_regdomain) +
 +		valid_rules * sizeof(struct ieee80211_reg_rule);
 +
 +	wmms_to_copy = sizeof(struct ieee80211_wmm_rule) * n_wmms;
 +
 +	copy_rd = kzalloc(regd_to_copy + wmms_to_copy, GFP_KERNEL);
 +	if (!copy_rd) {
 +		copy_rd = ERR_PTR(-ENOMEM);
 +		goto out;
 +	}
 +
 +	memcpy(copy_rd, regd, regd_to_copy);
 +	memcpy((u8 *)copy_rd + regd_to_copy, (u8 *)regd + size_of_regd,
 +	       wmms_to_copy);
 +
 +	d_wmm = (struct ieee80211_wmm_rule *)((u8 *)copy_rd + regd_to_copy);
 +	s_wmm = (struct ieee80211_wmm_rule *)((u8 *)regd + size_of_regd);
 +
 +	for (i = 0; i < regd->n_reg_rules; i++) {
 +		if (!regd->reg_rules[i].wmm_rule)
 +			continue;
 +
 +		copy_rd->reg_rules[i].wmm_rule = d_wmm +
 +			(regd->reg_rules[i].wmm_rule - s_wmm) /
 +			sizeof(struct ieee80211_wmm_rule);
 +	}
  
 -	return regd;
 +out:
 +	kfree(regdb_ptrs);
 +	kfree(regd);
 +	return copy_rd;
  }
  IWL_EXPORT_SYMBOL(iwl_parse_nvm_mcc_info);
+ 
+ #define IWL_MAX_NVM_SECTION_SIZE	0x1b58
+ #define IWL_MAX_EXT_NVM_SECTION_SIZE	0x1ffc
+ #define MAX_NVM_FILE_LEN	16384
+ 
+ void iwl_nvm_fixups(u32 hw_id, unsigned int section, u8 *data,
+ 		    unsigned int len)
+ {
+ #define IWL_4165_DEVICE_ID	0x5501
+ #define NVM_SKU_CAP_MIMO_DISABLE BIT(5)
+ 
+ 	if (section == NVM_SECTION_TYPE_PHY_SKU &&
+ 	    hw_id == IWL_4165_DEVICE_ID && data && len >= 5 &&
+ 	    (data[4] & NVM_SKU_CAP_MIMO_DISABLE))
+ 		/* OTP 0x52 bug work around: it's a 1x1 device */
+ 		data[3] = ANT_B | (ANT_B << 4);
+ }
+ IWL_EXPORT_SYMBOL(iwl_nvm_fixups);
+ 
+ /*
+  * Reads external NVM from a file into mvm->nvm_sections
+  *
+  * HOW TO CREATE THE NVM FILE FORMAT:
+  * ------------------------------
+  * 1. create hex file, format:
+  *      3800 -> header
+  *      0000 -> header
+  *      5a40 -> data
+  *
+  *   rev - 6 bit (word1)
+  *   len - 10 bit (word1)
+  *   id - 4 bit (word2)
+  *   rsv - 12 bit (word2)
+  *
+  * 2. flip 8bits with 8 bits per line to get the right NVM file format
+  *
+  * 3. create binary file from the hex file
+  *
+  * 4. save as "iNVM_xxx.bin" under /lib/firmware
+  */
+ int iwl_read_external_nvm(struct iwl_trans *trans,
+ 			  const char *nvm_file_name,
+ 			  struct iwl_nvm_section *nvm_sections)
+ {
+ 	int ret, section_size;
+ 	u16 section_id;
+ 	const struct firmware *fw_entry;
+ 	const struct {
+ 		__le16 word1;
+ 		__le16 word2;
+ 		u8 data[];
+ 	} *file_sec;
+ 	const u8 *eof;
+ 	u8 *temp;
+ 	int max_section_size;
+ 	const __le32 *dword_buff;
+ 
+ #define NVM_WORD1_LEN(x) (8 * (x & 0x03FF))
+ #define NVM_WORD2_ID(x) (x >> 12)
+ #define EXT_NVM_WORD2_LEN(x) (2 * (((x) & 0xFF) << 8 | (x) >> 8))
+ #define EXT_NVM_WORD1_ID(x) ((x) >> 4)
+ #define NVM_HEADER_0	(0x2A504C54)
+ #define NVM_HEADER_1	(0x4E564D2A)
+ #define NVM_HEADER_SIZE	(4 * sizeof(u32))
+ 
+ 	IWL_DEBUG_EEPROM(trans->dev, "Read from external NVM\n");
+ 
+ 	/* Maximal size depends on NVM version */
+ 	if (trans->cfg->nvm_type != IWL_NVM_EXT)
+ 		max_section_size = IWL_MAX_NVM_SECTION_SIZE;
+ 	else
+ 		max_section_size = IWL_MAX_EXT_NVM_SECTION_SIZE;
+ 
+ 	/*
+ 	 * Obtain NVM image via request_firmware. Since we already used
+ 	 * request_firmware_nowait() for the firmware binary load and only
+ 	 * get here after that we assume the NVM request can be satisfied
+ 	 * synchronously.
+ 	 */
+ 	ret = request_firmware(&fw_entry, nvm_file_name, trans->dev);
+ 	if (ret) {
+ 		IWL_ERR(trans, "ERROR: %s isn't available %d\n",
+ 			nvm_file_name, ret);
+ 		return ret;
+ 	}
+ 
+ 	IWL_INFO(trans, "Loaded NVM file %s (%zu bytes)\n",
+ 		 nvm_file_name, fw_entry->size);
+ 
+ 	if (fw_entry->size > MAX_NVM_FILE_LEN) {
+ 		IWL_ERR(trans, "NVM file too large\n");
+ 		ret = -EINVAL;
+ 		goto out;
+ 	}
+ 
+ 	eof = fw_entry->data + fw_entry->size;
+ 	dword_buff = (__le32 *)fw_entry->data;
+ 
+ 	/* some NVM file will contain a header.
+ 	 * The header is identified by 2 dwords header as follow:
+ 	 * dword[0] = 0x2A504C54
+ 	 * dword[1] = 0x4E564D2A
+ 	 *
+ 	 * This header must be skipped when providing the NVM data to the FW.
+ 	 */
+ 	if (fw_entry->size > NVM_HEADER_SIZE &&
+ 	    dword_buff[0] == cpu_to_le32(NVM_HEADER_0) &&
+ 	    dword_buff[1] == cpu_to_le32(NVM_HEADER_1)) {
+ 		file_sec = (void *)(fw_entry->data + NVM_HEADER_SIZE);
+ 		IWL_INFO(trans, "NVM Version %08X\n", le32_to_cpu(dword_buff[2]));
+ 		IWL_INFO(trans, "NVM Manufacturing date %08X\n",
+ 			 le32_to_cpu(dword_buff[3]));
+ 
+ 		/* nvm file validation, dword_buff[2] holds the file version */
+ 		if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000 &&
+ 		    CSR_HW_REV_STEP(trans->hw_rev) == SILICON_C_STEP &&
+ 		    le32_to_cpu(dword_buff[2]) < 0xE4A) {
+ 			ret = -EFAULT;
+ 			goto out;
+ 		}
+ 	} else {
+ 		file_sec = (void *)fw_entry->data;
+ 	}
+ 
+ 	while (true) {
+ 		if (file_sec->data > eof) {
+ 			IWL_ERR(trans,
+ 				"ERROR - NVM file too short for section header\n");
+ 			ret = -EINVAL;
+ 			break;
+ 		}
+ 
+ 		/* check for EOF marker */
+ 		if (!file_sec->word1 && !file_sec->word2) {
+ 			ret = 0;
+ 			break;
+ 		}
+ 
+ 		if (trans->cfg->nvm_type != IWL_NVM_EXT) {
+ 			section_size =
+ 				2 * NVM_WORD1_LEN(le16_to_cpu(file_sec->word1));
+ 			section_id = NVM_WORD2_ID(le16_to_cpu(file_sec->word2));
+ 		} else {
+ 			section_size = 2 * EXT_NVM_WORD2_LEN(
+ 						le16_to_cpu(file_sec->word2));
+ 			section_id = EXT_NVM_WORD1_ID(
+ 						le16_to_cpu(file_sec->word1));
+ 		}
+ 
+ 		if (section_size > max_section_size) {
+ 			IWL_ERR(trans, "ERROR - section too large (%d)\n",
+ 				section_size);
+ 			ret = -EINVAL;
+ 			break;
+ 		}
+ 
+ 		if (!section_size) {
+ 			IWL_ERR(trans, "ERROR - section empty\n");
+ 			ret = -EINVAL;
+ 			break;
+ 		}
+ 
+ 		if (file_sec->data + section_size > eof) {
+ 			IWL_ERR(trans,
+ 				"ERROR - NVM file too short for section (%d bytes)\n",
+ 				section_size);
+ 			ret = -EINVAL;
+ 			break;
+ 		}
+ 
+ 		if (WARN(section_id >= NVM_MAX_NUM_SECTIONS,
+ 			 "Invalid NVM section ID %d\n", section_id)) {
+ 			ret = -EINVAL;
+ 			break;
+ 		}
+ 
+ 		temp = kmemdup(file_sec->data, section_size, GFP_KERNEL);
+ 		if (!temp) {
+ 			ret = -ENOMEM;
+ 			break;
+ 		}
+ 
+ 		iwl_nvm_fixups(trans->hw_id, section_id, temp, section_size);
+ 
+ 		kfree(nvm_sections[section_id].data);
+ 		nvm_sections[section_id].data = temp;
+ 		nvm_sections[section_id].length = section_size;
+ 
+ 		/* advance to the next section */
+ 		file_sec = (void *)(file_sec->data + section_size);
+ 	}
+ out:
+ 	release_firmware(fw_entry);
+ 	return ret;
+ }
+ IWL_EXPORT_SYMBOL(iwl_read_external_nvm);
+ 
+ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans,
+ 				 const struct iwl_fw *fw)
+ {
+ 	struct iwl_nvm_get_info cmd = {};
+ 	struct iwl_nvm_get_info_rsp *rsp;
+ 	struct iwl_nvm_data *nvm;
+ 	struct iwl_host_cmd hcmd = {
+ 		.flags = CMD_WANT_SKB | CMD_SEND_IN_RFKILL,
+ 		.data = { &cmd, },
+ 		.len = { sizeof(cmd) },
+ 		.id = WIDE_ID(REGULATORY_AND_NVM_GROUP, NVM_GET_INFO)
+ 	};
+ 	int  ret;
+ 	bool lar_fw_supported = !iwlwifi_mod_params.lar_disable &&
+ 				fw_has_capa(&fw->ucode_capa,
+ 					    IWL_UCODE_TLV_CAPA_LAR_SUPPORT);
+ 	u32 mac_flags;
+ 	u32 sbands_flags = 0;
+ 
+ 	ret = iwl_trans_send_cmd(trans, &hcmd);
+ 	if (ret)
+ 		return ERR_PTR(ret);
+ 
+ 	if (WARN(iwl_rx_packet_payload_len(hcmd.resp_pkt) != sizeof(*rsp),
+ 		 "Invalid payload len in NVM response from FW %d",
+ 		 iwl_rx_packet_payload_len(hcmd.resp_pkt))) {
+ 		ret = -EINVAL;
+ 		goto out;
+ 	}
+ 
+ 	rsp = (void *)hcmd.resp_pkt->data;
+ 	if (le32_to_cpu(rsp->general.flags) & NVM_GENERAL_FLAGS_EMPTY_OTP)
+ 		IWL_INFO(trans, "OTP is empty\n");
+ 
+ 	nvm = kzalloc(sizeof(*nvm) +
+ 		      sizeof(struct ieee80211_channel) * IWL_NUM_CHANNELS,
+ 		      GFP_KERNEL);
+ 	if (!nvm) {
+ 		ret = -ENOMEM;
+ 		goto out;
+ 	}
+ 
+ 	iwl_set_hw_address_from_csr(trans, nvm);
+ 	/* TODO: if platform NVM has MAC address - override it here */
+ 
+ 	if (!is_valid_ether_addr(nvm->hw_addr)) {
+ 		IWL_ERR(trans, "no valid mac address was found\n");
+ 		ret = -EINVAL;
+ 		goto err_free;
+ 	}
+ 
+ 	IWL_INFO(trans, "base HW address: %pM\n", nvm->hw_addr);
+ 
+ 	/* Initialize general data */
+ 	nvm->nvm_version = le16_to_cpu(rsp->general.nvm_version);
+ 
+ 	/* Initialize MAC sku data */
+ 	mac_flags = le32_to_cpu(rsp->mac_sku.mac_sku_flags);
+ 	nvm->sku_cap_11ac_enable =
+ 		!!(mac_flags & NVM_MAC_SKU_FLAGS_802_11AC_ENABLED);
+ 	nvm->sku_cap_11n_enable =
+ 		!!(mac_flags & NVM_MAC_SKU_FLAGS_802_11N_ENABLED);
+ 	nvm->sku_cap_band_24ghz_enable =
+ 		!!(mac_flags & NVM_MAC_SKU_FLAGS_BAND_2_4_ENABLED);
+ 	nvm->sku_cap_band_52ghz_enable =
+ 		!!(mac_flags & NVM_MAC_SKU_FLAGS_BAND_5_2_ENABLED);
+ 	nvm->sku_cap_mimo_disabled =
+ 		!!(mac_flags & NVM_MAC_SKU_FLAGS_MIMO_DISABLED);
+ 
+ 	/* Initialize PHY sku data */
+ 	nvm->valid_tx_ant = (u8)le32_to_cpu(rsp->phy_sku.tx_chains);
+ 	nvm->valid_rx_ant = (u8)le32_to_cpu(rsp->phy_sku.rx_chains);
+ 
+ 	if (le32_to_cpu(rsp->regulatory.lar_enabled) && lar_fw_supported) {
+ 		nvm->lar_enabled = true;
+ 		sbands_flags |= IWL_NVM_SBANDS_FLAGS_LAR;
+ 	}
+ 
+ 	iwl_init_sbands(trans->dev, trans->cfg, nvm,
+ 			rsp->regulatory.channel_profile,
+ 			nvm->valid_tx_ant & fw->valid_tx_ant,
+ 			nvm->valid_rx_ant & fw->valid_rx_ant,
+ 			sbands_flags);
+ 
+ 	iwl_free_resp(&hcmd);
+ 	return nvm;
+ 
+ err_free:
+ 	kfree(nvm);
+ out:
+ 	iwl_free_resp(&hcmd);
+ 	return ERR_PTR(ret);
+ }
+ IWL_EXPORT_SYMBOL(iwl_get_nvm);

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

             reply	other threads:[~2018-04-26  1:10 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-04-26  1:09 Stephen Rothwell [this message]
2018-04-26  7:38 ` linux-next: manual merge of the wireless-drivers-next tree with the wireless-drivers tree Luciano Coelho
2018-04-26 10:33   ` Kalle Valo
2018-04-26 11:51     ` Luciano Coelho
  -- strict thread matches above, loose matches on Subject: below --
2020-03-24  0:16 Stephen Rothwell
2020-03-24  7:00 ` Kalle Valo
2020-03-24  7:29   ` Luca Coelho
2020-03-24  8:07     ` Kalle Valo
2019-10-31  0:13 Stephen Rothwell
2019-10-31  9:36 ` Kalle Valo
2019-04-30  4:08 Stephen Rothwell
2019-04-30  5:30 ` Luciano Coelho
2019-04-15  2:08 Stephen Rothwell
2019-04-18 13:49 ` Kalle Valo
2019-04-15  2:01 Stephen Rothwell
2019-04-18 13:49 ` Kalle Valo
2017-12-08  1:00 Stephen Rothwell
2017-12-08 12:30 ` Kalle Valo
2017-10-12 17:25 Mark Brown
2017-10-12 18:16 ` Luciano Coelho
2017-10-12 18:21   ` Mark Brown
2017-10-12 18:27     ` Luciano Coelho
2017-10-12 18:35       ` Mark Brown
2017-10-12 18:50         ` Luca Coelho
2017-10-12 18:59           ` Mark Brown
2017-10-12 19:02             ` Luca Coelho
2017-10-12 18:29 ` Luca Coelho
2017-10-12 19:12   ` Mark Brown
2017-10-12 17:20 Mark Brown
2017-10-12 17:14 Mark Brown

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180426110917.446204af@canb.auug.org.au \
    --to=sfr@canb.auug.org.au \
    --cc=haim.dreyfuss@intel.com \
    --cc=kvalo@codeaurora.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-next@vger.kernel.org \
    --cc=linux-wireless@vger.kernel.org \
    --cc=shaul.triebitz@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).