2019-05-31 11:09:25 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2021-03-17 23:39:32 +03:00
/*
2009-05-14 10:05:58 +04:00
* Copyright ( C ) 2008 , Creative Technology Ltd . All Rights Reserved .
*
* @ File ctdaio . c
*
* @ Brief
* This file contains the implementation of Digital Audio Input Output
* resource management object .
*
* @ Author Liu Chun
* @ Date May 23 2008
*/
# include "ctdaio.h"
# include "cthardware.h"
# include "ctimap.h"
# include <linux/slab.h>
# include <linux/kernel.h>
# define DAIO_OUT_MAX SPDIFOO
2011-06-11 12:02:06 +04:00
struct daio_usage {
2009-05-14 10:05:58 +04:00
unsigned short data ;
} ;
struct daio_rsc_idx {
unsigned short left ;
unsigned short right ;
} ;
2020-01-05 17:47:46 +03:00
static const struct daio_rsc_idx idx_20k1 [ NUM_DAIOTYP ] = {
2009-05-14 10:05:58 +04:00
[ LINEO1 ] = { . left = 0x00 , . right = 0x01 } ,
[ LINEO2 ] = { . left = 0x18 , . right = 0x19 } ,
[ LINEO3 ] = { . left = 0x08 , . right = 0x09 } ,
[ LINEO4 ] = { . left = 0x10 , . right = 0x11 } ,
[ LINEIM ] = { . left = 0x1b5 , . right = 0x1bd } ,
[ SPDIFOO ] = { . left = 0x20 , . right = 0x21 } ,
[ SPDIFIO ] = { . left = 0x15 , . right = 0x1d } ,
[ SPDIFI1 ] = { . left = 0x95 , . right = 0x9d } ,
} ;
2020-01-05 17:47:46 +03:00
static const struct daio_rsc_idx idx_20k2 [ NUM_DAIOTYP ] = {
2009-05-14 10:05:58 +04:00
[ LINEO1 ] = { . left = 0x40 , . right = 0x41 } ,
2009-07-20 19:00:14 +04:00
[ LINEO2 ] = { . left = 0x60 , . right = 0x61 } ,
2009-05-14 10:05:58 +04:00
[ LINEO3 ] = { . left = 0x50 , . right = 0x51 } ,
2009-07-20 19:00:14 +04:00
[ LINEO4 ] = { . left = 0x70 , . right = 0x71 } ,
2009-05-14 10:05:58 +04:00
[ LINEIM ] = { . left = 0x45 , . right = 0xc5 } ,
2011-06-11 12:02:06 +04:00
[ MIC ] = { . left = 0x55 , . right = 0xd5 } ,
2009-05-14 10:05:58 +04:00
[ SPDIFOO ] = { . left = 0x00 , . right = 0x01 } ,
[ SPDIFIO ] = { . left = 0x05 , . right = 0x85 } ,
} ;
static int daio_master ( struct rsc * rsc )
{
/* Actually, this is not the resource index of DAIO.
* For DAO , it is the input mapper index . And , for DAI ,
* it is the output time - slot index . */
return rsc - > conj = rsc - > idx ;
}
static int daio_index ( const struct rsc * rsc )
{
return rsc - > conj ;
}
static int daio_out_next_conj ( struct rsc * rsc )
{
return rsc - > conj + = 2 ;
}
static int daio_in_next_conj_20k1 ( struct rsc * rsc )
{
return rsc - > conj + = 0x200 ;
}
static int daio_in_next_conj_20k2 ( struct rsc * rsc )
{
return rsc - > conj + = 0x100 ;
}
2015-11-09 01:40:41 +03:00
static const struct rsc_ops daio_out_rsc_ops = {
2009-05-14 10:05:58 +04:00
. master = daio_master ,
. next_conj = daio_out_next_conj ,
. index = daio_index ,
. output_slot = NULL ,
} ;
2015-11-09 01:40:41 +03:00
static const struct rsc_ops daio_in_rsc_ops_20k1 = {
2009-05-14 10:05:58 +04:00
. master = daio_master ,
. next_conj = daio_in_next_conj_20k1 ,
. index = NULL ,
. output_slot = daio_index ,
} ;
2015-11-09 01:40:41 +03:00
static const struct rsc_ops daio_in_rsc_ops_20k2 = {
2009-05-14 10:05:58 +04:00
. master = daio_master ,
. next_conj = daio_in_next_conj_20k2 ,
. index = NULL ,
. output_slot = daio_index ,
} ;
static unsigned int daio_device_index ( enum DAIOTYP type , struct hw * hw )
{
2009-06-08 20:10:32 +04:00
switch ( hw - > chip_type ) {
2009-05-14 10:05:58 +04:00
case ATC20K1 :
switch ( type ) {
case SPDIFOO : return 0 ;
case SPDIFIO : return 0 ;
case SPDIFI1 : return 1 ;
case LINEO1 : return 4 ;
case LINEO2 : return 7 ;
case LINEO3 : return 5 ;
case LINEO4 : return 6 ;
case LINEIM : return 7 ;
default : return - EINVAL ;
}
case ATC20K2 :
switch ( type ) {
case SPDIFOO : return 0 ;
case SPDIFIO : return 0 ;
case LINEO1 : return 4 ;
case LINEO2 : return 7 ;
case LINEO3 : return 5 ;
case LINEO4 : return 6 ;
case LINEIM : return 4 ;
2011-06-11 12:02:06 +04:00
case MIC : return 5 ;
2009-05-14 10:05:58 +04:00
default : return - EINVAL ;
}
default :
return - EINVAL ;
}
}
static int dao_rsc_reinit ( struct dao * dao , const struct dao_desc * desc ) ;
static int dao_spdif_get_spos ( struct dao * dao , unsigned int * spos )
{
2014-09-29 13:03:23 +04:00
dao - > hw - > dao_get_spos ( dao - > ctrl_blk , spos ) ;
2009-05-14 10:05:58 +04:00
return 0 ;
}
static int dao_spdif_set_spos ( struct dao * dao , unsigned int spos )
{
2014-09-29 13:03:23 +04:00
dao - > hw - > dao_set_spos ( dao - > ctrl_blk , spos ) ;
2009-05-14 10:05:58 +04:00
return 0 ;
}
static int dao_commit_write ( struct dao * dao )
{
2014-09-29 13:03:23 +04:00
dao - > hw - > dao_commit_write ( dao - > hw ,
2009-05-14 10:05:58 +04:00
daio_device_index ( dao - > daio . type , dao - > hw ) , dao - > ctrl_blk ) ;
return 0 ;
}
static int dao_set_left_input ( struct dao * dao , struct rsc * input )
{
2009-06-08 16:57:57 +04:00
struct imapper * entry ;
2009-05-14 10:05:58 +04:00
struct daio * daio = & dao - > daio ;
2009-06-08 16:57:57 +04:00
int i ;
2009-05-14 10:05:58 +04:00
entry = kzalloc ( ( sizeof ( * entry ) * daio - > rscl . msr ) , GFP_KERNEL ) ;
2009-07-22 19:12:34 +04:00
if ( ! entry )
2009-05-14 10:05:58 +04:00
return - ENOMEM ;
2011-03-13 18:18:58 +03:00
dao - > ops - > clear_left_input ( dao ) ;
2009-05-14 10:05:58 +04:00
/* Program master and conjugate resources */
input - > ops - > master ( input ) ;
daio - > rscl . ops - > master ( & daio - > rscl ) ;
for ( i = 0 ; i < daio - > rscl . msr ; i + + , entry + + ) {
entry - > slot = input - > ops - > output_slot ( input ) ;
entry - > user = entry - > addr = daio - > rscl . ops - > index ( & daio - > rscl ) ;
dao - > mgr - > imap_add ( dao - > mgr , entry ) ;
dao - > imappers [ i ] = entry ;
input - > ops - > next_conj ( input ) ;
daio - > rscl . ops - > next_conj ( & daio - > rscl ) ;
}
input - > ops - > master ( input ) ;
daio - > rscl . ops - > master ( & daio - > rscl ) ;
return 0 ;
}
static int dao_set_right_input ( struct dao * dao , struct rsc * input )
{
2009-06-08 16:57:57 +04:00
struct imapper * entry ;
2009-05-14 10:05:58 +04:00
struct daio * daio = & dao - > daio ;
2009-06-08 16:57:57 +04:00
int i ;
2009-05-14 10:05:58 +04:00
entry = kzalloc ( ( sizeof ( * entry ) * daio - > rscr . msr ) , GFP_KERNEL ) ;
2009-07-22 19:12:34 +04:00
if ( ! entry )
2009-05-14 10:05:58 +04:00
return - ENOMEM ;
2011-03-13 18:18:58 +03:00
dao - > ops - > clear_right_input ( dao ) ;
2009-05-14 10:05:58 +04:00
/* Program master and conjugate resources */
input - > ops - > master ( input ) ;
daio - > rscr . ops - > master ( & daio - > rscr ) ;
for ( i = 0 ; i < daio - > rscr . msr ; i + + , entry + + ) {
entry - > slot = input - > ops - > output_slot ( input ) ;
entry - > user = entry - > addr = daio - > rscr . ops - > index ( & daio - > rscr ) ;
dao - > mgr - > imap_add ( dao - > mgr , entry ) ;
dao - > imappers [ daio - > rscl . msr + i ] = entry ;
input - > ops - > next_conj ( input ) ;
daio - > rscr . ops - > next_conj ( & daio - > rscr ) ;
}
input - > ops - > master ( input ) ;
daio - > rscr . ops - > master ( & daio - > rscr ) ;
return 0 ;
}
static int dao_clear_left_input ( struct dao * dao )
{
2009-06-08 16:57:57 +04:00
struct imapper * entry ;
2009-05-14 10:05:58 +04:00
struct daio * daio = & dao - > daio ;
2009-06-08 16:57:57 +04:00
int i ;
2009-05-14 10:05:58 +04:00
2009-07-22 19:12:34 +04:00
if ( ! dao - > imappers [ 0 ] )
2009-05-14 10:05:58 +04:00
return 0 ;
entry = dao - > imappers [ 0 ] ;
dao - > mgr - > imap_delete ( dao - > mgr , entry ) ;
/* Program conjugate resources */
for ( i = 1 ; i < daio - > rscl . msr ; i + + ) {
entry = dao - > imappers [ i ] ;
dao - > mgr - > imap_delete ( dao - > mgr , entry ) ;
dao - > imappers [ i ] = NULL ;
}
kfree ( dao - > imappers [ 0 ] ) ;
dao - > imappers [ 0 ] = NULL ;
return 0 ;
}
static int dao_clear_right_input ( struct dao * dao )
{
2009-06-08 16:57:57 +04:00
struct imapper * entry ;
2009-05-14 10:05:58 +04:00
struct daio * daio = & dao - > daio ;
2009-06-08 16:57:57 +04:00
int i ;
2009-05-14 10:05:58 +04:00
2009-07-22 19:12:34 +04:00
if ( ! dao - > imappers [ daio - > rscl . msr ] )
2009-05-14 10:05:58 +04:00
return 0 ;
entry = dao - > imappers [ daio - > rscl . msr ] ;
dao - > mgr - > imap_delete ( dao - > mgr , entry ) ;
/* Program conjugate resources */
for ( i = 1 ; i < daio - > rscr . msr ; i + + ) {
entry = dao - > imappers [ daio - > rscl . msr + i ] ;
dao - > mgr - > imap_delete ( dao - > mgr , entry ) ;
dao - > imappers [ daio - > rscl . msr + i ] = NULL ;
}
kfree ( dao - > imappers [ daio - > rscl . msr ] ) ;
dao - > imappers [ daio - > rscl . msr ] = NULL ;
return 0 ;
}
2015-11-09 01:40:41 +03:00
static const struct dao_rsc_ops dao_ops = {
2009-05-14 10:05:58 +04:00
. set_spos = dao_spdif_set_spos ,
. commit_write = dao_commit_write ,
. get_spos = dao_spdif_get_spos ,
. reinit = dao_rsc_reinit ,
. set_left_input = dao_set_left_input ,
. set_right_input = dao_set_right_input ,
. clear_left_input = dao_clear_left_input ,
. clear_right_input = dao_clear_right_input ,
} ;
static int dai_set_srt_srcl ( struct dai * dai , struct rsc * src )
{
src - > ops - > master ( src ) ;
2014-09-29 13:03:23 +04:00
dai - > hw - > dai_srt_set_srcm ( dai - > ctrl_blk , src - > ops - > index ( src ) ) ;
2009-05-14 10:05:58 +04:00
return 0 ;
}
static int dai_set_srt_srcr ( struct dai * dai , struct rsc * src )
{
src - > ops - > master ( src ) ;
2014-09-29 13:03:23 +04:00
dai - > hw - > dai_srt_set_srco ( dai - > ctrl_blk , src - > ops - > index ( src ) ) ;
2009-05-14 10:05:58 +04:00
return 0 ;
}
static int dai_set_srt_msr ( struct dai * dai , unsigned int msr )
{
2009-06-08 16:57:57 +04:00
unsigned int rsr ;
2009-05-14 10:05:58 +04:00
for ( rsr = 0 ; msr > 1 ; msr > > = 1 )
rsr + + ;
2014-09-29 13:03:23 +04:00
dai - > hw - > dai_srt_set_rsr ( dai - > ctrl_blk , rsr ) ;
2009-05-14 10:05:58 +04:00
return 0 ;
}
static int dai_set_enb_src ( struct dai * dai , unsigned int enb )
{
2014-09-29 13:03:23 +04:00
dai - > hw - > dai_srt_set_ec ( dai - > ctrl_blk , enb ) ;
2009-05-14 10:05:58 +04:00
return 0 ;
}
static int dai_set_enb_srt ( struct dai * dai , unsigned int enb )
{
2014-09-29 13:03:23 +04:00
dai - > hw - > dai_srt_set_et ( dai - > ctrl_blk , enb ) ;
2009-05-14 10:05:58 +04:00
return 0 ;
}
static int dai_commit_write ( struct dai * dai )
{
2014-09-29 13:03:23 +04:00
dai - > hw - > dai_commit_write ( dai - > hw ,
2009-05-14 10:05:58 +04:00
daio_device_index ( dai - > daio . type , dai - > hw ) , dai - > ctrl_blk ) ;
return 0 ;
}
2015-11-09 01:40:41 +03:00
static const struct dai_rsc_ops dai_ops = {
2009-05-14 10:05:58 +04:00
. set_srt_srcl = dai_set_srt_srcl ,
. set_srt_srcr = dai_set_srt_srcr ,
. set_srt_msr = dai_set_srt_msr ,
. set_enb_src = dai_set_enb_src ,
. set_enb_srt = dai_set_enb_srt ,
. commit_write = dai_commit_write ,
} ;
static int daio_rsc_init ( struct daio * daio ,
const struct daio_desc * desc ,
2014-09-29 13:03:21 +04:00
struct hw * hw )
2009-05-14 10:05:58 +04:00
{
2009-06-08 16:57:57 +04:00
int err ;
unsigned int idx_l , idx_r ;
2009-05-14 10:05:58 +04:00
2014-09-29 13:03:23 +04:00
switch ( hw - > chip_type ) {
2009-05-14 10:05:58 +04:00
case ATC20K1 :
idx_l = idx_20k1 [ desc - > type ] . left ;
idx_r = idx_20k1 [ desc - > type ] . right ;
break ;
case ATC20K2 :
idx_l = idx_20k2 [ desc - > type ] . left ;
idx_r = idx_20k2 [ desc - > type ] . right ;
break ;
default :
return - EINVAL ;
}
err = rsc_init ( & daio - > rscl , idx_l , DAIO , desc - > msr , hw ) ;
if ( err )
return err ;
err = rsc_init ( & daio - > rscr , idx_r , DAIO , desc - > msr , hw ) ;
if ( err )
goto error1 ;
/* Set daio->rscl/r->ops to daio specific ones */
if ( desc - > type < = DAIO_OUT_MAX ) {
daio - > rscl . ops = daio - > rscr . ops = & daio_out_rsc_ops ;
} else {
2014-09-29 13:03:23 +04:00
switch ( hw - > chip_type ) {
2009-05-14 10:05:58 +04:00
case ATC20K1 :
daio - > rscl . ops = daio - > rscr . ops = & daio_in_rsc_ops_20k1 ;
break ;
case ATC20K2 :
daio - > rscl . ops = daio - > rscr . ops = & daio_in_rsc_ops_20k2 ;
break ;
default :
break ;
}
}
daio - > type = desc - > type ;
return 0 ;
error1 :
rsc_uninit ( & daio - > rscl ) ;
return err ;
}
static int daio_rsc_uninit ( struct daio * daio )
{
rsc_uninit ( & daio - > rscl ) ;
rsc_uninit ( & daio - > rscr ) ;
return 0 ;
}
static int dao_rsc_init ( struct dao * dao ,
const struct daio_desc * desc ,
struct daio_mgr * mgr )
{
struct hw * hw = mgr - > mgr . hw ;
2009-06-08 16:57:57 +04:00
unsigned int conf ;
int err ;
2009-05-14 10:05:58 +04:00
err = daio_rsc_init ( & dao - > daio , desc , mgr - > mgr . hw ) ;
if ( err )
return err ;
treewide: kzalloc() -> kcalloc()
The kzalloc() function has a 2-factor argument form, kcalloc(). This
patch replaces cases of:
kzalloc(a * b, gfp)
with:
kcalloc(a * b, gfp)
as well as handling cases of:
kzalloc(a * b * c, gfp)
with:
kzalloc(array3_size(a, b, c), gfp)
as it's slightly less ugly than:
kzalloc_array(array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
kzalloc(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.
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
type TYPE;
expression THING, E;
@@
(
kzalloc(
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
kzalloc(
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression COUNT;
typedef u8;
typedef __u8;
@@
(
kzalloc(
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(char) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
identifier SIZE, COUNT;
@@
- kzalloc
+ kcalloc
(
- SIZE * COUNT
+ COUNT, SIZE
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
kzalloc(
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
kzalloc(
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kzalloc(
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
identifier STRIDE, SIZE, COUNT;
@@
(
kzalloc(
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- 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 E1, E2, E3;
constant C1, C2, C3;
@@
(
kzalloc(C1 * C2 * C3, ...)
|
kzalloc(
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- 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 THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@
(
kzalloc(sizeof(THING) * C2, ...)
|
kzalloc(sizeof(TYPE) * C2, ...)
|
kzalloc(C1 * C2 * C3, ...)
|
kzalloc(C1 * C2, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- (E1) * E2
+ E1, E2
, ...)
|
- kzalloc
+ kcalloc
(
- (E1) * (E2)
+ E1, E2
, ...)
|
- kzalloc
+ kcalloc
(
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-13 00:03:40 +03:00
dao - > imappers = kzalloc ( array3_size ( sizeof ( void * ) , desc - > msr , 2 ) ,
GFP_KERNEL ) ;
2009-07-22 19:12:34 +04:00
if ( ! dao - > imappers ) {
2009-05-14 10:05:58 +04:00
err = - ENOMEM ;
goto error1 ;
}
dao - > ops = & dao_ops ;
dao - > mgr = mgr ;
dao - > hw = hw ;
err = hw - > dao_get_ctrl_blk ( & dao - > ctrl_blk ) ;
if ( err )
goto error2 ;
hw - > daio_mgr_dsb_dao ( mgr - > mgr . ctrl_blk ,
daio_device_index ( dao - > daio . type , hw ) ) ;
hw - > daio_mgr_commit_write ( hw , mgr - > mgr . ctrl_blk ) ;
2009-06-08 16:57:57 +04:00
conf = ( desc - > msr & 0x7 ) | ( desc - > passthru < < 3 ) ;
2009-05-14 10:05:58 +04:00
hw - > daio_mgr_dao_init ( mgr - > mgr . ctrl_blk ,
daio_device_index ( dao - > daio . type , hw ) , conf ) ;
hw - > daio_mgr_enb_dao ( mgr - > mgr . ctrl_blk ,
daio_device_index ( dao - > daio . type , hw ) ) ;
hw - > daio_mgr_commit_write ( hw , mgr - > mgr . ctrl_blk ) ;
return 0 ;
error2 :
kfree ( dao - > imappers ) ;
dao - > imappers = NULL ;
error1 :
daio_rsc_uninit ( & dao - > daio ) ;
return err ;
}
static int dao_rsc_uninit ( struct dao * dao )
{
2009-07-22 19:12:34 +04:00
if ( dao - > imappers ) {
if ( dao - > imappers [ 0 ] )
2009-05-14 10:05:58 +04:00
dao_clear_left_input ( dao ) ;
2009-07-22 19:12:34 +04:00
if ( dao - > imappers [ dao - > daio . rscl . msr ] )
2009-05-14 10:05:58 +04:00
dao_clear_right_input ( dao ) ;
kfree ( dao - > imappers ) ;
dao - > imappers = NULL ;
}
2014-09-29 13:03:23 +04:00
dao - > hw - > dao_put_ctrl_blk ( dao - > ctrl_blk ) ;
2009-05-14 10:05:58 +04:00
dao - > hw = dao - > ctrl_blk = NULL ;
daio_rsc_uninit ( & dao - > daio ) ;
return 0 ;
}
static int dao_rsc_reinit ( struct dao * dao , const struct dao_desc * desc )
{
struct daio_mgr * mgr = dao - > mgr ;
struct daio_desc dsc = { 0 } ;
dsc . type = dao - > daio . type ;
dsc . msr = desc - > msr ;
dsc . passthru = desc - > passthru ;
dao_rsc_uninit ( dao ) ;
return dao_rsc_init ( dao , & dsc , mgr ) ;
}
static int dai_rsc_init ( struct dai * dai ,
const struct daio_desc * desc ,
struct daio_mgr * mgr )
{
2009-06-08 16:57:57 +04:00
int err ;
2009-05-14 10:05:58 +04:00
struct hw * hw = mgr - > mgr . hw ;
2009-06-08 16:57:57 +04:00
unsigned int rsr , msr ;
2009-05-14 10:05:58 +04:00
err = daio_rsc_init ( & dai - > daio , desc , mgr - > mgr . hw ) ;
if ( err )
return err ;
dai - > ops = & dai_ops ;
dai - > hw = mgr - > mgr . hw ;
err = hw - > dai_get_ctrl_blk ( & dai - > ctrl_blk ) ;
if ( err )
goto error1 ;
for ( rsr = 0 , msr = desc - > msr ; msr > 1 ; msr > > = 1 )
rsr + + ;
hw - > dai_srt_set_rsr ( dai - > ctrl_blk , rsr ) ;
hw - > dai_srt_set_drat ( dai - > ctrl_blk , 0 ) ;
/* default to disabling control of a SRC */
hw - > dai_srt_set_ec ( dai - > ctrl_blk , 0 ) ;
hw - > dai_srt_set_et ( dai - > ctrl_blk , 0 ) ; /* default to disabling SRT */
hw - > dai_commit_write ( hw ,
daio_device_index ( dai - > daio . type , dai - > hw ) , dai - > ctrl_blk ) ;
return 0 ;
error1 :
daio_rsc_uninit ( & dai - > daio ) ;
return err ;
}
static int dai_rsc_uninit ( struct dai * dai )
{
2014-09-29 13:03:23 +04:00
dai - > hw - > dai_put_ctrl_blk ( dai - > ctrl_blk ) ;
2009-05-14 10:05:58 +04:00
dai - > hw = dai - > ctrl_blk = NULL ;
daio_rsc_uninit ( & dai - > daio ) ;
return 0 ;
}
static int daio_mgr_get_rsc ( struct rsc_mgr * mgr , enum DAIOTYP type )
{
2011-06-11 12:02:06 +04:00
if ( ( ( struct daio_usage * ) mgr - > rscs ) - > data & ( 0x1 < < type ) )
2009-05-14 10:05:58 +04:00
return - ENOENT ;
2011-06-11 12:02:06 +04:00
( ( struct daio_usage * ) mgr - > rscs ) - > data | = ( 0x1 < < type ) ;
2009-05-14 10:05:58 +04:00
return 0 ;
}
static int daio_mgr_put_rsc ( struct rsc_mgr * mgr , enum DAIOTYP type )
{
2011-06-11 12:02:06 +04:00
( ( struct daio_usage * ) mgr - > rscs ) - > data & = ~ ( 0x1 < < type ) ;
2009-05-14 10:05:58 +04:00
return 0 ;
}
static int get_daio_rsc ( struct daio_mgr * mgr ,
const struct daio_desc * desc ,
struct daio * * rdaio )
{
2009-06-08 16:57:57 +04:00
int err ;
2009-05-14 10:05:58 +04:00
unsigned long flags ;
* rdaio = NULL ;
/* Check whether there are sufficient daio resources to meet request. */
spin_lock_irqsave ( & mgr - > mgr_lock , flags ) ;
err = daio_mgr_get_rsc ( & mgr - > mgr , desc - > type ) ;
spin_unlock_irqrestore ( & mgr - > mgr_lock , flags ) ;
if ( err ) {
2014-09-29 13:03:26 +04:00
dev_err ( mgr - > card - > dev ,
" Can't meet DAIO resource request! \n " ) ;
2009-05-14 10:05:58 +04:00
return err ;
}
2014-12-03 20:59:31 +03:00
err = - ENOMEM ;
2009-05-14 10:05:58 +04:00
/* Allocate mem for daio resource */
if ( desc - > type < = DAIO_OUT_MAX ) {
2014-12-03 20:59:31 +03:00
struct dao * dao = kzalloc ( sizeof ( * dao ) , GFP_KERNEL ) ;
if ( ! dao )
2009-05-14 10:05:58 +04:00
goto error ;
2014-12-03 20:59:31 +03:00
2009-05-14 10:05:58 +04:00
err = dao_rsc_init ( dao , desc , mgr ) ;
2014-12-03 20:59:31 +03:00
if ( err ) {
kfree ( dao ) ;
2009-05-14 10:05:58 +04:00
goto error ;
2014-12-03 20:59:31 +03:00
}
2009-05-14 10:05:58 +04:00
* rdaio = & dao - > daio ;
} else {
2014-12-03 20:59:31 +03:00
struct dai * dai = kzalloc ( sizeof ( * dai ) , GFP_KERNEL ) ;
if ( ! dai )
2009-05-14 10:05:58 +04:00
goto error ;
2014-12-03 20:59:31 +03:00
2009-05-14 10:05:58 +04:00
err = dai_rsc_init ( dai , desc , mgr ) ;
2014-12-03 20:59:31 +03:00
if ( err ) {
kfree ( dai ) ;
2009-05-14 10:05:58 +04:00
goto error ;
2014-12-03 20:59:31 +03:00
}
2009-05-14 10:05:58 +04:00
* rdaio = & dai - > daio ;
}
mgr - > daio_enable ( mgr , * rdaio ) ;
mgr - > commit_write ( mgr ) ;
return 0 ;
error :
spin_lock_irqsave ( & mgr - > mgr_lock , flags ) ;
daio_mgr_put_rsc ( & mgr - > mgr , desc - > type ) ;
spin_unlock_irqrestore ( & mgr - > mgr_lock , flags ) ;
return err ;
}
static int put_daio_rsc ( struct daio_mgr * mgr , struct daio * daio )
{
unsigned long flags ;
mgr - > daio_disable ( mgr , daio ) ;
mgr - > commit_write ( mgr ) ;
spin_lock_irqsave ( & mgr - > mgr_lock , flags ) ;
daio_mgr_put_rsc ( & mgr - > mgr , daio - > type ) ;
spin_unlock_irqrestore ( & mgr - > mgr_lock , flags ) ;
if ( daio - > type < = DAIO_OUT_MAX ) {
dao_rsc_uninit ( container_of ( daio , struct dao , daio ) ) ;
kfree ( container_of ( daio , struct dao , daio ) ) ;
} else {
dai_rsc_uninit ( container_of ( daio , struct dai , daio ) ) ;
kfree ( container_of ( daio , struct dai , daio ) ) ;
}
return 0 ;
}
static int daio_mgr_enb_daio ( struct daio_mgr * mgr , struct daio * daio )
{
struct hw * hw = mgr - > mgr . hw ;
if ( DAIO_OUT_MAX > = daio - > type ) {
hw - > daio_mgr_enb_dao ( mgr - > mgr . ctrl_blk ,
daio_device_index ( daio - > type , hw ) ) ;
} else {
hw - > daio_mgr_enb_dai ( mgr - > mgr . ctrl_blk ,
daio_device_index ( daio - > type , hw ) ) ;
}
return 0 ;
}
static int daio_mgr_dsb_daio ( struct daio_mgr * mgr , struct daio * daio )
{
struct hw * hw = mgr - > mgr . hw ;
if ( DAIO_OUT_MAX > = daio - > type ) {
hw - > daio_mgr_dsb_dao ( mgr - > mgr . ctrl_blk ,
daio_device_index ( daio - > type , hw ) ) ;
} else {
hw - > daio_mgr_dsb_dai ( mgr - > mgr . ctrl_blk ,
daio_device_index ( daio - > type , hw ) ) ;
}
return 0 ;
}
static int daio_map_op ( void * data , struct imapper * entry )
{
struct rsc_mgr * mgr = & ( ( struct daio_mgr * ) data ) - > mgr ;
struct hw * hw = mgr - > hw ;
hw - > daio_mgr_set_imaparc ( mgr - > ctrl_blk , entry - > slot ) ;
hw - > daio_mgr_set_imapnxt ( mgr - > ctrl_blk , entry - > next ) ;
hw - > daio_mgr_set_imapaddr ( mgr - > ctrl_blk , entry - > addr ) ;
hw - > daio_mgr_commit_write ( mgr - > hw , mgr - > ctrl_blk ) ;
return 0 ;
}
static int daio_imap_add ( struct daio_mgr * mgr , struct imapper * entry )
{
unsigned long flags ;
2009-06-08 16:57:57 +04:00
int err ;
2009-05-14 10:05:58 +04:00
spin_lock_irqsave ( & mgr - > imap_lock , flags ) ;
2009-07-22 19:12:34 +04:00
if ( ! entry - > addr & & mgr - > init_imap_added ) {
2009-05-14 10:05:58 +04:00
input_mapper_delete ( & mgr - > imappers , mgr - > init_imap ,
daio_map_op , mgr ) ;
mgr - > init_imap_added = 0 ;
}
err = input_mapper_add ( & mgr - > imappers , entry , daio_map_op , mgr ) ;
spin_unlock_irqrestore ( & mgr - > imap_lock , flags ) ;
return err ;
}
static int daio_imap_delete ( struct daio_mgr * mgr , struct imapper * entry )
{
unsigned long flags ;
2009-06-08 16:57:57 +04:00
int err ;
2009-05-14 10:05:58 +04:00
spin_lock_irqsave ( & mgr - > imap_lock , flags ) ;
err = input_mapper_delete ( & mgr - > imappers , entry , daio_map_op , mgr ) ;
if ( list_empty ( & mgr - > imappers ) ) {
input_mapper_add ( & mgr - > imappers , mgr - > init_imap ,
daio_map_op , mgr ) ;
mgr - > init_imap_added = 1 ;
}
spin_unlock_irqrestore ( & mgr - > imap_lock , flags ) ;
return err ;
}
static int daio_mgr_commit_write ( struct daio_mgr * mgr )
{
struct hw * hw = mgr - > mgr . hw ;
hw - > daio_mgr_commit_write ( hw , mgr - > mgr . ctrl_blk ) ;
return 0 ;
}
2014-09-29 13:03:21 +04:00
int daio_mgr_create ( struct hw * hw , struct daio_mgr * * rdaio_mgr )
2009-05-14 10:05:58 +04:00
{
2009-06-08 16:57:57 +04:00
int err , i ;
2009-05-14 10:05:58 +04:00
struct daio_mgr * daio_mgr ;
struct imapper * entry ;
* rdaio_mgr = NULL ;
daio_mgr = kzalloc ( sizeof ( * daio_mgr ) , GFP_KERNEL ) ;
2009-07-22 19:12:34 +04:00
if ( ! daio_mgr )
2009-05-14 10:05:58 +04:00
return - ENOMEM ;
2011-06-11 12:02:06 +04:00
err = rsc_mgr_init ( & daio_mgr - > mgr , DAIO , NUM_DAIOTYP , hw ) ;
2009-05-14 10:05:58 +04:00
if ( err )
goto error1 ;
spin_lock_init ( & daio_mgr - > mgr_lock ) ;
spin_lock_init ( & daio_mgr - > imap_lock ) ;
INIT_LIST_HEAD ( & daio_mgr - > imappers ) ;
entry = kzalloc ( sizeof ( * entry ) , GFP_KERNEL ) ;
2009-07-22 19:12:34 +04:00
if ( ! entry ) {
2009-05-14 10:05:58 +04:00
err = - ENOMEM ;
goto error2 ;
}
entry - > slot = entry - > addr = entry - > next = entry - > user = 0 ;
list_add ( & entry - > list , & daio_mgr - > imappers ) ;
daio_mgr - > init_imap = entry ;
daio_mgr - > init_imap_added = 1 ;
daio_mgr - > get_daio = get_daio_rsc ;
daio_mgr - > put_daio = put_daio_rsc ;
daio_mgr - > daio_enable = daio_mgr_enb_daio ;
daio_mgr - > daio_disable = daio_mgr_dsb_daio ;
daio_mgr - > imap_add = daio_imap_add ;
daio_mgr - > imap_delete = daio_imap_delete ;
daio_mgr - > commit_write = daio_mgr_commit_write ;
2014-09-29 13:03:24 +04:00
daio_mgr - > card = hw - > card ;
2009-05-14 10:05:58 +04:00
for ( i = 0 ; i < 8 ; i + + ) {
2014-09-29 13:03:23 +04:00
hw - > daio_mgr_dsb_dao ( daio_mgr - > mgr . ctrl_blk , i ) ;
hw - > daio_mgr_dsb_dai ( daio_mgr - > mgr . ctrl_blk , i ) ;
2009-05-14 10:05:58 +04:00
}
2014-09-29 13:03:23 +04:00
hw - > daio_mgr_commit_write ( hw , daio_mgr - > mgr . ctrl_blk ) ;
2009-05-14 10:05:58 +04:00
* rdaio_mgr = daio_mgr ;
return 0 ;
error2 :
rsc_mgr_uninit ( & daio_mgr - > mgr ) ;
error1 :
kfree ( daio_mgr ) ;
return err ;
}
int daio_mgr_destroy ( struct daio_mgr * daio_mgr )
{
unsigned long flags ;
/* free daio input mapper list */
spin_lock_irqsave ( & daio_mgr - > imap_lock , flags ) ;
free_input_mapper_list ( & daio_mgr - > imappers ) ;
spin_unlock_irqrestore ( & daio_mgr - > imap_lock , flags ) ;
rsc_mgr_uninit ( & daio_mgr - > mgr ) ;
kfree ( daio_mgr ) ;
return 0 ;
}