diff options
| author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-12 03:26:34 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-12 03:26:34 -0400 |
| commit | cbd09dbbb62096c1da627eca865f988d2ed0a84e (patch) | |
| tree | 9601e631cee6651c638cc7b4d2d9b7cf20b6b485 | |
| parent | d81fec0f97cce4aea36a89340af247523c1263a0 (diff) | |
| parent | d4faaecbcc6d9ea4f7c05f6de6af98e2336a4afb (diff) | |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
* 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6:
[ZLIB]: Fix external builds of zlib_inflate code.
[TG3]: Fix APE induced regression
[SKY2]: version 1.19
[SKY2]: use netdevice stats struct
[SKY2]: fiber advertise bits initialization (trivial)
[SKY2]: fix power settings on Yukon XL
[SKY2]: ethtool register reserved area blackout
| -rw-r--r-- | drivers/net/sky2.c | 114 | ||||
| -rw-r--r-- | drivers/net/sky2.h | 2 | ||||
| -rw-r--r-- | drivers/net/tg3.c | 7 | ||||
| -rw-r--r-- | lib/zlib_inflate/Makefile | 2 | ||||
| -rw-r--r-- | lib/zlib_inflate/inflate.c | 47 | ||||
| -rw-r--r-- | lib/zlib_inflate/infutil.c | 49 |
6 files changed, 129 insertions, 92 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 0a3203465415..68f728f0b600 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
| @@ -52,7 +52,7 @@ | |||
| 52 | #include "sky2.h" | 52 | #include "sky2.h" |
| 53 | 53 | ||
| 54 | #define DRV_NAME "sky2" | 54 | #define DRV_NAME "sky2" |
| 55 | #define DRV_VERSION "1.18" | 55 | #define DRV_VERSION "1.19" |
| 56 | #define PFX DRV_NAME " " | 56 | #define PFX DRV_NAME " " |
| 57 | 57 | ||
| 58 | /* | 58 | /* |
| @@ -296,10 +296,10 @@ static const u16 copper_fc_adv[] = { | |||
| 296 | 296 | ||
| 297 | /* flow control to advertise bits when using 1000BaseX */ | 297 | /* flow control to advertise bits when using 1000BaseX */ |
| 298 | static const u16 fiber_fc_adv[] = { | 298 | static const u16 fiber_fc_adv[] = { |
| 299 | [FC_BOTH] = PHY_M_P_BOTH_MD_X, | 299 | [FC_NONE] = PHY_M_P_NO_PAUSE_X, |
| 300 | [FC_TX] = PHY_M_P_ASYM_MD_X, | 300 | [FC_TX] = PHY_M_P_ASYM_MD_X, |
| 301 | [FC_RX] = PHY_M_P_SYM_MD_X, | 301 | [FC_RX] = PHY_M_P_SYM_MD_X, |
| 302 | [FC_NONE] = PHY_M_P_NO_PAUSE_X, | 302 | [FC_BOTH] = PHY_M_P_BOTH_MD_X, |
| 303 | }; | 303 | }; |
| 304 | 304 | ||
| 305 | /* flow control to GMA disable bits */ | 305 | /* flow control to GMA disable bits */ |
| @@ -606,20 +606,19 @@ static void sky2_phy_power(struct sky2_hw *hw, unsigned port, int onoff) | |||
| 606 | { | 606 | { |
| 607 | struct pci_dev *pdev = hw->pdev; | 607 | struct pci_dev *pdev = hw->pdev; |
| 608 | u32 reg1; | 608 | u32 reg1; |
| 609 | static const u32 phy_power[] | 609 | static const u32 phy_power[] = { PCI_Y2_PHY1_POWD, PCI_Y2_PHY2_POWD }; |
| 610 | = { PCI_Y2_PHY1_POWD, PCI_Y2_PHY2_POWD }; | 610 | static const u32 coma_mode[] = { PCI_Y2_PHY1_COMA, PCI_Y2_PHY2_COMA }; |
| 611 | |||
| 612 | /* looks like this XL is back asswards .. */ | ||
| 613 | if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1) | ||
| 614 | onoff = !onoff; | ||
| 615 | 611 | ||
| 616 | pci_read_config_dword(pdev, PCI_DEV_REG1, ®1); | 612 | pci_read_config_dword(pdev, PCI_DEV_REG1, ®1); |
| 613 | /* Turn on/off phy power saving */ | ||
| 617 | if (onoff) | 614 | if (onoff) |
| 618 | /* Turn off phy power saving */ | ||
| 619 | reg1 &= ~phy_power[port]; | 615 | reg1 &= ~phy_power[port]; |
| 620 | else | 616 | else |
| 621 | reg1 |= phy_power[port]; | 617 | reg1 |= phy_power[port]; |
| 622 | 618 | ||
| 619 | if (onoff && hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1) | ||
| 620 | reg1 |= coma_mode[port]; | ||
| 621 | |||
| 623 | pci_write_config_dword(pdev, PCI_DEV_REG1, reg1); | 622 | pci_write_config_dword(pdev, PCI_DEV_REG1, reg1); |
| 624 | pci_read_config_dword(pdev, PCI_DEV_REG1, ®1); | 623 | pci_read_config_dword(pdev, PCI_DEV_REG1, ®1); |
| 625 | 624 | ||
| @@ -1636,8 +1635,8 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done) | |||
| 1636 | printk(KERN_DEBUG "%s: tx done %u\n", | 1635 | printk(KERN_DEBUG "%s: tx done %u\n", |
| 1637 | dev->name, idx); | 1636 | dev->name, idx); |
| 1638 | 1637 | ||
| 1639 | sky2->net_stats.tx_packets++; | 1638 | dev->stats.tx_packets++; |
| 1640 | sky2->net_stats.tx_bytes += re->skb->len; | 1639 | dev->stats.tx_bytes += re->skb->len; |
| 1641 | 1640 | ||
| 1642 | dev_kfree_skb_any(re->skb); | 1641 | dev_kfree_skb_any(re->skb); |
| 1643 | sky2->tx_next = RING_NEXT(idx, TX_RING_SIZE); | 1642 | sky2->tx_next = RING_NEXT(idx, TX_RING_SIZE); |
| @@ -2205,16 +2204,16 @@ resubmit: | |||
| 2205 | len_error: | 2204 | len_error: |
| 2206 | /* Truncation of overlength packets | 2205 | /* Truncation of overlength packets |
| 2207 | causes PHY length to not match MAC length */ | 2206 | causes PHY length to not match MAC length */ |
| 2208 | ++sky2->net_stats.rx_length_errors; | 2207 | ++dev->stats.rx_length_errors; |
| 2209 | if (netif_msg_rx_err(sky2) && net_ratelimit()) | 2208 | if (netif_msg_rx_err(sky2) && net_ratelimit()) |
| 2210 | pr_info(PFX "%s: rx length error: status %#x length %d\n", | 2209 | pr_info(PFX "%s: rx length error: status %#x length %d\n", |
| 2211 | dev->name, status, length); | 2210 | dev->name, status, length); |
| 2212 | goto resubmit; | 2211 | goto resubmit; |
| 2213 | 2212 | ||
| 2214 | error: | 2213 | error: |
| 2215 | ++sky2->net_stats.rx_errors; | 2214 | ++dev->stats.rx_errors; |
| 2216 | if (status & GMR_FS_RX_FF_OV) { | 2215 | if (status & GMR_FS_RX_FF_OV) { |
| 2217 | sky2->net_stats.rx_over_errors++; | 2216 | dev->stats.rx_over_errors++; |
| 2218 | goto resubmit; | 2217 | goto resubmit; |
| 2219 | } | 2218 | } |
| 2220 | 2219 | ||
| @@ -2223,11 +2222,11 @@ error: | |||
| 2223 | dev->name, status, length); | 2222 | dev->name, status, length); |
| 2224 | 2223 | ||
| 2225 | if (status & (GMR_FS_LONG_ERR | GMR_FS_UN_SIZE)) | 2224 | if (status & (GMR_FS_LONG_ERR | GMR_FS_UN_SIZE)) |
| 2226 | sky2->net_stats.rx_length_errors++; | 2225 | dev->stats.rx_length_errors++; |
| 2227 | if (status & GMR_FS_FRAGMENT) | 2226 | if (status & GMR_FS_FRAGMENT) |
| 2228 | sky2->net_stats.rx_frame_errors++; | 2227 | dev->stats.rx_frame_errors++; |
| 2229 | if (status & GMR_FS_CRC_ERR) | 2228 | if (status & GMR_FS_CRC_ERR) |
| 2230 | sky2->net_stats.rx_crc_errors++; | 2229 | dev->stats.rx_crc_errors++; |
| 2231 | 2230 | ||
| 2232 | goto resubmit; | 2231 | goto resubmit; |
| 2233 | } | 2232 | } |
| @@ -2272,7 +2271,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx) | |||
| 2272 | ++rx[port]; | 2271 | ++rx[port]; |
| 2273 | skb = sky2_receive(dev, length, status); | 2272 | skb = sky2_receive(dev, length, status); |
| 2274 | if (unlikely(!skb)) { | 2273 | if (unlikely(!skb)) { |
| 2275 | sky2->net_stats.rx_dropped++; | 2274 | dev->stats.rx_dropped++; |
| 2276 | break; | 2275 | break; |
| 2277 | } | 2276 | } |
| 2278 | 2277 | ||
| @@ -2287,8 +2286,8 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx) | |||
| 2287 | } | 2286 | } |
| 2288 | 2287 | ||
| 2289 | skb->protocol = eth_type_trans(skb, dev); | 2288 | skb->protocol = eth_type_trans(skb, dev); |
| 2290 | sky2->net_stats.rx_packets++; | 2289 | dev->stats.rx_packets++; |
| 2291 | sky2->net_stats.rx_bytes += skb->len; | 2290 | dev->stats.rx_bytes += skb->len; |
| 2292 | dev->last_rx = jiffies; | 2291 | dev->last_rx = jiffies; |
| 2293 | 2292 | ||
| 2294 | #ifdef SKY2_VLAN_TAG_USED | 2293 | #ifdef SKY2_VLAN_TAG_USED |
| @@ -2479,12 +2478,12 @@ static void sky2_mac_intr(struct sky2_hw *hw, unsigned port) | |||
| 2479 | gma_read16(hw, port, GM_TX_IRQ_SRC); | 2478 | gma_read16(hw, port, GM_TX_IRQ_SRC); |
| 2480 | 2479 | ||
| 2481 | if (status & GM_IS_RX_FF_OR) { | 2480 | if (status & GM_IS_RX_FF_OR) { |
| 2482 | ++sky2->net_stats.rx_fifo_errors; | 2481 | ++dev->stats.rx_fifo_errors; |
| 2483 | sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_CLI_RX_FO); | 2482 | sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_CLI_RX_FO); |
| 2484 | } | 2483 | } |
| 2485 | 2484 | ||
| 2486 | if (status & GM_IS_TX_FF_UR) { | 2485 | if (status & GM_IS_TX_FF_UR) { |
| 2487 | ++sky2->net_stats.tx_fifo_errors; | 2486 | ++dev->stats.tx_fifo_errors; |
| 2488 | sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_CLI_TX_FU); | 2487 | sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_CLI_TX_FU); |
| 2489 | } | 2488 | } |
| 2490 | } | 2489 | } |
| @@ -3223,12 +3222,6 @@ static void sky2_get_strings(struct net_device *dev, u32 stringset, u8 * data) | |||
| 3223 | } | 3222 | } |
| 3224 | } | 3223 | } |
| 3225 | 3224 | ||
| 3226 | static struct net_device_stats *sky2_get_stats(struct net_device *dev) | ||
| 3227 | { | ||
| 3228 | struct sky2_port *sky2 = netdev_priv(dev); | ||
| 3229 | return &sky2->net_stats; | ||
| 3230 | } | ||
| 3231 | |||
| 3232 | static int sky2_set_mac_address(struct net_device *dev, void *p) | 3225 | static int sky2_set_mac_address(struct net_device *dev, void *p) |
| 3233 | { | 3226 | { |
| 3234 | struct sky2_port *sky2 = netdev_priv(dev); | 3227 | struct sky2_port *sky2 = netdev_priv(dev); |
| @@ -3569,20 +3562,64 @@ static void sky2_get_regs(struct net_device *dev, struct ethtool_regs *regs, | |||
| 3569 | { | 3562 | { |
| 3570 | const struct sky2_port *sky2 = netdev_priv(dev); | 3563 | const struct sky2_port *sky2 = netdev_priv(dev); |
| 3571 | const void __iomem *io = sky2->hw->regs; | 3564 | const void __iomem *io = sky2->hw->regs; |
| 3565 | unsigned int b; | ||
| 3572 | 3566 | ||
| 3573 | regs->version = 1; | 3567 | regs->version = 1; |
| 3574 | memset(p, 0, regs->len); | ||
| 3575 | |||
| 3576 | memcpy_fromio(p, io, B3_RAM_ADDR); | ||
| 3577 | 3568 | ||
| 3578 | /* skip diagnostic ram region */ | 3569 | for (b = 0; b < 128; b++) { |
| 3579 | memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1, 0x2000 - B3_RI_WTO_R1); | 3570 | /* This complicated switch statement is to make sure and |
| 3571 | * only access regions that are unreserved. | ||
| 3572 | * Some blocks are only valid on dual port cards. | ||
| 3573 | * and block 3 has some special diagnostic registers that | ||
| 3574 | * are poison. | ||
| 3575 | */ | ||
| 3576 | switch (b) { | ||
| 3577 | case 3: | ||
| 3578 | /* skip diagnostic ram region */ | ||
| 3579 | memcpy_fromio(p + 0x10, io + 0x10, 128 - 0x10); | ||
| 3580 | break; | ||
| 3580 | 3581 | ||
| 3581 | /* copy GMAC registers */ | 3582 | /* dual port cards only */ |
| 3582 | memcpy_fromio(p + BASE_GMAC_1, io + BASE_GMAC_1, 0x1000); | 3583 | case 5: /* Tx Arbiter 2 */ |
| 3583 | if (sky2->hw->ports > 1) | 3584 | case 9: /* RX2 */ |
| 3584 | memcpy_fromio(p + BASE_GMAC_2, io + BASE_GMAC_2, 0x1000); | 3585 | case 14 ... 15: /* TX2 */ |
| 3586 | case 17: case 19: /* Ram Buffer 2 */ | ||
| 3587 | case 22 ... 23: /* Tx Ram Buffer 2 */ | ||
| 3588 | case 25: /* Rx MAC Fifo 1 */ | ||
| 3589 | case 27: /* Tx MAC Fifo 2 */ | ||
| 3590 | case 31: /* GPHY 2 */ | ||
| 3591 | case 40 ... 47: /* Pattern Ram 2 */ | ||
| 3592 | case 52: case 54: /* TCP Segmentation 2 */ | ||
| 3593 | case 112 ... 116: /* GMAC 2 */ | ||
| 3594 | if (sky2->hw->ports == 1) | ||
| 3595 | goto reserved; | ||
| 3596 | /* fall through */ | ||
| 3597 | case 0: /* Control */ | ||
| 3598 | case 2: /* Mac address */ | ||
| 3599 | case 4: /* Tx Arbiter 1 */ | ||
| 3600 | case 7: /* PCI express reg */ | ||
| 3601 | case 8: /* RX1 */ | ||
| 3602 | case 12 ... 13: /* TX1 */ | ||
| 3603 | case 16: case 18:/* Rx Ram Buffer 1 */ | ||
| 3604 | case 20 ... 21: /* Tx Ram Buffer 1 */ | ||
| 3605 | case 24: /* Rx MAC Fifo 1 */ | ||
| 3606 | case 26: /* Tx MAC Fifo 1 */ | ||
| 3607 | case 28 ... 29: /* Descriptor and status unit */ | ||
| 3608 | case 30: /* GPHY 1*/ | ||
| 3609 | case 32 ... 39: /* Pattern Ram 1 */ | ||
| 3610 | case 48: case 50: /* TCP Segmentation 1 */ | ||
| 3611 | case 56 ... 60: /* PCI space */ | ||
| 3612 | case 80 ... 84: /* GMAC 1 */ | ||
| 3613 | memcpy_fromio(p, io, 128); | ||
| 3614 | break; | ||
| 3615 | default: | ||
| 3616 | reserved: | ||
| 3617 | memset(p, 0, 128); | ||
| 3618 | } | ||
| 3585 | 3619 | ||
| 3620 | p += 128; | ||
| 3621 | io += 128; | ||
| 3622 | } | ||
| 3586 | } | 3623 | } |
| 3587 | 3624 | ||
| 3588 | /* In order to do Jumbo packets on these chips, need to turn off the | 3625 | /* In order to do Jumbo packets on these chips, need to turn off the |
| @@ -3934,7 +3971,6 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, | |||
| 3934 | dev->stop = sky2_down; | 3971 | dev->stop = sky2_down; |
| 3935 | dev->do_ioctl = sky2_ioctl; | 3972 | dev->do_ioctl = sky2_ioctl; |
| 3936 | dev->hard_start_xmit = sky2_xmit_frame; | 3973 | dev->hard_start_xmit = sky2_xmit_frame; |
| 3937 | dev->get_stats = sky2_get_stats; | ||
| 3938 | dev->set_multicast_list = sky2_set_multicast; | 3974 | dev->set_multicast_list = sky2_set_multicast; |
| 3939 | dev->set_mac_address = sky2_set_mac_address; | 3975 | dev->set_mac_address = sky2_set_mac_address; |
| 3940 | dev->change_mtu = sky2_change_mtu; | 3976 | dev->change_mtu = sky2_change_mtu; |
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index f4a3c2f403e5..49ee264064ab 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h | |||
| @@ -2031,8 +2031,6 @@ struct sky2_port { | |||
| 2031 | #ifdef CONFIG_SKY2_DEBUG | 2031 | #ifdef CONFIG_SKY2_DEBUG |
| 2032 | struct dentry *debugfs; | 2032 | struct dentry *debugfs; |
| 2033 | #endif | 2033 | #endif |
| 2034 | struct net_device_stats net_stats; | ||
| 2035 | |||
| 2036 | }; | 2034 | }; |
| 2037 | 2035 | ||
| 2038 | struct sky2_hw { | 2036 | struct sky2_hw { |
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index a402b5c01896..e795c33b982d 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
| @@ -6985,9 +6985,10 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) | |||
| 6985 | break; | 6985 | break; |
| 6986 | }; | 6986 | }; |
| 6987 | 6987 | ||
| 6988 | /* Write our heartbeat update interval to APE. */ | 6988 | if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) |
| 6989 | tg3_ape_write32(tp, TG3_APE_HOST_HEARTBEAT_INT_MS, | 6989 | /* Write our heartbeat update interval to APE. */ |
| 6990 | APE_HOST_HEARTBEAT_INT_DISABLE); | 6990 | tg3_ape_write32(tp, TG3_APE_HOST_HEARTBEAT_INT_MS, |
| 6991 | APE_HOST_HEARTBEAT_INT_DISABLE); | ||
| 6991 | 6992 | ||
| 6992 | tg3_write_sig_post_reset(tp, RESET_KIND_INIT); | 6993 | tg3_write_sig_post_reset(tp, RESET_KIND_INIT); |
| 6993 | 6994 | ||
diff --git a/lib/zlib_inflate/Makefile b/lib/zlib_inflate/Makefile index bf065482fa67..49f8ce5774d2 100644 --- a/lib/zlib_inflate/Makefile +++ b/lib/zlib_inflate/Makefile | |||
| @@ -15,5 +15,5 @@ | |||
| 15 | 15 | ||
| 16 | obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate.o | 16 | obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate.o |
| 17 | 17 | ||
| 18 | zlib_inflate-objs := inffast.o inflate.o \ | 18 | zlib_inflate-objs := inffast.o inflate.o infutil.o \ |
| 19 | inftrees.o inflate_syms.o | 19 | inftrees.o inflate_syms.o |
diff --git a/lib/zlib_inflate/inflate.c b/lib/zlib_inflate/inflate.c index 0ad1ebf00947..f5ce87b0800e 100644 --- a/lib/zlib_inflate/inflate.c +++ b/lib/zlib_inflate/inflate.c | |||
| @@ -916,50 +916,3 @@ int zlib_inflateIncomp(z_stream *z) | |||
| 916 | 916 | ||
| 917 | return Z_OK; | 917 | return Z_OK; |
| 918 | } | 918 | } |
| 919 | |||
| 920 | #include <linux/errno.h> | ||
| 921 | #include <linux/slab.h> | ||
| 922 | #include <linux/vmalloc.h> | ||
| 923 | |||
| 924 | /* Utility function: initialize zlib, unpack binary blob, clean up zlib, | ||
| 925 | * return len or negative error code. */ | ||
| 926 | int zlib_inflate_blob(void *gunzip_buf, unsigned sz, const void *buf, unsigned len) | ||
| 927 | { | ||
| 928 | const u8 *zbuf = buf; | ||
| 929 | struct z_stream_s *strm; | ||
| 930 | int rc; | ||
| 931 | |||
| 932 | rc = -ENOMEM; | ||
| 933 | strm = kmalloc(sizeof(*strm), GFP_KERNEL); | ||
| 934 | if (strm == NULL) | ||
| 935 | goto gunzip_nomem1; | ||
| 936 | strm->workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL); | ||
| 937 | if (strm->workspace == NULL) | ||
| 938 | goto gunzip_nomem2; | ||
| 939 | |||
| 940 | /* gzip header (1f,8b,08... 10 bytes total + possible asciz filename) | ||
| 941 | * expected to be stripped from input */ | ||
| 942 | |||
| 943 | strm->next_in = zbuf; | ||
| 944 | strm->avail_in = len; | ||
| 945 | strm->next_out = gunzip_buf; | ||
| 946 | strm->avail_out = sz; | ||
| 947 | |||
| 948 | rc = zlib_inflateInit2(strm, -MAX_WBITS); | ||
| 949 | if (rc == Z_OK) { | ||
| 950 | rc = zlib_inflate(strm, Z_FINISH); | ||
| 951 | /* after Z_FINISH, only Z_STREAM_END is "we unpacked it all" */ | ||
| 952 | if (rc == Z_STREAM_END) | ||
| 953 | rc = sz - strm->avail_out; | ||
| 954 | else | ||
| 955 | rc = -EINVAL; | ||
| 956 | zlib_inflateEnd(strm); | ||
| 957 | } else | ||
| 958 | rc = -EINVAL; | ||
| 959 | |||
| 960 | kfree(strm->workspace); | ||
| 961 | gunzip_nomem2: | ||
| 962 | kfree(strm); | ||
| 963 | gunzip_nomem1: | ||
| 964 | return rc; /* returns Z_OK (0) if successful */ | ||
| 965 | } | ||
diff --git a/lib/zlib_inflate/infutil.c b/lib/zlib_inflate/infutil.c new file mode 100644 index 000000000000..4824c2cc7a09 --- /dev/null +++ b/lib/zlib_inflate/infutil.c | |||
| @@ -0,0 +1,49 @@ | |||
| 1 | #include <linux/zutil.h> | ||
| 2 | #include <linux/errno.h> | ||
| 3 | #include <linux/slab.h> | ||
| 4 | #include <linux/vmalloc.h> | ||
| 5 | |||
| 6 | /* Utility function: initialize zlib, unpack binary blob, clean up zlib, | ||
| 7 | * return len or negative error code. | ||
| 8 | */ | ||
| 9 | int zlib_inflate_blob(void *gunzip_buf, unsigned int sz, | ||
| 10 | const void *buf, unsigned int len) | ||
| 11 | { | ||
| 12 | const u8 *zbuf = buf; | ||
| 13 | struct z_stream_s *strm; | ||
| 14 | int rc; | ||
| 15 | |||
| 16 | rc = -ENOMEM; | ||
| 17 | strm = kmalloc(sizeof(*strm), GFP_KERNEL); | ||
| 18 | if (strm == NULL) | ||
| 19 | goto gunzip_nomem1; | ||
| 20 | strm->workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL); | ||
| 21 | if (strm->workspace == NULL) | ||
| 22 | goto gunzip_nomem2; | ||
| 23 | |||
| 24 | /* gzip header (1f,8b,08... 10 bytes total + possible asciz filename) | ||
| 25 | * expected to be stripped from input | ||
| 26 | */ | ||
| 27 | strm->next_in = zbuf; | ||
| 28 | strm->avail_in = len; | ||
| 29 | strm->next_out = gunzip_buf; | ||
| 30 | strm->avail_out = sz; | ||
| 31 | |||
| 32 | rc = zlib_inflateInit2(strm, -MAX_WBITS); | ||
| 33 | if (rc == Z_OK) { | ||
| 34 | rc = zlib_inflate(strm, Z_FINISH); | ||
| 35 | /* after Z_FINISH, only Z_STREAM_END is "we unpacked it all" */ | ||
| 36 | if (rc == Z_STREAM_END) | ||
| 37 | rc = sz - strm->avail_out; | ||
| 38 | else | ||
| 39 | rc = -EINVAL; | ||
| 40 | zlib_inflateEnd(strm); | ||
| 41 | } else | ||
| 42 | rc = -EINVAL; | ||
| 43 | |||
| 44 | kfree(strm->workspace); | ||
| 45 | gunzip_nomem2: | ||
| 46 | kfree(strm); | ||
| 47 | gunzip_nomem1: | ||
| 48 | return rc; /* returns Z_OK (0) if successful */ | ||
| 49 | } | ||
