diff options
-rw-r--r-- | drivers/net/Kconfig | 2 | ||||
-rw-r--r-- | drivers/net/bnx2.c | 159 | ||||
-rw-r--r-- | drivers/net/bnx2.h | 3 |
3 files changed, 152 insertions, 12 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index bdaaad8f2123..1fb0a195b610 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
@@ -2163,6 +2163,8 @@ config TIGON3 | |||
2163 | config BNX2 | 2163 | config BNX2 |
2164 | tristate "Broadcom NetXtremeII support" | 2164 | tristate "Broadcom NetXtremeII support" |
2165 | depends on PCI | 2165 | depends on PCI |
2166 | select CRC32 | ||
2167 | select ZLIB_INFLATE | ||
2166 | help | 2168 | help |
2167 | This driver supports Broadcom NetXtremeII gigabit Ethernet cards. | 2169 | This driver supports Broadcom NetXtremeII gigabit Ethernet cards. |
2168 | 2170 | ||
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 | |||
2089 | static int | ||
2090 | bnx2_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 | |||
2104 | gunzip_nomem3: | ||
2105 | kfree(bp->strm); | ||
2106 | bp->strm = NULL; | ||
2107 | |||
2108 | gunzip_nomem2: | ||
2109 | vfree(bp->gunzip_buf); | ||
2110 | bp->gunzip_buf = NULL; | ||
2111 | |||
2112 | gunzip_nomem1: | ||
2113 | printk(KERN_ERR PFX "%s: Cannot allocate firmware buffer for " | ||
2114 | "uncompression.\n", bp->dev->name); | ||
2115 | return -ENOMEM; | ||
2116 | } | ||
2117 | |||
2118 | static void | ||
2119 | bnx2_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 | |||
2132 | static int | ||
2133 | bnx2_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 | |||
2086 | static void | 2173 | static void |
2087 | load_rv2p_fw(struct bnx2 *bp, u32 *rv2p_code, u32 rv2p_code_len, | 2174 | load_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 | ||
2193 | static void | 2280 | static int |
2194 | bnx2_init_cpus(struct bnx2 *bp) | 2281 | bnx2_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 | ||
2515 | init_cpu_err: | ||
2516 | bnx2_gunzip_end(bp); | ||
2517 | return rc; | ||
2387 | } | 2518 | } |
2388 | 2519 | ||
2389 | static int | 2520 | static 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; |
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index ea1ab06046d7..cc36b75b2b39 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h | |||
@@ -4051,6 +4051,9 @@ struct bnx2 { | |||
4051 | u32 flash_size; | 4051 | u32 flash_size; |
4052 | 4052 | ||
4053 | int status_stats_size; | 4053 | int status_stats_size; |
4054 | |||
4055 | struct z_stream_s *strm; | ||
4056 | void *gunzip_buf; | ||
4054 | }; | 4057 | }; |
4055 | 4058 | ||
4056 | static u32 bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset); | 4059 | static u32 bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset); |