Path: blob/master/drivers/crypto/intel/iaa/iaa_crypto_main.c
29278 views
// SPDX-License-Identifier: GPL-2.01/* Copyright(c) 2021 Intel Corporation. All rights rsvd. */23#include <linux/init.h>4#include <linux/kernel.h>5#include <linux/module.h>6#include <linux/pci.h>7#include <linux/device.h>8#include <linux/iommu.h>9#include <uapi/linux/idxd.h>10#include <linux/highmem.h>11#include <linux/sched/smt.h>12#include <crypto/internal/acompress.h>1314#include "idxd.h"15#include "iaa_crypto.h"16#include "iaa_crypto_stats.h"1718#ifdef pr_fmt19#undef pr_fmt20#endif2122#define pr_fmt(fmt) "idxd: " IDXD_SUBDRIVER_NAME ": " fmt2324#define IAA_ALG_PRIORITY 3002526/* number of iaa instances probed */27static unsigned int nr_iaa;28static unsigned int nr_cpus;29static unsigned int nr_nodes;30static unsigned int nr_cpus_per_node;3132/* Number of physical cpus sharing each iaa instance */33static unsigned int cpus_per_iaa;3435/* Per-cpu lookup table for balanced wqs */36static struct wq_table_entry __percpu *wq_table;3738static struct idxd_wq *wq_table_next_wq(int cpu)39{40struct wq_table_entry *entry = per_cpu_ptr(wq_table, cpu);4142if (++entry->cur_wq >= entry->n_wqs)43entry->cur_wq = 0;4445if (!entry->wqs[entry->cur_wq])46return NULL;4748pr_debug("%s: returning wq at idx %d (iaa wq %d.%d) from cpu %d\n", __func__,49entry->cur_wq, entry->wqs[entry->cur_wq]->idxd->id,50entry->wqs[entry->cur_wq]->id, cpu);5152return entry->wqs[entry->cur_wq];53}5455static void wq_table_add(int cpu, struct idxd_wq *wq)56{57struct wq_table_entry *entry = per_cpu_ptr(wq_table, cpu);5859if (WARN_ON(entry->n_wqs == entry->max_wqs))60return;6162entry->wqs[entry->n_wqs++] = wq;6364pr_debug("%s: added iaa wq %d.%d to idx %d of cpu %d\n", __func__,65entry->wqs[entry->n_wqs - 1]->idxd->id,66entry->wqs[entry->n_wqs - 1]->id, entry->n_wqs - 1, cpu);67}6869static void wq_table_free_entry(int cpu)70{71struct wq_table_entry *entry = per_cpu_ptr(wq_table, cpu);7273kfree(entry->wqs);74memset(entry, 0, sizeof(*entry));75}7677static void wq_table_clear_entry(int cpu)78{79struct wq_table_entry *entry = per_cpu_ptr(wq_table, cpu);8081entry->n_wqs = 0;82entry->cur_wq = 0;83memset(entry->wqs, 0, entry->max_wqs * sizeof(struct idxd_wq *));84}8586LIST_HEAD(iaa_devices);87DEFINE_MUTEX(iaa_devices_lock);8889/* If enabled, IAA hw crypto algos are registered, unavailable otherwise */90static bool iaa_crypto_enabled;91static bool iaa_crypto_registered;9293/* Verify results of IAA compress or not */94static bool iaa_verify_compress = true;9596static ssize_t verify_compress_show(struct device_driver *driver, char *buf)97{98return sprintf(buf, "%d\n", iaa_verify_compress);99}100101static ssize_t verify_compress_store(struct device_driver *driver,102const char *buf, size_t count)103{104int ret = -EBUSY;105106mutex_lock(&iaa_devices_lock);107108if (iaa_crypto_enabled)109goto out;110111ret = kstrtobool(buf, &iaa_verify_compress);112if (ret)113goto out;114115ret = count;116out:117mutex_unlock(&iaa_devices_lock);118119return ret;120}121static DRIVER_ATTR_RW(verify_compress);122123/*124* The iaa crypto driver supports three 'sync' methods determining how125* compressions and decompressions are performed:126*127* - sync: the compression or decompression completes before128* returning. This is the mode used by the async crypto129* interface when the sync mode is set to 'sync' and by130* the sync crypto interface regardless of setting.131*132* - async: the compression or decompression is submitted and returns133* immediately. Completion interrupts are not used so134* the caller is responsible for polling the descriptor135* for completion. This mode is applicable to only the136* async crypto interface and is ignored for anything137* else.138*139* - async_irq: the compression or decompression is submitted and140* returns immediately. Completion interrupts are141* enabled so the caller can wait for the completion and142* yield to other threads. When the compression or143* decompression completes, the completion is signaled144* and the caller awakened. This mode is applicable to145* only the async crypto interface and is ignored for146* anything else.147*148* These modes can be set using the iaa_crypto sync_mode driver149* attribute.150*/151152/* Use async mode */153static bool async_mode;154/* Use interrupts */155static bool use_irq;156157/**158* set_iaa_sync_mode - Set IAA sync mode159* @name: The name of the sync mode160*161* Make the IAA sync mode named @name the current sync mode used by162* compression/decompression.163*/164165static int set_iaa_sync_mode(const char *name)166{167int ret = 0;168169if (sysfs_streq(name, "sync")) {170async_mode = false;171use_irq = false;172} else if (sysfs_streq(name, "async")) {173async_mode = false;174use_irq = false;175} else if (sysfs_streq(name, "async_irq")) {176async_mode = true;177use_irq = true;178} else {179ret = -EINVAL;180}181182return ret;183}184185static ssize_t sync_mode_show(struct device_driver *driver, char *buf)186{187int ret = 0;188189if (!async_mode && !use_irq)190ret = sprintf(buf, "%s\n", "sync");191else if (async_mode && !use_irq)192ret = sprintf(buf, "%s\n", "async");193else if (async_mode && use_irq)194ret = sprintf(buf, "%s\n", "async_irq");195196return ret;197}198199static ssize_t sync_mode_store(struct device_driver *driver,200const char *buf, size_t count)201{202int ret = -EBUSY;203204mutex_lock(&iaa_devices_lock);205206if (iaa_crypto_enabled)207goto out;208209ret = set_iaa_sync_mode(buf);210if (ret == 0)211ret = count;212out:213mutex_unlock(&iaa_devices_lock);214215return ret;216}217static DRIVER_ATTR_RW(sync_mode);218219static struct iaa_compression_mode *iaa_compression_modes[IAA_COMP_MODES_MAX];220221static int find_empty_iaa_compression_mode(void)222{223int i = -EINVAL;224225for (i = 0; i < IAA_COMP_MODES_MAX; i++) {226if (iaa_compression_modes[i])227continue;228break;229}230231return i;232}233234static struct iaa_compression_mode *find_iaa_compression_mode(const char *name, int *idx)235{236struct iaa_compression_mode *mode;237int i;238239for (i = 0; i < IAA_COMP_MODES_MAX; i++) {240mode = iaa_compression_modes[i];241if (!mode)242continue;243244if (!strcmp(mode->name, name)) {245*idx = i;246return iaa_compression_modes[i];247}248}249250return NULL;251}252253static void free_iaa_compression_mode(struct iaa_compression_mode *mode)254{255kfree(mode->name);256kfree(mode->ll_table);257kfree(mode->d_table);258259kfree(mode);260}261262/*263* IAA Compression modes are defined by an ll_table and a d_table.264* These tables are typically generated and captured using statistics265* collected from running actual compress/decompress workloads.266*267* A module or other kernel code can add and remove compression modes268* with a given name using the exported @add_iaa_compression_mode()269* and @remove_iaa_compression_mode functions.270*271* When a new compression mode is added, the tables are saved in a272* global compression mode list. When IAA devices are added, a273* per-IAA device dma mapping is created for each IAA device, for each274* compression mode. These are the tables used to do the actual275* compression/deccompression and are unmapped if/when the devices are276* removed. Currently, compression modes must be added before any277* device is added, and removed after all devices have been removed.278*/279280/**281* remove_iaa_compression_mode - Remove an IAA compression mode282* @name: The name the compression mode will be known as283*284* Remove the IAA compression mode named @name.285*/286void remove_iaa_compression_mode(const char *name)287{288struct iaa_compression_mode *mode;289int idx;290291mutex_lock(&iaa_devices_lock);292293if (!list_empty(&iaa_devices))294goto out;295296mode = find_iaa_compression_mode(name, &idx);297if (mode) {298free_iaa_compression_mode(mode);299iaa_compression_modes[idx] = NULL;300}301out:302mutex_unlock(&iaa_devices_lock);303}304EXPORT_SYMBOL_GPL(remove_iaa_compression_mode);305306/**307* add_iaa_compression_mode - Add an IAA compression mode308* @name: The name the compression mode will be known as309* @ll_table: The ll table310* @ll_table_size: The ll table size in bytes311* @d_table: The d table312* @d_table_size: The d table size in bytes313* @init: Optional callback function to init the compression mode data314* @free: Optional callback function to free the compression mode data315*316* Add a new IAA compression mode named @name.317*318* Returns 0 if successful, errcode otherwise.319*/320int add_iaa_compression_mode(const char *name,321const u32 *ll_table,322int ll_table_size,323const u32 *d_table,324int d_table_size,325iaa_dev_comp_init_fn_t init,326iaa_dev_comp_free_fn_t free)327{328struct iaa_compression_mode *mode;329int idx, ret = -ENOMEM;330331mutex_lock(&iaa_devices_lock);332333if (!list_empty(&iaa_devices)) {334ret = -EBUSY;335goto out;336}337338mode = kzalloc(sizeof(*mode), GFP_KERNEL);339if (!mode)340goto out;341342mode->name = kstrdup(name, GFP_KERNEL);343if (!mode->name)344goto free;345346if (ll_table) {347mode->ll_table = kmemdup(ll_table, ll_table_size, GFP_KERNEL);348if (!mode->ll_table)349goto free;350mode->ll_table_size = ll_table_size;351}352353if (d_table) {354mode->d_table = kmemdup(d_table, d_table_size, GFP_KERNEL);355if (!mode->d_table)356goto free;357mode->d_table_size = d_table_size;358}359360mode->init = init;361mode->free = free;362363idx = find_empty_iaa_compression_mode();364if (idx < 0)365goto free;366367pr_debug("IAA compression mode %s added at idx %d\n",368mode->name, idx);369370iaa_compression_modes[idx] = mode;371372ret = 0;373out:374mutex_unlock(&iaa_devices_lock);375376return ret;377free:378free_iaa_compression_mode(mode);379goto out;380}381EXPORT_SYMBOL_GPL(add_iaa_compression_mode);382383static struct iaa_device_compression_mode *384get_iaa_device_compression_mode(struct iaa_device *iaa_device, int idx)385{386return iaa_device->compression_modes[idx];387}388389static void free_device_compression_mode(struct iaa_device *iaa_device,390struct iaa_device_compression_mode *device_mode)391{392size_t size = sizeof(struct aecs_comp_table_record) + IAA_AECS_ALIGN;393struct device *dev = &iaa_device->idxd->pdev->dev;394395kfree(device_mode->name);396397if (device_mode->aecs_comp_table)398dma_free_coherent(dev, size, device_mode->aecs_comp_table,399device_mode->aecs_comp_table_dma_addr);400kfree(device_mode);401}402403#define IDXD_OP_FLAG_AECS_RW_TGLS 0x400000404#define IAX_AECS_DEFAULT_FLAG (IDXD_OP_FLAG_CRAV | IDXD_OP_FLAG_RCR | IDXD_OP_FLAG_CC)405#define IAX_AECS_COMPRESS_FLAG (IAX_AECS_DEFAULT_FLAG | IDXD_OP_FLAG_RD_SRC2_AECS)406#define IAX_AECS_DECOMPRESS_FLAG (IAX_AECS_DEFAULT_FLAG | IDXD_OP_FLAG_RD_SRC2_AECS)407#define IAX_AECS_GEN_FLAG (IAX_AECS_DEFAULT_FLAG | \408IDXD_OP_FLAG_WR_SRC2_AECS_COMP | \409IDXD_OP_FLAG_AECS_RW_TGLS)410411static int check_completion(struct device *dev,412struct iax_completion_record *comp,413bool compress,414bool only_once);415416static int init_device_compression_mode(struct iaa_device *iaa_device,417struct iaa_compression_mode *mode,418int idx, struct idxd_wq *wq)419{420size_t size = sizeof(struct aecs_comp_table_record) + IAA_AECS_ALIGN;421struct device *dev = &iaa_device->idxd->pdev->dev;422struct iaa_device_compression_mode *device_mode;423int ret = -ENOMEM;424425device_mode = kzalloc(sizeof(*device_mode), GFP_KERNEL);426if (!device_mode)427return -ENOMEM;428429device_mode->name = kstrdup(mode->name, GFP_KERNEL);430if (!device_mode->name)431goto free;432433device_mode->aecs_comp_table = dma_alloc_coherent(dev, size,434&device_mode->aecs_comp_table_dma_addr, GFP_KERNEL);435if (!device_mode->aecs_comp_table)436goto free;437438/* Add Huffman table to aecs */439memset(device_mode->aecs_comp_table, 0, sizeof(*device_mode->aecs_comp_table));440memcpy(device_mode->aecs_comp_table->ll_sym, mode->ll_table, mode->ll_table_size);441memcpy(device_mode->aecs_comp_table->d_sym, mode->d_table, mode->d_table_size);442443if (mode->init) {444ret = mode->init(device_mode);445if (ret)446goto free;447}448449/* mode index should match iaa_compression_modes idx */450iaa_device->compression_modes[idx] = device_mode;451452pr_debug("IAA %s compression mode initialized for iaa device %d\n",453mode->name, iaa_device->idxd->id);454455ret = 0;456out:457return ret;458free:459pr_debug("IAA %s compression mode initialization failed for iaa device %d\n",460mode->name, iaa_device->idxd->id);461462free_device_compression_mode(iaa_device, device_mode);463goto out;464}465466static int init_device_compression_modes(struct iaa_device *iaa_device,467struct idxd_wq *wq)468{469struct iaa_compression_mode *mode;470int i, ret = 0;471472for (i = 0; i < IAA_COMP_MODES_MAX; i++) {473mode = iaa_compression_modes[i];474if (!mode)475continue;476477ret = init_device_compression_mode(iaa_device, mode, i, wq);478if (ret)479break;480}481482return ret;483}484485static void remove_device_compression_modes(struct iaa_device *iaa_device)486{487struct iaa_device_compression_mode *device_mode;488int i;489490for (i = 0; i < IAA_COMP_MODES_MAX; i++) {491device_mode = iaa_device->compression_modes[i];492if (!device_mode)493continue;494495if (iaa_compression_modes[i]->free)496iaa_compression_modes[i]->free(device_mode);497free_device_compression_mode(iaa_device, device_mode);498iaa_device->compression_modes[i] = NULL;499}500}501502static struct iaa_device *iaa_device_alloc(void)503{504struct iaa_device *iaa_device;505506iaa_device = kzalloc(sizeof(*iaa_device), GFP_KERNEL);507if (!iaa_device)508return NULL;509510INIT_LIST_HEAD(&iaa_device->wqs);511512return iaa_device;513}514515static bool iaa_has_wq(struct iaa_device *iaa_device, struct idxd_wq *wq)516{517struct iaa_wq *iaa_wq;518519list_for_each_entry(iaa_wq, &iaa_device->wqs, list) {520if (iaa_wq->wq == wq)521return true;522}523524return false;525}526527static struct iaa_device *add_iaa_device(struct idxd_device *idxd)528{529struct iaa_device *iaa_device;530531iaa_device = iaa_device_alloc();532if (!iaa_device)533return NULL;534535iaa_device->idxd = idxd;536537list_add_tail(&iaa_device->list, &iaa_devices);538539nr_iaa++;540541return iaa_device;542}543544static int init_iaa_device(struct iaa_device *iaa_device, struct iaa_wq *iaa_wq)545{546int ret = 0;547548ret = init_device_compression_modes(iaa_device, iaa_wq->wq);549if (ret)550return ret;551552return ret;553}554555static void del_iaa_device(struct iaa_device *iaa_device)556{557list_del(&iaa_device->list);558559nr_iaa--;560}561562static int add_iaa_wq(struct iaa_device *iaa_device, struct idxd_wq *wq,563struct iaa_wq **new_wq)564{565struct idxd_device *idxd = iaa_device->idxd;566struct pci_dev *pdev = idxd->pdev;567struct device *dev = &pdev->dev;568struct iaa_wq *iaa_wq;569570iaa_wq = kzalloc(sizeof(*iaa_wq), GFP_KERNEL);571if (!iaa_wq)572return -ENOMEM;573574iaa_wq->wq = wq;575iaa_wq->iaa_device = iaa_device;576idxd_wq_set_private(wq, iaa_wq);577578list_add_tail(&iaa_wq->list, &iaa_device->wqs);579580iaa_device->n_wq++;581582if (new_wq)583*new_wq = iaa_wq;584585dev_dbg(dev, "added wq %d to iaa device %d, n_wq %d\n",586wq->id, iaa_device->idxd->id, iaa_device->n_wq);587588return 0;589}590591static void del_iaa_wq(struct iaa_device *iaa_device, struct idxd_wq *wq)592{593struct idxd_device *idxd = iaa_device->idxd;594struct pci_dev *pdev = idxd->pdev;595struct device *dev = &pdev->dev;596struct iaa_wq *iaa_wq;597598list_for_each_entry(iaa_wq, &iaa_device->wqs, list) {599if (iaa_wq->wq == wq) {600list_del(&iaa_wq->list);601iaa_device->n_wq--;602603dev_dbg(dev, "removed wq %d from iaa_device %d, n_wq %d, nr_iaa %d\n",604wq->id, iaa_device->idxd->id,605iaa_device->n_wq, nr_iaa);606607if (iaa_device->n_wq == 0)608del_iaa_device(iaa_device);609break;610}611}612}613614static void clear_wq_table(void)615{616int cpu;617618for (cpu = 0; cpu < nr_cpus; cpu++)619wq_table_clear_entry(cpu);620621pr_debug("cleared wq table\n");622}623624static void free_iaa_device(struct iaa_device *iaa_device)625{626if (!iaa_device)627return;628629remove_device_compression_modes(iaa_device);630kfree(iaa_device);631}632633static void __free_iaa_wq(struct iaa_wq *iaa_wq)634{635struct iaa_device *iaa_device;636637if (!iaa_wq)638return;639640iaa_device = iaa_wq->iaa_device;641if (iaa_device->n_wq == 0)642free_iaa_device(iaa_wq->iaa_device);643}644645static void free_iaa_wq(struct iaa_wq *iaa_wq)646{647struct idxd_wq *wq;648649__free_iaa_wq(iaa_wq);650651wq = iaa_wq->wq;652653kfree(iaa_wq);654idxd_wq_set_private(wq, NULL);655}656657static int iaa_wq_get(struct idxd_wq *wq)658{659struct idxd_device *idxd = wq->idxd;660struct iaa_wq *iaa_wq;661int ret = 0;662663spin_lock(&idxd->dev_lock);664iaa_wq = idxd_wq_get_private(wq);665if (iaa_wq && !iaa_wq->remove) {666iaa_wq->ref++;667idxd_wq_get(wq);668} else {669ret = -ENODEV;670}671spin_unlock(&idxd->dev_lock);672673return ret;674}675676static int iaa_wq_put(struct idxd_wq *wq)677{678struct idxd_device *idxd = wq->idxd;679struct iaa_wq *iaa_wq;680bool free = false;681int ret = 0;682683spin_lock(&idxd->dev_lock);684iaa_wq = idxd_wq_get_private(wq);685if (iaa_wq) {686iaa_wq->ref--;687if (iaa_wq->ref == 0 && iaa_wq->remove) {688idxd_wq_set_private(wq, NULL);689free = true;690}691idxd_wq_put(wq);692} else {693ret = -ENODEV;694}695spin_unlock(&idxd->dev_lock);696if (free) {697__free_iaa_wq(iaa_wq);698kfree(iaa_wq);699}700701return ret;702}703704static void free_wq_table(void)705{706int cpu;707708for (cpu = 0; cpu < nr_cpus; cpu++)709wq_table_free_entry(cpu);710711free_percpu(wq_table);712713pr_debug("freed wq table\n");714}715716static int alloc_wq_table(int max_wqs)717{718struct wq_table_entry *entry;719int cpu;720721wq_table = alloc_percpu(struct wq_table_entry);722if (!wq_table)723return -ENOMEM;724725for (cpu = 0; cpu < nr_cpus; cpu++) {726entry = per_cpu_ptr(wq_table, cpu);727entry->wqs = kcalloc(max_wqs, sizeof(*entry->wqs), GFP_KERNEL);728if (!entry->wqs) {729free_wq_table();730return -ENOMEM;731}732733entry->max_wqs = max_wqs;734}735736pr_debug("initialized wq table\n");737738return 0;739}740741static int save_iaa_wq(struct idxd_wq *wq)742{743struct iaa_device *iaa_device, *found = NULL;744struct idxd_device *idxd;745struct pci_dev *pdev;746struct device *dev;747int ret = 0;748749list_for_each_entry(iaa_device, &iaa_devices, list) {750if (iaa_device->idxd == wq->idxd) {751idxd = iaa_device->idxd;752pdev = idxd->pdev;753dev = &pdev->dev;754/*755* Check to see that we don't already have this wq.756* Shouldn't happen but we don't control probing.757*/758if (iaa_has_wq(iaa_device, wq)) {759dev_dbg(dev, "same wq probed multiple times for iaa_device %p\n",760iaa_device);761goto out;762}763764found = iaa_device;765766ret = add_iaa_wq(iaa_device, wq, NULL);767if (ret)768goto out;769770break;771}772}773774if (!found) {775struct iaa_device *new_device;776struct iaa_wq *new_wq;777778new_device = add_iaa_device(wq->idxd);779if (!new_device) {780ret = -ENOMEM;781goto out;782}783784ret = add_iaa_wq(new_device, wq, &new_wq);785if (ret) {786del_iaa_device(new_device);787free_iaa_device(new_device);788goto out;789}790791ret = init_iaa_device(new_device, new_wq);792if (ret) {793del_iaa_wq(new_device, new_wq->wq);794del_iaa_device(new_device);795free_iaa_wq(new_wq);796goto out;797}798}799800if (WARN_ON(nr_iaa == 0))801return -EINVAL;802803cpus_per_iaa = (nr_nodes * nr_cpus_per_node) / nr_iaa;804if (!cpus_per_iaa)805cpus_per_iaa = 1;806out:807return 0;808}809810static void remove_iaa_wq(struct idxd_wq *wq)811{812struct iaa_device *iaa_device;813814list_for_each_entry(iaa_device, &iaa_devices, list) {815if (iaa_has_wq(iaa_device, wq)) {816del_iaa_wq(iaa_device, wq);817break;818}819}820821if (nr_iaa) {822cpus_per_iaa = (nr_nodes * nr_cpus_per_node) / nr_iaa;823if (!cpus_per_iaa)824cpus_per_iaa = 1;825} else826cpus_per_iaa = 1;827}828829static int wq_table_add_wqs(int iaa, int cpu)830{831struct iaa_device *iaa_device, *found_device = NULL;832int ret = 0, cur_iaa = 0, n_wqs_added = 0;833struct idxd_device *idxd;834struct iaa_wq *iaa_wq;835struct pci_dev *pdev;836struct device *dev;837838list_for_each_entry(iaa_device, &iaa_devices, list) {839idxd = iaa_device->idxd;840pdev = idxd->pdev;841dev = &pdev->dev;842843if (cur_iaa != iaa) {844cur_iaa++;845continue;846}847848found_device = iaa_device;849dev_dbg(dev, "getting wq from iaa_device %d, cur_iaa %d\n",850found_device->idxd->id, cur_iaa);851break;852}853854if (!found_device) {855found_device = list_first_entry_or_null(&iaa_devices,856struct iaa_device, list);857if (!found_device) {858pr_debug("couldn't find any iaa devices with wqs!\n");859ret = -EINVAL;860goto out;861}862cur_iaa = 0;863864idxd = found_device->idxd;865pdev = idxd->pdev;866dev = &pdev->dev;867dev_dbg(dev, "getting wq from only iaa_device %d, cur_iaa %d\n",868found_device->idxd->id, cur_iaa);869}870871list_for_each_entry(iaa_wq, &found_device->wqs, list) {872wq_table_add(cpu, iaa_wq->wq);873pr_debug("rebalance: added wq for cpu=%d: iaa wq %d.%d\n",874cpu, iaa_wq->wq->idxd->id, iaa_wq->wq->id);875n_wqs_added++;876}877878if (!n_wqs_added) {879pr_debug("couldn't find any iaa wqs!\n");880ret = -EINVAL;881goto out;882}883out:884return ret;885}886887/*888* Rebalance the wq table so that given a cpu, it's easy to find the889* closest IAA instance. The idea is to try to choose the most890* appropriate IAA instance for a caller and spread available891* workqueues around to clients.892*/893static void rebalance_wq_table(void)894{895const struct cpumask *node_cpus;896int node_cpu, node, cpu, iaa = 0;897898if (nr_iaa == 0)899return;900901pr_debug("rebalance: nr_nodes=%d, nr_cpus %d, nr_iaa %d, cpus_per_iaa %d\n",902nr_nodes, nr_cpus, nr_iaa, cpus_per_iaa);903904clear_wq_table();905906if (nr_iaa == 1) {907for_each_possible_cpu(cpu) {908if (WARN_ON(wq_table_add_wqs(0, cpu)))909goto err;910}911912return;913}914915for_each_node_with_cpus(node) {916cpu = 0;917node_cpus = cpumask_of_node(node);918919for_each_cpu(node_cpu, node_cpus) {920iaa = cpu / cpus_per_iaa;921if (WARN_ON(wq_table_add_wqs(iaa, node_cpu)))922goto err;923cpu++;924}925}926927return;928err:929pr_debug("could not add any wqs for iaa %d to cpu %d!\n", iaa, cpu);930}931932static inline int check_completion(struct device *dev,933struct iax_completion_record *comp,934bool compress,935bool only_once)936{937char *op_str = compress ? "compress" : "decompress";938int status_checks = 0;939int ret = 0;940941while (!comp->status) {942if (only_once)943return -EAGAIN;944cpu_relax();945if (status_checks++ >= IAA_COMPLETION_TIMEOUT) {946/* Something is wrong with the hw, disable it. */947dev_err(dev, "%s completion timed out - "948"assuming broken hw, iaa_crypto now DISABLED\n",949op_str);950iaa_crypto_enabled = false;951ret = -ETIMEDOUT;952goto out;953}954}955956if (comp->status != IAX_COMP_SUCCESS) {957if (comp->status == IAA_ERROR_WATCHDOG_EXPIRED) {958ret = -ETIMEDOUT;959dev_dbg(dev, "%s timed out, size=0x%x\n",960op_str, comp->output_size);961update_completion_timeout_errs();962goto out;963}964965if (comp->status == IAA_ANALYTICS_ERROR &&966comp->error_code == IAA_ERROR_COMP_BUF_OVERFLOW && compress) {967ret = -E2BIG;968dev_dbg(dev, "compressed > uncompressed size,"969" not compressing, size=0x%x\n",970comp->output_size);971update_completion_comp_buf_overflow_errs();972goto out;973}974975if (comp->status == IAA_ERROR_DECOMP_BUF_OVERFLOW) {976ret = -EOVERFLOW;977goto out;978}979980ret = -EINVAL;981dev_dbg(dev, "iaa %s status=0x%x, error=0x%x, size=0x%x\n",982op_str, comp->status, comp->error_code, comp->output_size);983print_hex_dump(KERN_INFO, "cmp-rec: ", DUMP_PREFIX_OFFSET, 8, 1, comp, 64, 0);984update_completion_einval_errs();985986goto out;987}988out:989return ret;990}991992static int deflate_generic_decompress(struct acomp_req *req)993{994ACOMP_FBREQ_ON_STACK(fbreq, req);995int ret;996997ret = crypto_acomp_decompress(fbreq);998req->dlen = fbreq->dlen;9991000update_total_sw_decomp_calls();10011002return ret;1003}10041005static int iaa_remap_for_verify(struct device *dev, struct iaa_wq *iaa_wq,1006struct acomp_req *req,1007dma_addr_t *src_addr, dma_addr_t *dst_addr);10081009static int iaa_compress_verify(struct crypto_tfm *tfm, struct acomp_req *req,1010struct idxd_wq *wq,1011dma_addr_t src_addr, unsigned int slen,1012dma_addr_t dst_addr, unsigned int *dlen);10131014static void iaa_desc_complete(struct idxd_desc *idxd_desc,1015enum idxd_complete_type comp_type,1016bool free_desc, void *__ctx,1017u32 *status)1018{1019struct iaa_device_compression_mode *active_compression_mode;1020struct iaa_compression_ctx *compression_ctx;1021struct crypto_ctx *ctx = __ctx;1022struct iaa_device *iaa_device;1023struct idxd_device *idxd;1024struct iaa_wq *iaa_wq;1025struct pci_dev *pdev;1026struct device *dev;1027int ret, err = 0;10281029compression_ctx = crypto_tfm_ctx(ctx->tfm);10301031iaa_wq = idxd_wq_get_private(idxd_desc->wq);1032iaa_device = iaa_wq->iaa_device;1033idxd = iaa_device->idxd;1034pdev = idxd->pdev;1035dev = &pdev->dev;10361037active_compression_mode = get_iaa_device_compression_mode(iaa_device,1038compression_ctx->mode);1039dev_dbg(dev, "%s: compression mode %s,"1040" ctx->src_addr %llx, ctx->dst_addr %llx\n", __func__,1041active_compression_mode->name,1042ctx->src_addr, ctx->dst_addr);10431044ret = check_completion(dev, idxd_desc->iax_completion,1045ctx->compress, false);1046if (ret) {1047dev_dbg(dev, "%s: check_completion failed ret=%d\n", __func__, ret);1048if (!ctx->compress &&1049idxd_desc->iax_completion->status == IAA_ANALYTICS_ERROR) {1050pr_warn("%s: falling back to deflate-generic decompress, "1051"analytics error code %x\n", __func__,1052idxd_desc->iax_completion->error_code);1053ret = deflate_generic_decompress(ctx->req);1054if (ret) {1055dev_dbg(dev, "%s: deflate-generic failed ret=%d\n",1056__func__, ret);1057err = -EIO;1058goto err;1059}1060} else {1061err = -EIO;1062goto err;1063}1064} else {1065ctx->req->dlen = idxd_desc->iax_completion->output_size;1066}10671068/* Update stats */1069if (ctx->compress) {1070update_total_comp_bytes_out(ctx->req->dlen);1071update_wq_comp_bytes(iaa_wq->wq, ctx->req->dlen);1072} else {1073update_total_decomp_bytes_in(ctx->req->slen);1074update_wq_decomp_bytes(iaa_wq->wq, ctx->req->slen);1075}10761077if (ctx->compress && compression_ctx->verify_compress) {1078u32 *compression_crc = acomp_request_ctx(ctx->req);1079dma_addr_t src_addr, dst_addr;10801081*compression_crc = idxd_desc->iax_completion->crc;10821083ret = iaa_remap_for_verify(dev, iaa_wq, ctx->req, &src_addr, &dst_addr);1084if (ret) {1085dev_dbg(dev, "%s: compress verify remap failed ret=%d\n", __func__, ret);1086err = -EIO;1087goto out;1088}10891090ret = iaa_compress_verify(ctx->tfm, ctx->req, iaa_wq->wq, src_addr,1091ctx->req->slen, dst_addr, &ctx->req->dlen);1092if (ret) {1093dev_dbg(dev, "%s: compress verify failed ret=%d\n", __func__, ret);1094err = -EIO;1095}10961097dma_unmap_sg(dev, ctx->req->dst, sg_nents(ctx->req->dst), DMA_TO_DEVICE);1098dma_unmap_sg(dev, ctx->req->src, sg_nents(ctx->req->src), DMA_FROM_DEVICE);10991100goto out;1101}1102err:1103dma_unmap_sg(dev, ctx->req->dst, sg_nents(ctx->req->dst), DMA_FROM_DEVICE);1104dma_unmap_sg(dev, ctx->req->src, sg_nents(ctx->req->src), DMA_TO_DEVICE);1105out:1106if (ret != 0)1107dev_dbg(dev, "asynchronous compress failed ret=%d\n", ret);11081109if (ctx->req->base.complete)1110acomp_request_complete(ctx->req, err);11111112if (free_desc)1113idxd_free_desc(idxd_desc->wq, idxd_desc);1114iaa_wq_put(idxd_desc->wq);1115}11161117static int iaa_compress(struct crypto_tfm *tfm, struct acomp_req *req,1118struct idxd_wq *wq,1119dma_addr_t src_addr, unsigned int slen,1120dma_addr_t dst_addr, unsigned int *dlen)1121{1122struct iaa_device_compression_mode *active_compression_mode;1123struct iaa_compression_ctx *ctx = crypto_tfm_ctx(tfm);1124u32 *compression_crc = acomp_request_ctx(req);1125struct iaa_device *iaa_device;1126struct idxd_desc *idxd_desc;1127struct iax_hw_desc *desc;1128struct idxd_device *idxd;1129struct iaa_wq *iaa_wq;1130struct pci_dev *pdev;1131struct device *dev;1132int ret = 0;11331134iaa_wq = idxd_wq_get_private(wq);1135iaa_device = iaa_wq->iaa_device;1136idxd = iaa_device->idxd;1137pdev = idxd->pdev;1138dev = &pdev->dev;11391140active_compression_mode = get_iaa_device_compression_mode(iaa_device, ctx->mode);11411142idxd_desc = idxd_alloc_desc(wq, IDXD_OP_BLOCK);1143if (IS_ERR(idxd_desc)) {1144dev_dbg(dev, "idxd descriptor allocation failed\n");1145dev_dbg(dev, "iaa compress failed: ret=%ld\n", PTR_ERR(idxd_desc));1146return PTR_ERR(idxd_desc);1147}1148desc = idxd_desc->iax_hw;11491150desc->flags = IDXD_OP_FLAG_CRAV | IDXD_OP_FLAG_RCR |1151IDXD_OP_FLAG_RD_SRC2_AECS | IDXD_OP_FLAG_CC;1152desc->opcode = IAX_OPCODE_COMPRESS;1153desc->compr_flags = IAA_COMP_FLAGS;1154desc->priv = 0;11551156desc->src1_addr = (u64)src_addr;1157desc->src1_size = slen;1158desc->dst_addr = (u64)dst_addr;1159desc->max_dst_size = *dlen;1160desc->src2_addr = active_compression_mode->aecs_comp_table_dma_addr;1161desc->src2_size = sizeof(struct aecs_comp_table_record);1162desc->completion_addr = idxd_desc->compl_dma;11631164if (ctx->use_irq) {1165desc->flags |= IDXD_OP_FLAG_RCI;11661167idxd_desc->crypto.req = req;1168idxd_desc->crypto.tfm = tfm;1169idxd_desc->crypto.src_addr = src_addr;1170idxd_desc->crypto.dst_addr = dst_addr;1171idxd_desc->crypto.compress = true;11721173dev_dbg(dev, "%s use_async_irq: compression mode %s,"1174" src_addr %llx, dst_addr %llx\n", __func__,1175active_compression_mode->name,1176src_addr, dst_addr);1177}11781179dev_dbg(dev, "%s: compression mode %s,"1180" desc->src1_addr %llx, desc->src1_size %d,"1181" desc->dst_addr %llx, desc->max_dst_size %d,"1182" desc->src2_addr %llx, desc->src2_size %d\n", __func__,1183active_compression_mode->name,1184desc->src1_addr, desc->src1_size, desc->dst_addr,1185desc->max_dst_size, desc->src2_addr, desc->src2_size);11861187ret = idxd_submit_desc(wq, idxd_desc);1188if (ret) {1189dev_dbg(dev, "submit_desc failed ret=%d\n", ret);1190goto err;1191}11921193/* Update stats */1194update_total_comp_calls();1195update_wq_comp_calls(wq);11961197if (ctx->async_mode) {1198ret = -EINPROGRESS;1199dev_dbg(dev, "%s: returning -EINPROGRESS\n", __func__);1200goto out;1201}12021203ret = check_completion(dev, idxd_desc->iax_completion, true, false);1204if (ret) {1205dev_dbg(dev, "check_completion failed ret=%d\n", ret);1206goto err;1207}12081209*dlen = idxd_desc->iax_completion->output_size;12101211/* Update stats */1212update_total_comp_bytes_out(*dlen);1213update_wq_comp_bytes(wq, *dlen);12141215*compression_crc = idxd_desc->iax_completion->crc;12161217if (!ctx->async_mode)1218idxd_free_desc(wq, idxd_desc);1219out:1220return ret;1221err:1222idxd_free_desc(wq, idxd_desc);1223dev_dbg(dev, "iaa compress failed: ret=%d\n", ret);12241225goto out;1226}12271228static int iaa_remap_for_verify(struct device *dev, struct iaa_wq *iaa_wq,1229struct acomp_req *req,1230dma_addr_t *src_addr, dma_addr_t *dst_addr)1231{1232int ret = 0;1233int nr_sgs;12341235dma_unmap_sg(dev, req->dst, sg_nents(req->dst), DMA_FROM_DEVICE);1236dma_unmap_sg(dev, req->src, sg_nents(req->src), DMA_TO_DEVICE);12371238nr_sgs = dma_map_sg(dev, req->src, sg_nents(req->src), DMA_FROM_DEVICE);1239if (nr_sgs <= 0 || nr_sgs > 1) {1240dev_dbg(dev, "verify: couldn't map src sg for iaa device %d,"1241" wq %d: ret=%d\n", iaa_wq->iaa_device->idxd->id,1242iaa_wq->wq->id, ret);1243ret = -EIO;1244goto out;1245}1246*src_addr = sg_dma_address(req->src);1247dev_dbg(dev, "verify: dma_map_sg, src_addr %llx, nr_sgs %d, req->src %p,"1248" req->slen %d, sg_dma_len(sg) %d\n", *src_addr, nr_sgs,1249req->src, req->slen, sg_dma_len(req->src));12501251nr_sgs = dma_map_sg(dev, req->dst, sg_nents(req->dst), DMA_TO_DEVICE);1252if (nr_sgs <= 0 || nr_sgs > 1) {1253dev_dbg(dev, "verify: couldn't map dst sg for iaa device %d,"1254" wq %d: ret=%d\n", iaa_wq->iaa_device->idxd->id,1255iaa_wq->wq->id, ret);1256ret = -EIO;1257dma_unmap_sg(dev, req->src, sg_nents(req->src), DMA_FROM_DEVICE);1258goto out;1259}1260*dst_addr = sg_dma_address(req->dst);1261dev_dbg(dev, "verify: dma_map_sg, dst_addr %llx, nr_sgs %d, req->dst %p,"1262" req->dlen %d, sg_dma_len(sg) %d\n", *dst_addr, nr_sgs,1263req->dst, req->dlen, sg_dma_len(req->dst));1264out:1265return ret;1266}12671268static int iaa_compress_verify(struct crypto_tfm *tfm, struct acomp_req *req,1269struct idxd_wq *wq,1270dma_addr_t src_addr, unsigned int slen,1271dma_addr_t dst_addr, unsigned int *dlen)1272{1273struct iaa_device_compression_mode *active_compression_mode;1274struct iaa_compression_ctx *ctx = crypto_tfm_ctx(tfm);1275u32 *compression_crc = acomp_request_ctx(req);1276struct iaa_device *iaa_device;1277struct idxd_desc *idxd_desc;1278struct iax_hw_desc *desc;1279struct idxd_device *idxd;1280struct iaa_wq *iaa_wq;1281struct pci_dev *pdev;1282struct device *dev;1283int ret = 0;12841285iaa_wq = idxd_wq_get_private(wq);1286iaa_device = iaa_wq->iaa_device;1287idxd = iaa_device->idxd;1288pdev = idxd->pdev;1289dev = &pdev->dev;12901291active_compression_mode = get_iaa_device_compression_mode(iaa_device, ctx->mode);12921293idxd_desc = idxd_alloc_desc(wq, IDXD_OP_BLOCK);1294if (IS_ERR(idxd_desc)) {1295dev_dbg(dev, "idxd descriptor allocation failed\n");1296dev_dbg(dev, "iaa compress failed: ret=%ld\n",1297PTR_ERR(idxd_desc));1298return PTR_ERR(idxd_desc);1299}1300desc = idxd_desc->iax_hw;13011302/* Verify (optional) - decompress and check crc, suppress dest write */13031304desc->flags = IDXD_OP_FLAG_CRAV | IDXD_OP_FLAG_RCR | IDXD_OP_FLAG_CC;1305desc->opcode = IAX_OPCODE_DECOMPRESS;1306desc->decompr_flags = IAA_DECOMP_FLAGS | IAA_DECOMP_SUPPRESS_OUTPUT;1307desc->priv = 0;13081309desc->src1_addr = (u64)dst_addr;1310desc->src1_size = *dlen;1311desc->dst_addr = (u64)src_addr;1312desc->max_dst_size = slen;1313desc->completion_addr = idxd_desc->compl_dma;13141315dev_dbg(dev, "(verify) compression mode %s,"1316" desc->src1_addr %llx, desc->src1_size %d,"1317" desc->dst_addr %llx, desc->max_dst_size %d,"1318" desc->src2_addr %llx, desc->src2_size %d\n",1319active_compression_mode->name,1320desc->src1_addr, desc->src1_size, desc->dst_addr,1321desc->max_dst_size, desc->src2_addr, desc->src2_size);13221323ret = idxd_submit_desc(wq, idxd_desc);1324if (ret) {1325dev_dbg(dev, "submit_desc (verify) failed ret=%d\n", ret);1326goto err;1327}13281329ret = check_completion(dev, idxd_desc->iax_completion, false, false);1330if (ret) {1331dev_dbg(dev, "(verify) check_completion failed ret=%d\n", ret);1332goto err;1333}13341335if (*compression_crc != idxd_desc->iax_completion->crc) {1336ret = -EINVAL;1337dev_dbg(dev, "(verify) iaa comp/decomp crc mismatch:"1338" comp=0x%x, decomp=0x%x\n", *compression_crc,1339idxd_desc->iax_completion->crc);1340print_hex_dump(KERN_INFO, "cmp-rec: ", DUMP_PREFIX_OFFSET,13418, 1, idxd_desc->iax_completion, 64, 0);1342goto err;1343}13441345idxd_free_desc(wq, idxd_desc);1346out:1347return ret;1348err:1349idxd_free_desc(wq, idxd_desc);1350dev_dbg(dev, "iaa compress failed: ret=%d\n", ret);13511352goto out;1353}13541355static int iaa_decompress(struct crypto_tfm *tfm, struct acomp_req *req,1356struct idxd_wq *wq,1357dma_addr_t src_addr, unsigned int slen,1358dma_addr_t dst_addr, unsigned int *dlen)1359{1360struct iaa_device_compression_mode *active_compression_mode;1361struct iaa_compression_ctx *ctx = crypto_tfm_ctx(tfm);1362struct iaa_device *iaa_device;1363struct idxd_desc *idxd_desc;1364struct iax_hw_desc *desc;1365struct idxd_device *idxd;1366struct iaa_wq *iaa_wq;1367struct pci_dev *pdev;1368struct device *dev;1369int ret = 0;13701371iaa_wq = idxd_wq_get_private(wq);1372iaa_device = iaa_wq->iaa_device;1373idxd = iaa_device->idxd;1374pdev = idxd->pdev;1375dev = &pdev->dev;13761377active_compression_mode = get_iaa_device_compression_mode(iaa_device, ctx->mode);13781379idxd_desc = idxd_alloc_desc(wq, IDXD_OP_BLOCK);1380if (IS_ERR(idxd_desc)) {1381dev_dbg(dev, "idxd descriptor allocation failed\n");1382dev_dbg(dev, "iaa decompress failed: ret=%ld\n",1383PTR_ERR(idxd_desc));1384return PTR_ERR(idxd_desc);1385}1386desc = idxd_desc->iax_hw;13871388desc->flags = IDXD_OP_FLAG_CRAV | IDXD_OP_FLAG_RCR | IDXD_OP_FLAG_CC;1389desc->opcode = IAX_OPCODE_DECOMPRESS;1390desc->max_dst_size = PAGE_SIZE;1391desc->decompr_flags = IAA_DECOMP_FLAGS;1392desc->priv = 0;13931394desc->src1_addr = (u64)src_addr;1395desc->dst_addr = (u64)dst_addr;1396desc->max_dst_size = *dlen;1397desc->src1_size = slen;1398desc->completion_addr = idxd_desc->compl_dma;13991400if (ctx->use_irq) {1401desc->flags |= IDXD_OP_FLAG_RCI;14021403idxd_desc->crypto.req = req;1404idxd_desc->crypto.tfm = tfm;1405idxd_desc->crypto.src_addr = src_addr;1406idxd_desc->crypto.dst_addr = dst_addr;1407idxd_desc->crypto.compress = false;14081409dev_dbg(dev, "%s: use_async_irq compression mode %s,"1410" src_addr %llx, dst_addr %llx\n", __func__,1411active_compression_mode->name,1412src_addr, dst_addr);1413}14141415dev_dbg(dev, "%s: decompression mode %s,"1416" desc->src1_addr %llx, desc->src1_size %d,"1417" desc->dst_addr %llx, desc->max_dst_size %d,"1418" desc->src2_addr %llx, desc->src2_size %d\n", __func__,1419active_compression_mode->name,1420desc->src1_addr, desc->src1_size, desc->dst_addr,1421desc->max_dst_size, desc->src2_addr, desc->src2_size);14221423ret = idxd_submit_desc(wq, idxd_desc);1424if (ret) {1425dev_dbg(dev, "submit_desc failed ret=%d\n", ret);1426goto err;1427}14281429/* Update stats */1430update_total_decomp_calls();1431update_wq_decomp_calls(wq);14321433if (ctx->async_mode) {1434ret = -EINPROGRESS;1435dev_dbg(dev, "%s: returning -EINPROGRESS\n", __func__);1436goto out;1437}14381439ret = check_completion(dev, idxd_desc->iax_completion, false, false);1440if (ret) {1441dev_dbg(dev, "%s: check_completion failed ret=%d\n", __func__, ret);1442if (idxd_desc->iax_completion->status == IAA_ANALYTICS_ERROR) {1443pr_warn("%s: falling back to deflate-generic decompress, "1444"analytics error code %x\n", __func__,1445idxd_desc->iax_completion->error_code);1446ret = deflate_generic_decompress(req);1447if (ret) {1448dev_dbg(dev, "%s: deflate-generic failed ret=%d\n",1449__func__, ret);1450goto err;1451}1452} else {1453goto err;1454}1455} else {1456req->dlen = idxd_desc->iax_completion->output_size;1457}14581459*dlen = req->dlen;14601461if (!ctx->async_mode)1462idxd_free_desc(wq, idxd_desc);14631464/* Update stats */1465update_total_decomp_bytes_in(slen);1466update_wq_decomp_bytes(wq, slen);1467out:1468return ret;1469err:1470idxd_free_desc(wq, idxd_desc);1471dev_dbg(dev, "iaa decompress failed: ret=%d\n", ret);14721473goto out;1474}14751476static int iaa_comp_acompress(struct acomp_req *req)1477{1478struct iaa_compression_ctx *compression_ctx;1479struct crypto_tfm *tfm = req->base.tfm;1480dma_addr_t src_addr, dst_addr;1481int nr_sgs, cpu, ret = 0;1482struct iaa_wq *iaa_wq;1483struct idxd_wq *wq;1484struct device *dev;14851486compression_ctx = crypto_tfm_ctx(tfm);14871488if (!iaa_crypto_enabled) {1489pr_debug("iaa_crypto disabled, not compressing\n");1490return -ENODEV;1491}14921493if (!req->src || !req->slen) {1494pr_debug("invalid src, not compressing\n");1495return -EINVAL;1496}14971498cpu = get_cpu();1499wq = wq_table_next_wq(cpu);1500put_cpu();1501if (!wq) {1502pr_debug("no wq configured for cpu=%d\n", cpu);1503return -ENODEV;1504}15051506ret = iaa_wq_get(wq);1507if (ret) {1508pr_debug("no wq available for cpu=%d\n", cpu);1509return -ENODEV;1510}15111512iaa_wq = idxd_wq_get_private(wq);15131514dev = &wq->idxd->pdev->dev;15151516nr_sgs = dma_map_sg(dev, req->src, sg_nents(req->src), DMA_TO_DEVICE);1517if (nr_sgs <= 0 || nr_sgs > 1) {1518dev_dbg(dev, "couldn't map src sg for iaa device %d,"1519" wq %d: ret=%d\n", iaa_wq->iaa_device->idxd->id,1520iaa_wq->wq->id, ret);1521ret = -EIO;1522goto out;1523}1524src_addr = sg_dma_address(req->src);1525dev_dbg(dev, "dma_map_sg, src_addr %llx, nr_sgs %d, req->src %p,"1526" req->slen %d, sg_dma_len(sg) %d\n", src_addr, nr_sgs,1527req->src, req->slen, sg_dma_len(req->src));15281529nr_sgs = dma_map_sg(dev, req->dst, sg_nents(req->dst), DMA_FROM_DEVICE);1530if (nr_sgs <= 0 || nr_sgs > 1) {1531dev_dbg(dev, "couldn't map dst sg for iaa device %d,"1532" wq %d: ret=%d\n", iaa_wq->iaa_device->idxd->id,1533iaa_wq->wq->id, ret);1534ret = -EIO;1535goto err_map_dst;1536}1537dst_addr = sg_dma_address(req->dst);1538dev_dbg(dev, "dma_map_sg, dst_addr %llx, nr_sgs %d, req->dst %p,"1539" req->dlen %d, sg_dma_len(sg) %d\n", dst_addr, nr_sgs,1540req->dst, req->dlen, sg_dma_len(req->dst));15411542ret = iaa_compress(tfm, req, wq, src_addr, req->slen, dst_addr,1543&req->dlen);1544if (ret == -EINPROGRESS)1545return ret;15461547if (!ret && compression_ctx->verify_compress) {1548ret = iaa_remap_for_verify(dev, iaa_wq, req, &src_addr, &dst_addr);1549if (ret) {1550dev_dbg(dev, "%s: compress verify remap failed ret=%d\n", __func__, ret);1551goto out;1552}15531554ret = iaa_compress_verify(tfm, req, wq, src_addr, req->slen,1555dst_addr, &req->dlen);1556if (ret)1557dev_dbg(dev, "asynchronous compress verification failed ret=%d\n", ret);15581559dma_unmap_sg(dev, req->dst, sg_nents(req->dst), DMA_TO_DEVICE);1560dma_unmap_sg(dev, req->src, sg_nents(req->src), DMA_FROM_DEVICE);15611562goto out;1563}15641565if (ret)1566dev_dbg(dev, "asynchronous compress failed ret=%d\n", ret);15671568dma_unmap_sg(dev, req->dst, sg_nents(req->dst), DMA_FROM_DEVICE);1569err_map_dst:1570dma_unmap_sg(dev, req->src, sg_nents(req->src), DMA_TO_DEVICE);1571out:1572iaa_wq_put(wq);15731574return ret;1575}15761577static int iaa_comp_adecompress(struct acomp_req *req)1578{1579struct crypto_tfm *tfm = req->base.tfm;1580dma_addr_t src_addr, dst_addr;1581int nr_sgs, cpu, ret = 0;1582struct iaa_wq *iaa_wq;1583struct device *dev;1584struct idxd_wq *wq;15851586if (!iaa_crypto_enabled) {1587pr_debug("iaa_crypto disabled, not decompressing\n");1588return -ENODEV;1589}15901591if (!req->src || !req->slen) {1592pr_debug("invalid src, not decompressing\n");1593return -EINVAL;1594}15951596cpu = get_cpu();1597wq = wq_table_next_wq(cpu);1598put_cpu();1599if (!wq) {1600pr_debug("no wq configured for cpu=%d\n", cpu);1601return -ENODEV;1602}16031604ret = iaa_wq_get(wq);1605if (ret) {1606pr_debug("no wq available for cpu=%d\n", cpu);1607return -ENODEV;1608}16091610iaa_wq = idxd_wq_get_private(wq);16111612dev = &wq->idxd->pdev->dev;16131614nr_sgs = dma_map_sg(dev, req->src, sg_nents(req->src), DMA_TO_DEVICE);1615if (nr_sgs <= 0 || nr_sgs > 1) {1616dev_dbg(dev, "couldn't map src sg for iaa device %d,"1617" wq %d: ret=%d\n", iaa_wq->iaa_device->idxd->id,1618iaa_wq->wq->id, ret);1619ret = -EIO;1620goto out;1621}1622src_addr = sg_dma_address(req->src);1623dev_dbg(dev, "dma_map_sg, src_addr %llx, nr_sgs %d, req->src %p,"1624" req->slen %d, sg_dma_len(sg) %d\n", src_addr, nr_sgs,1625req->src, req->slen, sg_dma_len(req->src));16261627nr_sgs = dma_map_sg(dev, req->dst, sg_nents(req->dst), DMA_FROM_DEVICE);1628if (nr_sgs <= 0 || nr_sgs > 1) {1629dev_dbg(dev, "couldn't map dst sg for iaa device %d,"1630" wq %d: ret=%d\n", iaa_wq->iaa_device->idxd->id,1631iaa_wq->wq->id, ret);1632ret = -EIO;1633goto err_map_dst;1634}1635dst_addr = sg_dma_address(req->dst);1636dev_dbg(dev, "dma_map_sg, dst_addr %llx, nr_sgs %d, req->dst %p,"1637" req->dlen %d, sg_dma_len(sg) %d\n", dst_addr, nr_sgs,1638req->dst, req->dlen, sg_dma_len(req->dst));16391640ret = iaa_decompress(tfm, req, wq, src_addr, req->slen,1641dst_addr, &req->dlen);1642if (ret == -EINPROGRESS)1643return ret;16441645if (ret != 0)1646dev_dbg(dev, "asynchronous decompress failed ret=%d\n", ret);16471648dma_unmap_sg(dev, req->dst, sg_nents(req->dst), DMA_FROM_DEVICE);1649err_map_dst:1650dma_unmap_sg(dev, req->src, sg_nents(req->src), DMA_TO_DEVICE);1651out:1652iaa_wq_put(wq);16531654return ret;1655}16561657static void compression_ctx_init(struct iaa_compression_ctx *ctx)1658{1659ctx->verify_compress = iaa_verify_compress;1660ctx->async_mode = async_mode;1661ctx->use_irq = use_irq;1662}16631664static int iaa_comp_init_fixed(struct crypto_acomp *acomp_tfm)1665{1666struct crypto_tfm *tfm = crypto_acomp_tfm(acomp_tfm);1667struct iaa_compression_ctx *ctx = crypto_tfm_ctx(tfm);16681669compression_ctx_init(ctx);16701671ctx->mode = IAA_MODE_FIXED;16721673return 0;1674}16751676static struct acomp_alg iaa_acomp_fixed_deflate = {1677.init = iaa_comp_init_fixed,1678.compress = iaa_comp_acompress,1679.decompress = iaa_comp_adecompress,1680.base = {1681.cra_name = "deflate",1682.cra_driver_name = "deflate-iaa",1683.cra_flags = CRYPTO_ALG_ASYNC,1684.cra_ctxsize = sizeof(struct iaa_compression_ctx),1685.cra_reqsize = sizeof(u32),1686.cra_module = THIS_MODULE,1687.cra_priority = IAA_ALG_PRIORITY,1688}1689};16901691static int iaa_register_compression_device(void)1692{1693int ret;16941695ret = crypto_register_acomp(&iaa_acomp_fixed_deflate);1696if (ret) {1697pr_err("deflate algorithm acomp fixed registration failed (%d)\n", ret);1698goto out;1699}17001701iaa_crypto_registered = true;1702out:1703return ret;1704}17051706static int iaa_unregister_compression_device(void)1707{1708if (iaa_crypto_registered)1709crypto_unregister_acomp(&iaa_acomp_fixed_deflate);17101711return 0;1712}17131714static int iaa_crypto_probe(struct idxd_dev *idxd_dev)1715{1716struct idxd_wq *wq = idxd_dev_to_wq(idxd_dev);1717struct idxd_device *idxd = wq->idxd;1718struct idxd_driver_data *data = idxd->data;1719struct device *dev = &idxd_dev->conf_dev;1720bool first_wq = false;1721int ret = 0;17221723if (idxd->state != IDXD_DEV_ENABLED)1724return -ENXIO;17251726if (data->type != IDXD_TYPE_IAX)1727return -ENODEV;17281729mutex_lock(&wq->wq_lock);17301731if (idxd_wq_get_private(wq)) {1732mutex_unlock(&wq->wq_lock);1733return -EBUSY;1734}17351736if (!idxd_wq_driver_name_match(wq, dev)) {1737dev_dbg(dev, "wq %d.%d driver_name match failed: wq driver_name %s, dev driver name %s\n",1738idxd->id, wq->id, wq->driver_name, dev->driver->name);1739idxd->cmd_status = IDXD_SCMD_WQ_NO_DRV_NAME;1740ret = -ENODEV;1741goto err;1742}17431744wq->type = IDXD_WQT_KERNEL;17451746ret = idxd_drv_enable_wq(wq);1747if (ret < 0) {1748dev_dbg(dev, "enable wq %d.%d failed: %d\n",1749idxd->id, wq->id, ret);1750ret = -ENXIO;1751goto err;1752}17531754mutex_lock(&iaa_devices_lock);17551756if (list_empty(&iaa_devices)) {1757ret = alloc_wq_table(wq->idxd->max_wqs);1758if (ret)1759goto err_alloc;1760first_wq = true;1761}17621763ret = save_iaa_wq(wq);1764if (ret)1765goto err_save;17661767rebalance_wq_table();17681769if (first_wq) {1770iaa_crypto_enabled = true;1771ret = iaa_register_compression_device();1772if (ret != 0) {1773iaa_crypto_enabled = false;1774dev_dbg(dev, "IAA compression device registration failed\n");1775goto err_register;1776}1777try_module_get(THIS_MODULE);17781779pr_info("iaa_crypto now ENABLED\n");1780}17811782mutex_unlock(&iaa_devices_lock);1783out:1784mutex_unlock(&wq->wq_lock);17851786return ret;17871788err_register:1789remove_iaa_wq(wq);1790free_iaa_wq(idxd_wq_get_private(wq));1791err_save:1792if (first_wq)1793free_wq_table();1794err_alloc:1795mutex_unlock(&iaa_devices_lock);1796idxd_drv_disable_wq(wq);1797err:1798wq->type = IDXD_WQT_NONE;17991800goto out;1801}18021803static void iaa_crypto_remove(struct idxd_dev *idxd_dev)1804{1805struct idxd_wq *wq = idxd_dev_to_wq(idxd_dev);1806struct idxd_device *idxd = wq->idxd;1807struct iaa_wq *iaa_wq;1808bool free = false;18091810idxd_wq_quiesce(wq);18111812mutex_lock(&wq->wq_lock);1813mutex_lock(&iaa_devices_lock);18141815remove_iaa_wq(wq);18161817spin_lock(&idxd->dev_lock);1818iaa_wq = idxd_wq_get_private(wq);1819if (!iaa_wq) {1820spin_unlock(&idxd->dev_lock);1821pr_err("%s: no iaa_wq available to remove\n", __func__);1822goto out;1823}18241825if (iaa_wq->ref) {1826iaa_wq->remove = true;1827} else {1828wq = iaa_wq->wq;1829idxd_wq_set_private(wq, NULL);1830free = true;1831}1832spin_unlock(&idxd->dev_lock);1833if (free) {1834__free_iaa_wq(iaa_wq);1835kfree(iaa_wq);1836}18371838idxd_drv_disable_wq(wq);1839rebalance_wq_table();18401841if (nr_iaa == 0) {1842iaa_crypto_enabled = false;1843free_wq_table();1844module_put(THIS_MODULE);18451846pr_info("iaa_crypto now DISABLED\n");1847}1848out:1849mutex_unlock(&iaa_devices_lock);1850mutex_unlock(&wq->wq_lock);1851}18521853static enum idxd_dev_type dev_types[] = {1854IDXD_DEV_WQ,1855IDXD_DEV_NONE,1856};18571858static struct idxd_device_driver iaa_crypto_driver = {1859.probe = iaa_crypto_probe,1860.remove = iaa_crypto_remove,1861.name = IDXD_SUBDRIVER_NAME,1862.type = dev_types,1863.desc_complete = iaa_desc_complete,1864};18651866static int __init iaa_crypto_init_module(void)1867{1868int ret = 0;1869int node;18701871nr_cpus = num_possible_cpus();1872for_each_node_with_cpus(node)1873nr_nodes++;1874if (!nr_nodes) {1875pr_err("IAA couldn't find any nodes with cpus\n");1876return -ENODEV;1877}1878nr_cpus_per_node = nr_cpus / nr_nodes;18791880ret = iaa_aecs_init_fixed();1881if (ret < 0) {1882pr_debug("IAA fixed compression mode init failed\n");1883goto err_aecs_init;1884}18851886ret = idxd_driver_register(&iaa_crypto_driver);1887if (ret) {1888pr_debug("IAA wq sub-driver registration failed\n");1889goto err_driver_reg;1890}18911892ret = driver_create_file(&iaa_crypto_driver.drv,1893&driver_attr_verify_compress);1894if (ret) {1895pr_debug("IAA verify_compress attr creation failed\n");1896goto err_verify_attr_create;1897}18981899ret = driver_create_file(&iaa_crypto_driver.drv,1900&driver_attr_sync_mode);1901if (ret) {1902pr_debug("IAA sync mode attr creation failed\n");1903goto err_sync_attr_create;1904}19051906if (iaa_crypto_debugfs_init())1907pr_warn("debugfs init failed, stats not available\n");19081909pr_debug("initialized\n");1910out:1911return ret;19121913err_sync_attr_create:1914driver_remove_file(&iaa_crypto_driver.drv,1915&driver_attr_verify_compress);1916err_verify_attr_create:1917idxd_driver_unregister(&iaa_crypto_driver);1918err_driver_reg:1919iaa_aecs_cleanup_fixed();1920err_aecs_init:19211922goto out;1923}19241925static void __exit iaa_crypto_cleanup_module(void)1926{1927if (iaa_unregister_compression_device())1928pr_debug("IAA compression device unregister failed\n");19291930iaa_crypto_debugfs_cleanup();1931driver_remove_file(&iaa_crypto_driver.drv,1932&driver_attr_sync_mode);1933driver_remove_file(&iaa_crypto_driver.drv,1934&driver_attr_verify_compress);1935idxd_driver_unregister(&iaa_crypto_driver);1936iaa_aecs_cleanup_fixed();19371938pr_debug("cleaned up\n");1939}19401941MODULE_IMPORT_NS("IDXD");1942MODULE_LICENSE("GPL");1943MODULE_ALIAS_IDXD_DEVICE(0);1944MODULE_AUTHOR("Intel Corporation");1945MODULE_DESCRIPTION("IAA Compression Accelerator Crypto Driver");19461947module_init(iaa_crypto_init_module);1948module_exit(iaa_crypto_cleanup_module);194919501951