18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *  Copyright (C) 2018 Chelsio Communications.  All rights reserved.
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#include <linux/zlib.h>
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include "cxgb4.h"
98c2ecf20Sopenharmony_ci#include "cudbg_if.h"
108c2ecf20Sopenharmony_ci#include "cudbg_lib_common.h"
118c2ecf20Sopenharmony_ci#include "cudbg_zlib.h"
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_cistatic int cudbg_get_compress_hdr(struct cudbg_buffer *pdbg_buff,
148c2ecf20Sopenharmony_ci				  struct cudbg_buffer *pin_buff)
158c2ecf20Sopenharmony_ci{
168c2ecf20Sopenharmony_ci	if (pdbg_buff->offset + sizeof(struct cudbg_compress_hdr) >
178c2ecf20Sopenharmony_ci	    pdbg_buff->size)
188c2ecf20Sopenharmony_ci		return CUDBG_STATUS_NO_MEM;
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci	pin_buff->data = (char *)pdbg_buff->data + pdbg_buff->offset;
218c2ecf20Sopenharmony_ci	pin_buff->offset = 0;
228c2ecf20Sopenharmony_ci	pin_buff->size = sizeof(struct cudbg_compress_hdr);
238c2ecf20Sopenharmony_ci	pdbg_buff->offset += sizeof(struct cudbg_compress_hdr);
248c2ecf20Sopenharmony_ci	return 0;
258c2ecf20Sopenharmony_ci}
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ciint cudbg_compress_buff(struct cudbg_init *pdbg_init,
288c2ecf20Sopenharmony_ci			struct cudbg_buffer *pin_buff,
298c2ecf20Sopenharmony_ci			struct cudbg_buffer *pout_buff)
308c2ecf20Sopenharmony_ci{
318c2ecf20Sopenharmony_ci	struct cudbg_buffer temp_buff = { 0 };
328c2ecf20Sopenharmony_ci	struct z_stream_s compress_stream;
338c2ecf20Sopenharmony_ci	struct cudbg_compress_hdr *c_hdr;
348c2ecf20Sopenharmony_ci	int rc;
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci	/* Write compression header to output buffer before compression */
378c2ecf20Sopenharmony_ci	rc = cudbg_get_compress_hdr(pout_buff, &temp_buff);
388c2ecf20Sopenharmony_ci	if (rc)
398c2ecf20Sopenharmony_ci		return rc;
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci	c_hdr = (struct cudbg_compress_hdr *)temp_buff.data;
428c2ecf20Sopenharmony_ci	c_hdr->compress_id = CUDBG_ZLIB_COMPRESS_ID;
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci	memset(&compress_stream, 0, sizeof(struct z_stream_s));
458c2ecf20Sopenharmony_ci	compress_stream.workspace = pdbg_init->workspace;
468c2ecf20Sopenharmony_ci	rc = zlib_deflateInit2(&compress_stream, Z_DEFAULT_COMPRESSION,
478c2ecf20Sopenharmony_ci			       Z_DEFLATED, CUDBG_ZLIB_WIN_BITS,
488c2ecf20Sopenharmony_ci			       CUDBG_ZLIB_MEM_LVL, Z_DEFAULT_STRATEGY);
498c2ecf20Sopenharmony_ci	if (rc != Z_OK)
508c2ecf20Sopenharmony_ci		return CUDBG_SYSTEM_ERROR;
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci	compress_stream.next_in = pin_buff->data;
538c2ecf20Sopenharmony_ci	compress_stream.avail_in = pin_buff->size;
548c2ecf20Sopenharmony_ci	compress_stream.next_out = pout_buff->data + pout_buff->offset;
558c2ecf20Sopenharmony_ci	compress_stream.avail_out = pout_buff->size - pout_buff->offset;
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci	rc = zlib_deflate(&compress_stream, Z_FINISH);
588c2ecf20Sopenharmony_ci	if (rc != Z_STREAM_END)
598c2ecf20Sopenharmony_ci		return CUDBG_SYSTEM_ERROR;
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci	rc = zlib_deflateEnd(&compress_stream);
628c2ecf20Sopenharmony_ci	if (rc != Z_OK)
638c2ecf20Sopenharmony_ci		return CUDBG_SYSTEM_ERROR;
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci	c_hdr->compress_size = compress_stream.total_out;
668c2ecf20Sopenharmony_ci	c_hdr->decompress_size = pin_buff->size;
678c2ecf20Sopenharmony_ci	pout_buff->offset += compress_stream.total_out;
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci	return 0;
708c2ecf20Sopenharmony_ci}
71