^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Driver for IBM Power 842 compression accelerator
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) IBM Corporation, 2012
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Authors: Robert Jennings <rcj@linux.vnet.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Seth Jennings <sjenning@linux.vnet.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <asm/vio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "nx-842.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "nx_csbcpb.h" /* struct nx_csbcpb */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) MODULE_AUTHOR("Robert Jennings <rcj@linux.vnet.ibm.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) MODULE_DESCRIPTION("842 H/W Compression driver for IBM Power processors");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) MODULE_ALIAS_CRYPTO("842");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) MODULE_ALIAS_CRYPTO("842-nx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) static struct nx842_constraints nx842_pseries_constraints = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) .alignment = DDE_BUFFER_ALIGN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) .multiple = DDE_BUFFER_LAST_MULT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) .minimum = DDE_BUFFER_LAST_MULT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) .maximum = PAGE_SIZE, /* dynamic, max_sync_size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) static int check_constraints(unsigned long buf, unsigned int *len, bool in)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) if (!IS_ALIGNED(buf, nx842_pseries_constraints.alignment)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) pr_debug("%s buffer 0x%lx not aligned to 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) in ? "input" : "output", buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) nx842_pseries_constraints.alignment);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) if (*len % nx842_pseries_constraints.multiple) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) pr_debug("%s buffer len 0x%x not multiple of 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) in ? "input" : "output", *len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) nx842_pseries_constraints.multiple);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) if (in)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) *len = round_down(*len, nx842_pseries_constraints.multiple);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) if (*len < nx842_pseries_constraints.minimum) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) pr_debug("%s buffer len 0x%x under minimum 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) in ? "input" : "output", *len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) nx842_pseries_constraints.minimum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (*len > nx842_pseries_constraints.maximum) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) pr_debug("%s buffer len 0x%x over maximum 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) in ? "input" : "output", *len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) nx842_pseries_constraints.maximum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) if (in)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) *len = nx842_pseries_constraints.maximum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) /* I assume we need to align the CSB? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define WORKMEM_ALIGN (256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct nx842_workmem {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /* scatterlist */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) char slin[4096];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) char slout[4096];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) /* coprocessor status/parameter block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct nx_csbcpb csbcpb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) char padding[WORKMEM_ALIGN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) } __aligned(WORKMEM_ALIGN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) /* Macros for fields within nx_csbcpb */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) /* Check the valid bit within the csbcpb valid field */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define NX842_CSBCBP_VALID_CHK(x) (x & BIT_MASK(7))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) /* CE macros operate on the completion_extension field bits in the csbcpb.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * CE0 0=full completion, 1=partial completion
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * CE1 0=CE0 indicates completion, 1=termination (output may be modified)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) * CE2 0=processed_bytes is source bytes, 1=processed_bytes is target bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define NX842_CSBCPB_CE0(x) (x & BIT_MASK(7))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define NX842_CSBCPB_CE1(x) (x & BIT_MASK(6))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define NX842_CSBCPB_CE2(x) (x & BIT_MASK(5))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) /* The NX unit accepts data only on 4K page boundaries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define NX842_HW_PAGE_SIZE (4096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define NX842_HW_PAGE_MASK (~(NX842_HW_PAGE_SIZE-1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) struct ibm_nx842_counters {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) atomic64_t comp_complete;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) atomic64_t comp_failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) atomic64_t decomp_complete;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) atomic64_t decomp_failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) atomic64_t swdecomp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) atomic64_t comp_times[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) atomic64_t decomp_times[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static struct nx842_devdata {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct vio_dev *vdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) struct ibm_nx842_counters *counters;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) unsigned int max_sg_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) unsigned int max_sync_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) unsigned int max_sync_sg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) } __rcu *devdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) static DEFINE_SPINLOCK(devdata_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define NX842_COUNTER_INC(_x) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static inline void nx842_inc_##_x( \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) const struct nx842_devdata *dev) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (dev) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) atomic64_inc(&dev->counters->_x); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) NX842_COUNTER_INC(comp_complete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) NX842_COUNTER_INC(comp_failed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) NX842_COUNTER_INC(decomp_complete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) NX842_COUNTER_INC(decomp_failed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) NX842_COUNTER_INC(swdecomp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) #define NX842_HIST_SLOTS 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) static void ibm_nx842_incr_hist(atomic64_t *times, unsigned int time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) int bucket = fls(time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (bucket)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) bucket = min((NX842_HIST_SLOTS - 1), bucket - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) atomic64_inc(×[bucket]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) /* NX unit operation flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) #define NX842_OP_COMPRESS 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #define NX842_OP_CRC 0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) #define NX842_OP_DECOMPRESS 0x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) #define NX842_OP_COMPRESS_CRC (NX842_OP_COMPRESS | NX842_OP_CRC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) #define NX842_OP_DECOMPRESS_CRC (NX842_OP_DECOMPRESS | NX842_OP_CRC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) #define NX842_OP_ASYNC (1<<23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) #define NX842_OP_NOTIFY (1<<22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #define NX842_OP_NOTIFY_INT(x) ((x & 0xff)<<8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) static unsigned long nx842_get_desired_dma(struct vio_dev *viodev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) /* No use of DMA mappings within the driver. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) struct nx842_slentry {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) __be64 ptr; /* Real address (use __pa()) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) __be64 len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) /* pHyp scatterlist entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) struct nx842_scatterlist {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) int entry_nr; /* number of slentries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) struct nx842_slentry *entries; /* ptr to array of slentries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) /* Does not include sizeof(entry_nr) in the size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) static inline unsigned long nx842_get_scatterlist_size(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) struct nx842_scatterlist *sl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) return sl->entry_nr * sizeof(struct nx842_slentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) static int nx842_build_scatterlist(unsigned long buf, int len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) struct nx842_scatterlist *sl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) unsigned long entrylen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) struct nx842_slentry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) sl->entry_nr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) entry = sl->entries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) while (len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) entry->ptr = cpu_to_be64(nx842_get_pa((void *)buf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) entrylen = min_t(int, len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) LEN_ON_SIZE(buf, NX842_HW_PAGE_SIZE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) entry->len = cpu_to_be64(entrylen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) len -= entrylen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) buf += entrylen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) sl->entry_nr++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) entry++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) static int nx842_validate_result(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) struct cop_status_block *csb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) /* The csb must be valid after returning from vio_h_cop_sync */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (!NX842_CSBCBP_VALID_CHK(csb->valid)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) dev_err(dev, "%s: cspcbp not valid upon completion.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) dev_dbg(dev, "valid:0x%02x cs:0x%02x cc:0x%02x ce:0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) csb->valid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) csb->crb_seq_number,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) csb->completion_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) csb->completion_extension);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) dev_dbg(dev, "processed_bytes:%d address:0x%016lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) be32_to_cpu(csb->processed_byte_count),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) (unsigned long)be64_to_cpu(csb->address));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) /* Check return values from the hardware in the CSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) switch (csb->completion_code) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) case 0: /* Completed without error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) case 64: /* Compression ok, but output larger than input */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) dev_dbg(dev, "%s: output size larger than input size\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) case 13: /* Output buffer too small */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) dev_dbg(dev, "%s: Out of space in output buffer\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) case 65: /* Calculated CRC doesn't match the passed value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) dev_dbg(dev, "%s: CRC mismatch for decompression\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) case 66: /* Input data contains an illegal template field */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) case 67: /* Template indicates data past the end of the input stream */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) dev_dbg(dev, "%s: Bad data for decompression (code:%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) __func__, csb->completion_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) dev_dbg(dev, "%s: Unspecified error (code:%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) __func__, csb->completion_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) /* Hardware sanity check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) if (!NX842_CSBCPB_CE2(csb->completion_extension)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) dev_err(dev, "%s: No error returned by hardware, but "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) "data returned is unusable, contact support.\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) "(Additional info: csbcbp->processed bytes "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) "does not specify processed bytes for the "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) "target buffer.)\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) * nx842_pseries_compress - Compress data using the 842 algorithm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) * Compression provide by the NX842 coprocessor on IBM Power systems.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) * The input buffer is compressed and the result is stored in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * provided output buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) * Upon return from this function @outlen contains the length of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) * compressed data. If there is an error then @outlen will be 0 and an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) * error will be specified by the return code from this function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) * @in: Pointer to input buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) * @inlen: Length of input buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) * @out: Pointer to output buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) * @outlen: Length of output buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) * @wrkmem: ptr to buffer for working memory, size determined by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * nx842_pseries_driver.workmem_size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) * 0 Success, output of length @outlen stored in the buffer at @out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) * -ENOMEM Unable to allocate internal buffers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) * -ENOSPC Output buffer is to small
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) * -EIO Internal error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) * -ENODEV Hardware unavailable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) static int nx842_pseries_compress(const unsigned char *in, unsigned int inlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) unsigned char *out, unsigned int *outlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) void *wmem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) struct nx842_devdata *local_devdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) struct device *dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) struct nx842_workmem *workmem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) struct nx842_scatterlist slin, slout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) struct nx_csbcpb *csbcpb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) unsigned long inbuf, outbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) struct vio_pfo_op op = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) .done = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) .handle = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) .timeout = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) unsigned long start = get_tb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) inbuf = (unsigned long)in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (check_constraints(inbuf, &inlen, true))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) outbuf = (unsigned long)out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (check_constraints(outbuf, outlen, false))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) local_devdata = rcu_dereference(devdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) if (!local_devdata || !local_devdata->dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) dev = local_devdata->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) /* Init scatterlist */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) workmem = PTR_ALIGN(wmem, WORKMEM_ALIGN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) slin.entries = (struct nx842_slentry *)workmem->slin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) slout.entries = (struct nx842_slentry *)workmem->slout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) /* Init operation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) op.flags = NX842_OP_COMPRESS_CRC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) csbcpb = &workmem->csbcpb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) memset(csbcpb, 0, sizeof(*csbcpb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) op.csbcpb = nx842_get_pa(csbcpb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) if ((inbuf & NX842_HW_PAGE_MASK) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) ((inbuf + inlen - 1) & NX842_HW_PAGE_MASK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) /* Create direct DDE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) op.in = nx842_get_pa((void *)inbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) op.inlen = inlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) /* Create indirect DDE (scatterlist) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) nx842_build_scatterlist(inbuf, inlen, &slin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) op.in = nx842_get_pa(slin.entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) op.inlen = -nx842_get_scatterlist_size(&slin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if ((outbuf & NX842_HW_PAGE_MASK) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) ((outbuf + *outlen - 1) & NX842_HW_PAGE_MASK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) /* Create direct DDE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) op.out = nx842_get_pa((void *)outbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) op.outlen = *outlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) /* Create indirect DDE (scatterlist) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) nx842_build_scatterlist(outbuf, *outlen, &slout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) op.out = nx842_get_pa(slout.entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) op.outlen = -nx842_get_scatterlist_size(&slout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) dev_dbg(dev, "%s: op.in %lx op.inlen %ld op.out %lx op.outlen %ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) __func__, (unsigned long)op.in, (long)op.inlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) (unsigned long)op.out, (long)op.outlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) /* Send request to pHyp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) ret = vio_h_cop_sync(local_devdata->vdev, &op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) /* Check for pHyp error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) dev_dbg(dev, "%s: vio_h_cop_sync error (ret=%d, hret=%ld)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) __func__, ret, op.hcall_err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) /* Check for hardware error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) ret = nx842_validate_result(dev, &csbcpb->csb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) *outlen = be32_to_cpu(csbcpb->csb.processed_byte_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) dev_dbg(dev, "%s: processed_bytes=%d\n", __func__, *outlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) nx842_inc_comp_failed(local_devdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) nx842_inc_comp_complete(local_devdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) ibm_nx842_incr_hist(local_devdata->counters->comp_times,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) (get_tb() - start) / tb_ticks_per_usec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) * nx842_pseries_decompress - Decompress data using the 842 algorithm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) * Decompression provide by the NX842 coprocessor on IBM Power systems.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) * The input buffer is decompressed and the result is stored in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) * provided output buffer. The size allocated to the output buffer is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) * provided by the caller of this function in @outlen. Upon return from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) * this function @outlen contains the length of the decompressed data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) * If there is an error then @outlen will be 0 and an error will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) * specified by the return code from this function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) * @in: Pointer to input buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) * @inlen: Length of input buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) * @out: Pointer to output buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) * @outlen: Length of output buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) * @wrkmem: ptr to buffer for working memory, size determined by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) * nx842_pseries_driver.workmem_size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) * 0 Success, output of length @outlen stored in the buffer at @out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) * -ENODEV Hardware decompression device is unavailable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) * -ENOMEM Unable to allocate internal buffers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) * -ENOSPC Output buffer is to small
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) * -EINVAL Bad input data encountered when attempting decompress
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) * -EIO Internal error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) static int nx842_pseries_decompress(const unsigned char *in, unsigned int inlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) unsigned char *out, unsigned int *outlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) void *wmem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) struct nx842_devdata *local_devdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) struct device *dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) struct nx842_workmem *workmem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) struct nx842_scatterlist slin, slout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) struct nx_csbcpb *csbcpb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) unsigned long inbuf, outbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) struct vio_pfo_op op = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) .done = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) .handle = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) .timeout = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) unsigned long start = get_tb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) /* Ensure page alignment and size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) inbuf = (unsigned long)in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) if (check_constraints(inbuf, &inlen, true))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) outbuf = (unsigned long)out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (check_constraints(outbuf, outlen, false))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) local_devdata = rcu_dereference(devdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) if (!local_devdata || !local_devdata->dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) dev = local_devdata->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) workmem = PTR_ALIGN(wmem, WORKMEM_ALIGN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) /* Init scatterlist */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) slin.entries = (struct nx842_slentry *)workmem->slin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) slout.entries = (struct nx842_slentry *)workmem->slout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) /* Init operation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) op.flags = NX842_OP_DECOMPRESS_CRC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) csbcpb = &workmem->csbcpb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) memset(csbcpb, 0, sizeof(*csbcpb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) op.csbcpb = nx842_get_pa(csbcpb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) if ((inbuf & NX842_HW_PAGE_MASK) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) ((inbuf + inlen - 1) & NX842_HW_PAGE_MASK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) /* Create direct DDE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) op.in = nx842_get_pa((void *)inbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) op.inlen = inlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) /* Create indirect DDE (scatterlist) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) nx842_build_scatterlist(inbuf, inlen, &slin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) op.in = nx842_get_pa(slin.entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) op.inlen = -nx842_get_scatterlist_size(&slin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if ((outbuf & NX842_HW_PAGE_MASK) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) ((outbuf + *outlen - 1) & NX842_HW_PAGE_MASK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) /* Create direct DDE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) op.out = nx842_get_pa((void *)outbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) op.outlen = *outlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) /* Create indirect DDE (scatterlist) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) nx842_build_scatterlist(outbuf, *outlen, &slout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) op.out = nx842_get_pa(slout.entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) op.outlen = -nx842_get_scatterlist_size(&slout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) dev_dbg(dev, "%s: op.in %lx op.inlen %ld op.out %lx op.outlen %ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) __func__, (unsigned long)op.in, (long)op.inlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) (unsigned long)op.out, (long)op.outlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) /* Send request to pHyp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) ret = vio_h_cop_sync(local_devdata->vdev, &op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) /* Check for pHyp error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) dev_dbg(dev, "%s: vio_h_cop_sync error (ret=%d, hret=%ld)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) __func__, ret, op.hcall_err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) /* Check for hardware error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) ret = nx842_validate_result(dev, &csbcpb->csb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) *outlen = be32_to_cpu(csbcpb->csb.processed_byte_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) /* decompress fail */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) nx842_inc_decomp_failed(local_devdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) nx842_inc_decomp_complete(local_devdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) ibm_nx842_incr_hist(local_devdata->counters->decomp_times,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) (get_tb() - start) / tb_ticks_per_usec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) }
^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) * nx842_OF_set_defaults -- Set default (disabled) values for devdata
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) * @devdata - struct nx842_devdata to update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) * 0 on success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) * -ENOENT if @devdata ptr is NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) static int nx842_OF_set_defaults(struct nx842_devdata *devdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) if (devdata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) devdata->max_sync_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) devdata->max_sync_sg = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) devdata->max_sg_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) }
^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) * nx842_OF_upd_status -- Check the device info from OF status prop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) * The status property indicates if the accelerator is enabled. If the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) * device is in the OF tree it indicates that the hardware is present.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) * The status field indicates if the device is enabled when the status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) * is 'okay'. Otherwise the device driver will be disabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) * @devdata: struct nx842_devdata to use for dev_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) * @prop: struct property point containing the maxsyncop for the update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) * 0 - Device is available
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) * -ENODEV - Device is not available
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) static int nx842_OF_upd_status(struct nx842_devdata *devdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) struct property *prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) const char *status = (const char *)prop->value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) if (!strncmp(status, "okay", (size_t)prop->length))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) if (!strncmp(status, "disabled", (size_t)prop->length))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) dev_info(devdata->dev, "%s: unknown status '%s'\n", __func__, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) * nx842_OF_upd_maxsglen -- Update the device info from OF maxsglen prop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) * Definition of the 'ibm,max-sg-len' OF property:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) * This field indicates the maximum byte length of a scatter list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) * for the platform facility. It is a single cell encoded as with encode-int.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) * Example:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) * # od -x ibm,max-sg-len
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) * 0000000 0000 0ff0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) * In this example, the maximum byte length of a scatter list is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) * 0x0ff0 (4,080).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) * @devdata - struct nx842_devdata to update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) * @prop - struct property point containing the maxsyncop for the update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) * 0 on success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) * -EINVAL on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) static int nx842_OF_upd_maxsglen(struct nx842_devdata *devdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) struct property *prop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) const unsigned int maxsglen = of_read_number(prop->value, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) if (prop->length != sizeof(maxsglen)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) dev_err(devdata->dev, "%s: unexpected format for ibm,max-sg-len property\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) dev_dbg(devdata->dev, "%s: ibm,max-sg-len is %d bytes long, expected %lu bytes\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) prop->length, sizeof(maxsglen));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) devdata->max_sg_len = min_t(unsigned int,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) maxsglen, NX842_HW_PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) * nx842_OF_upd_maxsyncop -- Update the device info from OF maxsyncop prop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) * Definition of the 'ibm,max-sync-cop' OF property:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) * Two series of cells. The first series of cells represents the maximums
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) * that can be synchronously compressed. The second series of cells
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) * represents the maximums that can be synchronously decompressed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) * 1. The first cell in each series contains the count of the number of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) * data length, scatter list elements pairs that follow – each being
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) * of the form
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) * a. One cell data byte length
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) * b. One cell total number of scatter list elements
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) * Example:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) * # od -x ibm,max-sync-cop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) * 0000000 0000 0001 0000 1000 0000 01fe 0000 0001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) * 0000020 0000 1000 0000 01fe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) * In this example, compression supports 0x1000 (4,096) data byte length
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) * and 0x1fe (510) total scatter list elements. Decompression supports
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) * 0x1000 (4,096) data byte length and 0x1f3 (510) total scatter list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) * elements.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) * @devdata - struct nx842_devdata to update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) * @prop - struct property point containing the maxsyncop for the update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) * 0 on success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) * -EINVAL on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) static int nx842_OF_upd_maxsyncop(struct nx842_devdata *devdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) struct property *prop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) unsigned int comp_data_limit, decomp_data_limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) unsigned int comp_sg_limit, decomp_sg_limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) const struct maxsynccop_t {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) __be32 comp_elements;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) __be32 comp_data_limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) __be32 comp_sg_limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) __be32 decomp_elements;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) __be32 decomp_data_limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) __be32 decomp_sg_limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) } *maxsynccop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) if (prop->length != sizeof(*maxsynccop)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) dev_err(devdata->dev, "%s: unexpected format for ibm,max-sync-cop property\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) dev_dbg(devdata->dev, "%s: ibm,max-sync-cop is %d bytes long, expected %lu bytes\n", __func__, prop->length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) sizeof(*maxsynccop));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) maxsynccop = (const struct maxsynccop_t *)prop->value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) comp_data_limit = be32_to_cpu(maxsynccop->comp_data_limit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) comp_sg_limit = be32_to_cpu(maxsynccop->comp_sg_limit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) decomp_data_limit = be32_to_cpu(maxsynccop->decomp_data_limit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) decomp_sg_limit = be32_to_cpu(maxsynccop->decomp_sg_limit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) /* Use one limit rather than separate limits for compression and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) * decompression. Set a maximum for this so as not to exceed the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) * size that the header can support and round the value down to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) * the hardware page size (4K) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) devdata->max_sync_size = min(comp_data_limit, decomp_data_limit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) devdata->max_sync_size = min_t(unsigned int, devdata->max_sync_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) 65536);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) if (devdata->max_sync_size < 4096) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) dev_err(devdata->dev, "%s: hardware max data size (%u) is "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) "less than the driver minimum, unable to use "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) "the hardware device\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) __func__, devdata->max_sync_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) nx842_pseries_constraints.maximum = devdata->max_sync_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) devdata->max_sync_sg = min(comp_sg_limit, decomp_sg_limit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) if (devdata->max_sync_sg < 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) dev_err(devdata->dev, "%s: hardware max sg size (%u) is "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) "less than the driver minimum, unable to use "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) "the hardware device\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) __func__, devdata->max_sync_sg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) return ret;
^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) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) * nx842_OF_upd -- Handle OF properties updates for the device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) * Set all properties from the OF tree. Optionally, a new property
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) * can be provided by the @new_prop pointer to overwrite an existing value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) * The device will remain disabled until all values are valid, this function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) * will return an error for updates unless all values are valid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) * @new_prop: If not NULL, this property is being updated. If NULL, update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) * all properties from the current values in the OF tree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) * 0 - Success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) * -ENOMEM - Could not allocate memory for new devdata structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) * -EINVAL - property value not found, new_prop is not a recognized
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) * property for the device or property value is not valid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) * -ENODEV - Device is not available
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) static int nx842_OF_upd(struct property *new_prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) struct nx842_devdata *old_devdata = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) struct nx842_devdata *new_devdata = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) struct device_node *of_node = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) struct property *status = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) struct property *maxsglen = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) struct property *maxsyncop = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) new_devdata = kzalloc(sizeof(*new_devdata), GFP_NOFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) if (!new_devdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) spin_lock_irqsave(&devdata_mutex, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) old_devdata = rcu_dereference_check(devdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) lockdep_is_held(&devdata_mutex));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) if (old_devdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) of_node = old_devdata->dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) if (!old_devdata || !of_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) pr_err("%s: device is not available\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) spin_unlock_irqrestore(&devdata_mutex, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) kfree(new_devdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) memcpy(new_devdata, old_devdata, sizeof(*old_devdata));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) new_devdata->counters = old_devdata->counters;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) /* Set ptrs for existing properties */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) status = of_find_property(of_node, "status", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) maxsglen = of_find_property(of_node, "ibm,max-sg-len", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) maxsyncop = of_find_property(of_node, "ibm,max-sync-cop", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) if (!status || !maxsglen || !maxsyncop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) dev_err(old_devdata->dev, "%s: Could not locate device properties\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) goto error_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) * If this is a property update, there are only certain properties that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) * we care about. Bail if it isn't in the below list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) if (new_prop && (strncmp(new_prop->name, "status", new_prop->length) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) strncmp(new_prop->name, "ibm,max-sg-len", new_prop->length) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) strncmp(new_prop->name, "ibm,max-sync-cop", new_prop->length)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) /* Perform property updates */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) ret = nx842_OF_upd_status(new_devdata, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) goto error_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) ret = nx842_OF_upd_maxsglen(new_devdata, maxsglen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) goto error_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) ret = nx842_OF_upd_maxsyncop(new_devdata, maxsyncop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) goto error_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) dev_info(old_devdata->dev, "%s: max_sync_size new:%u old:%u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) __func__, new_devdata->max_sync_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) old_devdata->max_sync_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) dev_info(old_devdata->dev, "%s: max_sync_sg new:%u old:%u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) __func__, new_devdata->max_sync_sg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) old_devdata->max_sync_sg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) dev_info(old_devdata->dev, "%s: max_sg_len new:%u old:%u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) __func__, new_devdata->max_sg_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) old_devdata->max_sg_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) rcu_assign_pointer(devdata, new_devdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) spin_unlock_irqrestore(&devdata_mutex, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) synchronize_rcu();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) dev_set_drvdata(new_devdata->dev, new_devdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) kfree(old_devdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) error_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) if (new_devdata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) dev_info(old_devdata->dev, "%s: device disabled\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) nx842_OF_set_defaults(new_devdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) rcu_assign_pointer(devdata, new_devdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) spin_unlock_irqrestore(&devdata_mutex, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) synchronize_rcu();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) dev_set_drvdata(new_devdata->dev, new_devdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) kfree(old_devdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) dev_err(old_devdata->dev, "%s: could not update driver from hardware\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) spin_unlock_irqrestore(&devdata_mutex, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) * nx842_OF_notifier - Process updates to OF properties for the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) * @np: notifier block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) * @action: notifier action
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) * @update: struct pSeries_reconfig_prop_update pointer if action is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) * PSERIES_UPDATE_PROPERTY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) * NOTIFY_OK on success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) * NOTIFY_BAD encoded with error number on failure, use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) * notifier_to_errno() to decode this value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) static int nx842_OF_notifier(struct notifier_block *np, unsigned long action,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) struct of_reconfig_data *upd = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) struct nx842_devdata *local_devdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) struct device_node *node = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) local_devdata = rcu_dereference(devdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) if (local_devdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) node = local_devdata->dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) if (local_devdata &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) action == OF_RECONFIG_UPDATE_PROPERTY &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) !strcmp(upd->dn->name, node->name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) nx842_OF_upd(upd->prop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) return NOTIFY_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) static struct notifier_block nx842_of_nb = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) .notifier_call = nx842_OF_notifier,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) #define nx842_counter_read(_name) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) static ssize_t nx842_##_name##_show(struct device *dev, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) struct device_attribute *attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) char *buf) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) struct nx842_devdata *local_devdata; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) int p = 0; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) rcu_read_lock(); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) local_devdata = rcu_dereference(devdata); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) if (local_devdata) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) p = snprintf(buf, PAGE_SIZE, "%lld\n", \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) atomic64_read(&local_devdata->counters->_name)); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) rcu_read_unlock(); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) return p; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) #define NX842DEV_COUNTER_ATTR_RO(_name) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) nx842_counter_read(_name); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) static struct device_attribute dev_attr_##_name = __ATTR(_name, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) 0444, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) nx842_##_name##_show,\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) NX842DEV_COUNTER_ATTR_RO(comp_complete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) NX842DEV_COUNTER_ATTR_RO(comp_failed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) NX842DEV_COUNTER_ATTR_RO(decomp_complete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) NX842DEV_COUNTER_ATTR_RO(decomp_failed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) NX842DEV_COUNTER_ATTR_RO(swdecomp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) static ssize_t nx842_timehist_show(struct device *,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) struct device_attribute *, char *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) static struct device_attribute dev_attr_comp_times = __ATTR(comp_times, 0444,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) nx842_timehist_show, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) static struct device_attribute dev_attr_decomp_times = __ATTR(decomp_times,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) 0444, nx842_timehist_show, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) static ssize_t nx842_timehist_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) struct device_attribute *attr, char *buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) char *p = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) struct nx842_devdata *local_devdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) atomic64_t *times;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) int bytes_remain = PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) int bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) local_devdata = rcu_dereference(devdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) if (!local_devdata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) if (attr == &dev_attr_comp_times)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) times = local_devdata->counters->comp_times;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) else if (attr == &dev_attr_decomp_times)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) times = local_devdata->counters->decomp_times;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) for (i = 0; i < (NX842_HIST_SLOTS - 2); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) bytes = snprintf(p, bytes_remain, "%u-%uus:\t%lld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) i ? (2<<(i-1)) : 0, (2<<i)-1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) atomic64_read(×[i]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) bytes_remain -= bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) p += bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) /* The last bucket holds everything over
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) * 2<<(NX842_HIST_SLOTS - 2) us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) bytes = snprintf(p, bytes_remain, "%uus - :\t%lld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) 2<<(NX842_HIST_SLOTS - 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) atomic64_read(×[(NX842_HIST_SLOTS - 1)]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) p += bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) return p - buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) static struct attribute *nx842_sysfs_entries[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) &dev_attr_comp_complete.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) &dev_attr_comp_failed.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) &dev_attr_decomp_complete.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) &dev_attr_decomp_failed.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) &dev_attr_swdecomp.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) &dev_attr_comp_times.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) &dev_attr_decomp_times.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) static struct attribute_group nx842_attribute_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) .name = NULL, /* put in device directory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) .attrs = nx842_sysfs_entries,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) static struct nx842_driver nx842_pseries_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) .name = KBUILD_MODNAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) .workmem_size = sizeof(struct nx842_workmem),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) .constraints = &nx842_pseries_constraints,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) .compress = nx842_pseries_compress,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) .decompress = nx842_pseries_decompress,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) static int nx842_pseries_crypto_init(struct crypto_tfm *tfm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) return nx842_crypto_init(tfm, &nx842_pseries_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) static struct crypto_alg nx842_pseries_alg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) .cra_name = "842",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) .cra_driver_name = "842-nx",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) .cra_priority = 300,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) .cra_flags = CRYPTO_ALG_TYPE_COMPRESS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) .cra_ctxsize = sizeof(struct nx842_crypto_ctx),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) .cra_module = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) .cra_init = nx842_pseries_crypto_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) .cra_exit = nx842_crypto_exit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) .cra_u = { .compress = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) .coa_compress = nx842_crypto_compress,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) .coa_decompress = nx842_crypto_decompress } }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) static int nx842_probe(struct vio_dev *viodev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) const struct vio_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) struct nx842_devdata *old_devdata, *new_devdata = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) new_devdata = kzalloc(sizeof(*new_devdata), GFP_NOFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) if (!new_devdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) new_devdata->counters = kzalloc(sizeof(*new_devdata->counters),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) GFP_NOFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) if (!new_devdata->counters) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) kfree(new_devdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) spin_lock_irqsave(&devdata_mutex, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) old_devdata = rcu_dereference_check(devdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) lockdep_is_held(&devdata_mutex));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) if (old_devdata && old_devdata->vdev != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) dev_err(&viodev->dev, "%s: Attempt to register more than one instance of the hardware\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) ret = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) goto error_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) dev_set_drvdata(&viodev->dev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) new_devdata->vdev = viodev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) new_devdata->dev = &viodev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) nx842_OF_set_defaults(new_devdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) rcu_assign_pointer(devdata, new_devdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) spin_unlock_irqrestore(&devdata_mutex, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) synchronize_rcu();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) kfree(old_devdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) of_reconfig_notifier_register(&nx842_of_nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) ret = nx842_OF_upd(NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) ret = crypto_register_alg(&nx842_pseries_alg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) dev_err(&viodev->dev, "could not register comp alg: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) dev_set_drvdata(&viodev->dev, rcu_dereference(devdata));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) if (sysfs_create_group(&viodev->dev.kobj, &nx842_attribute_group)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) dev_err(&viodev->dev, "could not create sysfs device attributes\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) ret = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) error_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) spin_unlock_irqrestore(&devdata_mutex, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) if (new_devdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) kfree(new_devdata->counters);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) kfree(new_devdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) static int nx842_remove(struct vio_dev *viodev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) struct nx842_devdata *old_devdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) pr_info("Removing IBM Power 842 compression device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) sysfs_remove_group(&viodev->dev.kobj, &nx842_attribute_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) crypto_unregister_alg(&nx842_pseries_alg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) spin_lock_irqsave(&devdata_mutex, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) old_devdata = rcu_dereference_check(devdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) lockdep_is_held(&devdata_mutex));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) of_reconfig_notifier_unregister(&nx842_of_nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) RCU_INIT_POINTER(devdata, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) spin_unlock_irqrestore(&devdata_mutex, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) synchronize_rcu();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) dev_set_drvdata(&viodev->dev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) if (old_devdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) kfree(old_devdata->counters);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) kfree(old_devdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) static const struct vio_device_id nx842_vio_driver_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) {"ibm,compression-v1", "ibm,compression"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) {"", ""},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) MODULE_DEVICE_TABLE(vio, nx842_vio_driver_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) static struct vio_driver nx842_vio_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) .name = KBUILD_MODNAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) .probe = nx842_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) .remove = nx842_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) .get_desired_dma = nx842_get_desired_dma,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) .id_table = nx842_vio_driver_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) static int __init nx842_pseries_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) struct nx842_devdata *new_devdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) if (!of_find_compatible_node(NULL, NULL, "ibm,compression"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) RCU_INIT_POINTER(devdata, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) new_devdata = kzalloc(sizeof(*new_devdata), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) if (!new_devdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) RCU_INIT_POINTER(devdata, new_devdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) ret = vio_register_driver(&nx842_vio_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) pr_err("Could not register VIO driver %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) kfree(new_devdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) module_init(nx842_pseries_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) static void __exit nx842_pseries_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) struct nx842_devdata *old_devdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) crypto_unregister_alg(&nx842_pseries_alg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) spin_lock_irqsave(&devdata_mutex, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) old_devdata = rcu_dereference_check(devdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) lockdep_is_held(&devdata_mutex));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) RCU_INIT_POINTER(devdata, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) spin_unlock_irqrestore(&devdata_mutex, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) synchronize_rcu();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) if (old_devdata && old_devdata->dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) dev_set_drvdata(old_devdata->dev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) kfree(old_devdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) vio_unregister_driver(&nx842_vio_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) module_exit(nx842_pseries_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134)