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

Commit a0987a8d authored by Reinette Chatre's avatar Reinette Chatre Committed by John W. Linville
Browse files

iwlwifi: rely on API version read from firmware



This adds the infrastructure to support older firmware APIs.
The API version number is stored as part of the filename, we first try to
load the most recent firmware and progressively try lower versions.
The API version is also read from the firmware self and stored as part
of the iwl_priv structure. Only firmware that is supported by driver will
be loaded. The version number read from firmware is compared
to supported versions in the driver not the API version used as part of
filename.

An example using this new infrastrucure:
   if (IWL_UCODE_API(priv->ucode_ver) >= 2) {
        Driver interacts with Firmware API version >= 2.
   } else {
        Driver interacts with Firmware API version 1.
   }

Signed-off-by: default avatarReinette Chatre <reinette.chatre@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent c02b3acd
Loading
Loading
Loading
Loading
+25 −1
Original line number Diff line number Diff line
@@ -71,9 +71,33 @@
#define IWL_SKU_G       0x1
#define IWL_SKU_A       0x2

/**
 * struct iwl_3945_cfg
 * @fw_name_pre: Firmware filename prefix. The api version and extension
 * 	(.ucode) will be added to filename before loading from disk. The
 * 	filename is constructed as fw_name_pre<api>.ucode.
 * @ucode_api_max: Highest version of uCode API supported by driver.
 * @ucode_api_min: Lowest version of uCode API supported by driver.
 *
 * We enable the driver to be backward compatible wrt API version. The
 * driver specifies which APIs it supports (with @ucode_api_max being the
 * highest and @ucode_api_min the lowest). Firmware will only be loaded if
 * it has a supported API version. The firmware's API version will be
 * stored in @iwl_priv, enabling the driver to make runtime changes based
 * on firmware version used.
 *
 * For example,
 * if (IWL_UCODE_API(priv->ucode_ver) >= 2) {
 * 	Driver interacts with Firmware API version >= 2.
 * } else {
 * 	Driver interacts with Firmware API version 1.
 * }
 */
struct iwl_3945_cfg {
	const char *name;
	const char *fw_name;
	const char *fw_name_pre;
	const unsigned int ucode_api_max;
	const unsigned int ucode_api_min;
	unsigned int sku;
};

+6 −2
Original line number Diff line number Diff line
@@ -2508,13 +2508,17 @@ void iwl3945_hw_cancel_deferred_work(struct iwl3945_priv *priv)

static struct iwl_3945_cfg iwl3945_bg_cfg = {
	.name = "3945BG",
	.fw_name = "iwlwifi-3945" IWL3945_UCODE_API ".ucode",
	.fw_name_pre = IWL3945_FW_PRE,
	.ucode_api_max = IWL3945_UCODE_API_MAX,
	.ucode_api_min = IWL3945_UCODE_API_MIN,
	.sku = IWL_SKU_G,
};

static struct iwl_3945_cfg iwl3945_abg_cfg = {
	.name = "3945ABG",
	.fw_name = "iwlwifi-3945" IWL3945_UCODE_API ".ucode",
	.fw_name_pre = IWL3945_FW_PRE,
	.ucode_api_max = IWL3945_UCODE_API_MAX,
	.ucode_api_min = IWL3945_UCODE_API_MIN,
	.sku = IWL_SKU_A|IWL_SKU_G,
};

+9 −5
Original line number Diff line number Diff line
@@ -50,11 +50,15 @@ extern struct pci_device_id iwl3945_hw_card_ids[];
#include "iwl-3945-debug.h"
#include "iwl-3945-led.h"

/* Change firmware file name, using "-" and incrementing number,
 *   *only* when uCode interface or architecture changes so that it
 *   is not compatible with earlier drivers.
 * This number will also appear in << 8 position of 1st dword of uCode file */
#define IWL3945_UCODE_API "-1"
/* Highest firmware API version supported */
#define IWL3945_UCODE_API_MAX 1

/* Lowest firmware API version supported */
#define IWL3945_UCODE_API_MIN 1

#define IWL3945_FW_PRE	"iwlwifi-3945-"
#define _IWL3945_MODULE_FIRMWARE(api) IWL3945_FW_PRE #api ".ucode"
#define IWL3945_MODULE_FIRMWARE(api) _IWL3945_MODULE_FIRMWARE(api)

/* Default noise level to report when noise measurement is not available.
 *   This may be because we're:
+13 −8
Original line number Diff line number Diff line
@@ -48,12 +48,15 @@
static int iwl4965_send_tx_power(struct iwl_priv *priv);
static int iwl4965_hw_get_temperature(const struct iwl_priv *priv);

/* Change firmware file name, using "-" and incrementing number,
 *   *only* when uCode interface or architecture changes so that it
 *   is not compatible with earlier drivers.
 * This number will also appear in << 8 position of 1st dword of uCode file */
#define IWL4965_UCODE_API "-2"
#define IWL4965_MODULE_FIRMWARE "iwlwifi-4965" IWL4965_UCODE_API ".ucode"
/* Highest firmware API version supported */
#define IWL4965_UCODE_API_MAX 2

/* Lowest firmware API version supported */
#define IWL4965_UCODE_API_MIN 2

#define IWL4965_FW_PRE "iwlwifi-4965-"
#define _IWL4965_MODULE_FIRMWARE(api) IWL4965_FW_PRE #api ".ucode"
#define IWL4965_MODULE_FIRMWARE(api) _IWL4965_MODULE_FIRMWARE(api)


/* module parameters */
@@ -2336,7 +2339,9 @@ static struct iwl_ops iwl4965_ops = {

struct iwl_cfg iwl4965_agn_cfg = {
	.name = "4965AGN",
	.fw_name = IWL4965_MODULE_FIRMWARE,
	.fw_name_pre = IWL4965_FW_PRE,
	.ucode_api_max = IWL4965_UCODE_API_MAX,
	.ucode_api_min = IWL4965_UCODE_API_MIN,
	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
	.eeprom_size = IWL4965_EEPROM_IMG_SIZE,
	.eeprom_ver = EEPROM_4965_EEPROM_VERSION,
@@ -2346,7 +2351,7 @@ struct iwl_cfg iwl4965_agn_cfg = {
};

/* Module firmware */
MODULE_FIRMWARE(IWL4965_MODULE_FIRMWARE);
MODULE_FIRMWARE(IWL4965_MODULE_FIRMWARE(IWL4965_UCODE_API_MAX));

module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444);
MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
+34 −12
Original line number Diff line number Diff line
@@ -44,11 +44,21 @@
#include "iwl-helpers.h"
#include "iwl-5000-hw.h"

#define IWL5000_UCODE_API  "-1"
#define IWL5150_UCODE_API  "-1"
/* Highest firmware API version supported */
#define IWL5000_UCODE_API_MAX 1
#define IWL5150_UCODE_API_MAX 1

#define IWL5000_MODULE_FIRMWARE "iwlwifi-5000" IWL5000_UCODE_API ".ucode"
#define IWL5150_MODULE_FIRMWARE "iwlwifi-5150" IWL5150_UCODE_API ".ucode"
/* Lowest firmware API version supported */
#define IWL5000_UCODE_API_MIN 1
#define IWL5150_UCODE_API_MIN 1

#define IWL5000_FW_PRE "iwlwifi-5000-"
#define _IWL5000_MODULE_FIRMWARE(api) IWL5000_FW_PRE #api ".ucode"
#define IWL5000_MODULE_FIRMWARE(api) _IWL5000_MODULE_FIRMWARE(api)

#define IWL5150_FW_PRE "iwlwifi-5150-"
#define _IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE #api ".ucode"
#define IWL5150_MODULE_FIRMWARE(api) _IWL5150_MODULE_FIRMWARE(api)

static const u16 iwl5000_default_queue_to_tx_fifo[] = {
	IWL_TX_FIFO_AC3,
@@ -1532,7 +1542,9 @@ static struct iwl_mod_params iwl50_mod_params = {

struct iwl_cfg iwl5300_agn_cfg = {
	.name = "5300AGN",
	.fw_name = IWL5000_MODULE_FIRMWARE,
	.fw_name_pre = IWL5000_FW_PRE,
	.ucode_api_max = IWL5000_UCODE_API_MAX,
	.ucode_api_min = IWL5000_UCODE_API_MIN,
	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
	.ops = &iwl5000_ops,
	.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
@@ -1543,7 +1555,9 @@ struct iwl_cfg iwl5300_agn_cfg = {

struct iwl_cfg iwl5100_bg_cfg = {
	.name = "5100BG",
	.fw_name = IWL5000_MODULE_FIRMWARE,
	.fw_name_pre = IWL5000_FW_PRE,
	.ucode_api_max = IWL5000_UCODE_API_MAX,
	.ucode_api_min = IWL5000_UCODE_API_MIN,
	.sku = IWL_SKU_G,
	.ops = &iwl5000_ops,
	.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
@@ -1554,7 +1568,9 @@ struct iwl_cfg iwl5100_bg_cfg = {

struct iwl_cfg iwl5100_abg_cfg = {
	.name = "5100ABG",
	.fw_name = IWL5000_MODULE_FIRMWARE,
	.fw_name_pre = IWL5000_FW_PRE,
	.ucode_api_max = IWL5000_UCODE_API_MAX,
	.ucode_api_min = IWL5000_UCODE_API_MIN,
	.sku = IWL_SKU_A|IWL_SKU_G,
	.ops = &iwl5000_ops,
	.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
@@ -1565,7 +1581,9 @@ struct iwl_cfg iwl5100_abg_cfg = {

struct iwl_cfg iwl5100_agn_cfg = {
	.name = "5100AGN",
	.fw_name = IWL5000_MODULE_FIRMWARE,
	.fw_name_pre = IWL5000_FW_PRE,
	.ucode_api_max = IWL5000_UCODE_API_MAX,
	.ucode_api_min = IWL5000_UCODE_API_MIN,
	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
	.ops = &iwl5000_ops,
	.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
@@ -1576,7 +1594,9 @@ struct iwl_cfg iwl5100_agn_cfg = {

struct iwl_cfg iwl5350_agn_cfg = {
	.name = "5350AGN",
	.fw_name = IWL5000_MODULE_FIRMWARE,
	.fw_name_pre = IWL5000_FW_PRE,
	.ucode_api_max = IWL5000_UCODE_API_MAX,
	.ucode_api_min = IWL5000_UCODE_API_MIN,
	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
	.ops = &iwl5000_ops,
	.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
@@ -1587,7 +1607,9 @@ struct iwl_cfg iwl5350_agn_cfg = {

struct iwl_cfg iwl5150_agn_cfg = {
	.name = "5150AGN",
	.fw_name = IWL5150_MODULE_FIRMWARE,
	.fw_name_pre = IWL5150_FW_PRE,
	.ucode_api_max = IWL5150_UCODE_API_MAX,
	.ucode_api_min = IWL5150_UCODE_API_MIN,
	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
	.ops = &iwl5000_ops,
	.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
@@ -1596,8 +1618,8 @@ struct iwl_cfg iwl5150_agn_cfg = {
	.mod_params = &iwl50_mod_params,
};

MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE);
MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE);
MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_MAX));

module_param_named(disable50, iwl50_mod_params.disable, int, 0444);
MODULE_PARM_DESC(disable50,
Loading