2017-08-18 03:53:35 +03:00
/*
* This file is subject to the terms and conditions of the GNU General Public
* License . See the file " COPYING " in the main directory of this archive
* for more details .
*
* Copyright ( C ) 2016 , 2017 Cavium Inc .
*/
# include <linux/bitops.h>
# include <linux/gpio/driver.h>
# include <linux/interrupt.h>
# include <linux/io.h>
# include <linux/irq.h>
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/pci.h>
# include <linux/spinlock.h>
2020-01-14 11:28:21 +03:00
# include <asm-generic/msi.h>
2017-08-18 03:53:35 +03:00
# define GPIO_RX_DAT 0x0
# define GPIO_TX_SET 0x8
# define GPIO_TX_CLR 0x10
# define GPIO_CONST 0x90
# define GPIO_CONST_GPIOS_MASK 0xff
# define GPIO_BIT_CFG 0x400
# define GPIO_BIT_CFG_TX_OE BIT(0)
# define GPIO_BIT_CFG_PIN_XOR BIT(1)
# define GPIO_BIT_CFG_INT_EN BIT(2)
# define GPIO_BIT_CFG_INT_TYPE BIT(3)
# define GPIO_BIT_CFG_FIL_MASK GENMASK(11, 4)
# define GPIO_BIT_CFG_FIL_CNT_SHIFT 4
# define GPIO_BIT_CFG_FIL_SEL_SHIFT 8
# define GPIO_BIT_CFG_TX_OD BIT(12)
# define GPIO_BIT_CFG_PIN_SEL_MASK GENMASK(25, 16)
# define GPIO_INTR 0x800
# define GPIO_INTR_INTR BIT(0)
# define GPIO_INTR_INTR_W1S BIT(1)
# define GPIO_INTR_ENA_W1C BIT(2)
# define GPIO_INTR_ENA_W1S BIT(3)
# define GPIO_2ND_BANK 0x1400
# define GLITCH_FILTER_400NS ((4u << GPIO_BIT_CFG_FIL_SEL_SHIFT) | \
( 9u < < GPIO_BIT_CFG_FIL_CNT_SHIFT ) )
struct thunderx_gpio ;
struct thunderx_line {
struct thunderx_gpio * txgpio ;
unsigned int line ;
unsigned int fil_bits ;
} ;
struct thunderx_gpio {
struct gpio_chip chip ;
u8 __iomem * register_base ;
struct msix_entry * msix_entries ; /* per line MSI-X */
struct thunderx_line * line_entries ; /* per line irq info */
raw_spinlock_t lock ;
unsigned long invert_mask [ 2 ] ;
unsigned long od_mask [ 2 ] ;
int base_msi ;
} ;
static unsigned int bit_cfg_reg ( unsigned int line )
{
return 8 * line + GPIO_BIT_CFG ;
}
static unsigned int intr_reg ( unsigned int line )
{
return 8 * line + GPIO_INTR ;
}
static bool thunderx_gpio_is_gpio_nowarn ( struct thunderx_gpio * txgpio ,
unsigned int line )
{
u64 bit_cfg = readq ( txgpio - > register_base + bit_cfg_reg ( line ) ) ;
return ( bit_cfg & GPIO_BIT_CFG_PIN_SEL_MASK ) = = 0 ;
}
/*
* Check ( and WARN ) that the pin is available for GPIO . We will not
* allow modification of the state of non - GPIO pins from this driver .
*/
static bool thunderx_gpio_is_gpio ( struct thunderx_gpio * txgpio ,
unsigned int line )
{
bool rv = thunderx_gpio_is_gpio_nowarn ( txgpio , line ) ;
WARN_RATELIMIT ( ! rv , " Pin %d not available for GPIO \n " , line ) ;
return rv ;
}
static int thunderx_gpio_request ( struct gpio_chip * chip , unsigned int line )
{
struct thunderx_gpio * txgpio = gpiochip_get_data ( chip ) ;
return thunderx_gpio_is_gpio ( txgpio , line ) ? 0 : - EIO ;
}
static int thunderx_gpio_dir_in ( struct gpio_chip * chip , unsigned int line )
{
struct thunderx_gpio * txgpio = gpiochip_get_data ( chip ) ;
if ( ! thunderx_gpio_is_gpio ( txgpio , line ) )
return - EIO ;
raw_spin_lock ( & txgpio - > lock ) ;
clear_bit ( line , txgpio - > invert_mask ) ;
clear_bit ( line , txgpio - > od_mask ) ;
writeq ( txgpio - > line_entries [ line ] . fil_bits ,
txgpio - > register_base + bit_cfg_reg ( line ) ) ;
raw_spin_unlock ( & txgpio - > lock ) ;
return 0 ;
}
static void thunderx_gpio_set ( struct gpio_chip * chip , unsigned int line ,
int value )
{
struct thunderx_gpio * txgpio = gpiochip_get_data ( chip ) ;
int bank = line / 64 ;
int bank_bit = line % 64 ;
void __iomem * reg = txgpio - > register_base +
( bank * GPIO_2ND_BANK ) + ( value ? GPIO_TX_SET : GPIO_TX_CLR ) ;
writeq ( BIT_ULL ( bank_bit ) , reg ) ;
}
static int thunderx_gpio_dir_out ( struct gpio_chip * chip , unsigned int line ,
int value )
{
struct thunderx_gpio * txgpio = gpiochip_get_data ( chip ) ;
u64 bit_cfg = txgpio - > line_entries [ line ] . fil_bits | GPIO_BIT_CFG_TX_OE ;
if ( ! thunderx_gpio_is_gpio ( txgpio , line ) )
return - EIO ;
raw_spin_lock ( & txgpio - > lock ) ;
thunderx_gpio_set ( chip , line , value ) ;
if ( test_bit ( line , txgpio - > invert_mask ) )
bit_cfg | = GPIO_BIT_CFG_PIN_XOR ;
if ( test_bit ( line , txgpio - > od_mask ) )
bit_cfg | = GPIO_BIT_CFG_TX_OD ;
writeq ( bit_cfg , txgpio - > register_base + bit_cfg_reg ( line ) ) ;
raw_spin_unlock ( & txgpio - > lock ) ;
return 0 ;
}
static int thunderx_gpio_get_direction ( struct gpio_chip * chip , unsigned int line )
{
struct thunderx_gpio * txgpio = gpiochip_get_data ( chip ) ;
u64 bit_cfg ;
if ( ! thunderx_gpio_is_gpio_nowarn ( txgpio , line ) )
/*
* Say it is input for now to avoid WARNing on
* gpiochip_add_data ( ) . We will WARN if someone
* requests it or tries to use it .
*/
return 1 ;
bit_cfg = readq ( txgpio - > register_base + bit_cfg_reg ( line ) ) ;
2019-11-06 11:54:12 +03:00
if ( bit_cfg & GPIO_BIT_CFG_TX_OE )
return GPIO_LINE_DIRECTION_OUT ;
return GPIO_LINE_DIRECTION_IN ;
2017-08-18 03:53:35 +03:00
}
static int thunderx_gpio_set_config ( struct gpio_chip * chip ,
unsigned int line ,
unsigned long cfg )
{
bool orig_invert , orig_od , orig_dat , new_invert , new_od ;
u32 arg , sel ;
u64 bit_cfg ;
int bank = line / 64 ;
int bank_bit = line % 64 ;
int ret = - ENOTSUPP ;
struct thunderx_gpio * txgpio = gpiochip_get_data ( chip ) ;
void __iomem * reg = txgpio - > register_base + ( bank * GPIO_2ND_BANK ) + GPIO_TX_SET ;
if ( ! thunderx_gpio_is_gpio ( txgpio , line ) )
return - EIO ;
raw_spin_lock ( & txgpio - > lock ) ;
orig_invert = test_bit ( line , txgpio - > invert_mask ) ;
new_invert = orig_invert ;
orig_od = test_bit ( line , txgpio - > od_mask ) ;
new_od = orig_od ;
orig_dat = ( ( readq ( reg ) > > bank_bit ) & 1 ) ^ orig_invert ;
bit_cfg = readq ( txgpio - > register_base + bit_cfg_reg ( line ) ) ;
switch ( pinconf_to_config_param ( cfg ) ) {
case PIN_CONFIG_DRIVE_OPEN_DRAIN :
/*
* Weird , setting open - drain mode causes signal
* inversion . Note this so we can compensate in the
* dir_out function .
*/
set_bit ( line , txgpio - > invert_mask ) ;
new_invert = true ;
set_bit ( line , txgpio - > od_mask ) ;
new_od = true ;
ret = 0 ;
break ;
case PIN_CONFIG_DRIVE_PUSH_PULL :
clear_bit ( line , txgpio - > invert_mask ) ;
new_invert = false ;
clear_bit ( line , txgpio - > od_mask ) ;
new_od = false ;
ret = 0 ;
break ;
case PIN_CONFIG_INPUT_DEBOUNCE :
arg = pinconf_to_config_argument ( cfg ) ;
if ( arg > 1228 ) { /* 15 * 2^15 * 2.5nS maximum */
ret = - EINVAL ;
break ;
}
arg * = 400 ; /* scale to 2.5nS clocks. */
sel = 0 ;
while ( arg > 15 ) {
sel + + ;
arg + + ; /* always round up */
arg > > = 1 ;
}
txgpio - > line_entries [ line ] . fil_bits =
( sel < < GPIO_BIT_CFG_FIL_SEL_SHIFT ) |
( arg < < GPIO_BIT_CFG_FIL_CNT_SHIFT ) ;
bit_cfg & = ~ GPIO_BIT_CFG_FIL_MASK ;
bit_cfg | = txgpio - > line_entries [ line ] . fil_bits ;
writeq ( bit_cfg , txgpio - > register_base + bit_cfg_reg ( line ) ) ;
ret = 0 ;
break ;
default :
break ;
}
raw_spin_unlock ( & txgpio - > lock ) ;
/*
* If currently output and OPEN_DRAIN changed , install the new
* settings
*/
if ( ( new_invert ! = orig_invert | | new_od ! = orig_od ) & &
( bit_cfg & GPIO_BIT_CFG_TX_OE ) )
ret = thunderx_gpio_dir_out ( chip , line , orig_dat ^ new_invert ) ;
return ret ;
}
static int thunderx_gpio_get ( struct gpio_chip * chip , unsigned int line )
{
struct thunderx_gpio * txgpio = gpiochip_get_data ( chip ) ;
int bank = line / 64 ;
int bank_bit = line % 64 ;
u64 read_bits = readq ( txgpio - > register_base + ( bank * GPIO_2ND_BANK ) + GPIO_RX_DAT ) ;
u64 masked_bits = read_bits & BIT_ULL ( bank_bit ) ;
if ( test_bit ( line , txgpio - > invert_mask ) )
return masked_bits = = 0 ;
else
return masked_bits ! = 0 ;
}
static void thunderx_gpio_set_multiple ( struct gpio_chip * chip ,
unsigned long * mask ,
unsigned long * bits )
{
int bank ;
u64 set_bits , clear_bits ;
struct thunderx_gpio * txgpio = gpiochip_get_data ( chip ) ;
for ( bank = 0 ; bank < = chip - > ngpio / 64 ; bank + + ) {
set_bits = bits [ bank ] & mask [ bank ] ;
clear_bits = ~ bits [ bank ] & mask [ bank ] ;
writeq ( set_bits , txgpio - > register_base + ( bank * GPIO_2ND_BANK ) + GPIO_TX_SET ) ;
writeq ( clear_bits , txgpio - > register_base + ( bank * GPIO_2ND_BANK ) + GPIO_TX_CLR ) ;
}
}
2020-01-14 11:28:21 +03:00
static void thunderx_gpio_irq_ack ( struct irq_data * d )
2017-08-18 03:53:35 +03:00
{
2020-01-14 11:28:21 +03:00
struct gpio_chip * gc = irq_data_get_irq_chip_data ( d ) ;
struct thunderx_gpio * txgpio = gpiochip_get_data ( gc ) ;
2017-08-18 03:53:35 +03:00
writeq ( GPIO_INTR_INTR ,
2020-01-14 11:28:21 +03:00
txgpio - > register_base + intr_reg ( irqd_to_hwirq ( d ) ) ) ;
2017-08-18 03:53:35 +03:00
}
2020-01-14 11:28:21 +03:00
static void thunderx_gpio_irq_mask ( struct irq_data * d )
2017-08-18 03:53:35 +03:00
{
2020-01-14 11:28:21 +03:00
struct gpio_chip * gc = irq_data_get_irq_chip_data ( d ) ;
struct thunderx_gpio * txgpio = gpiochip_get_data ( gc ) ;
2017-08-18 03:53:35 +03:00
writeq ( GPIO_INTR_ENA_W1C ,
2020-01-14 11:28:21 +03:00
txgpio - > register_base + intr_reg ( irqd_to_hwirq ( d ) ) ) ;
2017-08-18 03:53:35 +03:00
}
2020-01-14 11:28:21 +03:00
static void thunderx_gpio_irq_mask_ack ( struct irq_data * d )
2017-08-18 03:53:35 +03:00
{
2020-01-14 11:28:21 +03:00
struct gpio_chip * gc = irq_data_get_irq_chip_data ( d ) ;
struct thunderx_gpio * txgpio = gpiochip_get_data ( gc ) ;
2017-08-18 03:53:35 +03:00
writeq ( GPIO_INTR_ENA_W1C | GPIO_INTR_INTR ,
2020-01-14 11:28:21 +03:00
txgpio - > register_base + intr_reg ( irqd_to_hwirq ( d ) ) ) ;
2017-08-18 03:53:35 +03:00
}
2020-01-14 11:28:21 +03:00
static void thunderx_gpio_irq_unmask ( struct irq_data * d )
2017-08-18 03:53:35 +03:00
{
2020-01-14 11:28:21 +03:00
struct gpio_chip * gc = irq_data_get_irq_chip_data ( d ) ;
struct thunderx_gpio * txgpio = gpiochip_get_data ( gc ) ;
2017-08-18 03:53:35 +03:00
writeq ( GPIO_INTR_ENA_W1S ,
2020-01-14 11:28:21 +03:00
txgpio - > register_base + intr_reg ( irqd_to_hwirq ( d ) ) ) ;
2017-08-18 03:53:35 +03:00
}
2020-01-14 11:28:21 +03:00
static int thunderx_gpio_irq_set_type ( struct irq_data * d ,
2017-08-18 03:53:35 +03:00
unsigned int flow_type )
{
2020-01-14 11:28:21 +03:00
struct gpio_chip * gc = irq_data_get_irq_chip_data ( d ) ;
struct thunderx_gpio * txgpio = gpiochip_get_data ( gc ) ;
struct thunderx_line * txline =
& txgpio - > line_entries [ irqd_to_hwirq ( d ) ] ;
2017-08-18 03:53:35 +03:00
u64 bit_cfg ;
2020-01-14 11:28:21 +03:00
irqd_set_trigger_type ( d , flow_type ) ;
2017-08-18 03:53:35 +03:00
bit_cfg = txline - > fil_bits | GPIO_BIT_CFG_INT_EN ;
if ( flow_type & IRQ_TYPE_EDGE_BOTH ) {
2020-01-14 11:28:21 +03:00
irq_set_handler_locked ( d , handle_fasteoi_ack_irq ) ;
2017-08-18 03:53:35 +03:00
bit_cfg | = GPIO_BIT_CFG_INT_TYPE ;
} else {
2020-01-14 11:28:21 +03:00
irq_set_handler_locked ( d , handle_fasteoi_mask_irq ) ;
2017-08-18 03:53:35 +03:00
}
raw_spin_lock ( & txgpio - > lock ) ;
if ( flow_type & ( IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW ) ) {
bit_cfg | = GPIO_BIT_CFG_PIN_XOR ;
set_bit ( txline - > line , txgpio - > invert_mask ) ;
} else {
clear_bit ( txline - > line , txgpio - > invert_mask ) ;
}
clear_bit ( txline - > line , txgpio - > od_mask ) ;
writeq ( bit_cfg , txgpio - > register_base + bit_cfg_reg ( txline - > line ) ) ;
raw_spin_unlock ( & txgpio - > lock ) ;
return IRQ_SET_MASK_OK ;
}
static void thunderx_gpio_irq_enable ( struct irq_data * data )
{
irq_chip_enable_parent ( data ) ;
thunderx_gpio_irq_unmask ( data ) ;
}
static void thunderx_gpio_irq_disable ( struct irq_data * data )
{
thunderx_gpio_irq_mask ( data ) ;
irq_chip_disable_parent ( data ) ;
}
/*
* Interrupts are chained from underlying MSI - X vectors . We have
* these irq_chip functions to be able to handle level triggering
* semantics and other acknowledgment tasks associated with the GPIO
* mechanism .
*/
static struct irq_chip thunderx_gpio_irq_chip = {
. name = " GPIO " ,
. irq_enable = thunderx_gpio_irq_enable ,
. irq_disable = thunderx_gpio_irq_disable ,
. irq_ack = thunderx_gpio_irq_ack ,
. irq_mask = thunderx_gpio_irq_mask ,
. irq_mask_ack = thunderx_gpio_irq_mask_ack ,
. irq_unmask = thunderx_gpio_irq_unmask ,
. irq_eoi = irq_chip_eoi_parent ,
. irq_set_affinity = irq_chip_set_affinity_parent ,
. irq_set_type = thunderx_gpio_irq_set_type ,
. flags = IRQCHIP_SET_TYPE_MASKED
} ;
2020-01-14 11:28:21 +03:00
static int thunderx_gpio_child_to_parent_hwirq ( struct gpio_chip * gc ,
unsigned int child ,
unsigned int child_type ,
unsigned int * parent ,
unsigned int * parent_type )
2017-08-18 03:53:35 +03:00
{
2020-01-14 11:28:21 +03:00
struct thunderx_gpio * txgpio = gpiochip_get_data ( gc ) ;
struct irq_data * irqd ;
unsigned int irq ;
2020-01-14 11:28:18 +03:00
2020-01-14 11:28:21 +03:00
irq = txgpio - > msix_entries [ child ] . vector ;
irqd = irq_domain_get_irq_data ( gc - > irq . parent_domain , irq ) ;
if ( ! irqd )
2020-01-14 11:28:18 +03:00
return - EINVAL ;
2020-01-14 11:28:21 +03:00
* parent = irqd_to_hwirq ( irqd ) ;
* parent_type = IRQ_TYPE_LEVEL_HIGH ;
2019-08-08 15:32:40 +03:00
return 0 ;
2017-08-18 03:53:35 +03:00
}
2020-01-14 11:28:21 +03:00
static void * thunderx_gpio_populate_parent_alloc_info ( struct gpio_chip * chip ,
unsigned int parent_hwirq ,
unsigned int parent_type )
2020-01-14 11:28:18 +03:00
{
2020-01-14 11:28:21 +03:00
msi_alloc_info_t * info ;
2020-01-14 11:28:18 +03:00
2020-01-14 11:28:21 +03:00
info = kmalloc ( sizeof ( * info ) , GFP_KERNEL ) ;
if ( ! info )
return NULL ;
2020-01-14 11:28:18 +03:00
2020-01-14 11:28:21 +03:00
info - > hwirq = parent_hwirq ;
return info ;
2020-01-14 11:28:18 +03:00
}
2017-08-18 03:53:35 +03:00
static int thunderx_gpio_probe ( struct pci_dev * pdev ,
const struct pci_device_id * id )
{
void __iomem * const * tbl ;
struct device * dev = & pdev - > dev ;
struct thunderx_gpio * txgpio ;
struct gpio_chip * chip ;
2020-01-14 11:28:21 +03:00
struct gpio_irq_chip * girq ;
2017-08-18 03:53:35 +03:00
int ngpio , i ;
int err = 0 ;
txgpio = devm_kzalloc ( dev , sizeof ( * txgpio ) , GFP_KERNEL ) ;
if ( ! txgpio )
return - ENOMEM ;
raw_spin_lock_init ( & txgpio - > lock ) ;
chip = & txgpio - > chip ;
pci_set_drvdata ( pdev , txgpio ) ;
err = pcim_enable_device ( pdev ) ;
if ( err ) {
dev_err ( dev , " Failed to enable PCI device: err %d \n " , err ) ;
goto out ;
}
err = pcim_iomap_regions ( pdev , 1 < < 0 , KBUILD_MODNAME ) ;
if ( err ) {
dev_err ( dev , " Failed to iomap PCI device: err %d \n " , err ) ;
goto out ;
}
tbl = pcim_iomap_table ( pdev ) ;
txgpio - > register_base = tbl [ 0 ] ;
if ( ! txgpio - > register_base ) {
dev_err ( dev , " Cannot map PCI resource \n " ) ;
err = - ENOMEM ;
goto out ;
}
if ( pdev - > subsystem_device = = 0xa10a ) {
/* CN88XX has no GPIO_CONST register*/
ngpio = 50 ;
txgpio - > base_msi = 48 ;
} else {
u64 c = readq ( txgpio - > register_base + GPIO_CONST ) ;
ngpio = c & GPIO_CONST_GPIOS_MASK ;
txgpio - > base_msi = ( c > > 8 ) & 0xff ;
}
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
txgpio - > msix_entries = devm_kcalloc ( dev ,
2020-01-14 11:28:21 +03:00
ngpio , sizeof ( struct msix_entry ) ,
GFP_KERNEL ) ;
2017-08-18 03:53:35 +03:00
if ( ! txgpio - > msix_entries ) {
err = - ENOMEM ;
goto out ;
}
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
txgpio - > line_entries = devm_kcalloc ( dev ,
ngpio ,
sizeof ( struct thunderx_line ) ,
2017-08-18 03:53:35 +03:00
GFP_KERNEL ) ;
if ( ! txgpio - > line_entries ) {
err = - ENOMEM ;
goto out ;
}
for ( i = 0 ; i < ngpio ; i + + ) {
u64 bit_cfg = readq ( txgpio - > register_base + bit_cfg_reg ( i ) ) ;
txgpio - > msix_entries [ i ] . entry = txgpio - > base_msi + ( 2 * i ) ;
txgpio - > line_entries [ i ] . line = i ;
txgpio - > line_entries [ i ] . txgpio = txgpio ;
/*
* If something has already programmed the pin , use
* the existing glitch filter settings , otherwise go
* to 400 nS .
*/
txgpio - > line_entries [ i ] . fil_bits = bit_cfg ?
( bit_cfg & GPIO_BIT_CFG_FIL_MASK ) : GLITCH_FILTER_400NS ;
if ( ( bit_cfg & GPIO_BIT_CFG_TX_OE ) & & ( bit_cfg & GPIO_BIT_CFG_TX_OD ) )
set_bit ( i , txgpio - > od_mask ) ;
if ( bit_cfg & GPIO_BIT_CFG_PIN_XOR )
set_bit ( i , txgpio - > invert_mask ) ;
}
/* Enable all MSI-X for interrupts on all possible lines. */
err = pci_enable_msix_range ( pdev , txgpio - > msix_entries , ngpio , ngpio ) ;
if ( err < 0 )
goto out ;
chip - > label = KBUILD_MODNAME ;
chip - > parent = dev ;
chip - > owner = THIS_MODULE ;
chip - > request = thunderx_gpio_request ;
chip - > base = - 1 ; /* System allocated */
chip - > can_sleep = false ;
chip - > ngpio = ngpio ;
chip - > get_direction = thunderx_gpio_get_direction ;
chip - > direction_input = thunderx_gpio_dir_in ;
chip - > get = thunderx_gpio_get ;
chip - > direction_output = thunderx_gpio_dir_out ;
chip - > set = thunderx_gpio_set ;
chip - > set_multiple = thunderx_gpio_set_multiple ;
chip - > set_config = thunderx_gpio_set_config ;
2020-01-14 11:28:21 +03:00
girq = & chip - > irq ;
girq - > chip = & thunderx_gpio_irq_chip ;
girq - > fwnode = of_node_to_fwnode ( dev - > of_node ) ;
girq - > parent_domain =
irq_get_irq_data ( txgpio - > msix_entries [ 0 ] . vector ) - > domain ;
girq - > child_to_parent_hwirq = thunderx_gpio_child_to_parent_hwirq ;
girq - > populate_parent_alloc_arg = thunderx_gpio_populate_parent_alloc_info ;
girq - > handler = handle_bad_irq ;
girq - > default_type = IRQ_TYPE_NONE ;
2017-08-18 03:53:35 +03:00
err = devm_gpiochip_add_data ( dev , chip , txgpio ) ;
if ( err )
goto out ;
2020-01-14 11:28:21 +03:00
/* Push on irq_data and the domain for each line. */
for ( i = 0 ; i < ngpio ; i + + ) {
struct irq_fwspec fwspec ;
fwspec . fwnode = of_node_to_fwnode ( dev - > of_node ) ;
fwspec . param_count = 2 ;
fwspec . param [ 0 ] = i ;
fwspec . param [ 1 ] = IRQ_TYPE_NONE ;
err = irq_domain_push_irq ( girq - > domain ,
txgpio - > msix_entries [ i ] . vector ,
& fwspec ) ;
if ( err < 0 )
dev_err ( dev , " irq_domain_push_irq: %d \n " , err ) ;
}
2017-08-18 03:53:35 +03:00
dev_info ( dev , " ThunderX GPIO: %d lines with base %d. \n " ,
ngpio , chip - > base ) ;
return 0 ;
out :
pci_set_drvdata ( pdev , NULL ) ;
return err ;
}
static void thunderx_gpio_remove ( struct pci_dev * pdev )
{
int i ;
struct thunderx_gpio * txgpio = pci_get_drvdata ( pdev ) ;
for ( i = 0 ; i < txgpio - > chip . ngpio ; i + + )
2020-01-14 11:28:21 +03:00
irq_domain_pop_irq ( txgpio - > chip . irq . domain ,
2017-08-18 03:53:35 +03:00
txgpio - > msix_entries [ i ] . vector ) ;
2020-01-14 11:28:21 +03:00
irq_domain_remove ( txgpio - > chip . irq . domain ) ;
2017-08-18 03:53:35 +03:00
pci_set_drvdata ( pdev , NULL ) ;
}
static const struct pci_device_id thunderx_gpio_id_table [ ] = {
{ PCI_DEVICE ( PCI_VENDOR_ID_CAVIUM , 0xA00A ) } ,
{ 0 , } /* end of table */
} ;
MODULE_DEVICE_TABLE ( pci , thunderx_gpio_id_table ) ;
static struct pci_driver thunderx_gpio_driver = {
. name = KBUILD_MODNAME ,
. id_table = thunderx_gpio_id_table ,
. probe = thunderx_gpio_probe ,
. remove = thunderx_gpio_remove ,
} ;
module_pci_driver ( thunderx_gpio_driver ) ;
MODULE_DESCRIPTION ( " Cavium Inc. ThunderX/OCTEON-TX GPIO Driver " ) ;
MODULE_LICENSE ( " GPL " ) ;