1ef4b04f8SRavi Kumar /* SPDX-License-Identifier: BSD-3-Clause 2ef4b04f8SRavi Kumar * Copyright(c) 2018 Advanced Micro Devices, Inc. All rights reserved. 3ef4b04f8SRavi Kumar */ 4ef4b04f8SRavi Kumar 5ef4b04f8SRavi Kumar #include <dirent.h> 6ef4b04f8SRavi Kumar #include <fcntl.h> 7ef4b04f8SRavi Kumar #include <stdio.h> 8ef4b04f8SRavi Kumar #include <string.h> 9ef4b04f8SRavi Kumar #include <sys/mman.h> 10ef4b04f8SRavi Kumar #include <sys/queue.h> 11ef4b04f8SRavi Kumar #include <sys/types.h> 12ef4b04f8SRavi Kumar #include <sys/file.h> 13ef4b04f8SRavi Kumar #include <unistd.h> 14ef4b04f8SRavi Kumar 15ef4b04f8SRavi Kumar #include <rte_hexdump.h> 16ef4b04f8SRavi Kumar #include <rte_memzone.h> 17ef4b04f8SRavi Kumar #include <rte_malloc.h> 18ef4b04f8SRavi Kumar #include <rte_memory.h> 19ef4b04f8SRavi Kumar #include <rte_spinlock.h> 20ef4b04f8SRavi Kumar #include <rte_string_fns.h> 21ef4b04f8SRavi Kumar 22ef4b04f8SRavi Kumar #include "ccp_dev.h" 23ef4b04f8SRavi Kumar #include "ccp_pmd_private.h" 24ef4b04f8SRavi Kumar 25e849b88fSDavid Marchand static TAILQ_HEAD(, ccp_device) ccp_list = TAILQ_HEAD_INITIALIZER(ccp_list); 26ef4b04f8SRavi Kumar static int ccp_dev_id; 27ef4b04f8SRavi Kumar 283c20cf98SRavi Kumar int 293c20cf98SRavi Kumar ccp_dev_start(struct rte_cryptodev *dev) 303c20cf98SRavi Kumar { 313c20cf98SRavi Kumar struct ccp_private *priv = dev->data->dev_private; 323c20cf98SRavi Kumar 333c20cf98SRavi Kumar priv->last_dev = TAILQ_FIRST(&ccp_list); 343c20cf98SRavi Kumar return 0; 353c20cf98SRavi Kumar } 363c20cf98SRavi Kumar 3770f0f8a8SRavi Kumar struct ccp_queue * 3870f0f8a8SRavi Kumar ccp_allot_queue(struct rte_cryptodev *cdev, int slot_req) 3970f0f8a8SRavi Kumar { 4070f0f8a8SRavi Kumar int i, ret = 0; 4170f0f8a8SRavi Kumar struct ccp_device *dev; 4270f0f8a8SRavi Kumar struct ccp_private *priv = cdev->data->dev_private; 4370f0f8a8SRavi Kumar 4470f0f8a8SRavi Kumar dev = TAILQ_NEXT(priv->last_dev, next); 4570f0f8a8SRavi Kumar if (unlikely(dev == NULL)) 4670f0f8a8SRavi Kumar dev = TAILQ_FIRST(&ccp_list); 4770f0f8a8SRavi Kumar priv->last_dev = dev; 4870f0f8a8SRavi Kumar if (dev->qidx >= dev->cmd_q_count) 4970f0f8a8SRavi Kumar dev->qidx = 0; 5070f0f8a8SRavi Kumar ret = rte_atomic64_read(&dev->cmd_q[dev->qidx].free_slots); 5170f0f8a8SRavi Kumar if (ret >= slot_req) 5270f0f8a8SRavi Kumar return &dev->cmd_q[dev->qidx]; 5370f0f8a8SRavi Kumar for (i = 0; i < dev->cmd_q_count; i++) { 5470f0f8a8SRavi Kumar dev->qidx++; 5570f0f8a8SRavi Kumar if (dev->qidx >= dev->cmd_q_count) 5670f0f8a8SRavi Kumar dev->qidx = 0; 5770f0f8a8SRavi Kumar ret = rte_atomic64_read(&dev->cmd_q[dev->qidx].free_slots); 5870f0f8a8SRavi Kumar if (ret >= slot_req) 5970f0f8a8SRavi Kumar return &dev->cmd_q[dev->qidx]; 6070f0f8a8SRavi Kumar } 6170f0f8a8SRavi Kumar return NULL; 6270f0f8a8SRavi Kumar } 6370f0f8a8SRavi Kumar 64585d4037SRavi Kumar int 65585d4037SRavi Kumar ccp_read_hwrng(uint32_t *value) 66585d4037SRavi Kumar { 67585d4037SRavi Kumar struct ccp_device *dev; 68585d4037SRavi Kumar 69585d4037SRavi Kumar TAILQ_FOREACH(dev, &ccp_list, next) { 70e849b88fSDavid Marchand void *vaddr = (void *)(dev->pci->mem_resource[2].addr); 71585d4037SRavi Kumar 72585d4037SRavi Kumar while (dev->hwrng_retries++ < CCP_MAX_TRNG_RETRIES) { 73585d4037SRavi Kumar *value = CCP_READ_REG(vaddr, TRNG_OUT_REG); 74585d4037SRavi Kumar if (*value) { 75585d4037SRavi Kumar dev->hwrng_retries = 0; 76585d4037SRavi Kumar return 0; 77585d4037SRavi Kumar } 78585d4037SRavi Kumar } 79585d4037SRavi Kumar dev->hwrng_retries = 0; 80585d4037SRavi Kumar } 81585d4037SRavi Kumar return -1; 82585d4037SRavi Kumar } 83585d4037SRavi Kumar 84ef4b04f8SRavi Kumar static const struct rte_memzone * 85ef4b04f8SRavi Kumar ccp_queue_dma_zone_reserve(const char *queue_name, 86ef4b04f8SRavi Kumar uint32_t queue_size, 87ef4b04f8SRavi Kumar int socket_id) 88ef4b04f8SRavi Kumar { 89ef4b04f8SRavi Kumar const struct rte_memzone *mz; 90ef4b04f8SRavi Kumar 91ef4b04f8SRavi Kumar mz = rte_memzone_lookup(queue_name); 92ef4b04f8SRavi Kumar if (mz != 0) { 93ef4b04f8SRavi Kumar if (((size_t)queue_size <= mz->len) && 94ef4b04f8SRavi Kumar ((socket_id == SOCKET_ID_ANY) || 95ef4b04f8SRavi Kumar (socket_id == mz->socket_id))) { 96ef4b04f8SRavi Kumar CCP_LOG_INFO("re-use memzone already " 97ef4b04f8SRavi Kumar "allocated for %s", queue_name); 98ef4b04f8SRavi Kumar return mz; 99ef4b04f8SRavi Kumar } 100ef4b04f8SRavi Kumar CCP_LOG_ERR("Incompatible memzone already " 101ef4b04f8SRavi Kumar "allocated %s, size %u, socket %d. " 102ef4b04f8SRavi Kumar "Requested size %u, socket %u", 103ef4b04f8SRavi Kumar queue_name, (uint32_t)mz->len, 104ef4b04f8SRavi Kumar mz->socket_id, queue_size, socket_id); 105ef4b04f8SRavi Kumar return NULL; 106ef4b04f8SRavi Kumar } 107ef4b04f8SRavi Kumar 108ef4b04f8SRavi Kumar CCP_LOG_INFO("Allocate memzone for %s, size %u on socket %u", 109ef4b04f8SRavi Kumar queue_name, queue_size, socket_id); 110ef4b04f8SRavi Kumar 111ef4b04f8SRavi Kumar return rte_memzone_reserve_aligned(queue_name, queue_size, 112ef4b04f8SRavi Kumar socket_id, RTE_MEMZONE_IOVA_CONTIG, queue_size); 113ef4b04f8SRavi Kumar } 114ef4b04f8SRavi Kumar 115ef4b04f8SRavi Kumar /* bitmap support apis */ 116ef4b04f8SRavi Kumar static inline void 117ef4b04f8SRavi Kumar ccp_set_bit(unsigned long *bitmap, int n) 118ef4b04f8SRavi Kumar { 119e12a0166STyler Retzlaff rte_atomic_fetch_or_explicit((unsigned long __rte_atomic *)&bitmap[WORD_OFFSET(n)], 120e12a0166STyler Retzlaff (1UL << BIT_OFFSET(n)), rte_memory_order_seq_cst); 121ef4b04f8SRavi Kumar } 122ef4b04f8SRavi Kumar 123ef4b04f8SRavi Kumar static inline void 124ef4b04f8SRavi Kumar ccp_clear_bit(unsigned long *bitmap, int n) 125ef4b04f8SRavi Kumar { 126e12a0166STyler Retzlaff rte_atomic_fetch_and_explicit((unsigned long __rte_atomic *)&bitmap[WORD_OFFSET(n)], 127e12a0166STyler Retzlaff ~(1UL << BIT_OFFSET(n)), rte_memory_order_seq_cst); 128ef4b04f8SRavi Kumar } 129ef4b04f8SRavi Kumar 130ef4b04f8SRavi Kumar static inline uint32_t 131ef4b04f8SRavi Kumar ccp_get_bit(unsigned long *bitmap, int n) 132ef4b04f8SRavi Kumar { 133ef4b04f8SRavi Kumar return ((bitmap[WORD_OFFSET(n)] & (1 << BIT_OFFSET(n))) != 0); 134ef4b04f8SRavi Kumar } 135ef4b04f8SRavi Kumar 136ef4b04f8SRavi Kumar 137ef4b04f8SRavi Kumar static inline uint32_t 138ef4b04f8SRavi Kumar ccp_ffz(unsigned long word) 139ef4b04f8SRavi Kumar { 140ef4b04f8SRavi Kumar unsigned long first_zero; 141ef4b04f8SRavi Kumar 142ef4b04f8SRavi Kumar first_zero = __builtin_ffsl(~word); 143ef4b04f8SRavi Kumar return first_zero ? (first_zero - 1) : 144ef4b04f8SRavi Kumar BITS_PER_WORD; 145ef4b04f8SRavi Kumar } 146ef4b04f8SRavi Kumar 147ef4b04f8SRavi Kumar static inline uint32_t 148ef4b04f8SRavi Kumar ccp_find_first_zero_bit(unsigned long *addr, uint32_t limit) 149ef4b04f8SRavi Kumar { 150ef4b04f8SRavi Kumar uint32_t i; 151ef4b04f8SRavi Kumar uint32_t nwords = 0; 152ef4b04f8SRavi Kumar 153ef4b04f8SRavi Kumar nwords = (limit - 1) / BITS_PER_WORD + 1; 154ef4b04f8SRavi Kumar for (i = 0; i < nwords; i++) { 155ef4b04f8SRavi Kumar if (addr[i] == 0UL) 156ef4b04f8SRavi Kumar return i * BITS_PER_WORD; 157ef4b04f8SRavi Kumar if (addr[i] < ~(0UL)) 158ef4b04f8SRavi Kumar break; 159ef4b04f8SRavi Kumar } 160ef4b04f8SRavi Kumar return (i == nwords) ? limit : i * BITS_PER_WORD + ccp_ffz(addr[i]); 161ef4b04f8SRavi Kumar } 162ef4b04f8SRavi Kumar 163ef4b04f8SRavi Kumar static void 164ef4b04f8SRavi Kumar ccp_bitmap_set(unsigned long *map, unsigned int start, int len) 165ef4b04f8SRavi Kumar { 166ef4b04f8SRavi Kumar unsigned long *p = map + WORD_OFFSET(start); 167ef4b04f8SRavi Kumar const unsigned int size = start + len; 168ef4b04f8SRavi Kumar int bits_to_set = BITS_PER_WORD - (start % BITS_PER_WORD); 169ef4b04f8SRavi Kumar unsigned long mask_to_set = CCP_BITMAP_FIRST_WORD_MASK(start); 170ef4b04f8SRavi Kumar 171ef4b04f8SRavi Kumar while (len - bits_to_set >= 0) { 172ef4b04f8SRavi Kumar *p |= mask_to_set; 173ef4b04f8SRavi Kumar len -= bits_to_set; 174ef4b04f8SRavi Kumar bits_to_set = BITS_PER_WORD; 175ef4b04f8SRavi Kumar mask_to_set = ~0UL; 176ef4b04f8SRavi Kumar p++; 177ef4b04f8SRavi Kumar } 178ef4b04f8SRavi Kumar if (len) { 179ef4b04f8SRavi Kumar mask_to_set &= CCP_BITMAP_LAST_WORD_MASK(size); 180ef4b04f8SRavi Kumar *p |= mask_to_set; 181ef4b04f8SRavi Kumar } 182ef4b04f8SRavi Kumar } 183ef4b04f8SRavi Kumar 184ef4b04f8SRavi Kumar static void 185ef4b04f8SRavi Kumar ccp_bitmap_clear(unsigned long *map, unsigned int start, int len) 186ef4b04f8SRavi Kumar { 187ef4b04f8SRavi Kumar unsigned long *p = map + WORD_OFFSET(start); 188ef4b04f8SRavi Kumar const unsigned int size = start + len; 189ef4b04f8SRavi Kumar int bits_to_clear = BITS_PER_WORD - (start % BITS_PER_WORD); 190ef4b04f8SRavi Kumar unsigned long mask_to_clear = CCP_BITMAP_FIRST_WORD_MASK(start); 191ef4b04f8SRavi Kumar 192ef4b04f8SRavi Kumar while (len - bits_to_clear >= 0) { 193ef4b04f8SRavi Kumar *p &= ~mask_to_clear; 194ef4b04f8SRavi Kumar len -= bits_to_clear; 195ef4b04f8SRavi Kumar bits_to_clear = BITS_PER_WORD; 196ef4b04f8SRavi Kumar mask_to_clear = ~0UL; 197ef4b04f8SRavi Kumar p++; 198ef4b04f8SRavi Kumar } 199ef4b04f8SRavi Kumar if (len) { 200ef4b04f8SRavi Kumar mask_to_clear &= CCP_BITMAP_LAST_WORD_MASK(size); 201ef4b04f8SRavi Kumar *p &= ~mask_to_clear; 202ef4b04f8SRavi Kumar } 203ef4b04f8SRavi Kumar } 204ef4b04f8SRavi Kumar 205ef4b04f8SRavi Kumar 206ef4b04f8SRavi Kumar static unsigned long 207ef4b04f8SRavi Kumar _ccp_find_next_bit(const unsigned long *addr, 208ef4b04f8SRavi Kumar unsigned long nbits, 209ef4b04f8SRavi Kumar unsigned long start, 210ef4b04f8SRavi Kumar unsigned long invert) 211ef4b04f8SRavi Kumar { 212ef4b04f8SRavi Kumar unsigned long tmp; 213ef4b04f8SRavi Kumar 214ef4b04f8SRavi Kumar if (!nbits || start >= nbits) 215ef4b04f8SRavi Kumar return nbits; 216ef4b04f8SRavi Kumar 217ef4b04f8SRavi Kumar tmp = addr[start / BITS_PER_WORD] ^ invert; 218ef4b04f8SRavi Kumar 219ef4b04f8SRavi Kumar /* Handle 1st word. */ 220ef4b04f8SRavi Kumar tmp &= CCP_BITMAP_FIRST_WORD_MASK(start); 221ef4b04f8SRavi Kumar start = ccp_round_down(start, BITS_PER_WORD); 222ef4b04f8SRavi Kumar 223ef4b04f8SRavi Kumar while (!tmp) { 224ef4b04f8SRavi Kumar start += BITS_PER_WORD; 225ef4b04f8SRavi Kumar if (start >= nbits) 226ef4b04f8SRavi Kumar return nbits; 227ef4b04f8SRavi Kumar 228ef4b04f8SRavi Kumar tmp = addr[start / BITS_PER_WORD] ^ invert; 229ef4b04f8SRavi Kumar } 230ef4b04f8SRavi Kumar 231ef4b04f8SRavi Kumar return RTE_MIN(start + (ffs(tmp) - 1), nbits); 232ef4b04f8SRavi Kumar } 233ef4b04f8SRavi Kumar 234ef4b04f8SRavi Kumar static unsigned long 235ef4b04f8SRavi Kumar ccp_find_next_bit(const unsigned long *addr, 236ef4b04f8SRavi Kumar unsigned long size, 237ef4b04f8SRavi Kumar unsigned long offset) 238ef4b04f8SRavi Kumar { 239ef4b04f8SRavi Kumar return _ccp_find_next_bit(addr, size, offset, 0UL); 240ef4b04f8SRavi Kumar } 241ef4b04f8SRavi Kumar 242ef4b04f8SRavi Kumar static unsigned long 243ef4b04f8SRavi Kumar ccp_find_next_zero_bit(const unsigned long *addr, 244ef4b04f8SRavi Kumar unsigned long size, 245ef4b04f8SRavi Kumar unsigned long offset) 246ef4b04f8SRavi Kumar { 247ef4b04f8SRavi Kumar return _ccp_find_next_bit(addr, size, offset, ~0UL); 248ef4b04f8SRavi Kumar } 249ef4b04f8SRavi Kumar 250ef4b04f8SRavi Kumar /** 251ef4b04f8SRavi Kumar * bitmap_find_next_zero_area - find a contiguous aligned zero area 252ef4b04f8SRavi Kumar * @map: The address to base the search on 253ef4b04f8SRavi Kumar * @size: The bitmap size in bits 254ef4b04f8SRavi Kumar * @start: The bitnumber to start searching at 255ef4b04f8SRavi Kumar * @nr: The number of zeroed bits we're looking for 256ef4b04f8SRavi Kumar */ 257ef4b04f8SRavi Kumar static unsigned long 258ef4b04f8SRavi Kumar ccp_bitmap_find_next_zero_area(unsigned long *map, 259ef4b04f8SRavi Kumar unsigned long size, 260ef4b04f8SRavi Kumar unsigned long start, 261ef4b04f8SRavi Kumar unsigned int nr) 262ef4b04f8SRavi Kumar { 263ef4b04f8SRavi Kumar unsigned long index, end, i; 264ef4b04f8SRavi Kumar 265ef4b04f8SRavi Kumar again: 266ef4b04f8SRavi Kumar index = ccp_find_next_zero_bit(map, size, start); 267ef4b04f8SRavi Kumar 268ef4b04f8SRavi Kumar end = index + nr; 269ef4b04f8SRavi Kumar if (end > size) 270ef4b04f8SRavi Kumar return end; 271ef4b04f8SRavi Kumar i = ccp_find_next_bit(map, end, index); 272ef4b04f8SRavi Kumar if (i < end) { 273ef4b04f8SRavi Kumar start = i + 1; 274ef4b04f8SRavi Kumar goto again; 275ef4b04f8SRavi Kumar } 276ef4b04f8SRavi Kumar return index; 277ef4b04f8SRavi Kumar } 278ef4b04f8SRavi Kumar 279ef4b04f8SRavi Kumar static uint32_t 280ef4b04f8SRavi Kumar ccp_lsb_alloc(struct ccp_queue *cmd_q, unsigned int count) 281ef4b04f8SRavi Kumar { 282ef4b04f8SRavi Kumar struct ccp_device *ccp; 283ef4b04f8SRavi Kumar int start; 284ef4b04f8SRavi Kumar 285ef4b04f8SRavi Kumar /* First look at the map for the queue */ 286ef4b04f8SRavi Kumar if (cmd_q->lsb >= 0) { 287ef4b04f8SRavi Kumar start = (uint32_t)ccp_bitmap_find_next_zero_area(cmd_q->lsbmap, 288ef4b04f8SRavi Kumar LSB_SIZE, 0, 289ef4b04f8SRavi Kumar count); 290ef4b04f8SRavi Kumar if (start < LSB_SIZE) { 291ef4b04f8SRavi Kumar ccp_bitmap_set(cmd_q->lsbmap, start, count); 292ef4b04f8SRavi Kumar return start + cmd_q->lsb * LSB_SIZE; 293ef4b04f8SRavi Kumar } 294ef4b04f8SRavi Kumar } 295ef4b04f8SRavi Kumar 296ef4b04f8SRavi Kumar /* try to get an entry from the shared blocks */ 297ef4b04f8SRavi Kumar ccp = cmd_q->dev; 298ef4b04f8SRavi Kumar 299ef4b04f8SRavi Kumar rte_spinlock_lock(&ccp->lsb_lock); 300ef4b04f8SRavi Kumar 301ef4b04f8SRavi Kumar start = (uint32_t)ccp_bitmap_find_next_zero_area(ccp->lsbmap, 302ef4b04f8SRavi Kumar MAX_LSB_CNT * LSB_SIZE, 303ef4b04f8SRavi Kumar 0, count); 304ef4b04f8SRavi Kumar if (start <= MAX_LSB_CNT * LSB_SIZE) { 305ef4b04f8SRavi Kumar ccp_bitmap_set(ccp->lsbmap, start, count); 306ef4b04f8SRavi Kumar rte_spinlock_unlock(&ccp->lsb_lock); 307ef4b04f8SRavi Kumar return start * LSB_ITEM_SIZE; 308ef4b04f8SRavi Kumar } 309ef4b04f8SRavi Kumar CCP_LOG_ERR("NO LSBs available"); 310ef4b04f8SRavi Kumar 311ef4b04f8SRavi Kumar rte_spinlock_unlock(&ccp->lsb_lock); 312ef4b04f8SRavi Kumar 313ef4b04f8SRavi Kumar return 0; 314ef4b04f8SRavi Kumar } 315ef4b04f8SRavi Kumar 316ef4b04f8SRavi Kumar static void __rte_unused 317ef4b04f8SRavi Kumar ccp_lsb_free(struct ccp_queue *cmd_q, 318ef4b04f8SRavi Kumar unsigned int start, 319ef4b04f8SRavi Kumar unsigned int count) 320ef4b04f8SRavi Kumar { 321ef4b04f8SRavi Kumar int lsbno = start / LSB_SIZE; 322ef4b04f8SRavi Kumar 323ef4b04f8SRavi Kumar if (!start) 324ef4b04f8SRavi Kumar return; 325ef4b04f8SRavi Kumar 326ef4b04f8SRavi Kumar if (cmd_q->lsb == lsbno) { 327ef4b04f8SRavi Kumar /* An entry from the private LSB */ 328ef4b04f8SRavi Kumar ccp_bitmap_clear(cmd_q->lsbmap, start % LSB_SIZE, count); 329ef4b04f8SRavi Kumar } else { 330ef4b04f8SRavi Kumar /* From the shared LSBs */ 331ef4b04f8SRavi Kumar struct ccp_device *ccp = cmd_q->dev; 332ef4b04f8SRavi Kumar 333ef4b04f8SRavi Kumar rte_spinlock_lock(&ccp->lsb_lock); 334ef4b04f8SRavi Kumar ccp_bitmap_clear(ccp->lsbmap, start, count); 335ef4b04f8SRavi Kumar rte_spinlock_unlock(&ccp->lsb_lock); 336ef4b04f8SRavi Kumar } 337ef4b04f8SRavi Kumar } 338ef4b04f8SRavi Kumar 339ef4b04f8SRavi Kumar static int 340ef4b04f8SRavi Kumar ccp_find_lsb_regions(struct ccp_queue *cmd_q, uint64_t status) 341ef4b04f8SRavi Kumar { 342ef4b04f8SRavi Kumar int q_mask = 1 << cmd_q->id; 343ef4b04f8SRavi Kumar int weight = 0; 344ef4b04f8SRavi Kumar int j; 345ef4b04f8SRavi Kumar 346ef4b04f8SRavi Kumar /* Build a bit mask to know which LSBs 347ef4b04f8SRavi Kumar * this queue has access to. 348ef4b04f8SRavi Kumar * Don't bother with segment 0 349ef4b04f8SRavi Kumar * as it has special 350ef4b04f8SRavi Kumar * privileges. 351ef4b04f8SRavi Kumar */ 352ef4b04f8SRavi Kumar cmd_q->lsbmask = 0; 353ef4b04f8SRavi Kumar status >>= LSB_REGION_WIDTH; 354ef4b04f8SRavi Kumar for (j = 1; j < MAX_LSB_CNT; j++) { 355ef4b04f8SRavi Kumar if (status & q_mask) 356ef4b04f8SRavi Kumar ccp_set_bit(&cmd_q->lsbmask, j); 357ef4b04f8SRavi Kumar 358ef4b04f8SRavi Kumar status >>= LSB_REGION_WIDTH; 359ef4b04f8SRavi Kumar } 360ef4b04f8SRavi Kumar 361ef4b04f8SRavi Kumar for (j = 0; j < MAX_LSB_CNT; j++) 362ef4b04f8SRavi Kumar if (ccp_get_bit(&cmd_q->lsbmask, j)) 363ef4b04f8SRavi Kumar weight++; 364ef4b04f8SRavi Kumar 365*f665790aSDavid Marchand CCP_LOG_DBG("Queue %d can access %d LSB regions of mask %lu", 366ef4b04f8SRavi Kumar (int)cmd_q->id, weight, cmd_q->lsbmask); 367ef4b04f8SRavi Kumar 368ef4b04f8SRavi Kumar return weight ? 0 : -EINVAL; 369ef4b04f8SRavi Kumar } 370ef4b04f8SRavi Kumar 371ef4b04f8SRavi Kumar static int 372ef4b04f8SRavi Kumar ccp_find_and_assign_lsb_to_q(struct ccp_device *ccp, 373ef4b04f8SRavi Kumar int lsb_cnt, int n_lsbs, 374ef4b04f8SRavi Kumar unsigned long *lsb_pub) 375ef4b04f8SRavi Kumar { 376ef4b04f8SRavi Kumar unsigned long qlsb = 0; 377ef4b04f8SRavi Kumar int bitno = 0; 378ef4b04f8SRavi Kumar int qlsb_wgt = 0; 379ef4b04f8SRavi Kumar int i, j; 380ef4b04f8SRavi Kumar 381ef4b04f8SRavi Kumar /* For each queue: 382ef4b04f8SRavi Kumar * If the count of potential LSBs available to a queue matches the 383ef4b04f8SRavi Kumar * ordinal given to us in lsb_cnt: 384ef4b04f8SRavi Kumar * Copy the mask of possible LSBs for this queue into "qlsb"; 385ef4b04f8SRavi Kumar * For each bit in qlsb, see if the corresponding bit in the 386ef4b04f8SRavi Kumar * aggregation mask is set; if so, we have a match. 387ef4b04f8SRavi Kumar * If we have a match, clear the bit in the aggregation to 388ef4b04f8SRavi Kumar * mark it as no longer available. 389ef4b04f8SRavi Kumar * If there is no match, clear the bit in qlsb and keep looking. 390ef4b04f8SRavi Kumar */ 391ef4b04f8SRavi Kumar for (i = 0; i < ccp->cmd_q_count; i++) { 392ef4b04f8SRavi Kumar struct ccp_queue *cmd_q = &ccp->cmd_q[i]; 393ef4b04f8SRavi Kumar 394ef4b04f8SRavi Kumar qlsb_wgt = 0; 395ef4b04f8SRavi Kumar for (j = 0; j < MAX_LSB_CNT; j++) 396ef4b04f8SRavi Kumar if (ccp_get_bit(&cmd_q->lsbmask, j)) 397ef4b04f8SRavi Kumar qlsb_wgt++; 398ef4b04f8SRavi Kumar 399ef4b04f8SRavi Kumar if (qlsb_wgt == lsb_cnt) { 400ef4b04f8SRavi Kumar qlsb = cmd_q->lsbmask; 401ef4b04f8SRavi Kumar 402ef4b04f8SRavi Kumar bitno = ffs(qlsb) - 1; 403ef4b04f8SRavi Kumar while (bitno < MAX_LSB_CNT) { 404ef4b04f8SRavi Kumar if (ccp_get_bit(lsb_pub, bitno)) { 405ef4b04f8SRavi Kumar /* We found an available LSB 406ef4b04f8SRavi Kumar * that this queue can access 407ef4b04f8SRavi Kumar */ 408ef4b04f8SRavi Kumar cmd_q->lsb = bitno; 409ef4b04f8SRavi Kumar ccp_clear_bit(lsb_pub, bitno); 410ef4b04f8SRavi Kumar break; 411ef4b04f8SRavi Kumar } 412ef4b04f8SRavi Kumar ccp_clear_bit(&qlsb, bitno); 413ef4b04f8SRavi Kumar bitno = ffs(qlsb) - 1; 414ef4b04f8SRavi Kumar } 415ef4b04f8SRavi Kumar if (bitno >= MAX_LSB_CNT) 416ef4b04f8SRavi Kumar return -EINVAL; 417ef4b04f8SRavi Kumar n_lsbs--; 418ef4b04f8SRavi Kumar } 419ef4b04f8SRavi Kumar } 420ef4b04f8SRavi Kumar return n_lsbs; 421ef4b04f8SRavi Kumar } 422ef4b04f8SRavi Kumar 423ef4b04f8SRavi Kumar /* For each queue, from the most- to least-constrained: 424ef4b04f8SRavi Kumar * find an LSB that can be assigned to the queue. If there are N queues that 425ef4b04f8SRavi Kumar * can only use M LSBs, where N > M, fail; otherwise, every queue will get a 426ef4b04f8SRavi Kumar * dedicated LSB. Remaining LSB regions become a shared resource. 427ef4b04f8SRavi Kumar * If we have fewer LSBs than queues, all LSB regions become shared 428ef4b04f8SRavi Kumar * resources. 429ef4b04f8SRavi Kumar */ 430ef4b04f8SRavi Kumar static int 431ef4b04f8SRavi Kumar ccp_assign_lsbs(struct ccp_device *ccp) 432ef4b04f8SRavi Kumar { 433ef4b04f8SRavi Kumar unsigned long lsb_pub = 0, qlsb = 0; 434ef4b04f8SRavi Kumar int n_lsbs = 0; 435ef4b04f8SRavi Kumar int bitno; 436ef4b04f8SRavi Kumar int i, lsb_cnt; 437ef4b04f8SRavi Kumar int rc = 0; 438ef4b04f8SRavi Kumar 439ef4b04f8SRavi Kumar rte_spinlock_init(&ccp->lsb_lock); 440ef4b04f8SRavi Kumar 441ef4b04f8SRavi Kumar /* Create an aggregate bitmap to get a total count of available LSBs */ 442ef4b04f8SRavi Kumar for (i = 0; i < ccp->cmd_q_count; i++) 443ef4b04f8SRavi Kumar lsb_pub |= ccp->cmd_q[i].lsbmask; 444ef4b04f8SRavi Kumar 445ef4b04f8SRavi Kumar for (i = 0; i < MAX_LSB_CNT; i++) 446ef4b04f8SRavi Kumar if (ccp_get_bit(&lsb_pub, i)) 447ef4b04f8SRavi Kumar n_lsbs++; 448ef4b04f8SRavi Kumar 449ef4b04f8SRavi Kumar if (n_lsbs >= ccp->cmd_q_count) { 450ef4b04f8SRavi Kumar /* We have enough LSBS to give every queue a private LSB. 451ef4b04f8SRavi Kumar * Brute force search to start with the queues that are more 452ef4b04f8SRavi Kumar * constrained in LSB choice. When an LSB is privately 453ef4b04f8SRavi Kumar * assigned, it is removed from the public mask. 454ef4b04f8SRavi Kumar * This is an ugly N squared algorithm with some optimization. 455ef4b04f8SRavi Kumar */ 456ef4b04f8SRavi Kumar for (lsb_cnt = 1; n_lsbs && (lsb_cnt <= MAX_LSB_CNT); 457ef4b04f8SRavi Kumar lsb_cnt++) { 458ef4b04f8SRavi Kumar rc = ccp_find_and_assign_lsb_to_q(ccp, lsb_cnt, n_lsbs, 459ef4b04f8SRavi Kumar &lsb_pub); 460ef4b04f8SRavi Kumar if (rc < 0) 461ef4b04f8SRavi Kumar return -EINVAL; 462ef4b04f8SRavi Kumar n_lsbs = rc; 463ef4b04f8SRavi Kumar } 464ef4b04f8SRavi Kumar } 465ef4b04f8SRavi Kumar 466ef4b04f8SRavi Kumar rc = 0; 467ef4b04f8SRavi Kumar /* What's left of the LSBs, according to the public mask, now become 468ef4b04f8SRavi Kumar * shared. Any zero bits in the lsb_pub mask represent an LSB region 469ef4b04f8SRavi Kumar * that can't be used as a shared resource, so mark the LSB slots for 470ef4b04f8SRavi Kumar * them as "in use". 471ef4b04f8SRavi Kumar */ 472ef4b04f8SRavi Kumar qlsb = lsb_pub; 473ef4b04f8SRavi Kumar bitno = ccp_find_first_zero_bit(&qlsb, MAX_LSB_CNT); 474ef4b04f8SRavi Kumar while (bitno < MAX_LSB_CNT) { 475ef4b04f8SRavi Kumar ccp_bitmap_set(ccp->lsbmap, bitno * LSB_SIZE, LSB_SIZE); 476ef4b04f8SRavi Kumar ccp_set_bit(&qlsb, bitno); 477ef4b04f8SRavi Kumar bitno = ccp_find_first_zero_bit(&qlsb, MAX_LSB_CNT); 478ef4b04f8SRavi Kumar } 479ef4b04f8SRavi Kumar 480ef4b04f8SRavi Kumar return rc; 481ef4b04f8SRavi Kumar } 482ef4b04f8SRavi Kumar 483ef4b04f8SRavi Kumar static int 484e849b88fSDavid Marchand ccp_add_device(struct ccp_device *dev) 485ef4b04f8SRavi Kumar { 486ef4b04f8SRavi Kumar int i; 487ef4b04f8SRavi Kumar uint32_t qmr, status_lo, status_hi, dma_addr_lo, dma_addr_hi; 488ef4b04f8SRavi Kumar uint64_t status; 489ef4b04f8SRavi Kumar struct ccp_queue *cmd_q; 490ef4b04f8SRavi Kumar const struct rte_memzone *q_mz; 491ef4b04f8SRavi Kumar void *vaddr; 492ef4b04f8SRavi Kumar 493ef4b04f8SRavi Kumar if (dev == NULL) 494ef4b04f8SRavi Kumar return -1; 495ef4b04f8SRavi Kumar 496ef4b04f8SRavi Kumar dev->id = ccp_dev_id++; 497ef4b04f8SRavi Kumar dev->qidx = 0; 498e849b88fSDavid Marchand vaddr = (void *)(dev->pci->mem_resource[2].addr); 499ef4b04f8SRavi Kumar 500e849b88fSDavid Marchand if (dev->pci->id.device_id == AMD_PCI_CCP_5B) { 501ef4b04f8SRavi Kumar CCP_WRITE_REG(vaddr, CMD_TRNG_CTL_OFFSET, 0x00012D57); 502ef4b04f8SRavi Kumar CCP_WRITE_REG(vaddr, CMD_CONFIG_0_OFFSET, 0x00000003); 503ef4b04f8SRavi Kumar for (i = 0; i < 12; i++) { 504ef4b04f8SRavi Kumar CCP_WRITE_REG(vaddr, CMD_AES_MASK_OFFSET, 505ef4b04f8SRavi Kumar CCP_READ_REG(vaddr, TRNG_OUT_REG)); 506ef4b04f8SRavi Kumar } 507ef4b04f8SRavi Kumar CCP_WRITE_REG(vaddr, CMD_QUEUE_MASK_OFFSET, 0x0000001F); 508ef4b04f8SRavi Kumar CCP_WRITE_REG(vaddr, CMD_QUEUE_PRIO_OFFSET, 0x00005B6D); 509ef4b04f8SRavi Kumar CCP_WRITE_REG(vaddr, CMD_CMD_TIMEOUT_OFFSET, 0x00000000); 510ef4b04f8SRavi Kumar 511ef4b04f8SRavi Kumar CCP_WRITE_REG(vaddr, LSB_PRIVATE_MASK_LO_OFFSET, 0x3FFFFFFF); 512ef4b04f8SRavi Kumar CCP_WRITE_REG(vaddr, LSB_PRIVATE_MASK_HI_OFFSET, 0x000003FF); 513ef4b04f8SRavi Kumar 514ef4b04f8SRavi Kumar CCP_WRITE_REG(vaddr, CMD_CLK_GATE_CTL_OFFSET, 0x00108823); 515ef4b04f8SRavi Kumar } 51609a0fd73SAmaranath Somalapuram CCP_WRITE_REG(vaddr, CMD_REQID_CONFIG_OFFSET, 0x0); 517ef4b04f8SRavi Kumar 518ef4b04f8SRavi Kumar /* Copy the private LSB mask to the public registers */ 519ef4b04f8SRavi Kumar status_lo = CCP_READ_REG(vaddr, LSB_PRIVATE_MASK_LO_OFFSET); 520ef4b04f8SRavi Kumar status_hi = CCP_READ_REG(vaddr, LSB_PRIVATE_MASK_HI_OFFSET); 521ef4b04f8SRavi Kumar CCP_WRITE_REG(vaddr, LSB_PUBLIC_MASK_LO_OFFSET, status_lo); 522ef4b04f8SRavi Kumar CCP_WRITE_REG(vaddr, LSB_PUBLIC_MASK_HI_OFFSET, status_hi); 523ef4b04f8SRavi Kumar status = ((uint64_t)status_hi<<30) | ((uint64_t)status_lo); 524ef4b04f8SRavi Kumar 525ef4b04f8SRavi Kumar dev->cmd_q_count = 0; 526ef4b04f8SRavi Kumar /* Find available queues */ 527ef4b04f8SRavi Kumar qmr = CCP_READ_REG(vaddr, Q_MASK_REG); 528ef4b04f8SRavi Kumar for (i = 0; i < MAX_HW_QUEUES; i++) { 529ef4b04f8SRavi Kumar if (!(qmr & (1 << i))) 530ef4b04f8SRavi Kumar continue; 531ef4b04f8SRavi Kumar cmd_q = &dev->cmd_q[dev->cmd_q_count++]; 532ef4b04f8SRavi Kumar cmd_q->dev = dev; 533ef4b04f8SRavi Kumar cmd_q->id = i; 534ef4b04f8SRavi Kumar cmd_q->qidx = 0; 535ef4b04f8SRavi Kumar cmd_q->qsize = Q_SIZE(Q_DESC_SIZE); 536ef4b04f8SRavi Kumar 537ef4b04f8SRavi Kumar cmd_q->reg_base = (uint8_t *)vaddr + 538ef4b04f8SRavi Kumar CMD_Q_STATUS_INCR * (i + 1); 539ef4b04f8SRavi Kumar 540ef4b04f8SRavi Kumar /* CCP queue memory */ 541ef4b04f8SRavi Kumar snprintf(cmd_q->memz_name, sizeof(cmd_q->memz_name), 542ef4b04f8SRavi Kumar "%s_%d_%s_%d_%s", 543ef4b04f8SRavi Kumar "ccp_dev", 544ef4b04f8SRavi Kumar (int)dev->id, "queue", 545ef4b04f8SRavi Kumar (int)cmd_q->id, "mem"); 546ef4b04f8SRavi Kumar q_mz = ccp_queue_dma_zone_reserve(cmd_q->memz_name, 547ef4b04f8SRavi Kumar cmd_q->qsize, SOCKET_ID_ANY); 548ef4b04f8SRavi Kumar cmd_q->qbase_addr = (void *)q_mz->addr; 549ef4b04f8SRavi Kumar cmd_q->qbase_desc = (void *)q_mz->addr; 55072f82c43SThomas Monjalon cmd_q->qbase_phys_addr = q_mz->iova; 551ef4b04f8SRavi Kumar 552ef4b04f8SRavi Kumar cmd_q->qcontrol = 0; 553ef4b04f8SRavi Kumar /* init control reg to zero */ 554ef4b04f8SRavi Kumar CCP_WRITE_REG(cmd_q->reg_base, CMD_Q_CONTROL_BASE, 555ef4b04f8SRavi Kumar cmd_q->qcontrol); 556ef4b04f8SRavi Kumar 557ef4b04f8SRavi Kumar /* Disable the interrupts */ 558ef4b04f8SRavi Kumar CCP_WRITE_REG(cmd_q->reg_base, CMD_Q_INT_ENABLE_BASE, 0x00); 559ef4b04f8SRavi Kumar CCP_READ_REG(cmd_q->reg_base, CMD_Q_INT_STATUS_BASE); 560ef4b04f8SRavi Kumar CCP_READ_REG(cmd_q->reg_base, CMD_Q_STATUS_BASE); 561ef4b04f8SRavi Kumar 562ef4b04f8SRavi Kumar /* Clear the interrupts */ 563ef4b04f8SRavi Kumar CCP_WRITE_REG(cmd_q->reg_base, CMD_Q_INTERRUPT_STATUS_BASE, 564ef4b04f8SRavi Kumar ALL_INTERRUPTS); 565ef4b04f8SRavi Kumar 566ef4b04f8SRavi Kumar /* Configure size of each virtual queue accessible to host */ 567ef4b04f8SRavi Kumar cmd_q->qcontrol &= ~(CMD_Q_SIZE << CMD_Q_SHIFT); 568ef4b04f8SRavi Kumar cmd_q->qcontrol |= QUEUE_SIZE_VAL << CMD_Q_SHIFT; 569ef4b04f8SRavi Kumar 570ef4b04f8SRavi Kumar dma_addr_lo = low32_value(cmd_q->qbase_phys_addr); 571ef4b04f8SRavi Kumar CCP_WRITE_REG(cmd_q->reg_base, CMD_Q_TAIL_LO_BASE, 572ef4b04f8SRavi Kumar (uint32_t)dma_addr_lo); 573ef4b04f8SRavi Kumar CCP_WRITE_REG(cmd_q->reg_base, CMD_Q_HEAD_LO_BASE, 574ef4b04f8SRavi Kumar (uint32_t)dma_addr_lo); 575ef4b04f8SRavi Kumar 576ef4b04f8SRavi Kumar dma_addr_hi = high32_value(cmd_q->qbase_phys_addr); 577ef4b04f8SRavi Kumar cmd_q->qcontrol |= (dma_addr_hi << 16); 578ef4b04f8SRavi Kumar CCP_WRITE_REG(cmd_q->reg_base, CMD_Q_CONTROL_BASE, 579ef4b04f8SRavi Kumar cmd_q->qcontrol); 580ef4b04f8SRavi Kumar 581ef4b04f8SRavi Kumar /* create LSB Mask map */ 582ef4b04f8SRavi Kumar if (ccp_find_lsb_regions(cmd_q, status)) 583ef4b04f8SRavi Kumar CCP_LOG_ERR("queue doesn't have lsb regions"); 584ef4b04f8SRavi Kumar cmd_q->lsb = -1; 585ef4b04f8SRavi Kumar 586ef4b04f8SRavi Kumar rte_atomic64_init(&cmd_q->free_slots); 587ef4b04f8SRavi Kumar rte_atomic64_set(&cmd_q->free_slots, (COMMANDS_PER_QUEUE - 1)); 588ef4b04f8SRavi Kumar /* unused slot barrier b/w H&T */ 589ef4b04f8SRavi Kumar } 590ef4b04f8SRavi Kumar 591ef4b04f8SRavi Kumar if (ccp_assign_lsbs(dev)) 592ef4b04f8SRavi Kumar CCP_LOG_ERR("Unable to assign lsb region"); 593ef4b04f8SRavi Kumar 594ef4b04f8SRavi Kumar /* pre-allocate LSB slots */ 595ef4b04f8SRavi Kumar for (i = 0; i < dev->cmd_q_count; i++) { 596ef4b04f8SRavi Kumar dev->cmd_q[i].sb_key = 597ef4b04f8SRavi Kumar ccp_lsb_alloc(&dev->cmd_q[i], 1); 598ef4b04f8SRavi Kumar dev->cmd_q[i].sb_iv = 599ef4b04f8SRavi Kumar ccp_lsb_alloc(&dev->cmd_q[i], 1); 600ef4b04f8SRavi Kumar dev->cmd_q[i].sb_sha = 601ef4b04f8SRavi Kumar ccp_lsb_alloc(&dev->cmd_q[i], 2); 602ef4b04f8SRavi Kumar dev->cmd_q[i].sb_hmac = 603ef4b04f8SRavi Kumar ccp_lsb_alloc(&dev->cmd_q[i], 2); 604ef4b04f8SRavi Kumar } 605ef4b04f8SRavi Kumar 606ef4b04f8SRavi Kumar TAILQ_INSERT_TAIL(&ccp_list, dev, next); 607ef4b04f8SRavi Kumar return 0; 608ef4b04f8SRavi Kumar } 609ef4b04f8SRavi Kumar 610ef4b04f8SRavi Kumar static void 611ef4b04f8SRavi Kumar ccp_remove_device(struct ccp_device *dev) 612ef4b04f8SRavi Kumar { 613ef4b04f8SRavi Kumar if (dev == NULL) 614ef4b04f8SRavi Kumar return; 615ef4b04f8SRavi Kumar 616ef4b04f8SRavi Kumar TAILQ_REMOVE(&ccp_list, dev, next); 617ef4b04f8SRavi Kumar } 618ef4b04f8SRavi Kumar 619e849b88fSDavid Marchand int 620e849b88fSDavid Marchand ccp_probe_device(struct rte_pci_device *pci_dev) 621ef4b04f8SRavi Kumar { 6229631fb8fSDavid Marchand struct ccp_device *ccp_dev; 623ef4b04f8SRavi Kumar 624ef4b04f8SRavi Kumar ccp_dev = rte_zmalloc("ccp_device", sizeof(*ccp_dev), 625ef4b04f8SRavi Kumar RTE_CACHE_LINE_SIZE); 626ef4b04f8SRavi Kumar if (ccp_dev == NULL) 627ef4b04f8SRavi Kumar goto fail; 628ef4b04f8SRavi Kumar 629e849b88fSDavid Marchand ccp_dev->pci = pci_dev; 630ef4b04f8SRavi Kumar 631ef4b04f8SRavi Kumar /* device is valid, add in list */ 632e849b88fSDavid Marchand if (ccp_add_device(ccp_dev)) { 633ef4b04f8SRavi Kumar ccp_remove_device(ccp_dev); 634ef4b04f8SRavi Kumar goto fail; 635ef4b04f8SRavi Kumar } 636ef4b04f8SRavi Kumar 637ef4b04f8SRavi Kumar return 0; 638ef4b04f8SRavi Kumar fail: 639ef4b04f8SRavi Kumar CCP_LOG_ERR("CCP Device probe failed"); 640ef4b04f8SRavi Kumar rte_free(ccp_dev); 641ef4b04f8SRavi Kumar return -1; 642ef4b04f8SRavi Kumar } 643