aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl3945-base.c
diff options
context:
space:
mode:
authorReinette Chatre <reinette.chatre@intel.com>2008-12-02 15:14:06 -0500
committerJohn W. Linville <linville@tuxdriver.com>2008-12-05 09:35:56 -0500
commita0987a8d68c86562f267efa97be01314c490c496 (patch)
treebd2fe7c65c61fbbb9a94c5264b0690fddbcbe6d2 /drivers/net/wireless/iwlwifi/iwl3945-base.c
parentc02b3acd29766c6f79c2411cb5b85e1ee72c4c8f (diff)
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: Reinette Chatre <reinette.chatre@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl3945-base.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c64
1 files changed, 50 insertions, 14 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 03ff87fbe924..1d3efa9d01b4 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -5296,25 +5296,41 @@ static void iwl3945_nic_start(struct iwl3945_priv *priv)
5296static int iwl3945_read_ucode(struct iwl3945_priv *priv) 5296static int iwl3945_read_ucode(struct iwl3945_priv *priv)
5297{ 5297{
5298 struct iwl3945_ucode *ucode; 5298 struct iwl3945_ucode *ucode;
5299 int ret = 0; 5299 int ret = -EINVAL, index;
5300 const struct firmware *ucode_raw; 5300 const struct firmware *ucode_raw;
5301 /* firmware file name contains uCode/driver compatibility version */ 5301 /* firmware file name contains uCode/driver compatibility version */
5302 const char *name = priv->cfg->fw_name; 5302 const char *name_pre = priv->cfg->fw_name_pre;
5303 const unsigned int api_max = priv->cfg->ucode_api_max;
5304 const unsigned int api_min = priv->cfg->ucode_api_min;
5305 char buf[25];
5303 u8 *src; 5306 u8 *src;
5304 size_t len; 5307 size_t len;
5305 u32 inst_size, data_size, init_size, init_data_size, boot_size; 5308 u32 api_ver, inst_size, data_size, init_size, init_data_size, boot_size;
5306 5309
5307 /* Ask kernel firmware_class module to get the boot firmware off disk. 5310 /* Ask kernel firmware_class module to get the boot firmware off disk.
5308 * request_firmware() is synchronous, file is in memory on return. */ 5311 * request_firmware() is synchronous, file is in memory on return. */
5309 ret = request_firmware(&ucode_raw, name, &priv->pci_dev->dev); 5312 for (index = api_max; index >= api_min; index--) {
5310 if (ret < 0) { 5313 sprintf(buf, "%s%u%s", name_pre, index, ".ucode");
5311 IWL_ERROR("%s firmware file req failed: Reason %d\n", 5314 ret = request_firmware(&ucode_raw, buf, &priv->pci_dev->dev);
5312 name, ret); 5315 if (ret < 0) {
5313 goto error; 5316 IWL_ERROR("%s firmware file req failed: Reason %d\n",
5317 buf, ret);
5318 if (ret == -ENOENT)
5319 continue;
5320 else
5321 goto error;
5322 } else {
5323 if (index < api_max)
5324 IWL_ERROR("Loaded firmware %s, which is deprecated. Please use API v%u instead.\n",
5325 buf, api_max);
5326 IWL_DEBUG_INFO("Got firmware '%s' file (%zd bytes) from disk\n",
5327 buf, ucode_raw->size);
5328 break;
5329 }
5314 } 5330 }
5315 5331
5316 IWL_DEBUG_INFO("Got firmware '%s' file (%zd bytes) from disk\n", 5332 if (ret < 0)
5317 name, ucode_raw->size); 5333 goto error;
5318 5334
5319 /* Make sure that we got at least our header! */ 5335 /* Make sure that we got at least our header! */
5320 if (ucode_raw->size < sizeof(*ucode)) { 5336 if (ucode_raw->size < sizeof(*ucode)) {
@@ -5327,25 +5343,45 @@ static int iwl3945_read_ucode(struct iwl3945_priv *priv)
5327 ucode = (void *)ucode_raw->data; 5343 ucode = (void *)ucode_raw->data;
5328 5344
5329 priv->ucode_ver = le32_to_cpu(ucode->ver); 5345 priv->ucode_ver = le32_to_cpu(ucode->ver);
5346 api_ver = IWL_UCODE_API(priv->ucode_ver);
5330 inst_size = le32_to_cpu(ucode->inst_size); 5347 inst_size = le32_to_cpu(ucode->inst_size);
5331 data_size = le32_to_cpu(ucode->data_size); 5348 data_size = le32_to_cpu(ucode->data_size);
5332 init_size = le32_to_cpu(ucode->init_size); 5349 init_size = le32_to_cpu(ucode->init_size);
5333 init_data_size = le32_to_cpu(ucode->init_data_size); 5350 init_data_size = le32_to_cpu(ucode->init_data_size);
5334 boot_size = le32_to_cpu(ucode->boot_size); 5351 boot_size = le32_to_cpu(ucode->boot_size);
5335 5352
5336 IWL_DEBUG_INFO("f/w package hdr ucode version raw = 0x%x\n", 5353 /* api_ver should match the api version forming part of the
5337 priv->ucode_ver); 5354 * firmware filename ... but we don't check for that and only rely
5338 IWL_DEBUG_INFO("f/w package hdr ucode version = %u.%u.%u.%u\n", 5355 * on the API version read from firware header from here on forward */
5356
5357 if (api_ver < api_min || api_ver > api_max) {
5358 IWL_ERROR("Driver unable to support your firmware API. "
5359 "Driver supports v%u, firmware is v%u.\n",
5360 api_max, api_ver);
5361 priv->ucode_ver = 0;
5362 ret = -EINVAL;
5363 goto err_release;
5364 }
5365 if (api_ver != api_max)
5366 IWL_ERROR("Firmware has old API version. Expected %u, "
5367 "got %u. New firmware can be obtained "
5368 "from http://www.intellinuxwireless.org.\n",
5369 api_max, api_ver);
5370
5371 printk(KERN_INFO DRV_NAME " loaded firmware version %u.%u.%u.%u\n",
5339 IWL_UCODE_MAJOR(priv->ucode_ver), 5372 IWL_UCODE_MAJOR(priv->ucode_ver),
5340 IWL_UCODE_MINOR(priv->ucode_ver), 5373 IWL_UCODE_MINOR(priv->ucode_ver),
5341 IWL_UCODE_API(priv->ucode_ver), 5374 IWL_UCODE_API(priv->ucode_ver),
5342 IWL_UCODE_SERIAL(priv->ucode_ver)); 5375 IWL_UCODE_SERIAL(priv->ucode_ver));
5376 IWL_DEBUG_INFO("f/w package hdr ucode version raw = 0x%x\n",
5377 priv->ucode_ver);
5343 IWL_DEBUG_INFO("f/w package hdr runtime inst size = %u\n", inst_size); 5378 IWL_DEBUG_INFO("f/w package hdr runtime inst size = %u\n", inst_size);
5344 IWL_DEBUG_INFO("f/w package hdr runtime data size = %u\n", data_size); 5379 IWL_DEBUG_INFO("f/w package hdr runtime data size = %u\n", data_size);
5345 IWL_DEBUG_INFO("f/w package hdr init inst size = %u\n", init_size); 5380 IWL_DEBUG_INFO("f/w package hdr init inst size = %u\n", init_size);
5346 IWL_DEBUG_INFO("f/w package hdr init data size = %u\n", init_data_size); 5381 IWL_DEBUG_INFO("f/w package hdr init data size = %u\n", init_data_size);
5347 IWL_DEBUG_INFO("f/w package hdr boot inst size = %u\n", boot_size); 5382 IWL_DEBUG_INFO("f/w package hdr boot inst size = %u\n", boot_size);
5348 5383
5384
5349 /* Verify size of file vs. image size info in file's header */ 5385 /* Verify size of file vs. image size info in file's header */
5350 if (ucode_raw->size < sizeof(*ucode) + 5386 if (ucode_raw->size < sizeof(*ucode) +
5351 inst_size + data_size + init_size + 5387 inst_size + data_size + init_size +
@@ -8304,7 +8340,7 @@ static void __exit iwl3945_exit(void)
8304 iwl3945_rate_control_unregister(); 8340 iwl3945_rate_control_unregister();
8305} 8341}
8306 8342
8307MODULE_FIRMWARE("iwlwifi-3945" IWL3945_UCODE_API ".ucode"); 8343MODULE_FIRMWARE(IWL3945_MODULE_FIRMWARE(IWL3945_UCODE_API_MAX));
8308 8344
8309module_param_named(antenna, iwl3945_param_antenna, int, 0444); 8345module_param_named(antenna, iwl3945_param_antenna, int, 0444);
8310MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); 8346MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");