u32 iwl_read_targ_mem(struct iwl_bus *bus, u32 addr) { u32 value; _iwl_read_targ_mem_words(bus, addr, &value, 1); return value; }
/* * This function handles the user application commands for SRAM data dump * * It retrieves the mandatory fields IWL_TM_ATTR_SRAM_ADDR and * IWL_TM_ATTR_SRAM_SIZE to decide the memory area for SRAM data reading * * Several error will be retured, -EBUSY if the SRAM data retrieved by * previous command has not been delivered to userspace, or -ENOMSG if * the mandatory fields (IWL_TM_ATTR_SRAM_ADDR,IWL_TM_ATTR_SRAM_SIZE) * are missing, or -ENOMEM if the buffer allocation fails. * * Otherwise 0 is replied indicating the success of the SRAM reading. * * @hw: ieee80211_hw object that represents the device * @tb: gnl message fields from the user space */ static int iwl_testmode_sram(struct ieee80211_hw *hw, struct nlattr **tb) { struct iwl_priv *priv = hw->priv; u32 base, ofs, size, maxsize; if (priv->testmode_sram.sram_readed) return -EBUSY; if (!tb[IWL_TM_ATTR_SRAM_ADDR]) { IWL_DEBUG_INFO(priv, "Error finding SRAM offset address\n"); return -ENOMSG; } ofs = nla_get_u32(tb[IWL_TM_ATTR_SRAM_ADDR]); if (!tb[IWL_TM_ATTR_SRAM_SIZE]) { IWL_DEBUG_INFO(priv, "Error finding size for SRAM reading\n"); return -ENOMSG; } size = nla_get_u32(tb[IWL_TM_ATTR_SRAM_SIZE]); switch (priv->shrd->ucode_type) { case IWL_UCODE_REGULAR: maxsize = trans(priv)->ucode_rt.data.len; break; case IWL_UCODE_INIT: maxsize = trans(priv)->ucode_init.data.len; break; case IWL_UCODE_WOWLAN: maxsize = trans(priv)->ucode_wowlan.data.len; break; case IWL_UCODE_NONE: IWL_DEBUG_INFO(priv, "Error, uCode does not been loaded\n"); return -ENOSYS; default: IWL_DEBUG_INFO(priv, "Error, unsupported uCode type\n"); return -ENOSYS; } if ((ofs + size) > maxsize) { IWL_DEBUG_INFO(priv, "Invalid offset/size: out of range\n"); return -EINVAL; } priv->testmode_sram.buff_size = (size / 4) * 4; priv->testmode_sram.buff_addr = kmalloc(priv->testmode_sram.buff_size, GFP_KERNEL); if (priv->testmode_sram.buff_addr == NULL) { IWL_DEBUG_INFO(priv, "Error allocating memory\n"); return -ENOMEM; } base = 0x800000; _iwl_read_targ_mem_words(bus(priv), base + ofs, priv->testmode_sram.buff_addr, priv->testmode_sram.buff_size / 4); priv->testmode_sram.num_chunks = DIV_ROUND_UP(priv->testmode_sram.buff_size, DUMP_CHUNK_SIZE); priv->testmode_sram.sram_readed = true; return 0; }
static int iwl_testmode_indirect_read(struct iwl_priv *priv, u32 addr, u32 size) { struct iwl_trans *trans = trans(priv); unsigned long flags; int i; if (size & 0x3) return -EINVAL; priv->testmode_mem.buff_size = size; priv->testmode_mem.buff_addr = kmalloc(priv->testmode_mem.buff_size, GFP_KERNEL); if (priv->testmode_mem.buff_addr == NULL) return -ENOMEM; /* Hard-coded periphery absolute address */ if (IWL_TM_ABS_PRPH_START <= addr && addr < IWL_TM_ABS_PRPH_START + PRPH_END) { spin_lock_irqsave(&trans->reg_lock, flags); iwl_grab_nic_access(trans); iwl_write32(trans, HBUS_TARG_PRPH_RADDR, addr | (3 << 24)); for (i = 0; i < size; i += 4) *(u32 *)(priv->testmode_mem.buff_addr + i) = iwl_read32(trans, HBUS_TARG_PRPH_RDAT); iwl_release_nic_access(trans); spin_unlock_irqrestore(&trans->reg_lock, flags); } else { /* target memory (SRAM) */ _iwl_read_targ_mem_words(trans, addr, priv->testmode_mem.buff_addr, priv->testmode_mem.buff_size / 4); } priv->testmode_mem.num_chunks = DIV_ROUND_UP(priv->testmode_mem.buff_size, DUMP_CHUNK_SIZE); priv->testmode_mem.read_in_progress = true; return 0; }