Skip to content

Commit

Permalink
cxgb4: use zlib deflate to compress firmware dump
Browse files Browse the repository at this point in the history
Use zlib deflate to compress firmware dump. Collect and compress
as much firmware dump as possible into a 32 MB buffer.

Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
Signed-off-by: Vishal Kulkarni <vishal@chelsio.com>
Signed-off-by: Ganesh Goudar <ganeshgr@chelsio.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Rahul Lakkireddy authored and David S. Miller committed Jan 19, 2018
1 parent 56cf263 commit 91c1953
Show file tree
Hide file tree
Showing 7 changed files with 169 additions and 3 deletions.
1 change: 1 addition & 0 deletions drivers/net/ethernet/chelsio/cxgb4/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ cxgb4-objs := cxgb4_main.o l2t.o smt.o t4_hw.o sge.o clip_tbl.o cxgb4_ethtool.o
cxgb4-$(CONFIG_CHELSIO_T4_DCB) += cxgb4_dcb.o
cxgb4-$(CONFIG_CHELSIO_T4_FCOE) += cxgb4_fcoe.o
cxgb4-$(CONFIG_DEBUG_FS) += cxgb4_debugfs.o
cxgb4-$(CONFIG_ZLIB_DEFLATE) += cudbg_zlib.o
1 change: 1 addition & 0 deletions drivers/net/ethernet/chelsio/cxgb4/cudbg_if.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ struct cudbg_init {
u8 compress_type; /* Type of compression to use */
void *compress_buff; /* Compression buffer */
u32 compress_buff_size; /* Compression buffer size */
void *workspace; /* Workspace for zlib */
};

static inline unsigned int cudbg_mbytes_to_bytes(unsigned int size)
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/chelsio/cxgb4/cudbg_lib_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ enum cudbg_dump_type {

enum cudbg_compression_type {
CUDBG_COMPRESSION_NONE = 1,
CUDBG_COMPRESSION_ZLIB,
};

struct cudbg_hdr {
Expand Down
81 changes: 81 additions & 0 deletions drivers/net/ethernet/chelsio/cxgb4/cudbg_zlib.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Copyright (C) 2018 Chelsio Communications. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* The full GNU General Public License is included in this distribution in
* the file called "COPYING".
*
*/

#include <linux/zlib.h>

#include "cxgb4.h"
#include "cudbg_if.h"
#include "cudbg_lib_common.h"
#include "cudbg_zlib.h"

static int cudbg_get_compress_hdr(struct cudbg_buffer *pdbg_buff,
struct cudbg_buffer *pin_buff)
{
if (pdbg_buff->offset + sizeof(struct cudbg_compress_hdr) >
pdbg_buff->size)
return CUDBG_STATUS_NO_MEM;

pin_buff->data = (char *)pdbg_buff->data + pdbg_buff->offset;
pin_buff->offset = 0;
pin_buff->size = sizeof(struct cudbg_compress_hdr);
pdbg_buff->offset += sizeof(struct cudbg_compress_hdr);
return 0;
}

int cudbg_compress_buff(struct cudbg_init *pdbg_init,
struct cudbg_buffer *pin_buff,
struct cudbg_buffer *pout_buff)
{
struct z_stream_s compress_stream = { 0 };
struct cudbg_buffer temp_buff = { 0 };
struct cudbg_compress_hdr *c_hdr;
int rc;

/* Write compression header to output buffer before compression */
rc = cudbg_get_compress_hdr(pout_buff, &temp_buff);
if (rc)
return rc;

c_hdr = (struct cudbg_compress_hdr *)temp_buff.data;
c_hdr->compress_id = CUDBG_ZLIB_COMPRESS_ID;

compress_stream.workspace = pdbg_init->workspace;
rc = zlib_deflateInit2(&compress_stream, Z_DEFAULT_COMPRESSION,
Z_DEFLATED, CUDBG_ZLIB_WIN_BITS,
CUDBG_ZLIB_MEM_LVL, Z_DEFAULT_STRATEGY);
if (rc != Z_OK)
return CUDBG_SYSTEM_ERROR;

compress_stream.next_in = pin_buff->data;
compress_stream.avail_in = pin_buff->size;
compress_stream.next_out = pout_buff->data + pout_buff->offset;
compress_stream.avail_out = pout_buff->size - pout_buff->offset;

rc = zlib_deflate(&compress_stream, Z_FINISH);
if (rc != Z_STREAM_END)
return CUDBG_SYSTEM_ERROR;

rc = zlib_deflateEnd(&compress_stream);
if (rc != Z_OK)
return CUDBG_SYSTEM_ERROR;

c_hdr->compress_size = compress_stream.total_out;
c_hdr->decompress_size = pin_buff->size;
pout_buff->offset += compress_stream.total_out;

return 0;
}
29 changes: 29 additions & 0 deletions drivers/net/ethernet/chelsio/cxgb4/cudbg_zlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,39 @@
#ifndef __CUDBG_ZLIB_H__
#define __CUDBG_ZLIB_H__

#include <linux/zlib.h>

#define CUDBG_ZLIB_COMPRESS_ID 17
#define CUDBG_ZLIB_WIN_BITS 12
#define CUDBG_ZLIB_MEM_LVL 4

struct cudbg_compress_hdr {
u32 compress_id;
u64 decompress_size;
u64 compress_size;
u64 rsvd[32];
};

static inline int cudbg_get_workspace_size(void)
{
#ifdef CONFIG_ZLIB_DEFLATE
return zlib_deflate_workspacesize(CUDBG_ZLIB_WIN_BITS,
CUDBG_ZLIB_MEM_LVL);
#else
return 0;
#endif /* CONFIG_ZLIB_DEFLATE */
}

#ifndef CONFIG_ZLIB_DEFLATE
static inline int cudbg_compress_buff(struct cudbg_init *pdbg_init,
struct cudbg_buffer *pin_buff,
struct cudbg_buffer *pout_buff)
{
return 0;
}
#else
int cudbg_compress_buff(struct cudbg_init *pdbg_init,
struct cudbg_buffer *pin_buff,
struct cudbg_buffer *pout_buff);
#endif /* CONFIG_ZLIB_DEFLATE */
#endif /* __CUDBG_ZLIB_H__ */
56 changes: 53 additions & 3 deletions drivers/net/ethernet/chelsio/cxgb4/cxgb4_cudbg.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "t4_regs.h"
#include "cxgb4.h"
#include "cxgb4_cudbg.h"
#include "cudbg_zlib.h"

static const struct cxgb4_collect_entity cxgb4_collect_mem_dump[] = {
{ CUDBG_EDC0, cudbg_collect_edc0_meminfo },
Expand Down Expand Up @@ -318,6 +319,7 @@ u32 cxgb4_get_dump_length(struct adapter *adap, u32 flag)
{
u32 i, entity;
u32 len = 0;
u32 wsize;

if (flag & CXGB4_ETH_DUMP_HW) {
for (i = 0; i < ARRAY_SIZE(cxgb4_collect_hw_dump); i++) {
Expand All @@ -333,6 +335,11 @@ u32 cxgb4_get_dump_length(struct adapter *adap, u32 flag)
}
}

/* If compression is enabled, a smaller destination buffer is enough */
wsize = cudbg_get_workspace_size();
if (wsize && len > CUDBG_DUMP_BUFF_SIZE)
len = CUDBG_DUMP_BUFF_SIZE;

return len;
}

Expand Down Expand Up @@ -374,13 +381,36 @@ static void cxgb4_cudbg_collect_entity(struct cudbg_init *pdbg_init,
*tot_size += total_size;
}

static int cudbg_alloc_compress_buff(struct cudbg_init *pdbg_init)
{
u32 workspace_size;

workspace_size = cudbg_get_workspace_size();
pdbg_init->compress_buff = vzalloc(CUDBG_COMPRESS_BUFF_SIZE +
workspace_size);
if (!pdbg_init->compress_buff)
return -ENOMEM;

pdbg_init->compress_buff_size = CUDBG_COMPRESS_BUFF_SIZE;
pdbg_init->workspace = (u8 *)pdbg_init->compress_buff +
CUDBG_COMPRESS_BUFF_SIZE - workspace_size;
return 0;
}

static void cudbg_free_compress_buff(struct cudbg_init *pdbg_init)
{
if (pdbg_init->compress_buff)
vfree(pdbg_init->compress_buff);
}

int cxgb4_cudbg_collect(struct adapter *adap, void *buf, u32 *buf_size,
u32 flag)
{
struct cudbg_init cudbg_init = { 0 };
struct cudbg_buffer dbg_buff = { 0 };
u32 size, min_size, total_size = 0;
struct cudbg_hdr *cudbg_hdr;
int rc;

size = *buf_size;

Expand All @@ -400,15 +430,31 @@ int cxgb4_cudbg_collect(struct adapter *adap, void *buf, u32 *buf_size,
cudbg_hdr->max_entities = CUDBG_MAX_ENTITY;
cudbg_hdr->chip_ver = adap->params.chip;
cudbg_hdr->dump_type = CUDBG_DUMP_TYPE_MINI;
cudbg_init.compress_type = CUDBG_COMPRESSION_NONE;
cudbg_hdr->compress_type = cudbg_init.compress_type;

min_size = sizeof(struct cudbg_hdr) +
sizeof(struct cudbg_entity_hdr) *
cudbg_hdr->max_entities;
if (size < min_size)
return -ENOMEM;

rc = cudbg_get_workspace_size();
if (rc) {
/* Zlib available. So, use zlib deflate */
cudbg_init.compress_type = CUDBG_COMPRESSION_ZLIB;
rc = cudbg_alloc_compress_buff(&cudbg_init);
if (rc) {
/* Ignore error and continue without compression. */
dev_warn(adap->pdev_dev,
"Fail allocating compression buffer ret: %d. Continuing without compression.\n",
rc);
cudbg_init.compress_type = CUDBG_COMPRESSION_NONE;
rc = 0;
}
} else {
cudbg_init.compress_type = CUDBG_COMPRESSION_NONE;
}

cudbg_hdr->compress_type = cudbg_init.compress_type;
dbg_buff.offset += min_size;
total_size = dbg_buff.offset;

Expand All @@ -426,8 +472,12 @@ int cxgb4_cudbg_collect(struct adapter *adap, void *buf, u32 *buf_size,
buf,
&total_size);

cudbg_free_compress_buff(&cudbg_init);
cudbg_hdr->data_len = total_size;
*buf_size = total_size;
if (cudbg_init.compress_type != CUDBG_COMPRESSION_NONE)
*buf_size = size;
else
*buf_size = total_size;
return 0;
}

Expand Down
3 changes: 3 additions & 0 deletions drivers/net/ethernet/chelsio/cxgb4/cxgb4_cudbg.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
#include "cudbg_entity.h"
#include "cudbg_lib.h"

#define CUDBG_DUMP_BUFF_SIZE (32 * 1024 * 1024) /* 32 MB */
#define CUDBG_COMPRESS_BUFF_SIZE (4 * 1024 * 1024) /* 4 MB */

typedef int (*cudbg_collect_callback_t)(struct cudbg_init *pdbg_init,
struct cudbg_buffer *dbg_buff,
struct cudbg_error *cudbg_err);
Expand Down

0 comments on commit 91c1953

Please sign in to comment.