cxgb4: use zlib deflate to compress firmware dump

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>
This commit is contained in:
Rahul Lakkireddy 2018-01-17 12:53:47 +05:30 committed by David S. Miller
parent 56cf2635ce
commit 91c1953de3
7 changed files with 169 additions and 3 deletions

View File

@ -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

View File

@ -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)

View File

@ -26,6 +26,7 @@ enum cudbg_dump_type {
enum cudbg_compression_type {
CUDBG_COMPRESSION_NONE = 1,
CUDBG_COMPRESSION_ZLIB,
};
struct cudbg_hdr {

View File

@ -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;
}

View File

@ -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__ */

View File

@ -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 },
@ -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++) {
@ -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;
}
@ -374,6 +381,28 @@ 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)
{
@ -381,6 +410,7 @@ int cxgb4_cudbg_collect(struct adapter *adap, void *buf, u32 *buf_size,
struct cudbg_buffer dbg_buff = { 0 };
u32 size, min_size, total_size = 0;
struct cudbg_hdr *cudbg_hdr;
int rc;
size = *buf_size;
@ -400,8 +430,6 @@ 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) *
@ -409,6 +437,24 @@ int cxgb4_cudbg_collect(struct adapter *adap, void *buf, u32 *buf_size,
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;
@ -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;
}

View File

@ -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);