2005-04-17 02:20:36 +04:00
/*
* pci_bind . c - ACPI PCI Device Binding ( $ Revision : 2 $ )
*
* Copyright ( C ) 2001 , 2002 Andy Grover < andrew . grover @ intel . com >
* Copyright ( C ) 2001 , 2002 Paul Diefenbaugh < paul . s . diefenbaugh @ intel . com >
*
* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or ( at
* your option ) any later version .
*
* This program is distributed in the hope that it will be useful , but
* WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* General Public License for more details .
*
* You should have received a copy of the GNU General Public License along
* with this program ; if not , write to the Free Software Foundation , Inc . ,
* 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA .
*
* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
*/
# include <linux/kernel.h>
# include <linux/types.h>
# include <linux/pci.h>
2010-02-18 01:44:09 +03:00
# include <linux/pci-acpi.h>
2005-04-17 02:20:36 +04:00
# include <linux/acpi.h>
2010-02-18 01:44:09 +03:00
# include <linux/pm_runtime.h>
2005-04-17 02:20:36 +04:00
# include <acpi/acpi_bus.h>
# include <acpi/acpi_drivers.h>
# define _COMPONENT ACPI_PCI_COMPONENT
2007-02-13 06:42:12 +03:00
ACPI_MODULE_NAME ( " pci_bind " ) ;
2005-04-17 02:20:36 +04:00
2009-06-10 23:55:25 +04:00
static int acpi_pci_unbind ( struct acpi_device * device )
{
2009-06-10 23:55:30 +04:00
struct pci_dev * dev ;
2009-06-10 23:55:25 +04:00
2009-06-10 23:55:30 +04:00
dev = acpi_get_pci_dev ( device - > handle ) ;
2010-02-18 01:44:09 +03:00
if ( ! dev )
goto out ;
device_set_run_wake ( & dev - > dev , false ) ;
pci_acpi_remove_pm_notifier ( device ) ;
if ( ! dev - > subordinate )
2009-06-10 23:55:45 +04:00
goto out ;
acpi_pci_irq_del_prt ( dev - > subordinate ) ;
2009-06-10 23:55:25 +04:00
2009-06-10 23:55:45 +04:00
device - > ops . bind = NULL ;
device - > ops . unbind = NULL ;
2009-06-10 23:55:25 +04:00
2009-06-10 23:55:45 +04:00
out :
2009-06-10 23:55:30 +04:00
pci_dev_put ( dev ) ;
return 0 ;
2009-06-10 23:55:25 +04:00
}
2009-06-10 23:55:09 +04:00
static int acpi_pci_bind ( struct acpi_device * device )
2005-04-17 02:20:36 +04:00
{
2008-12-31 06:44:33 +03:00
acpi_status status ;
acpi_handle handle ;
2009-06-10 23:55:35 +04:00
struct pci_bus * bus ;
2009-06-10 23:55:30 +04:00
struct pci_dev * dev ;
2005-04-17 02:20:36 +04:00
2009-06-10 23:55:30 +04:00
dev = acpi_get_pci_dev ( device - > handle ) ;
if ( ! dev )
return 0 ;
2005-04-17 02:20:36 +04:00
2010-02-18 01:44:09 +03:00
pci_acpi_add_pm_notifier ( device , dev ) ;
if ( device - > wakeup . flags . run_wake )
device_set_run_wake ( & dev - > dev , true ) ;
2005-04-17 02:20:36 +04:00
/*
2009-06-10 23:55:30 +04:00
* Install the ' bind ' function to facilitate callbacks for
* children of the P2P bridge .
2005-04-17 02:20:36 +04:00
*/
2009-06-10 23:55:30 +04:00
if ( dev - > subordinate ) {
2005-08-05 08:44:28 +04:00
ACPI_DEBUG_PRINT ( ( ACPI_DB_INFO ,
2008-12-09 07:30:05 +03:00
" Device %04x:%02x:%02x.%d is a PCI bridge \n " ,
2009-06-10 23:55:30 +04:00
pci_domain_nr ( dev - > bus ) , dev - > bus - > number ,
PCI_SLOT ( dev - > devfn ) , PCI_FUNC ( dev - > devfn ) ) ) ;
2005-04-17 02:20:36 +04:00
device - > ops . bind = acpi_pci_bind ;
device - > ops . unbind = acpi_pci_unbind ;
}
/*
2009-06-10 23:55:30 +04:00
* Evaluate and parse _PRT , if exists . This code allows parsing of
* _PRT objects within the scope of non - bridge devices . Note that
* _PRTs within the scope of a PCI bridge assume the bridge ' s
* subordinate bus number .
2005-04-17 02:20:36 +04:00
*
* TBD : Can _PRTs exist within the scope of non - bridge PCI devices ?
*/
status = acpi_get_handle ( device - > handle , METHOD_NAME__PRT , & handle ) ;
2009-06-10 23:55:30 +04:00
if ( ACPI_FAILURE ( status ) )
goto out ;
2005-04-17 02:20:36 +04:00
2009-06-10 23:55:30 +04:00
if ( dev - > subordinate )
2009-06-10 23:55:35 +04:00
bus = dev - > subordinate ;
2009-06-10 23:55:30 +04:00
else
2009-06-10 23:55:35 +04:00
bus = dev - > bus ;
2005-04-17 02:20:36 +04:00
2009-06-10 23:55:35 +04:00
acpi_pci_irq_add_prt ( device - > handle , bus ) ;
2005-04-17 02:20:36 +04:00
2009-06-10 23:55:30 +04:00
out :
pci_dev_put ( dev ) ;
return 0 ;
}
2005-04-17 02:20:36 +04:00
2009-06-10 23:55:30 +04:00
int acpi_pci_bind_root ( struct acpi_device * device )
{
2005-04-17 02:20:36 +04:00
device - > ops . bind = acpi_pci_bind ;
device - > ops . unbind = acpi_pci_unbind ;
2009-06-10 23:55:30 +04:00
return 0 ;
2005-04-17 02:20:36 +04:00
}