ret = iwl_mvm_send_cmd(mvm, &cmd); if (ret) return ret;
pkt = cmd.resp_pkt;
/* Extract NVM response */
nvm_resp = (void *)pkt->data;
ret = le16_to_cpu(nvm_resp->status);
bytes_read = le16_to_cpu(nvm_resp->length);
offset_read = le16_to_cpu(nvm_resp->offset);
resp_data = nvm_resp->data; if (ret) { if ((offset != 0) &&
(ret == READ_NVM_CHUNK_NOT_VALID_ADDRESS)) { /* * meaning of NOT_VALID_ADDRESS: * driver try to read chunk from address that is * multiple of 2K and got an error since addr is empty. * meaning of (offset != 0): driver already * read valid data from another chunk so this case * is not an error.
*/
IWL_DEBUG_EEPROM(mvm->trans->dev, "NVM access command failed on offset 0x%x since that section size is multiple 2K\n",
offset);
ret = 0;
} else {
IWL_DEBUG_EEPROM(mvm->trans->dev, "NVM access command failed with status %d (device: %s)\n",
ret, mvm->trans->info.name);
ret = -ENODATA;
} gotoexit;
}
if (offset_read != offset) {
IWL_ERR(mvm, "NVM ACCESS response with invalid offset %d\n",
offset_read);
ret = -EINVAL; gotoexit;
}
/* Write data to NVM */
memcpy(data + offset, resp_data, bytes_read);
ret = bytes_read;
ret = iwl_nvm_write_chunk(mvm, section, offset,
chunk_size, data + offset); if (ret < 0) return ret;
offset += chunk_size;
}
return 0;
}
/* * Reads an NVM section completely. * NICs prior to 7000 family doesn't have a real NVM, but just read * section 0 which is the EEPROM. Because the EEPROM reading is unlimited * by uCode, we need to manually check in this case that we don't * overflow and try to read more than the EEPROM size. * For 7000 family NICs, we supply the maximal size we can read, and * the uCode fills the response with as much data as we can, * without overflowing, so no check is needed.
*/ staticint iwl_nvm_read_section(struct iwl_mvm *mvm, u16 section,
u8 *data, u32 size_read)
{
u16 length, offset = 0; int ret;
/* Set nvm section read length */
length = IWL_NVM_DEFAULT_CHUNK_SIZE;
ret = length;
/* Read the NVM until exhausted (reading less than requested) */ while (ret == length) { /* Check no memory assumptions fail and cause an overflow */ if ((size_read + offset + length) >
mvm->trans->mac_cfg->base->eeprom_size) {
IWL_ERR(mvm, "EEPROM size is too small for NVM\n"); return -ENOBUFS;
}
/* Loads the NVM data stored in mvm->nvm_sections into the NIC */ int iwl_mvm_load_nvm_to_nic(struct iwl_mvm *mvm)
{ int i, ret = 0; struct iwl_nvm_section *sections = mvm->nvm_sections;
IWL_DEBUG_EEPROM(mvm->trans->dev, "'Write to NVM\n");
for (i = 0; i < ARRAY_SIZE(mvm->nvm_sections); i++) { if (!mvm->nvm_sections[i].data || !mvm->nvm_sections[i].length) continue;
ret = iwl_nvm_write_section(mvm, i, sections[i].data,
sections[i].length); if (ret < 0) {
IWL_ERR(mvm, "iwl_mvm_send_cmd failed: %d\n", ret); break;
}
} return ret;
}
int iwl_nvm_init(struct iwl_mvm *mvm)
{ int ret, section;
u32 size_read = 0;
u8 *nvm_buffer, *temp;
if (WARN_ON_ONCE(mvm->trans->mac_cfg->base->nvm_hw_section_num >= NVM_MAX_NUM_SECTIONS)) return -EINVAL;
/* load NVM values from nic */ /* Read From FW NVM */
IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from NVM\n");
nvm_buffer = kmalloc(mvm->trans->mac_cfg->base->eeprom_size,
GFP_KERNEL); if (!nvm_buffer) return -ENOMEM; for (section = 0; section < NVM_MAX_NUM_SECTIONS; section++) { /* we override the constness for initial read */
ret = iwl_nvm_read_section(mvm, section, nvm_buffer,
size_read); if (ret == -ENODATA) {
ret = 0; continue;
} if (ret < 0) break;
size_read += ret;
temp = kmemdup(nvm_buffer, ret, GFP_KERNEL); if (!temp) {
ret = -ENOMEM; break;
}
#ifdef CONFIG_IWLWIFI_DEBUGFS switch (section) { case NVM_SECTION_TYPE_SW:
mvm->nvm_sw_blob.data = temp;
mvm->nvm_sw_blob.size = ret; break; case NVM_SECTION_TYPE_CALIBRATION:
mvm->nvm_calib_blob.data = temp;
mvm->nvm_calib_blob.size = ret; break; case NVM_SECTION_TYPE_PRODUCTION:
mvm->nvm_prod_blob.data = temp;
mvm->nvm_prod_blob.size = ret; break; case NVM_SECTION_TYPE_PHY_SKU:
mvm->nvm_phy_sku_blob.data = temp;
mvm->nvm_phy_sku_blob.size = ret; break; case NVM_SECTION_TYPE_REGULATORY_SDP: case NVM_SECTION_TYPE_REGULATORY:
mvm->nvm_reg_blob.data = temp;
mvm->nvm_reg_blob.size = ret; break; default: if (section == mvm->trans->mac_cfg->base->nvm_hw_section_num) {
mvm->nvm_hw_blob.data = temp;
mvm->nvm_hw_blob.size = ret; break;
}
} #endif
} if (!size_read)
IWL_ERR(mvm, "OTP is blank\n");
kfree(nvm_buffer);
/* Only if PNVM selected in the mod param - load external NVM */ if (mvm->nvm_file_name) { /* read External NVM file from the mod param */
ret = iwl_read_external_nvm(mvm->trans, mvm->nvm_file_name,
mvm->nvm_sections); if (ret) return ret;
}
/* parse the relevant nvm sections */
mvm->nvm_data = iwl_parse_nvm_sections(mvm); if (!mvm->nvm_data) return -ENODATA;
IWL_DEBUG_EEPROM(mvm->trans->dev, "nvm version = %x\n",
mvm->nvm_data->nvm_version);
/* * try to replay the last set MCC to FW. If it doesn't exist, * queue an update to cfg80211 to retrieve the default alpha2 from FW.
*/
retval = iwl_mvm_init_fw_regd(mvm, true); if (retval != -ENOENT) return retval;
/* * Driver regulatory hint for initial update, this also informs the * firmware we support wifi location updates. * Disallow scans that might crash the FW while the LAR regdomain * is not set.
*/
mvm->lar_regdom_set = false;
regd = iwl_mvm_get_current_regdomain(mvm, NULL); if (IS_ERR_OR_NULL(regd)) return -EIO;
if (iwl_mvm_is_wifi_mcc_supported(mvm) &&
!iwl_bios_get_mcc(&mvm->fwrt, mcc)) {
kfree(regd);
regd = iwl_mvm_get_regdomain(mvm->hw->wiphy, mcc,
MCC_SOURCE_BIOS, NULL); if (IS_ERR_OR_NULL(regd)) return -EIO;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.