aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers/misc/xilinx_sdfec.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/xilinx_sdfec.c')
-rw-r--r--drivers/misc/xilinx_sdfec.c61
1 files changed, 21 insertions, 40 deletions
diff --git a/drivers/misc/xilinx_sdfec.c b/drivers/misc/xilinx_sdfec.c
index 71bbaa56bdb5..92291292756a 100644
--- a/drivers/misc/xilinx_sdfec.c
+++ b/drivers/misc/xilinx_sdfec.c
@@ -602,10 +602,10 @@ static int xsdfec_table_write(struct xsdfec_dev *xsdfec, u32 offset,
const u32 depth)
{
u32 reg = 0;
- u32 res;
- u32 n, i;
+ int res, i, nr_pages;
+ u32 n;
u32 *addr = NULL;
- struct page *page[MAX_NUM_PAGES];
+ struct page *pages[MAX_NUM_PAGES];
/*
* Writes that go beyond the length of
@@ -622,15 +622,21 @@ static int xsdfec_table_write(struct xsdfec_dev *xsdfec, u32 offset,
if ((len * XSDFEC_REG_WIDTH_JUMP) % PAGE_SIZE)
n += 1;
- res = get_user_pages_fast((unsigned long)src_ptr, n, 0, page);
- if (res < n) {
- for (i = 0; i < res; i++)
- put_page(page[i]);
+ if (WARN_ON_ONCE(n > INT_MAX))
+ return -EINVAL;
+
+ nr_pages = n;
+
+ res = pin_user_pages_fast((unsigned long)src_ptr, nr_pages, 0, pages);
+ if (res < nr_pages) {
+ if (res > 0)
+ unpin_user_pages(pages, res);
+
return -EINVAL;
}
- for (i = 0; i < n; i++) {
- addr = kmap(page[i]);
+ for (i = 0; i < nr_pages; i++) {
+ addr = kmap(pages[i]);
do {
xsdfec_regwrite(xsdfec,
base_addr + ((offset + reg) *
@@ -639,9 +645,9 @@ static int xsdfec_table_write(struct xsdfec_dev *xsdfec, u32 offset,
reg++;
} while ((reg < len) &&
((reg * XSDFEC_REG_WIDTH_JUMP) % PAGE_SIZE));
- put_page(page[i]);
+ unpin_user_page(pages[i]);
}
- return reg;
+ return 0;
}
static int xsdfec_add_ldpc(struct xsdfec_dev *xsdfec, void __user *arg)
@@ -649,14 +655,9 @@ static int xsdfec_add_ldpc(struct xsdfec_dev *xsdfec, void __user *arg)
struct xsdfec_ldpc_params *ldpc;
int ret, n;
- ldpc = kzalloc(sizeof(*ldpc), GFP_KERNEL);
- if (!ldpc)
- return -ENOMEM;
-
- if (copy_from_user(ldpc, arg, sizeof(*ldpc))) {
- ret = -EFAULT;
- goto err_out;
- }
+ ldpc = memdup_user(arg, sizeof(*ldpc));
+ if (IS_ERR(ldpc))
+ return PTR_ERR(ldpc);
if (xsdfec->config.code == XSDFEC_TURBO_CODE) {
ret = -EIO;
@@ -720,8 +721,6 @@ static int xsdfec_add_ldpc(struct xsdfec_dev *xsdfec, void __user *arg)
ret = xsdfec_table_write(xsdfec, 4 * ldpc->qc_off, ldpc->qc_table,
ldpc->nqc, XSDFEC_LDPC_QC_TABLE_ADDR_BASE,
XSDFEC_QC_TABLE_DEPTH);
- if (ret > 0)
- ret = 0;
err_out:
kfree(ldpc);
return ret;
@@ -1484,25 +1483,7 @@ static struct platform_driver xsdfec_driver = {
.remove = xsdfec_remove,
};
-static int __init xsdfec_init(void)
-{
- int err;
-
- err = platform_driver_register(&xsdfec_driver);
- if (err < 0) {
- pr_err("%s Unabled to register SDFEC driver", __func__);
- return err;
- }
- return 0;
-}
-
-static void __exit xsdfec_exit(void)
-{
- platform_driver_unregister(&xsdfec_driver);
-}
-
-module_init(xsdfec_init);
-module_exit(xsdfec_exit);
+module_platform_driver(xsdfec_driver);
MODULE_AUTHOR("Xilinx, Inc");
MODULE_DESCRIPTION("Xilinx SD-FEC16 Driver");