162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *  Copyright (C) 2018 Chelsio Communications.  All rights reserved.
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include <linux/zlib.h>
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include "cxgb4.h"
962306a36Sopenharmony_ci#include "cudbg_if.h"
1062306a36Sopenharmony_ci#include "cudbg_lib_common.h"
1162306a36Sopenharmony_ci#include "cudbg_zlib.h"
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_cistatic int cudbg_get_compress_hdr(struct cudbg_buffer *pdbg_buff,
1462306a36Sopenharmony_ci				  struct cudbg_buffer *pin_buff)
1562306a36Sopenharmony_ci{
1662306a36Sopenharmony_ci	if (pdbg_buff->offset + sizeof(struct cudbg_compress_hdr) >
1762306a36Sopenharmony_ci	    pdbg_buff->size)
1862306a36Sopenharmony_ci		return CUDBG_STATUS_NO_MEM;
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci	pin_buff->data = (char *)pdbg_buff->data + pdbg_buff->offset;
2162306a36Sopenharmony_ci	pin_buff->offset = 0;
2262306a36Sopenharmony_ci	pin_buff->size = sizeof(struct cudbg_compress_hdr);
2362306a36Sopenharmony_ci	pdbg_buff->offset += sizeof(struct cudbg_compress_hdr);
2462306a36Sopenharmony_ci	return 0;
2562306a36Sopenharmony_ci}
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ciint cudbg_compress_buff(struct cudbg_init *pdbg_init,
2862306a36Sopenharmony_ci			struct cudbg_buffer *pin_buff,
2962306a36Sopenharmony_ci			struct cudbg_buffer *pout_buff)
3062306a36Sopenharmony_ci{
3162306a36Sopenharmony_ci	struct cudbg_buffer temp_buff = { 0 };
3262306a36Sopenharmony_ci	struct z_stream_s compress_stream;
3362306a36Sopenharmony_ci	struct cudbg_compress_hdr *c_hdr;
3462306a36Sopenharmony_ci	int rc;
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci	/* Write compression header to output buffer before compression */
3762306a36Sopenharmony_ci	rc = cudbg_get_compress_hdr(pout_buff, &temp_buff);
3862306a36Sopenharmony_ci	if (rc)
3962306a36Sopenharmony_ci		return rc;
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	c_hdr = (struct cudbg_compress_hdr *)temp_buff.data;
4262306a36Sopenharmony_ci	c_hdr->compress_id = CUDBG_ZLIB_COMPRESS_ID;
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	memset(&compress_stream, 0, sizeof(struct z_stream_s));
4562306a36Sopenharmony_ci	compress_stream.workspace = pdbg_init->workspace;
4662306a36Sopenharmony_ci	rc = zlib_deflateInit2(&compress_stream, Z_DEFAULT_COMPRESSION,
4762306a36Sopenharmony_ci			       Z_DEFLATED, CUDBG_ZLIB_WIN_BITS,
4862306a36Sopenharmony_ci			       CUDBG_ZLIB_MEM_LVL, Z_DEFAULT_STRATEGY);
4962306a36Sopenharmony_ci	if (rc != Z_OK)
5062306a36Sopenharmony_ci		return CUDBG_SYSTEM_ERROR;
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	compress_stream.next_in = pin_buff->data;
5362306a36Sopenharmony_ci	compress_stream.avail_in = pin_buff->size;
5462306a36Sopenharmony_ci	compress_stream.next_out = pout_buff->data + pout_buff->offset;
5562306a36Sopenharmony_ci	compress_stream.avail_out = pout_buff->size - pout_buff->offset;
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	rc = zlib_deflate(&compress_stream, Z_FINISH);
5862306a36Sopenharmony_ci	if (rc != Z_STREAM_END)
5962306a36Sopenharmony_ci		return CUDBG_SYSTEM_ERROR;
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	rc = zlib_deflateEnd(&compress_stream);
6262306a36Sopenharmony_ci	if (rc != Z_OK)
6362306a36Sopenharmony_ci		return CUDBG_SYSTEM_ERROR;
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	c_hdr->compress_size = compress_stream.total_out;
6662306a36Sopenharmony_ci	c_hdr->decompress_size = pin_buff->size;
6762306a36Sopenharmony_ci	pout_buff->offset += compress_stream.total_out;
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	return 0;
7062306a36Sopenharmony_ci}
71