RE: [PATCH v7 2/3] hw_random: cctrng: introduce Arm CryptoCell driver

From: Hadar Gat
Date: Tue Apr 21 2020 - 09:16:33 EST


Thank you Geert for reviewing the cctrng code.

> -----Original Message-----
> From: Geert Uytterhoeven <geert@xxxxxxxxxxxxxx>
> Sent: Monday, 20 April 2020 16:45
>
> Hi Hadar,
>
> On Fri, Mar 27, 2020 at 7:11 AM Hadar Gat <hadar.gat@xxxxxxx> wrote:
> > Introduce low level Arm CryptoCell TRNG HW support.
> >
> > Signed-off-by: Hadar Gat <hadar.gat@xxxxxxx>
>
> Thanks for your patch!
>
> > --- /dev/null
> > +++ b/drivers/char/hw_random/cctrng.c
>
> > +static int cctrng_probe(struct platform_device *pdev) {
> > + struct resource *req_mem_cc_regs = NULL;
> > + struct cctrng_drvdata *drvdata;
> > + struct device *dev = &pdev->dev;
> > + int rc = 0;
> > + u32 val;
> > + int irq;
> > +
> > + drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
> > + if (!drvdata)
> > + return -ENOMEM;
> > +
> > + drvdata->rng.name = devm_kstrdup(dev, dev_name(dev),
> GFP_KERNEL);
> > + if (!drvdata->rng.name)
> > + return -ENOMEM;
> > +
> > + drvdata->rng.read = cctrng_read;
> > + drvdata->rng.priv = (unsigned long)drvdata;
> > + drvdata->rng.quality = CC_TRNG_QUALITY;
> > +
> > + platform_set_drvdata(pdev, drvdata);
> > + drvdata->pdev = pdev;
> > +
> > + drvdata->circ.buf = (char *)drvdata->data_buf;
> > +
> > + /* Get device resources */
> > + /* First CC registers space */
> > + req_mem_cc_regs = platform_get_resource(pdev,
> IORESOURCE_MEM, 0);
> > + /* Map registers space */
> > + drvdata->cc_base = devm_ioremap_resource(dev,
> req_mem_cc_regs);
> > + if (IS_ERR(drvdata->cc_base)) {
> > + dev_err(dev, "Failed to ioremap registers");
> > + return PTR_ERR(drvdata->cc_base);
> > + }
> > +
> > + dev_dbg(dev, "Got MEM resource (%s): %pR\n", req_mem_cc_regs-
> >name,
> > + req_mem_cc_regs);
> > + dev_dbg(dev, "CC registers mapped from %pa to 0x%p\n",
> > + &req_mem_cc_regs->start, drvdata->cc_base);
> > +
> > + /* Then IRQ */
> > + irq = platform_get_irq(pdev, 0);
> > + if (irq < 0) {
> > + dev_err(dev, "Failed getting IRQ resource\n");
> > + return irq;
> > + }
> > +
> > + /* parse sampling rate from device tree */
> > + rc = cc_trng_parse_sampling_ratio(drvdata);
> > + if (rc) {
> > + dev_err(dev, "Failed to get legal sampling ratio for rosc\n");
> > + return rc;
> > + }
> > +
> > + rc = cc_trng_clk_init(drvdata);
> > + if (rc) {
> > + dev_err(dev, "cc_trng_clk_init failed\n");
> > + return rc;
> > + }
> > +
> > + INIT_WORK(&drvdata->compwork, cc_trng_compwork_handler);
> > + INIT_WORK(&drvdata->startwork, cc_trng_startwork_handler);
> > + spin_lock_init(&drvdata->read_lock);
> > +
> > + /* register the driver isr function */
> > + rc = devm_request_irq(dev, irq, cc_isr, IRQF_SHARED, "cctrng",
> > + drvdata);
>
> Shoudn't this be done after clearing the pending interrupts below?

I'm not sure what do you mean in your question...
I assume you're suggesting that the registration of the driver ISR function should be done only after clearing the pending interrupts?!
Anyway, any pending interrupt that might exist is irrelevant to the current cctrng driver which just started (we're in the probe function)

> > + if (rc) {
> > + dev_err(dev, "Could not register to interrupt %d\n", irq);
> > + goto post_clk_err;
> > + }
> > + dev_dbg(dev, "Registered to IRQ: %d\n", irq);
> > +
> > + /* Clear all pending interrupts */
> > + val = cc_ioread(drvdata, CC_HOST_RGF_IRR_REG_OFFSET);
> > + dev_dbg(dev, "IRR=0x%08X\n", val);
> > + cc_iowrite(drvdata, CC_HOST_RGF_ICR_REG_OFFSET, val);
>
> The above accesses the engine's registers...

That is right.

> > +
> > + /* unmask HOST RNG interrupt */
> > + cc_iowrite(drvdata, CC_HOST_RGF_IMR_REG_OFFSET,
> > + cc_ioread(drvdata, CC_HOST_RGF_IMR_REG_OFFSET) &
> > + ~CC_HOST_RNG_IRQ_MASK);
> > +
> > + /* init PM */
> > + rc = cc_trng_pm_init(drvdata);
> > + if (rc) {
> > + dev_err(dev, "cc_trng_pm_init failed\n");
> > + goto post_clk_err;
> > + }
>
> > +
> > + /* increment device's usage counter */
> > + rc = cc_trng_pm_get(dev);
>
> ... but only here is Runtime PM initialized, and the device guaranteed to be
> powered. If a device is accessed while powered down, this may lead to an
> asynchronous external abort, or a plain lockup.

It is assumed that when the driver is probed it is already powered. Only then, the driver initializes and enables the runtime PM to allow power down of the HW when it is not in use.

>
> Gr{oetje,eeting}s,
>
> Geert
>
> --
> Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-
> m68k.org
>
> In personal conversations with technical people, I call myself a hacker. But
> when I'm talking to journalists I just say "programmer" or something like that.
> -- Linus Torvalds