2005-04-17 02:20:36 +04:00
/*
* manager . c - Resource Management , Conflict Resolution , Activation and Disabling of Devices
*
2007-10-15 11:50:19 +04:00
* based on isapnp . c resource management ( c ) Jaroslav Kysela < perex @ perex . cz >
2005-04-17 02:20:36 +04:00
* Copyright 2003 Adam Belay < ambx1 @ neo . rr . com >
*/
# include <linux/errno.h>
# include <linux/module.h>
# include <linux/init.h>
# include <linux/kernel.h>
# include <linux/pnp.h>
2005-10-31 02:03:48 +03:00
# include <linux/slab.h>
# include <linux/bitmap.h>
2008-02-06 12:40:04 +03:00
# include <linux/mutex.h>
2005-04-17 02:20:36 +04:00
# include "base.h"
2008-02-06 12:40:04 +03:00
DEFINE_MUTEX ( pnp_res_mutex ) ;
2005-04-17 02:20:36 +04:00
static int pnp_assign_port ( struct pnp_dev * dev , struct pnp_port * rule , int idx )
{
2006-06-13 04:07:07 +04:00
resource_size_t * start , * end ;
unsigned long * flags ;
2005-04-17 02:20:36 +04:00
if ( idx > = PNP_MAX_PORT ) {
2007-10-17 10:31:10 +04:00
dev_err ( & dev - > dev , " too many I/O port resources \n " ) ;
2005-04-17 02:20:36 +04:00
/* pretend we were successful so at least the manager won't try again */
return 1 ;
}
/* check if this resource has been manually set, if so skip */
if ( ! ( dev - > res . port_resource [ idx ] . flags & IORESOURCE_AUTO ) )
return 1 ;
start = & dev - > res . port_resource [ idx ] . start ;
end = & dev - > res . port_resource [ idx ] . end ;
flags = & dev - > res . port_resource [ idx ] . flags ;
/* set the initial values */
* flags | = rule - > flags | IORESOURCE_IO ;
2007-07-26 21:41:20 +04:00
* flags & = ~ IORESOURCE_UNSET ;
2005-04-17 02:20:36 +04:00
if ( ! rule - > size ) {
* flags | = IORESOURCE_DISABLED ;
2007-07-26 21:41:20 +04:00
return 1 ; /* skip disabled resource requests */
2005-04-17 02:20:36 +04:00
}
* start = rule - > min ;
* end = * start + rule - > size - 1 ;
/* run through until pnp_check_port is happy */
while ( ! pnp_check_port ( dev , idx ) ) {
* start + = rule - > align ;
* end = * start + rule - > size - 1 ;
if ( * start > rule - > max | | ! rule - > align )
return 0 ;
}
return 1 ;
}
static int pnp_assign_mem ( struct pnp_dev * dev , struct pnp_mem * rule , int idx )
{
2006-06-13 04:07:07 +04:00
resource_size_t * start , * end ;
unsigned long * flags ;
2005-04-17 02:20:36 +04:00
if ( idx > = PNP_MAX_MEM ) {
2007-10-17 10:31:10 +04:00
dev_err ( & dev - > dev , " too many memory resources \n " ) ;
2005-04-17 02:20:36 +04:00
/* pretend we were successful so at least the manager won't try again */
return 1 ;
}
/* check if this resource has been manually set, if so skip */
if ( ! ( dev - > res . mem_resource [ idx ] . flags & IORESOURCE_AUTO ) )
return 1 ;
start = & dev - > res . mem_resource [ idx ] . start ;
end = & dev - > res . mem_resource [ idx ] . end ;
flags = & dev - > res . mem_resource [ idx ] . flags ;
/* set the initial values */
* flags | = rule - > flags | IORESOURCE_MEM ;
2007-07-26 21:41:20 +04:00
* flags & = ~ IORESOURCE_UNSET ;
2005-04-17 02:20:36 +04:00
/* convert pnp flags to standard Linux flags */
if ( ! ( rule - > flags & IORESOURCE_MEM_WRITEABLE ) )
* flags | = IORESOURCE_READONLY ;
if ( rule - > flags & IORESOURCE_MEM_CACHEABLE )
* flags | = IORESOURCE_CACHEABLE ;
if ( rule - > flags & IORESOURCE_MEM_RANGELENGTH )
* flags | = IORESOURCE_RANGELENGTH ;
if ( rule - > flags & IORESOURCE_MEM_SHADOWABLE )
* flags | = IORESOURCE_SHADOWABLE ;
if ( ! rule - > size ) {
* flags | = IORESOURCE_DISABLED ;
2007-07-26 21:41:20 +04:00
return 1 ; /* skip disabled resource requests */
2005-04-17 02:20:36 +04:00
}
* start = rule - > min ;
2007-07-26 21:41:20 +04:00
* end = * start + rule - > size - 1 ;
2005-04-17 02:20:36 +04:00
/* run through until pnp_check_mem is happy */
while ( ! pnp_check_mem ( dev , idx ) ) {
* start + = rule - > align ;
* end = * start + rule - > size - 1 ;
if ( * start > rule - > max | | ! rule - > align )
return 0 ;
}
return 1 ;
}
2007-07-26 21:41:20 +04:00
static int pnp_assign_irq ( struct pnp_dev * dev , struct pnp_irq * rule , int idx )
2005-04-17 02:20:36 +04:00
{
2006-06-13 04:07:07 +04:00
resource_size_t * start , * end ;
unsigned long * flags ;
2005-04-17 02:20:36 +04:00
int i ;
/* IRQ priority: this table is good for i386 */
static unsigned short xtab [ 16 ] = {
5 , 10 , 11 , 12 , 9 , 14 , 15 , 7 , 3 , 4 , 13 , 0 , 1 , 6 , 8 , 2
} ;
if ( idx > = PNP_MAX_IRQ ) {
2007-10-17 10:31:10 +04:00
dev_err ( & dev - > dev , " too many IRQ resources \n " ) ;
2005-04-17 02:20:36 +04:00
/* pretend we were successful so at least the manager won't try again */
return 1 ;
}
/* check if this resource has been manually set, if so skip */
if ( ! ( dev - > res . irq_resource [ idx ] . flags & IORESOURCE_AUTO ) )
return 1 ;
start = & dev - > res . irq_resource [ idx ] . start ;
end = & dev - > res . irq_resource [ idx ] . end ;
flags = & dev - > res . irq_resource [ idx ] . flags ;
/* set the initial values */
* flags | = rule - > flags | IORESOURCE_IRQ ;
2007-07-26 21:41:20 +04:00
* flags & = ~ IORESOURCE_UNSET ;
2005-04-17 02:20:36 +04:00
if ( bitmap_empty ( rule - > map , PNP_IRQ_NR ) ) {
* flags | = IORESOURCE_DISABLED ;
2007-07-26 21:41:20 +04:00
return 1 ; /* skip disabled resource requests */
2005-04-17 02:20:36 +04:00
}
/* TBD: need check for >16 IRQ */
* start = find_next_bit ( rule - > map , PNP_IRQ_NR , 16 ) ;
if ( * start < PNP_IRQ_NR ) {
* end = * start ;
return 1 ;
}
for ( i = 0 ; i < 16 ; i + + ) {
2007-07-26 21:41:20 +04:00
if ( test_bit ( xtab [ i ] , rule - > map ) ) {
2005-04-17 02:20:36 +04:00
* start = * end = xtab [ i ] ;
2007-07-26 21:41:20 +04:00
if ( pnp_check_irq ( dev , idx ) )
2005-04-17 02:20:36 +04:00
return 1 ;
}
}
return 0 ;
}
2007-10-17 10:31:07 +04:00
static void pnp_assign_dma ( struct pnp_dev * dev , struct pnp_dma * rule , int idx )
2005-04-17 02:20:36 +04:00
{
2006-06-13 04:07:07 +04:00
resource_size_t * start , * end ;
unsigned long * flags ;
2005-04-17 02:20:36 +04:00
int i ;
/* DMA priority: this table is good for i386 */
static unsigned short xtab [ 8 ] = {
1 , 3 , 5 , 6 , 7 , 0 , 2 , 4
} ;
if ( idx > = PNP_MAX_DMA ) {
2007-10-17 10:31:10 +04:00
dev_err ( & dev - > dev , " too many DMA resources \n " ) ;
2007-10-17 10:31:07 +04:00
return ;
2005-04-17 02:20:36 +04:00
}
/* check if this resource has been manually set, if so skip */
if ( ! ( dev - > res . dma_resource [ idx ] . flags & IORESOURCE_AUTO ) )
2007-10-17 10:31:07 +04:00
return ;
2005-04-17 02:20:36 +04:00
start = & dev - > res . dma_resource [ idx ] . start ;
end = & dev - > res . dma_resource [ idx ] . end ;
flags = & dev - > res . dma_resource [ idx ] . flags ;
/* set the initial values */
* flags | = rule - > flags | IORESOURCE_DMA ;
2007-07-26 21:41:20 +04:00
* flags & = ~ IORESOURCE_UNSET ;
2005-04-17 02:20:36 +04:00
for ( i = 0 ; i < 8 ; i + + ) {
2007-07-26 21:41:20 +04:00
if ( rule - > map & ( 1 < < xtab [ i ] ) ) {
2005-04-17 02:20:36 +04:00
* start = * end = xtab [ i ] ;
2007-07-26 21:41:20 +04:00
if ( pnp_check_dma ( dev , idx ) )
2007-10-17 10:31:07 +04:00
return ;
2005-04-17 02:20:36 +04:00
}
}
2007-10-17 10:31:07 +04:00
# ifdef MAX_DMA_CHANNELS
* start = * end = MAX_DMA_CHANNELS ;
# endif
* flags | = IORESOURCE_UNSET | IORESOURCE_DISABLED ;
2005-04-17 02:20:36 +04:00
}
/**
* pnp_init_resources - Resets a resource table to default values .
* @ table : pointer to the desired resource table
*/
void pnp_init_resource_table ( struct pnp_resource_table * table )
{
int idx ;
2007-07-26 21:41:21 +04:00
2005-04-17 02:20:36 +04:00
for ( idx = 0 ; idx < PNP_MAX_IRQ ; idx + + ) {
table - > irq_resource [ idx ] . name = NULL ;
table - > irq_resource [ idx ] . start = - 1 ;
table - > irq_resource [ idx ] . end = - 1 ;
2007-07-26 21:41:20 +04:00
table - > irq_resource [ idx ] . flags =
IORESOURCE_IRQ | IORESOURCE_AUTO | IORESOURCE_UNSET ;
2005-04-17 02:20:36 +04:00
}
for ( idx = 0 ; idx < PNP_MAX_DMA ; idx + + ) {
table - > dma_resource [ idx ] . name = NULL ;
table - > dma_resource [ idx ] . start = - 1 ;
table - > dma_resource [ idx ] . end = - 1 ;
2007-07-26 21:41:20 +04:00
table - > dma_resource [ idx ] . flags =
IORESOURCE_DMA | IORESOURCE_AUTO | IORESOURCE_UNSET ;
2005-04-17 02:20:36 +04:00
}
for ( idx = 0 ; idx < PNP_MAX_PORT ; idx + + ) {
table - > port_resource [ idx ] . name = NULL ;
table - > port_resource [ idx ] . start = 0 ;
table - > port_resource [ idx ] . end = 0 ;
2007-07-26 21:41:20 +04:00
table - > port_resource [ idx ] . flags =
IORESOURCE_IO | IORESOURCE_AUTO | IORESOURCE_UNSET ;
2005-04-17 02:20:36 +04:00
}
for ( idx = 0 ; idx < PNP_MAX_MEM ; idx + + ) {
table - > mem_resource [ idx ] . name = NULL ;
table - > mem_resource [ idx ] . start = 0 ;
table - > mem_resource [ idx ] . end = 0 ;
2007-07-26 21:41:20 +04:00
table - > mem_resource [ idx ] . flags =
IORESOURCE_MEM | IORESOURCE_AUTO | IORESOURCE_UNSET ;
2005-04-17 02:20:36 +04:00
}
}
/**
* pnp_clean_resources - clears resources that were not manually set
2005-05-01 19:59:26 +04:00
* @ res : the resources to clean
2005-04-17 02:20:36 +04:00
*/
2007-07-26 21:41:20 +04:00
static void pnp_clean_resource_table ( struct pnp_resource_table * res )
2005-04-17 02:20:36 +04:00
{
int idx ;
2007-07-26 21:41:21 +04:00
2005-04-17 02:20:36 +04:00
for ( idx = 0 ; idx < PNP_MAX_IRQ ; idx + + ) {
if ( ! ( res - > irq_resource [ idx ] . flags & IORESOURCE_AUTO ) )
continue ;
res - > irq_resource [ idx ] . start = - 1 ;
res - > irq_resource [ idx ] . end = - 1 ;
2007-07-26 21:41:20 +04:00
res - > irq_resource [ idx ] . flags =
IORESOURCE_IRQ | IORESOURCE_AUTO | IORESOURCE_UNSET ;
2005-04-17 02:20:36 +04:00
}
for ( idx = 0 ; idx < PNP_MAX_DMA ; idx + + ) {
if ( ! ( res - > dma_resource [ idx ] . flags & IORESOURCE_AUTO ) )
continue ;
res - > dma_resource [ idx ] . start = - 1 ;
res - > dma_resource [ idx ] . end = - 1 ;
2007-07-26 21:41:20 +04:00
res - > dma_resource [ idx ] . flags =
IORESOURCE_DMA | IORESOURCE_AUTO | IORESOURCE_UNSET ;
2005-04-17 02:20:36 +04:00
}
for ( idx = 0 ; idx < PNP_MAX_PORT ; idx + + ) {
if ( ! ( res - > port_resource [ idx ] . flags & IORESOURCE_AUTO ) )
continue ;
res - > port_resource [ idx ] . start = 0 ;
res - > port_resource [ idx ] . end = 0 ;
2007-07-26 21:41:20 +04:00
res - > port_resource [ idx ] . flags =
IORESOURCE_IO | IORESOURCE_AUTO | IORESOURCE_UNSET ;
2005-04-17 02:20:36 +04:00
}
for ( idx = 0 ; idx < PNP_MAX_MEM ; idx + + ) {
if ( ! ( res - > mem_resource [ idx ] . flags & IORESOURCE_AUTO ) )
continue ;
res - > mem_resource [ idx ] . start = 0 ;
res - > mem_resource [ idx ] . end = 0 ;
2007-07-26 21:41:20 +04:00
res - > mem_resource [ idx ] . flags =
IORESOURCE_MEM | IORESOURCE_AUTO | IORESOURCE_UNSET ;
2005-04-17 02:20:36 +04:00
}
}
/**
* pnp_assign_resources - assigns resources to the device based on the specified dependent number
* @ dev : pointer to the desired device
* @ depnum : the dependent function number
*
* Only set depnum to 0 if the device does not have dependent options .
*/
static int pnp_assign_resources ( struct pnp_dev * dev , int depnum )
{
struct pnp_port * port ;
struct pnp_mem * mem ;
struct pnp_irq * irq ;
struct pnp_dma * dma ;
int nport = 0 , nmem = 0 , nirq = 0 , ndma = 0 ;
if ( ! pnp_can_configure ( dev ) )
return - ENODEV ;
2008-02-06 12:40:04 +03:00
mutex_lock ( & pnp_res_mutex ) ;
2007-07-26 21:41:20 +04:00
pnp_clean_resource_table ( & dev - > res ) ; /* start with a fresh slate */
2005-04-17 02:20:36 +04:00
if ( dev - > independent ) {
port = dev - > independent - > port ;
mem = dev - > independent - > mem ;
irq = dev - > independent - > irq ;
dma = dev - > independent - > dma ;
while ( port ) {
if ( ! pnp_assign_port ( dev , port , nport ) )
goto fail ;
nport + + ;
port = port - > next ;
}
while ( mem ) {
if ( ! pnp_assign_mem ( dev , mem , nmem ) )
goto fail ;
nmem + + ;
mem = mem - > next ;
}
while ( irq ) {
if ( ! pnp_assign_irq ( dev , irq , nirq ) )
goto fail ;
nirq + + ;
irq = irq - > next ;
}
while ( dma ) {
2007-10-17 10:31:07 +04:00
pnp_assign_dma ( dev , dma , ndma ) ;
2005-04-17 02:20:36 +04:00
ndma + + ;
dma = dma - > next ;
}
}
if ( depnum ) {
struct pnp_option * dep ;
int i ;
2007-07-26 21:41:20 +04:00
for ( i = 1 , dep = dev - > dependent ; i < depnum ;
i + + , dep = dep - > next )
if ( ! dep )
2005-04-17 02:20:36 +04:00
goto fail ;
2007-07-26 21:41:20 +04:00
port = dep - > port ;
2005-04-17 02:20:36 +04:00
mem = dep - > mem ;
irq = dep - > irq ;
dma = dep - > dma ;
while ( port ) {
if ( ! pnp_assign_port ( dev , port , nport ) )
goto fail ;
nport + + ;
port = port - > next ;
}
while ( mem ) {
if ( ! pnp_assign_mem ( dev , mem , nmem ) )
goto fail ;
nmem + + ;
mem = mem - > next ;
}
while ( irq ) {
if ( ! pnp_assign_irq ( dev , irq , nirq ) )
goto fail ;
nirq + + ;
irq = irq - > next ;
}
while ( dma ) {
2007-10-17 10:31:07 +04:00
pnp_assign_dma ( dev , dma , ndma ) ;
2005-04-17 02:20:36 +04:00
ndma + + ;
dma = dma - > next ;
}
} else if ( dev - > dependent )
goto fail ;
2008-02-06 12:40:04 +03:00
mutex_unlock ( & pnp_res_mutex ) ;
2005-04-17 02:20:36 +04:00
return 1 ;
2007-08-15 20:32:08 +04:00
fail :
2005-04-17 02:20:36 +04:00
pnp_clean_resource_table ( & dev - > res ) ;
2008-02-06 12:40:04 +03:00
mutex_unlock ( & pnp_res_mutex ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
/**
* pnp_manual_config_dev - Disables Auto Config and Manually sets the resource table
* @ dev : pointer to the desired device
* @ res : pointer to the new resource config
2005-06-24 09:05:21 +04:00
* @ mode : 0 or PNP_CONFIG_FORCE
2005-04-17 02:20:36 +04:00
*
* This function can be used by drivers that want to manually set thier resources .
*/
2007-07-26 21:41:20 +04:00
int pnp_manual_config_dev ( struct pnp_dev * dev , struct pnp_resource_table * res ,
int mode )
2005-04-17 02:20:36 +04:00
{
int i ;
2007-07-26 21:41:20 +04:00
struct pnp_resource_table * bak ;
2007-07-26 21:41:21 +04:00
2005-04-17 02:20:36 +04:00
if ( ! pnp_can_configure ( dev ) )
return - ENODEV ;
bak = pnp_alloc ( sizeof ( struct pnp_resource_table ) ) ;
if ( ! bak )
return - ENOMEM ;
* bak = dev - > res ;
2008-02-06 12:40:04 +03:00
mutex_lock ( & pnp_res_mutex ) ;
2005-04-17 02:20:36 +04:00
dev - > res = * res ;
if ( ! ( mode & PNP_CONFIG_FORCE ) ) {
for ( i = 0 ; i < PNP_MAX_PORT ; i + + ) {
2007-07-26 21:41:20 +04:00
if ( ! pnp_check_port ( dev , i ) )
2005-04-17 02:20:36 +04:00
goto fail ;
}
for ( i = 0 ; i < PNP_MAX_MEM ; i + + ) {
2007-07-26 21:41:20 +04:00
if ( ! pnp_check_mem ( dev , i ) )
2005-04-17 02:20:36 +04:00
goto fail ;
}
for ( i = 0 ; i < PNP_MAX_IRQ ; i + + ) {
2007-07-26 21:41:20 +04:00
if ( ! pnp_check_irq ( dev , i ) )
2005-04-17 02:20:36 +04:00
goto fail ;
}
for ( i = 0 ; i < PNP_MAX_DMA ; i + + ) {
2007-07-26 21:41:20 +04:00
if ( ! pnp_check_dma ( dev , i ) )
2005-04-17 02:20:36 +04:00
goto fail ;
}
}
2008-02-06 12:40:04 +03:00
mutex_unlock ( & pnp_res_mutex ) ;
2005-04-17 02:20:36 +04:00
kfree ( bak ) ;
return 0 ;
2007-08-15 20:32:08 +04:00
fail :
2005-04-17 02:20:36 +04:00
dev - > res = * bak ;
2008-02-06 12:40:04 +03:00
mutex_unlock ( & pnp_res_mutex ) ;
2005-04-17 02:20:36 +04:00
kfree ( bak ) ;
return - EINVAL ;
}
/**
* pnp_auto_config_dev - automatically assigns resources to a device
* @ dev : pointer to the desired device
*/
int pnp_auto_config_dev ( struct pnp_dev * dev )
{
struct pnp_option * dep ;
int i = 1 ;
2007-07-26 21:41:20 +04:00
if ( ! pnp_can_configure ( dev ) ) {
2007-10-17 10:31:10 +04:00
dev_dbg ( & dev - > dev , " configuration not supported \n " ) ;
2005-04-17 02:20:36 +04:00
return - ENODEV ;
}
if ( ! dev - > dependent ) {
if ( pnp_assign_resources ( dev , 0 ) )
return 0 ;
} else {
dep = dev - > dependent ;
do {
if ( pnp_assign_resources ( dev , i ) )
return 0 ;
dep = dep - > next ;
i + + ;
} while ( dep ) ;
}
2007-10-17 10:31:10 +04:00
dev_err ( & dev - > dev , " unable to assign resources \n " ) ;
2005-04-17 02:20:36 +04:00
return - EBUSY ;
}
2005-11-29 11:09:32 +03:00
/**
* pnp_start_dev - low - level start of the PnP device
* @ dev : pointer to the desired device
*
2007-07-26 21:41:21 +04:00
* assumes that resources have already been allocated
2005-11-29 11:09:32 +03:00
*/
int pnp_start_dev ( struct pnp_dev * dev )
{
if ( ! pnp_can_write ( dev ) ) {
2007-10-17 10:31:10 +04:00
dev_dbg ( & dev - > dev , " activation not supported \n " ) ;
2005-11-29 11:09:32 +03:00
return - EINVAL ;
}
2008-04-29 02:34:05 +04:00
if ( dev - > protocol - > set ( dev ) < 0 ) {
2007-10-17 10:31:10 +04:00
dev_err ( & dev - > dev , " activation failed \n " ) ;
2005-11-29 11:09:32 +03:00
return - EIO ;
}
2007-10-17 10:31:10 +04:00
dev_info ( & dev - > dev , " activated \n " ) ;
2005-11-29 11:09:32 +03:00
return 0 ;
}
/**
* pnp_stop_dev - low - level disable of the PnP device
* @ dev : pointer to the desired device
*
* does not free resources
*/
int pnp_stop_dev ( struct pnp_dev * dev )
{
if ( ! pnp_can_disable ( dev ) ) {
2007-10-17 10:31:10 +04:00
dev_dbg ( & dev - > dev , " disabling not supported \n " ) ;
2005-11-29 11:09:32 +03:00
return - EINVAL ;
}
2007-07-26 21:41:20 +04:00
if ( dev - > protocol - > disable ( dev ) < 0 ) {
2007-10-17 10:31:10 +04:00
dev_err ( & dev - > dev , " disable failed \n " ) ;
2005-11-29 11:09:32 +03:00
return - EIO ;
}
2007-10-17 10:31:10 +04:00
dev_info ( & dev - > dev , " disabled \n " ) ;
2005-11-29 11:09:32 +03:00
return 0 ;
}
2005-04-17 02:20:36 +04:00
/**
* pnp_activate_dev - activates a PnP device for use
* @ dev : pointer to the desired device
*
* does not validate or set resources so be careful .
*/
int pnp_activate_dev ( struct pnp_dev * dev )
{
2005-11-29 11:09:32 +03:00
int error ;
2007-07-26 21:41:21 +04:00
if ( dev - > active )
2008-02-06 12:40:02 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
/* ensure resources are allocated */
if ( pnp_auto_config_dev ( dev ) )
return - EBUSY ;
2005-11-29 11:09:32 +03:00
error = pnp_start_dev ( dev ) ;
if ( error )
return error ;
2005-04-17 02:20:36 +04:00
dev - > active = 1 ;
2008-02-06 12:40:02 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
/**
* pnp_disable_dev - disables device
* @ dev : pointer to the desired device
*
* inform the correct pnp protocol so that resources can be used by other devices
*/
int pnp_disable_dev ( struct pnp_dev * dev )
{
2005-11-29 11:09:32 +03:00
int error ;
2007-07-26 21:41:21 +04:00
if ( ! dev - > active )
2008-02-06 12:40:02 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
2005-11-29 11:09:32 +03:00
error = pnp_stop_dev ( dev ) ;
if ( error )
return error ;
2005-04-17 02:20:36 +04:00
dev - > active = 0 ;
/* release the resources so that other devices can use them */
2008-02-06 12:40:04 +03:00
mutex_lock ( & pnp_res_mutex ) ;
2005-04-17 02:20:36 +04:00
pnp_clean_resource_table ( & dev - > res ) ;
2008-02-06 12:40:04 +03:00
mutex_unlock ( & pnp_res_mutex ) ;
2005-04-17 02:20:36 +04:00
2008-02-06 12:40:02 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
/**
* pnp_resource_change - change one resource
* @ resource : pointer to resource to be changed
* @ start : start of region
* @ size : size of region
*/
2006-06-13 04:07:07 +04:00
void pnp_resource_change ( struct resource * resource , resource_size_t start ,
2007-07-26 21:41:20 +04:00
resource_size_t size )
2005-04-17 02:20:36 +04:00
{
resource - > flags & = ~ ( IORESOURCE_AUTO | IORESOURCE_UNSET ) ;
resource - > start = start ;
resource - > end = start + size - 1 ;
}
EXPORT_SYMBOL ( pnp_manual_config_dev ) ;
2005-11-29 11:09:32 +03:00
EXPORT_SYMBOL ( pnp_start_dev ) ;
EXPORT_SYMBOL ( pnp_stop_dev ) ;
2005-04-17 02:20:36 +04:00
EXPORT_SYMBOL ( pnp_activate_dev ) ;
EXPORT_SYMBOL ( pnp_disable_dev ) ;
EXPORT_SYMBOL ( pnp_resource_change ) ;
EXPORT_SYMBOL ( pnp_init_resource_table ) ;