diff options
author | Tomas Winkler <tomas.winkler@intel.com> | 2007-11-28 22:09:41 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 18:05:12 -0500 |
commit | 90e759d14cd58ea1e34042bab930ce434fa0e4fa (patch) | |
tree | a3c3de33fbf6fd358dd9489026b80d9f8358983a /drivers/net/wireless/iwlwifi/iwl4965-base.c | |
parent | 5a6012e105ae1664cd2841c33bf59fbdd8d4dbcc (diff) |
iwlwifi: Support for uCode without init and bsm section
This patch enables loading fw w/o init and bsm section. It also provides
general cleanup of the rutine.
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
Signed-off-by: Zhu Yi <yi.zhu@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl4965-base.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl4965-base.c | 122 |
1 files changed, 56 insertions, 66 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 02433930f7e2..921c662da380 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c | |||
@@ -6146,6 +6146,12 @@ static void iwl4965_nic_start(struct iwl4965_priv *priv) | |||
6146 | iwl4965_write32(priv, CSR_RESET, 0); | 6146 | iwl4965_write32(priv, CSR_RESET, 0); |
6147 | } | 6147 | } |
6148 | 6148 | ||
6149 | static int iwl4965_alloc_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc) | ||
6150 | { | ||
6151 | desc->v_addr = pci_alloc_consistent(pci_dev, desc->len, &desc->p_addr); | ||
6152 | return (desc->v_addr != NULL) ? 0 : -ENOMEM; | ||
6153 | } | ||
6154 | |||
6149 | /** | 6155 | /** |
6150 | * iwl4965_read_ucode - Read uCode images from disk file. | 6156 | * iwl4965_read_ucode - Read uCode images from disk file. |
6151 | * | 6157 | * |
@@ -6154,7 +6160,7 @@ static void iwl4965_nic_start(struct iwl4965_priv *priv) | |||
6154 | static int iwl4965_read_ucode(struct iwl4965_priv *priv) | 6160 | static int iwl4965_read_ucode(struct iwl4965_priv *priv) |
6155 | { | 6161 | { |
6156 | struct iwl4965_ucode *ucode; | 6162 | struct iwl4965_ucode *ucode; |
6157 | int rc = 0; | 6163 | int ret; |
6158 | const struct firmware *ucode_raw; | 6164 | const struct firmware *ucode_raw; |
6159 | const char *name = "iwlwifi-4965" IWL4965_UCODE_API ".ucode"; | 6165 | const char *name = "iwlwifi-4965" IWL4965_UCODE_API ".ucode"; |
6160 | u8 *src; | 6166 | u8 *src; |
@@ -6163,9 +6169,10 @@ static int iwl4965_read_ucode(struct iwl4965_priv *priv) | |||
6163 | 6169 | ||
6164 | /* Ask kernel firmware_class module to get the boot firmware off disk. | 6170 | /* Ask kernel firmware_class module to get the boot firmware off disk. |
6165 | * request_firmware() is synchronous, file is in memory on return. */ | 6171 | * request_firmware() is synchronous, file is in memory on return. */ |
6166 | rc = request_firmware(&ucode_raw, name, &priv->pci_dev->dev); | 6172 | ret = request_firmware(&ucode_raw, name, &priv->pci_dev->dev); |
6167 | if (rc < 0) { | 6173 | if (ret < 0) { |
6168 | IWL_ERROR("%s firmware file req failed: Reason %d\n", name, rc); | 6174 | IWL_ERROR("%s firmware file req failed: Reason %d\n", |
6175 | name, ret); | ||
6169 | goto error; | 6176 | goto error; |
6170 | } | 6177 | } |
6171 | 6178 | ||
@@ -6175,7 +6182,7 @@ static int iwl4965_read_ucode(struct iwl4965_priv *priv) | |||
6175 | /* Make sure that we got at least our header! */ | 6182 | /* Make sure that we got at least our header! */ |
6176 | if (ucode_raw->size < sizeof(*ucode)) { | 6183 | if (ucode_raw->size < sizeof(*ucode)) { |
6177 | IWL_ERROR("File size way too small!\n"); | 6184 | IWL_ERROR("File size way too small!\n"); |
6178 | rc = -EINVAL; | 6185 | ret = -EINVAL; |
6179 | goto err_release; | 6186 | goto err_release; |
6180 | } | 6187 | } |
6181 | 6188 | ||
@@ -6208,43 +6215,43 @@ static int iwl4965_read_ucode(struct iwl4965_priv *priv) | |||
6208 | 6215 | ||
6209 | IWL_DEBUG_INFO("uCode file size %d too small\n", | 6216 | IWL_DEBUG_INFO("uCode file size %d too small\n", |
6210 | (int)ucode_raw->size); | 6217 | (int)ucode_raw->size); |
6211 | rc = -EINVAL; | 6218 | ret = -EINVAL; |
6212 | goto err_release; | 6219 | goto err_release; |
6213 | } | 6220 | } |
6214 | 6221 | ||
6215 | /* Verify that uCode images will fit in card's SRAM */ | 6222 | /* Verify that uCode images will fit in card's SRAM */ |
6216 | if (inst_size > IWL_MAX_INST_SIZE) { | 6223 | if (inst_size > IWL_MAX_INST_SIZE) { |
6217 | IWL_DEBUG_INFO("uCode instr len %d too large to fit in card\n", | 6224 | IWL_DEBUG_INFO("uCode instr len %d too large to fit in\n", |
6218 | (int)inst_size); | 6225 | inst_size); |
6219 | rc = -EINVAL; | 6226 | ret = -EINVAL; |
6220 | goto err_release; | 6227 | goto err_release; |
6221 | } | 6228 | } |
6222 | 6229 | ||
6223 | if (data_size > IWL_MAX_DATA_SIZE) { | 6230 | if (data_size > IWL_MAX_DATA_SIZE) { |
6224 | IWL_DEBUG_INFO("uCode data len %d too large to fit in card\n", | 6231 | IWL_DEBUG_INFO("uCode data len %d too large to fit in\n", |
6225 | (int)data_size); | 6232 | data_size); |
6226 | rc = -EINVAL; | 6233 | ret = -EINVAL; |
6227 | goto err_release; | 6234 | goto err_release; |
6228 | } | 6235 | } |
6229 | if (init_size > IWL_MAX_INST_SIZE) { | 6236 | if (init_size > IWL_MAX_INST_SIZE) { |
6230 | IWL_DEBUG_INFO | 6237 | IWL_DEBUG_INFO |
6231 | ("uCode init instr len %d too large to fit in card\n", | 6238 | ("uCode init instr len %d too large to fit in\n", |
6232 | (int)init_size); | 6239 | init_size); |
6233 | rc = -EINVAL; | 6240 | ret = -EINVAL; |
6234 | goto err_release; | 6241 | goto err_release; |
6235 | } | 6242 | } |
6236 | if (init_data_size > IWL_MAX_DATA_SIZE) { | 6243 | if (init_data_size > IWL_MAX_DATA_SIZE) { |
6237 | IWL_DEBUG_INFO | 6244 | IWL_DEBUG_INFO |
6238 | ("uCode init data len %d too large to fit in card\n", | 6245 | ("uCode init data len %d too large to fit in\n", |
6239 | (int)init_data_size); | 6246 | init_data_size); |
6240 | rc = -EINVAL; | 6247 | ret = -EINVAL; |
6241 | goto err_release; | 6248 | goto err_release; |
6242 | } | 6249 | } |
6243 | if (boot_size > IWL_MAX_BSM_SIZE) { | 6250 | if (boot_size > IWL_MAX_BSM_SIZE) { |
6244 | IWL_DEBUG_INFO | 6251 | IWL_DEBUG_INFO |
6245 | ("uCode boot instr len %d too large to fit in bsm\n", | 6252 | ("uCode boot instr len %d too large to fit in\n", |
6246 | (int)boot_size); | 6253 | boot_size); |
6247 | rc = -EINVAL; | 6254 | ret = -EINVAL; |
6248 | goto err_release; | 6255 | goto err_release; |
6249 | } | 6256 | } |
6250 | 6257 | ||
@@ -6254,56 +6261,41 @@ static int iwl4965_read_ucode(struct iwl4965_priv *priv) | |||
6254 | * 1) unmodified from disk | 6261 | * 1) unmodified from disk |
6255 | * 2) backup cache for save/restore during power-downs */ | 6262 | * 2) backup cache for save/restore during power-downs */ |
6256 | priv->ucode_code.len = inst_size; | 6263 | priv->ucode_code.len = inst_size; |
6257 | priv->ucode_code.v_addr = | 6264 | iwl4965_alloc_fw_desc(priv->pci_dev, &priv->ucode_code); |
6258 | pci_alloc_consistent(priv->pci_dev, | ||
6259 | priv->ucode_code.len, | ||
6260 | &(priv->ucode_code.p_addr)); | ||
6261 | 6265 | ||
6262 | priv->ucode_data.len = data_size; | 6266 | priv->ucode_data.len = data_size; |
6263 | priv->ucode_data.v_addr = | 6267 | iwl4965_alloc_fw_desc(priv->pci_dev, &priv->ucode_data); |
6264 | pci_alloc_consistent(priv->pci_dev, | ||
6265 | priv->ucode_data.len, | ||
6266 | &(priv->ucode_data.p_addr)); | ||
6267 | 6268 | ||
6268 | priv->ucode_data_backup.len = data_size; | 6269 | priv->ucode_data_backup.len = data_size; |
6269 | priv->ucode_data_backup.v_addr = | 6270 | iwl4965_alloc_fw_desc(priv->pci_dev, &priv->ucode_data_backup); |
6270 | pci_alloc_consistent(priv->pci_dev, | ||
6271 | priv->ucode_data_backup.len, | ||
6272 | &(priv->ucode_data_backup.p_addr)); | ||
6273 | |||
6274 | 6271 | ||
6275 | /* Initialization instructions and data */ | 6272 | /* Initialization instructions and data */ |
6276 | priv->ucode_init.len = init_size; | 6273 | if (init_size && init_data_size) { |
6277 | priv->ucode_init.v_addr = | 6274 | priv->ucode_init.len = init_size; |
6278 | pci_alloc_consistent(priv->pci_dev, | 6275 | iwl4965_alloc_fw_desc(priv->pci_dev, &priv->ucode_init); |
6279 | priv->ucode_init.len, | 6276 | |
6280 | &(priv->ucode_init.p_addr)); | 6277 | priv->ucode_init_data.len = init_data_size; |
6281 | 6278 | iwl4965_alloc_fw_desc(priv->pci_dev, &priv->ucode_init_data); | |
6282 | priv->ucode_init_data.len = init_data_size; | 6279 | |
6283 | priv->ucode_init_data.v_addr = | 6280 | if (!priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr) |
6284 | pci_alloc_consistent(priv->pci_dev, | 6281 | goto err_pci_alloc; |
6285 | priv->ucode_init_data.len, | 6282 | } |
6286 | &(priv->ucode_init_data.p_addr)); | ||
6287 | 6283 | ||
6288 | /* Bootstrap (instructions only, no data) */ | 6284 | /* Bootstrap (instructions only, no data) */ |
6289 | priv->ucode_boot.len = boot_size; | 6285 | if (boot_size) { |
6290 | priv->ucode_boot.v_addr = | 6286 | priv->ucode_boot.len = boot_size; |
6291 | pci_alloc_consistent(priv->pci_dev, | 6287 | iwl4965_alloc_fw_desc(priv->pci_dev, &priv->ucode_boot); |
6292 | priv->ucode_boot.len, | ||
6293 | &(priv->ucode_boot.p_addr)); | ||
6294 | 6288 | ||
6295 | if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr || | 6289 | if (!priv->ucode_boot.v_addr) |
6296 | !priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr || | 6290 | goto err_pci_alloc; |
6297 | !priv->ucode_boot.v_addr || !priv->ucode_data_backup.v_addr) | 6291 | } |
6298 | goto err_pci_alloc; | ||
6299 | 6292 | ||
6300 | /* Copy images into buffers for card's bus-master reads ... */ | 6293 | /* Copy images into buffers for card's bus-master reads ... */ |
6301 | 6294 | ||
6302 | /* Runtime instructions (first block of data in file) */ | 6295 | /* Runtime instructions (first block of data in file) */ |
6303 | src = &ucode->data[0]; | 6296 | src = &ucode->data[0]; |
6304 | len = priv->ucode_code.len; | 6297 | len = priv->ucode_code.len; |
6305 | IWL_DEBUG_INFO("Copying (but not loading) uCode instr len %d\n", | 6298 | IWL_DEBUG_INFO("Copying (but not loading) uCode instr len %Zd\n", len); |
6306 | (int)len); | ||
6307 | memcpy(priv->ucode_code.v_addr, src, len); | 6299 | memcpy(priv->ucode_code.v_addr, src, len); |
6308 | IWL_DEBUG_INFO("uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n", | 6300 | IWL_DEBUG_INFO("uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n", |
6309 | priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr); | 6301 | priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr); |
@@ -6312,8 +6304,7 @@ static int iwl4965_read_ucode(struct iwl4965_priv *priv) | |||
6312 | * NOTE: Copy into backup buffer will be done in iwl4965_up() */ | 6304 | * NOTE: Copy into backup buffer will be done in iwl4965_up() */ |
6313 | src = &ucode->data[inst_size]; | 6305 | src = &ucode->data[inst_size]; |
6314 | len = priv->ucode_data.len; | 6306 | len = priv->ucode_data.len; |
6315 | IWL_DEBUG_INFO("Copying (but not loading) uCode data len %d\n", | 6307 | IWL_DEBUG_INFO("Copying (but not loading) uCode data len %Zd\n", len); |
6316 | (int)len); | ||
6317 | memcpy(priv->ucode_data.v_addr, src, len); | 6308 | memcpy(priv->ucode_data.v_addr, src, len); |
6318 | memcpy(priv->ucode_data_backup.v_addr, src, len); | 6309 | memcpy(priv->ucode_data_backup.v_addr, src, len); |
6319 | 6310 | ||
@@ -6321,8 +6312,8 @@ static int iwl4965_read_ucode(struct iwl4965_priv *priv) | |||
6321 | if (init_size) { | 6312 | if (init_size) { |
6322 | src = &ucode->data[inst_size + data_size]; | 6313 | src = &ucode->data[inst_size + data_size]; |
6323 | len = priv->ucode_init.len; | 6314 | len = priv->ucode_init.len; |
6324 | IWL_DEBUG_INFO("Copying (but not loading) init instr len %d\n", | 6315 | IWL_DEBUG_INFO("Copying (but not loading) init instr len %Zd\n", |
6325 | (int)len); | 6316 | len); |
6326 | memcpy(priv->ucode_init.v_addr, src, len); | 6317 | memcpy(priv->ucode_init.v_addr, src, len); |
6327 | } | 6318 | } |
6328 | 6319 | ||
@@ -6330,16 +6321,15 @@ static int iwl4965_read_ucode(struct iwl4965_priv *priv) | |||
6330 | if (init_data_size) { | 6321 | if (init_data_size) { |
6331 | src = &ucode->data[inst_size + data_size + init_size]; | 6322 | src = &ucode->data[inst_size + data_size + init_size]; |
6332 | len = priv->ucode_init_data.len; | 6323 | len = priv->ucode_init_data.len; |
6333 | IWL_DEBUG_INFO("Copying (but not loading) init data len %d\n", | 6324 | IWL_DEBUG_INFO("Copying (but not loading) init data len %Zd\n", |
6334 | (int)len); | 6325 | len); |
6335 | memcpy(priv->ucode_init_data.v_addr, src, len); | 6326 | memcpy(priv->ucode_init_data.v_addr, src, len); |
6336 | } | 6327 | } |
6337 | 6328 | ||
6338 | /* Bootstrap instructions (5th block) */ | 6329 | /* Bootstrap instructions (5th block) */ |
6339 | src = &ucode->data[inst_size + data_size + init_size + init_data_size]; | 6330 | src = &ucode->data[inst_size + data_size + init_size + init_data_size]; |
6340 | len = priv->ucode_boot.len; | 6331 | len = priv->ucode_boot.len; |
6341 | IWL_DEBUG_INFO("Copying (but not loading) boot instr len %d\n", | 6332 | IWL_DEBUG_INFO("Copying (but not loading) boot instr len %Zd\n", len); |
6342 | (int)len); | ||
6343 | memcpy(priv->ucode_boot.v_addr, src, len); | 6333 | memcpy(priv->ucode_boot.v_addr, src, len); |
6344 | 6334 | ||
6345 | /* We have our copies now, allow OS release its copies */ | 6335 | /* We have our copies now, allow OS release its copies */ |
@@ -6348,14 +6338,14 @@ static int iwl4965_read_ucode(struct iwl4965_priv *priv) | |||
6348 | 6338 | ||
6349 | err_pci_alloc: | 6339 | err_pci_alloc: |
6350 | IWL_ERROR("failed to allocate pci memory\n"); | 6340 | IWL_ERROR("failed to allocate pci memory\n"); |
6351 | rc = -ENOMEM; | 6341 | ret = -ENOMEM; |
6352 | iwl4965_dealloc_ucode_pci(priv); | 6342 | iwl4965_dealloc_ucode_pci(priv); |
6353 | 6343 | ||
6354 | err_release: | 6344 | err_release: |
6355 | release_firmware(ucode_raw); | 6345 | release_firmware(ucode_raw); |
6356 | 6346 | ||
6357 | error: | 6347 | error: |
6358 | return rc; | 6348 | return ret; |
6359 | } | 6349 | } |
6360 | 6350 | ||
6361 | 6351 | ||