2017-12-02 13:22:45 +03:00
// SPDX-License-Identifier: GPL-2.0
2016-03-17 03:23:14 +03:00
/*
* Texas Instruments ' Message Manager Driver
*
2022-02-10 07:16:31 +03:00
* Copyright ( C ) 2015 - 2022 Texas Instruments Incorporated - https : //www.ti.com/
2016-03-17 03:23:14 +03:00
* Nishanth Menon
*/
# define pr_fmt(fmt) "%s: " fmt, __func__
# include <linux/device.h>
# include <linux/interrupt.h>
# include <linux/io.h>
2022-02-10 07:16:31 +03:00
# include <linux/iopoll.h>
2016-03-17 03:23:14 +03:00
# include <linux/kernel.h>
# include <linux/mailbox_controller.h>
# include <linux/module.h>
# include <linux/of_device.h>
# include <linux/of.h>
# include <linux/of_irq.h>
# include <linux/platform_device.h>
# include <linux/soc/ti/ti-msgmgr.h>
# define Q_DATA_OFFSET(proxy, queue, reg) \
( ( 0x10000 * ( proxy ) ) + ( 0x80 * ( queue ) ) + ( ( reg ) * 4 ) )
# define Q_STATE_OFFSET(queue) ((queue) * 0x4)
# define Q_STATE_ENTRY_COUNT_MASK (0xFFF000)
2018-07-16 21:06:07 +03:00
# define SPROXY_THREAD_OFFSET(tid) (0x1000 * (tid))
# define SPROXY_THREAD_DATA_OFFSET(tid, reg) \
( SPROXY_THREAD_OFFSET ( tid ) + ( ( reg ) * 0x4 ) + 0x4 )
# define SPROXY_THREAD_STATUS_OFFSET(tid) (SPROXY_THREAD_OFFSET(tid))
# define SPROXY_THREAD_STATUS_COUNT_MASK (0xFF)
# define SPROXY_THREAD_CTRL_OFFSET(tid) (0x1000 + SPROXY_THREAD_OFFSET(tid))
# define SPROXY_THREAD_CTRL_DIR_MASK (0x1 << 31)
2016-03-17 03:23:14 +03:00
/**
* struct ti_msgmgr_valid_queue_desc - SoC valid queues meant for this processor
* @ queue_id : Queue Number for this path
* @ proxy_id : Proxy ID representing the processor in SoC
* @ is_tx : Is this a receive path ?
*/
struct ti_msgmgr_valid_queue_desc {
u8 queue_id ;
u8 proxy_id ;
bool is_tx ;
} ;
/**
* struct ti_msgmgr_desc - Description of message manager integration
* @ queue_count : Number of Queues
* @ max_message_size : Message size in bytes
* @ max_messages : Number of messages
* @ data_first_reg : First data register for proxy data region
* @ data_last_reg : Last data register for proxy data region
2018-07-16 21:06:04 +03:00
* @ status_cnt_mask : Mask for getting the status value
2018-07-16 21:06:07 +03:00
* @ status_err_mask : Mask for getting the error value , if applicable
2016-03-17 03:23:14 +03:00
* @ tx_polled : Do I need to use polled mechanism for tx
* @ tx_poll_timeout_ms : Timeout in ms if polled
* @ valid_queues : List of Valid queues that the processor can access
2018-07-16 21:06:05 +03:00
* @ data_region_name : Name of the proxy data region
* @ status_region_name : Name of the proxy status region
2018-07-16 21:06:07 +03:00
* @ ctrl_region_name : Name of the proxy control region
2016-03-17 03:23:14 +03:00
* @ num_valid_queues : Number of valid queues
2018-07-16 21:06:07 +03:00
* @ is_sproxy : Is this an Secure Proxy instance ?
2016-03-17 03:23:14 +03:00
*
* This structure is used in of match data to describe how integration
* for a specific compatible SoC is done .
*/
struct ti_msgmgr_desc {
u8 queue_count ;
u8 max_message_size ;
u8 max_messages ;
u8 data_first_reg ;
u8 data_last_reg ;
2018-07-16 21:06:04 +03:00
u32 status_cnt_mask ;
2018-07-16 21:06:07 +03:00
u32 status_err_mask ;
2016-03-17 03:23:14 +03:00
bool tx_polled ;
int tx_poll_timeout_ms ;
const struct ti_msgmgr_valid_queue_desc * valid_queues ;
2018-07-16 21:06:05 +03:00
const char * data_region_name ;
const char * status_region_name ;
2018-07-16 21:06:07 +03:00
const char * ctrl_region_name ;
2016-03-17 03:23:14 +03:00
int num_valid_queues ;
2018-07-16 21:06:07 +03:00
bool is_sproxy ;
2016-03-17 03:23:14 +03:00
} ;
/**
* struct ti_queue_inst - Description of a queue instance
* @ name : Queue Name
* @ queue_id : Queue Identifier as mapped on SoC
* @ proxy_id : Proxy Identifier as mapped on SoC
* @ irq : IRQ for Rx Queue
* @ is_tx : ' true ' if transmit queue , else , ' false '
* @ queue_buff_start : First register of Data Buffer
* @ queue_buff_end : Last ( or confirmation ) register of Data buffer
* @ queue_state : Queue status register
2018-07-16 21:06:07 +03:00
* @ queue_ctrl : Queue Control register
2016-03-17 03:23:14 +03:00
* @ chan : Mailbox channel
* @ rx_buff : Receive buffer pointer allocated at probe , max_message_size
2022-02-10 07:16:31 +03:00
* @ polled_rx_mode : Use polling for rx instead of interrupts
2016-03-17 03:23:14 +03:00
*/
struct ti_queue_inst {
char name [ 30 ] ;
u8 queue_id ;
u8 proxy_id ;
int irq ;
bool is_tx ;
void __iomem * queue_buff_start ;
void __iomem * queue_buff_end ;
void __iomem * queue_state ;
2018-07-16 21:06:07 +03:00
void __iomem * queue_ctrl ;
2016-03-17 03:23:14 +03:00
struct mbox_chan * chan ;
u32 * rx_buff ;
2022-02-10 07:16:31 +03:00
bool polled_rx_mode ;
2016-03-17 03:23:14 +03:00
} ;
/**
* struct ti_msgmgr_inst - Description of a Message Manager Instance
* @ dev : device pointer corresponding to the Message Manager instance
* @ desc : Description of the SoC integration
* @ queue_proxy_region : Queue proxy region where queue buffers are located
* @ queue_state_debug_region : Queue status register regions
2018-07-16 21:06:07 +03:00
* @ queue_ctrl_region : Queue Control register regions
2016-03-17 03:23:14 +03:00
* @ num_valid_queues : Number of valid queues defined for the processor
* Note : other queues are probably reserved for other processors
* in the SoC .
* @ qinsts : Array of valid Queue Instances for the Processor
* @ mbox : Mailbox Controller
* @ chans : Array for channels corresponding to the Queue Instances .
*/
struct ti_msgmgr_inst {
struct device * dev ;
const struct ti_msgmgr_desc * desc ;
void __iomem * queue_proxy_region ;
void __iomem * queue_state_debug_region ;
2018-07-16 21:06:07 +03:00
void __iomem * queue_ctrl_region ;
2016-03-17 03:23:14 +03:00
u8 num_valid_queues ;
struct ti_queue_inst * qinsts ;
struct mbox_controller mbox ;
struct mbox_chan * chans ;
} ;
/**
* ti_msgmgr_queue_get_num_messages ( ) - Get the number of pending messages
2018-07-16 21:06:04 +03:00
* @ d : Description of message manager
2016-03-17 03:23:14 +03:00
* @ qinst : Queue instance for which we check the number of pending messages
*
* Return : number of messages pending in the queue ( 0 = = no pending messages )
*/
2018-07-16 21:06:04 +03:00
static inline int
ti_msgmgr_queue_get_num_messages ( const struct ti_msgmgr_desc * d ,
struct ti_queue_inst * qinst )
2016-03-17 03:23:14 +03:00
{
u32 val ;
2018-07-16 21:06:04 +03:00
u32 status_cnt_mask = d - > status_cnt_mask ;
2016-03-17 03:23:14 +03:00
/*
* We cannot use relaxed operation here - update may happen
* real - time .
*/
2018-07-16 21:06:04 +03:00
val = readl ( qinst - > queue_state ) & status_cnt_mask ;
val > > = __ffs ( status_cnt_mask ) ;
2016-03-17 03:23:14 +03:00
return val ;
}
2018-07-16 21:06:07 +03:00
/**
* ti_msgmgr_queue_is_error ( ) - Check to see if there is queue error
* @ d : Description of message manager
* @ qinst : Queue instance for which we check the number of pending messages
*
* Return : true if error , else false
*/
static inline bool ti_msgmgr_queue_is_error ( const struct ti_msgmgr_desc * d ,
struct ti_queue_inst * qinst )
{
u32 val ;
/* Msgmgr has no error detection */
if ( ! d - > is_sproxy )
return false ;
/*
* We cannot use relaxed operation here - update may happen
* real - time .
*/
val = readl ( qinst - > queue_state ) & d - > status_err_mask ;
return val ? true : false ;
}
2022-02-10 07:16:30 +03:00
static int ti_msgmgr_queue_rx_data ( struct mbox_chan * chan , struct ti_queue_inst * qinst ,
const struct ti_msgmgr_desc * desc )
{
int num_words ;
struct ti_msgmgr_message message ;
void __iomem * data_reg ;
u32 * word_data ;
/*
* I have no idea about the protocol being used to communicate with the
* remote producer - 0 could be valid data , so I wont make a judgement
* of how many bytes I should be reading . Let the client figure this
* out . . I just read the full message and pass it on . .
*/
message . len = desc - > max_message_size ;
message . buf = ( u8 * ) qinst - > rx_buff ;
/*
* NOTE about register access involved here :
* the hardware block is implemented with 32 bit access operations and no
* support for data splitting . We don ' t want the hardware to misbehave
* with sub 32 bit access - For example : if the last register read is
* split into byte wise access , it can result in the queue getting
* stuck or indeterminate behavior . An out of order read operation may
* result in weird data results as well .
* Hence , we do not use memcpy_fromio or __ioread32_copy here , instead
* we depend on readl for the purpose .
*
* Also note that the final register read automatically marks the
* queue message as read .
*/
for ( data_reg = qinst - > queue_buff_start , word_data = qinst - > rx_buff ,
num_words = ( desc - > max_message_size / sizeof ( u32 ) ) ;
num_words ; num_words - - , data_reg + = sizeof ( u32 ) , word_data + + )
* word_data = readl ( data_reg ) ;
/*
* Last register read automatically clears the IRQ if only 1 message
* is pending - so send the data up the stack . .
* NOTE : Client is expected to be as optimal as possible , since
* we invoke the handler in IRQ context .
*/
mbox_chan_received_data ( chan , ( void * ) & message ) ;
return 0 ;
}
2022-02-10 07:16:31 +03:00
static int ti_msgmgr_queue_rx_poll_timeout ( struct mbox_chan * chan , int timeout_us )
{
struct device * dev = chan - > mbox - > dev ;
struct ti_msgmgr_inst * inst = dev_get_drvdata ( dev ) ;
struct ti_queue_inst * qinst = chan - > con_priv ;
const struct ti_msgmgr_desc * desc = inst - > desc ;
int msg_count ;
int ret ;
ret = readl_poll_timeout_atomic ( qinst - > queue_state , msg_count ,
( msg_count & desc - > status_cnt_mask ) ,
10 , timeout_us ) ;
if ( ret ! = 0 )
return ret ;
ti_msgmgr_queue_rx_data ( chan , qinst , desc ) ;
return 0 ;
}
2016-03-17 03:23:14 +03:00
/**
* ti_msgmgr_queue_rx_interrupt ( ) - Interrupt handler for receive Queue
* @ irq : Interrupt number
* @ p : Channel Pointer
*
* Return : - EINVAL if there is no instance
* IRQ_NONE if the interrupt is not ours .
* IRQ_HANDLED if the rx interrupt was successfully handled .
*/
static irqreturn_t ti_msgmgr_queue_rx_interrupt ( int irq , void * p )
{
struct mbox_chan * chan = p ;
struct device * dev = chan - > mbox - > dev ;
struct ti_msgmgr_inst * inst = dev_get_drvdata ( dev ) ;
struct ti_queue_inst * qinst = chan - > con_priv ;
const struct ti_msgmgr_desc * desc ;
2022-02-10 07:16:30 +03:00
int msg_count ;
2016-03-17 03:23:14 +03:00
if ( WARN_ON ( ! inst ) ) {
dev_err ( dev , " no platform drv data?? \n " ) ;
return - EINVAL ;
}
/* Do I have an invalid interrupt source? */
if ( qinst - > is_tx ) {
dev_err ( dev , " Cannot handle rx interrupt on tx channel %s \n " ,
qinst - > name ) ;
return IRQ_NONE ;
}
2018-07-16 21:06:04 +03:00
desc = inst - > desc ;
2018-07-16 21:06:07 +03:00
if ( ti_msgmgr_queue_is_error ( desc , qinst ) ) {
dev_err ( dev , " Error on Rx channel %s \n " , qinst - > name ) ;
return IRQ_NONE ;
}
2016-03-17 03:23:14 +03:00
/* Do I actually have messages to read? */
2018-07-16 21:06:04 +03:00
msg_count = ti_msgmgr_queue_get_num_messages ( desc , qinst ) ;
2016-03-17 03:23:14 +03:00
if ( ! msg_count ) {
/* Shared IRQ? */
dev_dbg ( dev , " Spurious event - 0 pending data! \n " ) ;
return IRQ_NONE ;
}
2022-02-10 07:16:30 +03:00
ti_msgmgr_queue_rx_data ( chan , qinst , desc ) ;
2016-03-17 03:23:14 +03:00
return IRQ_HANDLED ;
}
/**
* ti_msgmgr_queue_peek_data ( ) - Peek to see if there are any rx messages .
* @ chan : Channel Pointer
*
* Return : ' true ' if there is pending rx data , ' false ' if there is none .
*/
static bool ti_msgmgr_queue_peek_data ( struct mbox_chan * chan )
{
struct ti_queue_inst * qinst = chan - > con_priv ;
2018-07-16 21:06:04 +03:00
struct device * dev = chan - > mbox - > dev ;
struct ti_msgmgr_inst * inst = dev_get_drvdata ( dev ) ;
2018-07-16 21:06:07 +03:00
const struct ti_msgmgr_desc * desc = inst - > desc ;
2016-03-17 03:23:14 +03:00
int msg_count ;
if ( qinst - > is_tx )
return false ;
2018-07-16 21:06:07 +03:00
if ( ti_msgmgr_queue_is_error ( desc , qinst ) ) {
dev_err ( dev , " Error on channel %s \n " , qinst - > name ) ;
return false ;
}
msg_count = ti_msgmgr_queue_get_num_messages ( desc , qinst ) ;
2016-03-17 03:23:14 +03:00
return msg_count ? true : false ;
}
/**
* ti_msgmgr_last_tx_done ( ) - See if all the tx messages are sent
* @ chan : Channel pointer
*
* Return : ' true ' is no pending tx data , ' false ' if there are any .
*/
static bool ti_msgmgr_last_tx_done ( struct mbox_chan * chan )
{
struct ti_queue_inst * qinst = chan - > con_priv ;
2018-07-16 21:06:04 +03:00
struct device * dev = chan - > mbox - > dev ;
struct ti_msgmgr_inst * inst = dev_get_drvdata ( dev ) ;
2018-07-16 21:06:07 +03:00
const struct ti_msgmgr_desc * desc = inst - > desc ;
2016-03-17 03:23:14 +03:00
int msg_count ;
if ( ! qinst - > is_tx )
return false ;
2018-07-16 21:06:07 +03:00
if ( ti_msgmgr_queue_is_error ( desc , qinst ) ) {
dev_err ( dev , " Error on channel %s \n " , qinst - > name ) ;
return false ;
}
msg_count = ti_msgmgr_queue_get_num_messages ( desc , qinst ) ;
if ( desc - > is_sproxy ) {
/* In secure proxy, msg_count indicates how many we can send */
return msg_count ? true : false ;
}
2016-03-17 03:23:14 +03:00
/* if we have any messages pending.. */
return msg_count ? false : true ;
}
2022-02-10 07:16:31 +03:00
static bool ti_msgmgr_chan_has_polled_queue_rx ( struct mbox_chan * chan )
{
struct ti_queue_inst * qinst ;
if ( ! chan )
return false ;
qinst = chan - > con_priv ;
return qinst - > polled_rx_mode ;
}
2016-03-17 03:23:14 +03:00
/**
* ti_msgmgr_send_data ( ) - Send data
* @ chan : Channel Pointer
* @ data : ti_msgmgr_message * Message Pointer
*
* Return : 0 if all goes good , else appropriate error messages .
*/
static int ti_msgmgr_send_data ( struct mbox_chan * chan , void * data )
{
struct device * dev = chan - > mbox - > dev ;
struct ti_msgmgr_inst * inst = dev_get_drvdata ( dev ) ;
const struct ti_msgmgr_desc * desc ;
struct ti_queue_inst * qinst = chan - > con_priv ;
int num_words , trail_bytes ;
struct ti_msgmgr_message * message = data ;
void __iomem * data_reg ;
u32 * word_data ;
2022-02-10 07:16:31 +03:00
int ret = 0 ;
2016-03-17 03:23:14 +03:00
if ( WARN_ON ( ! inst ) ) {
dev_err ( dev , " no platform drv data?? \n " ) ;
return - EINVAL ;
}
desc = inst - > desc ;
2018-07-16 21:06:07 +03:00
if ( ti_msgmgr_queue_is_error ( desc , qinst ) ) {
dev_err ( dev , " Error on channel %s \n " , qinst - > name ) ;
return false ;
}
2016-03-17 03:23:14 +03:00
if ( desc - > max_message_size < message - > len ) {
2017-12-02 13:27:18 +03:00
dev_err ( dev , " Queue %s message length %zu > max %d \n " ,
2016-03-17 03:23:14 +03:00
qinst - > name , message - > len , desc - > max_message_size ) ;
return - EINVAL ;
}
/* NOTE: Constraints similar to rx path exists here as well */
for ( data_reg = qinst - > queue_buff_start ,
num_words = message - > len / sizeof ( u32 ) ,
word_data = ( u32 * ) message - > buf ;
num_words ; num_words - - , data_reg + = sizeof ( u32 ) , word_data + + )
writel ( * word_data , data_reg ) ;
trail_bytes = message - > len % sizeof ( u32 ) ;
if ( trail_bytes ) {
u32 data_trail = * word_data ;
/* Ensure all unused data is 0 */
data_trail & = 0xFFFFFFFF > > ( 8 * ( sizeof ( u32 ) - trail_bytes ) ) ;
writel ( data_trail , data_reg ) ;
data_reg + + ;
}
/*
* ' data_reg ' indicates next register to write . If we did not already
* write on tx complete reg ( last reg ) , we must do so for transmit
*/
if ( data_reg < = qinst - > queue_buff_end )
writel ( 0 , qinst - > queue_buff_end ) ;
2022-02-10 07:16:31 +03:00
/* If we are in polled mode, wait for a response before proceeding */
if ( ti_msgmgr_chan_has_polled_queue_rx ( message - > chan_rx ) )
ret = ti_msgmgr_queue_rx_poll_timeout ( message - > chan_rx ,
message - > timeout_rx_ms * 1000 ) ;
return ret ;
2016-03-17 03:23:14 +03:00
}
2018-07-16 21:06:03 +03:00
/**
* ti_msgmgr_queue_rx_irq_req ( ) - RX IRQ request
* @ dev : device pointer
2018-07-16 21:06:07 +03:00
* @ d : descriptor for ti_msgmgr
2018-07-16 21:06:03 +03:00
* @ qinst : Queue instance
* @ chan : Channel pointer
*/
static int ti_msgmgr_queue_rx_irq_req ( struct device * dev ,
2018-07-16 21:06:07 +03:00
const struct ti_msgmgr_desc * d ,
2018-07-16 21:06:03 +03:00
struct ti_queue_inst * qinst ,
struct mbox_chan * chan )
{
int ret = 0 ;
char of_rx_irq_name [ 7 ] ;
struct device_node * np ;
snprintf ( of_rx_irq_name , sizeof ( of_rx_irq_name ) ,
2018-07-16 21:06:07 +03:00
" rx_%03d " , d - > is_sproxy ? qinst - > proxy_id : qinst - > queue_id ) ;
2018-07-16 21:06:03 +03:00
/* Get the IRQ if not found */
if ( qinst - > irq < 0 ) {
np = of_node_get ( dev - > of_node ) ;
if ( ! np )
return - ENODATA ;
qinst - > irq = of_irq_get_byname ( np , of_rx_irq_name ) ;
of_node_put ( np ) ;
if ( qinst - > irq < 0 ) {
dev_err ( dev ,
" QID %d PID %d:No IRQ[%s]: %d \n " ,
qinst - > queue_id , qinst - > proxy_id ,
of_rx_irq_name , qinst - > irq ) ;
return qinst - > irq ;
}
}
/* With the expectation that the IRQ might be shared in SoC */
ret = request_irq ( qinst - > irq , ti_msgmgr_queue_rx_interrupt ,
IRQF_SHARED , qinst - > name , chan ) ;
if ( ret ) {
dev_err ( dev , " Unable to get IRQ %d on %s(res=%d) \n " ,
qinst - > irq , qinst - > name , ret ) ;
}
return ret ;
}
2016-03-17 03:23:14 +03:00
/**
* ti_msgmgr_queue_startup ( ) - Startup queue
* @ chan : Channel pointer
*
* Return : 0 if all goes good , else return corresponding error message
*/
static int ti_msgmgr_queue_startup ( struct mbox_chan * chan )
{
struct device * dev = chan - > mbox - > dev ;
2018-07-16 21:06:03 +03:00
struct ti_msgmgr_inst * inst = dev_get_drvdata ( dev ) ;
struct ti_queue_inst * qinst = chan - > con_priv ;
const struct ti_msgmgr_desc * d = inst - > desc ;
2016-03-17 03:23:14 +03:00
int ret ;
2018-07-16 21:06:07 +03:00
int msg_count ;
/*
* If sproxy is starting and can send messages , we are a Tx thread ,
* else Rx
*/
if ( d - > is_sproxy ) {
qinst - > is_tx = ( readl ( qinst - > queue_ctrl ) &
SPROXY_THREAD_CTRL_DIR_MASK ) ? false : true ;
msg_count = ti_msgmgr_queue_get_num_messages ( d , qinst ) ;
if ( ! msg_count & & qinst - > is_tx ) {
dev_err ( dev , " %s: Cannot transmit with 0 credits! \n " ,
qinst - > name ) ;
return - EINVAL ;
}
}
2016-03-17 03:23:14 +03:00
if ( ! qinst - > is_tx ) {
2018-07-16 21:06:03 +03:00
/* Allocate usage buffer for rx */
qinst - > rx_buff = kzalloc ( d - > max_message_size , GFP_KERNEL ) ;
if ( ! qinst - > rx_buff )
return - ENOMEM ;
/* Request IRQ */
2018-07-16 21:06:07 +03:00
ret = ti_msgmgr_queue_rx_irq_req ( dev , d , qinst , chan ) ;
2016-03-17 03:23:14 +03:00
if ( ret ) {
2018-07-16 21:06:03 +03:00
kfree ( qinst - > rx_buff ) ;
2016-03-17 03:23:14 +03:00
return ret ;
}
}
return 0 ;
}
/**
* ti_msgmgr_queue_shutdown ( ) - Shutdown the queue
* @ chan : Channel pointer
*/
static void ti_msgmgr_queue_shutdown ( struct mbox_chan * chan )
{
struct ti_queue_inst * qinst = chan - > con_priv ;
2018-07-16 21:06:03 +03:00
if ( ! qinst - > is_tx ) {
2016-03-17 03:23:14 +03:00
free_irq ( qinst - > irq , chan ) ;
2018-07-16 21:06:03 +03:00
kfree ( qinst - > rx_buff ) ;
}
2016-03-17 03:23:14 +03:00
}
/**
* ti_msgmgr_of_xlate ( ) - Translation of phandle to queue
* @ mbox : Mailbox controller
* @ p : phandle pointer
*
* Return : Mailbox channel corresponding to the queue , else return error
* pointer .
*/
static struct mbox_chan * ti_msgmgr_of_xlate ( struct mbox_controller * mbox ,
const struct of_phandle_args * p )
{
struct ti_msgmgr_inst * inst ;
int req_qid , req_pid ;
struct ti_queue_inst * qinst ;
2018-07-16 21:06:07 +03:00
const struct ti_msgmgr_desc * d ;
int i , ncells ;
2016-03-17 03:23:14 +03:00
inst = container_of ( mbox , struct ti_msgmgr_inst , mbox ) ;
if ( WARN_ON ( ! inst ) )
return ERR_PTR ( - EINVAL ) ;
2018-07-16 21:06:07 +03:00
d = inst - > desc ;
if ( d - > is_sproxy )
ncells = 1 ;
else
ncells = 2 ;
if ( p - > args_count ! = ncells ) {
dev_err ( inst - > dev , " Invalid arguments in dt[%d]. Must be %d \n " ,
p - > args_count , ncells ) ;
2016-03-17 03:23:14 +03:00
return ERR_PTR ( - EINVAL ) ;
}
2018-07-16 21:06:07 +03:00
if ( ncells = = 1 ) {
req_qid = 0 ;
req_pid = p - > args [ 0 ] ;
} else {
req_qid = p - > args [ 0 ] ;
req_pid = p - > args [ 1 ] ;
}
if ( d - > is_sproxy ) {
2018-12-03 17:50:11 +03:00
if ( req_pid > = d - > num_valid_queues )
2018-07-16 21:06:07 +03:00
goto err ;
qinst = & inst - > qinsts [ req_pid ] ;
return qinst - > chan ;
}
2016-03-17 03:23:14 +03:00
for ( qinst = inst - > qinsts , i = 0 ; i < inst - > num_valid_queues ;
i + + , qinst + + ) {
if ( req_qid = = qinst - > queue_id & & req_pid = = qinst - > proxy_id )
return qinst - > chan ;
}
2018-07-16 21:06:07 +03:00
err :
2018-08-28 04:52:28 +03:00
dev_err ( inst - > dev , " Queue ID %d, Proxy ID %d is wrong on %pOFn \n " ,
req_qid , req_pid , p - > np ) ;
2016-03-17 03:23:14 +03:00
return ERR_PTR ( - ENOENT ) ;
}
/**
* ti_msgmgr_queue_setup ( ) - Setup data structures for each queue instance
* @ idx : index of the queue
* @ dev : pointer to the message manager device
* @ np : pointer to the of node
* @ inst : Queue instance pointer
* @ d : Message Manager instance description data
* @ qd : Queue description data
* @ qinst : Queue instance pointer
* @ chan : pointer to mailbox channel
*
* Return : 0 if all went well , else return corresponding error
*/
static int ti_msgmgr_queue_setup ( int idx , struct device * dev ,
struct device_node * np ,
struct ti_msgmgr_inst * inst ,
const struct ti_msgmgr_desc * d ,
const struct ti_msgmgr_valid_queue_desc * qd ,
struct ti_queue_inst * qinst ,
struct mbox_chan * chan )
{
2018-07-16 21:06:07 +03:00
char * dir ;
2016-03-17 03:23:14 +03:00
qinst - > proxy_id = qd - > proxy_id ;
qinst - > queue_id = qd - > queue_id ;
if ( qinst - > queue_id > d - > queue_count ) {
dev_err ( dev , " Queue Data [idx=%d] queuid %d > %d \n " ,
idx , qinst - > queue_id , d - > queue_count ) ;
return - ERANGE ;
}
2018-07-16 21:06:07 +03:00
if ( d - > is_sproxy ) {
qinst - > queue_buff_start = inst - > queue_proxy_region +
SPROXY_THREAD_DATA_OFFSET ( qinst - > proxy_id ,
d - > data_first_reg ) ;
qinst - > queue_buff_end = inst - > queue_proxy_region +
SPROXY_THREAD_DATA_OFFSET ( qinst - > proxy_id ,
d - > data_last_reg ) ;
qinst - > queue_state = inst - > queue_state_debug_region +
SPROXY_THREAD_STATUS_OFFSET ( qinst - > proxy_id ) ;
qinst - > queue_ctrl = inst - > queue_ctrl_region +
SPROXY_THREAD_CTRL_OFFSET ( qinst - > proxy_id ) ;
/* XXX: DONOT read registers here!.. Some may be unusable */
dir = " thr " ;
snprintf ( qinst - > name , sizeof ( qinst - > name ) , " %s %s_%03d " ,
dev_name ( dev ) , dir , qinst - > proxy_id ) ;
} else {
qinst - > queue_buff_start = inst - > queue_proxy_region +
Q_DATA_OFFSET ( qinst - > proxy_id , qinst - > queue_id ,
d - > data_first_reg ) ;
qinst - > queue_buff_end = inst - > queue_proxy_region +
Q_DATA_OFFSET ( qinst - > proxy_id , qinst - > queue_id ,
d - > data_last_reg ) ;
qinst - > queue_state =
inst - > queue_state_debug_region +
Q_STATE_OFFSET ( qinst - > queue_id ) ;
qinst - > is_tx = qd - > is_tx ;
dir = qinst - > is_tx ? " tx " : " rx " ;
snprintf ( qinst - > name , sizeof ( qinst - > name ) , " %s %s_%03d_%03d " ,
dev_name ( dev ) , dir , qinst - > queue_id , qinst - > proxy_id ) ;
}
2016-03-17 03:23:14 +03:00
qinst - > chan = chan ;
2018-07-16 21:06:03 +03:00
/* Setup an error value for IRQ - Lazy allocation */
qinst - > irq = - EINVAL ;
2016-03-17 03:23:14 +03:00
chan - > con_priv = qinst ;
dev_dbg ( dev , " [%d] qidx=%d pidx=%d irq=%d q_s=%p q_e = %p \n " ,
idx , qinst - > queue_id , qinst - > proxy_id , qinst - > irq ,
qinst - > queue_buff_start , qinst - > queue_buff_end ) ;
return 0 ;
}
2022-02-10 07:16:31 +03:00
static int ti_msgmgr_queue_rx_set_polled_mode ( struct ti_queue_inst * qinst , bool enable )
{
if ( enable ) {
disable_irq ( qinst - > irq ) ;
qinst - > polled_rx_mode = true ;
} else {
enable_irq ( qinst - > irq ) ;
qinst - > polled_rx_mode = false ;
}
return 0 ;
}
static int ti_msgmgr_suspend ( struct device * dev )
{
struct ti_msgmgr_inst * inst = dev_get_drvdata ( dev ) ;
struct ti_queue_inst * qinst ;
int i ;
/*
* We must switch operation to polled mode now as drivers and the genpd
* layer may make late TI SCI calls to change clock and device states
* from the noirq phase of suspend .
*/
for ( qinst = inst - > qinsts , i = 0 ; i < inst - > num_valid_queues ; qinst + + , i + + ) {
if ( ! qinst - > is_tx )
ti_msgmgr_queue_rx_set_polled_mode ( qinst , true ) ;
}
return 0 ;
}
static int ti_msgmgr_resume ( struct device * dev )
{
struct ti_msgmgr_inst * inst = dev_get_drvdata ( dev ) ;
struct ti_queue_inst * qinst ;
int i ;
for ( qinst = inst - > qinsts , i = 0 ; i < inst - > num_valid_queues ; qinst + + , i + + ) {
if ( ! qinst - > is_tx )
ti_msgmgr_queue_rx_set_polled_mode ( qinst , false ) ;
}
return 0 ;
}
static DEFINE_SIMPLE_DEV_PM_OPS ( ti_msgmgr_pm_ops , ti_msgmgr_suspend , ti_msgmgr_resume ) ;
2016-03-17 03:23:14 +03:00
/* Queue operations */
static const struct mbox_chan_ops ti_msgmgr_chan_ops = {
. startup = ti_msgmgr_queue_startup ,
. shutdown = ti_msgmgr_queue_shutdown ,
. peek_data = ti_msgmgr_queue_peek_data ,
. last_tx_done = ti_msgmgr_last_tx_done ,
. send_data = ti_msgmgr_send_data ,
} ;
/* Keystone K2G SoC integration details */
static const struct ti_msgmgr_valid_queue_desc k2g_valid_queues [ ] = {
{ . queue_id = 0 , . proxy_id = 0 , . is_tx = true , } ,
{ . queue_id = 1 , . proxy_id = 0 , . is_tx = true , } ,
{ . queue_id = 2 , . proxy_id = 0 , . is_tx = true , } ,
{ . queue_id = 3 , . proxy_id = 0 , . is_tx = true , } ,
{ . queue_id = 5 , . proxy_id = 2 , . is_tx = false , } ,
{ . queue_id = 56 , . proxy_id = 1 , . is_tx = true , } ,
{ . queue_id = 57 , . proxy_id = 2 , . is_tx = false , } ,
{ . queue_id = 58 , . proxy_id = 3 , . is_tx = true , } ,
{ . queue_id = 59 , . proxy_id = 4 , . is_tx = true , } ,
{ . queue_id = 60 , . proxy_id = 5 , . is_tx = true , } ,
{ . queue_id = 61 , . proxy_id = 6 , . is_tx = true , } ,
} ;
static const struct ti_msgmgr_desc k2g_desc = {
. queue_count = 64 ,
. max_message_size = 64 ,
. max_messages = 128 ,
2018-07-16 21:06:05 +03:00
. data_region_name = " queue_proxy_region " ,
. status_region_name = " queue_state_debug_region " ,
2016-03-17 03:23:14 +03:00
. data_first_reg = 16 ,
. data_last_reg = 31 ,
2018-07-16 21:06:04 +03:00
. status_cnt_mask = Q_STATE_ENTRY_COUNT_MASK ,
2016-03-17 03:23:14 +03:00
. tx_polled = false ,
. valid_queues = k2g_valid_queues ,
. num_valid_queues = ARRAY_SIZE ( k2g_valid_queues ) ,
2018-07-16 21:06:07 +03:00
. is_sproxy = false ,
} ;
static const struct ti_msgmgr_desc am654_desc = {
. queue_count = 190 ,
. num_valid_queues = 190 ,
. max_message_size = 60 ,
. data_region_name = " target_data " ,
. status_region_name = " rt " ,
. ctrl_region_name = " scfg " ,
. data_first_reg = 0 ,
. data_last_reg = 14 ,
. status_cnt_mask = SPROXY_THREAD_STATUS_COUNT_MASK ,
. tx_polled = false ,
. is_sproxy = true ,
2016-03-17 03:23:14 +03:00
} ;
static const struct of_device_id ti_msgmgr_of_match [ ] = {
{ . compatible = " ti,k2g-message-manager " , . data = & k2g_desc } ,
2018-07-16 21:06:07 +03:00
{ . compatible = " ti,am654-secure-proxy " , . data = & am654_desc } ,
2016-03-17 03:23:14 +03:00
{ /* Sentinel */ }
} ;
2018-07-16 21:06:07 +03:00
2016-03-17 03:23:14 +03:00
MODULE_DEVICE_TABLE ( of , ti_msgmgr_of_match ) ;
static int ti_msgmgr_probe ( struct platform_device * pdev )
{
struct device * dev = & pdev - > dev ;
const struct of_device_id * of_id ;
struct device_node * np ;
struct resource * res ;
const struct ti_msgmgr_desc * desc ;
struct ti_msgmgr_inst * inst ;
struct ti_queue_inst * qinst ;
struct mbox_controller * mbox ;
struct mbox_chan * chans ;
int queue_count ;
int i ;
int ret = - EINVAL ;
const struct ti_msgmgr_valid_queue_desc * queue_desc ;
if ( ! dev - > of_node ) {
dev_err ( dev , " no OF information \n " ) ;
return - EINVAL ;
}
np = dev - > of_node ;
of_id = of_match_device ( ti_msgmgr_of_match , dev ) ;
if ( ! of_id ) {
dev_err ( dev , " OF data missing \n " ) ;
return - EINVAL ;
}
desc = of_id - > data ;
inst = devm_kzalloc ( dev , sizeof ( * inst ) , GFP_KERNEL ) ;
if ( ! inst )
return - ENOMEM ;
inst - > dev = dev ;
inst - > desc = desc ;
res = platform_get_resource_byname ( pdev , IORESOURCE_MEM ,
2018-07-16 21:06:05 +03:00
desc - > data_region_name ) ;
2016-03-17 03:23:14 +03:00
inst - > queue_proxy_region = devm_ioremap_resource ( dev , res ) ;
if ( IS_ERR ( inst - > queue_proxy_region ) )
return PTR_ERR ( inst - > queue_proxy_region ) ;
res = platform_get_resource_byname ( pdev , IORESOURCE_MEM ,
2018-07-16 21:06:05 +03:00
desc - > status_region_name ) ;
2016-03-17 03:23:14 +03:00
inst - > queue_state_debug_region = devm_ioremap_resource ( dev , res ) ;
if ( IS_ERR ( inst - > queue_state_debug_region ) )
return PTR_ERR ( inst - > queue_state_debug_region ) ;
2018-07-16 21:06:07 +03:00
if ( desc - > is_sproxy ) {
res = platform_get_resource_byname ( pdev , IORESOURCE_MEM ,
desc - > ctrl_region_name ) ;
inst - > queue_ctrl_region = devm_ioremap_resource ( dev , res ) ;
if ( IS_ERR ( inst - > queue_ctrl_region ) )
return PTR_ERR ( inst - > queue_ctrl_region ) ;
}
2016-03-17 03:23:14 +03:00
dev_dbg ( dev , " proxy region=%p, queue_state=%p \n " ,
inst - > queue_proxy_region , inst - > queue_state_debug_region ) ;
queue_count = desc - > num_valid_queues ;
if ( ! queue_count | | queue_count > desc - > queue_count ) {
dev_crit ( dev , " Invalid Number of queues %d. Max %d \n " ,
queue_count , desc - > queue_count ) ;
return - ERANGE ;
}
inst - > num_valid_queues = queue_count ;
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
qinst = devm_kcalloc ( dev , queue_count , sizeof ( * qinst ) , GFP_KERNEL ) ;
2016-03-17 03:23:14 +03:00
if ( ! qinst )
return - ENOMEM ;
inst - > qinsts = qinst ;
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
chans = devm_kcalloc ( dev , queue_count , sizeof ( * chans ) , GFP_KERNEL ) ;
2016-03-17 03:23:14 +03:00
if ( ! chans )
return - ENOMEM ;
inst - > chans = chans ;
2018-07-16 21:06:07 +03:00
if ( desc - > is_sproxy ) {
struct ti_msgmgr_valid_queue_desc sproxy_desc ;
/* All proxies may be valid in Secure Proxy instance */
for ( i = 0 ; i < queue_count ; i + + , qinst + + , chans + + ) {
sproxy_desc . queue_id = 0 ;
sproxy_desc . proxy_id = i ;
ret = ti_msgmgr_queue_setup ( i , dev , np , inst ,
desc , & sproxy_desc , qinst ,
chans ) ;
if ( ret )
return ret ;
}
} else {
/* Only Some proxies are valid in Message Manager */
for ( i = 0 , queue_desc = desc - > valid_queues ;
i < queue_count ; i + + , qinst + + , chans + + , queue_desc + + ) {
ret = ti_msgmgr_queue_setup ( i , dev , np , inst ,
desc , queue_desc , qinst ,
chans ) ;
if ( ret )
return ret ;
}
2016-03-17 03:23:14 +03:00
}
mbox = & inst - > mbox ;
mbox - > dev = dev ;
mbox - > ops = & ti_msgmgr_chan_ops ;
mbox - > chans = inst - > chans ;
mbox - > num_chans = inst - > num_valid_queues ;
mbox - > txdone_irq = false ;
mbox - > txdone_poll = desc - > tx_polled ;
if ( desc - > tx_polled )
mbox - > txpoll_period = desc - > tx_poll_timeout_ms ;
mbox - > of_xlate = ti_msgmgr_of_xlate ;
platform_set_drvdata ( pdev , inst ) ;
2018-12-20 20:20:02 +03:00
ret = devm_mbox_controller_register ( dev , mbox ) ;
2016-03-17 03:23:14 +03:00
if ( ret )
dev_err ( dev , " Failed to register mbox_controller(%d) \n " , ret ) ;
return ret ;
}
static struct platform_driver ti_msgmgr_driver = {
. probe = ti_msgmgr_probe ,
. driver = {
. name = " ti-msgmgr " ,
. of_match_table = of_match_ptr ( ti_msgmgr_of_match ) ,
2022-02-10 07:16:31 +03:00
. pm = & ti_msgmgr_pm_ops ,
2016-03-17 03:23:14 +03:00
} ,
} ;
module_platform_driver ( ti_msgmgr_driver ) ;
MODULE_LICENSE ( " GPL v2 " ) ;
MODULE_DESCRIPTION ( " TI message manager driver " ) ;
MODULE_AUTHOR ( " Nishanth Menon " ) ;
MODULE_ALIAS ( " platform:ti-msgmgr " ) ;