summaryrefslogtreecommitdiff
path: root/drivers/crypto/caam/jr.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/crypto/caam/jr.c')
-rw-r--r--drivers/crypto/caam/jr.c50
1 files changed, 41 insertions, 9 deletions
diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c
index 1d80bd3..0875f85 100644
--- a/drivers/crypto/caam/jr.c
+++ b/drivers/crypto/caam/jr.c
@@ -69,11 +69,17 @@ int caam_jr_shutdown(struct device *dev)
{
struct caam_drv_private_jr *jrp = dev_get_drvdata(dev);
dma_addr_t inpbusaddr, outbusaddr;
- int ret;
+ int i, ret;
ret = caam_reset_hw_jr(dev);
- tasklet_kill(&jrp->irqtask);
+ for_each_possible_cpu(i) {
+ napi_disable(per_cpu_ptr(jrp->irqtask, i));
+ netif_napi_del(per_cpu_ptr(jrp->irqtask, i));
+ }
+
+ free_percpu(jrp->irqtask);
+ free_percpu(jrp->net_dev);
/* Release interrupt */
free_irq(jrp->irq, dev);
@@ -153,23 +159,24 @@ static irqreturn_t caam_jr_interrupt(int irq, void *st_dev)
wr_reg32(&jrp->rregs->jrintstatus, irqstate);
preempt_disable();
- tasklet_schedule(&jrp->irqtask);
+ napi_schedule(per_cpu_ptr(jrp->irqtask, smp_processor_id()));
preempt_enable();
return IRQ_HANDLED;
}
/* Deferred service handler, run as interrupt-fired tasklet */
-static void caam_jr_dequeue(unsigned long devarg)
+static int caam_jr_dequeue(struct napi_struct *napi, int budget)
{
int hw_idx, sw_idx, i, head, tail;
- struct device *dev = (struct device *)devarg;
+ struct device *dev = &napi->dev->dev;
struct caam_drv_private_jr *jrp = dev_get_drvdata(dev);
void (*usercall)(struct device *dev, u32 *desc, u32 status, void *arg);
u32 *userdesc, userstatus;
void *userarg;
+ int cleaned = 0;
- while (rd_reg32(&jrp->rregs->outring_used)) {
+ while (rd_reg32(&jrp->rregs->outring_used) && cleaned < budget) {
head = ACCESS_ONCE(jrp->head);
@@ -229,10 +236,15 @@ static void caam_jr_dequeue(unsigned long devarg)
/* Finally, execute user's callback */
usercall(dev, userdesc, userstatus, userarg);
+ cleaned++;
+ }
+ if (cleaned < budget) {
+ napi_complete(per_cpu_ptr(jrp->irqtask, smp_processor_id()));
+ /* reenable / unmask IRQs */
+ clrbits32(&jrp->rregs->rconfig_lo, JRCFG_IMSK);
}
- /* reenable / unmask IRQs */
- clrbits32(&jrp->rregs->rconfig_lo, JRCFG_IMSK);
+ return cleaned;
}
/**
@@ -378,8 +390,28 @@ static int caam_jr_init(struct device *dev)
int i, error;
jrp = dev_get_drvdata(dev);
+ /* Connect job ring interrupt handler. */
+ jrp->irqtask = alloc_percpu(struct napi_struct);
+ if (!jrp->irqtask) {
+ dev_err(dev, "can't allocate percpu irqtask memory\n");
+ return -ENOMEM;
+ }
+
+ jrp->net_dev = alloc_percpu(struct net_device);
+ if (!jrp->net_dev) {
+ dev_err(dev, "can't allocate percpu net_dev memory\n");
+ free_percpu(jrp->irqtask);
+ return -ENOMEM;
+ }
- tasklet_init(&jrp->irqtask, caam_jr_dequeue, (unsigned long)dev);
+ for_each_possible_cpu(i) {
+ (per_cpu_ptr(jrp->net_dev, i))->dev = *dev;
+ INIT_LIST_HEAD(&per_cpu_ptr(jrp->net_dev, i)->napi_list);
+ netif_napi_add(per_cpu_ptr(jrp->net_dev, i),
+ per_cpu_ptr(jrp->irqtask, i),
+ caam_jr_dequeue, CAAM_NAPI_WEIGHT);
+ napi_enable(per_cpu_ptr(jrp->irqtask, i));
+ }
/* Connect job ring interrupt handler. */
error = request_irq(jrp->irq, caam_jr_interrupt, IRQF_SHARED,