2012-11-29 12:50:30 +01:00
/*
* Copyright IBM Corp . 2012
*
* Author ( s ) :
* Jan Glauber < jang @ linux . vnet . ibm . com >
*
* The System z PCI code is a rewrite from a prototype by
* the following people ( Kudoz ! ) :
2012-12-06 14:06:28 +01:00
* Alexander Schmidt
* Christoph Raisch
* Hannes Hering
* Hoang - Nam Nguyen
* Jan - Bernd Themann
* Stefan Roscher
* Thomas Klein
2012-11-29 12:50:30 +01:00
*/
2014-07-16 17:21:01 +02:00
# define KMSG_COMPONENT "zpci"
# define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
2012-11-29 12:50:30 +01:00
# include <linux/kernel.h>
# include <linux/slab.h>
# include <linux/err.h>
# include <linux/export.h>
# include <linux/delay.h>
2012-11-29 13:05:05 +01:00
# include <linux/irq.h>
# include <linux/kernel_stat.h>
2012-11-29 12:50:30 +01:00
# include <linux/seq_file.h>
# include <linux/pci.h>
# include <linux/msi.h>
2012-11-29 13:05:05 +01:00
# include <asm/isc.h>
# include <asm/airq.h>
2012-11-29 12:50:30 +01:00
# include <asm/facility.h>
# include <asm/pci_insn.h>
2012-11-29 12:55:21 +01:00
# include <asm/pci_clp.h>
2012-11-29 14:33:30 +01:00
# include <asm/pci_dma.h>
2012-11-29 12:50:30 +01:00
# define DEBUG /* enable pr_debug */
2012-11-29 13:05:05 +01:00
# define SIC_IRQ_MODE_ALL 0
# define SIC_IRQ_MODE_SINGLE 1
2012-11-29 12:50:30 +01:00
# define ZPCI_NR_DMA_SPACES 1
# define ZPCI_NR_DEVICES CONFIG_PCI_NR_FUNCTIONS
/* list of all detected zpci devices */
2013-08-29 19:33:16 +02:00
static LIST_HEAD ( zpci_list ) ;
2013-08-29 19:40:01 +02:00
static DEFINE_SPINLOCK ( zpci_list_lock ) ;
2012-11-29 12:50:30 +01:00
2013-06-27 09:01:09 +02:00
static struct irq_chip zpci_irq_chip = {
. name = " zPCI " ,
2014-07-08 10:08:05 +08:00
. irq_unmask = unmask_msi_irq ,
. irq_mask = mask_msi_irq ,
2012-11-29 13:05:05 +01:00
} ;
2013-06-27 09:01:09 +02:00
static DECLARE_BITMAP ( zpci_domain , ZPCI_NR_DEVICES ) ;
static DEFINE_SPINLOCK ( zpci_domain_lock ) ;
2012-11-29 13:05:05 +01:00
2013-06-25 16:36:29 +02:00
static struct airq_iv * zpci_aisb_iv ;
2013-06-27 09:01:09 +02:00
static struct airq_iv * zpci_aibv [ ZPCI_NR_DEVICES ] ;
2012-11-29 13:05:05 +01:00
2013-06-24 10:30:41 +02:00
/* Adapter interrupt definitions */
static void zpci_irq_handler ( struct airq_struct * airq ) ;
static struct airq_struct zpci_airq = {
. handler = zpci_irq_handler ,
. isc = PCI_ISC ,
} ;
2012-11-29 13:05:05 +01:00
2012-11-29 12:50:30 +01:00
/* I/O Map */
static DEFINE_SPINLOCK ( zpci_iomap_lock ) ;
static DECLARE_BITMAP ( zpci_iomap , ZPCI_IOMAP_MAX_ENTRIES ) ;
struct zpci_iomap_entry * zpci_iomap_start ;
EXPORT_SYMBOL_GPL ( zpci_iomap_start ) ;
2012-12-11 14:53:35 +01:00
static struct kmem_cache * zdev_fmb_cache ;
2012-11-29 12:50:30 +01:00
struct zpci_dev * get_zdev ( struct pci_dev * pdev )
{
return ( struct zpci_dev * ) pdev - > sysdata ;
}
struct zpci_dev * get_zdev_by_fid ( u32 fid )
{
struct zpci_dev * tmp , * zdev = NULL ;
2013-08-29 19:40:01 +02:00
spin_lock ( & zpci_list_lock ) ;
2012-11-29 12:50:30 +01:00
list_for_each_entry ( tmp , & zpci_list , entry ) {
if ( tmp - > fid = = fid ) {
zdev = tmp ;
break ;
}
}
2013-08-29 19:40:01 +02:00
spin_unlock ( & zpci_list_lock ) ;
2012-11-29 12:50:30 +01:00
return zdev ;
}
static struct zpci_dev * get_zdev_by_bus ( struct pci_bus * bus )
{
return ( bus & & bus - > sysdata ) ? ( struct zpci_dev * ) bus - > sysdata : NULL ;
}
int pci_domain_nr ( struct pci_bus * bus )
{
return ( ( struct zpci_dev * ) bus - > sysdata ) - > domain ;
}
EXPORT_SYMBOL_GPL ( pci_domain_nr ) ;
int pci_proc_domain ( struct pci_bus * bus )
{
return pci_domain_nr ( bus ) ;
}
EXPORT_SYMBOL_GPL ( pci_proc_domain ) ;
2012-11-29 13:05:05 +01:00
/* Modify PCI: Register adapter interruptions */
2013-06-25 16:36:29 +02:00
static int zpci_set_airq ( struct zpci_dev * zdev )
2012-11-29 13:05:05 +01:00
{
u64 req = ZPCI_CREATE_REQ ( zdev - > fh , 0 , ZPCI_MOD_FC_REG_INT ) ;
2013-10-22 15:19:24 +02:00
struct zpci_fib fib = { 0 } ;
2012-11-29 13:05:05 +01:00
2013-10-22 15:19:24 +02:00
fib . isc = PCI_ISC ;
fib . sum = 1 ; /* enable summary notifications */
fib . noi = airq_iv_end ( zdev - > aibv ) ;
fib . aibv = ( unsigned long ) zdev - > aibv - > vector ;
fib . aibvo = 0 ; /* each zdev has its own interrupt vector */
fib . aisb = ( unsigned long ) zpci_aisb_iv - > vector + ( zdev - > aisb / 64 ) * 8 ;
fib . aisbo = zdev - > aisb & 63 ;
2012-11-29 13:05:05 +01:00
2013-10-22 15:19:24 +02:00
return zpci_mod_fc ( req , & fib ) ;
2012-11-29 13:05:05 +01:00
}
struct mod_pci_args {
u64 base ;
u64 limit ;
u64 iota ;
2012-12-11 14:53:35 +01:00
u64 fmb_addr ;
2012-11-29 13:05:05 +01:00
} ;
static int mod_pci ( struct zpci_dev * zdev , int fn , u8 dmaas , struct mod_pci_args * args )
{
u64 req = ZPCI_CREATE_REQ ( zdev - > fh , dmaas , fn ) ;
2013-10-22 15:19:24 +02:00
struct zpci_fib fib = { 0 } ;
fib . pba = args - > base ;
fib . pal = args - > limit ;
fib . iota = args - > iota ;
fib . fmb_addr = args - > fmb_addr ;
return zpci_mod_fc ( req , & fib ) ;
2012-11-29 13:05:05 +01:00
}
2012-11-29 14:33:30 +01:00
/* Modify PCI: Register I/O address translation parameters */
int zpci_register_ioat ( struct zpci_dev * zdev , u8 dmaas ,
u64 base , u64 limit , u64 iota )
{
2012-12-11 14:53:35 +01:00
struct mod_pci_args args = { base , limit , iota , 0 } ;
2012-11-29 14:33:30 +01:00
WARN_ON_ONCE ( iota & 0x3fff ) ;
args . iota | = ZPCI_IOTA_RTTO_FLAG ;
return mod_pci ( zdev , ZPCI_MOD_FC_REG_IOAT , dmaas , & args ) ;
}
/* Modify PCI: Unregister I/O address translation parameters */
int zpci_unregister_ioat ( struct zpci_dev * zdev , u8 dmaas )
{
2012-12-11 14:53:35 +01:00
struct mod_pci_args args = { 0 , 0 , 0 , 0 } ;
2012-11-29 14:33:30 +01:00
return mod_pci ( zdev , ZPCI_MOD_FC_DEREG_IOAT , dmaas , & args ) ;
}
2012-11-29 13:05:05 +01:00
/* Modify PCI: Unregister adapter interruptions */
2013-06-25 16:36:29 +02:00
static int zpci_clear_airq ( struct zpci_dev * zdev )
2012-11-29 13:05:05 +01:00
{
2012-12-11 14:53:35 +01:00
struct mod_pci_args args = { 0 , 0 , 0 , 0 } ;
2012-11-29 13:05:05 +01:00
return mod_pci ( zdev , ZPCI_MOD_FC_DEREG_INT , 0 , & args ) ;
}
2012-12-11 14:53:35 +01:00
/* Modify PCI: Set PCI function measurement parameters */
int zpci_fmb_enable_device ( struct zpci_dev * zdev )
{
struct mod_pci_args args = { 0 , 0 , 0 , 0 } ;
if ( zdev - > fmb )
return - EINVAL ;
2013-02-25 22:09:25 +08:00
zdev - > fmb = kmem_cache_zalloc ( zdev_fmb_cache , GFP_KERNEL ) ;
2012-12-11 14:53:35 +01:00
if ( ! zdev - > fmb )
return - ENOMEM ;
WARN_ON ( ( u64 ) zdev - > fmb & 0xf ) ;
args . fmb_addr = virt_to_phys ( zdev - > fmb ) ;
return mod_pci ( zdev , ZPCI_MOD_FC_SET_MEASURE , 0 , & args ) ;
}
/* Modify PCI: Disable PCI function measurement */
int zpci_fmb_disable_device ( struct zpci_dev * zdev )
{
struct mod_pci_args args = { 0 , 0 , 0 , 0 } ;
int rc ;
if ( ! zdev - > fmb )
return - EINVAL ;
/* Function measurement is disabled if fmb address is zero */
rc = mod_pci ( zdev , ZPCI_MOD_FC_SET_MEASURE , 0 , & args ) ;
kmem_cache_free ( zdev_fmb_cache , zdev - > fmb ) ;
zdev - > fmb = NULL ;
return rc ;
}
2012-11-29 12:50:30 +01:00
# define ZPCI_PCIAS_CFGSPC 15
static int zpci_cfg_load ( struct zpci_dev * zdev , int offset , u32 * val , u8 len )
{
u64 req = ZPCI_CREATE_REQ ( zdev - > fh , ZPCI_PCIAS_CFGSPC , len ) ;
u64 data ;
int rc ;
2013-06-25 14:52:23 +02:00
rc = zpci_load ( & data , req , offset ) ;
2013-04-16 14:17:15 +02:00
if ( ! rc ) {
data = data < < ( ( 8 - len ) * 8 ) ;
data = le64_to_cpu ( data ) ;
2012-11-29 12:50:30 +01:00
* val = ( u32 ) data ;
2013-04-16 14:17:15 +02:00
} else
2012-11-29 12:50:30 +01:00
* val = 0xffffffff ;
return rc ;
}
static int zpci_cfg_store ( struct zpci_dev * zdev , int offset , u32 val , u8 len )
{
u64 req = ZPCI_CREATE_REQ ( zdev - > fh , ZPCI_PCIAS_CFGSPC , len ) ;
u64 data = val ;
int rc ;
data = cpu_to_le64 ( data ) ;
data = data > > ( ( 8 - len ) * 8 ) ;
2013-06-25 14:52:23 +02:00
rc = zpci_store ( data , req , offset ) ;
2012-11-29 12:50:30 +01:00
return rc ;
}
2012-12-21 14:06:37 -08:00
void pcibios_fixup_bus ( struct pci_bus * bus )
2012-11-29 12:50:30 +01:00
{
}
resource_size_t pcibios_align_resource ( void * data , const struct resource * res ,
resource_size_t size ,
resource_size_t align )
{
return 0 ;
}
2012-12-06 14:30:28 +01:00
/* combine single writes by using store-block insn */
void __iowrite64_copy ( void __iomem * to , const void * from , size_t count )
{
zpci_memcpy_toio ( to , from , count ) ;
}
2012-11-29 12:50:30 +01:00
/* Create a virtual mapping cookie for a PCI BAR */
void __iomem * pci_iomap ( struct pci_dev * pdev , int bar , unsigned long max )
{
struct zpci_dev * zdev = get_zdev ( pdev ) ;
u64 addr ;
int idx ;
if ( ( bar & 7 ) ! = bar )
return NULL ;
idx = zdev - > bars [ bar ] . map_idx ;
spin_lock ( & zpci_iomap_lock ) ;
zpci_iomap_start [ idx ] . fh = zdev - > fh ;
zpci_iomap_start [ idx ] . bar = bar ;
spin_unlock ( & zpci_iomap_lock ) ;
addr = ZPCI_IOMAP_ADDR_BASE | ( ( u64 ) idx < < 48 ) ;
return ( void __iomem * ) addr ;
}
EXPORT_SYMBOL_GPL ( pci_iomap ) ;
void pci_iounmap ( struct pci_dev * pdev , void __iomem * addr )
{
unsigned int idx ;
idx = ( ( ( __force u64 ) addr ) & ~ ZPCI_IOMAP_ADDR_BASE ) > > 48 ;
spin_lock ( & zpci_iomap_lock ) ;
zpci_iomap_start [ idx ] . fh = 0 ;
zpci_iomap_start [ idx ] . bar = 0 ;
spin_unlock ( & zpci_iomap_lock ) ;
}
EXPORT_SYMBOL_GPL ( pci_iounmap ) ;
static int pci_read ( struct pci_bus * bus , unsigned int devfn , int where ,
int size , u32 * val )
{
struct zpci_dev * zdev = get_zdev_by_bus ( bus ) ;
2013-04-16 14:18:41 +02:00
int ret ;
2012-11-29 12:50:30 +01:00
if ( ! zdev | | devfn ! = ZPCI_DEVFN )
2013-04-16 14:18:41 +02:00
ret = - ENODEV ;
else
ret = zpci_cfg_load ( zdev , where , val , size ) ;
return ret ;
2012-11-29 12:50:30 +01:00
}
static int pci_write ( struct pci_bus * bus , unsigned int devfn , int where ,
int size , u32 val )
{
struct zpci_dev * zdev = get_zdev_by_bus ( bus ) ;
2013-04-16 14:18:41 +02:00
int ret ;
2012-11-29 12:50:30 +01:00
if ( ! zdev | | devfn ! = ZPCI_DEVFN )
2013-04-16 14:18:41 +02:00
ret = - ENODEV ;
else
ret = zpci_cfg_store ( zdev , where , val , size ) ;
return ret ;
2012-11-29 12:50:30 +01:00
}
static struct pci_ops pci_root_ops = {
. read = pci_read ,
. write = pci_write ,
} ;
2013-06-24 10:30:41 +02:00
static void zpci_irq_handler ( struct airq_struct * airq )
2012-11-29 13:05:05 +01:00
{
2013-06-25 16:36:29 +02:00
unsigned long si , ai ;
2013-06-27 09:01:09 +02:00
struct airq_iv * aibv ;
2013-06-25 16:36:29 +02:00
int irqs_on = 0 ;
2012-11-29 13:05:05 +01:00
2013-01-02 15:18:18 +01:00
inc_irq_stat ( IRQIO_PCI ) ;
2013-06-25 16:36:29 +02:00
for ( si = 0 ; ; ) {
/* Scan adapter summary indicator bit vector */
si = airq_iv_scan ( zpci_aisb_iv , si , airq_iv_end ( zpci_aisb_iv ) ) ;
if ( si = = - 1UL ) {
if ( irqs_on + + )
/* End of second scan with interrupts on. */
break ;
/* First scan complete, reenable interrupts. */
zpci_set_irq_ctrl ( SIC_IRQ_MODE_SINGLE , NULL , PCI_ISC ) ;
si = 0 ;
continue ;
}
2012-11-29 13:05:05 +01:00
2013-06-25 16:36:29 +02:00
/* Scan the adapter interrupt vector for this device. */
2013-06-27 09:01:09 +02:00
aibv = zpci_aibv [ si ] ;
2013-06-25 16:36:29 +02:00
for ( ai = 0 ; ; ) {
2013-06-27 09:01:09 +02:00
ai = airq_iv_scan ( aibv , ai , airq_iv_end ( aibv ) ) ;
2013-06-25 16:36:29 +02:00
if ( ai = = - 1UL )
break ;
2013-01-02 15:18:18 +01:00
inc_irq_stat ( IRQIO_MSI ) ;
2013-06-27 09:01:09 +02:00
airq_iv_lock ( aibv , ai ) ;
generic_handle_irq ( airq_iv_get_data ( aibv , ai ) ) ;
airq_iv_unlock ( aibv , ai ) ;
2012-11-29 13:05:05 +01:00
}
}
2013-06-25 16:36:29 +02:00
}
2012-11-29 13:05:05 +01:00
2013-06-25 16:36:29 +02:00
int arch_setup_msi_irqs ( struct pci_dev * pdev , int nvec , int type )
2012-11-29 13:05:05 +01:00
{
struct zpci_dev * zdev = get_zdev ( pdev ) ;
2014-05-07 15:44:19 +00:00
unsigned int hwirq , msi_vecs ;
2013-06-25 16:36:29 +02:00
unsigned long aisb ;
2012-11-29 13:05:05 +01:00
struct msi_desc * msi ;
2013-06-27 09:01:09 +02:00
struct msi_msg msg ;
2014-05-07 15:44:19 +00:00
int rc , irq ;
2012-11-29 13:05:05 +01:00
2013-12-16 09:34:54 +01:00
if ( type = = PCI_CAP_ID_MSI & & nvec > 1 )
return 1 ;
2013-06-25 16:36:29 +02:00
msi_vecs = min ( nvec , ZPCI_MSI_VEC_MAX ) ;
2013-06-27 09:01:09 +02:00
msi_vecs = min_t ( unsigned int , msi_vecs , CONFIG_PCI_NR_MSI ) ;
2012-11-29 13:05:05 +01:00
2013-06-25 16:36:29 +02:00
/* Allocate adapter summary indicator bit */
rc = - EIO ;
aisb = airq_iv_alloc_bit ( zpci_aisb_iv ) ;
if ( aisb = = - 1UL )
goto out ;
2012-11-29 13:05:05 +01:00
zdev - > aisb = aisb ;
2013-06-25 16:36:29 +02:00
/* Create adapter interrupt vector */
rc = - ENOMEM ;
2013-06-27 09:01:09 +02:00
zdev - > aibv = airq_iv_create ( msi_vecs , AIRQ_IV_DATA | AIRQ_IV_BITLOCK ) ;
2013-06-25 16:36:29 +02:00
if ( ! zdev - > aibv )
goto out_si ;
2012-11-29 13:05:05 +01:00
2013-06-25 16:36:29 +02:00
/* Wire up shortcut pointer */
2013-06-27 09:01:09 +02:00
zpci_aibv [ aisb ] = zdev - > aibv ;
2013-06-25 16:36:29 +02:00
2013-06-27 09:01:09 +02:00
/* Request MSI interrupts */
hwirq = 0 ;
2012-11-29 13:05:05 +01:00
list_for_each_entry ( msi , & pdev - > msi_list , list ) {
2013-06-27 09:01:09 +02:00
rc = - EIO ;
irq = irq_alloc_desc ( 0 ) ; /* Alloc irq on node 0 */
2014-05-07 15:44:19 +00:00
if ( irq < 0 )
2013-06-27 09:01:09 +02:00
goto out_msi ;
rc = irq_set_msi_desc ( irq , msi ) ;
2012-11-29 13:05:05 +01:00
if ( rc )
2013-06-25 16:36:29 +02:00
goto out_msi ;
2013-06-27 09:01:09 +02:00
irq_set_chip_and_handler ( irq , & zpci_irq_chip ,
handle_simple_irq ) ;
msg . data = hwirq ;
msg . address_lo = zdev - > msi_addr & 0xffffffff ;
msg . address_hi = zdev - > msi_addr > > 32 ;
write_msi_msg ( irq , & msg ) ;
airq_iv_set_data ( zdev - > aibv , hwirq , irq ) ;
hwirq + + ;
2012-11-29 13:05:05 +01:00
}
2013-06-25 16:36:29 +02:00
/* Enable adapter interrupts */
rc = zpci_set_airq ( zdev ) ;
if ( rc )
goto out_msi ;
return ( msi_vecs = = nvec ) ? 0 : msi_vecs ;
out_msi :
list_for_each_entry ( msi , & pdev - > msi_list , list ) {
2013-06-27 09:01:09 +02:00
if ( hwirq - - = = 0 )
2013-06-25 16:36:29 +02:00
break ;
2013-06-27 09:01:09 +02:00
irq_set_msi_desc ( msi - > irq , NULL ) ;
irq_free_desc ( msi - > irq ) ;
msi - > msg . address_lo = 0 ;
msi - > msg . address_hi = 0 ;
msi - > msg . data = 0 ;
msi - > irq = 0 ;
2012-11-29 13:05:05 +01:00
}
2013-06-27 09:01:09 +02:00
zpci_aibv [ aisb ] = NULL ;
2013-06-25 16:36:29 +02:00
airq_iv_release ( zdev - > aibv ) ;
out_si :
airq_iv_free_bit ( zpci_aisb_iv , aisb ) ;
out :
return rc ;
2012-11-29 13:05:05 +01:00
}
2013-06-25 16:36:29 +02:00
void arch_teardown_msi_irqs ( struct pci_dev * pdev )
2012-11-29 13:05:05 +01:00
{
struct zpci_dev * zdev = get_zdev ( pdev ) ;
struct msi_desc * msi ;
2013-06-25 16:36:29 +02:00
int rc ;
/* Disable adapter interrupts */
rc = zpci_clear_airq ( zdev ) ;
2013-10-22 15:17:19 +02:00
if ( rc )
2012-11-29 13:05:05 +01:00
return ;
2013-06-27 09:01:09 +02:00
/* Release MSI interrupts */
list_for_each_entry ( msi , & pdev - > msi_list , list ) {
2014-07-08 10:08:05 +08:00
if ( msi - > msi_attrib . is_msix )
default_msix_mask_irq ( msi , 1 ) ;
else
default_msi_mask_irq ( msi , 1 , 1 ) ;
2013-06-27 09:01:09 +02:00
irq_set_msi_desc ( msi - > irq , NULL ) ;
irq_free_desc ( msi - > irq ) ;
msi - > msg . address_lo = 0 ;
msi - > msg . address_hi = 0 ;
msi - > msg . data = 0 ;
msi - > irq = 0 ;
}
2012-11-29 13:05:05 +01:00
2013-06-27 09:01:09 +02:00
zpci_aibv [ zdev - > aisb ] = NULL ;
2013-06-25 16:36:29 +02:00
airq_iv_release ( zdev - > aibv ) ;
airq_iv_free_bit ( zpci_aisb_iv , zdev - > aisb ) ;
2012-11-29 13:05:05 +01:00
}
2012-11-29 12:50:30 +01:00
static void zpci_map_resources ( struct zpci_dev * zdev )
{
struct pci_dev * pdev = zdev - > pdev ;
resource_size_t len ;
int i ;
for ( i = 0 ; i < PCI_BAR_COUNT ; i + + ) {
len = pci_resource_len ( pdev , i ) ;
if ( ! len )
continue ;
pdev - > resource [ i ] . start = ( resource_size_t ) pci_iomap ( pdev , i , 0 ) ;
pdev - > resource [ i ] . end = pdev - > resource [ i ] . start + len - 1 ;
}
2013-06-05 16:06:16 +02:00
}
static void zpci_unmap_resources ( struct zpci_dev * zdev )
{
struct pci_dev * pdev = zdev - > pdev ;
resource_size_t len ;
int i ;
for ( i = 0 ; i < PCI_BAR_COUNT ; i + + ) {
len = pci_resource_len ( pdev , i ) ;
if ( ! len )
continue ;
pci_iounmap ( pdev , ( void * ) pdev - > resource [ i ] . start ) ;
}
}
2012-11-29 12:50:30 +01:00
2012-11-29 13:05:05 +01:00
static int __init zpci_irq_init ( void )
{
2013-06-25 16:36:29 +02:00
int rc ;
2012-11-29 13:05:05 +01:00
2013-06-24 10:30:41 +02:00
rc = register_adapter_interrupt ( & zpci_airq ) ;
if ( rc )
2013-06-25 16:36:29 +02:00
goto out ;
2013-06-24 10:30:41 +02:00
/* Set summary to 1 to be called every time for the ISC. */
* zpci_airq . lsi_ptr = 1 ;
2012-11-29 13:05:05 +01:00
2013-06-25 16:36:29 +02:00
rc = - ENOMEM ;
zpci_aisb_iv = airq_iv_create ( ZPCI_NR_DEVICES , AIRQ_IV_ALLOC ) ;
if ( ! zpci_aisb_iv )
goto out_airq ;
2012-11-29 13:05:05 +01:00
2013-06-25 14:52:23 +02:00
zpci_set_irq_ctrl ( SIC_IRQ_MODE_SINGLE , NULL , PCI_ISC ) ;
2012-11-29 13:05:05 +01:00
return 0 ;
2013-06-25 16:36:29 +02:00
out_airq :
unregister_adapter_interrupt ( & zpci_airq ) ;
out :
2012-11-29 13:05:05 +01:00
return rc ;
}
static void zpci_irq_exit ( void )
{
2013-06-25 16:36:29 +02:00
airq_iv_release ( zpci_aisb_iv ) ;
2013-06-24 10:30:41 +02:00
unregister_adapter_interrupt ( & zpci_airq ) ;
2012-11-29 13:05:05 +01:00
}
2012-11-29 12:50:30 +01:00
static int zpci_alloc_iomap ( struct zpci_dev * zdev )
{
int entry ;
spin_lock ( & zpci_iomap_lock ) ;
entry = find_first_zero_bit ( zpci_iomap , ZPCI_IOMAP_MAX_ENTRIES ) ;
if ( entry = = ZPCI_IOMAP_MAX_ENTRIES ) {
spin_unlock ( & zpci_iomap_lock ) ;
return - ENOSPC ;
}
set_bit ( entry , zpci_iomap ) ;
spin_unlock ( & zpci_iomap_lock ) ;
return entry ;
}
static void zpci_free_iomap ( struct zpci_dev * zdev , int entry )
{
spin_lock ( & zpci_iomap_lock ) ;
memset ( & zpci_iomap_start [ entry ] , 0 , sizeof ( struct zpci_iomap_entry ) ) ;
clear_bit ( entry , zpci_iomap ) ;
spin_unlock ( & zpci_iomap_lock ) ;
}
2013-11-12 19:33:06 +01:00
static struct resource * __alloc_res ( struct zpci_dev * zdev , unsigned long start ,
unsigned long size , unsigned long flags )
{
struct resource * r ;
r = kzalloc ( sizeof ( * r ) , GFP_KERNEL ) ;
if ( ! r )
return NULL ;
r - > start = start ;
r - > end = r - > start + size - 1 ;
r - > flags = flags ;
r - > name = zdev - > res_name ;
if ( request_resource ( & iomem_resource , r ) ) {
kfree ( r ) ;
return NULL ;
}
return r ;
}
static int zpci_setup_bus_resources ( struct zpci_dev * zdev ,
struct list_head * resources )
{
unsigned long addr , size , flags ;
struct resource * res ;
int i , entry ;
snprintf ( zdev - > res_name , sizeof ( zdev - > res_name ) ,
" PCI Bus %04x:%02x " , zdev - > domain , ZPCI_BUS_NR ) ;
for ( i = 0 ; i < PCI_BAR_COUNT ; i + + ) {
if ( ! zdev - > bars [ i ] . size )
continue ;
entry = zpci_alloc_iomap ( zdev ) ;
if ( entry < 0 )
return entry ;
zdev - > bars [ i ] . map_idx = entry ;
/* only MMIO is supported */
flags = IORESOURCE_MEM ;
if ( zdev - > bars [ i ] . val & 8 )
flags | = IORESOURCE_PREFETCH ;
if ( zdev - > bars [ i ] . val & 4 )
flags | = IORESOURCE_MEM_64 ;
addr = ZPCI_IOMAP_ADDR_BASE + ( ( u64 ) entry < < 48 ) ;
size = 1UL < < zdev - > bars [ i ] . size ;
res = __alloc_res ( zdev , addr , size , flags ) ;
if ( ! res ) {
zpci_free_iomap ( zdev , entry ) ;
return - ENOMEM ;
}
zdev - > bars [ i ] . res = res ;
pci_add_resource ( resources , res ) ;
}
return 0 ;
}
static void zpci_cleanup_bus_resources ( struct zpci_dev * zdev )
{
int i ;
for ( i = 0 ; i < PCI_BAR_COUNT ; i + + ) {
if ( ! zdev - > bars [ i ] . size )
continue ;
zpci_free_iomap ( zdev , zdev - > bars [ i ] . map_idx ) ;
release_resource ( zdev - > bars [ i ] . res ) ;
kfree ( zdev - > bars [ i ] . res ) ;
}
}
2013-04-16 14:13:21 +02:00
int pcibios_add_device ( struct pci_dev * pdev )
{
struct zpci_dev * zdev = get_zdev ( pdev ) ;
2013-08-29 19:34:37 +02:00
struct resource * res ;
int i ;
zdev - > pdev = pdev ;
2014-04-30 14:50:09 -06:00
pdev - > dev . groups = zpci_attr_groups ;
2013-08-29 19:34:37 +02:00
zpci_map_resources ( zdev ) ;
for ( i = 0 ; i < PCI_BAR_COUNT ; i + + ) {
res = & pdev - > resource [ i ] ;
if ( res - > parent | | ! res - > flags )
continue ;
pci_claim_resource ( pdev , i ) ;
}
return 0 ;
}
int pcibios_enable_device ( struct pci_dev * pdev , int mask )
{
struct zpci_dev * zdev = get_zdev ( pdev ) ;
2013-04-16 14:13:21 +02:00
2013-04-25 14:49:48 +02:00
zdev - > pdev = pdev ;
2013-04-16 14:13:21 +02:00
zpci_debug_init_device ( zdev ) ;
zpci_fmb_enable_device ( zdev ) ;
zpci_map_resources ( zdev ) ;
2014-02-26 15:30:24 -07:00
return pci_enable_resources ( pdev , mask ) ;
2013-04-16 14:13:21 +02:00
}
2013-08-29 19:34:37 +02:00
void pcibios_disable_device ( struct pci_dev * pdev )
2013-06-05 16:06:16 +02:00
{
struct zpci_dev * zdev = get_zdev ( pdev ) ;
zpci_unmap_resources ( zdev ) ;
zpci_fmb_disable_device ( zdev ) ;
zpci_debug_exit_device ( zdev ) ;
zdev - > pdev = NULL ;
}
2013-09-25 12:27:43 +02:00
# ifdef CONFIG_HIBERNATE_CALLBACKS
static int zpci_restore ( struct device * dev )
{
struct zpci_dev * zdev = get_zdev ( to_pci_dev ( dev ) ) ;
int ret = 0 ;
if ( zdev - > state ! = ZPCI_FN_STATE_ONLINE )
goto out ;
ret = clp_enable_fh ( zdev , ZPCI_NR_DMA_SPACES ) ;
if ( ret )
goto out ;
zpci_map_resources ( zdev ) ;
zpci_register_ioat ( zdev , 0 , zdev - > start_dma + PAGE_OFFSET ,
zdev - > start_dma + zdev - > iommu_size - 1 ,
( u64 ) zdev - > dma_table ) ;
out :
return ret ;
}
static int zpci_freeze ( struct device * dev )
{
struct zpci_dev * zdev = get_zdev ( to_pci_dev ( dev ) ) ;
if ( zdev - > state ! = ZPCI_FN_STATE_ONLINE )
return 0 ;
zpci_unregister_ioat ( zdev , 0 ) ;
return clp_disable_fh ( zdev ) ;
}
struct dev_pm_ops pcibios_pm_ops = {
. thaw_noirq = zpci_restore ,
. freeze_noirq = zpci_freeze ,
. restore_noirq = zpci_restore ,
. poweroff_noirq = zpci_freeze ,
} ;
# endif /* CONFIG_HIBERNATE_CALLBACKS */
2012-11-29 12:50:30 +01:00
static int zpci_alloc_domain ( struct zpci_dev * zdev )
{
spin_lock ( & zpci_domain_lock ) ;
zdev - > domain = find_first_zero_bit ( zpci_domain , ZPCI_NR_DEVICES ) ;
if ( zdev - > domain = = ZPCI_NR_DEVICES ) {
spin_unlock ( & zpci_domain_lock ) ;
return - ENOSPC ;
}
set_bit ( zdev - > domain , zpci_domain ) ;
spin_unlock ( & zpci_domain_lock ) ;
return 0 ;
}
static void zpci_free_domain ( struct zpci_dev * zdev )
{
spin_lock ( & zpci_domain_lock ) ;
clear_bit ( zdev - > domain , zpci_domain ) ;
spin_unlock ( & zpci_domain_lock ) ;
}
2013-11-12 19:35:01 +01:00
void pcibios_remove_bus ( struct pci_bus * bus )
{
struct zpci_dev * zdev = get_zdev_by_bus ( bus ) ;
zpci_exit_slot ( zdev ) ;
zpci_cleanup_bus_resources ( zdev ) ;
zpci_free_domain ( zdev ) ;
spin_lock ( & zpci_list_lock ) ;
list_del ( & zdev - > entry ) ;
spin_unlock ( & zpci_list_lock ) ;
kfree ( zdev ) ;
}
static int zpci_scan_bus ( struct zpci_dev * zdev )
{
LIST_HEAD ( resources ) ;
int ret ;
ret = zpci_setup_bus_resources ( zdev , & resources ) ;
if ( ret )
return ret ;
zdev - > bus = pci_scan_root_bus ( NULL , ZPCI_BUS_NR , & pci_root_ops ,
zdev , & resources ) ;
if ( ! zdev - > bus ) {
zpci_cleanup_bus_resources ( zdev ) ;
return - EIO ;
}
zdev - > bus - > max_bus_speed = zdev - > max_bus_speed ;
return 0 ;
}
2012-11-29 12:55:21 +01:00
int zpci_enable_device ( struct zpci_dev * zdev )
{
int rc ;
rc = clp_enable_fh ( zdev , ZPCI_NR_DMA_SPACES ) ;
if ( rc )
goto out ;
2012-11-29 14:33:30 +01:00
rc = zpci_dma_init_device ( zdev ) ;
if ( rc )
goto out_dma ;
2013-08-29 19:35:19 +02:00
zdev - > state = ZPCI_FN_STATE_ONLINE ;
2012-11-29 12:55:21 +01:00
return 0 ;
2012-11-29 14:33:30 +01:00
out_dma :
clp_disable_fh ( zdev ) ;
2012-11-29 12:55:21 +01:00
out :
return rc ;
}
EXPORT_SYMBOL_GPL ( zpci_enable_device ) ;
2013-04-16 14:12:17 +02:00
int zpci_disable_device ( struct zpci_dev * zdev )
{
zpci_dma_exit_device ( zdev ) ;
return clp_disable_fh ( zdev ) ;
}
EXPORT_SYMBOL_GPL ( zpci_disable_device ) ;
2012-11-29 12:50:30 +01:00
int zpci_create_device ( struct zpci_dev * zdev )
{
int rc ;
rc = zpci_alloc_domain ( zdev ) ;
if ( rc )
goto out ;
2013-04-25 14:49:48 +02:00
if ( zdev - > state = = ZPCI_FN_STATE_CONFIGURED ) {
rc = zpci_enable_device ( zdev ) ;
if ( rc )
goto out_free ;
}
rc = zpci_scan_bus ( zdev ) ;
2012-11-29 12:50:30 +01:00
if ( rc )
2013-04-25 14:49:48 +02:00
goto out_disable ;
2012-11-29 12:50:30 +01:00
2013-08-29 19:40:01 +02:00
spin_lock ( & zpci_list_lock ) ;
2012-11-29 12:50:30 +01:00
list_add_tail ( & zdev - > entry , & zpci_list ) ;
2013-08-29 19:40:01 +02:00
spin_unlock ( & zpci_list_lock ) ;
2012-11-29 12:50:30 +01:00
2013-08-29 19:33:16 +02:00
zpci_init_slot ( zdev ) ;
2012-11-29 12:50:30 +01:00
return 0 ;
2013-04-25 14:49:48 +02:00
out_disable :
if ( zdev - > state = = ZPCI_FN_STATE_ONLINE )
zpci_disable_device ( zdev ) ;
out_free :
2012-11-29 12:50:30 +01:00
zpci_free_domain ( zdev ) ;
out :
return rc ;
}
void zpci_stop_device ( struct zpci_dev * zdev )
{
2012-11-29 14:33:30 +01:00
zpci_dma_exit_device ( zdev ) ;
2012-11-29 12:50:30 +01:00
/*
* Note : SCLP disables fh via set - pci - fn so don ' t
* do that here .
*/
}
EXPORT_SYMBOL_GPL ( zpci_stop_device ) ;
static inline int barsize ( u8 size )
{
return ( size ) ? ( 1 < < size ) > > 10 : 0 ;
}
static int zpci_mem_init ( void )
{
2012-12-11 14:53:35 +01:00
zdev_fmb_cache = kmem_cache_create ( " PCI_FMB_cache " , sizeof ( struct zpci_fmb ) ,
16 , 0 , NULL ) ;
if ( ! zdev_fmb_cache )
2013-06-27 09:01:09 +02:00
goto error_zdev ;
2012-12-11 14:53:35 +01:00
2012-11-29 12:50:30 +01:00
/* TODO: use realloc */
zpci_iomap_start = kzalloc ( ZPCI_IOMAP_MAX_ENTRIES * sizeof ( * zpci_iomap_start ) ,
GFP_KERNEL ) ;
if ( ! zpci_iomap_start )
2012-11-29 13:05:05 +01:00
goto error_iomap ;
2012-11-29 12:50:30 +01:00
return 0 ;
2012-11-29 13:05:05 +01:00
error_iomap :
2012-12-11 14:53:35 +01:00
kmem_cache_destroy ( zdev_fmb_cache ) ;
2012-11-29 12:50:30 +01:00
error_zdev :
return - ENOMEM ;
}
static void zpci_mem_exit ( void )
{
kfree ( zpci_iomap_start ) ;
2012-12-11 14:53:35 +01:00
kmem_cache_destroy ( zdev_fmb_cache ) ;
2012-11-29 12:50:30 +01:00
}
2013-12-12 17:55:22 +01:00
static unsigned int s390_pci_probe = 1 ;
2013-12-12 17:48:32 +01:00
static unsigned int s390_pci_initialized ;
2012-11-29 12:50:30 +01:00
char * __init pcibios_setup ( char * str )
{
2013-12-12 17:55:22 +01:00
if ( ! strcmp ( str , " off " ) ) {
s390_pci_probe = 0 ;
2012-11-29 12:50:30 +01:00
return NULL ;
}
return str ;
}
2013-12-12 17:48:32 +01:00
bool zpci_is_enabled ( void )
{
return s390_pci_initialized ;
}
2012-11-29 12:50:30 +01:00
static int __init pci_base_init ( void )
{
int rc ;
2013-01-30 15:52:16 +01:00
if ( ! s390_pci_probe )
2012-11-29 12:50:30 +01:00
return 0 ;
if ( ! test_facility ( 2 ) | | ! test_facility ( 69 )
| | ! test_facility ( 71 ) | | ! test_facility ( 72 ) )
return 0 ;
2012-12-11 14:53:35 +01:00
rc = zpci_debug_init ( ) ;
if ( rc )
2013-06-27 09:01:09 +02:00
goto out ;
2012-12-11 14:53:35 +01:00
2012-11-29 12:50:30 +01:00
rc = zpci_mem_init ( ) ;
if ( rc )
goto out_mem ;
2012-11-29 13:05:05 +01:00
rc = zpci_irq_init ( ) ;
if ( rc )
goto out_irq ;
2012-11-29 14:33:30 +01:00
rc = zpci_dma_init ( ) ;
if ( rc )
goto out_dma ;
2013-08-29 19:37:28 +02:00
rc = clp_scan_pci_devices ( ) ;
2012-11-29 12:55:21 +01:00
if ( rc )
goto out_find ;
2013-12-12 17:48:32 +01:00
s390_pci_initialized = 1 ;
2012-11-29 12:50:30 +01:00
return 0 ;
2012-11-29 12:55:21 +01:00
out_find :
2012-11-29 14:33:30 +01:00
zpci_dma_exit ( ) ;
out_dma :
2012-11-29 13:05:05 +01:00
zpci_irq_exit ( ) ;
out_irq :
2012-11-29 12:50:30 +01:00
zpci_mem_exit ( ) ;
out_mem :
2012-12-11 14:53:35 +01:00
zpci_debug_exit ( ) ;
2013-06-27 09:01:09 +02:00
out :
2012-11-29 12:50:30 +01:00
return rc ;
}
2013-08-29 19:33:16 +02:00
subsys_initcall_sync ( pci_base_init ) ;
2013-08-29 19:40:01 +02:00
void zpci_rescan ( void )
{
2013-12-12 17:48:32 +01:00
if ( zpci_is_enabled ( ) )
clp_rescan_pci_devices_simple ( ) ;
2013-08-29 19:40:01 +02:00
}