Commit 035f0cd3 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6

Pull crypto fixes from Herbert Xu:
 "This fixes the following issues:

   - memory corruption when kmalloc fails in xts/lrw

   - mark some CCP DMA channels as private

   - fix reordering race in padata

   - regression in omap-rng DT description"

* 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6:
  crypto: xts,lrw - fix out-of-bounds write after kmalloc failure
  crypto: ccp - Make some CCP DMA channels private
  padata: avoid race in reordering
  dt-bindings: rng: clocks property on omap_rng not always mandatory
parents 728f4b3a 9df0eb18
......@@ -12,7 +12,8 @@ Required properties:
- reg : Offset and length of the register set for the module
- interrupts : the interrupt number for the RNG module.
Used for "ti,omap4-rng" and "inside-secure,safexcel-eip76"
- clocks: the trng clock source
- clocks: the trng clock source. Only mandatory for the
"inside-secure,safexcel-eip76" compatible.
Example:
/* AM335x */
......
......@@ -286,8 +286,11 @@ static int init_crypt(struct skcipher_request *req, crypto_completion_t done)
subreq->cryptlen = LRW_BUFFER_SIZE;
if (req->cryptlen > LRW_BUFFER_SIZE) {
subreq->cryptlen = min(req->cryptlen, (unsigned)PAGE_SIZE);
rctx->ext = kmalloc(subreq->cryptlen, gfp);
unsigned int n = min(req->cryptlen, (unsigned int)PAGE_SIZE);
rctx->ext = kmalloc(n, gfp);
if (rctx->ext)
subreq->cryptlen = n;
}
rctx->src = req->src;
......
......@@ -230,8 +230,11 @@ static int init_crypt(struct skcipher_request *req, crypto_completion_t done)
subreq->cryptlen = XTS_BUFFER_SIZE;
if (req->cryptlen > XTS_BUFFER_SIZE) {
subreq->cryptlen = min(req->cryptlen, (unsigned)PAGE_SIZE);
rctx->ext = kmalloc(subreq->cryptlen, gfp);
unsigned int n = min(req->cryptlen, (unsigned int)PAGE_SIZE);
rctx->ext = kmalloc(n, gfp);
if (rctx->ext)
subreq->cryptlen = n;
}
rctx->src = req->src;
......
......@@ -1015,6 +1015,7 @@ const struct ccp_vdata ccpv5a = {
const struct ccp_vdata ccpv5b = {
.version = CCP_VERSION(5, 0),
.dma_chan_attr = DMA_PRIVATE,
.setup = ccp5other_config,
.perform = &ccp5_actions,
.bar = 2,
......
......@@ -179,6 +179,10 @@
/* ------------------------ General CCP Defines ------------------------ */
#define CCP_DMA_DFLT 0x0
#define CCP_DMA_PRIV 0x1
#define CCP_DMA_PUB 0x2
#define CCP_DMAPOOL_MAX_SIZE 64
#define CCP_DMAPOOL_ALIGN BIT(5)
......@@ -636,6 +640,7 @@ struct ccp_actions {
/* Structure to hold CCP version-specific values */
struct ccp_vdata {
const unsigned int version;
const unsigned int dma_chan_attr;
void (*setup)(struct ccp_device *);
const struct ccp_actions *perform;
const unsigned int bar;
......
......@@ -10,6 +10,7 @@
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/dmaengine.h>
#include <linux/spinlock.h>
......@@ -25,6 +26,37 @@
(mask == 0) ? 64 : fls64(mask); \
})
/* The CCP as a DMA provider can be configured for public or private
* channels. Default is specified in the vdata for the device (PCI ID).
* This module parameter will override for all channels on all devices:
* dma_chan_attr = 0x2 to force all channels public
* = 0x1 to force all channels private
* = 0x0 to defer to the vdata setting
* = any other value: warning, revert to 0x0
*/
static unsigned int dma_chan_attr = CCP_DMA_DFLT;
module_param(dma_chan_attr, uint, 0444);
MODULE_PARM_DESC(dma_chan_attr, "Set DMA channel visibility: 0 (default) = device defaults, 1 = make private, 2 = make public");
unsigned int ccp_get_dma_chan_attr(struct ccp_device *ccp)
{
switch (dma_chan_attr) {
case CCP_DMA_DFLT:
return ccp->vdata->dma_chan_attr;
case CCP_DMA_PRIV:
return DMA_PRIVATE;
case CCP_DMA_PUB:
return 0;
default:
dev_info_once(ccp->dev, "Invalid value for dma_chan_attr: %d\n",
dma_chan_attr);
return ccp->vdata->dma_chan_attr;
}
}
static void ccp_free_cmd_resources(struct ccp_device *ccp,
struct list_head *list)
{
......@@ -675,6 +707,15 @@ int ccp_dmaengine_register(struct ccp_device *ccp)
dma_cap_set(DMA_SG, dma_dev->cap_mask);
dma_cap_set(DMA_INTERRUPT, dma_dev->cap_mask);
/* The DMA channels for this device can be set to public or private,
* and overridden by the module parameter dma_chan_attr.
* Default: according to the value in vdata (dma_chan_attr=0)
* dma_chan_attr=0x1: all channels private (override vdata)
* dma_chan_attr=0x2: all channels public (override vdata)
*/
if (ccp_get_dma_chan_attr(ccp) == DMA_PRIVATE)
dma_cap_set(DMA_PRIVATE, dma_dev->cap_mask);
INIT_LIST_HEAD(&dma_dev->channels);
for (i = 0; i < ccp->cmd_q_count; i++) {
chan = ccp->ccp_dma_chan + i;
......
......@@ -186,19 +186,20 @@ static struct padata_priv *padata_get_next(struct parallel_data *pd)
reorder = &next_queue->reorder;
spin_lock(&reorder->lock);
if (!list_empty(&reorder->list)) {
padata = list_entry(reorder->list.next,
struct padata_priv, list);
spin_lock(&reorder->lock);
list_del_init(&padata->list);
atomic_dec(&pd->reorder_objects);
spin_unlock(&reorder->lock);
pd->processed++;
spin_unlock(&reorder->lock);
goto out;
}
spin_unlock(&reorder->lock);
if (__this_cpu_read(pd->pqueue->cpu_index) == next_queue->cpu_index) {
padata = ERR_PTR(-ENODATA);
......
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