diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl3945-base.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl3945-base.c | 64 |
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) | |||
5296 | static int iwl3945_read_ucode(struct iwl3945_priv *priv) | 5296 | static 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 | ||
8307 | MODULE_FIRMWARE("iwlwifi-3945" IWL3945_UCODE_API ".ucode"); | 8343 | MODULE_FIRMWARE(IWL3945_MODULE_FIRMWARE(IWL3945_UCODE_API_MAX)); |
8308 | 8344 | ||
8309 | module_param_named(antenna, iwl3945_param_antenna, int, 0444); | 8345 | module_param_named(antenna, iwl3945_param_antenna, int, 0444); |
8310 | MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); | 8346 | MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); |