2019-06-01 11:08:55 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2012-05-09 17:27:20 +04:00
/**
* tpci200 . c
*
* driver for the TEWS TPCI - 200 device
2012-11-16 19:19:58 +04:00
*
* Copyright ( C ) 2009 - 2012 CERN ( www . cern . ch )
* Author : Nicolas Serafini , EIC2 SA
* Author : Samuel Iglesias Gonsalvez < siglesias @ igalia . com >
2012-05-09 17:27:20 +04:00
*/
# include <linux/module.h>
2012-10-22 11:36:48 +04:00
# include <linux/slab.h>
2012-05-09 17:27:20 +04:00
# include "tpci200.h"
2012-09-27 14:37:30 +04:00
static const u16 tpci200_status_timeout [ ] = {
2012-09-11 15:34:56 +04:00
TPCI200_A_TIMEOUT ,
TPCI200_B_TIMEOUT ,
TPCI200_C_TIMEOUT ,
TPCI200_D_TIMEOUT ,
} ;
2012-09-27 14:37:30 +04:00
static const u16 tpci200_status_error [ ] = {
2012-09-11 15:34:56 +04:00
TPCI200_A_ERROR ,
TPCI200_B_ERROR ,
TPCI200_C_ERROR ,
TPCI200_D_ERROR ,
} ;
2012-09-27 14:37:31 +04:00
static const size_t tpci200_space_size [ IPACK_SPACE_COUNT ] = {
2012-09-27 14:37:36 +04:00
[ IPACK_IO_SPACE ] = TPCI200_IO_SPACE_SIZE ,
[ IPACK_ID_SPACE ] = TPCI200_ID_SPACE_SIZE ,
[ IPACK_INT_SPACE ] = TPCI200_INT_SPACE_SIZE ,
[ IPACK_MEM8_SPACE ] = TPCI200_MEM8_SPACE_SIZE ,
2012-09-27 14:37:37 +04:00
[ IPACK_MEM16_SPACE ] = TPCI200_MEM16_SPACE_SIZE ,
2012-09-27 14:37:31 +04:00
} ;
static const size_t tpci200_space_interval [ IPACK_SPACE_COUNT ] = {
2012-09-27 14:37:36 +04:00
[ IPACK_IO_SPACE ] = TPCI200_IO_SPACE_INTERVAL ,
[ IPACK_ID_SPACE ] = TPCI200_ID_SPACE_INTERVAL ,
[ IPACK_INT_SPACE ] = TPCI200_INT_SPACE_INTERVAL ,
[ IPACK_MEM8_SPACE ] = TPCI200_MEM8_SPACE_INTERVAL ,
2012-09-27 14:37:37 +04:00
[ IPACK_MEM16_SPACE ] = TPCI200_MEM16_SPACE_INTERVAL ,
2012-09-27 14:37:31 +04:00
} ;
2012-05-09 17:27:20 +04:00
static struct tpci200_board * check_slot ( struct ipack_device * dev )
{
struct tpci200_board * tpci200 ;
2012-05-25 15:08:12 +04:00
if ( dev = = NULL )
2012-05-09 17:27:20 +04:00
return NULL ;
2012-07-20 11:39:04 +04:00
tpci200 = dev_get_drvdata ( dev - > bus - > parent ) ;
if ( tpci200 = = NULL ) {
dev_info ( & dev - > dev , " carrier board not found \n " ) ;
2012-05-09 17:27:20 +04:00
return NULL ;
}
if ( dev - > slot > = TPCI200_NB_SLOT ) {
2012-05-25 15:08:12 +04:00
dev_info ( & dev - > dev ,
" Slot [%d:%d] doesn't exist! Last tpci200 slot is %d. \n " ,
2012-09-27 14:37:25 +04:00
dev - > bus - > bus_nr , dev - > slot , TPCI200_NB_SLOT - 1 ) ;
2012-05-09 17:27:20 +04:00
return NULL ;
}
return tpci200 ;
}
2012-09-12 16:55:23 +04:00
static void tpci200_clear_mask ( struct tpci200_board * tpci200 ,
__le16 __iomem * addr , u16 mask )
{
2012-09-12 16:55:33 +04:00
unsigned long flags ;
spin_lock_irqsave ( & tpci200 - > regs_lock , flags ) ;
iowrite16 ( ioread16 ( addr ) & ( ~ mask ) , addr ) ;
spin_unlock_irqrestore ( & tpci200 - > regs_lock , flags ) ;
2012-09-12 16:55:23 +04:00
}
static void tpci200_set_mask ( struct tpci200_board * tpci200 ,
__le16 __iomem * addr , u16 mask )
{
2012-09-12 16:55:33 +04:00
unsigned long flags ;
spin_lock_irqsave ( & tpci200 - > regs_lock , flags ) ;
iowrite16 ( ioread16 ( addr ) | mask , addr ) ;
spin_unlock_irqrestore ( & tpci200 - > regs_lock , flags ) ;
2012-09-12 16:55:23 +04:00
}
2012-05-09 17:27:20 +04:00
static void tpci200_unregister ( struct tpci200_board * tpci200 )
{
free_irq ( tpci200 - > info - > pdev - > irq , ( void * ) tpci200 ) ;
pci_iounmap ( tpci200 - > info - > pdev , tpci200 - > info - > interface_regs ) ;
2012-09-11 15:35:04 +04:00
pci_iounmap ( tpci200 - > info - > pdev , tpci200 - > info - > cfg_regs ) ;
2012-05-09 17:27:20 +04:00
pci_release_region ( tpci200 - > info - > pdev , TPCI200_IP_INTERFACE_BAR ) ;
pci_release_region ( tpci200 - > info - > pdev , TPCI200_IO_ID_INT_SPACES_BAR ) ;
2012-09-27 14:37:37 +04:00
pci_release_region ( tpci200 - > info - > pdev , TPCI200_MEM16_SPACE_BAR ) ;
2012-05-09 17:27:20 +04:00
pci_release_region ( tpci200 - > info - > pdev , TPCI200_MEM8_SPACE_BAR ) ;
2012-09-11 15:35:04 +04:00
pci_release_region ( tpci200 - > info - > pdev , TPCI200_CFG_MEM_BAR ) ;
2012-05-09 17:27:20 +04:00
pci_disable_device ( tpci200 - > info - > pdev ) ;
pci_dev_put ( tpci200 - > info - > pdev ) ;
}
2012-09-12 16:55:36 +04:00
static void tpci200_enable_irq ( struct tpci200_board * tpci200 ,
int islot )
{
tpci200_set_mask ( tpci200 ,
& tpci200 - > info - > interface_regs - > control [ islot ] ,
TPCI200_INT0_EN | TPCI200_INT1_EN ) ;
}
static void tpci200_disable_irq ( struct tpci200_board * tpci200 ,
int islot )
{
tpci200_clear_mask ( tpci200 ,
& tpci200 - > info - > interface_regs - > control [ islot ] ,
TPCI200_INT0_EN | TPCI200_INT1_EN ) ;
}
2012-09-12 16:55:25 +04:00
static irqreturn_t tpci200_slot_irq ( struct slot_irq * slot_irq )
{
2012-09-12 16:55:35 +04:00
irqreturn_t ret ;
2012-09-12 16:55:25 +04:00
2012-09-12 16:55:35 +04:00
if ( ! slot_irq )
return - ENODEV ;
ret = slot_irq - > handler ( slot_irq - > arg ) ;
2012-09-12 16:55:25 +04:00
return ret ;
}
2012-05-09 17:27:20 +04:00
static irqreturn_t tpci200_interrupt ( int irq , void * dev_id )
{
struct tpci200_board * tpci200 = ( struct tpci200_board * ) dev_id ;
2012-09-11 15:35:13 +04:00
struct slot_irq * slot_irq ;
2012-09-12 16:55:35 +04:00
irqreturn_t ret ;
u16 status_reg ;
int i ;
2012-05-09 17:27:20 +04:00
/* Read status register */
2012-09-12 16:55:35 +04:00
status_reg = ioread16 ( & tpci200 - > info - > interface_regs - > status ) ;
2012-05-09 17:27:20 +04:00
2012-09-12 16:55:35 +04:00
/* Did we cause the interrupt? */
if ( ! ( status_reg & TPCI200_SLOT_INT_MASK ) )
2012-09-12 16:55:34 +04:00
return IRQ_NONE ;
2012-09-12 16:55:35 +04:00
/* callback to the IRQ handler for the corresponding slot */
rcu_read_lock ( ) ;
for ( i = 0 ; i < TPCI200_NB_SLOT ; i + + ) {
if ( ! ( status_reg & ( ( TPCI200_A_INT0 | TPCI200_A_INT1 ) < < ( 2 * i ) ) ) )
continue ;
slot_irq = rcu_dereference ( tpci200 - > slots [ i ] . irq ) ;
ret = tpci200_slot_irq ( slot_irq ) ;
if ( ret = = - ENODEV ) {
dev_info ( & tpci200 - > info - > pdev - > dev ,
" No registered ISR for slot [%d:%d]!. IRQ will be disabled. \n " ,
tpci200 - > number , i ) ;
2012-09-12 16:55:36 +04:00
tpci200_disable_irq ( tpci200 , i ) ;
2012-09-12 16:55:35 +04:00
}
2012-09-12 16:55:34 +04:00
}
2012-09-12 16:55:35 +04:00
rcu_read_unlock ( ) ;
return IRQ_HANDLED ;
2012-05-09 17:27:20 +04:00
}
2012-09-12 16:55:37 +04:00
static int tpci200_free_irq ( struct ipack_device * dev )
{
struct slot_irq * slot_irq ;
struct tpci200_board * tpci200 ;
tpci200 = check_slot ( dev ) ;
if ( tpci200 = = NULL )
return - EINVAL ;
if ( mutex_lock_interruptible ( & tpci200 - > mutex ) )
return - ERESTARTSYS ;
if ( tpci200 - > slots [ dev - > slot ] . irq = = NULL ) {
mutex_unlock ( & tpci200 - > mutex ) ;
return - EINVAL ;
}
tpci200_disable_irq ( tpci200 , dev - > slot ) ;
slot_irq = tpci200 - > slots [ dev - > slot ] . irq ;
/* uninstall handler */
RCU_INIT_POINTER ( tpci200 - > slots [ dev - > slot ] . irq , NULL ) ;
synchronize_rcu ( ) ;
kfree ( slot_irq ) ;
mutex_unlock ( & tpci200 - > mutex ) ;
return 0 ;
}
2012-09-13 14:32:21 +04:00
static int tpci200_request_irq ( struct ipack_device * dev ,
2012-09-12 16:55:38 +04:00
irqreturn_t ( * handler ) ( void * ) , void * arg )
2012-09-12 16:55:37 +04:00
{
int res = 0 ;
struct slot_irq * slot_irq ;
struct tpci200_board * tpci200 ;
tpci200 = check_slot ( dev ) ;
if ( tpci200 = = NULL )
return - EINVAL ;
if ( mutex_lock_interruptible ( & tpci200 - > mutex ) )
return - ERESTARTSYS ;
if ( tpci200 - > slots [ dev - > slot ] . irq ! = NULL ) {
dev_err ( & dev - > dev ,
2012-11-12 00:41:13 +04:00
" Slot [%d:%d] IRQ already registered ! \n " ,
dev - > bus - > bus_nr ,
2012-09-12 16:55:37 +04:00
dev - > slot ) ;
res = - EINVAL ;
goto out_unlock ;
}
slot_irq = kzalloc ( sizeof ( struct slot_irq ) , GFP_KERNEL ) ;
if ( slot_irq = = NULL ) {
dev_err ( & dev - > dev ,
" Slot [%d:%d] unable to allocate memory for IRQ ! \n " ,
2012-09-27 14:37:25 +04:00
dev - > bus - > bus_nr , dev - > slot ) ;
2012-09-12 16:55:37 +04:00
res = - ENOMEM ;
goto out_unlock ;
}
/*
* WARNING : Setup Interrupt Vector in the IndustryPack device
* before an IRQ request .
* Read the User Manual of your IndustryPack device to know
* where to write the vector in memory .
*/
slot_irq - > handler = handler ;
slot_irq - > arg = arg ;
slot_irq - > holder = dev ;
rcu_assign_pointer ( tpci200 - > slots [ dev - > slot ] . irq , slot_irq ) ;
tpci200_enable_irq ( tpci200 , dev - > slot ) ;
out_unlock :
mutex_unlock ( & tpci200 - > mutex ) ;
return res ;
}
2012-05-09 17:27:20 +04:00
static int tpci200_register ( struct tpci200_board * tpci200 )
{
2012-05-23 17:54:40 +04:00
int i ;
2012-05-09 17:27:20 +04:00
int res ;
2012-09-27 14:37:28 +04:00
phys_addr_t ioidint_base ;
2012-05-09 17:27:20 +04:00
unsigned short slot_ctrl ;
if ( pci_enable_device ( tpci200 - > info - > pdev ) < 0 )
return - ENODEV ;
/* Request IP interface register (Bar 2) */
res = pci_request_region ( tpci200 - > info - > pdev , TPCI200_IP_INTERFACE_BAR ,
" Carrier IP interface registers " ) ;
if ( res ) {
2012-05-25 15:08:12 +04:00
dev_err ( & tpci200 - > info - > pdev - > dev ,
" (bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 2 ! " ,
tpci200 - > info - > pdev - > bus - > number ,
tpci200 - > info - > pdev - > devfn ) ;
2012-05-23 17:54:40 +04:00
goto out_disable_pci ;
2012-05-09 17:27:20 +04:00
}
/* Request IO ID INT space (Bar 3) */
res = pci_request_region ( tpci200 - > info - > pdev ,
TPCI200_IO_ID_INT_SPACES_BAR ,
" Carrier IO ID INT space " ) ;
if ( res ) {
2012-05-25 15:08:12 +04:00
dev_err ( & tpci200 - > info - > pdev - > dev ,
" (bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 3 ! " ,
tpci200 - > info - > pdev - > bus - > number ,
tpci200 - > info - > pdev - > devfn ) ;
2012-05-09 17:27:20 +04:00
goto out_release_ip_space ;
}
2012-09-27 14:37:36 +04:00
/* Request MEM8 space (Bar 5) */
2012-05-09 17:27:20 +04:00
res = pci_request_region ( tpci200 - > info - > pdev , TPCI200_MEM8_SPACE_BAR ,
2012-09-27 14:37:36 +04:00
" Carrier MEM8 space " ) ;
2012-05-09 17:27:20 +04:00
if ( res ) {
2012-05-25 15:08:12 +04:00
dev_err ( & tpci200 - > info - > pdev - > dev ,
2012-09-27 14:37:36 +04:00
" (bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 5! " ,
2012-05-25 15:08:12 +04:00
tpci200 - > info - > pdev - > bus - > number ,
tpci200 - > info - > pdev - > devfn ) ;
2012-05-09 17:27:20 +04:00
goto out_release_ioid_int_space ;
}
2012-09-27 14:37:37 +04:00
/* Request MEM16 space (Bar 4) */
res = pci_request_region ( tpci200 - > info - > pdev , TPCI200_MEM16_SPACE_BAR ,
" Carrier MEM16 space " ) ;
if ( res ) {
dev_err ( & tpci200 - > info - > pdev - > dev ,
" (bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 4! " ,
tpci200 - > info - > pdev - > bus - > number ,
tpci200 - > info - > pdev - > devfn ) ;
goto out_release_mem8_space ;
}
2012-05-09 17:27:20 +04:00
/* Map internal tpci200 driver user space */
tpci200 - > info - > interface_regs =
2020-01-06 11:43:50 +03:00
ioremap ( pci_resource_start ( tpci200 - > info - > pdev ,
2012-05-09 17:27:20 +04:00
TPCI200_IP_INTERFACE_BAR ) ,
TPCI200_IFACE_SIZE ) ;
2018-06-12 06:07:21 +03:00
if ( ! tpci200 - > info - > interface_regs ) {
dev_err ( & tpci200 - > info - > pdev - > dev ,
" (bn 0x%X, sn 0x%X) failed to map driver user space! " ,
tpci200 - > info - > pdev - > bus - > number ,
tpci200 - > info - > pdev - > devfn ) ;
2020-05-07 12:42:37 +03:00
res = - ENOMEM ;
2018-06-12 06:07:21 +03:00
goto out_release_mem8_space ;
}
2012-05-09 17:27:20 +04:00
2012-09-12 16:55:33 +04:00
/* Initialize lock that protects interface_regs */
spin_lock_init ( & tpci200 - > regs_lock ) ;
2012-05-09 17:27:20 +04:00
ioidint_base = pci_resource_start ( tpci200 - > info - > pdev ,
TPCI200_IO_ID_INT_SPACES_BAR ) ;
2012-09-27 14:37:29 +04:00
tpci200 - > mod_mem [ IPACK_IO_SPACE ] = ioidint_base + TPCI200_IO_SPACE_OFF ;
tpci200 - > mod_mem [ IPACK_ID_SPACE ] = ioidint_base + TPCI200_ID_SPACE_OFF ;
tpci200 - > mod_mem [ IPACK_INT_SPACE ] =
ioidint_base + TPCI200_INT_SPACE_OFF ;
2012-09-27 14:37:36 +04:00
tpci200 - > mod_mem [ IPACK_MEM8_SPACE ] =
2012-09-27 14:37:29 +04:00
pci_resource_start ( tpci200 - > info - > pdev ,
2012-09-27 14:37:30 +04:00
TPCI200_MEM8_SPACE_BAR ) ;
2012-09-27 14:37:37 +04:00
tpci200 - > mod_mem [ IPACK_MEM16_SPACE ] =
pci_resource_start ( tpci200 - > info - > pdev ,
TPCI200_MEM16_SPACE_BAR ) ;
2012-05-09 17:27:20 +04:00
/* Set the default parameters of the slot
* INT0 disabled , level sensitive
* INT1 disabled , level sensitive
* error interrupt disabled
* timeout interrupt disabled
* recover time disabled
* clock rate 8 MHz
*/
slot_ctrl = 0 ;
2012-09-27 14:37:35 +04:00
for ( i = 0 ; i < TPCI200_NB_SLOT ; i + + )
2012-09-11 15:34:54 +04:00
writew ( slot_ctrl , & tpci200 - > info - > interface_regs - > control [ i ] ) ;
2012-05-09 17:27:20 +04:00
res = request_irq ( tpci200 - > info - > pdev - > irq ,
tpci200_interrupt , IRQF_SHARED ,
2012-05-18 13:10:07 +04:00
KBUILD_MODNAME , ( void * ) tpci200 ) ;
2012-05-09 17:27:20 +04:00
if ( res ) {
2012-05-25 15:08:12 +04:00
dev_err ( & tpci200 - > info - > pdev - > dev ,
" (bn 0x%X, sn 0x%X) unable to register IRQ ! " ,
tpci200 - > info - > pdev - > bus - > number ,
tpci200 - > info - > pdev - > devfn ) ;
2012-05-23 17:54:40 +04:00
goto out_release_ioid_int_space ;
2012-05-09 17:27:20 +04:00
}
return 0 ;
2012-09-27 14:37:37 +04:00
out_release_mem8_space :
pci_release_region ( tpci200 - > info - > pdev , TPCI200_MEM8_SPACE_BAR ) ;
2012-05-09 17:27:20 +04:00
out_release_ioid_int_space :
pci_release_region ( tpci200 - > info - > pdev , TPCI200_IO_ID_INT_SPACES_BAR ) ;
out_release_ip_space :
pci_release_region ( tpci200 - > info - > pdev , TPCI200_IP_INTERFACE_BAR ) ;
out_disable_pci :
pci_disable_device ( tpci200 - > info - > pdev ) ;
return res ;
}
2012-09-11 15:34:56 +04:00
static int tpci200_get_clockrate ( struct ipack_device * dev )
{
struct tpci200_board * tpci200 = check_slot ( dev ) ;
2012-09-12 16:55:46 +04:00
__le16 __iomem * addr ;
2012-09-11 15:34:56 +04:00
if ( ! tpci200 )
return - ENODEV ;
addr = & tpci200 - > info - > interface_regs - > control [ dev - > slot ] ;
return ( ioread16 ( addr ) & TPCI200_CLK32 ) ? 32 : 8 ;
}
static int tpci200_set_clockrate ( struct ipack_device * dev , int mherz )
{
struct tpci200_board * tpci200 = check_slot ( dev ) ;
2012-09-12 16:55:46 +04:00
__le16 __iomem * addr ;
2012-09-11 15:34:56 +04:00
if ( ! tpci200 )
return - ENODEV ;
addr = & tpci200 - > info - > interface_regs - > control [ dev - > slot ] ;
switch ( mherz ) {
case 8 :
2012-09-12 16:55:23 +04:00
tpci200_clear_mask ( tpci200 , addr , TPCI200_CLK32 ) ;
2012-09-11 15:34:56 +04:00
break ;
case 32 :
2012-09-12 16:55:23 +04:00
tpci200_set_mask ( tpci200 , addr , TPCI200_CLK32 ) ;
2012-09-11 15:34:56 +04:00
break ;
default :
return - EINVAL ;
}
return 0 ;
}
static int tpci200_get_error ( struct ipack_device * dev )
{
struct tpci200_board * tpci200 = check_slot ( dev ) ;
2012-09-12 16:55:46 +04:00
__le16 __iomem * addr ;
2012-09-11 15:34:56 +04:00
u16 mask ;
if ( ! tpci200 )
return - ENODEV ;
addr = & tpci200 - > info - > interface_regs - > status ;
mask = tpci200_status_error [ dev - > slot ] ;
return ( ioread16 ( addr ) & mask ) ? 1 : 0 ;
}
static int tpci200_get_timeout ( struct ipack_device * dev )
{
struct tpci200_board * tpci200 = check_slot ( dev ) ;
2012-09-12 16:55:46 +04:00
__le16 __iomem * addr ;
2012-09-11 15:34:56 +04:00
u16 mask ;
if ( ! tpci200 )
return - ENODEV ;
addr = & tpci200 - > info - > interface_regs - > status ;
mask = tpci200_status_timeout [ dev - > slot ] ;
return ( ioread16 ( addr ) & mask ) ? 1 : 0 ;
}
static int tpci200_reset_timeout ( struct ipack_device * dev )
{
struct tpci200_board * tpci200 = check_slot ( dev ) ;
2012-09-12 16:55:46 +04:00
__le16 __iomem * addr ;
2012-09-11 15:34:56 +04:00
u16 mask ;
if ( ! tpci200 )
return - ENODEV ;
addr = & tpci200 - > info - > interface_regs - > status ;
mask = tpci200_status_timeout [ dev - > slot ] ;
iowrite16 ( mask , addr ) ;
return 0 ;
}
2012-05-09 17:27:20 +04:00
static void tpci200_uninstall ( struct tpci200_board * tpci200 )
{
tpci200_unregister ( tpci200 ) ;
kfree ( tpci200 - > slots ) ;
}
2012-09-10 22:14:01 +04:00
static const struct ipack_bus_ops tpci200_bus_ops = {
2012-05-09 17:27:20 +04:00
. request_irq = tpci200_request_irq ,
. free_irq = tpci200_free_irq ,
2012-09-11 15:34:56 +04:00
. get_clockrate = tpci200_get_clockrate ,
. set_clockrate = tpci200_set_clockrate ,
. get_error = tpci200_get_error ,
. get_timeout = tpci200_get_timeout ,
. reset_timeout = tpci200_reset_timeout ,
2012-05-09 17:27:20 +04:00
} ;
static int tpci200_install ( struct tpci200_board * tpci200 )
{
int res ;
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
tpci200 - > slots = kcalloc ( TPCI200_NB_SLOT , sizeof ( struct tpci200_slot ) ,
GFP_KERNEL ) ;
2012-06-07 12:24:54 +04:00
if ( tpci200 - > slots = = NULL )
return - ENOMEM ;
2012-05-09 17:27:20 +04:00
res = tpci200_register ( tpci200 ) ;
2012-06-07 12:24:54 +04:00
if ( res ) {
kfree ( tpci200 - > slots ) ;
tpci200 - > slots = NULL ;
return res ;
}
2012-05-09 17:27:20 +04:00
mutex_init ( & tpci200 - > mutex ) ;
return 0 ;
}
2012-09-27 14:37:26 +04:00
static void tpci200_release_device ( struct ipack_device * dev )
{
kfree ( dev ) ;
}
static int tpci200_create_device ( struct tpci200_board * tpci200 , int i )
{
2013-03-08 12:21:47 +04:00
int ret ;
2012-09-27 14:37:31 +04:00
enum ipack_space space ;
2012-09-27 14:37:26 +04:00
struct ipack_device * dev =
kzalloc ( sizeof ( struct ipack_device ) , GFP_KERNEL ) ;
if ( ! dev )
return - ENOMEM ;
dev - > slot = i ;
dev - > bus = tpci200 - > info - > ipack_bus ;
dev - > release = tpci200_release_device ;
2012-09-27 14:37:31 +04:00
for ( space = 0 ; space < IPACK_SPACE_COUNT ; space + + ) {
dev - > region [ space ] . start =
tpci200 - > mod_mem [ space ]
+ tpci200_space_interval [ space ] * i ;
dev - > region [ space ] . size = tpci200_space_size [ space ] ;
}
2013-03-08 12:21:47 +04:00
ret = ipack_device_init ( dev ) ;
if ( ret < 0 ) {
ipack_put_device ( dev ) ;
return ret ;
}
ret = ipack_device_add ( dev ) ;
if ( ret < 0 )
ipack_put_device ( dev ) ;
return ret ;
2012-09-27 14:37:26 +04:00
}
2012-09-07 19:50:54 +04:00
static int tpci200_pci_probe ( struct pci_dev * pdev ,
const struct pci_device_id * id )
2012-05-09 17:27:20 +04:00
{
2012-05-23 17:54:40 +04:00
int ret , i ;
2012-05-09 17:27:20 +04:00
struct tpci200_board * tpci200 ;
2012-09-11 15:34:56 +04:00
u32 reg32 ;
2012-05-09 17:27:20 +04:00
tpci200 = kzalloc ( sizeof ( struct tpci200_board ) , GFP_KERNEL ) ;
if ( ! tpci200 )
return - ENOMEM ;
tpci200 - > info = kzalloc ( sizeof ( struct tpci200_infos ) , GFP_KERNEL ) ;
if ( ! tpci200 - > info ) {
2012-09-04 19:01:06 +04:00
ret = - ENOMEM ;
goto out_err_info ;
2012-05-09 17:27:20 +04:00
}
2012-09-11 15:35:05 +04:00
pci_dev_get ( pdev ) ;
2012-09-04 19:01:07 +04:00
/* Obtain a mapping of the carrier's PCI configuration registers */
ret = pci_request_region ( pdev , TPCI200_CFG_MEM_BAR ,
KBUILD_MODNAME " Configuration Memory " ) ;
if ( ret ) {
dev_err ( & pdev - > dev , " Failed to allocate PCI Configuration Memory " ) ;
ret = - EBUSY ;
goto out_err_pci_request ;
}
2020-01-06 11:43:50 +03:00
tpci200 - > info - > cfg_regs = ioremap (
2012-09-04 19:01:07 +04:00
pci_resource_start ( pdev , TPCI200_CFG_MEM_BAR ) ,
pci_resource_len ( pdev , TPCI200_CFG_MEM_BAR ) ) ;
if ( ! tpci200 - > info - > cfg_regs ) {
dev_err ( & pdev - > dev , " Failed to map PCI Configuration Memory " ) ;
ret = - EFAULT ;
goto out_err_ioremap ;
}
/* Disable byte swapping for 16 bit IP module access. This will ensure
* that the Industrypack big endian byte order is preserved by the
* carrier . */
reg32 = ioread32 ( tpci200 - > info - > cfg_regs + LAS1_DESC ) ;
reg32 | = 1 < < LAS_BIT_BIGENDIAN ;
iowrite32 ( reg32 , tpci200 - > info - > cfg_regs + LAS1_DESC ) ;
reg32 = ioread32 ( tpci200 - > info - > cfg_regs + LAS2_DESC ) ;
reg32 | = 1 < < LAS_BIT_BIGENDIAN ;
iowrite32 ( reg32 , tpci200 - > info - > cfg_regs + LAS2_DESC ) ;
2012-05-09 17:27:20 +04:00
/* Save struct pci_dev pointer */
tpci200 - > info - > pdev = pdev ;
tpci200 - > info - > id_table = ( struct pci_device_id * ) id ;
/* register the device and initialize it */
ret = tpci200_install ( tpci200 ) ;
if ( ret ) {
2012-09-04 19:01:06 +04:00
dev_err ( & pdev - > dev , " error during tpci200 install \n " ) ;
ret = - ENODEV ;
goto out_err_install ;
2012-05-09 17:27:20 +04:00
}
2012-05-18 13:10:05 +04:00
/* Register the carrier in the industry pack bus driver */
tpci200 - > info - > ipack_bus = ipack_bus_register ( & pdev - > dev ,
TPCI200_NB_SLOT ,
2014-09-02 19:31:40 +04:00
& tpci200_bus_ops ,
THIS_MODULE ) ;
2012-05-18 13:10:05 +04:00
if ( ! tpci200 - > info - > ipack_bus ) {
2012-05-25 15:08:12 +04:00
dev_err ( & pdev - > dev ,
" error registering the carrier on ipack driver \n " ) ;
2012-09-04 19:01:06 +04:00
ret = - EFAULT ;
goto out_err_bus_register ;
2012-05-09 17:27:20 +04:00
}
2012-05-18 13:10:05 +04:00
2012-05-09 17:27:20 +04:00
/* save the bus number given by ipack to logging purpose */
2012-05-18 13:10:05 +04:00
tpci200 - > number = tpci200 - > info - > ipack_bus - > bus_nr ;
2012-05-09 17:27:20 +04:00
dev_set_drvdata ( & pdev - > dev , tpci200 ) ;
2012-05-23 17:54:40 +04:00
for ( i = 0 ; i < TPCI200_NB_SLOT ; i + + )
2012-09-27 14:37:26 +04:00
tpci200_create_device ( tpci200 , i ) ;
2012-09-04 19:01:06 +04:00
return 0 ;
out_err_bus_register :
tpci200_uninstall ( tpci200 ) ;
out_err_install :
2012-09-04 19:01:07 +04:00
iounmap ( tpci200 - > info - > cfg_regs ) ;
out_err_ioremap :
pci_release_region ( pdev , TPCI200_CFG_MEM_BAR ) ;
out_err_pci_request :
2012-09-11 15:35:05 +04:00
pci_dev_put ( pdev ) ;
2012-09-04 19:01:06 +04:00
kfree ( tpci200 - > info ) ;
out_err_info :
kfree ( tpci200 ) ;
2012-05-09 17:27:20 +04:00
return ret ;
}
static void __tpci200_pci_remove ( struct tpci200_board * tpci200 )
{
2012-05-18 13:10:05 +04:00
ipack_bus_unregister ( tpci200 - > info - > ipack_bus ) ;
2012-09-11 15:35:10 +04:00
tpci200_uninstall ( tpci200 ) ;
2012-09-04 19:01:07 +04:00
2012-05-18 13:10:05 +04:00
kfree ( tpci200 - > info ) ;
2012-05-09 17:27:20 +04:00
kfree ( tpci200 ) ;
}
2012-11-19 22:26:39 +04:00
static void tpci200_pci_remove ( struct pci_dev * dev )
2012-05-09 17:27:20 +04:00
{
2012-07-20 11:39:04 +04:00
struct tpci200_board * tpci200 = pci_get_drvdata ( dev ) ;
2012-05-09 17:27:20 +04:00
2012-07-20 11:39:04 +04:00
__tpci200_pci_remove ( tpci200 ) ;
2012-05-09 17:27:20 +04:00
}
2014-07-18 19:27:12 +04:00
static const struct pci_device_id tpci200_idtable [ ] = {
2012-05-09 17:27:20 +04:00
{ TPCI200_VENDOR_ID , TPCI200_DEVICE_ID , TPCI200_SUBVENDOR_ID ,
TPCI200_SUBDEVICE_ID } ,
{ 0 , } ,
} ;
2012-06-07 12:24:58 +04:00
MODULE_DEVICE_TABLE ( pci , tpci200_idtable ) ;
2012-05-09 17:27:20 +04:00
static struct pci_driver tpci200_pci_drv = {
. name = " tpci200 " ,
. id_table = tpci200_idtable ,
2012-09-07 19:50:54 +04:00
. probe = tpci200_pci_probe ,
2012-11-19 22:21:31 +04:00
. remove = tpci200_pci_remove ,
2012-05-09 17:27:20 +04:00
} ;
2012-10-18 19:18:46 +04:00
module_pci_driver ( tpci200_pci_drv ) ;
2012-05-09 17:27:20 +04:00
MODULE_DESCRIPTION ( " TEWS TPCI-200 device driver " ) ;
MODULE_LICENSE ( " GPL " ) ;