2009-11-12 09:27:40 +03:00
# include <linux/init.h>
# include <linux/pci.h>
2010-02-10 12:20:11 +03:00
# include <linux/range.h>
2009-11-12 09:27:40 +03:00
# include "bus_numa.h"
2012-04-03 05:31:54 +04:00
LIST_HEAD ( pci_root_infos ) ;
2009-11-12 09:27:40 +03:00
2012-04-03 05:31:54 +04:00
static struct pci_root_info * x86_find_pci_root_info ( int bus )
2009-11-12 09:27:40 +03:00
{
struct pci_root_info * info ;
2012-04-03 05:31:54 +04:00
list_for_each_entry ( info , & pci_root_infos , list )
2012-05-18 05:51:12 +04:00
if ( info - > busn . start = = bus )
2012-04-03 05:31:54 +04:00
return info ;
return NULL ;
}
2009-11-12 09:27:40 +03:00
2014-01-24 22:54:36 +04:00
int x86_pci_root_bus_node ( int bus )
{
struct pci_root_info * info = x86_find_pci_root_info ( bus ) ;
if ( ! info )
return NUMA_NO_NODE ;
return info - > node ;
}
2012-04-03 05:31:54 +04:00
void x86_pci_root_bus_resources ( int bus , struct list_head * resources )
{
struct pci_root_info * info = x86_find_pci_root_info ( bus ) ;
struct pci_root_res * root_res ;
2015-02-05 08:44:44 +03:00
struct resource_entry * window ;
2012-05-18 05:51:12 +04:00
bool found = false ;
2012-04-03 05:31:54 +04:00
if ( ! info )
2011-10-29 02:28:14 +04:00
goto default_resources ;
2009-11-12 09:27:40 +03:00
2011-10-29 02:28:14 +04:00
printk ( KERN_DEBUG " PCI: root bus %02x: hardware-probed resources \n " ,
bus ) ;
2009-11-12 09:27:40 +03:00
2012-05-18 05:51:12 +04:00
/* already added by acpi ? */
2015-02-05 08:44:44 +03:00
resource_list_for_each_entry ( window , resources )
2012-05-18 05:51:12 +04:00
if ( window - > res - > flags & IORESOURCE_BUS ) {
found = true ;
break ;
}
if ( ! found )
pci_add_resource ( resources , & info - > busn ) ;
2015-11-27 06:12:33 +03:00
list_for_each_entry ( root_res , & info - > resources , list )
pci_add_resource ( resources , & root_res - > res ) ;
2011-10-29 02:28:14 +04:00
return ;
default_resources :
/*
* We don ' t have any host bridge aperture information from the
* " native host bridge drivers, " e . g . , amd_bus or broadcom_bus ,
* so fall back to the defaults historically used by pci_create_bus ( ) .
*/
printk ( KERN_DEBUG " PCI: root bus %02x: using default resources \n " , bus ) ;
pci_add_resource ( resources , & ioport_resource ) ;
pci_add_resource ( resources , & iomem_resource ) ;
2009-11-12 09:27:40 +03:00
}
2012-04-03 05:31:54 +04:00
struct pci_root_info __init * alloc_pci_root_info ( int bus_min , int bus_max ,
int node , int link )
{
struct pci_root_info * info ;
info = kzalloc ( sizeof ( * info ) , GFP_KERNEL ) ;
if ( ! info )
return info ;
2012-05-18 05:51:12 +04:00
sprintf ( info - > name , " PCI Bus #%02x " , bus_min ) ;
2012-04-03 05:31:54 +04:00
INIT_LIST_HEAD ( & info - > resources ) ;
2012-05-18 05:51:12 +04:00
info - > busn . name = info - > name ;
info - > busn . start = bus_min ;
info - > busn . end = bus_max ;
info - > busn . flags = IORESOURCE_BUS ;
2012-04-03 05:31:54 +04:00
info - > node = node ;
info - > link = link ;
list_add_tail ( & info - > list , & pci_root_infos ) ;
return info ;
}
2012-12-22 02:02:53 +04:00
void update_res ( struct pci_root_info * info , resource_size_t start ,
resource_size_t end , unsigned long flags , int merge )
2009-11-12 09:27:40 +03:00
{
struct resource * res ;
2012-04-03 05:31:54 +04:00
struct pci_root_res * root_res ;
2009-11-12 09:27:40 +03:00
if ( start > end )
return ;
2010-02-10 12:20:11 +03:00
if ( start = = MAX_RESOURCE )
return ;
2009-11-12 09:27:40 +03:00
if ( ! merge )
goto addit ;
/* try to merge it with old one */
2012-04-03 05:31:54 +04:00
list_for_each_entry ( root_res , & info - > resources , list ) {
2010-02-10 12:20:08 +03:00
resource_size_t final_start , final_end ;
resource_size_t common_start , common_end ;
2009-11-12 09:27:40 +03:00
2012-04-03 05:31:54 +04:00
res = & root_res - > res ;
2009-11-12 09:27:40 +03:00
if ( res - > flags ! = flags )
continue ;
2010-02-10 12:20:08 +03:00
common_start = max ( res - > start , start ) ;
common_end = min ( res - > end , end ) ;
2009-11-12 09:27:40 +03:00
if ( common_start > common_end + 1 )
continue ;
2010-02-10 12:20:08 +03:00
final_start = min ( res - > start , start ) ;
final_end = max ( res - > end , end ) ;
2009-11-12 09:27:40 +03:00
res - > start = final_start ;
res - > end = final_end ;
return ;
}
addit :
/* need to add that */
2012-04-03 05:31:54 +04:00
root_res = kzalloc ( sizeof ( * root_res ) , GFP_KERNEL ) ;
if ( ! root_res )
2009-11-12 09:27:40 +03:00
return ;
2012-04-03 05:31:54 +04:00
res = & root_res - > res ;
2009-11-12 09:27:40 +03:00
res - > name = info - > name ;
res - > flags = flags ;
res - > start = start ;
res - > end = end ;
2012-04-03 05:31:54 +04:00
list_add_tail ( & root_res - > list , & info - > resources ) ;
2009-11-12 09:27:40 +03:00
}