Merge tag 'wberr-v4.14-1' of git://git.kernel.org/pub/scm/linux/kernel/git/jlayton...
[sfrench/cifs-2.6.git] / drivers / staging / ccree / ssi_sram_mgr.c
1 /*
2  * Copyright (C) 2012-2017 ARM Limited or its affiliates.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, see <http://www.gnu.org/licenses/>.
15  */
16
17 #include "ssi_driver.h"
18 #include "ssi_sram_mgr.h"
19
20 /**
21  * struct ssi_sram_mgr_ctx -Internal RAM context manager
22  * @sram_free_offset:   the offset to the non-allocated area
23  */
24 struct ssi_sram_mgr_ctx {
25         ssi_sram_addr_t sram_free_offset;
26 };
27
28 /**
29  * ssi_sram_mgr_fini() - Cleanup SRAM pool.
30  *
31  * @drvdata: Associated device driver context
32  */
33 void ssi_sram_mgr_fini(struct ssi_drvdata *drvdata)
34 {
35         struct ssi_sram_mgr_ctx *smgr_ctx = drvdata->sram_mgr_handle;
36
37         /* Free "this" context */
38         if (smgr_ctx) {
39                 memset(smgr_ctx, 0, sizeof(struct ssi_sram_mgr_ctx));
40                 kfree(smgr_ctx);
41         }
42 }
43
44 /**
45  * ssi_sram_mgr_init() - Initializes SRAM pool.
46  *      The pool starts right at the beginning of SRAM.
47  *      Returns zero for success, negative value otherwise.
48  *
49  * @drvdata: Associated device driver context
50  */
51 int ssi_sram_mgr_init(struct ssi_drvdata *drvdata)
52 {
53         struct ssi_sram_mgr_ctx *smgr_ctx;
54         int rc;
55
56         /* Allocate "this" context */
57         drvdata->sram_mgr_handle = kzalloc(
58                         sizeof(struct ssi_sram_mgr_ctx), GFP_KERNEL);
59         if (!drvdata->sram_mgr_handle) {
60                 SSI_LOG_ERR("Not enough memory to allocate SRAM_MGR ctx (%zu)\n",
61                             sizeof(struct ssi_sram_mgr_ctx));
62                 rc = -ENOMEM;
63                 goto out;
64         }
65         smgr_ctx = drvdata->sram_mgr_handle;
66
67         /* Pool starts at start of SRAM */
68         smgr_ctx->sram_free_offset = 0;
69
70         return 0;
71
72 out:
73         ssi_sram_mgr_fini(drvdata);
74         return rc;
75 }
76
77 /*!
78  * Allocated buffer from SRAM pool.
79  * Note: Caller is responsible to free the LAST allocated buffer.
80  * This function does not taking care of any fragmentation may occur
81  * by the order of calls to alloc/free.
82  *
83  * \param drvdata
84  * \param size The requested bytes to allocate
85  */
86 ssi_sram_addr_t ssi_sram_mgr_alloc(struct ssi_drvdata *drvdata, u32 size)
87 {
88         struct ssi_sram_mgr_ctx *smgr_ctx = drvdata->sram_mgr_handle;
89         ssi_sram_addr_t p;
90
91         if (unlikely((size & 0x3) != 0)) {
92                 SSI_LOG_ERR("Requested buffer size (%u) is not multiple of 4",
93                             size);
94                 return NULL_SRAM_ADDR;
95         }
96         if (unlikely(size > (SSI_CC_SRAM_SIZE - smgr_ctx->sram_free_offset))) {
97                 SSI_LOG_ERR("Not enough space to allocate %u B (at offset %llu)\n",
98                             size, smgr_ctx->sram_free_offset);
99                 return NULL_SRAM_ADDR;
100         }
101
102         p = smgr_ctx->sram_free_offset;
103         smgr_ctx->sram_free_offset += size;
104         SSI_LOG_DEBUG("Allocated %u B @ %u\n", size, (unsigned int)p);
105         return p;
106 }
107
108 /**
109  * ssi_sram_mgr_const2sram_desc() - Create const descriptors sequence to
110  *      set values in given array into SRAM.
111  * Note: each const value can't exceed word size.
112  *
113  * @src:          A pointer to array of words to set as consts.
114  * @dst:          The target SRAM buffer to set into
115  * @nelements:    The number of words in "src" array
116  * @seq:          A pointer to the given IN/OUT descriptor sequence
117  * @seq_len:      A pointer to the given IN/OUT sequence length
118  */
119 void ssi_sram_mgr_const2sram_desc(
120         const u32 *src, ssi_sram_addr_t dst,
121         unsigned int nelement,
122         struct cc_hw_desc *seq, unsigned int *seq_len)
123 {
124         u32 i;
125         unsigned int idx = *seq_len;
126
127         for (i = 0; i < nelement; i++, idx++) {
128                 hw_desc_init(&seq[idx]);
129                 set_din_const(&seq[idx], src[i], sizeof(u32));
130                 set_dout_sram(&seq[idx], dst + (i * sizeof(u32)), sizeof(u32));
131                 set_flow_mode(&seq[idx], BYPASS);
132         }
133
134         *seq_len = idx;
135 }
136