^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Routines supporting the Power 7+ Nest Accelerators driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2011-2012 International Business Machines Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Author: Kent Yoder <yoder1@us.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <crypto/internal/aead.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <crypto/internal/hash.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <crypto/aes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <crypto/sha.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <crypto/algapi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <crypto/scatterwalk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/moduleparam.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/scatterlist.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <asm/hvcall.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <asm/vio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include "nx_csbcpb.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include "nx.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * nx_hcall_sync - make an H_COP_OP hcall for the passed in op structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * @nx_ctx: the crypto context handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * @op: PFO operation struct to pass in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * @may_sleep: flag indicating the request can sleep
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * Make the hcall, retrying while the hardware is busy. If we cannot yield
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * the thread, limit the number of retries to 10 here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) int nx_hcall_sync(struct nx_crypto_ctx *nx_ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) struct vio_pfo_op *op,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) u32 may_sleep)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) int rc, retries = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct vio_dev *viodev = nx_driver.viodev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) atomic_inc(&(nx_ctx->stats->sync_ops));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) rc = vio_h_cop_sync(viodev, op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) } while (rc == -EBUSY && !may_sleep && retries--);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) dev_dbg(&viodev->dev, "vio_h_cop_sync failed: rc: %d "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) "hcall rc: %ld\n", rc, op->hcall_err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) atomic_inc(&(nx_ctx->stats->errors));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) atomic_set(&(nx_ctx->stats->last_error), op->hcall_err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) atomic_set(&(nx_ctx->stats->last_error_pid), current->pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * nx_build_sg_list - build an NX scatter list describing a single buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * @sg_head: pointer to the first scatter list element to build
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * @start_addr: pointer to the linear buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * @len: length of the data at @start_addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * @sgmax: the largest number of scatter list elements we're allowed to create
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * This function will start writing nx_sg elements at @sg_head and keep
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * writing them until all of the data from @start_addr is described or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * until sgmax elements have been written. Scatter list elements will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * created such that none of the elements describes a buffer that crosses a 4K
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * boundary.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct nx_sg *nx_build_sg_list(struct nx_sg *sg_head,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) u8 *start_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) unsigned int *len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) u32 sgmax)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) unsigned int sg_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) struct nx_sg *sg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) u64 sg_addr = (u64)start_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) u64 end_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) /* determine the start and end for this address range - slightly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * different if this is in VMALLOC_REGION */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if (is_vmalloc_addr(start_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) sg_addr = page_to_phys(vmalloc_to_page(start_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) + offset_in_page(sg_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) sg_addr = __pa(sg_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) end_addr = sg_addr + *len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) /* each iteration will write one struct nx_sg element and add the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * length of data described by that element to sg_len. Once @len bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * have been described (or @sgmax elements have been written), the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * loop ends. min_t is used to ensure @end_addr falls on the same page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * as sg_addr, if not, we need to create another nx_sg element for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * data on the next page.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * Also when using vmalloc'ed data, every time that a system page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * boundary is crossed the physical address needs to be re-calculated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) for (sg = sg_head; sg_len < *len; sg++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) u64 next_page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) sg->addr = sg_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) sg_addr = min_t(u64, NX_PAGE_NUM(sg_addr + NX_PAGE_SIZE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) end_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) next_page = (sg->addr & PAGE_MASK) + PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) sg->len = min_t(u64, sg_addr, next_page) - sg->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) sg_len += sg->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if (sg_addr >= next_page &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) is_vmalloc_addr(start_addr + sg_len)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) sg_addr = page_to_phys(vmalloc_to_page(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) start_addr + sg_len));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) end_addr = sg_addr + *len - sg_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) if ((sg - sg_head) == sgmax) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) pr_err("nx: scatter/gather list overflow, pid: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) current->pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) sg++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) *len = sg_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) /* return the moved sg_head pointer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return sg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * nx_walk_and_build - walk a linux scatterlist and build an nx scatterlist
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * @nx_dst: pointer to the first nx_sg element to write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * @sglen: max number of nx_sg entries we're allowed to write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * @sg_src: pointer to the source linux scatterlist to walk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * @start: number of bytes to fast-forward past at the beginning of @sg_src
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) * @src_len: number of bytes to walk in @sg_src
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) struct nx_sg *nx_walk_and_build(struct nx_sg *nx_dst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) unsigned int sglen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) struct scatterlist *sg_src,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) unsigned int start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) unsigned int *src_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) struct scatter_walk walk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) struct nx_sg *nx_sg = nx_dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) unsigned int n, offset = 0, len = *src_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) char *dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /* we need to fast forward through @start bytes first */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) scatterwalk_start(&walk, sg_src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (start < offset + sg_src->length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) offset += sg_src->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) sg_src = sg_next(sg_src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) /* start - offset is the number of bytes to advance in the scatterlist
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * element we're currently looking at */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) scatterwalk_advance(&walk, start - offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) while (len && (nx_sg - nx_dst) < sglen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) n = scatterwalk_clamp(&walk, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) if (!n) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) /* In cases where we have scatterlist chain sg_next
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) * handles with it properly */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) scatterwalk_start(&walk, sg_next(walk.sg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) n = scatterwalk_clamp(&walk, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) dst = scatterwalk_map(&walk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) nx_sg = nx_build_sg_list(nx_sg, dst, &n, sglen - (nx_sg - nx_dst));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) len -= n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) scatterwalk_unmap(dst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) scatterwalk_advance(&walk, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) scatterwalk_done(&walk, SCATTERWALK_FROM_SG, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) /* update to_process */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) *src_len -= len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) /* return the moved destination pointer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) return nx_sg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * trim_sg_list - ensures the bound in sg list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) * @sg: sg list head
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) * @end: sg lisg end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) * @delta: is the amount we need to crop in order to bound the list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) static long int trim_sg_list(struct nx_sg *sg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) struct nx_sg *end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) unsigned int delta,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) unsigned int *nbytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) long int oplen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) long int data_back;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) unsigned int is_delta = delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) while (delta && end > sg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) struct nx_sg *last = end - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) if (last->len > delta) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) last->len -= delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) delta = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) end--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) delta -= last->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) /* There are cases where we need to crop list in order to make it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) * a block size multiple, but we also need to align data. In order to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) * that we need to calculate how much we need to put back to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) * processed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) oplen = (sg - end) * sizeof(struct nx_sg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (is_delta) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) data_back = (abs(oplen) / AES_BLOCK_SIZE) * sg->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) data_back = *nbytes - (data_back & ~(AES_BLOCK_SIZE - 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) *nbytes -= data_back;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) return oplen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) * nx_build_sg_lists - walk the input scatterlists and build arrays of NX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) * scatterlists based on them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) * @nx_ctx: NX crypto context for the lists we're building
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) * @iv: iv data, if the algorithm requires it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) * @dst: destination scatterlist
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) * @src: source scatterlist
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) * @nbytes: length of data described in the scatterlists
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) * @offset: number of bytes to fast-forward past at the beginning of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) * scatterlists.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) * @oiv: destination for the iv data, if the algorithm requires it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) * This is common code shared by all the AES algorithms. It uses the crypto
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) * scatterlist walk routines to traverse input and output scatterlists, building
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) * corresponding NX scatterlists
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) int nx_build_sg_lists(struct nx_crypto_ctx *nx_ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) const u8 *iv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) struct scatterlist *dst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) struct scatterlist *src,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) unsigned int *nbytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) unsigned int offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) u8 *oiv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) unsigned int delta = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) unsigned int total = *nbytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) struct nx_sg *nx_insg = nx_ctx->in_sg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) struct nx_sg *nx_outsg = nx_ctx->out_sg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) unsigned int max_sg_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) max_sg_len = min_t(u64, nx_ctx->ap->sglen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) nx_driver.of.max_sg_len/sizeof(struct nx_sg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) max_sg_len = min_t(u64, max_sg_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) nx_ctx->ap->databytelen/NX_PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (oiv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) memcpy(oiv, iv, AES_BLOCK_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) *nbytes = min_t(u64, *nbytes, nx_ctx->ap->databytelen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) nx_outsg = nx_walk_and_build(nx_outsg, max_sg_len, dst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) offset, nbytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) nx_insg = nx_walk_and_build(nx_insg, max_sg_len, src,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) offset, nbytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) if (*nbytes < total)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) delta = *nbytes - (*nbytes & ~(AES_BLOCK_SIZE - 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) /* these lengths should be negative, which will indicate to phyp that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * the input and output parameters are scatterlists, not linear
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) * buffers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) nx_ctx->op.inlen = trim_sg_list(nx_ctx->in_sg, nx_insg, delta, nbytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) nx_ctx->op.outlen = trim_sg_list(nx_ctx->out_sg, nx_outsg, delta, nbytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) * nx_ctx_init - initialize an nx_ctx's vio_pfo_op struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) * @nx_ctx: the nx context to initialize
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) * @function: the function code for the op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) void nx_ctx_init(struct nx_crypto_ctx *nx_ctx, unsigned int function)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) spin_lock_init(&nx_ctx->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) memset(nx_ctx->kmem, 0, nx_ctx->kmem_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) nx_ctx->csbcpb->csb.valid |= NX_CSB_VALID_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) nx_ctx->op.flags = function;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) nx_ctx->op.csbcpb = __pa(nx_ctx->csbcpb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) nx_ctx->op.in = __pa(nx_ctx->in_sg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) nx_ctx->op.out = __pa(nx_ctx->out_sg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) if (nx_ctx->csbcpb_aead) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) nx_ctx->csbcpb_aead->csb.valid |= NX_CSB_VALID_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) nx_ctx->op_aead.flags = function;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) nx_ctx->op_aead.csbcpb = __pa(nx_ctx->csbcpb_aead);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) nx_ctx->op_aead.in = __pa(nx_ctx->in_sg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) nx_ctx->op_aead.out = __pa(nx_ctx->out_sg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) static void nx_of_update_status(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) struct property *p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) struct nx_of *props)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (!strncmp(p->value, "okay", p->length)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) props->status = NX_WAITING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) props->flags |= NX_OF_FLAG_STATUS_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) dev_info(dev, "%s: status '%s' is not 'okay'\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) (char *)p->value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) static void nx_of_update_sglen(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) struct property *p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) struct nx_of *props)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) if (p->length != sizeof(props->max_sg_len)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) dev_err(dev, "%s: unexpected format for "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) "ibm,max-sg-len property\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) dev_dbg(dev, "%s: ibm,max-sg-len is %d bytes "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) "long, expected %zd bytes\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) p->length, sizeof(props->max_sg_len));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) props->max_sg_len = *(u32 *)p->value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) props->flags |= NX_OF_FLAG_MAXSGLEN_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) static void nx_of_update_msc(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) struct property *p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) struct nx_of *props)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) struct msc_triplet *trip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) struct max_sync_cop *msc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) unsigned int bytes_so_far, i, lenp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) msc = (struct max_sync_cop *)p->value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) lenp = p->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) /* You can't tell if the data read in for this property is sane by its
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) * size alone. This is because there are sizes embedded in the data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) * structure. The best we can do is check lengths as we parse and bail
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) * as soon as a length error is detected. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) bytes_so_far = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) while ((bytes_so_far + sizeof(struct max_sync_cop)) <= lenp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) bytes_so_far += sizeof(struct max_sync_cop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) trip = msc->trip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) for (i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) ((bytes_so_far + sizeof(struct msc_triplet)) <= lenp) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) i < msc->triplets;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) if (msc->fc >= NX_MAX_FC || msc->mode >= NX_MAX_MODE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) dev_err(dev, "unknown function code/mode "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) "combo: %d/%d (ignored)\n", msc->fc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) msc->mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) goto next_loop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) if (!trip->sglen || trip->databytelen < NX_PAGE_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) dev_warn(dev, "bogus sglen/databytelen: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) "%u/%u (ignored)\n", trip->sglen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) trip->databytelen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) goto next_loop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) switch (trip->keybitlen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) case 128:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) case 160:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) props->ap[msc->fc][msc->mode][0].databytelen =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) trip->databytelen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) props->ap[msc->fc][msc->mode][0].sglen =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) trip->sglen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) case 192:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) props->ap[msc->fc][msc->mode][1].databytelen =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) trip->databytelen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) props->ap[msc->fc][msc->mode][1].sglen =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) trip->sglen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) case 256:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) if (msc->fc == NX_FC_AES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) props->ap[msc->fc][msc->mode][2].
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) databytelen = trip->databytelen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) props->ap[msc->fc][msc->mode][2].sglen =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) trip->sglen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) } else if (msc->fc == NX_FC_AES_HMAC ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) msc->fc == NX_FC_SHA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) props->ap[msc->fc][msc->mode][1].
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) databytelen = trip->databytelen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) props->ap[msc->fc][msc->mode][1].sglen =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) trip->sglen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) dev_warn(dev, "unknown function "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) "code/key bit len combo"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) ": (%u/256)\n", msc->fc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) case 512:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) props->ap[msc->fc][msc->mode][2].databytelen =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) trip->databytelen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) props->ap[msc->fc][msc->mode][2].sglen =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) trip->sglen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) dev_warn(dev, "unknown function code/key bit "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) "len combo: (%u/%u)\n", msc->fc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) trip->keybitlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) next_loop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) bytes_so_far += sizeof(struct msc_triplet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) trip++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) msc = (struct max_sync_cop *)trip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) props->flags |= NX_OF_FLAG_MAXSYNCCOP_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) * nx_of_init - read openFirmware values from the device tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) * @dev: device handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) * @props: pointer to struct to hold the properties values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) * Called once at driver probe time, this function will read out the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) * openFirmware properties we use at runtime. If all the OF properties are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) * acceptable, when we exit this function props->flags will indicate that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) * we're ready to register our crypto algorithms.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) static void nx_of_init(struct device *dev, struct nx_of *props)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) struct device_node *base_node = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) struct property *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) p = of_find_property(base_node, "status", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) dev_info(dev, "%s: property 'status' not found\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) nx_of_update_status(dev, p, props);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) p = of_find_property(base_node, "ibm,max-sg-len", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) dev_info(dev, "%s: property 'ibm,max-sg-len' not found\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) nx_of_update_sglen(dev, p, props);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) p = of_find_property(base_node, "ibm,max-sync-cop", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) dev_info(dev, "%s: property 'ibm,max-sync-cop' not found\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) nx_of_update_msc(dev, p, props);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) static bool nx_check_prop(struct device *dev, u32 fc, u32 mode, int slot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) struct alg_props *props = &nx_driver.of.ap[fc][mode][slot];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) if (!props->sglen || props->databytelen < NX_PAGE_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) if (dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) dev_warn(dev, "bogus sglen/databytelen for %u/%u/%u: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) "%u/%u (ignored)\n", fc, mode, slot,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) props->sglen, props->databytelen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) static bool nx_check_props(struct device *dev, u32 fc, u32 mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) for (i = 0; i < 3; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) if (!nx_check_prop(dev, fc, mode, i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) static int nx_register_skcipher(struct skcipher_alg *alg, u32 fc, u32 mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) return nx_check_props(&nx_driver.viodev->dev, fc, mode) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) crypto_register_skcipher(alg) : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) static int nx_register_aead(struct aead_alg *alg, u32 fc, u32 mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) return nx_check_props(&nx_driver.viodev->dev, fc, mode) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) crypto_register_aead(alg) : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) static int nx_register_shash(struct shash_alg *alg, u32 fc, u32 mode, int slot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) return (slot >= 0 ? nx_check_prop(&nx_driver.viodev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) fc, mode, slot) :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) nx_check_props(&nx_driver.viodev->dev, fc, mode)) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) crypto_register_shash(alg) : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) static void nx_unregister_skcipher(struct skcipher_alg *alg, u32 fc, u32 mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) if (nx_check_props(NULL, fc, mode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) crypto_unregister_skcipher(alg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) static void nx_unregister_aead(struct aead_alg *alg, u32 fc, u32 mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) if (nx_check_props(NULL, fc, mode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) crypto_unregister_aead(alg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) static void nx_unregister_shash(struct shash_alg *alg, u32 fc, u32 mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) int slot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) if (slot >= 0 ? nx_check_prop(NULL, fc, mode, slot) :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) nx_check_props(NULL, fc, mode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) crypto_unregister_shash(alg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) * nx_register_algs - register algorithms with the crypto API
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) * Called from nx_probe()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) * If all OF properties are in an acceptable state, the driver flags will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) * indicate that we're ready and we'll create our debugfs files and register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) * out crypto algorithms.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) static int nx_register_algs(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) int rc = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) if (nx_driver.of.flags != NX_OF_FLAG_MASK_READY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) memset(&nx_driver.stats, 0, sizeof(struct nx_stats));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) NX_DEBUGFS_INIT(&nx_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) nx_driver.of.status = NX_OKAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) rc = nx_register_skcipher(&nx_ecb_aes_alg, NX_FC_AES, NX_MODE_AES_ECB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) rc = nx_register_skcipher(&nx_cbc_aes_alg, NX_FC_AES, NX_MODE_AES_CBC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) goto out_unreg_ecb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) rc = nx_register_skcipher(&nx_ctr3686_aes_alg, NX_FC_AES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) NX_MODE_AES_CTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) goto out_unreg_cbc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) rc = nx_register_aead(&nx_gcm_aes_alg, NX_FC_AES, NX_MODE_AES_GCM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) goto out_unreg_ctr3686;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) rc = nx_register_aead(&nx_gcm4106_aes_alg, NX_FC_AES, NX_MODE_AES_GCM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) goto out_unreg_gcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) rc = nx_register_aead(&nx_ccm_aes_alg, NX_FC_AES, NX_MODE_AES_CCM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) goto out_unreg_gcm4106;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) rc = nx_register_aead(&nx_ccm4309_aes_alg, NX_FC_AES, NX_MODE_AES_CCM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) goto out_unreg_ccm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) rc = nx_register_shash(&nx_shash_sha256_alg, NX_FC_SHA, NX_MODE_SHA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) NX_PROPS_SHA256);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) goto out_unreg_ccm4309;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) rc = nx_register_shash(&nx_shash_sha512_alg, NX_FC_SHA, NX_MODE_SHA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) NX_PROPS_SHA512);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) goto out_unreg_s256;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) rc = nx_register_shash(&nx_shash_aes_xcbc_alg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) NX_FC_AES, NX_MODE_AES_XCBC_MAC, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) goto out_unreg_s512;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) out_unreg_s512:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) nx_unregister_shash(&nx_shash_sha512_alg, NX_FC_SHA, NX_MODE_SHA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) NX_PROPS_SHA512);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) out_unreg_s256:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) nx_unregister_shash(&nx_shash_sha256_alg, NX_FC_SHA, NX_MODE_SHA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) NX_PROPS_SHA256);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) out_unreg_ccm4309:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) nx_unregister_aead(&nx_ccm4309_aes_alg, NX_FC_AES, NX_MODE_AES_CCM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) out_unreg_ccm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) nx_unregister_aead(&nx_ccm_aes_alg, NX_FC_AES, NX_MODE_AES_CCM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) out_unreg_gcm4106:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) nx_unregister_aead(&nx_gcm4106_aes_alg, NX_FC_AES, NX_MODE_AES_GCM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) out_unreg_gcm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) nx_unregister_aead(&nx_gcm_aes_alg, NX_FC_AES, NX_MODE_AES_GCM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) out_unreg_ctr3686:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) nx_unregister_skcipher(&nx_ctr3686_aes_alg, NX_FC_AES, NX_MODE_AES_CTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) out_unreg_cbc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) nx_unregister_skcipher(&nx_cbc_aes_alg, NX_FC_AES, NX_MODE_AES_CBC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) out_unreg_ecb:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) nx_unregister_skcipher(&nx_ecb_aes_alg, NX_FC_AES, NX_MODE_AES_ECB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) * nx_crypto_ctx_init - create and initialize a crypto api context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) * @nx_ctx: the crypto api context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) * @fc: function code for the context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) * @mode: the function code specific mode for this context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) static int nx_crypto_ctx_init(struct nx_crypto_ctx *nx_ctx, u32 fc, u32 mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) if (nx_driver.of.status != NX_OKAY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) pr_err("Attempt to initialize NX crypto context while device "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) "is not available!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) /* we need an extra page for csbcpb_aead for these modes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) if (mode == NX_MODE_AES_GCM || mode == NX_MODE_AES_CCM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) nx_ctx->kmem_len = (5 * NX_PAGE_SIZE) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) sizeof(struct nx_csbcpb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) nx_ctx->kmem_len = (4 * NX_PAGE_SIZE) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) sizeof(struct nx_csbcpb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) nx_ctx->kmem = kmalloc(nx_ctx->kmem_len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) if (!nx_ctx->kmem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) /* the csbcpb and scatterlists must be 4K aligned pages */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) nx_ctx->csbcpb = (struct nx_csbcpb *)(round_up((u64)nx_ctx->kmem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) (u64)NX_PAGE_SIZE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) nx_ctx->in_sg = (struct nx_sg *)((u8 *)nx_ctx->csbcpb + NX_PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) nx_ctx->out_sg = (struct nx_sg *)((u8 *)nx_ctx->in_sg + NX_PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) if (mode == NX_MODE_AES_GCM || mode == NX_MODE_AES_CCM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) nx_ctx->csbcpb_aead =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) (struct nx_csbcpb *)((u8 *)nx_ctx->out_sg +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) NX_PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) /* give each context a pointer to global stats and their OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) * properties */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) nx_ctx->stats = &nx_driver.stats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) memcpy(nx_ctx->props, nx_driver.of.ap[fc][mode],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) sizeof(struct alg_props) * 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) /* entry points from the crypto tfm initializers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) int nx_crypto_ctx_aes_ccm_init(struct crypto_aead *tfm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) crypto_aead_set_reqsize(tfm, sizeof(struct nx_ccm_rctx));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) return nx_crypto_ctx_init(crypto_aead_ctx(tfm), NX_FC_AES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) NX_MODE_AES_CCM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) int nx_crypto_ctx_aes_gcm_init(struct crypto_aead *tfm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) crypto_aead_set_reqsize(tfm, sizeof(struct nx_gcm_rctx));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) return nx_crypto_ctx_init(crypto_aead_ctx(tfm), NX_FC_AES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) NX_MODE_AES_GCM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) int nx_crypto_ctx_aes_ctr_init(struct crypto_skcipher *tfm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) return nx_crypto_ctx_init(crypto_skcipher_ctx(tfm), NX_FC_AES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) NX_MODE_AES_CTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) int nx_crypto_ctx_aes_cbc_init(struct crypto_skcipher *tfm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) return nx_crypto_ctx_init(crypto_skcipher_ctx(tfm), NX_FC_AES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) NX_MODE_AES_CBC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) int nx_crypto_ctx_aes_ecb_init(struct crypto_skcipher *tfm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) return nx_crypto_ctx_init(crypto_skcipher_ctx(tfm), NX_FC_AES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) NX_MODE_AES_ECB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) int nx_crypto_ctx_sha_init(struct crypto_tfm *tfm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) return nx_crypto_ctx_init(crypto_tfm_ctx(tfm), NX_FC_SHA, NX_MODE_SHA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) int nx_crypto_ctx_aes_xcbc_init(struct crypto_tfm *tfm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) return nx_crypto_ctx_init(crypto_tfm_ctx(tfm), NX_FC_AES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) NX_MODE_AES_XCBC_MAC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) * nx_crypto_ctx_exit - destroy a crypto api context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) * @tfm: the crypto transform pointer for the context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) * As crypto API contexts are destroyed, this exit hook is called to free the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) * memory associated with it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) void nx_crypto_ctx_exit(struct crypto_tfm *tfm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(tfm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) kfree_sensitive(nx_ctx->kmem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) nx_ctx->csbcpb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) nx_ctx->csbcpb_aead = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) nx_ctx->in_sg = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) nx_ctx->out_sg = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) void nx_crypto_ctx_skcipher_exit(struct crypto_skcipher *tfm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) nx_crypto_ctx_exit(crypto_skcipher_ctx(tfm));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) void nx_crypto_ctx_aead_exit(struct crypto_aead *tfm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) struct nx_crypto_ctx *nx_ctx = crypto_aead_ctx(tfm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) kfree_sensitive(nx_ctx->kmem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) static int nx_probe(struct vio_dev *viodev, const struct vio_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) dev_dbg(&viodev->dev, "driver probed: %s resource id: 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) viodev->name, viodev->resource_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) if (nx_driver.viodev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) dev_err(&viodev->dev, "%s: Attempt to register more than one "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) "instance of the hardware\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) nx_driver.viodev = viodev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) nx_of_init(&viodev->dev, &nx_driver.of);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) return nx_register_algs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) static int nx_remove(struct vio_dev *viodev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) dev_dbg(&viodev->dev, "entering nx_remove for UA 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) viodev->unit_address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) if (nx_driver.of.status == NX_OKAY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) NX_DEBUGFS_FINI(&nx_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) nx_unregister_shash(&nx_shash_aes_xcbc_alg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) NX_FC_AES, NX_MODE_AES_XCBC_MAC, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) nx_unregister_shash(&nx_shash_sha512_alg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) NX_FC_SHA, NX_MODE_SHA, NX_PROPS_SHA256);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) nx_unregister_shash(&nx_shash_sha256_alg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) NX_FC_SHA, NX_MODE_SHA, NX_PROPS_SHA512);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) nx_unregister_aead(&nx_ccm4309_aes_alg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) NX_FC_AES, NX_MODE_AES_CCM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) nx_unregister_aead(&nx_ccm_aes_alg, NX_FC_AES, NX_MODE_AES_CCM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) nx_unregister_aead(&nx_gcm4106_aes_alg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) NX_FC_AES, NX_MODE_AES_GCM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) nx_unregister_aead(&nx_gcm_aes_alg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) NX_FC_AES, NX_MODE_AES_GCM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) nx_unregister_skcipher(&nx_ctr3686_aes_alg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) NX_FC_AES, NX_MODE_AES_CTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) nx_unregister_skcipher(&nx_cbc_aes_alg, NX_FC_AES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) NX_MODE_AES_CBC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) nx_unregister_skcipher(&nx_ecb_aes_alg, NX_FC_AES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) NX_MODE_AES_ECB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) /* module wide initialization/cleanup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) static int __init nx_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) return vio_register_driver(&nx_driver.viodriver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) static void __exit nx_fini(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) vio_unregister_driver(&nx_driver.viodriver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) static const struct vio_device_id nx_crypto_driver_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) { "ibm,sym-encryption-v1", "ibm,sym-encryption" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) { "", "" }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) MODULE_DEVICE_TABLE(vio, nx_crypto_driver_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) /* driver state structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) struct nx_crypto_driver nx_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) .viodriver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) .id_table = nx_crypto_driver_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) .probe = nx_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) .remove = nx_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) .name = NX_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) module_init(nx_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) module_exit(nx_fini);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) MODULE_AUTHOR("Kent Yoder <yoder1@us.ibm.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) MODULE_DESCRIPTION(NX_STRING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) MODULE_VERSION(NX_VERSION);