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

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

iwlwifi: enlarge number of ucode sections



The maximum number of firmware sections is now 32 instead of 16 for
a000 devices. Set the appropriate define.  Avoid out of bounds access
in case there are more sections than the maximum set by driver.

Make the driver extensible to FW size changes by allocating the
section memory dynamically.

Signed-off-by: default avatarSara Sharon <sara.sharon@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent 850fe9af
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -163,7 +163,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
				       REGULATORY_DISABLE_BEACON_HINTS;

#ifdef CONFIG_PM_SLEEP
	if (priv->fw->img[IWL_UCODE_WOWLAN].sec[0].len &&
	if (priv->fw->img[IWL_UCODE_WOWLAN].num_sec &&
	    priv->trans->ops->d3_suspend &&
	    priv->trans->ops->d3_resume &&
	    device_can_wakeup(priv->trans->dev)) {
+1 −1
Original line number Diff line number Diff line
@@ -407,7 +407,7 @@ int iwl_run_init_ucode(struct iwl_priv *priv)
	lockdep_assert_held(&priv->mutex);

	/* No init ucode required? Curious, but maybe ok */
	if (!priv->fw->img[IWL_UCODE_INIT].sec[0].len)
	if (!priv->fw->img[IWL_UCODE_INIT].num_sec)
		return 0;

	iwl_init_notification_wait(&priv->notif_wait, &calib_wait,
+24 −7
Original line number Diff line number Diff line
@@ -166,8 +166,9 @@ static void iwl_free_fw_desc(struct iwl_drv *drv, struct fw_desc *desc)
static void iwl_free_fw_img(struct iwl_drv *drv, struct fw_img *img)
{
	int i;
	for (i = 0; i < IWL_UCODE_SECTION_MAX; i++)
	for (i = 0; i < img->num_sec; i++)
		iwl_free_fw_desc(drv, &img->sec[i]);
	kfree(img->sec);
}

static void iwl_dealloc_ucode(struct iwl_drv *drv)
@@ -240,7 +241,7 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first)
}

struct fw_img_parsing {
	struct fw_sec sec[IWL_UCODE_SECTION_MAX];
	struct fw_sec *sec;
	int sec_counter;
};

@@ -383,6 +384,7 @@ static int iwl_store_ucode_sec(struct iwl_firmware_pieces *pieces,
	struct fw_img_parsing *img;
	struct fw_sec *sec;
	struct fw_sec_parsing *sec_parse;
	size_t alloc_size;

	if (WARN_ON(!pieces || !data || type >= IWL_UCODE_TYPE_MAX))
		return -1;
@@ -390,6 +392,13 @@ static int iwl_store_ucode_sec(struct iwl_firmware_pieces *pieces,
	sec_parse = (struct fw_sec_parsing *)data;

	img = &pieces->img[type];

	alloc_size = sizeof(*img->sec) * (img->sec_counter + 1);
	sec = krealloc(img->sec, alloc_size, GFP_KERNEL);
	if (!sec)
		return -ENOMEM;
	img->sec = sec;

	sec = &img->sec[img->sec_counter];

	sec->offset = le32_to_cpu(sec_parse->offset);
@@ -1089,12 +1098,18 @@ static int iwl_alloc_ucode(struct iwl_drv *drv,
			   enum iwl_ucode_type type)
{
	int i;
	for (i = 0;
	     i < IWL_UCODE_SECTION_MAX && get_sec_size(pieces, type, i);
	     i++)
		if (iwl_alloc_fw_desc(drv, &(drv->fw.img[type].sec[i]),
				      get_sec(pieces, type, i)))
	struct fw_desc *sec;

	sec = kcalloc(pieces->img[type].sec_counter, sizeof(*sec), GFP_KERNEL);
	if (!sec)
		return -ENOMEM;
	drv->fw.img[type].sec = sec;
	drv->fw.img[type].num_sec = pieces->img[type].sec_counter;

	for (i = 0; i < pieces->img[type].sec_counter; i++)
		if (iwl_alloc_fw_desc(drv, &sec[i], get_sec(pieces, type, i)))
			return -ENOMEM;

	return 0;
}

@@ -1457,6 +1472,8 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
	complete(&drv->request_firmware_complete);
	device_release_driver(drv->trans->dev);
 free:
	for (i = 0; i < ARRAY_SIZE(pieces->img); i++)
		kfree(pieces->img[i].sec);
	kfree(pieces->dbg_mem_tlv);
	kfree(pieces);
}
+0 −1
Original line number Diff line number Diff line
@@ -379,7 +379,6 @@ enum iwl_ucode_tlv_capa {
 * For 16.0 uCode and above, there is no differentiation between sections,
 * just an offset to the HW address.
 */
#define IWL_UCODE_SECTION_MAX 16
#define CPU1_CPU2_SEPARATOR_SECTION	0xFFFFCCCC
#define PAGING_SEPARATOR_SECTION	0xAAAABBBB

+2 −1
Original line number Diff line number Diff line
@@ -132,7 +132,8 @@ struct fw_desc {
};

struct fw_img {
	struct fw_desc sec[IWL_UCODE_SECTION_MAX];
	struct fw_desc *sec;
	int num_sec;
	bool is_dual_cpus;
	u32 paging_mem_size;
};
Loading