Path: blob/master/drivers/crypto/intel/iaa/iaa_crypto_main.c
51759 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/sysfs.h>8#include <linux/device.h>9#include <linux/iommu.h>10#include <uapi/linux/idxd.h>11#include <linux/highmem.h>12#include <linux/sched/smt.h>13#include <crypto/internal/acompress.h>1415#include "idxd.h"16#include "iaa_crypto.h"17#include "iaa_crypto_stats.h"1819#ifdef pr_fmt20#undef pr_fmt21#endif2223#define pr_fmt(fmt) "idxd: " IDXD_SUBDRIVER_NAME ": " fmt2425#define IAA_ALG_PRIORITY 3002627/* number of iaa instances probed */28static unsigned int nr_iaa;29static unsigned int nr_cpus;30static unsigned int nr_nodes;31static unsigned int nr_cpus_per_node;3233/* Number of physical cpus sharing each iaa instance */34static unsigned int cpus_per_iaa;3536/* Per-cpu lookup table for balanced wqs */37static struct wq_table_entry __percpu *wq_table;3839static struct idxd_wq *wq_table_next_wq(int cpu)40{41struct wq_table_entry *entry = per_cpu_ptr(wq_table, cpu);4243if (++entry->cur_wq >= entry->n_wqs)44entry->cur_wq = 0;4546if (!entry->wqs[entry->cur_wq])47return NULL;4849pr_debug("%s: returning wq at idx %d (iaa wq %d.%d) from cpu %d\n", __func__,50entry->cur_wq, entry->wqs[entry->cur_wq]->idxd->id,51entry->wqs[entry->cur_wq]->id, cpu);5253return entry->wqs[entry->cur_wq];54}5556static void wq_table_add(int cpu, struct idxd_wq *wq)57{58struct wq_table_entry *entry = per_cpu_ptr(wq_table, cpu);5960if (WARN_ON(entry->n_wqs == entry->max_wqs))61return;6263entry->wqs[entry->n_wqs++] = wq;6465pr_debug("%s: added iaa wq %d.%d to idx %d of cpu %d\n", __func__,66entry->wqs[entry->n_wqs - 1]->idxd->id,67entry->wqs[entry->n_wqs - 1]->id, entry->n_wqs - 1, cpu);68}6970static void wq_table_free_entry(int cpu)71{72struct wq_table_entry *entry = per_cpu_ptr(wq_table, cpu);7374kfree(entry->wqs);75memset(entry, 0, sizeof(*entry));76}7778static void wq_table_clear_entry(int cpu)79{80struct wq_table_entry *entry = per_cpu_ptr(wq_table, cpu);8182entry->n_wqs = 0;83entry->cur_wq = 0;84memset(entry->wqs, 0, entry->max_wqs * sizeof(struct idxd_wq *));85}8687LIST_HEAD(iaa_devices);88DEFINE_MUTEX(iaa_devices_lock);8990/* If enabled, IAA hw crypto algos are registered, unavailable otherwise */91static bool iaa_crypto_enabled;92static bool iaa_crypto_registered;9394/* Verify results of IAA compress or not */95static bool iaa_verify_compress = true;9697static ssize_t verify_compress_show(struct device_driver *driver, char *buf)98{99return sysfs_emit(buf, "%d\n", iaa_verify_compress);100}101102static ssize_t verify_compress_store(struct device_driver *driver,103const char *buf, size_t count)104{105int ret = -EBUSY;106107mutex_lock(&iaa_devices_lock);108109if (iaa_crypto_enabled)110goto out;111112ret = kstrtobool(buf, &iaa_verify_compress);113if (ret)114goto out;115116ret = count;117out:118mutex_unlock(&iaa_devices_lock);119120return ret;121}122static DRIVER_ATTR_RW(verify_compress);123124/*125* The iaa crypto driver supports three 'sync' methods determining how126* compressions and decompressions are performed:127*128* - sync: the compression or decompression completes before129* returning. This is the mode used by the async crypto130* interface when the sync mode is set to 'sync' and by131* the sync crypto interface regardless of setting.132*133* - async: the compression or decompression is submitted and returns134* immediately. Completion interrupts are not used so135* the caller is responsible for polling the descriptor136* for completion. This mode is applicable to only the137* async crypto interface and is ignored for anything138* else.139*140* - async_irq: the compression or decompression is submitted and141* returns immediately. Completion interrupts are142* enabled so the caller can wait for the completion and143* yield to other threads. When the compression or144* decompression completes, the completion is signaled145* and the caller awakened. This mode is applicable to146* only the async crypto interface and is ignored for147* anything else.148*149* These modes can be set using the iaa_crypto sync_mode driver150* attribute.151*/152153/* Use async mode */154static bool async_mode;155/* Use interrupts */156static bool use_irq;157158/**159* set_iaa_sync_mode - Set IAA sync mode160* @name: The name of the sync mode161*162* Make the IAA sync mode named @name the current sync mode used by163* compression/decompression.164*/165166static int set_iaa_sync_mode(const char *name)167{168int ret = 0;169170if (sysfs_streq(name, "sync")) {171async_mode = false;172use_irq = false;173} else if (sysfs_streq(name, "async")) {174async_mode = false;175use_irq = false;176} else if (sysfs_streq(name, "async_irq")) {177async_mode = true;178use_irq = true;179} else {180ret = -EINVAL;181}182183return ret;184}185186static ssize_t sync_mode_show(struct device_driver *driver, char *buf)187{188int ret = 0;189190if (!async_mode && !use_irq)191ret = sysfs_emit(buf, "%s\n", "sync");192else if (async_mode && !use_irq)193ret = sysfs_emit(buf, "%s\n", "async");194else if (async_mode && use_irq)195ret = sysfs_emit(buf, "%s\n", "async_irq");196197return ret;198}199200static ssize_t sync_mode_store(struct device_driver *driver,201const char *buf, size_t count)202{203int ret = -EBUSY;204205mutex_lock(&iaa_devices_lock);206207if (iaa_crypto_enabled)208goto out;209210ret = set_iaa_sync_mode(buf);211if (ret == 0)212ret = count;213out:214mutex_unlock(&iaa_devices_lock);215216return ret;217}218static DRIVER_ATTR_RW(sync_mode);219220static struct iaa_compression_mode *iaa_compression_modes[IAA_COMP_MODES_MAX];221222static int find_empty_iaa_compression_mode(void)223{224int i;225226for (i = 0; i < IAA_COMP_MODES_MAX; i++)227if (!iaa_compression_modes[i])228return i;229230return -EINVAL;231}232233static struct iaa_compression_mode *find_iaa_compression_mode(const char *name, int *idx)234{235struct iaa_compression_mode *mode;236int i;237238for (i = 0; i < IAA_COMP_MODES_MAX; i++) {239mode = iaa_compression_modes[i];240if (!mode)241continue;242243if (!strcmp(mode->name, name)) {244*idx = i;245return iaa_compression_modes[i];246}247}248249return NULL;250}251252static void free_iaa_compression_mode(struct iaa_compression_mode *mode)253{254kfree(mode->name);255kfree(mode->ll_table);256kfree(mode->d_table);257258kfree(mode);259}260261/*262* IAA Compression modes are defined by an ll_table and a d_table.263* These tables are typically generated and captured using statistics264* collected from running actual compress/decompress workloads.265*266* A module or other kernel code can add and remove compression modes267* with a given name using the exported @add_iaa_compression_mode()268* and @remove_iaa_compression_mode functions.269*270* When a new compression mode is added, the tables are saved in a271* global compression mode list. When IAA devices are added, a272* per-IAA device dma mapping is created for each IAA device, for each273* compression mode. These are the tables used to do the actual274* compression/deccompression and are unmapped if/when the devices are275* removed. Currently, compression modes must be added before any276* device is added, and removed after all devices have been removed.277*/278279/**280* remove_iaa_compression_mode - Remove an IAA compression mode281* @name: The name the compression mode will be known as282*283* Remove the IAA compression mode named @name.284*/285void remove_iaa_compression_mode(const char *name)286{287struct iaa_compression_mode *mode;288int idx;289290mutex_lock(&iaa_devices_lock);291292if (!list_empty(&iaa_devices))293goto out;294295mode = find_iaa_compression_mode(name, &idx);296if (mode) {297free_iaa_compression_mode(mode);298iaa_compression_modes[idx] = NULL;299}300out:301mutex_unlock(&iaa_devices_lock);302}303EXPORT_SYMBOL_GPL(remove_iaa_compression_mode);304305/**306* add_iaa_compression_mode - Add an IAA compression mode307* @name: The name the compression mode will be known as308* @ll_table: The ll table309* @ll_table_size: The ll table size in bytes310* @d_table: The d table311* @d_table_size: The d table size in bytes312* @init: Optional callback function to init the compression mode data313* @free: Optional callback function to free the compression mode data314*315* Add a new IAA compression mode named @name.316*317* Returns 0 if successful, errcode otherwise.318*/319int add_iaa_compression_mode(const char *name,320const u32 *ll_table,321int ll_table_size,322const u32 *d_table,323int d_table_size,324iaa_dev_comp_init_fn_t init,325iaa_dev_comp_free_fn_t free)326{327struct iaa_compression_mode *mode;328int idx, ret = -ENOMEM;329330mutex_lock(&iaa_devices_lock);331332if (!list_empty(&iaa_devices)) {333ret = -EBUSY;334goto out;335}336337mode = kzalloc(sizeof(*mode), GFP_KERNEL);338if (!mode)339goto out;340341mode->name = kstrdup(name, GFP_KERNEL);342if (!mode->name)343goto free;344345if (ll_table) {346mode->ll_table = kmemdup(ll_table, ll_table_size, GFP_KERNEL);347if (!mode->ll_table)348goto free;349mode->ll_table_size = ll_table_size;350}351352if (d_table) {353mode->d_table = kmemdup(d_table, d_table_size, GFP_KERNEL);354if (!mode->d_table)355goto free;356mode->d_table_size = d_table_size;357}358359mode->init = init;360mode->free = free;361362idx = find_empty_iaa_compression_mode();363if (idx < 0)364goto free;365366pr_debug("IAA compression mode %s added at idx %d\n",367mode->name, idx);368369iaa_compression_modes[idx] = mode;370371ret = 0;372out:373mutex_unlock(&iaa_devices_lock);374375return ret;376free:377free_iaa_compression_mode(mode);378goto out;379}380EXPORT_SYMBOL_GPL(add_iaa_compression_mode);381382static struct iaa_device_compression_mode *383get_iaa_device_compression_mode(struct iaa_device *iaa_device, int idx)384{385return iaa_device->compression_modes[idx];386}387388static void free_device_compression_mode(struct iaa_device *iaa_device,389struct iaa_device_compression_mode *device_mode)390{391size_t size = sizeof(struct aecs_comp_table_record) + IAA_AECS_ALIGN;392struct device *dev = &iaa_device->idxd->pdev->dev;393394kfree(device_mode->name);395396if (device_mode->aecs_comp_table)397dma_free_coherent(dev, size, device_mode->aecs_comp_table,398device_mode->aecs_comp_table_dma_addr);399kfree(device_mode);400}401402#define IDXD_OP_FLAG_AECS_RW_TGLS 0x400000403#define IAX_AECS_DEFAULT_FLAG (IDXD_OP_FLAG_CRAV | IDXD_OP_FLAG_RCR | IDXD_OP_FLAG_CC)404#define IAX_AECS_COMPRESS_FLAG (IAX_AECS_DEFAULT_FLAG | IDXD_OP_FLAG_RD_SRC2_AECS)405#define IAX_AECS_DECOMPRESS_FLAG (IAX_AECS_DEFAULT_FLAG | IDXD_OP_FLAG_RD_SRC2_AECS)406#define IAX_AECS_GEN_FLAG (IAX_AECS_DEFAULT_FLAG | \407IDXD_OP_FLAG_WR_SRC2_AECS_COMP | \408IDXD_OP_FLAG_AECS_RW_TGLS)409410static int check_completion(struct device *dev,411struct iax_completion_record *comp,412bool compress,413bool only_once);414415static int init_device_compression_mode(struct iaa_device *iaa_device,416struct iaa_compression_mode *mode,417int idx, struct idxd_wq *wq)418{419size_t size = sizeof(struct aecs_comp_table_record) + IAA_AECS_ALIGN;420struct device *dev = &iaa_device->idxd->pdev->dev;421struct iaa_device_compression_mode *device_mode;422int ret = -ENOMEM;423424device_mode = kzalloc(sizeof(*device_mode), GFP_KERNEL);425if (!device_mode)426return -ENOMEM;427428device_mode->name = kstrdup(mode->name, GFP_KERNEL);429if (!device_mode->name)430goto free;431432device_mode->aecs_comp_table = dma_alloc_coherent(dev, size,433&device_mode->aecs_comp_table_dma_addr, GFP_KERNEL);434if (!device_mode->aecs_comp_table)435goto free;436437/* Add Huffman table to aecs */438memset(device_mode->aecs_comp_table, 0, sizeof(*device_mode->aecs_comp_table));439memcpy(device_mode->aecs_comp_table->ll_sym, mode->ll_table, mode->ll_table_size);440memcpy(device_mode->aecs_comp_table->d_sym, mode->d_table, mode->d_table_size);441442if (mode->init) {443ret = mode->init(device_mode);444if (ret)445goto free;446}447448/* mode index should match iaa_compression_modes idx */449iaa_device->compression_modes[idx] = device_mode;450451pr_debug("IAA %s compression mode initialized for iaa device %d\n",452mode->name, iaa_device->idxd->id);453454ret = 0;455out:456return ret;457free:458pr_debug("IAA %s compression mode initialization failed for iaa device %d\n",459mode->name, iaa_device->idxd->id);460461free_device_compression_mode(iaa_device, device_mode);462goto out;463}464465static int init_device_compression_modes(struct iaa_device *iaa_device,466struct idxd_wq *wq)467{468struct iaa_compression_mode *mode;469int i, ret = 0;470471for (i = 0; i < IAA_COMP_MODES_MAX; i++) {472mode = iaa_compression_modes[i];473if (!mode)474continue;475476ret = init_device_compression_mode(iaa_device, mode, i, wq);477if (ret)478break;479}480481return ret;482}483484static void remove_device_compression_modes(struct iaa_device *iaa_device)485{486struct iaa_device_compression_mode *device_mode;487int i;488489for (i = 0; i < IAA_COMP_MODES_MAX; i++) {490device_mode = iaa_device->compression_modes[i];491if (!device_mode)492continue;493494if (iaa_compression_modes[i]->free)495iaa_compression_modes[i]->free(device_mode);496free_device_compression_mode(iaa_device, device_mode);497iaa_device->compression_modes[i] = NULL;498}499}500501static struct iaa_device *iaa_device_alloc(void)502{503struct iaa_device *iaa_device;504505iaa_device = kzalloc(sizeof(*iaa_device), GFP_KERNEL);506if (!iaa_device)507return NULL;508509INIT_LIST_HEAD(&iaa_device->wqs);510511return iaa_device;512}513514static bool iaa_has_wq(struct iaa_device *iaa_device, struct idxd_wq *wq)515{516struct iaa_wq *iaa_wq;517518list_for_each_entry(iaa_wq, &iaa_device->wqs, list) {519if (iaa_wq->wq == wq)520return true;521}522523return false;524}525526static struct iaa_device *add_iaa_device(struct idxd_device *idxd)527{528struct iaa_device *iaa_device;529530iaa_device = iaa_device_alloc();531if (!iaa_device)532return NULL;533534iaa_device->idxd = idxd;535536list_add_tail(&iaa_device->list, &iaa_devices);537538nr_iaa++;539540return iaa_device;541}542543static int init_iaa_device(struct iaa_device *iaa_device, struct iaa_wq *iaa_wq)544{545return init_device_compression_modes(iaa_device, iaa_wq->wq);546}547548static void del_iaa_device(struct iaa_device *iaa_device)549{550list_del(&iaa_device->list);551552nr_iaa--;553}554555static int add_iaa_wq(struct iaa_device *iaa_device, struct idxd_wq *wq,556struct iaa_wq **new_wq)557{558struct idxd_device *idxd = iaa_device->idxd;559struct pci_dev *pdev = idxd->pdev;560struct device *dev = &pdev->dev;561struct iaa_wq *iaa_wq;562563iaa_wq = kzalloc(sizeof(*iaa_wq), GFP_KERNEL);564if (!iaa_wq)565return -ENOMEM;566567iaa_wq->wq = wq;568iaa_wq->iaa_device = iaa_device;569idxd_wq_set_private(wq, iaa_wq);570571list_add_tail(&iaa_wq->list, &iaa_device->wqs);572573iaa_device->n_wq++;574575if (new_wq)576*new_wq = iaa_wq;577578dev_dbg(dev, "added wq %d to iaa device %d, n_wq %d\n",579wq->id, iaa_device->idxd->id, iaa_device->n_wq);580581return 0;582}583584static void del_iaa_wq(struct iaa_device *iaa_device, struct idxd_wq *wq)585{586struct idxd_device *idxd = iaa_device->idxd;587struct pci_dev *pdev = idxd->pdev;588struct device *dev = &pdev->dev;589struct iaa_wq *iaa_wq;590591list_for_each_entry(iaa_wq, &iaa_device->wqs, list) {592if (iaa_wq->wq == wq) {593list_del(&iaa_wq->list);594iaa_device->n_wq--;595596dev_dbg(dev, "removed wq %d from iaa_device %d, n_wq %d, nr_iaa %d\n",597wq->id, iaa_device->idxd->id,598iaa_device->n_wq, nr_iaa);599600if (iaa_device->n_wq == 0)601del_iaa_device(iaa_device);602break;603}604}605}606607static void clear_wq_table(void)608{609int cpu;610611for (cpu = 0; cpu < nr_cpus; cpu++)612wq_table_clear_entry(cpu);613614pr_debug("cleared wq table\n");615}616617static void free_iaa_device(struct iaa_device *iaa_device)618{619if (!iaa_device)620return;621622remove_device_compression_modes(iaa_device);623kfree(iaa_device);624}625626static void __free_iaa_wq(struct iaa_wq *iaa_wq)627{628struct iaa_device *iaa_device;629630if (!iaa_wq)631return;632633iaa_device = iaa_wq->iaa_device;634if (iaa_device->n_wq == 0)635free_iaa_device(iaa_wq->iaa_device);636}637638static void free_iaa_wq(struct iaa_wq *iaa_wq)639{640struct idxd_wq *wq;641642__free_iaa_wq(iaa_wq);643644wq = iaa_wq->wq;645646kfree(iaa_wq);647idxd_wq_set_private(wq, NULL);648}649650static int iaa_wq_get(struct idxd_wq *wq)651{652struct idxd_device *idxd = wq->idxd;653struct iaa_wq *iaa_wq;654int ret = 0;655656spin_lock(&idxd->dev_lock);657iaa_wq = idxd_wq_get_private(wq);658if (iaa_wq && !iaa_wq->remove) {659iaa_wq->ref++;660idxd_wq_get(wq);661} else {662ret = -ENODEV;663}664spin_unlock(&idxd->dev_lock);665666return ret;667}668669static int iaa_wq_put(struct idxd_wq *wq)670{671struct idxd_device *idxd = wq->idxd;672struct iaa_wq *iaa_wq;673bool free = false;674int ret = 0;675676spin_lock(&idxd->dev_lock);677iaa_wq = idxd_wq_get_private(wq);678if (iaa_wq) {679iaa_wq->ref--;680if (iaa_wq->ref == 0 && iaa_wq->remove) {681idxd_wq_set_private(wq, NULL);682free = true;683}684idxd_wq_put(wq);685} else {686ret = -ENODEV;687}688spin_unlock(&idxd->dev_lock);689if (free) {690__free_iaa_wq(iaa_wq);691kfree(iaa_wq);692}693694return ret;695}696697static void free_wq_table(void)698{699int cpu;700701for (cpu = 0; cpu < nr_cpus; cpu++)702wq_table_free_entry(cpu);703704free_percpu(wq_table);705706pr_debug("freed wq table\n");707}708709static int alloc_wq_table(int max_wqs)710{711struct wq_table_entry *entry;712int cpu;713714wq_table = alloc_percpu(struct wq_table_entry);715if (!wq_table)716return -ENOMEM;717718for (cpu = 0; cpu < nr_cpus; cpu++) {719entry = per_cpu_ptr(wq_table, cpu);720entry->wqs = kcalloc(max_wqs, sizeof(*entry->wqs), GFP_KERNEL);721if (!entry->wqs) {722free_wq_table();723return -ENOMEM;724}725726entry->max_wqs = max_wqs;727}728729pr_debug("initialized wq table\n");730731return 0;732}733734static int save_iaa_wq(struct idxd_wq *wq)735{736struct iaa_device *iaa_device, *found = NULL;737struct idxd_device *idxd;738struct pci_dev *pdev;739struct device *dev;740int ret = 0;741742list_for_each_entry(iaa_device, &iaa_devices, list) {743if (iaa_device->idxd == wq->idxd) {744idxd = iaa_device->idxd;745pdev = idxd->pdev;746dev = &pdev->dev;747/*748* Check to see that we don't already have this wq.749* Shouldn't happen but we don't control probing.750*/751if (iaa_has_wq(iaa_device, wq)) {752dev_dbg(dev, "same wq probed multiple times for iaa_device %p\n",753iaa_device);754goto out;755}756757found = iaa_device;758759ret = add_iaa_wq(iaa_device, wq, NULL);760if (ret)761goto out;762763break;764}765}766767if (!found) {768struct iaa_device *new_device;769struct iaa_wq *new_wq;770771new_device = add_iaa_device(wq->idxd);772if (!new_device) {773ret = -ENOMEM;774goto out;775}776777ret = add_iaa_wq(new_device, wq, &new_wq);778if (ret) {779del_iaa_device(new_device);780free_iaa_device(new_device);781goto out;782}783784ret = init_iaa_device(new_device, new_wq);785if (ret) {786del_iaa_wq(new_device, new_wq->wq);787del_iaa_device(new_device);788free_iaa_wq(new_wq);789goto out;790}791}792793if (WARN_ON(nr_iaa == 0))794return -EINVAL;795796cpus_per_iaa = (nr_nodes * nr_cpus_per_node) / nr_iaa;797if (!cpus_per_iaa)798cpus_per_iaa = 1;799out:800return ret;801}802803static void remove_iaa_wq(struct idxd_wq *wq)804{805struct iaa_device *iaa_device;806807list_for_each_entry(iaa_device, &iaa_devices, list) {808if (iaa_has_wq(iaa_device, wq)) {809del_iaa_wq(iaa_device, wq);810break;811}812}813814if (nr_iaa) {815cpus_per_iaa = (nr_nodes * nr_cpus_per_node) / nr_iaa;816if (!cpus_per_iaa)817cpus_per_iaa = 1;818} else819cpus_per_iaa = 1;820}821822static int wq_table_add_wqs(int iaa, int cpu)823{824struct iaa_device *iaa_device, *found_device = NULL;825int ret = 0, cur_iaa = 0, n_wqs_added = 0;826struct idxd_device *idxd;827struct iaa_wq *iaa_wq;828struct pci_dev *pdev;829struct device *dev;830831list_for_each_entry(iaa_device, &iaa_devices, list) {832idxd = iaa_device->idxd;833pdev = idxd->pdev;834dev = &pdev->dev;835836if (cur_iaa != iaa) {837cur_iaa++;838continue;839}840841found_device = iaa_device;842dev_dbg(dev, "getting wq from iaa_device %d, cur_iaa %d\n",843found_device->idxd->id, cur_iaa);844break;845}846847if (!found_device) {848found_device = list_first_entry_or_null(&iaa_devices,849struct iaa_device, list);850if (!found_device) {851pr_debug("couldn't find any iaa devices with wqs!\n");852ret = -EINVAL;853goto out;854}855cur_iaa = 0;856857idxd = found_device->idxd;858pdev = idxd->pdev;859dev = &pdev->dev;860dev_dbg(dev, "getting wq from only iaa_device %d, cur_iaa %d\n",861found_device->idxd->id, cur_iaa);862}863864list_for_each_entry(iaa_wq, &found_device->wqs, list) {865wq_table_add(cpu, iaa_wq->wq);866pr_debug("rebalance: added wq for cpu=%d: iaa wq %d.%d\n",867cpu, iaa_wq->wq->idxd->id, iaa_wq->wq->id);868n_wqs_added++;869}870871if (!n_wqs_added) {872pr_debug("couldn't find any iaa wqs!\n");873ret = -EINVAL;874goto out;875}876out:877return ret;878}879880/*881* Rebalance the wq table so that given a cpu, it's easy to find the882* closest IAA instance. The idea is to try to choose the most883* appropriate IAA instance for a caller and spread available884* workqueues around to clients.885*/886static void rebalance_wq_table(void)887{888const struct cpumask *node_cpus;889int node_cpu, node, cpu, iaa = 0;890891if (nr_iaa == 0)892return;893894pr_debug("rebalance: nr_nodes=%d, nr_cpus %d, nr_iaa %d, cpus_per_iaa %d\n",895nr_nodes, nr_cpus, nr_iaa, cpus_per_iaa);896897clear_wq_table();898899if (nr_iaa == 1) {900for_each_possible_cpu(cpu) {901if (WARN_ON(wq_table_add_wqs(0, cpu)))902goto err;903}904905return;906}907908for_each_node_with_cpus(node) {909cpu = 0;910node_cpus = cpumask_of_node(node);911912for_each_cpu(node_cpu, node_cpus) {913iaa = cpu / cpus_per_iaa;914if (WARN_ON(wq_table_add_wqs(iaa, node_cpu)))915goto err;916cpu++;917}918}919920return;921err:922pr_debug("could not add any wqs for iaa %d to cpu %d!\n", iaa, cpu);923}924925static inline int check_completion(struct device *dev,926struct iax_completion_record *comp,927bool compress,928bool only_once)929{930char *op_str = compress ? "compress" : "decompress";931int status_checks = 0;932int ret = 0;933934while (!comp->status) {935if (only_once)936return -EAGAIN;937cpu_relax();938if (status_checks++ >= IAA_COMPLETION_TIMEOUT) {939/* Something is wrong with the hw, disable it. */940dev_err(dev, "%s completion timed out - "941"assuming broken hw, iaa_crypto now DISABLED\n",942op_str);943iaa_crypto_enabled = false;944ret = -ETIMEDOUT;945goto out;946}947}948949if (comp->status != IAX_COMP_SUCCESS) {950if (comp->status == IAA_ERROR_WATCHDOG_EXPIRED) {951ret = -ETIMEDOUT;952dev_dbg(dev, "%s timed out, size=0x%x\n",953op_str, comp->output_size);954update_completion_timeout_errs();955goto out;956}957958if (comp->status == IAA_ANALYTICS_ERROR &&959comp->error_code == IAA_ERROR_COMP_BUF_OVERFLOW && compress) {960ret = -E2BIG;961dev_dbg(dev, "compressed > uncompressed size,"962" not compressing, size=0x%x\n",963comp->output_size);964update_completion_comp_buf_overflow_errs();965goto out;966}967968if (comp->status == IAA_ERROR_DECOMP_BUF_OVERFLOW) {969ret = -EOVERFLOW;970goto out;971}972973ret = -EINVAL;974dev_dbg(dev, "iaa %s status=0x%x, error=0x%x, size=0x%x\n",975op_str, comp->status, comp->error_code, comp->output_size);976print_hex_dump(KERN_INFO, "cmp-rec: ", DUMP_PREFIX_OFFSET, 8, 1, comp, 64, 0);977update_completion_einval_errs();978979goto out;980}981out:982return ret;983}984985static int deflate_generic_decompress(struct acomp_req *req)986{987ACOMP_FBREQ_ON_STACK(fbreq, req);988int ret;989990ret = crypto_acomp_decompress(fbreq);991req->dlen = fbreq->dlen;992993update_total_sw_decomp_calls();994995return ret;996}997998static int iaa_remap_for_verify(struct device *dev, struct iaa_wq *iaa_wq,999struct acomp_req *req,1000dma_addr_t *src_addr, dma_addr_t *dst_addr);10011002static int iaa_compress_verify(struct crypto_tfm *tfm, struct acomp_req *req,1003struct idxd_wq *wq,1004dma_addr_t src_addr, unsigned int slen,1005dma_addr_t dst_addr, unsigned int *dlen);10061007static void iaa_desc_complete(struct idxd_desc *idxd_desc,1008enum idxd_complete_type comp_type,1009bool free_desc, void *__ctx,1010u32 *status)1011{1012struct iaa_device_compression_mode *active_compression_mode;1013struct iaa_compression_ctx *compression_ctx;1014struct crypto_ctx *ctx = __ctx;1015struct iaa_device *iaa_device;1016struct idxd_device *idxd;1017struct iaa_wq *iaa_wq;1018struct pci_dev *pdev;1019struct device *dev;1020int ret, err = 0;10211022compression_ctx = crypto_tfm_ctx(ctx->tfm);10231024iaa_wq = idxd_wq_get_private(idxd_desc->wq);1025iaa_device = iaa_wq->iaa_device;1026idxd = iaa_device->idxd;1027pdev = idxd->pdev;1028dev = &pdev->dev;10291030active_compression_mode = get_iaa_device_compression_mode(iaa_device,1031compression_ctx->mode);1032dev_dbg(dev, "%s: compression mode %s,"1033" ctx->src_addr %llx, ctx->dst_addr %llx\n", __func__,1034active_compression_mode->name,1035ctx->src_addr, ctx->dst_addr);10361037ret = check_completion(dev, idxd_desc->iax_completion,1038ctx->compress, false);1039if (ret) {1040dev_dbg(dev, "%s: check_completion failed ret=%d\n", __func__, ret);1041if (!ctx->compress &&1042idxd_desc->iax_completion->status == IAA_ANALYTICS_ERROR) {1043pr_warn("%s: falling back to deflate-generic decompress, "1044"analytics error code %x\n", __func__,1045idxd_desc->iax_completion->error_code);1046ret = deflate_generic_decompress(ctx->req);1047if (ret) {1048dev_dbg(dev, "%s: deflate-generic failed ret=%d\n",1049__func__, ret);1050err = -EIO;1051goto err;1052}1053} else {1054err = -EIO;1055goto err;1056}1057} else {1058ctx->req->dlen = idxd_desc->iax_completion->output_size;1059}10601061/* Update stats */1062if (ctx->compress) {1063update_total_comp_bytes_out(ctx->req->dlen);1064update_wq_comp_bytes(iaa_wq->wq, ctx->req->dlen);1065} else {1066update_total_decomp_bytes_in(ctx->req->slen);1067update_wq_decomp_bytes(iaa_wq->wq, ctx->req->slen);1068}10691070if (ctx->compress && compression_ctx->verify_compress) {1071u32 *compression_crc = acomp_request_ctx(ctx->req);1072dma_addr_t src_addr, dst_addr;10731074*compression_crc = idxd_desc->iax_completion->crc;10751076ret = iaa_remap_for_verify(dev, iaa_wq, ctx->req, &src_addr, &dst_addr);1077if (ret) {1078dev_dbg(dev, "%s: compress verify remap failed ret=%d\n", __func__, ret);1079err = -EIO;1080goto out;1081}10821083ret = iaa_compress_verify(ctx->tfm, ctx->req, iaa_wq->wq, src_addr,1084ctx->req->slen, dst_addr, &ctx->req->dlen);1085if (ret) {1086dev_dbg(dev, "%s: compress verify failed ret=%d\n", __func__, ret);1087err = -EIO;1088}10891090dma_unmap_sg(dev, ctx->req->dst, sg_nents(ctx->req->dst), DMA_TO_DEVICE);1091dma_unmap_sg(dev, ctx->req->src, sg_nents(ctx->req->src), DMA_FROM_DEVICE);10921093goto out;1094}1095err:1096dma_unmap_sg(dev, ctx->req->dst, sg_nents(ctx->req->dst), DMA_FROM_DEVICE);1097dma_unmap_sg(dev, ctx->req->src, sg_nents(ctx->req->src), DMA_TO_DEVICE);1098out:1099if (ret != 0)1100dev_dbg(dev, "asynchronous compress failed ret=%d\n", ret);11011102if (ctx->req->base.complete)1103acomp_request_complete(ctx->req, err);11041105if (free_desc)1106idxd_free_desc(idxd_desc->wq, idxd_desc);1107iaa_wq_put(idxd_desc->wq);1108}11091110static int iaa_compress(struct crypto_tfm *tfm, struct acomp_req *req,1111struct idxd_wq *wq,1112dma_addr_t src_addr, unsigned int slen,1113dma_addr_t dst_addr, unsigned int *dlen)1114{1115struct iaa_device_compression_mode *active_compression_mode;1116struct iaa_compression_ctx *ctx = crypto_tfm_ctx(tfm);1117u32 *compression_crc = acomp_request_ctx(req);1118struct iaa_device *iaa_device;1119struct idxd_desc *idxd_desc;1120struct iax_hw_desc *desc;1121struct idxd_device *idxd;1122struct iaa_wq *iaa_wq;1123struct pci_dev *pdev;1124struct device *dev;1125int ret = 0;11261127iaa_wq = idxd_wq_get_private(wq);1128iaa_device = iaa_wq->iaa_device;1129idxd = iaa_device->idxd;1130pdev = idxd->pdev;1131dev = &pdev->dev;11321133active_compression_mode = get_iaa_device_compression_mode(iaa_device, ctx->mode);11341135idxd_desc = idxd_alloc_desc(wq, IDXD_OP_BLOCK);1136if (IS_ERR(idxd_desc)) {1137dev_dbg(dev, "idxd descriptor allocation failed\n");1138dev_dbg(dev, "iaa compress failed: ret=%ld\n", PTR_ERR(idxd_desc));1139return PTR_ERR(idxd_desc);1140}1141desc = idxd_desc->iax_hw;11421143desc->flags = IDXD_OP_FLAG_CRAV | IDXD_OP_FLAG_RCR |1144IDXD_OP_FLAG_RD_SRC2_AECS | IDXD_OP_FLAG_CC;1145desc->opcode = IAX_OPCODE_COMPRESS;1146desc->compr_flags = IAA_COMP_FLAGS;1147desc->priv = 0;11481149desc->src1_addr = (u64)src_addr;1150desc->src1_size = slen;1151desc->dst_addr = (u64)dst_addr;1152desc->max_dst_size = *dlen;1153desc->src2_addr = active_compression_mode->aecs_comp_table_dma_addr;1154desc->src2_size = sizeof(struct aecs_comp_table_record);1155desc->completion_addr = idxd_desc->compl_dma;11561157if (ctx->use_irq) {1158desc->flags |= IDXD_OP_FLAG_RCI;11591160idxd_desc->crypto.req = req;1161idxd_desc->crypto.tfm = tfm;1162idxd_desc->crypto.src_addr = src_addr;1163idxd_desc->crypto.dst_addr = dst_addr;1164idxd_desc->crypto.compress = true;11651166dev_dbg(dev, "%s use_async_irq: compression mode %s,"1167" src_addr %llx, dst_addr %llx\n", __func__,1168active_compression_mode->name,1169src_addr, dst_addr);1170}11711172dev_dbg(dev, "%s: compression mode %s,"1173" desc->src1_addr %llx, desc->src1_size %d,"1174" desc->dst_addr %llx, desc->max_dst_size %d,"1175" desc->src2_addr %llx, desc->src2_size %d\n", __func__,1176active_compression_mode->name,1177desc->src1_addr, desc->src1_size, desc->dst_addr,1178desc->max_dst_size, desc->src2_addr, desc->src2_size);11791180ret = idxd_submit_desc(wq, idxd_desc);1181if (ret) {1182dev_dbg(dev, "submit_desc failed ret=%d\n", ret);1183goto err;1184}11851186/* Update stats */1187update_total_comp_calls();1188update_wq_comp_calls(wq);11891190if (ctx->async_mode) {1191ret = -EINPROGRESS;1192dev_dbg(dev, "%s: returning -EINPROGRESS\n", __func__);1193goto out;1194}11951196ret = check_completion(dev, idxd_desc->iax_completion, true, false);1197if (ret) {1198dev_dbg(dev, "check_completion failed ret=%d\n", ret);1199goto err;1200}12011202*dlen = idxd_desc->iax_completion->output_size;12031204/* Update stats */1205update_total_comp_bytes_out(*dlen);1206update_wq_comp_bytes(wq, *dlen);12071208*compression_crc = idxd_desc->iax_completion->crc;12091210if (!ctx->async_mode)1211idxd_free_desc(wq, idxd_desc);1212out:1213return ret;1214err:1215idxd_free_desc(wq, idxd_desc);1216dev_dbg(dev, "iaa compress failed: ret=%d\n", ret);12171218goto out;1219}12201221static int iaa_remap_for_verify(struct device *dev, struct iaa_wq *iaa_wq,1222struct acomp_req *req,1223dma_addr_t *src_addr, dma_addr_t *dst_addr)1224{1225int ret = 0;1226int nr_sgs;12271228dma_unmap_sg(dev, req->dst, sg_nents(req->dst), DMA_FROM_DEVICE);1229dma_unmap_sg(dev, req->src, sg_nents(req->src), DMA_TO_DEVICE);12301231nr_sgs = dma_map_sg(dev, req->src, sg_nents(req->src), DMA_FROM_DEVICE);1232if (nr_sgs <= 0 || nr_sgs > 1) {1233dev_dbg(dev, "verify: couldn't map src sg for iaa device %d,"1234" wq %d: ret=%d\n", iaa_wq->iaa_device->idxd->id,1235iaa_wq->wq->id, ret);1236ret = -EIO;1237goto out;1238}1239*src_addr = sg_dma_address(req->src);1240dev_dbg(dev, "verify: dma_map_sg, src_addr %llx, nr_sgs %d, req->src %p,"1241" req->slen %d, sg_dma_len(sg) %d\n", *src_addr, nr_sgs,1242req->src, req->slen, sg_dma_len(req->src));12431244nr_sgs = dma_map_sg(dev, req->dst, sg_nents(req->dst), DMA_TO_DEVICE);1245if (nr_sgs <= 0 || nr_sgs > 1) {1246dev_dbg(dev, "verify: couldn't map dst sg for iaa device %d,"1247" wq %d: ret=%d\n", iaa_wq->iaa_device->idxd->id,1248iaa_wq->wq->id, ret);1249ret = -EIO;1250dma_unmap_sg(dev, req->src, sg_nents(req->src), DMA_FROM_DEVICE);1251goto out;1252}1253*dst_addr = sg_dma_address(req->dst);1254dev_dbg(dev, "verify: dma_map_sg, dst_addr %llx, nr_sgs %d, req->dst %p,"1255" req->dlen %d, sg_dma_len(sg) %d\n", *dst_addr, nr_sgs,1256req->dst, req->dlen, sg_dma_len(req->dst));1257out:1258return ret;1259}12601261static int iaa_compress_verify(struct crypto_tfm *tfm, struct acomp_req *req,1262struct idxd_wq *wq,1263dma_addr_t src_addr, unsigned int slen,1264dma_addr_t dst_addr, unsigned int *dlen)1265{1266struct iaa_device_compression_mode *active_compression_mode;1267struct iaa_compression_ctx *ctx = crypto_tfm_ctx(tfm);1268u32 *compression_crc = acomp_request_ctx(req);1269struct iaa_device *iaa_device;1270struct idxd_desc *idxd_desc;1271struct iax_hw_desc *desc;1272struct idxd_device *idxd;1273struct iaa_wq *iaa_wq;1274struct pci_dev *pdev;1275struct device *dev;1276int ret = 0;12771278iaa_wq = idxd_wq_get_private(wq);1279iaa_device = iaa_wq->iaa_device;1280idxd = iaa_device->idxd;1281pdev = idxd->pdev;1282dev = &pdev->dev;12831284active_compression_mode = get_iaa_device_compression_mode(iaa_device, ctx->mode);12851286idxd_desc = idxd_alloc_desc(wq, IDXD_OP_BLOCK);1287if (IS_ERR(idxd_desc)) {1288dev_dbg(dev, "idxd descriptor allocation failed\n");1289dev_dbg(dev, "iaa compress failed: ret=%ld\n",1290PTR_ERR(idxd_desc));1291return PTR_ERR(idxd_desc);1292}1293desc = idxd_desc->iax_hw;12941295/* Verify (optional) - decompress and check crc, suppress dest write */12961297desc->flags = IDXD_OP_FLAG_CRAV | IDXD_OP_FLAG_RCR | IDXD_OP_FLAG_CC;1298desc->opcode = IAX_OPCODE_DECOMPRESS;1299desc->decompr_flags = IAA_DECOMP_FLAGS | IAA_DECOMP_SUPPRESS_OUTPUT;1300desc->priv = 0;13011302desc->src1_addr = (u64)dst_addr;1303desc->src1_size = *dlen;1304desc->dst_addr = (u64)src_addr;1305desc->max_dst_size = slen;1306desc->completion_addr = idxd_desc->compl_dma;13071308dev_dbg(dev, "(verify) compression mode %s,"1309" desc->src1_addr %llx, desc->src1_size %d,"1310" desc->dst_addr %llx, desc->max_dst_size %d,"1311" desc->src2_addr %llx, desc->src2_size %d\n",1312active_compression_mode->name,1313desc->src1_addr, desc->src1_size, desc->dst_addr,1314desc->max_dst_size, desc->src2_addr, desc->src2_size);13151316ret = idxd_submit_desc(wq, idxd_desc);1317if (ret) {1318dev_dbg(dev, "submit_desc (verify) failed ret=%d\n", ret);1319goto err;1320}13211322ret = check_completion(dev, idxd_desc->iax_completion, false, false);1323if (ret) {1324dev_dbg(dev, "(verify) check_completion failed ret=%d\n", ret);1325goto err;1326}13271328if (*compression_crc != idxd_desc->iax_completion->crc) {1329ret = -EINVAL;1330dev_dbg(dev, "(verify) iaa comp/decomp crc mismatch:"1331" comp=0x%x, decomp=0x%x\n", *compression_crc,1332idxd_desc->iax_completion->crc);1333print_hex_dump(KERN_INFO, "cmp-rec: ", DUMP_PREFIX_OFFSET,13348, 1, idxd_desc->iax_completion, 64, 0);1335goto err;1336}13371338idxd_free_desc(wq, idxd_desc);1339out:1340return ret;1341err:1342idxd_free_desc(wq, idxd_desc);1343dev_dbg(dev, "iaa compress failed: ret=%d\n", ret);13441345goto out;1346}13471348static int iaa_decompress(struct crypto_tfm *tfm, struct acomp_req *req,1349struct idxd_wq *wq,1350dma_addr_t src_addr, unsigned int slen,1351dma_addr_t dst_addr, unsigned int *dlen)1352{1353struct iaa_device_compression_mode *active_compression_mode;1354struct iaa_compression_ctx *ctx = crypto_tfm_ctx(tfm);1355struct iaa_device *iaa_device;1356struct idxd_desc *idxd_desc;1357struct iax_hw_desc *desc;1358struct idxd_device *idxd;1359struct iaa_wq *iaa_wq;1360struct pci_dev *pdev;1361struct device *dev;1362int ret = 0;13631364iaa_wq = idxd_wq_get_private(wq);1365iaa_device = iaa_wq->iaa_device;1366idxd = iaa_device->idxd;1367pdev = idxd->pdev;1368dev = &pdev->dev;13691370active_compression_mode = get_iaa_device_compression_mode(iaa_device, ctx->mode);13711372idxd_desc = idxd_alloc_desc(wq, IDXD_OP_BLOCK);1373if (IS_ERR(idxd_desc)) {1374dev_dbg(dev, "idxd descriptor allocation failed\n");1375dev_dbg(dev, "iaa decompress failed: ret=%ld\n",1376PTR_ERR(idxd_desc));1377return PTR_ERR(idxd_desc);1378}1379desc = idxd_desc->iax_hw;13801381desc->flags = IDXD_OP_FLAG_CRAV | IDXD_OP_FLAG_RCR | IDXD_OP_FLAG_CC;1382desc->opcode = IAX_OPCODE_DECOMPRESS;1383desc->max_dst_size = PAGE_SIZE;1384desc->decompr_flags = IAA_DECOMP_FLAGS;1385desc->priv = 0;13861387desc->src1_addr = (u64)src_addr;1388desc->dst_addr = (u64)dst_addr;1389desc->max_dst_size = *dlen;1390desc->src1_size = slen;1391desc->completion_addr = idxd_desc->compl_dma;13921393if (ctx->use_irq) {1394desc->flags |= IDXD_OP_FLAG_RCI;13951396idxd_desc->crypto.req = req;1397idxd_desc->crypto.tfm = tfm;1398idxd_desc->crypto.src_addr = src_addr;1399idxd_desc->crypto.dst_addr = dst_addr;1400idxd_desc->crypto.compress = false;14011402dev_dbg(dev, "%s: use_async_irq compression mode %s,"1403" src_addr %llx, dst_addr %llx\n", __func__,1404active_compression_mode->name,1405src_addr, dst_addr);1406}14071408dev_dbg(dev, "%s: decompression mode %s,"1409" desc->src1_addr %llx, desc->src1_size %d,"1410" desc->dst_addr %llx, desc->max_dst_size %d,"1411" desc->src2_addr %llx, desc->src2_size %d\n", __func__,1412active_compression_mode->name,1413desc->src1_addr, desc->src1_size, desc->dst_addr,1414desc->max_dst_size, desc->src2_addr, desc->src2_size);14151416ret = idxd_submit_desc(wq, idxd_desc);1417if (ret) {1418dev_dbg(dev, "submit_desc failed ret=%d\n", ret);1419goto err;1420}14211422/* Update stats */1423update_total_decomp_calls();1424update_wq_decomp_calls(wq);14251426if (ctx->async_mode) {1427ret = -EINPROGRESS;1428dev_dbg(dev, "%s: returning -EINPROGRESS\n", __func__);1429goto out;1430}14311432ret = check_completion(dev, idxd_desc->iax_completion, false, false);1433if (ret) {1434dev_dbg(dev, "%s: check_completion failed ret=%d\n", __func__, ret);1435if (idxd_desc->iax_completion->status == IAA_ANALYTICS_ERROR) {1436pr_warn("%s: falling back to deflate-generic decompress, "1437"analytics error code %x\n", __func__,1438idxd_desc->iax_completion->error_code);1439ret = deflate_generic_decompress(req);1440if (ret) {1441dev_dbg(dev, "%s: deflate-generic failed ret=%d\n",1442__func__, ret);1443goto err;1444}1445} else {1446goto err;1447}1448} else {1449req->dlen = idxd_desc->iax_completion->output_size;1450}14511452*dlen = req->dlen;14531454if (!ctx->async_mode)1455idxd_free_desc(wq, idxd_desc);14561457/* Update stats */1458update_total_decomp_bytes_in(slen);1459update_wq_decomp_bytes(wq, slen);1460out:1461return ret;1462err:1463idxd_free_desc(wq, idxd_desc);1464dev_dbg(dev, "iaa decompress failed: ret=%d\n", ret);14651466goto out;1467}14681469static int iaa_comp_acompress(struct acomp_req *req)1470{1471struct iaa_compression_ctx *compression_ctx;1472struct crypto_tfm *tfm = req->base.tfm;1473dma_addr_t src_addr, dst_addr;1474int nr_sgs, cpu, ret = 0;1475struct iaa_wq *iaa_wq;1476struct idxd_wq *wq;1477struct device *dev;14781479compression_ctx = crypto_tfm_ctx(tfm);14801481if (!iaa_crypto_enabled) {1482pr_debug("iaa_crypto disabled, not compressing\n");1483return -ENODEV;1484}14851486if (!req->src || !req->slen) {1487pr_debug("invalid src, not compressing\n");1488return -EINVAL;1489}14901491cpu = get_cpu();1492wq = wq_table_next_wq(cpu);1493put_cpu();1494if (!wq) {1495pr_debug("no wq configured for cpu=%d\n", cpu);1496return -ENODEV;1497}14981499ret = iaa_wq_get(wq);1500if (ret) {1501pr_debug("no wq available for cpu=%d\n", cpu);1502return -ENODEV;1503}15041505iaa_wq = idxd_wq_get_private(wq);15061507dev = &wq->idxd->pdev->dev;15081509nr_sgs = dma_map_sg(dev, req->src, sg_nents(req->src), DMA_TO_DEVICE);1510if (nr_sgs <= 0 || nr_sgs > 1) {1511dev_dbg(dev, "couldn't map src sg for iaa device %d,"1512" wq %d: ret=%d\n", iaa_wq->iaa_device->idxd->id,1513iaa_wq->wq->id, ret);1514ret = -EIO;1515goto out;1516}1517src_addr = sg_dma_address(req->src);1518dev_dbg(dev, "dma_map_sg, src_addr %llx, nr_sgs %d, req->src %p,"1519" req->slen %d, sg_dma_len(sg) %d\n", src_addr, nr_sgs,1520req->src, req->slen, sg_dma_len(req->src));15211522nr_sgs = dma_map_sg(dev, req->dst, sg_nents(req->dst), DMA_FROM_DEVICE);1523if (nr_sgs <= 0 || nr_sgs > 1) {1524dev_dbg(dev, "couldn't map dst sg for iaa device %d,"1525" wq %d: ret=%d\n", iaa_wq->iaa_device->idxd->id,1526iaa_wq->wq->id, ret);1527ret = -EIO;1528goto err_map_dst;1529}1530dst_addr = sg_dma_address(req->dst);1531dev_dbg(dev, "dma_map_sg, dst_addr %llx, nr_sgs %d, req->dst %p,"1532" req->dlen %d, sg_dma_len(sg) %d\n", dst_addr, nr_sgs,1533req->dst, req->dlen, sg_dma_len(req->dst));15341535ret = iaa_compress(tfm, req, wq, src_addr, req->slen, dst_addr,1536&req->dlen);1537if (ret == -EINPROGRESS)1538return ret;15391540if (!ret && compression_ctx->verify_compress) {1541ret = iaa_remap_for_verify(dev, iaa_wq, req, &src_addr, &dst_addr);1542if (ret) {1543dev_dbg(dev, "%s: compress verify remap failed ret=%d\n", __func__, ret);1544goto out;1545}15461547ret = iaa_compress_verify(tfm, req, wq, src_addr, req->slen,1548dst_addr, &req->dlen);1549if (ret)1550dev_dbg(dev, "asynchronous compress verification failed ret=%d\n", ret);15511552dma_unmap_sg(dev, req->dst, sg_nents(req->dst), DMA_TO_DEVICE);1553dma_unmap_sg(dev, req->src, sg_nents(req->src), DMA_FROM_DEVICE);15541555goto out;1556}15571558if (ret)1559dev_dbg(dev, "asynchronous compress failed ret=%d\n", ret);15601561dma_unmap_sg(dev, req->dst, sg_nents(req->dst), DMA_FROM_DEVICE);1562err_map_dst:1563dma_unmap_sg(dev, req->src, sg_nents(req->src), DMA_TO_DEVICE);1564out:1565iaa_wq_put(wq);15661567return ret;1568}15691570static int iaa_comp_adecompress(struct acomp_req *req)1571{1572struct crypto_tfm *tfm = req->base.tfm;1573dma_addr_t src_addr, dst_addr;1574int nr_sgs, cpu, ret = 0;1575struct iaa_wq *iaa_wq;1576struct device *dev;1577struct idxd_wq *wq;15781579if (!iaa_crypto_enabled) {1580pr_debug("iaa_crypto disabled, not decompressing\n");1581return -ENODEV;1582}15831584if (!req->src || !req->slen) {1585pr_debug("invalid src, not decompressing\n");1586return -EINVAL;1587}15881589cpu = get_cpu();1590wq = wq_table_next_wq(cpu);1591put_cpu();1592if (!wq) {1593pr_debug("no wq configured for cpu=%d\n", cpu);1594return -ENODEV;1595}15961597ret = iaa_wq_get(wq);1598if (ret) {1599pr_debug("no wq available for cpu=%d\n", cpu);1600return -ENODEV;1601}16021603iaa_wq = idxd_wq_get_private(wq);16041605dev = &wq->idxd->pdev->dev;16061607nr_sgs = dma_map_sg(dev, req->src, sg_nents(req->src), DMA_TO_DEVICE);1608if (nr_sgs <= 0 || nr_sgs > 1) {1609dev_dbg(dev, "couldn't map src sg for iaa device %d,"1610" wq %d: ret=%d\n", iaa_wq->iaa_device->idxd->id,1611iaa_wq->wq->id, ret);1612ret = -EIO;1613goto out;1614}1615src_addr = sg_dma_address(req->src);1616dev_dbg(dev, "dma_map_sg, src_addr %llx, nr_sgs %d, req->src %p,"1617" req->slen %d, sg_dma_len(sg) %d\n", src_addr, nr_sgs,1618req->src, req->slen, sg_dma_len(req->src));16191620nr_sgs = dma_map_sg(dev, req->dst, sg_nents(req->dst), DMA_FROM_DEVICE);1621if (nr_sgs <= 0 || nr_sgs > 1) {1622dev_dbg(dev, "couldn't map dst sg for iaa device %d,"1623" wq %d: ret=%d\n", iaa_wq->iaa_device->idxd->id,1624iaa_wq->wq->id, ret);1625ret = -EIO;1626goto err_map_dst;1627}1628dst_addr = sg_dma_address(req->dst);1629dev_dbg(dev, "dma_map_sg, dst_addr %llx, nr_sgs %d, req->dst %p,"1630" req->dlen %d, sg_dma_len(sg) %d\n", dst_addr, nr_sgs,1631req->dst, req->dlen, sg_dma_len(req->dst));16321633ret = iaa_decompress(tfm, req, wq, src_addr, req->slen,1634dst_addr, &req->dlen);1635if (ret == -EINPROGRESS)1636return ret;16371638if (ret != 0)1639dev_dbg(dev, "asynchronous decompress failed ret=%d\n", ret);16401641dma_unmap_sg(dev, req->dst, sg_nents(req->dst), DMA_FROM_DEVICE);1642err_map_dst:1643dma_unmap_sg(dev, req->src, sg_nents(req->src), DMA_TO_DEVICE);1644out:1645iaa_wq_put(wq);16461647return ret;1648}16491650static void compression_ctx_init(struct iaa_compression_ctx *ctx)1651{1652ctx->verify_compress = iaa_verify_compress;1653ctx->async_mode = async_mode;1654ctx->use_irq = use_irq;1655}16561657static int iaa_comp_init_fixed(struct crypto_acomp *acomp_tfm)1658{1659struct crypto_tfm *tfm = crypto_acomp_tfm(acomp_tfm);1660struct iaa_compression_ctx *ctx = crypto_tfm_ctx(tfm);16611662compression_ctx_init(ctx);16631664ctx->mode = IAA_MODE_FIXED;16651666return 0;1667}16681669static struct acomp_alg iaa_acomp_fixed_deflate = {1670.init = iaa_comp_init_fixed,1671.compress = iaa_comp_acompress,1672.decompress = iaa_comp_adecompress,1673.base = {1674.cra_name = "deflate",1675.cra_driver_name = "deflate-iaa",1676.cra_flags = CRYPTO_ALG_ASYNC,1677.cra_ctxsize = sizeof(struct iaa_compression_ctx),1678.cra_reqsize = sizeof(u32),1679.cra_module = THIS_MODULE,1680.cra_priority = IAA_ALG_PRIORITY,1681}1682};16831684static int iaa_register_compression_device(void)1685{1686int ret;16871688ret = crypto_register_acomp(&iaa_acomp_fixed_deflate);1689if (ret) {1690pr_err("deflate algorithm acomp fixed registration failed (%d)\n", ret);1691goto out;1692}16931694iaa_crypto_registered = true;1695out:1696return ret;1697}16981699static void iaa_unregister_compression_device(void)1700{1701if (iaa_crypto_registered)1702crypto_unregister_acomp(&iaa_acomp_fixed_deflate);1703}17041705static int iaa_crypto_probe(struct idxd_dev *idxd_dev)1706{1707struct idxd_wq *wq = idxd_dev_to_wq(idxd_dev);1708struct idxd_device *idxd = wq->idxd;1709struct idxd_driver_data *data = idxd->data;1710struct device *dev = &idxd_dev->conf_dev;1711bool first_wq = false;1712int ret = 0;17131714if (idxd->state != IDXD_DEV_ENABLED)1715return -ENXIO;17161717if (data->type != IDXD_TYPE_IAX)1718return -ENODEV;17191720mutex_lock(&wq->wq_lock);17211722if (idxd_wq_get_private(wq)) {1723mutex_unlock(&wq->wq_lock);1724return -EBUSY;1725}17261727if (!idxd_wq_driver_name_match(wq, dev)) {1728dev_dbg(dev, "wq %d.%d driver_name match failed: wq driver_name %s, dev driver name %s\n",1729idxd->id, wq->id, wq->driver_name, dev->driver->name);1730idxd->cmd_status = IDXD_SCMD_WQ_NO_DRV_NAME;1731ret = -ENODEV;1732goto err;1733}17341735wq->type = IDXD_WQT_KERNEL;17361737ret = idxd_drv_enable_wq(wq);1738if (ret < 0) {1739dev_dbg(dev, "enable wq %d.%d failed: %d\n",1740idxd->id, wq->id, ret);1741ret = -ENXIO;1742goto err;1743}17441745mutex_lock(&iaa_devices_lock);17461747if (list_empty(&iaa_devices)) {1748ret = alloc_wq_table(wq->idxd->max_wqs);1749if (ret)1750goto err_alloc;1751first_wq = true;1752}17531754ret = save_iaa_wq(wq);1755if (ret)1756goto err_save;17571758rebalance_wq_table();17591760if (first_wq) {1761iaa_crypto_enabled = true;1762ret = iaa_register_compression_device();1763if (ret != 0) {1764iaa_crypto_enabled = false;1765dev_dbg(dev, "IAA compression device registration failed\n");1766goto err_register;1767}1768try_module_get(THIS_MODULE);17691770pr_info("iaa_crypto now ENABLED\n");1771}17721773mutex_unlock(&iaa_devices_lock);1774out:1775mutex_unlock(&wq->wq_lock);17761777return ret;17781779err_register:1780remove_iaa_wq(wq);1781free_iaa_wq(idxd_wq_get_private(wq));1782err_save:1783if (first_wq)1784free_wq_table();1785err_alloc:1786mutex_unlock(&iaa_devices_lock);1787idxd_drv_disable_wq(wq);1788err:1789wq->type = IDXD_WQT_NONE;17901791goto out;1792}17931794static void iaa_crypto_remove(struct idxd_dev *idxd_dev)1795{1796struct idxd_wq *wq = idxd_dev_to_wq(idxd_dev);1797struct idxd_device *idxd = wq->idxd;1798struct iaa_wq *iaa_wq;1799bool free = false;18001801idxd_wq_quiesce(wq);18021803mutex_lock(&wq->wq_lock);1804mutex_lock(&iaa_devices_lock);18051806remove_iaa_wq(wq);18071808spin_lock(&idxd->dev_lock);1809iaa_wq = idxd_wq_get_private(wq);1810if (!iaa_wq) {1811spin_unlock(&idxd->dev_lock);1812pr_err("%s: no iaa_wq available to remove\n", __func__);1813goto out;1814}18151816if (iaa_wq->ref) {1817iaa_wq->remove = true;1818} else {1819wq = iaa_wq->wq;1820idxd_wq_set_private(wq, NULL);1821free = true;1822}1823spin_unlock(&idxd->dev_lock);1824if (free) {1825__free_iaa_wq(iaa_wq);1826kfree(iaa_wq);1827}18281829idxd_drv_disable_wq(wq);1830rebalance_wq_table();18311832if (nr_iaa == 0) {1833iaa_crypto_enabled = false;1834free_wq_table();1835module_put(THIS_MODULE);18361837pr_info("iaa_crypto now DISABLED\n");1838}1839out:1840mutex_unlock(&iaa_devices_lock);1841mutex_unlock(&wq->wq_lock);1842}18431844static enum idxd_dev_type dev_types[] = {1845IDXD_DEV_WQ,1846IDXD_DEV_NONE,1847};18481849static struct idxd_device_driver iaa_crypto_driver = {1850.probe = iaa_crypto_probe,1851.remove = iaa_crypto_remove,1852.name = IDXD_SUBDRIVER_NAME,1853.type = dev_types,1854.desc_complete = iaa_desc_complete,1855};18561857static int __init iaa_crypto_init_module(void)1858{1859int ret = 0;1860int node;18611862nr_cpus = num_possible_cpus();1863for_each_node_with_cpus(node)1864nr_nodes++;1865if (!nr_nodes) {1866pr_err("IAA couldn't find any nodes with cpus\n");1867return -ENODEV;1868}1869nr_cpus_per_node = nr_cpus / nr_nodes;18701871ret = iaa_aecs_init_fixed();1872if (ret < 0) {1873pr_debug("IAA fixed compression mode init failed\n");1874goto err_aecs_init;1875}18761877ret = idxd_driver_register(&iaa_crypto_driver);1878if (ret) {1879pr_debug("IAA wq sub-driver registration failed\n");1880goto err_driver_reg;1881}18821883ret = driver_create_file(&iaa_crypto_driver.drv,1884&driver_attr_verify_compress);1885if (ret) {1886pr_debug("IAA verify_compress attr creation failed\n");1887goto err_verify_attr_create;1888}18891890ret = driver_create_file(&iaa_crypto_driver.drv,1891&driver_attr_sync_mode);1892if (ret) {1893pr_debug("IAA sync mode attr creation failed\n");1894goto err_sync_attr_create;1895}18961897if (iaa_crypto_debugfs_init())1898pr_warn("debugfs init failed, stats not available\n");18991900pr_debug("initialized\n");1901out:1902return ret;19031904err_sync_attr_create:1905driver_remove_file(&iaa_crypto_driver.drv,1906&driver_attr_verify_compress);1907err_verify_attr_create:1908idxd_driver_unregister(&iaa_crypto_driver);1909err_driver_reg:1910iaa_aecs_cleanup_fixed();1911err_aecs_init:19121913goto out;1914}19151916static void __exit iaa_crypto_cleanup_module(void)1917{1918iaa_unregister_compression_device();19191920iaa_crypto_debugfs_cleanup();1921driver_remove_file(&iaa_crypto_driver.drv,1922&driver_attr_sync_mode);1923driver_remove_file(&iaa_crypto_driver.drv,1924&driver_attr_verify_compress);1925idxd_driver_unregister(&iaa_crypto_driver);1926iaa_aecs_cleanup_fixed();19271928pr_debug("cleaned up\n");1929}19301931MODULE_IMPORT_NS("IDXD");1932MODULE_LICENSE("GPL");1933MODULE_ALIAS_IDXD_DEVICE(0);1934MODULE_AUTHOR("Intel Corporation");1935MODULE_DESCRIPTION("IAA Compression Accelerator Crypto Driver");19361937module_init(iaa_crypto_init_module);1938module_exit(iaa_crypto_cleanup_module);193919401941