aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ipw2200.c
diff options
context:
space:
mode:
authorZhu Yi <yi.zhu@intel.com>2006-01-24 03:37:22 -0500
committerJohn W. Linville <linville@tuxdriver.com>2006-01-30 20:35:34 -0500
commit397ae121ee0116d3b4125d621f0ef528d1d52580 (patch)
treeb4de052ca78d6c8b4c05494a4a297aac9e88190e /drivers/net/wireless/ipw2200.c
parent4bfdb91dcff0dd4b70922de263ccffffb8fb1d16 (diff)
[PATCH] ipw2200: Scale firmware loading watchdog with the firmware size
I can't really help with why restarts happen, but the following patch greatly increases the likelihood that a firmware reload will succeed afterward on my thinkpad. It addresses two issues. First, sysfs module loading and hotplug are asynchronous, and as such file operations on the "loading" and "data" files are racy when you load 2 firmwares in quick succession. Second, the timeout for DMAing the firmware needs to scale with the size of the firmware being loaded. That is, the watchdog needs to be on throughput, not on time alone. I no longer get the firmware load errors, though this is at best a hacky workaround for a racy interface. (Obviously, this does nothing to address the fatal errors in firmware which cause reloads; it just causes the initial loading and the reloads to work more often.) Signed-off-by: Peter Jones <pjones@redhat.com> Signed-off-by: Ben M Cahill <ben.m.cahill@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/ipw2200.c')
-rw-r--r--drivers/net/wireless/ipw2200.c114
1 files changed, 63 insertions, 51 deletions
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index 624f29500490..c42eb54f379a 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -2772,22 +2772,25 @@ static int ipw_fw_dma_add_buffer(struct ipw_priv *priv,
2772 2772
2773static int ipw_fw_dma_wait(struct ipw_priv *priv) 2773static int ipw_fw_dma_wait(struct ipw_priv *priv)
2774{ 2774{
2775 u32 current_index = 0; 2775 u32 current_index = 0, previous_index;
2776 u32 watchdog = 0; 2776 u32 watchdog = 0;
2777 2777
2778 IPW_DEBUG_FW(">> : \n"); 2778 IPW_DEBUG_FW(">> : \n");
2779 2779
2780 current_index = ipw_fw_dma_command_block_index(priv); 2780 current_index = ipw_fw_dma_command_block_index(priv);
2781 IPW_DEBUG_FW_INFO("sram_desc.last_cb_index:0x%8X\n", 2781 IPW_DEBUG_FW_INFO("sram_desc.last_cb_index:0x%08X\n",
2782 (int)priv->sram_desc.last_cb_index); 2782 (int)priv->sram_desc.last_cb_index);
2783 2783
2784 while (current_index < priv->sram_desc.last_cb_index) { 2784 while (current_index < priv->sram_desc.last_cb_index) {
2785 udelay(50); 2785 udelay(50);
2786 previous_index = current_index;
2786 current_index = ipw_fw_dma_command_block_index(priv); 2787 current_index = ipw_fw_dma_command_block_index(priv);
2787 2788
2788 watchdog++; 2789 if (previous_index < current_index) {
2789 2790 watchdog = 0;
2790 if (watchdog > 400) { 2791 continue;
2792 }
2793 if (++watchdog > 400) {
2791 IPW_DEBUG_FW_INFO("Timeout\n"); 2794 IPW_DEBUG_FW_INFO("Timeout\n");
2792 ipw_fw_dma_dump_command_block(priv); 2795 ipw_fw_dma_dump_command_block(priv);
2793 ipw_fw_dma_abort(priv); 2796 ipw_fw_dma_abort(priv);
@@ -3276,55 +3279,31 @@ static int ipw_load(struct ipw_priv *priv)
3276 const struct firmware *firmware = NULL; 3279 const struct firmware *firmware = NULL;
3277 const struct firmware *ucode = NULL; 3280 const struct firmware *ucode = NULL;
3278#endif 3281#endif
3282 char *ucode_name;
3283 char *fw_name;
3279 int rc = 0, retries = 3; 3284 int rc = 0, retries = 3;
3280 3285
3281#ifdef CONFIG_PM 3286 switch (priv->ieee->iw_mode) {
3282 if (!fw_loaded) { 3287 case IW_MODE_ADHOC:
3283#endif 3288 ucode_name = IPW_FW_NAME("ibss_ucode");
3284 rc = ipw_get_fw(priv, &bootfw, IPW_FW_NAME("boot")); 3289 fw_name = IPW_FW_NAME("ibss");
3285 if (rc) 3290 break;
3286 goto error;
3287
3288 switch (priv->ieee->iw_mode) {
3289 case IW_MODE_ADHOC:
3290 rc = ipw_get_fw(priv, &ucode,
3291 IPW_FW_NAME("ibss_ucode"));
3292 if (rc)
3293 goto error;
3294
3295 rc = ipw_get_fw(priv, &firmware, IPW_FW_NAME("ibss"));
3296 break;
3297
3298#ifdef CONFIG_IPW2200_MONITOR 3291#ifdef CONFIG_IPW2200_MONITOR
3299 case IW_MODE_MONITOR: 3292 case IW_MODE_MONITOR:
3300 rc = ipw_get_fw(priv, &ucode, 3293 ucode_name = IPW_FW_NAME("sniffer_ucode");
3301 IPW_FW_NAME("sniffer_ucode")); 3294 fw_name = IPW_FW_NAME("sniffer");
3302 if (rc) 3295 break;
3303 goto error;
3304
3305 rc = ipw_get_fw(priv, &firmware,
3306 IPW_FW_NAME("sniffer"));
3307 break;
3308#endif 3296#endif
3309 case IW_MODE_INFRA: 3297 case IW_MODE_INFRA:
3310 rc = ipw_get_fw(priv, &ucode, IPW_FW_NAME("bss_ucode")); 3298 ucode_name = IPW_FW_NAME("bss_ucode");
3311 if (rc) 3299 fw_name = IPW_FW_NAME("bss");
3312 goto error; 3300 break;
3313 3301 default:
3314 rc = ipw_get_fw(priv, &firmware, IPW_FW_NAME("bss")); 3302 rc = -EINVAL;
3315 break;
3316
3317 default:
3318 rc = -EINVAL;
3319 }
3320
3321 if (rc)
3322 goto error;
3323
3324#ifdef CONFIG_PM
3325 fw_loaded = 1;
3326 } 3303 }
3327#endif 3304
3305 if (rc < 0)
3306 goto error;
3328 3307
3329 if (!priv->rxq) 3308 if (!priv->rxq)
3330 priv->rxq = ipw_rx_queue_alloc(priv); 3309 priv->rxq = ipw_rx_queue_alloc(priv);
@@ -3346,7 +3325,7 @@ static int ipw_load(struct ipw_priv *priv)
3346 ipw_stop_nic(priv); 3325 ipw_stop_nic(priv);
3347 3326
3348 rc = ipw_reset_nic(priv); 3327 rc = ipw_reset_nic(priv);
3349 if (rc) { 3328 if (rc < 0) {
3350 IPW_ERROR("Unable to reset NIC\n"); 3329 IPW_ERROR("Unable to reset NIC\n");
3351 goto error; 3330 goto error;
3352 } 3331 }
@@ -3354,6 +3333,15 @@ static int ipw_load(struct ipw_priv *priv)
3354 ipw_zero_memory(priv, IPW_NIC_SRAM_LOWER_BOUND, 3333 ipw_zero_memory(priv, IPW_NIC_SRAM_LOWER_BOUND,
3355 IPW_NIC_SRAM_UPPER_BOUND - IPW_NIC_SRAM_LOWER_BOUND); 3334 IPW_NIC_SRAM_UPPER_BOUND - IPW_NIC_SRAM_LOWER_BOUND);
3356 3335
3336#ifdef CONFIG_PM
3337 if (!fw_loaded) {
3338#endif
3339 rc = ipw_get_fw(priv, &bootfw, IPW_FW_NAME("boot"));
3340 if (rc < 0)
3341 goto error;
3342#ifdef CONFIG_PM
3343 }
3344#endif
3357 /* DMA the initial boot firmware into the device */ 3345 /* DMA the initial boot firmware into the device */
3358 rc = ipw_load_firmware(priv, bootfw->data + sizeof(struct fw_header), 3346 rc = ipw_load_firmware(priv, bootfw->data + sizeof(struct fw_header),
3359 bootfw->size - sizeof(struct fw_header)); 3347 bootfw->size - sizeof(struct fw_header));
@@ -3377,6 +3365,16 @@ static int ipw_load(struct ipw_priv *priv)
3377 /* ack fw init done interrupt */ 3365 /* ack fw init done interrupt */
3378 ipw_write32(priv, IPW_INTA_RW, IPW_INTA_BIT_FW_INITIALIZATION_DONE); 3366 ipw_write32(priv, IPW_INTA_RW, IPW_INTA_BIT_FW_INITIALIZATION_DONE);
3379 3367
3368#ifdef CONFIG_PM
3369 if (!fw_loaded) {
3370#endif
3371 rc = ipw_get_fw(priv, &ucode, ucode_name);
3372 if (rc < 0)
3373 goto error;
3374#ifdef CONFIG_PM
3375 }
3376#endif
3377
3380 /* DMA the ucode into the device */ 3378 /* DMA the ucode into the device */
3381 rc = ipw_load_ucode(priv, ucode->data + sizeof(struct fw_header), 3379 rc = ipw_load_ucode(priv, ucode->data + sizeof(struct fw_header),
3382 ucode->size - sizeof(struct fw_header)); 3380 ucode->size - sizeof(struct fw_header));
@@ -3388,6 +3386,16 @@ static int ipw_load(struct ipw_priv *priv)
3388 /* stop nic */ 3386 /* stop nic */
3389 ipw_stop_nic(priv); 3387 ipw_stop_nic(priv);
3390 3388
3389#ifdef CONFIG_PM
3390 if (!fw_loaded) {
3391#endif
3392 rc = ipw_get_fw(priv, &firmware, fw_name);
3393 if (rc < 0)
3394 goto error;
3395#ifdef CONFIG_PM
3396 }
3397#endif
3398
3391 /* DMA bss firmware into the device */ 3399 /* DMA bss firmware into the device */
3392 rc = ipw_load_firmware(priv, firmware->data + 3400 rc = ipw_load_firmware(priv, firmware->data +
3393 sizeof(struct fw_header), 3401 sizeof(struct fw_header),
@@ -3397,10 +3405,14 @@ static int ipw_load(struct ipw_priv *priv)
3397 goto error; 3405 goto error;
3398 } 3406 }
3399 3407
3408#ifdef CONFIG_PM
3409 fw_loaded = 1;
3410#endif
3411
3400 ipw_write32(priv, IPW_EEPROM_LOAD_DISABLE, 0); 3412 ipw_write32(priv, IPW_EEPROM_LOAD_DISABLE, 0);
3401 3413
3402 rc = ipw_queue_reset(priv); 3414 rc = ipw_queue_reset(priv);
3403 if (rc) { 3415 if (rc < 0) {
3404 IPW_ERROR("Unable to initialize queues\n"); 3416 IPW_ERROR("Unable to initialize queues\n");
3405 goto error; 3417 goto error;
3406 } 3418 }