Commit 9166c443 authored by raveendra padasalagi's avatar raveendra padasalagi Committed by Herbert Xu

crypto: brcm - Support more FlexRM rings than SPU engines.

Enhance code to generically support cases where DMA rings
are greater than or equal to number of SPU engines.
New hardware has underlying DMA engine-FlexRM with 32 rings
which can be used to communicate to any of the available
10 SPU engines.
Signed-off-by: default avatarRaveendra Padasalagi <raveendra.padasalagi@broadcom.com>
Reviewed-by: default avatarScott Branden <scott.branden@broadcom.com>
Reviewed-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 6d2bce6a
...@@ -90,8 +90,6 @@ static int aead_pri = 150; ...@@ -90,8 +90,6 @@ static int aead_pri = 150;
module_param(aead_pri, int, 0644); module_param(aead_pri, int, 0644);
MODULE_PARM_DESC(aead_pri, "Priority for AEAD algos"); MODULE_PARM_DESC(aead_pri, "Priority for AEAD algos");
#define MAX_SPUS 16
/* A type 3 BCM header, expected to precede the SPU header for SPU-M. /* A type 3 BCM header, expected to precede the SPU header for SPU-M.
* Bits 3 and 4 in the first byte encode the channel number (the dma ringset). * Bits 3 and 4 in the first byte encode the channel number (the dma ringset).
* 0x60 - ring 0 * 0x60 - ring 0
...@@ -120,7 +118,7 @@ static u8 select_channel(void) ...@@ -120,7 +118,7 @@ static u8 select_channel(void)
{ {
u8 chan_idx = atomic_inc_return(&iproc_priv.next_chan); u8 chan_idx = atomic_inc_return(&iproc_priv.next_chan);
return chan_idx % iproc_priv.spu.num_spu; return chan_idx % iproc_priv.spu.num_chan;
} }
/** /**
...@@ -4528,8 +4526,13 @@ static void spu_functions_register(struct device *dev, ...@@ -4528,8 +4526,13 @@ static void spu_functions_register(struct device *dev,
*/ */
static int spu_mb_init(struct device *dev) static int spu_mb_init(struct device *dev)
{ {
struct mbox_client *mcl = &iproc_priv.mcl[iproc_priv.spu.num_spu]; struct mbox_client *mcl = &iproc_priv.mcl;
int err; int err, i;
iproc_priv.mbox = devm_kcalloc(dev, iproc_priv.spu.num_chan,
sizeof(struct mbox_chan *), GFP_KERNEL);
if (!iproc_priv.mbox)
return -ENOMEM;
mcl->dev = dev; mcl->dev = dev;
mcl->tx_block = false; mcl->tx_block = false;
...@@ -4538,25 +4541,33 @@ static int spu_mb_init(struct device *dev) ...@@ -4538,25 +4541,33 @@ static int spu_mb_init(struct device *dev)
mcl->rx_callback = spu_rx_callback; mcl->rx_callback = spu_rx_callback;
mcl->tx_done = NULL; mcl->tx_done = NULL;
iproc_priv.mbox[iproc_priv.spu.num_spu] = for (i = 0; i < iproc_priv.spu.num_chan; i++) {
mbox_request_channel(mcl, 0); iproc_priv.mbox[i] = mbox_request_channel(mcl, i);
if (IS_ERR(iproc_priv.mbox[iproc_priv.spu.num_spu])) { if (IS_ERR(iproc_priv.mbox[i])) {
err = (int)PTR_ERR(iproc_priv.mbox[iproc_priv.spu.num_spu]); err = (int)PTR_ERR(iproc_priv.mbox[i]);
dev_err(dev, dev_err(dev,
"Mbox channel %d request failed with err %d", "Mbox channel %d request failed with err %d",
iproc_priv.spu.num_spu, err); i, err);
iproc_priv.mbox[iproc_priv.spu.num_spu] = NULL; iproc_priv.mbox[i] = NULL;
return err; goto free_channels;
}
} }
return 0; return 0;
free_channels:
for (i = 0; i < iproc_priv.spu.num_chan; i++) {
if (iproc_priv.mbox[i])
mbox_free_channel(iproc_priv.mbox[i]);
}
return err;
} }
static void spu_mb_release(struct platform_device *pdev) static void spu_mb_release(struct platform_device *pdev)
{ {
int i; int i;
for (i = 0; i < iproc_priv.spu.num_spu; i++) for (i = 0; i < iproc_priv.spu.num_chan; i++)
mbox_free_channel(iproc_priv.mbox[i]); mbox_free_channel(iproc_priv.mbox[i]);
} }
...@@ -4567,7 +4578,7 @@ static void spu_counters_init(void) ...@@ -4567,7 +4578,7 @@ static void spu_counters_init(void)
atomic_set(&iproc_priv.session_count, 0); atomic_set(&iproc_priv.session_count, 0);
atomic_set(&iproc_priv.stream_count, 0); atomic_set(&iproc_priv.stream_count, 0);
atomic_set(&iproc_priv.next_chan, (int)iproc_priv.spu.num_spu); atomic_set(&iproc_priv.next_chan, (int)iproc_priv.spu.num_chan);
atomic64_set(&iproc_priv.bytes_in, 0); atomic64_set(&iproc_priv.bytes_in, 0);
atomic64_set(&iproc_priv.bytes_out, 0); atomic64_set(&iproc_priv.bytes_out, 0);
for (i = 0; i < SPU_OP_NUM; i++) { for (i = 0; i < SPU_OP_NUM; i++) {
...@@ -4809,8 +4820,11 @@ static int spu_dt_read(struct platform_device *pdev) ...@@ -4809,8 +4820,11 @@ static int spu_dt_read(struct platform_device *pdev)
struct resource *spu_ctrl_regs; struct resource *spu_ctrl_regs;
const struct of_device_id *match; const struct of_device_id *match;
const struct spu_type_subtype *matched_spu_type; const struct spu_type_subtype *matched_spu_type;
void __iomem *spu_reg_vbase[MAX_SPUS]; struct device_node *dn = pdev->dev.of_node;
int err; int err, i;
/* Count number of mailbox channels */
spu->num_chan = of_count_phandle_with_args(dn, "mboxes", "#mbox-cells");
match = of_match_device(of_match_ptr(bcm_spu_dt_ids), dev); match = of_match_device(of_match_ptr(bcm_spu_dt_ids), dev);
if (!match) { if (!match) {
...@@ -4820,41 +4834,24 @@ static int spu_dt_read(struct platform_device *pdev) ...@@ -4820,41 +4834,24 @@ static int spu_dt_read(struct platform_device *pdev)
matched_spu_type = match->data; matched_spu_type = match->data;
if (iproc_priv.spu.num_spu > 1) {
/* If this is 2nd or later SPU, make sure it's same type */
if ((spu->spu_type != matched_spu_type->type) ||
(spu->spu_subtype != matched_spu_type->subtype)) {
err = -EINVAL;
dev_err(&pdev->dev, "Multiple SPU types not allowed");
return err;
}
} else {
/* Record type of first SPU */
spu->spu_type = matched_spu_type->type; spu->spu_type = matched_spu_type->type;
spu->spu_subtype = matched_spu_type->subtype; spu->spu_subtype = matched_spu_type->subtype;
}
/* Get and map SPU registers */ i = 0;
spu_ctrl_regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); for (i = 0; (i < MAX_SPUS) && ((spu_ctrl_regs =
if (!spu_ctrl_regs) { platform_get_resource(pdev, IORESOURCE_MEM, i)) != NULL); i++) {
err = -EINVAL;
dev_err(&pdev->dev, "Invalid/missing registers for SPU\n");
return err;
}
spu_reg_vbase[iproc_priv.spu.num_spu] = spu->reg_vbase[i] = devm_ioremap_resource(dev, spu_ctrl_regs);
devm_ioremap_resource(dev, spu_ctrl_regs); if (IS_ERR(spu->reg_vbase[i])) {
if (IS_ERR(spu_reg_vbase[iproc_priv.spu.num_spu])) { err = PTR_ERR(spu->reg_vbase[i]);
err = PTR_ERR(spu_reg_vbase[iproc_priv.spu.num_spu]);
dev_err(&pdev->dev, "Failed to map registers: %d\n", dev_err(&pdev->dev, "Failed to map registers: %d\n",
err); err);
spu_reg_vbase[iproc_priv.spu.num_spu] = NULL; spu->reg_vbase[i] = NULL;
return err; return err;
} }
}
dev_dbg(dev, "SPU %d detected.", iproc_priv.spu.num_spu); spu->num_spu = i;
dev_dbg(dev, "Device has %d SPUs", spu->num_spu);
spu->reg_vbase[iproc_priv.spu.num_spu] = spu_reg_vbase;
return 0; return 0;
} }
...@@ -4865,8 +4862,8 @@ int bcm_spu_probe(struct platform_device *pdev) ...@@ -4865,8 +4862,8 @@ int bcm_spu_probe(struct platform_device *pdev)
struct spu_hw *spu = &iproc_priv.spu; struct spu_hw *spu = &iproc_priv.spu;
int err = 0; int err = 0;
iproc_priv.pdev[iproc_priv.spu.num_spu] = pdev; iproc_priv.pdev = pdev;
platform_set_drvdata(iproc_priv.pdev[iproc_priv.spu.num_spu], platform_set_drvdata(iproc_priv.pdev,
&iproc_priv); &iproc_priv);
err = spu_dt_read(pdev); err = spu_dt_read(pdev);
...@@ -4877,12 +4874,6 @@ int bcm_spu_probe(struct platform_device *pdev) ...@@ -4877,12 +4874,6 @@ int bcm_spu_probe(struct platform_device *pdev)
if (err < 0) if (err < 0)
goto failure; goto failure;
iproc_priv.spu.num_spu++;
/* If already initialized, we've just added another SPU and are done */
if (iproc_priv.inited)
return 0;
if (spu->spu_type == SPU_TYPE_SPUM) if (spu->spu_type == SPU_TYPE_SPUM)
iproc_priv.bcm_hdr_len = 8; iproc_priv.bcm_hdr_len = 8;
else if (spu->spu_type == SPU_TYPE_SPU2) else if (spu->spu_type == SPU_TYPE_SPU2)
...@@ -4898,8 +4889,6 @@ int bcm_spu_probe(struct platform_device *pdev) ...@@ -4898,8 +4889,6 @@ int bcm_spu_probe(struct platform_device *pdev)
if (err < 0) if (err < 0)
goto fail_reg; goto fail_reg;
iproc_priv.inited = true;
return 0; return 0;
fail_reg: fail_reg:
......
...@@ -427,10 +427,13 @@ struct spu_hw { ...@@ -427,10 +427,13 @@ struct spu_hw {
/* The number of SPUs on this platform */ /* The number of SPUs on this platform */
u32 num_spu; u32 num_spu;
/* The number of SPU channels on this platform */
u32 num_chan;
}; };
struct device_private { struct device_private {
struct platform_device *pdev[MAX_SPUS]; struct platform_device *pdev;
struct spu_hw spu; struct spu_hw spu;
...@@ -470,12 +473,10 @@ struct device_private { ...@@ -470,12 +473,10 @@ struct device_private {
/* Number of ICV check failures for AEAD messages */ /* Number of ICV check failures for AEAD messages */
atomic_t bad_icv; atomic_t bad_icv;
struct mbox_client mcl[MAX_SPUS]; struct mbox_client mcl;
/* Array of mailbox channel pointers, one for each channel */
struct mbox_chan *mbox[MAX_SPUS];
/* Driver initialized */ /* Array of mailbox channel pointers, one for each channel */
bool inited; struct mbox_chan **mbox;
}; };
extern struct device_private iproc_priv; extern struct device_private iproc_priv;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment