aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bnx2.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/bnx2.c')
-rw-r--r--drivers/net/bnx2.c159
1 files changed, 147 insertions, 12 deletions
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 031455a8d1dd..c6510e17551b 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -49,6 +49,7 @@
49#include <linux/crc32.h> 49#include <linux/crc32.h>
50#include <linux/prefetch.h> 50#include <linux/prefetch.h>
51#include <linux/cache.h> 51#include <linux/cache.h>
52#include <linux/zlib.h>
52 53
53#include "bnx2.h" 54#include "bnx2.h"
54#include "bnx2_fw.h" 55#include "bnx2_fw.h"
@@ -2083,6 +2084,92 @@ bnx2_set_rx_mode(struct net_device *dev)
2083 spin_unlock_bh(&bp->phy_lock); 2084 spin_unlock_bh(&bp->phy_lock);
2084} 2085}
2085 2086
2087#define FW_BUF_SIZE 0x8000
2088
2089static int
2090bnx2_gunzip_init(struct bnx2 *bp)
2091{
2092 if ((bp->gunzip_buf = vmalloc(FW_BUF_SIZE)) == NULL)
2093 goto gunzip_nomem1;
2094
2095 if ((bp->strm = kmalloc(sizeof(*bp->strm), GFP_KERNEL)) == NULL)
2096 goto gunzip_nomem2;
2097
2098 bp->strm->workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL);
2099 if (bp->strm->workspace == NULL)
2100 goto gunzip_nomem3;
2101
2102 return 0;
2103
2104gunzip_nomem3:
2105 kfree(bp->strm);
2106 bp->strm = NULL;
2107
2108gunzip_nomem2:
2109 vfree(bp->gunzip_buf);
2110 bp->gunzip_buf = NULL;
2111
2112gunzip_nomem1:
2113 printk(KERN_ERR PFX "%s: Cannot allocate firmware buffer for "
2114 "uncompression.\n", bp->dev->name);
2115 return -ENOMEM;
2116}
2117
2118static void
2119bnx2_gunzip_end(struct bnx2 *bp)
2120{
2121 kfree(bp->strm->workspace);
2122
2123 kfree(bp->strm);
2124 bp->strm = NULL;
2125
2126 if (bp->gunzip_buf) {
2127 vfree(bp->gunzip_buf);
2128 bp->gunzip_buf = NULL;
2129 }
2130}
2131
2132static int
2133bnx2_gunzip(struct bnx2 *bp, u8 *zbuf, int len, void **outbuf, int *outlen)
2134{
2135 int n, rc;
2136
2137 /* check gzip header */
2138 if ((zbuf[0] != 0x1f) || (zbuf[1] != 0x8b) || (zbuf[2] != Z_DEFLATED))
2139 return -EINVAL;
2140
2141 n = 10;
2142
2143#define FNAME 0x8
2144 if (zbuf[3] & FNAME)
2145 while ((zbuf[n++] != 0) && (n < len));
2146
2147 bp->strm->next_in = zbuf + n;
2148 bp->strm->avail_in = len - n;
2149 bp->strm->next_out = bp->gunzip_buf;
2150 bp->strm->avail_out = FW_BUF_SIZE;
2151
2152 rc = zlib_inflateInit2(bp->strm, -MAX_WBITS);
2153 if (rc != Z_OK)
2154 return rc;
2155
2156 rc = zlib_inflate(bp->strm, Z_FINISH);
2157
2158 *outlen = FW_BUF_SIZE - bp->strm->avail_out;
2159 *outbuf = bp->gunzip_buf;
2160
2161 if ((rc != Z_OK) && (rc != Z_STREAM_END))
2162 printk(KERN_ERR PFX "%s: Firmware decompression error: %s\n",
2163 bp->dev->name, bp->strm->msg);
2164
2165 zlib_inflateEnd(bp->strm);
2166
2167 if (rc == Z_STREAM_END)
2168 return 0;
2169
2170 return rc;
2171}
2172
2086static void 2173static void
2087load_rv2p_fw(struct bnx2 *bp, u32 *rv2p_code, u32 rv2p_code_len, 2174load_rv2p_fw(struct bnx2 *bp, u32 *rv2p_code, u32 rv2p_code_len,
2088 u32 rv2p_proc) 2175 u32 rv2p_proc)
@@ -2092,9 +2179,9 @@ load_rv2p_fw(struct bnx2 *bp, u32 *rv2p_code, u32 rv2p_code_len,
2092 2179
2093 2180
2094 for (i = 0; i < rv2p_code_len; i += 8) { 2181 for (i = 0; i < rv2p_code_len; i += 8) {
2095 REG_WR(bp, BNX2_RV2P_INSTR_HIGH, *rv2p_code); 2182 REG_WR(bp, BNX2_RV2P_INSTR_HIGH, cpu_to_le32(*rv2p_code));
2096 rv2p_code++; 2183 rv2p_code++;
2097 REG_WR(bp, BNX2_RV2P_INSTR_LOW, *rv2p_code); 2184 REG_WR(bp, BNX2_RV2P_INSTR_LOW, cpu_to_le32(*rv2p_code));
2098 rv2p_code++; 2185 rv2p_code++;
2099 2186
2100 if (rv2p_proc == RV2P_PROC1) { 2187 if (rv2p_proc == RV2P_PROC1) {
@@ -2134,7 +2221,7 @@ load_cpu_fw(struct bnx2 *bp, struct cpu_reg *cpu_reg, struct fw_info *fw)
2134 int j; 2221 int j;
2135 2222
2136 for (j = 0; j < (fw->text_len / 4); j++, offset += 4) { 2223 for (j = 0; j < (fw->text_len / 4); j++, offset += 4) {
2137 REG_WR_IND(bp, offset, fw->text[j]); 2224 REG_WR_IND(bp, offset, cpu_to_le32(fw->text[j]));
2138 } 2225 }
2139 } 2226 }
2140 2227
@@ -2190,15 +2277,32 @@ load_cpu_fw(struct bnx2 *bp, struct cpu_reg *cpu_reg, struct fw_info *fw)
2190 REG_WR_IND(bp, cpu_reg->mode, val); 2277 REG_WR_IND(bp, cpu_reg->mode, val);
2191} 2278}
2192 2279
2193static void 2280static int
2194bnx2_init_cpus(struct bnx2 *bp) 2281bnx2_init_cpus(struct bnx2 *bp)
2195{ 2282{
2196 struct cpu_reg cpu_reg; 2283 struct cpu_reg cpu_reg;
2197 struct fw_info fw; 2284 struct fw_info fw;
2285 int rc = 0;
2286 void *text;
2287 u32 text_len;
2288
2289 if ((rc = bnx2_gunzip_init(bp)) != 0)
2290 return rc;
2198 2291
2199 /* Initialize the RV2P processor. */ 2292 /* Initialize the RV2P processor. */
2200 load_rv2p_fw(bp, bnx2_rv2p_proc1, sizeof(bnx2_rv2p_proc1), RV2P_PROC1); 2293 rc = bnx2_gunzip(bp, bnx2_rv2p_proc1, sizeof(bnx2_rv2p_proc1), &text,
2201 load_rv2p_fw(bp, bnx2_rv2p_proc2, sizeof(bnx2_rv2p_proc2), RV2P_PROC2); 2294 &text_len);
2295 if (rc)
2296 goto init_cpu_err;
2297
2298 load_rv2p_fw(bp, text, text_len, RV2P_PROC1);
2299
2300 rc = bnx2_gunzip(bp, bnx2_rv2p_proc2, sizeof(bnx2_rv2p_proc2), &text,
2301 &text_len);
2302 if (rc)
2303 goto init_cpu_err;
2304
2305 load_rv2p_fw(bp, text, text_len, RV2P_PROC2);
2202 2306
2203 /* Initialize the RX Processor. */ 2307 /* Initialize the RX Processor. */
2204 cpu_reg.mode = BNX2_RXP_CPU_MODE; 2308 cpu_reg.mode = BNX2_RXP_CPU_MODE;
@@ -2222,7 +2326,13 @@ bnx2_init_cpus(struct bnx2 *bp)
2222 fw.text_addr = bnx2_RXP_b06FwTextAddr; 2326 fw.text_addr = bnx2_RXP_b06FwTextAddr;
2223 fw.text_len = bnx2_RXP_b06FwTextLen; 2327 fw.text_len = bnx2_RXP_b06FwTextLen;
2224 fw.text_index = 0; 2328 fw.text_index = 0;
2225 fw.text = bnx2_RXP_b06FwText; 2329
2330 rc = bnx2_gunzip(bp, bnx2_RXP_b06FwText, sizeof(bnx2_RXP_b06FwText),
2331 &text, &text_len);
2332 if (rc)
2333 goto init_cpu_err;
2334
2335 fw.text = text;
2226 2336
2227 fw.data_addr = bnx2_RXP_b06FwDataAddr; 2337 fw.data_addr = bnx2_RXP_b06FwDataAddr;
2228 fw.data_len = bnx2_RXP_b06FwDataLen; 2338 fw.data_len = bnx2_RXP_b06FwDataLen;
@@ -2268,7 +2378,13 @@ bnx2_init_cpus(struct bnx2 *bp)
2268 fw.text_addr = bnx2_TXP_b06FwTextAddr; 2378 fw.text_addr = bnx2_TXP_b06FwTextAddr;
2269 fw.text_len = bnx2_TXP_b06FwTextLen; 2379 fw.text_len = bnx2_TXP_b06FwTextLen;
2270 fw.text_index = 0; 2380 fw.text_index = 0;
2271 fw.text = bnx2_TXP_b06FwText; 2381
2382 rc = bnx2_gunzip(bp, bnx2_TXP_b06FwText, sizeof(bnx2_TXP_b06FwText),
2383 &text, &text_len);
2384 if (rc)
2385 goto init_cpu_err;
2386
2387 fw.text = text;
2272 2388
2273 fw.data_addr = bnx2_TXP_b06FwDataAddr; 2389 fw.data_addr = bnx2_TXP_b06FwDataAddr;
2274 fw.data_len = bnx2_TXP_b06FwDataLen; 2390 fw.data_len = bnx2_TXP_b06FwDataLen;
@@ -2314,7 +2430,13 @@ bnx2_init_cpus(struct bnx2 *bp)
2314 fw.text_addr = bnx2_TPAT_b06FwTextAddr; 2430 fw.text_addr = bnx2_TPAT_b06FwTextAddr;
2315 fw.text_len = bnx2_TPAT_b06FwTextLen; 2431 fw.text_len = bnx2_TPAT_b06FwTextLen;
2316 fw.text_index = 0; 2432 fw.text_index = 0;
2317 fw.text = bnx2_TPAT_b06FwText; 2433
2434 rc = bnx2_gunzip(bp, bnx2_TPAT_b06FwText, sizeof(bnx2_TPAT_b06FwText),
2435 &text, &text_len);
2436 if (rc)
2437 goto init_cpu_err;
2438
2439 fw.text = text;
2318 2440
2319 fw.data_addr = bnx2_TPAT_b06FwDataAddr; 2441 fw.data_addr = bnx2_TPAT_b06FwDataAddr;
2320 fw.data_len = bnx2_TPAT_b06FwDataLen; 2442 fw.data_len = bnx2_TPAT_b06FwDataLen;
@@ -2360,7 +2482,13 @@ bnx2_init_cpus(struct bnx2 *bp)
2360 fw.text_addr = bnx2_COM_b06FwTextAddr; 2482 fw.text_addr = bnx2_COM_b06FwTextAddr;
2361 fw.text_len = bnx2_COM_b06FwTextLen; 2483 fw.text_len = bnx2_COM_b06FwTextLen;
2362 fw.text_index = 0; 2484 fw.text_index = 0;
2363 fw.text = bnx2_COM_b06FwText; 2485
2486 rc = bnx2_gunzip(bp, bnx2_COM_b06FwText, sizeof(bnx2_COM_b06FwText),
2487 &text, &text_len);
2488 if (rc)
2489 goto init_cpu_err;
2490
2491 fw.text = text;
2364 2492
2365 fw.data_addr = bnx2_COM_b06FwDataAddr; 2493 fw.data_addr = bnx2_COM_b06FwDataAddr;
2366 fw.data_len = bnx2_COM_b06FwDataLen; 2494 fw.data_len = bnx2_COM_b06FwDataLen;
@@ -2384,6 +2512,9 @@ bnx2_init_cpus(struct bnx2 *bp)
2384 2512
2385 load_cpu_fw(bp, &cpu_reg, &fw); 2513 load_cpu_fw(bp, &cpu_reg, &fw);
2386 2514
2515init_cpu_err:
2516 bnx2_gunzip_end(bp);
2517 return rc;
2387} 2518}
2388 2519
2389static int 2520static int
@@ -3256,7 +3387,9 @@ bnx2_init_chip(struct bnx2 *bp)
3256 * context block must have already been enabled. */ 3387 * context block must have already been enabled. */
3257 bnx2_init_context(bp); 3388 bnx2_init_context(bp);
3258 3389
3259 bnx2_init_cpus(bp); 3390 if ((rc = bnx2_init_cpus(bp)) != 0)
3391 return rc;
3392
3260 bnx2_init_nvram(bp); 3393 bnx2_init_nvram(bp);
3261 3394
3262 bnx2_set_mac_addr(bp); 3395 bnx2_set_mac_addr(bp);
@@ -3556,7 +3689,9 @@ bnx2_reset_nic(struct bnx2 *bp, u32 reset_code)
3556 if (rc) 3689 if (rc)
3557 return rc; 3690 return rc;
3558 3691
3559 bnx2_init_chip(bp); 3692 if ((rc = bnx2_init_chip(bp)) != 0)
3693 return rc;
3694
3560 bnx2_init_tx_ring(bp); 3695 bnx2_init_tx_ring(bp);
3561 bnx2_init_rx_ring(bp); 3696 bnx2_init_rx_ring(bp);
3562 return 0; 3697 return 0;