4040#define SEED_SHIFT_24 24
4141#define SEED_SHIFT_16 16
4242#define SEED_SHIFT_8 8
43+ #define SW_MAX_RANDOM_BYTES 65520
4344
4445struct hisi_trng_list {
4546 struct mutex lock ;
@@ -53,8 +54,10 @@ struct hisi_trng {
5354 struct list_head list ;
5455 struct hwrng rng ;
5556 u32 ver ;
56- bool is_used ;
57- struct mutex mutex ;
57+ u32 ctx_num ;
58+ /* The bytes of the random number generated since the last seeding. */
59+ u32 random_bytes ;
60+ struct mutex lock ;
5861};
5962
6063struct hisi_trng_ctx {
@@ -63,10 +66,14 @@ struct hisi_trng_ctx {
6366
6467static atomic_t trng_active_devs ;
6568static struct hisi_trng_list trng_devices ;
69+ static int hisi_trng_read (struct hwrng * rng , void * buf , size_t max , bool wait );
6670
67- static void hisi_trng_set_seed (struct hisi_trng * trng , const u8 * seed )
71+ static int hisi_trng_set_seed (struct hisi_trng * trng , const u8 * seed )
6872{
6973 u32 val , seed_reg , i ;
74+ int ret ;
75+
76+ writel (0x0 , trng -> base + SW_DRBG_BLOCKS );
7077
7178 for (i = 0 ; i < SW_DRBG_SEED_SIZE ;
7279 i += SW_DRBG_SEED_SIZE / SW_DRBG_SEED_REGS_NUM ) {
@@ -78,59 +85,74 @@ static void hisi_trng_set_seed(struct hisi_trng *trng, const u8 *seed)
7885 seed_reg = (i >> SW_DRBG_NUM_SHIFT ) % SW_DRBG_SEED_REGS_NUM ;
7986 writel (val , trng -> base + SW_DRBG_SEED (seed_reg ));
8087 }
88+
89+ writel (SW_DRBG_BLOCKS_NUM | (0x1 << SW_DRBG_ENABLE_SHIFT ),
90+ trng -> base + SW_DRBG_BLOCKS );
91+ writel (0x1 , trng -> base + SW_DRBG_INIT );
92+ ret = readl_relaxed_poll_timeout (trng -> base + SW_DRBG_STATUS ,
93+ val , val & BIT (0 ), SLEEP_US , TIMEOUT_US );
94+ if (ret ) {
95+ pr_err ("failed to init trng(%d)\n" , ret );
96+ return - EIO ;
97+ }
98+
99+ trng -> random_bytes = 0 ;
100+
101+ return 0 ;
81102}
82103
83104static int hisi_trng_seed (struct crypto_rng * tfm , const u8 * seed ,
84105 unsigned int slen )
85106{
86107 struct hisi_trng_ctx * ctx = crypto_rng_ctx (tfm );
87108 struct hisi_trng * trng = ctx -> trng ;
88- u32 val = 0 ;
89- int ret = 0 ;
109+ int ret ;
90110
91111 if (slen < SW_DRBG_SEED_SIZE ) {
92112 pr_err ("slen(%u) is not matched with trng(%d)\n" , slen ,
93113 SW_DRBG_SEED_SIZE );
94114 return - EINVAL ;
95115 }
96116
97- writel (0x0 , trng -> base + SW_DRBG_BLOCKS );
98- hisi_trng_set_seed (trng , seed );
117+ mutex_lock (& trng -> lock );
118+ ret = hisi_trng_set_seed (trng , seed );
119+ mutex_unlock (& trng -> lock );
99120
100- writel (SW_DRBG_BLOCKS_NUM | (0x1 << SW_DRBG_ENABLE_SHIFT ),
101- trng -> base + SW_DRBG_BLOCKS );
102- writel (0x1 , trng -> base + SW_DRBG_INIT );
121+ return ret ;
122+ }
103123
104- ret = readl_relaxed_poll_timeout ( trng -> base + SW_DRBG_STATUS ,
105- val , val & BIT ( 0 ), SLEEP_US , TIMEOUT_US );
106- if ( ret )
107- pr_err ( "fail to init trng(%d)\n" , ret ) ;
124+ static int hisi_trng_reseed ( struct hisi_trng * trng )
125+ {
126+ u8 seed [ SW_DRBG_SEED_SIZE ];
127+ int size ;
108128
109- return ret ;
129+ if (!trng -> random_bytes )
130+ return 0 ;
131+
132+ size = hisi_trng_read (& trng -> rng , seed , SW_DRBG_SEED_SIZE , false);
133+ if (size != SW_DRBG_SEED_SIZE )
134+ return - EIO ;
135+
136+ return hisi_trng_set_seed (trng , seed );
110137}
111138
112- static int hisi_trng_generate (struct crypto_rng * tfm , const u8 * src ,
113- unsigned int slen , u8 * dstn , unsigned int dlen )
139+ static int hisi_trng_get_bytes (struct hisi_trng * trng , u8 * dstn , unsigned int dlen )
114140{
115- struct hisi_trng_ctx * ctx = crypto_rng_ctx (tfm );
116- struct hisi_trng * trng = ctx -> trng ;
117141 u32 data [SW_DRBG_DATA_NUM ];
118142 u32 currsize = 0 ;
119143 u32 val = 0 ;
120144 int ret ;
121145 u32 i ;
122146
123- if (dlen > SW_DRBG_BLOCKS_NUM * SW_DRBG_BYTES || dlen == 0 ) {
124- pr_err ("dlen(%u) exceeds limit(%d)!\n" , dlen ,
125- SW_DRBG_BLOCKS_NUM * SW_DRBG_BYTES );
126- return - EINVAL ;
127- }
147+ ret = hisi_trng_reseed (trng );
148+ if (ret )
149+ return ret ;
128150
129151 do {
130152 ret = readl_relaxed_poll_timeout (trng -> base + SW_DRBG_STATUS ,
131- val , val & BIT (1 ), SLEEP_US , TIMEOUT_US );
153+ val , val & BIT (1 ), SLEEP_US , TIMEOUT_US );
132154 if (ret ) {
133- pr_err ("fail to generate random number(%d)!\n" , ret );
155+ pr_err ("failed to generate random number(%d)!\n" , ret );
134156 break ;
135157 }
136158
@@ -145,38 +167,65 @@ static int hisi_trng_generate(struct crypto_rng *tfm, const u8 *src,
145167 currsize = dlen ;
146168 }
147169
170+ trng -> random_bytes += SW_DRBG_BYTES ;
148171 writel (0x1 , trng -> base + SW_DRBG_GEN );
149172 } while (currsize < dlen );
150173
151174 return ret ;
152175}
153176
177+ static int hisi_trng_generate (struct crypto_rng * tfm , const u8 * src ,
178+ unsigned int slen , u8 * dstn , unsigned int dlen )
179+ {
180+ struct hisi_trng_ctx * ctx = crypto_rng_ctx (tfm );
181+ struct hisi_trng * trng = ctx -> trng ;
182+ unsigned int currsize = 0 ;
183+ unsigned int block_size ;
184+ int ret ;
185+
186+ if (!dstn || !dlen ) {
187+ pr_err ("output is error, dlen %u!\n" , dlen );
188+ return - EINVAL ;
189+ }
190+
191+ do {
192+ block_size = min_t (unsigned int , dlen - currsize , SW_MAX_RANDOM_BYTES );
193+ mutex_lock (& trng -> lock );
194+ ret = hisi_trng_get_bytes (trng , dstn + currsize , block_size );
195+ mutex_unlock (& trng -> lock );
196+ if (ret )
197+ return ret ;
198+ currsize += block_size ;
199+ } while (currsize < dlen );
200+
201+ return 0 ;
202+ }
203+
154204static int hisi_trng_init (struct crypto_tfm * tfm )
155205{
156206 struct hisi_trng_ctx * ctx = crypto_tfm_ctx (tfm );
157207 struct hisi_trng * trng ;
158- int ret = - EBUSY ;
208+ u32 ctx_num = ~ 0 ;
159209
160210 mutex_lock (& trng_devices .lock );
161211 list_for_each_entry (trng , & trng_devices .list , list ) {
162- if (! trng -> is_used ) {
163- trng -> is_used = true ;
212+ if (trng -> ctx_num < ctx_num ) {
213+ ctx_num = trng -> ctx_num ;
164214 ctx -> trng = trng ;
165- ret = 0 ;
166- break ;
167215 }
168216 }
217+ ctx -> trng -> ctx_num ++ ;
169218 mutex_unlock (& trng_devices .lock );
170219
171- return ret ;
220+ return 0 ;
172221}
173222
174223static void hisi_trng_exit (struct crypto_tfm * tfm )
175224{
176225 struct hisi_trng_ctx * ctx = crypto_tfm_ctx (tfm );
177226
178227 mutex_lock (& trng_devices .lock );
179- ctx -> trng -> is_used = false ;
228+ ctx -> trng -> ctx_num -- ;
180229 mutex_unlock (& trng_devices .lock );
181230}
182231
@@ -238,7 +287,7 @@ static int hisi_trng_del_from_list(struct hisi_trng *trng)
238287 int ret = - EBUSY ;
239288
240289 mutex_lock (& trng_devices .lock );
241- if (!trng -> is_used ) {
290+ if (!trng -> ctx_num ) {
242291 list_del (& trng -> list );
243292 ret = 0 ;
244293 }
@@ -262,7 +311,9 @@ static int hisi_trng_probe(struct platform_device *pdev)
262311 if (IS_ERR (trng -> base ))
263312 return PTR_ERR (trng -> base );
264313
265- trng -> is_used = false;
314+ trng -> ctx_num = 0 ;
315+ trng -> random_bytes = SW_MAX_RANDOM_BYTES ;
316+ mutex_init (& trng -> lock );
266317 trng -> ver = readl (trng -> base + HISI_TRNG_VERSION );
267318 if (!trng_devices .is_init ) {
268319 INIT_LIST_HEAD (& trng_devices .list );
0 commit comments