| /* |
| * Driver frontend for IBM Power 842 compression accelerator |
| * |
| * Copyright (C) 2015 Dan Streetman, IBM Corp |
| * |
| * Designer of the Power data compression engine: |
| * Bulent Abali <abali@us.ibm.com> |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| */ |
| |
| #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
| |
| #include "nx-842.h" |
| |
| #define MODULE_NAME "nx-compress" |
| MODULE_LICENSE("GPL"); |
| MODULE_AUTHOR("Dan Streetman <ddstreet@ieee.org>"); |
| MODULE_DESCRIPTION("842 H/W Compression driver for IBM Power processors"); |
| |
| /* Only one driver is expected, based on the HW platform */ |
| static struct nx842_driver *nx842_driver; |
| static DEFINE_SPINLOCK(nx842_driver_lock); /* protects driver pointers */ |
| |
| void nx842_register_driver(struct nx842_driver *driver) |
| { |
| spin_lock(&nx842_driver_lock); |
| |
| if (nx842_driver) { |
| pr_err("can't register driver %s, already using driver %s\n", |
| driver->owner->name, nx842_driver->owner->name); |
| } else { |
| pr_info("registering driver %s\n", driver->owner->name); |
| nx842_driver = driver; |
| } |
| |
| spin_unlock(&nx842_driver_lock); |
| } |
| EXPORT_SYMBOL_GPL(nx842_register_driver); |
| |
| void nx842_unregister_driver(struct nx842_driver *driver) |
| { |
| spin_lock(&nx842_driver_lock); |
| |
| if (nx842_driver == driver) { |
| pr_info("unregistering driver %s\n", driver->owner->name); |
| nx842_driver = NULL; |
| } else if (nx842_driver) { |
| pr_err("can't unregister driver %s, using driver %s\n", |
| driver->owner->name, nx842_driver->owner->name); |
| } else { |
| pr_err("can't unregister driver %s, no driver in use\n", |
| driver->owner->name); |
| } |
| |
| spin_unlock(&nx842_driver_lock); |
| } |
| EXPORT_SYMBOL_GPL(nx842_unregister_driver); |
| |
| static struct nx842_driver *get_driver(void) |
| { |
| struct nx842_driver *driver = NULL; |
| |
| spin_lock(&nx842_driver_lock); |
| |
| driver = nx842_driver; |
| |
| if (driver && !try_module_get(driver->owner)) |
| driver = NULL; |
| |
| spin_unlock(&nx842_driver_lock); |
| |
| return driver; |
| } |
| |
| static void put_driver(struct nx842_driver *driver) |
| { |
| module_put(driver->owner); |
| } |
| |
| int nx842_compress(const unsigned char *in, unsigned int in_len, |
| unsigned char *out, unsigned int *out_len, |
| void *wrkmem) |
| { |
| struct nx842_driver *driver = get_driver(); |
| int ret; |
| |
| if (!driver) |
| return -ENODEV; |
| |
| ret = driver->compress(in, in_len, out, out_len, wrkmem); |
| |
| put_driver(driver); |
| |
| return ret; |
| } |
| EXPORT_SYMBOL_GPL(nx842_compress); |
| |
| int nx842_decompress(const unsigned char *in, unsigned int in_len, |
| unsigned char *out, unsigned int *out_len, |
| void *wrkmem) |
| { |
| struct nx842_driver *driver = get_driver(); |
| int ret; |
| |
| if (!driver) |
| return -ENODEV; |
| |
| ret = driver->decompress(in, in_len, out, out_len, wrkmem); |
| |
| put_driver(driver); |
| |
| return ret; |
| } |
| EXPORT_SYMBOL_GPL(nx842_decompress); |
| |
| static __init int nx842_init(void) |
| { |
| pr_info("loading\n"); |
| |
| if (of_find_compatible_node(NULL, NULL, NX842_PSERIES_COMPAT_NAME)) |
| request_module_nowait(NX842_PSERIES_MODULE_NAME); |
| else |
| pr_err("no nx842 driver found.\n"); |
| |
| pr_info("loaded\n"); |
| |
| return 0; |
| } |
| module_init(nx842_init); |
| |
| static void __exit nx842_exit(void) |
| { |
| pr_info("NX842 unloaded\n"); |
| } |
| module_exit(nx842_exit); |