Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 50cfbbb7 authored by Gilad Ben-Yossef's avatar Gilad Ben-Yossef Committed by Greg Kroah-Hartman
Browse files

staging: ccree: add ahash support



Add CryptoCell async. hash and HMAC support.

Signed-off-by: default avatarGilad Ben-Yossef <gilad@benyossef.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent abefd674
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -2,6 +2,12 @@ config CRYPTO_DEV_CCREE
	tristate "Support for ARM TrustZone CryptoCell C7XX family of Crypto accelerators"
	depends on CRYPTO_HW && OF && HAS_DMA
	default n
	select CRYPTO_HASH
	select CRYPTO_SHA1
	select CRYPTO_MD5
	select CRYPTO_SHA256
	select CRYPTO_SHA512
	select CRYPTO_HMAC
	help
	  Say 'Y' to enable a driver for the Arm TrustZone CryptoCell 
	  C7xx. Currently only the CryptoCell 712 REE is supported.
+1 −1
Original line number Diff line number Diff line
obj-$(CONFIG_CRYPTO_DEV_CCREE) := ccree.o
ccree-y := ssi_driver.o ssi_sysfs.o ssi_buffer_mgr.o ssi_request_mgr.o ssi_sram_mgr.o ssi_pm.o ssi_pm_ext.o
ccree-y := ssi_driver.o ssi_sysfs.o ssi_buffer_mgr.o ssi_request_mgr.o ssi_hash.o ssi_sram_mgr.o ssi_pm.o ssi_pm_ext.o
+22 −0
Original line number Diff line number Diff line
@@ -220,6 +220,28 @@ struct drv_ctx_generic {
} __attribute__((__may_alias__));


struct drv_ctx_hash {
	enum drv_crypto_alg alg; /* DRV_CRYPTO_ALG_HASH */
	enum drv_hash_mode mode;
	uint8_t digest[CC_DIGEST_SIZE_MAX];
	/* reserve to end of allocated context size */
	uint8_t reserved[CC_CTX_SIZE - 2 * sizeof(uint32_t) -
			CC_DIGEST_SIZE_MAX];
};

/* !!!! drv_ctx_hmac should have the same structure as drv_ctx_hash except
   k0, k0_size fields */
struct drv_ctx_hmac {
	enum drv_crypto_alg alg; /* DRV_CRYPTO_ALG_HMAC */
	enum drv_hash_mode mode;
	uint8_t digest[CC_DIGEST_SIZE_MAX];
	uint32_t k0[CC_HMAC_BLOCK_SIZE_MAX/sizeof(uint32_t)];
	uint32_t k0_size;
	/* reserve to end of allocated context size */
	uint8_t reserved[CC_CTX_SIZE - 3 * sizeof(uint32_t) -
			CC_DIGEST_SIZE_MAX - CC_HMAC_BLOCK_SIZE_MAX];
};

/*******************************************************************/
/***************** MESSAGE BASED CONTEXTS **************************/
/*******************************************************************/
+78 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2012-2017 ARM Limited or its affiliates.
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 * 
 * This program is distributed in the hope that 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.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 */

#ifndef  _HASH_DEFS_H__
#define  _HASH_DEFS_H__

#include "cc_crypto_ctx.h"

/* this files provides definitions required for hash engine drivers */
#ifndef CC_CONFIG_HASH_SHA_512_SUPPORTED
#define SEP_HASH_LENGTH_WORDS		2
#else
#define SEP_HASH_LENGTH_WORDS		4
#endif

#ifdef BIG__ENDIAN
#define OPAD_CURRENT_LENGTH 0x40000000, 0x00000000 , 0x00000000, 0x00000000
#define HASH_LARVAL_MD5  0x76543210, 0xFEDCBA98, 0x89ABCDEF, 0x01234567
#define HASH_LARVAL_SHA1 0xF0E1D2C3, 0x76543210, 0xFEDCBA98, 0x89ABCDEF, 0x01234567
#define HASH_LARVAL_SHA224 0XA44FFABE, 0XA78FF964, 0X11155868, 0X310BC0FF, 0X39590EF7, 0X17DD7030, 0X07D57C36, 0XD89E05C1
#define HASH_LARVAL_SHA256 0X19CDE05B, 0XABD9831F, 0X8C68059B, 0X7F520E51, 0X3AF54FA5, 0X72F36E3C, 0X85AE67BB, 0X67E6096A
#define HASH_LARVAL_SHA384 0X1D48B547, 0XA44FFABE, 0X0D2E0CDB, 0XA78FF964, 0X874AB48E, 0X11155868, 0X67263367, 0X310BC0FF, 0XD8EC2F15, 0X39590EF7, 0X5A015991, 0X17DD7030, 0X2A299A62, 0X07D57C36, 0X5D9DBBCB, 0XD89E05C1
#define HASH_LARVAL_SHA512 0X19CDE05B, 0X79217E13, 0XABD9831F, 0X6BBD41FB, 0X8C68059B, 0X1F6C3E2B, 0X7F520E51, 0XD182E6AD, 0X3AF54FA5, 0XF1361D5F, 0X72F36E3C, 0X2BF894FE, 0X85AE67BB, 0X3BA7CA84, 0X67E6096A, 0X08C9BCF3
#else
#define OPAD_CURRENT_LENGTH 0x00000040, 0x00000000, 0x00000000, 0x00000000
#define HASH_LARVAL_MD5  0x10325476, 0x98BADCFE, 0xEFCDAB89, 0x67452301
#define HASH_LARVAL_SHA1 0xC3D2E1F0, 0x10325476, 0x98BADCFE, 0xEFCDAB89, 0x67452301
#define HASH_LARVAL_SHA224 0xbefa4fa4, 0x64f98fa7, 0x68581511, 0xffc00b31, 0xf70e5939, 0x3070dd17, 0x367cd507, 0xc1059ed8
#define HASH_LARVAL_SHA256 0x5be0cd19, 0x1f83d9ab, 0x9b05688c, 0x510e527f, 0xa54ff53a, 0x3c6ef372, 0xbb67ae85, 0x6a09e667
#define HASH_LARVAL_SHA384 0X47B5481D, 0XBEFA4FA4, 0XDB0C2E0D, 0X64F98FA7, 0X8EB44A87, 0X68581511, 0X67332667, 0XFFC00B31, 0X152FECD8, 0XF70E5939, 0X9159015A, 0X3070DD17, 0X629A292A, 0X367CD507, 0XCBBB9D5D, 0XC1059ED8
#define HASH_LARVAL_SHA512 0x5be0cd19, 0x137e2179, 0x1f83d9ab, 0xfb41bd6b, 0x9b05688c, 0x2b3e6c1f, 0x510e527f, 0xade682d1, 0xa54ff53a, 0x5f1d36f1, 0x3c6ef372, 0xfe94f82b, 0xbb67ae85, 0x84caa73b, 0x6a09e667, 0xf3bcc908
#endif

enum HashConfig1Padding {
	HASH_PADDING_DISABLED = 0,
	HASH_PADDING_ENABLED = 1,
	HASH_DIGEST_RESULT_LITTLE_ENDIAN = 2,
	HASH_CONFIG1_PADDING_RESERVE32 = INT32_MAX,
};

enum HashCipherDoPadding {
	DO_NOT_PAD = 0,
	DO_PAD = 1,
	HASH_CIPHER_DO_PADDING_RESERVE32 = INT32_MAX,
};

typedef struct SepHashPrivateContext {
	/* The current length is placed at the end of the context buffer because the hash 
	   context is used for all HMAC operations as well. HMAC context includes a 64 bytes 
	   K0 field.  The size of struct drv_ctx_hash reserved field is  88/184 bytes depend if t
	   he SHA512 is supported ( in this case teh context size is 256 bytes).
	   The size of struct drv_ctx_hash reseved field is 20 or 52 depend if the SHA512 is supported.
	   This means that this structure size (without the reserved field can be up to 20 bytes ,
	   in case sha512 is not suppported it is 20 bytes (SEP_HASH_LENGTH_WORDS define to 2 ) and in the other
	   case it is 28 (SEP_HASH_LENGTH_WORDS define to 4) */
	uint32_t reserved[(sizeof(struct drv_ctx_hash)/sizeof(uint32_t)) - SEP_HASH_LENGTH_WORDS - 3];
	uint32_t CurrentDigestedLength[SEP_HASH_LENGTH_WORDS];
	uint32_t KeyType;
	uint32_t dataCompleted;
	uint32_t hmacFinalization;
	/* no space left */
} SepHashPrivateContext_s;

#endif /*_HASH_DEFS_H__*/
+301 −10
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include <linux/crypto.h>
#include <linux/version.h>
#include <crypto/algapi.h>
#include <crypto/hash.h>
#include <crypto/authenc.h>
#include <crypto/scatterwalk.h>
#include <linux/dmapool.h>
@@ -27,6 +28,7 @@

#include "ssi_buffer_mgr.h"
#include "cc_lli_defs.h"
#include "ssi_hash.h"

#define LLI_MAX_NUM_OF_DATA_ENTRIES 128
#define LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES 4
@@ -281,11 +283,6 @@ static inline int ssi_buffer_mgr_render_scatterlist_to_mlli(
	return 0;
}

static int ssi_buffer_mgr_generate_mlli (
	struct device *dev,
	struct buffer_array *sg_data,
	struct mlli_params *mlli_params) __maybe_unused;

static int ssi_buffer_mgr_generate_mlli(
	struct device *dev,
	struct buffer_array *sg_data,
@@ -427,11 +424,6 @@ ssi_buffer_mgr_dma_map_sg(struct device *dev, struct scatterlist *sg, uint32_t n
	return 0;
}

static int ssi_buffer_mgr_map_scatterlist (struct device *dev,
	struct scatterlist *sg, unsigned int nbytes, int direction,
	uint32_t *nents, uint32_t max_sg_nents, uint32_t *lbytes,
	uint32_t *mapped_nents) __maybe_unused;

static int ssi_buffer_mgr_map_scatterlist(
	struct device *dev, struct scatterlist *sg,
	unsigned int nbytes, int direction,
@@ -493,6 +485,305 @@ static int ssi_buffer_mgr_map_scatterlist(
	return 0;
}

static inline int ssi_ahash_handle_curr_buf(struct device *dev,
					   struct ahash_req_ctx *areq_ctx,
					   uint8_t* curr_buff,
					   uint32_t curr_buff_cnt,
					   struct buffer_array *sg_data)
{
	SSI_LOG_DEBUG(" handle curr buff %x set to   DLLI \n", curr_buff_cnt);
	/* create sg for the current buffer */
	sg_init_one(areq_ctx->buff_sg,curr_buff, curr_buff_cnt);
	if (unlikely(dma_map_sg(dev, areq_ctx->buff_sg, 1,
				DMA_TO_DEVICE) != 1)) {
			SSI_LOG_ERR("dma_map_sg() "
			   "src buffer failed\n");
			return -ENOMEM;
	}
	SSI_LOG_DEBUG("Mapped curr_buff: dma_address=0x%llX "
		     "page_link=0x%08lX addr=%pK "
		     "offset=%u length=%u\n",
		     (unsigned long long)sg_dma_address(areq_ctx->buff_sg), 
		     areq_ctx->buff_sg->page_link, 
		     sg_virt(areq_ctx->buff_sg),
		     areq_ctx->buff_sg->offset, 
		     areq_ctx->buff_sg->length);
	areq_ctx->data_dma_buf_type = SSI_DMA_BUF_DLLI;
	areq_ctx->curr_sg = areq_ctx->buff_sg;
	areq_ctx->in_nents = 0;
	/* prepare for case of MLLI */
	ssi_buffer_mgr_add_scatterlist_entry(sg_data, 1, areq_ctx->buff_sg,
				curr_buff_cnt, 0, false, NULL);
	return 0;
}

int ssi_buffer_mgr_map_hash_request_final(
	struct ssi_drvdata *drvdata, void *ctx, struct scatterlist *src, unsigned int nbytes, bool do_update)
{
	struct ahash_req_ctx *areq_ctx = (struct ahash_req_ctx *)ctx;
	struct device *dev = &drvdata->plat_dev->dev;
	uint8_t* curr_buff = areq_ctx->buff_index ? areq_ctx->buff1 :
			areq_ctx->buff0;
	uint32_t *curr_buff_cnt = areq_ctx->buff_index ? &areq_ctx->buff1_cnt :
			&areq_ctx->buff0_cnt;
	struct mlli_params *mlli_params = &areq_ctx->mlli_params;	
	struct buffer_array sg_data;
	struct buff_mgr_handle *buff_mgr = drvdata->buff_mgr_handle;
	uint32_t dummy = 0;
	uint32_t mapped_nents = 0;

	SSI_LOG_DEBUG(" final params : curr_buff=%pK "
		     "curr_buff_cnt=0x%X nbytes = 0x%X "
		     "src=%pK curr_index=%u\n",
		     curr_buff, *curr_buff_cnt, nbytes,
		     src, areq_ctx->buff_index);
	/* Init the type of the dma buffer */
	areq_ctx->data_dma_buf_type = SSI_DMA_BUF_NULL;
	mlli_params->curr_pool = NULL;
	sg_data.num_of_buffers = 0;
	areq_ctx->in_nents = 0;

	if (unlikely(nbytes == 0 && *curr_buff_cnt == 0)) {
		/* nothing to do */
		return 0;
	}
	
	/*TODO: copy data in case that buffer is enough for operation */
	/* map the previous buffer */
	if (*curr_buff_cnt != 0 ) {
		if (ssi_ahash_handle_curr_buf(dev, areq_ctx, curr_buff,
					    *curr_buff_cnt, &sg_data) != 0) {
			return -ENOMEM;
		}
	}

	if (src && (nbytes > 0) && do_update) {
		if ( unlikely( ssi_buffer_mgr_map_scatterlist( dev,src,
					  nbytes,
					  DMA_TO_DEVICE,
					  &areq_ctx->in_nents,
					  LLI_MAX_NUM_OF_DATA_ENTRIES,
					  &dummy, &mapped_nents))){
			goto unmap_curr_buff;
		}
		if ( src && (mapped_nents == 1) 
		     && (areq_ctx->data_dma_buf_type == SSI_DMA_BUF_NULL) ) {
			memcpy(areq_ctx->buff_sg,src,
			       sizeof(struct scatterlist));
			areq_ctx->buff_sg->length = nbytes;
			areq_ctx->curr_sg = areq_ctx->buff_sg;
			areq_ctx->data_dma_buf_type = SSI_DMA_BUF_DLLI;
		} else {
			areq_ctx->data_dma_buf_type = SSI_DMA_BUF_MLLI;
		}

	}

	/*build mlli */
	if (unlikely(areq_ctx->data_dma_buf_type == SSI_DMA_BUF_MLLI)) {
		mlli_params->curr_pool = buff_mgr->mlli_buffs_pool;
		/* add the src data to the sg_data */
		ssi_buffer_mgr_add_scatterlist_entry(&sg_data,
					areq_ctx->in_nents,
					src,
					nbytes, 0,
					true, &areq_ctx->mlli_nents);
		if (unlikely(ssi_buffer_mgr_generate_mlli(dev, &sg_data,
						  mlli_params) != 0)) {
			goto fail_unmap_din;
		}
	}
	/* change the buffer index for the unmap function */
	areq_ctx->buff_index = (areq_ctx->buff_index^1);
	SSI_LOG_DEBUG("areq_ctx->data_dma_buf_type = %s\n",
		GET_DMA_BUFFER_TYPE(areq_ctx->data_dma_buf_type));
	return 0;

fail_unmap_din:
	dma_unmap_sg(dev, src, areq_ctx->in_nents, DMA_TO_DEVICE);

unmap_curr_buff:
	if (*curr_buff_cnt != 0 ) {
		dma_unmap_sg(dev, areq_ctx->buff_sg, 1, DMA_TO_DEVICE);
	}
	return -ENOMEM;
}

int ssi_buffer_mgr_map_hash_request_update(
	struct ssi_drvdata *drvdata, void *ctx, struct scatterlist *src, unsigned int nbytes, unsigned int block_size)
{
	struct ahash_req_ctx *areq_ctx = (struct ahash_req_ctx *)ctx;
	struct device *dev = &drvdata->plat_dev->dev;
	uint8_t* curr_buff = areq_ctx->buff_index ? areq_ctx->buff1 :
			areq_ctx->buff0;
	uint32_t *curr_buff_cnt = areq_ctx->buff_index ? &areq_ctx->buff1_cnt :
			&areq_ctx->buff0_cnt;
	uint8_t* next_buff = areq_ctx->buff_index ? areq_ctx->buff0 :
			areq_ctx->buff1;
	uint32_t *next_buff_cnt = areq_ctx->buff_index ? &areq_ctx->buff0_cnt :
			&areq_ctx->buff1_cnt;
	struct mlli_params *mlli_params = &areq_ctx->mlli_params;	
	unsigned int update_data_len;
	uint32_t total_in_len = nbytes + *curr_buff_cnt;
	struct buffer_array sg_data;
	struct buff_mgr_handle *buff_mgr = drvdata->buff_mgr_handle;
	unsigned int swap_index = 0;
	uint32_t dummy = 0;
	uint32_t mapped_nents = 0;
		
	SSI_LOG_DEBUG(" update params : curr_buff=%pK "
		     "curr_buff_cnt=0x%X nbytes=0x%X "
		     "src=%pK curr_index=%u \n",
		     curr_buff, *curr_buff_cnt, nbytes,
		     src, areq_ctx->buff_index);
	/* Init the type of the dma buffer */
	areq_ctx->data_dma_buf_type = SSI_DMA_BUF_NULL;
	mlli_params->curr_pool = NULL;
	areq_ctx->curr_sg = NULL;
	sg_data.num_of_buffers = 0;
	areq_ctx->in_nents = 0;

	if (unlikely(total_in_len < block_size)) {
		SSI_LOG_DEBUG(" less than one block: curr_buff=%pK "
			     "*curr_buff_cnt=0x%X copy_to=%pK\n",
			curr_buff, *curr_buff_cnt,
			&curr_buff[*curr_buff_cnt]);
		areq_ctx->in_nents = 
			ssi_buffer_mgr_get_sgl_nents(src,
						    nbytes,
						    &dummy, NULL);
		sg_copy_to_buffer(src, areq_ctx->in_nents,
				  &curr_buff[*curr_buff_cnt], nbytes); 
		*curr_buff_cnt += nbytes;
		return 1;
	}

	/* Calculate the residue size*/
	*next_buff_cnt = total_in_len & (block_size - 1);
	/* update data len */
	update_data_len = total_in_len - *next_buff_cnt;

	SSI_LOG_DEBUG(" temp length : *next_buff_cnt=0x%X "
		     "update_data_len=0x%X\n",
		*next_buff_cnt, update_data_len);

	/* Copy the new residue to next buffer */
	if (*next_buff_cnt != 0) {
		SSI_LOG_DEBUG(" handle residue: next buff %pK skip data %u"
			     " residue %u \n", next_buff,
			     (update_data_len - *curr_buff_cnt),
			     *next_buff_cnt);
		ssi_buffer_mgr_copy_scatterlist_portion(next_buff, src,
			     (update_data_len -*curr_buff_cnt),
			     nbytes,SSI_SG_TO_BUF);
		/* change the buffer index for next operation */
		swap_index = 1;
	}

	if (*curr_buff_cnt != 0) {
		if (ssi_ahash_handle_curr_buf(dev, areq_ctx, curr_buff,
					    *curr_buff_cnt, &sg_data) != 0) {
			return -ENOMEM;
		}
		/* change the buffer index for next operation */
		swap_index = 1;
	}
	
	if ( update_data_len > *curr_buff_cnt ) {
		if ( unlikely( ssi_buffer_mgr_map_scatterlist( dev,src,
					  (update_data_len -*curr_buff_cnt),
					  DMA_TO_DEVICE,
					  &areq_ctx->in_nents,
					  LLI_MAX_NUM_OF_DATA_ENTRIES,
					  &dummy, &mapped_nents))){
			goto unmap_curr_buff;
		}
		if ( (mapped_nents == 1) 
		     && (areq_ctx->data_dma_buf_type == SSI_DMA_BUF_NULL) ) {
			/* only one entry in the SG and no previous data */
			memcpy(areq_ctx->buff_sg,src,
			       sizeof(struct scatterlist));
			areq_ctx->buff_sg->length = update_data_len;
			areq_ctx->data_dma_buf_type = SSI_DMA_BUF_DLLI;
			areq_ctx->curr_sg = areq_ctx->buff_sg;
		} else {
			areq_ctx->data_dma_buf_type = SSI_DMA_BUF_MLLI;
		}
	}

	if (unlikely(areq_ctx->data_dma_buf_type == SSI_DMA_BUF_MLLI)) {
		mlli_params->curr_pool = buff_mgr->mlli_buffs_pool;
		/* add the src data to the sg_data */
		ssi_buffer_mgr_add_scatterlist_entry(&sg_data,
					areq_ctx->in_nents,
					src,
					(update_data_len - *curr_buff_cnt), 0,
					true, &areq_ctx->mlli_nents);
		if (unlikely(ssi_buffer_mgr_generate_mlli(dev, &sg_data,
						  mlli_params) != 0)) {
			goto fail_unmap_din;
		}

	}
	areq_ctx->buff_index = (areq_ctx->buff_index^swap_index);

	return 0;

fail_unmap_din:
	dma_unmap_sg(dev, src, areq_ctx->in_nents, DMA_TO_DEVICE);

unmap_curr_buff:
	if (*curr_buff_cnt != 0 ) {
		dma_unmap_sg(dev, areq_ctx->buff_sg, 1, DMA_TO_DEVICE);
	}
	return -ENOMEM;
}

void ssi_buffer_mgr_unmap_hash_request(
	struct device *dev, void *ctx, struct scatterlist *src, bool do_revert)
{
	struct ahash_req_ctx *areq_ctx = (struct ahash_req_ctx *)ctx;
	uint32_t *prev_len = areq_ctx->buff_index ?  &areq_ctx->buff0_cnt :
						&areq_ctx->buff1_cnt;

	/*In case a pool was set, a table was 
	  allocated and should be released */
	if (areq_ctx->mlli_params.curr_pool != NULL) {
		SSI_LOG_DEBUG("free MLLI buffer: dma=0x%llX virt=%pK\n", 
			     (unsigned long long)areq_ctx->mlli_params.mlli_dma_addr,
			     areq_ctx->mlli_params.mlli_virt_addr);
		SSI_RESTORE_DMA_ADDR_TO_48BIT(areq_ctx->mlli_params.mlli_dma_addr);
		dma_pool_free(areq_ctx->mlli_params.curr_pool,
			      areq_ctx->mlli_params.mlli_virt_addr,
			      areq_ctx->mlli_params.mlli_dma_addr);
	}
	
	if ((src) && likely(areq_ctx->in_nents != 0)) {
		SSI_LOG_DEBUG("Unmapped sg src: virt=%pK dma=0x%llX len=0x%X\n",
			     sg_virt(src),
			     (unsigned long long)sg_dma_address(src), 
			     sg_dma_len(src));
		SSI_RESTORE_DMA_ADDR_TO_48BIT(sg_dma_address(src));
		dma_unmap_sg(dev, src, 
			     areq_ctx->in_nents, DMA_TO_DEVICE);
	}

	if (*prev_len != 0) {
		SSI_LOG_DEBUG("Unmapped buffer: areq_ctx->buff_sg=%pK"
			     "dma=0x%llX len 0x%X\n", 
				sg_virt(areq_ctx->buff_sg),
				(unsigned long long)sg_dma_address(areq_ctx->buff_sg), 
				sg_dma_len(areq_ctx->buff_sg));
		dma_unmap_sg(dev, areq_ctx->buff_sg, 1, DMA_TO_DEVICE);
		if (!do_revert) {
			/* clean the previous data length for update operation */
			*prev_len = 0;
		} else {
			areq_ctx->buff_index ^= 1;
		}
	}
}

int ssi_buffer_mgr_init(struct ssi_drvdata *drvdata)
{
	struct buff_mgr_handle *buff_mgr_handle;
Loading