2016-02-15 16:50:24 +03:00
/*
* Hisilicon ' s Hi6220 mailbox driver
*
* Copyright ( c ) 2015 Hisilicon Limited .
* Copyright ( c ) 2015 Linaro Limited .
*
* Author : Leo Yan < leo . yan @ linaro . org >
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , version 2 of the License .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
*/
# include <linux/device.h>
# include <linux/err.h>
# include <linux/interrupt.h>
# include <linux/io.h>
# include <linux/kfifo.h>
# include <linux/mailbox_controller.h>
# include <linux/module.h>
# include <linux/platform_device.h>
# include <linux/slab.h>
# define MBOX_CHAN_MAX 32
# define MBOX_TX 0x1
/* Mailbox message length: 8 words */
# define MBOX_MSG_LEN 8
/* Mailbox Registers */
# define MBOX_OFF(m) (0x40 * (m))
# define MBOX_MODE_REG(m) (MBOX_OFF(m) + 0x0)
# define MBOX_DATA_REG(m) (MBOX_OFF(m) + 0x4)
# define MBOX_STATE_MASK (0xF << 4)
# define MBOX_STATE_IDLE (0x1 << 4)
# define MBOX_STATE_TX (0x2 << 4)
# define MBOX_STATE_RX (0x4 << 4)
# define MBOX_STATE_ACK (0x8 << 4)
# define MBOX_ACK_CONFIG_MASK (0x1 << 0)
# define MBOX_ACK_AUTOMATIC (0x1 << 0)
# define MBOX_ACK_IRQ (0x0 << 0)
/* IPC registers */
# define ACK_INT_RAW_REG(i) ((i) + 0x400)
# define ACK_INT_MSK_REG(i) ((i) + 0x404)
# define ACK_INT_STAT_REG(i) ((i) + 0x408)
# define ACK_INT_CLR_REG(i) ((i) + 0x40c)
# define ACK_INT_ENA_REG(i) ((i) + 0x500)
# define ACK_INT_DIS_REG(i) ((i) + 0x504)
# define DST_INT_RAW_REG(i) ((i) + 0x420)
struct hi6220_mbox_chan {
/*
* Description for channel ' s hardware info :
* - direction : tx or rx
* - dst irq : peer core ' s irq number
* - ack irq : local irq number
* - slot number
*/
unsigned int dir , dst_irq , ack_irq ;
unsigned int slot ;
struct hi6220_mbox * parent ;
} ;
struct hi6220_mbox {
struct device * dev ;
int irq ;
/* flag of enabling tx's irq mode */
bool tx_irq_mode ;
/* region for ipc event */
void __iomem * ipc ;
/* region for mailbox */
void __iomem * base ;
unsigned int chan_num ;
struct hi6220_mbox_chan * mchan ;
void * irq_map_chan [ MBOX_CHAN_MAX ] ;
struct mbox_chan * chan ;
struct mbox_controller controller ;
} ;
static void mbox_set_state ( struct hi6220_mbox * mbox ,
unsigned int slot , u32 val )
{
u32 status ;
status = readl ( mbox - > base + MBOX_MODE_REG ( slot ) ) ;
status = ( status & ~ MBOX_STATE_MASK ) | val ;
writel ( status , mbox - > base + MBOX_MODE_REG ( slot ) ) ;
}
static void mbox_set_mode ( struct hi6220_mbox * mbox ,
unsigned int slot , u32 val )
{
u32 mode ;
mode = readl ( mbox - > base + MBOX_MODE_REG ( slot ) ) ;
mode = ( mode & ~ MBOX_ACK_CONFIG_MASK ) | val ;
writel ( mode , mbox - > base + MBOX_MODE_REG ( slot ) ) ;
}
static bool hi6220_mbox_last_tx_done ( struct mbox_chan * chan )
{
struct hi6220_mbox_chan * mchan = chan - > con_priv ;
struct hi6220_mbox * mbox = mchan - > parent ;
u32 state ;
/* Only set idle state for polling mode */
BUG_ON ( mbox - > tx_irq_mode ) ;
state = readl ( mbox - > base + MBOX_MODE_REG ( mchan - > slot ) ) ;
return ( ( state & MBOX_STATE_MASK ) = = MBOX_STATE_IDLE ) ;
}
static int hi6220_mbox_send_data ( struct mbox_chan * chan , void * msg )
{
struct hi6220_mbox_chan * mchan = chan - > con_priv ;
struct hi6220_mbox * mbox = mchan - > parent ;
unsigned int slot = mchan - > slot ;
u32 * buf = msg ;
int i ;
/* indicate as a TX channel */
mchan - > dir = MBOX_TX ;
mbox_set_state ( mbox , slot , MBOX_STATE_TX ) ;
if ( mbox - > tx_irq_mode )
mbox_set_mode ( mbox , slot , MBOX_ACK_IRQ ) ;
else
mbox_set_mode ( mbox , slot , MBOX_ACK_AUTOMATIC ) ;
for ( i = 0 ; i < MBOX_MSG_LEN ; i + + )
writel ( buf [ i ] , mbox - > base + MBOX_DATA_REG ( slot ) + i * 4 ) ;
/* trigger remote request */
writel ( BIT ( mchan - > dst_irq ) , DST_INT_RAW_REG ( mbox - > ipc ) ) ;
return 0 ;
}
static irqreturn_t hi6220_mbox_interrupt ( int irq , void * p )
{
struct hi6220_mbox * mbox = p ;
struct hi6220_mbox_chan * mchan ;
struct mbox_chan * chan ;
unsigned int state , intr_bit , i ;
u32 msg [ MBOX_MSG_LEN ] ;
state = readl ( ACK_INT_STAT_REG ( mbox - > ipc ) ) ;
if ( ! state ) {
dev_warn ( mbox - > dev , " %s: spurious interrupt \n " ,
__func__ ) ;
return IRQ_HANDLED ;
}
while ( state ) {
intr_bit = __ffs ( state ) ;
state & = ( state - 1 ) ;
chan = mbox - > irq_map_chan [ intr_bit ] ;
if ( ! chan ) {
dev_warn ( mbox - > dev , " %s: unexpected irq vector %d \n " ,
__func__ , intr_bit ) ;
continue ;
}
mchan = chan - > con_priv ;
if ( mchan - > dir = = MBOX_TX )
mbox_chan_txdone ( chan , 0 ) ;
else {
for ( i = 0 ; i < MBOX_MSG_LEN ; i + + )
msg [ i ] = readl ( mbox - > base +
MBOX_DATA_REG ( mchan - > slot ) + i * 4 ) ;
mbox_chan_received_data ( chan , ( void * ) msg ) ;
}
/* clear IRQ source */
writel ( BIT ( mchan - > ack_irq ) , ACK_INT_CLR_REG ( mbox - > ipc ) ) ;
mbox_set_state ( mbox , mchan - > slot , MBOX_STATE_IDLE ) ;
}
return IRQ_HANDLED ;
}
static int hi6220_mbox_startup ( struct mbox_chan * chan )
{
struct hi6220_mbox_chan * mchan = chan - > con_priv ;
struct hi6220_mbox * mbox = mchan - > parent ;
mchan - > dir = 0 ;
/* enable interrupt */
writel ( BIT ( mchan - > ack_irq ) , ACK_INT_ENA_REG ( mbox - > ipc ) ) ;
return 0 ;
}
static void hi6220_mbox_shutdown ( struct mbox_chan * chan )
{
struct hi6220_mbox_chan * mchan = chan - > con_priv ;
struct hi6220_mbox * mbox = mchan - > parent ;
/* disable interrupt */
writel ( BIT ( mchan - > ack_irq ) , ACK_INT_DIS_REG ( mbox - > ipc ) ) ;
mbox - > irq_map_chan [ mchan - > ack_irq ] = NULL ;
}
2017-01-05 10:30:43 +03:00
static const struct mbox_chan_ops hi6220_mbox_ops = {
2016-02-15 16:50:24 +03:00
. send_data = hi6220_mbox_send_data ,
. startup = hi6220_mbox_startup ,
. shutdown = hi6220_mbox_shutdown ,
. last_tx_done = hi6220_mbox_last_tx_done ,
} ;
static struct mbox_chan * hi6220_mbox_xlate ( struct mbox_controller * controller ,
const struct of_phandle_args * spec )
{
struct hi6220_mbox * mbox = dev_get_drvdata ( controller - > dev ) ;
struct hi6220_mbox_chan * mchan ;
struct mbox_chan * chan ;
unsigned int i = spec - > args [ 0 ] ;
unsigned int dst_irq = spec - > args [ 1 ] ;
unsigned int ack_irq = spec - > args [ 2 ] ;
/* Bounds checking */
if ( i > = mbox - > chan_num | | dst_irq > = mbox - > chan_num | |
ack_irq > = mbox - > chan_num ) {
dev_err ( mbox - > dev ,
" Invalid channel idx %d dst_irq %d ack_irq %d \n " ,
i , dst_irq , ack_irq ) ;
return ERR_PTR ( - EINVAL ) ;
}
/* Is requested channel free? */
chan = & mbox - > chan [ i ] ;
if ( mbox - > irq_map_chan [ ack_irq ] = = ( void * ) chan ) {
dev_err ( mbox - > dev , " Channel in use \n " ) ;
return ERR_PTR ( - EBUSY ) ;
}
mchan = chan - > con_priv ;
mchan - > dst_irq = dst_irq ;
mchan - > ack_irq = ack_irq ;
mbox - > irq_map_chan [ ack_irq ] = ( void * ) chan ;
return chan ;
}
static const struct of_device_id hi6220_mbox_of_match [ ] = {
{ . compatible = " hisilicon,hi6220-mbox " , } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , hi6220_mbox_of_match ) ;
static int hi6220_mbox_probe ( struct platform_device * pdev )
{
struct device_node * node = pdev - > dev . of_node ;
struct device * dev = & pdev - > dev ;
struct hi6220_mbox * mbox ;
struct resource * res ;
int i , err ;
mbox = devm_kzalloc ( dev , sizeof ( * mbox ) , GFP_KERNEL ) ;
if ( ! mbox )
return - ENOMEM ;
mbox - > dev = dev ;
mbox - > chan_num = MBOX_CHAN_MAX ;
treewide: devm_kzalloc() -> devm_kcalloc()
The devm_kzalloc() function has a 2-factor argument form, devm_kcalloc().
This patch replaces cases of:
devm_kzalloc(handle, a * b, gfp)
with:
devm_kcalloc(handle, a * b, gfp)
as well as handling cases of:
devm_kzalloc(handle, a * b * c, gfp)
with:
devm_kzalloc(handle, array3_size(a, b, c), gfp)
as it's slightly less ugly than:
devm_kcalloc(handle, array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
devm_kzalloc(handle, 4 * 1024, gfp)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
Some manual whitespace fixes were needed in this patch, as Coccinelle
really liked to write "=devm_kcalloc..." instead of "= devm_kcalloc...".
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
expression HANDLE;
type TYPE;
expression THING, E;
@@
(
devm_kzalloc(HANDLE,
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
devm_kzalloc(HANDLE,
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression HANDLE;
expression COUNT;
typedef u8;
typedef __u8;
@@
(
devm_kzalloc(HANDLE,
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(char) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
expression HANDLE;
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
expression HANDLE;
identifier SIZE, COUNT;
@@
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- SIZE * COUNT
+ COUNT, SIZE
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression HANDLE;
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
devm_kzalloc(HANDLE,
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression HANDLE;
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
expression HANDLE;
identifier STRIDE, SIZE, COUNT;
@@
(
devm_kzalloc(HANDLE,
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products,
// when they're not all constants...
@@
expression HANDLE;
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
devm_kzalloc(HANDLE, C1 * C2 * C3, ...)
|
devm_kzalloc(HANDLE,
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants,
// keeping sizeof() as the second factor argument.
@@
expression HANDLE;
expression THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@
(
devm_kzalloc(HANDLE, sizeof(THING) * C2, ...)
|
devm_kzalloc(HANDLE, sizeof(TYPE) * C2, ...)
|
devm_kzalloc(HANDLE, C1 * C2 * C3, ...)
|
devm_kzalloc(HANDLE, C1 * C2, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- (E1) * E2
+ E1, E2
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- (E1) * (E2)
+ E1, E2
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-13 00:07:58 +03:00
mbox - > mchan = devm_kcalloc ( dev ,
mbox - > chan_num , sizeof ( * mbox - > mchan ) , GFP_KERNEL ) ;
2016-02-15 16:50:24 +03:00
if ( ! mbox - > mchan )
return - ENOMEM ;
treewide: devm_kzalloc() -> devm_kcalloc()
The devm_kzalloc() function has a 2-factor argument form, devm_kcalloc().
This patch replaces cases of:
devm_kzalloc(handle, a * b, gfp)
with:
devm_kcalloc(handle, a * b, gfp)
as well as handling cases of:
devm_kzalloc(handle, a * b * c, gfp)
with:
devm_kzalloc(handle, array3_size(a, b, c), gfp)
as it's slightly less ugly than:
devm_kcalloc(handle, array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
devm_kzalloc(handle, 4 * 1024, gfp)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
Some manual whitespace fixes were needed in this patch, as Coccinelle
really liked to write "=devm_kcalloc..." instead of "= devm_kcalloc...".
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
expression HANDLE;
type TYPE;
expression THING, E;
@@
(
devm_kzalloc(HANDLE,
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
devm_kzalloc(HANDLE,
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression HANDLE;
expression COUNT;
typedef u8;
typedef __u8;
@@
(
devm_kzalloc(HANDLE,
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(char) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
expression HANDLE;
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
expression HANDLE;
identifier SIZE, COUNT;
@@
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- SIZE * COUNT
+ COUNT, SIZE
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression HANDLE;
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
devm_kzalloc(HANDLE,
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression HANDLE;
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
expression HANDLE;
identifier STRIDE, SIZE, COUNT;
@@
(
devm_kzalloc(HANDLE,
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products,
// when they're not all constants...
@@
expression HANDLE;
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
devm_kzalloc(HANDLE, C1 * C2 * C3, ...)
|
devm_kzalloc(HANDLE,
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants,
// keeping sizeof() as the second factor argument.
@@
expression HANDLE;
expression THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@
(
devm_kzalloc(HANDLE, sizeof(THING) * C2, ...)
|
devm_kzalloc(HANDLE, sizeof(TYPE) * C2, ...)
|
devm_kzalloc(HANDLE, C1 * C2 * C3, ...)
|
devm_kzalloc(HANDLE, C1 * C2, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- (E1) * E2
+ E1, E2
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- (E1) * (E2)
+ E1, E2
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-13 00:07:58 +03:00
mbox - > chan = devm_kcalloc ( dev ,
mbox - > chan_num , sizeof ( * mbox - > chan ) , GFP_KERNEL ) ;
2016-02-15 16:50:24 +03:00
if ( ! mbox - > chan )
return - ENOMEM ;
mbox - > irq = platform_get_irq ( pdev , 0 ) ;
if ( mbox - > irq < 0 )
return mbox - > irq ;
res = platform_get_resource ( pdev , IORESOURCE_MEM , 0 ) ;
mbox - > ipc = devm_ioremap_resource ( dev , res ) ;
if ( IS_ERR ( mbox - > ipc ) ) {
dev_err ( dev , " ioremap ipc failed \n " ) ;
return PTR_ERR ( mbox - > ipc ) ;
}
res = platform_get_resource ( pdev , IORESOURCE_MEM , 1 ) ;
mbox - > base = devm_ioremap_resource ( dev , res ) ;
if ( IS_ERR ( mbox - > base ) ) {
dev_err ( dev , " ioremap buffer failed \n " ) ;
return PTR_ERR ( mbox - > base ) ;
}
err = devm_request_irq ( dev , mbox - > irq , hi6220_mbox_interrupt , 0 ,
dev_name ( dev ) , mbox ) ;
if ( err ) {
dev_err ( dev , " Failed to register a mailbox IRQ handler: %d \n " ,
err ) ;
return - ENODEV ;
}
mbox - > controller . dev = dev ;
mbox - > controller . chans = & mbox - > chan [ 0 ] ;
mbox - > controller . num_chans = mbox - > chan_num ;
mbox - > controller . ops = & hi6220_mbox_ops ;
mbox - > controller . of_xlate = hi6220_mbox_xlate ;
for ( i = 0 ; i < mbox - > chan_num ; i + + ) {
mbox - > chan [ i ] . con_priv = & mbox - > mchan [ i ] ;
mbox - > irq_map_chan [ i ] = NULL ;
mbox - > mchan [ i ] . parent = mbox ;
mbox - > mchan [ i ] . slot = i ;
}
/* mask and clear all interrupt vectors */
writel ( 0x0 , ACK_INT_MSK_REG ( mbox - > ipc ) ) ;
writel ( ~ 0x0 , ACK_INT_CLR_REG ( mbox - > ipc ) ) ;
/* use interrupt for tx's ack */
if ( of_find_property ( node , " hi6220,mbox-tx-noirq " , NULL ) )
mbox - > tx_irq_mode = false ;
else
mbox - > tx_irq_mode = true ;
if ( mbox - > tx_irq_mode )
mbox - > controller . txdone_irq = true ;
else {
mbox - > controller . txdone_poll = true ;
mbox - > controller . txpoll_period = 5 ;
}
2018-12-20 20:19:50 +03:00
err = devm_mbox_controller_register ( dev , & mbox - > controller ) ;
2016-02-15 16:50:24 +03:00
if ( err ) {
dev_err ( dev , " Failed to register mailbox %d \n " , err ) ;
return err ;
}
platform_set_drvdata ( pdev , mbox ) ;
dev_info ( dev , " Mailbox enabled \n " ) ;
return 0 ;
}
static struct platform_driver hi6220_mbox_driver = {
. driver = {
. name = " hi6220-mbox " ,
. owner = THIS_MODULE ,
. of_match_table = hi6220_mbox_of_match ,
} ,
. probe = hi6220_mbox_probe ,
} ;
static int __init hi6220_mbox_init ( void )
{
return platform_driver_register ( & hi6220_mbox_driver ) ;
}
core_initcall ( hi6220_mbox_init ) ;
static void __exit hi6220_mbox_exit ( void )
{
platform_driver_unregister ( & hi6220_mbox_driver ) ;
}
module_exit ( hi6220_mbox_exit ) ;
MODULE_AUTHOR ( " Leo Yan <leo.yan@linaro.org> " ) ;
MODULE_DESCRIPTION ( " Hi6220 mailbox driver " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;