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 )
{
2008-04-29 02:34:18 +04:00
struct resource * res ;
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 ;
}
2008-04-29 02:34:18 +04:00
res = & dev - > res . port_resource [ idx ] ;
2005-04-17 02:20:36 +04:00
2008-04-29 02:34:08 +04:00
/* check if this resource has been manually set, if so skip */
2008-04-29 02:34:18 +04:00
if ( ! ( res - > flags & IORESOURCE_AUTO ) ) {
2008-04-29 02:34:08 +04:00
dev_dbg ( & dev - > dev , " io %d already set to %#llx-%#llx "
2008-04-29 02:34:18 +04:00
" flags %#lx \n " , idx , ( unsigned long long ) res - > start ,
( unsigned long long ) res - > end , res - > flags ) ;
2008-04-29 02:34:08 +04:00
return 1 ;
}
2005-04-17 02:20:36 +04:00
/* set the initial values */
2008-04-29 02:34:18 +04:00
res - > flags | = rule - > flags | IORESOURCE_IO ;
res - > flags & = ~ IORESOURCE_UNSET ;
2005-04-17 02:20:36 +04:00
if ( ! rule - > size ) {
2008-04-29 02:34:18 +04:00
res - > flags | = IORESOURCE_DISABLED ;
2008-04-29 02:34:08 +04:00
dev_dbg ( & dev - > dev , " io %d disabled \n " , idx ) ;
2007-07-26 21:41:20 +04:00
return 1 ; /* skip disabled resource requests */
2005-04-17 02:20:36 +04:00
}
2008-04-29 02:34:18 +04:00
res - > start = rule - > min ;
res - > end = res - > start + rule - > size - 1 ;
2005-04-17 02:20:36 +04:00
/* run through until pnp_check_port is happy */
while ( ! pnp_check_port ( dev , idx ) ) {
2008-04-29 02:34:18 +04:00
res - > start + = rule - > align ;
res - > end = res - > start + rule - > size - 1 ;
if ( res - > start > rule - > max | | ! rule - > align ) {
2008-04-29 02:34:08 +04:00
dev_dbg ( & dev - > dev , " couldn't assign io %d \n " , idx ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
2008-04-29 02:34:08 +04:00
}
2005-04-17 02:20:36 +04:00
}
2008-04-29 02:34:08 +04:00
dev_dbg ( & dev - > dev , " assign io %d %#llx-%#llx \n " , idx ,
2008-04-29 02:34:18 +04:00
( unsigned long long ) res - > start , ( unsigned long long ) res - > end ) ;
2005-04-17 02:20:36 +04:00
return 1 ;
}
static int pnp_assign_mem ( struct pnp_dev * dev , struct pnp_mem * rule , int idx )
{
2008-04-29 02:34:18 +04:00
struct resource * res ;
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 ;
}
2008-04-29 02:34:18 +04:00
res = & dev - > res . mem_resource [ idx ] ;
2005-04-17 02:20:36 +04:00
2008-04-29 02:34:08 +04:00
/* check if this resource has been manually set, if so skip */
2008-04-29 02:34:18 +04:00
if ( ! ( res - > flags & IORESOURCE_AUTO ) ) {
2008-04-29 02:34:08 +04:00
dev_dbg ( & dev - > dev , " mem %d already set to %#llx-%#llx "
2008-04-29 02:34:18 +04:00
" flags %#lx \n " , idx , ( unsigned long long ) res - > start ,
( unsigned long long ) res - > end , res - > flags ) ;
2008-04-29 02:34:08 +04:00
return 1 ;
}
2005-04-17 02:20:36 +04:00
/* set the initial values */
2008-04-29 02:34:18 +04:00
res - > flags | = rule - > flags | IORESOURCE_MEM ;
res - > flags & = ~ IORESOURCE_UNSET ;
2005-04-17 02:20:36 +04:00
/* convert pnp flags to standard Linux flags */
if ( ! ( rule - > flags & IORESOURCE_MEM_WRITEABLE ) )
2008-04-29 02:34:18 +04:00
res - > flags | = IORESOURCE_READONLY ;
2005-04-17 02:20:36 +04:00
if ( rule - > flags & IORESOURCE_MEM_CACHEABLE )
2008-04-29 02:34:18 +04:00
res - > flags | = IORESOURCE_CACHEABLE ;
2005-04-17 02:20:36 +04:00
if ( rule - > flags & IORESOURCE_MEM_RANGELENGTH )
2008-04-29 02:34:18 +04:00
res - > flags | = IORESOURCE_RANGELENGTH ;
2005-04-17 02:20:36 +04:00
if ( rule - > flags & IORESOURCE_MEM_SHADOWABLE )
2008-04-29 02:34:18 +04:00
res - > flags | = IORESOURCE_SHADOWABLE ;
2005-04-17 02:20:36 +04:00
if ( ! rule - > size ) {
2008-04-29 02:34:18 +04:00
res - > flags | = IORESOURCE_DISABLED ;
2008-04-29 02:34:08 +04:00
dev_dbg ( & dev - > dev , " mem %d disabled \n " , idx ) ;
2007-07-26 21:41:20 +04:00
return 1 ; /* skip disabled resource requests */
2005-04-17 02:20:36 +04:00
}
2008-04-29 02:34:18 +04:00
res - > start = rule - > min ;
res - > end = res - > 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 ) ) {
2008-04-29 02:34:18 +04:00
res - > start + = rule - > align ;
res - > end = res - > start + rule - > size - 1 ;
if ( res - > start > rule - > max | | ! rule - > align ) {
2008-04-29 02:34:08 +04:00
dev_dbg ( & dev - > dev , " couldn't assign mem %d \n " , idx ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
2008-04-29 02:34:08 +04:00
}
2005-04-17 02:20:36 +04:00
}
2008-04-29 02:34:08 +04:00
dev_dbg ( & dev - > dev , " assign mem %d %#llx-%#llx \n " , idx ,
2008-04-29 02:34:18 +04:00
( unsigned long long ) res - > start , ( unsigned long long ) res - > end ) ;
2005-04-17 02:20:36 +04:00
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
{
2008-04-29 02:34:18 +04:00
struct resource * res ;
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 ;
}
2008-04-29 02:34:18 +04:00
res = & dev - > res . irq_resource [ idx ] ;
2005-04-17 02:20:36 +04:00
2008-04-29 02:34:08 +04:00
/* check if this resource has been manually set, if so skip */
2008-04-29 02:34:18 +04:00
if ( ! ( res - > flags & IORESOURCE_AUTO ) ) {
2008-04-29 02:34:08 +04:00
dev_dbg ( & dev - > dev , " irq %d already set to %d flags %#lx \n " ,
2008-04-29 02:34:18 +04:00
idx , ( int ) res - > start , res - > flags ) ;
2008-04-29 02:34:08 +04:00
return 1 ;
}
2005-04-17 02:20:36 +04:00
/* set the initial values */
2008-04-29 02:34:18 +04:00
res - > flags | = rule - > flags | IORESOURCE_IRQ ;
res - > flags & = ~ IORESOURCE_UNSET ;
2005-04-17 02:20:36 +04:00
if ( bitmap_empty ( rule - > map , PNP_IRQ_NR ) ) {
2008-04-29 02:34:18 +04:00
res - > flags | = IORESOURCE_DISABLED ;
2008-04-29 02:34:08 +04:00
dev_dbg ( & dev - > dev , " irq %d disabled \n " , idx ) ;
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 */
2008-04-29 02:34:18 +04:00
res - > start = find_next_bit ( rule - > map , PNP_IRQ_NR , 16 ) ;
if ( res - > start < PNP_IRQ_NR ) {
res - > end = res - > start ;
dev_dbg ( & dev - > dev , " assign irq %d %d \n " , idx ,
( int ) res - > start ) ;
2005-04-17 02:20:36 +04:00
return 1 ;
}
for ( i = 0 ; i < 16 ; i + + ) {
2007-07-26 21:41:20 +04:00
if ( test_bit ( xtab [ i ] , rule - > map ) ) {
2008-04-29 02:34:18 +04:00
res - > start = res - > end = xtab [ i ] ;
2008-04-29 02:34:08 +04:00
if ( pnp_check_irq ( dev , idx ) ) {
dev_dbg ( & dev - > dev , " assign irq %d %d \n " , idx ,
2008-04-29 02:34:18 +04:00
( int ) res - > start ) ;
2005-04-17 02:20:36 +04:00
return 1 ;
2008-04-29 02:34:08 +04:00
}
2005-04-17 02:20:36 +04:00
}
}
2008-04-29 02:34:08 +04:00
dev_dbg ( & dev - > dev , " couldn't assign irq %d \n " , idx ) ;
2005-04-17 02:20:36 +04:00
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
{
2008-04-29 02:34:18 +04:00
struct resource * res ;
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
}
2008-04-29 02:34:18 +04:00
res = & dev - > res . dma_resource [ idx ] ;
2005-04-17 02:20:36 +04:00
2008-04-29 02:34:08 +04:00
/* check if this resource has been manually set, if so skip */
2008-04-29 02:34:18 +04:00
if ( ! ( res - > flags & IORESOURCE_AUTO ) ) {
2008-04-29 02:34:08 +04:00
dev_dbg ( & dev - > dev , " dma %d already set to %d flags %#lx \n " ,
2008-04-29 02:34:18 +04:00
idx , ( int ) res - > start , res - > flags ) ;
2008-04-29 02:34:08 +04:00
return ;
}
2005-04-17 02:20:36 +04:00
/* set the initial values */
2008-04-29 02:34:18 +04:00
res - > flags | = rule - > flags | IORESOURCE_DMA ;
res - > 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 ] ) ) {
2008-04-29 02:34:18 +04:00
res - > start = res - > end = xtab [ i ] ;
2008-04-29 02:34:08 +04:00
if ( pnp_check_dma ( dev , idx ) ) {
dev_dbg ( & dev - > dev , " assign dma %d %d \n " , idx ,
2008-04-29 02:34:18 +04:00
( int ) res - > start ) ;
2007-10-17 10:31:07 +04:00
return ;
2008-04-29 02:34:08 +04:00
}
2005-04-17 02:20:36 +04:00
}
}
2007-10-17 10:31:07 +04:00
# ifdef MAX_DMA_CHANNELS
2008-04-29 02:34:18 +04:00
res - > start = res - > end = MAX_DMA_CHANNELS ;
2007-10-17 10:31:07 +04:00
# endif
2008-04-29 02:34:18 +04:00
res - > flags | = IORESOURCE_UNSET | IORESOURCE_DISABLED ;
2008-04-29 02:34:08 +04:00
dev_dbg ( & dev - > dev , " disable dma %d \n " , idx ) ;
2005-04-17 02:20:36 +04:00
}
2008-04-29 02:34:13 +04:00
void pnp_init_resource ( struct resource * res )
{
unsigned long type ;
type = res - > flags & ( IORESOURCE_IO | IORESOURCE_MEM |
IORESOURCE_IRQ | IORESOURCE_DMA ) ;
res - > name = NULL ;
res - > flags = type | IORESOURCE_AUTO | IORESOURCE_UNSET ;
if ( type = = IORESOURCE_IRQ | | type = = IORESOURCE_DMA ) {
res - > start = - 1 ;
res - > end = - 1 ;
} else {
res - > start = 0 ;
res - > end = 0 ;
}
}
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
*/
2008-04-29 02:34:11 +04:00
void pnp_init_resources ( struct pnp_dev * dev )
2005-04-17 02:20:36 +04:00
{
2008-04-29 02:34:13 +04:00
struct resource * 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 + + ) {
2008-04-29 02:34:13 +04:00
res = & dev - > res . irq_resource [ idx ] ;
res - > flags = IORESOURCE_IRQ ;
pnp_init_resource ( res ) ;
2005-04-17 02:20:36 +04:00
}
for ( idx = 0 ; idx < PNP_MAX_DMA ; idx + + ) {
2008-04-29 02:34:13 +04:00
res = & dev - > res . dma_resource [ idx ] ;
res - > flags = IORESOURCE_DMA ;
pnp_init_resource ( res ) ;
2005-04-17 02:20:36 +04:00
}
for ( idx = 0 ; idx < PNP_MAX_PORT ; idx + + ) {
2008-04-29 02:34:13 +04:00
res = & dev - > res . port_resource [ idx ] ;
res - > flags = IORESOURCE_IO ;
pnp_init_resource ( res ) ;
2005-04-17 02:20:36 +04:00
}
for ( idx = 0 ; idx < PNP_MAX_MEM ; idx + + ) {
2008-04-29 02:34:13 +04:00
res = & dev - > res . mem_resource [ idx ] ;
res - > flags = IORESOURCE_MEM ;
pnp_init_resource ( res ) ;
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
*/
2008-04-29 02:34:10 +04:00
static void pnp_clean_resource_table ( struct pnp_dev * dev )
2005-04-17 02:20:36 +04:00
{
2008-04-29 02:34:13 +04:00
struct resource * 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 + + ) {
2008-04-29 02:34:13 +04:00
res = & dev - > res . irq_resource [ idx ] ;
if ( res - > flags & IORESOURCE_AUTO ) {
res - > flags = IORESOURCE_IRQ ;
pnp_init_resource ( res ) ;
}
2005-04-17 02:20:36 +04:00
}
for ( idx = 0 ; idx < PNP_MAX_DMA ; idx + + ) {
2008-04-29 02:34:13 +04:00
res = & dev - > res . dma_resource [ idx ] ;
if ( res - > flags & IORESOURCE_AUTO ) {
res - > flags = IORESOURCE_DMA ;
pnp_init_resource ( res ) ;
}
2005-04-17 02:20:36 +04:00
}
for ( idx = 0 ; idx < PNP_MAX_PORT ; idx + + ) {
2008-04-29 02:34:13 +04:00
res = & dev - > res . port_resource [ idx ] ;
if ( res - > flags & IORESOURCE_AUTO ) {
res - > flags = IORESOURCE_IO ;
pnp_init_resource ( res ) ;
}
2005-04-17 02:20:36 +04:00
}
for ( idx = 0 ; idx < PNP_MAX_MEM ; idx + + ) {
2008-04-29 02:34:13 +04:00
res = & dev - > res . mem_resource [ idx ] ;
if ( res - > flags & IORESOURCE_AUTO ) {
res - > flags = IORESOURCE_MEM ;
pnp_init_resource ( res ) ;
}
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-04-29 02:34:08 +04:00
dbg_pnp_show_resources ( dev , " before pnp_assign_resources " ) ;
2008-02-06 12:40:04 +03:00
mutex_lock ( & pnp_res_mutex ) ;
2008-04-29 02:34:10 +04:00
pnp_clean_resource_table ( dev ) ;
2005-04-17 02:20:36 +04:00
if ( dev - > independent ) {
2008-04-29 02:34:08 +04:00
dev_dbg ( & dev - > dev , " assigning independent options \n " ) ;
2005-04-17 02:20:36 +04:00
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 ;
2008-04-29 02:34:08 +04:00
dev_dbg ( & dev - > dev , " assigning dependent option %d \n " , depnum ) ;
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 ) ;
2008-04-29 02:34:08 +04:00
dbg_pnp_show_resources ( dev , " after pnp_assign_resources " ) ;
2005-04-17 02:20:36 +04:00
return 1 ;
2007-08-15 20:32:08 +04:00
fail :
2008-04-29 02:34:10 +04:00
pnp_clean_resource_table ( dev ) ;
2008-02-06 12:40:04 +03:00
mutex_unlock ( & pnp_res_mutex ) ;
2008-04-29 02:34:08 +04:00
dbg_pnp_show_resources ( dev , " after pnp_assign_resources (failed) " ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
/**
* 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:08 +04:00
dbg_pnp_show_resources ( dev , " pnp_start_dev " ) ;
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 ) ;
2008-04-29 02:34:10 +04:00
pnp_clean_resource_table ( dev ) ;
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
}
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 ) ;