aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJames Ketrenos <jketreno@linux.intel.com>2006-03-07 14:22:28 -0500
committerJohn W. Linville <linville@tuxdriver.com>2006-03-17 15:08:04 -0500
commit9006ea75cfaded82acbc34d03e9d4e86447f40a9 (patch)
treea65ca3227d09488495444b9f4d43179c595191c4 /drivers
parent651be26f2daf31e61faf4b55ada709cf39ec76a2 (diff)
[PATCH] ipw2200: switch to the new ipw2200-fw-3.0 image format
This patch modifies the driver to support the ipw2200-fw-3.0 image format. The 3.0 fw image does not add any new capabilities, but as a result of image format changes, it should fix two problems experienced by users: 1) Race conditions with the request_firmware interface and udev/hotplug are improved as only a single request_firmware call is now required to load the firmware and microcode (vs. 3 separate calls previously) 2) The monitor mode firmware (sniffer) is now packaged with the correct boot image so it can now function without frequent restarts. Note: Once you apply this patch, you will also need to upgrade your firmware image to the 3.0 version available from: http://ipw2200.sf.net/firmware.php Signed-off-by: James Ketrenos <jketreno@linux.intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/ipw2200.c165
1 files changed, 64 insertions, 101 deletions
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index 078f33b01c2f..0b74b5a16647 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -2829,33 +2829,11 @@ static void ipw_arc_release(struct ipw_priv *priv)
2829 mdelay(5); 2829 mdelay(5);
2830} 2830}
2831 2831
2832struct fw_header {
2833 u32 version;
2834 u32 mode;
2835};
2836
2837struct fw_chunk { 2832struct fw_chunk {
2838 u32 address; 2833 u32 address;
2839 u32 length; 2834 u32 length;
2840}; 2835};
2841 2836
2842#define IPW_FW_MAJOR_VERSION 2
2843#define IPW_FW_MINOR_VERSION 4
2844
2845#define IPW_FW_MINOR(x) ((x & 0xff) >> 8)
2846#define IPW_FW_MAJOR(x) (x & 0xff)
2847
2848#define IPW_FW_VERSION ((IPW_FW_MINOR_VERSION << 8) | IPW_FW_MAJOR_VERSION)
2849
2850#define IPW_FW_PREFIX "ipw-" __stringify(IPW_FW_MAJOR_VERSION) \
2851"." __stringify(IPW_FW_MINOR_VERSION) "-"
2852
2853#if IPW_FW_MAJOR_VERSION >= 2 && IPW_FW_MINOR_VERSION > 0
2854#define IPW_FW_NAME(x) IPW_FW_PREFIX "" x ".fw"
2855#else
2856#define IPW_FW_NAME(x) "ipw2200_" x ".fw"
2857#endif
2858
2859static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len) 2837static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len)
2860{ 2838{
2861 int rc = 0, i, addr; 2839 int rc = 0, i, addr;
@@ -3124,33 +3102,47 @@ static int ipw_reset_nic(struct ipw_priv *priv)
3124 return rc; 3102 return rc;
3125} 3103}
3126 3104
3105
3106struct ipw_fw {
3107 u32 ver;
3108 u32 boot_size;
3109 u32 ucode_size;
3110 u32 fw_size;
3111 u8 data[0];
3112};
3113
3127static int ipw_get_fw(struct ipw_priv *priv, 3114static int ipw_get_fw(struct ipw_priv *priv,
3128 const struct firmware **fw, const char *name) 3115 const struct firmware **raw, const char *name)
3129{ 3116{
3130 struct fw_header *header; 3117 struct ipw_fw *fw;
3131 int rc; 3118 int rc;
3132 3119
3133 /* ask firmware_class module to get the boot firmware off disk */ 3120 /* ask firmware_class module to get the boot firmware off disk */
3134 rc = request_firmware(fw, name, &priv->pci_dev->dev); 3121 rc = request_firmware(raw, name, &priv->pci_dev->dev);
3135 if (rc < 0) { 3122 if (rc < 0) {
3136 IPW_ERROR("%s load failed: Reason %d\n", name, rc); 3123 IPW_ERROR("%s request_firmware failed: Reason %d\n", name, rc);
3137 return rc; 3124 return rc;
3138 } 3125 }
3139 3126
3140 header = (struct fw_header *)(*fw)->data; 3127 if ((*raw)->size < sizeof(*fw)) {
3141 if (IPW_FW_MAJOR(le32_to_cpu(header->version)) != IPW_FW_MAJOR_VERSION) { 3128 IPW_ERROR("%s is too small (%zd)\n", name, (*raw)->size);
3142 IPW_ERROR("'%s' firmware version not compatible (%d != %d)\n", 3129 return -EINVAL;
3143 name, 3130 }
3144 IPW_FW_MAJOR(le32_to_cpu(header->version)), 3131
3145 IPW_FW_MAJOR_VERSION); 3132 fw = (void *)(*raw)->data;
3133
3134 if ((*raw)->size < sizeof(*fw) +
3135 fw->boot_size + fw->ucode_size + fw->fw_size) {
3136 IPW_ERROR("%s is too small or corrupt (%zd)\n",
3137 name, (*raw)->size);
3146 return -EINVAL; 3138 return -EINVAL;
3147 } 3139 }
3148 3140
3149 IPW_DEBUG_INFO("Loading firmware '%s' file v%d.%d (%zd bytes)\n", 3141 IPW_DEBUG_INFO("Read firmware '%s' image v%d.%d (%zd bytes)\n",
3150 name, 3142 name,
3151 IPW_FW_MAJOR(le32_to_cpu(header->version)), 3143 le32_to_cpu(fw->ver) >> 16,
3152 IPW_FW_MINOR(le32_to_cpu(header->version)), 3144 le32_to_cpu(fw->ver) & 0xff,
3153 (*fw)->size - sizeof(struct fw_header)); 3145 (*raw)->size - sizeof(*fw));
3154 return 0; 3146 return 0;
3155} 3147}
3156 3148
@@ -3190,17 +3182,13 @@ static void ipw_rx_queue_reset(struct ipw_priv *priv,
3190 3182
3191#ifdef CONFIG_PM 3183#ifdef CONFIG_PM
3192static int fw_loaded = 0; 3184static int fw_loaded = 0;
3193static const struct firmware *bootfw = NULL; 3185static const struct firmware *raw = NULL;
3194static const struct firmware *firmware = NULL;
3195static const struct firmware *ucode = NULL;
3196 3186
3197static void free_firmware(void) 3187static void free_firmware(void)
3198{ 3188{
3199 if (fw_loaded) { 3189 if (fw_loaded) {
3200 release_firmware(bootfw); 3190 release_firmware(raw);
3201 release_firmware(ucode); 3191 raw = NULL;
3202 release_firmware(firmware);
3203 bootfw = ucode = firmware = NULL;
3204 fw_loaded = 0; 3192 fw_loaded = 0;
3205 } 3193 }
3206} 3194}
@@ -3211,32 +3199,46 @@ static void free_firmware(void)
3211static int ipw_load(struct ipw_priv *priv) 3199static int ipw_load(struct ipw_priv *priv)
3212{ 3200{
3213#ifndef CONFIG_PM 3201#ifndef CONFIG_PM
3214 const struct firmware *bootfw = NULL; 3202 const struct firmware *raw = NULL;
3215 const struct firmware *firmware = NULL;
3216 const struct firmware *ucode = NULL;
3217#endif 3203#endif
3218 char *ucode_name; 3204 struct ipw_fw *fw;
3219 char *fw_name; 3205 u8 *boot_img, *ucode_img, *fw_img;
3206 u8 *name = NULL;
3220 int rc = 0, retries = 3; 3207 int rc = 0, retries = 3;
3221 3208
3222 switch (priv->ieee->iw_mode) { 3209 switch (priv->ieee->iw_mode) {
3223 case IW_MODE_ADHOC: 3210 case IW_MODE_ADHOC:
3224 ucode_name = IPW_FW_NAME("ibss_ucode"); 3211 name = "ipw2200-ibss.fw";
3225 fw_name = IPW_FW_NAME("ibss");
3226 break; 3212 break;
3227#ifdef CONFIG_IPW2200_MONITOR 3213#ifdef CONFIG_IPW2200_MONITOR
3228 case IW_MODE_MONITOR: 3214 case IW_MODE_MONITOR:
3229 ucode_name = IPW_FW_NAME("sniffer_ucode"); 3215 name = "ipw2200-sniffer.fw";
3230 fw_name = IPW_FW_NAME("sniffer");
3231 break; 3216 break;
3232#endif 3217#endif
3233 case IW_MODE_INFRA: 3218 case IW_MODE_INFRA:
3234 ucode_name = IPW_FW_NAME("bss_ucode"); 3219 name = "ipw2200-bss.fw";
3235 fw_name = IPW_FW_NAME("bss");
3236 break; 3220 break;
3237 default: 3221 }
3222
3223 if (!name) {
3238 rc = -EINVAL; 3224 rc = -EINVAL;
3225 goto error;
3226 }
3227
3228#ifdef CONFIG_PM
3229 if (!fw_loaded) {
3230#endif
3231 rc = ipw_get_fw(priv, &raw, name);
3232 if (rc < 0)
3233 goto error;
3234#ifdef CONFIG_PM
3239 } 3235 }
3236#endif
3237
3238 fw = (void *)raw->data;
3239 boot_img = &fw->data[0];
3240 ucode_img = &fw->data[fw->boot_size];
3241 fw_img = &fw->data[fw->boot_size + fw->ucode_size];
3240 3242
3241 if (rc < 0) 3243 if (rc < 0)
3242 goto error; 3244 goto error;
@@ -3269,18 +3271,8 @@ static int ipw_load(struct ipw_priv *priv)
3269 ipw_zero_memory(priv, IPW_NIC_SRAM_LOWER_BOUND, 3271 ipw_zero_memory(priv, IPW_NIC_SRAM_LOWER_BOUND,
3270 IPW_NIC_SRAM_UPPER_BOUND - IPW_NIC_SRAM_LOWER_BOUND); 3272 IPW_NIC_SRAM_UPPER_BOUND - IPW_NIC_SRAM_LOWER_BOUND);
3271 3273
3272#ifdef CONFIG_PM
3273 if (!fw_loaded) {
3274#endif
3275 rc = ipw_get_fw(priv, &bootfw, IPW_FW_NAME("boot"));
3276 if (rc < 0)
3277 goto error;
3278#ifdef CONFIG_PM
3279 }
3280#endif
3281 /* DMA the initial boot firmware into the device */ 3274 /* DMA the initial boot firmware into the device */
3282 rc = ipw_load_firmware(priv, bootfw->data + sizeof(struct fw_header), 3275 rc = ipw_load_firmware(priv, boot_img, fw->boot_size);
3283 bootfw->size - sizeof(struct fw_header));
3284 if (rc < 0) { 3276 if (rc < 0) {
3285 IPW_ERROR("Unable to load boot firmware: %d\n", rc); 3277 IPW_ERROR("Unable to load boot firmware: %d\n", rc);
3286 goto error; 3278 goto error;
@@ -3301,19 +3293,8 @@ static int ipw_load(struct ipw_priv *priv)
3301 /* ack fw init done interrupt */ 3293 /* ack fw init done interrupt */
3302 ipw_write32(priv, IPW_INTA_RW, IPW_INTA_BIT_FW_INITIALIZATION_DONE); 3294 ipw_write32(priv, IPW_INTA_RW, IPW_INTA_BIT_FW_INITIALIZATION_DONE);
3303 3295
3304#ifdef CONFIG_PM
3305 if (!fw_loaded) {
3306#endif
3307 rc = ipw_get_fw(priv, &ucode, ucode_name);
3308 if (rc < 0)
3309 goto error;
3310#ifdef CONFIG_PM
3311 }
3312#endif
3313
3314 /* DMA the ucode into the device */ 3296 /* DMA the ucode into the device */
3315 rc = ipw_load_ucode(priv, ucode->data + sizeof(struct fw_header), 3297 rc = ipw_load_ucode(priv, ucode_img, fw->ucode_size);
3316 ucode->size - sizeof(struct fw_header));
3317 if (rc < 0) { 3298 if (rc < 0) {
3318 IPW_ERROR("Unable to load ucode: %d\n", rc); 3299 IPW_ERROR("Unable to load ucode: %d\n", rc);
3319 goto error; 3300 goto error;
@@ -3322,20 +3303,8 @@ static int ipw_load(struct ipw_priv *priv)
3322 /* stop nic */ 3303 /* stop nic */
3323 ipw_stop_nic(priv); 3304 ipw_stop_nic(priv);
3324 3305
3325#ifdef CONFIG_PM
3326 if (!fw_loaded) {
3327#endif
3328 rc = ipw_get_fw(priv, &firmware, fw_name);
3329 if (rc < 0)
3330 goto error;
3331#ifdef CONFIG_PM
3332 }
3333#endif
3334
3335 /* DMA bss firmware into the device */ 3306 /* DMA bss firmware into the device */
3336 rc = ipw_load_firmware(priv, firmware->data + 3307 rc = ipw_load_firmware(priv, fw_img, fw->fw_size);
3337 sizeof(struct fw_header),
3338 firmware->size - sizeof(struct fw_header));
3339 if (rc < 0) { 3308 if (rc < 0) {
3340 IPW_ERROR("Unable to load firmware: %d\n", rc); 3309 IPW_ERROR("Unable to load firmware: %d\n", rc);
3341 goto error; 3310 goto error;
@@ -3400,9 +3369,7 @@ static int ipw_load(struct ipw_priv *priv)
3400 ipw_write32(priv, IPW_INTA_RW, IPW_INTA_MASK_ALL); 3369 ipw_write32(priv, IPW_INTA_RW, IPW_INTA_MASK_ALL);
3401 3370
3402#ifndef CONFIG_PM 3371#ifndef CONFIG_PM
3403 release_firmware(bootfw); 3372 release_firmware(raw);
3404 release_firmware(ucode);
3405 release_firmware(firmware);
3406#endif 3373#endif
3407 return 0; 3374 return 0;
3408 3375
@@ -3412,15 +3379,11 @@ static int ipw_load(struct ipw_priv *priv)
3412 priv->rxq = NULL; 3379 priv->rxq = NULL;
3413 } 3380 }
3414 ipw_tx_queue_free(priv); 3381 ipw_tx_queue_free(priv);
3415 if (bootfw) 3382 if (raw)
3416 release_firmware(bootfw); 3383 release_firmware(raw);
3417 if (ucode)
3418 release_firmware(ucode);
3419 if (firmware)
3420 release_firmware(firmware);
3421#ifdef CONFIG_PM 3384#ifdef CONFIG_PM
3422 fw_loaded = 0; 3385 fw_loaded = 0;
3423 bootfw = ucode = firmware = NULL; 3386 raw = NULL;
3424#endif 3387#endif
3425 3388
3426 return rc; 3389 return rc;