2005-04-16 15:20:36 -07:00
/*
* Functions to handle I2O devices
*
* Copyright ( C ) 2004 Markus Lidel < Markus . Lidel @ shadowconnect . 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 .
*
* Fixes / additions :
* Markus Lidel < Markus . Lidel @ shadowconnect . com >
* initial version .
*/
# include <linux/module.h>
# include <linux/i2o.h>
# include <linux/delay.h>
2005-10-30 15:03:48 -08:00
# include <linux/string.h>
# include <linux/slab.h>
2005-06-23 22:02:21 -07:00
# include "core.h"
2005-04-16 15:20:36 -07:00
/**
* i2o_device_issue_claim - claim or release a device
* @ dev : I2O device to claim or release
* @ cmd : claim or release command
* @ type : type of claim
*
* Issue I2O UTIL_CLAIM or UTIL_RELEASE messages . The message to be sent
* is set by cmd . dev is the I2O device which should be claim or
* released and the type is the claim type ( see the I2O spec ) .
*
* Returs 0 on success or negative error code on failure .
*/
static inline int i2o_device_issue_claim ( struct i2o_device * dev , u32 cmd ,
u32 type )
{
2006-01-06 00:19:29 -08:00
struct i2o_message * msg ;
2005-04-16 15:20:36 -07:00
2006-01-06 00:19:29 -08:00
msg = i2o_msg_get_wait ( dev - > iop , I2O_TIMEOUT_MESSAGE_GET ) ;
if ( IS_ERR ( msg ) )
return PTR_ERR ( msg ) ;
2005-04-16 15:20:36 -07:00
2006-01-06 00:19:29 -08:00
msg - > u . head [ 0 ] = cpu_to_le32 ( FIVE_WORD_MSG_SIZE | SGL_OFFSET_0 ) ;
msg - > u . head [ 1 ] =
2006-01-06 00:19:34 -08:00
cpu_to_le32 ( cmd < < 24 | HOST_TID < < 12 | dev - > lct_data . tid ) ;
2006-01-06 00:19:29 -08:00
msg - > body [ 0 ] = cpu_to_le32 ( type ) ;
2005-04-16 15:20:36 -07:00
2006-01-06 00:19:29 -08:00
return i2o_msg_post_wait ( dev - > iop , msg , 60 ) ;
2005-09-15 02:01:32 -05:00
}
2005-04-16 15:20:36 -07:00
/**
2005-09-15 02:01:32 -05:00
* i2o_device_claim - claim a device for use by an OSM
2005-04-16 15:20:36 -07:00
* @ dev : I2O device to claim
*
2006-12-06 20:38:43 -08:00
* Do the leg work to assign a device to a given OSM . If the claim succeeds ,
* the owner is the primary . If the attempt fails a negative errno code
2005-04-16 15:20:36 -07:00
* is returned . On success zero is returned .
*/
int i2o_device_claim ( struct i2o_device * dev )
{
int rc = 0 ;
2007-07-15 23:39:49 -07:00
mutex_lock ( & dev - > lock ) ;
2005-04-16 15:20:36 -07:00
rc = i2o_device_issue_claim ( dev , I2O_CMD_UTIL_CLAIM , I2O_CLAIM_PRIMARY ) ;
if ( ! rc )
2011-03-30 22:57:33 -03:00
pr_debug ( " i2o: claim of device %d succeeded \n " ,
2005-04-16 15:20:36 -07:00
dev - > lct_data . tid ) ;
else
pr_debug ( " i2o: claim of device %d failed %d \n " ,
dev - > lct_data . tid , rc ) ;
2007-07-15 23:39:49 -07:00
mutex_unlock ( & dev - > lock ) ;
2005-04-16 15:20:36 -07:00
return rc ;
2005-09-15 02:01:32 -05:00
}
2005-04-16 15:20:36 -07:00
/**
* i2o_device_claim_release - release a device that the OSM is using
* @ dev : device to release
*
* Drop a claim by an OSM on a given I2O device .
*
* AC - some devices seem to want to refuse an unclaim until they have
* finished internal processing . It makes sense since you don ' t want a
* new device to go reconfiguring the entire system until you are done .
* Thus we are prepared to wait briefly .
*
* Returns 0 on success or negative error code on failure .
*/
int i2o_device_claim_release ( struct i2o_device * dev )
{
int tries ;
int rc = 0 ;
2007-07-15 23:39:49 -07:00
mutex_lock ( & dev - > lock ) ;
2005-04-16 15:20:36 -07:00
/*
* If the controller takes a nonblocking approach to
* releases we have to sleep / poll for a few times .
*/
for ( tries = 0 ; tries < 10 ; tries + + ) {
rc = i2o_device_issue_claim ( dev , I2O_CMD_UTIL_RELEASE ,
I2O_CLAIM_PRIMARY ) ;
if ( ! rc )
break ;
ssleep ( 1 ) ;
}
if ( ! rc )
2011-03-30 22:57:33 -03:00
pr_debug ( " i2o: claim release of device %d succeeded \n " ,
2005-04-16 15:20:36 -07:00
dev - > lct_data . tid ) ;
else
pr_debug ( " i2o: claim release of device %d failed %d \n " ,
dev - > lct_data . tid , rc ) ;
2007-07-15 23:39:49 -07:00
mutex_unlock ( & dev - > lock ) ;
2005-04-16 15:20:36 -07:00
return rc ;
2005-09-15 02:01:32 -05:00
}
2005-04-16 15:20:36 -07:00
/**
* i2o_device_release - release the memory for a I2O device
* @ dev : I2O device which should be released
*
* Release the allocated memory . This function is called if refcount of
* device reaches 0 automatically .
*/
static void i2o_device_release ( struct device * dev )
{
struct i2o_device * i2o_dev = to_i2o_device ( dev ) ;
2009-01-06 10:44:40 -08:00
pr_debug ( " i2o: device %s released \n " , dev_name ( dev ) ) ;
2005-04-16 15:20:36 -07:00
kfree ( i2o_dev ) ;
2005-09-15 02:01:32 -05:00
}
2005-04-16 15:20:36 -07:00
2005-09-15 02:01:32 -05:00
/**
2006-01-06 00:19:31 -08:00
* i2o_device_show_class_id - Displays class id of I2O device
* @ dev : device of which the class id should be displayed
* @ attr : pointer to device attribute
2005-09-15 02:01:32 -05:00
* @ buf : buffer into which the class id should be printed
*
* Returns the number of bytes which are printed into the buffer .
*/
2005-09-29 00:40:07 -05:00
static ssize_t i2o_device_show_class_id ( struct device * dev ,
struct device_attribute * attr ,
char * buf )
2005-09-15 02:01:32 -05:00
{
2005-09-29 00:40:07 -05:00
struct i2o_device * i2o_dev = to_i2o_device ( dev ) ;
2005-04-16 15:20:36 -07:00
2005-09-29 00:40:07 -05:00
sprintf ( buf , " 0x%03x \n " , i2o_dev - > lct_data . class_id ) ;
2005-09-15 02:01:32 -05:00
return strlen ( buf ) + 1 ;
}
2005-04-16 15:20:36 -07:00
2005-09-15 02:01:32 -05:00
/**
2006-01-06 00:19:31 -08:00
* i2o_device_show_tid - Displays TID of I2O device
* @ dev : device of which the TID should be displayed
* @ attr : pointer to device attribute
* @ buf : buffer into which the TID should be printed
2005-09-15 02:01:32 -05:00
*
* Returns the number of bytes which are printed into the buffer .
*/
2005-09-29 00:40:07 -05:00
static ssize_t i2o_device_show_tid ( struct device * dev ,
2006-01-06 00:19:31 -08:00
struct device_attribute * attr , char * buf )
2005-09-15 02:01:32 -05:00
{
2005-09-29 00:40:07 -05:00
struct i2o_device * i2o_dev = to_i2o_device ( dev ) ;
2005-09-15 02:01:32 -05:00
2005-09-29 00:40:07 -05:00
sprintf ( buf , " 0x%03x \n " , i2o_dev - > lct_data . tid ) ;
2005-09-15 02:01:32 -05:00
return strlen ( buf ) + 1 ;
}
2006-01-06 00:19:32 -08:00
/* I2O device attributes */
2005-09-29 00:40:07 -05:00
struct device_attribute i2o_device_attrs [ ] = {
__ATTR ( class_id , S_IRUGO , i2o_device_show_class_id , NULL ) ,
__ATTR ( tid , S_IRUGO , i2o_device_show_tid , NULL ) ,
2005-09-15 02:01:32 -05:00
__ATTR_NULL
2005-04-16 15:20:36 -07:00
} ;
/**
* i2o_device_alloc - Allocate a I2O device and initialize it
*
* Allocate the memory for a I2O device and initialize locks and lists
*
* Returns the allocated I2O device or a negative error code if the device
* could not be allocated .
*/
static struct i2o_device * i2o_device_alloc ( void )
{
struct i2o_device * dev ;
2006-01-06 00:19:33 -08:00
dev = kzalloc ( sizeof ( * dev ) , GFP_KERNEL ) ;
2005-04-16 15:20:36 -07:00
if ( ! dev )
return ERR_PTR ( - ENOMEM ) ;
INIT_LIST_HEAD ( & dev - > list ) ;
2007-07-15 23:39:49 -07:00
mutex_init ( & dev - > lock ) ;
2005-04-16 15:20:36 -07:00
dev - > device . bus = & i2o_bus_type ;
dev - > device . release = & i2o_device_release ;
return dev ;
2005-09-15 02:01:32 -05:00
}
2005-04-16 15:20:36 -07:00
/**
* i2o_device_add - allocate a new I2O device and add it to the IOP
2006-12-06 20:38:43 -08:00
* @ c : I2O controller that the device is on
2005-04-16 15:20:36 -07:00
* @ entry : LCT entry of the I2O device
*
* Allocate a new I2O device and initialize it with the LCT entry . The
* device is appended to the device list of the controller .
*
2006-12-06 20:35:31 -08:00
* Returns zero on success , or a - ve errno .
2005-04-16 15:20:36 -07:00
*/
2006-12-06 20:35:31 -08:00
static int i2o_device_add ( struct i2o_controller * c , i2o_lct_entry * entry )
2005-04-16 15:20:36 -07:00
{
2006-01-06 00:19:31 -08:00
struct i2o_device * i2o_dev , * tmp ;
2006-12-06 20:35:31 -08:00
int rc ;
2005-04-16 15:20:36 -07:00
2006-01-06 00:19:31 -08:00
i2o_dev = i2o_device_alloc ( ) ;
if ( IS_ERR ( i2o_dev ) ) {
2005-04-16 15:20:36 -07:00
printk ( KERN_ERR " i2o: unable to allocate i2o device \n " ) ;
2006-12-06 20:35:31 -08:00
return PTR_ERR ( i2o_dev ) ;
2005-04-16 15:20:36 -07:00
}
2006-01-06 00:19:31 -08:00
i2o_dev - > lct_data = * entry ;
2005-04-16 15:20:36 -07:00
2009-01-06 10:44:40 -08:00
dev_set_name ( & i2o_dev - > device , " %d:%03x " , c - > unit ,
i2o_dev - > lct_data . tid ) ;
2005-04-16 15:20:36 -07:00
2006-01-06 00:19:31 -08:00
i2o_dev - > iop = c ;
i2o_dev - > device . parent = & c - > device ;
2005-04-16 15:20:36 -07:00
2006-12-06 20:35:31 -08:00
rc = device_register ( & i2o_dev - > device ) ;
if ( rc )
goto err ;
2005-04-16 15:20:36 -07:00
2006-01-06 00:19:31 -08:00
list_add_tail ( & i2o_dev - > list , & c - > devices ) ;
2005-04-16 15:20:36 -07:00
2006-01-06 00:19:31 -08:00
/* create user entries for this device */
tmp = i2o_iop_find_device ( i2o_dev - > iop , i2o_dev - > lct_data . user_tid ) ;
2008-07-23 21:30:01 -07:00
if ( tmp & & ( tmp ! = i2o_dev ) ) {
rc = sysfs_create_link ( & i2o_dev - > device . kobj ,
& tmp - > device . kobj , " user " ) ;
if ( rc )
goto unreg_dev ;
}
2005-09-15 02:01:32 -05:00
2011-03-30 22:57:33 -03:00
/* create user entries referring to this device */
2006-01-06 00:19:31 -08:00
list_for_each_entry ( tmp , & c - > devices , list )
2006-01-06 00:19:34 -08:00
if ( ( tmp - > lct_data . user_tid = = i2o_dev - > lct_data . tid )
2008-07-23 21:30:01 -07:00
& & ( tmp ! = i2o_dev ) ) {
rc = sysfs_create_link ( & tmp - > device . kobj ,
& i2o_dev - > device . kobj , " user " ) ;
if ( rc )
goto rmlink1 ;
}
2005-04-16 15:20:36 -07:00
2006-01-06 00:19:31 -08:00
/* create parent entries for this device */
tmp = i2o_iop_find_device ( i2o_dev - > iop , i2o_dev - > lct_data . parent_tid ) ;
2008-07-23 21:30:01 -07:00
if ( tmp & & ( tmp ! = i2o_dev ) ) {
rc = sysfs_create_link ( & i2o_dev - > device . kobj ,
& tmp - > device . kobj , " parent " ) ;
if ( rc )
goto rmlink1 ;
}
2005-04-16 15:20:36 -07:00
2011-03-30 22:57:33 -03:00
/* create parent entries referring to this device */
2006-01-06 00:19:31 -08:00
list_for_each_entry ( tmp , & c - > devices , list )
2006-01-06 00:19:34 -08:00
if ( ( tmp - > lct_data . parent_tid = = i2o_dev - > lct_data . tid )
2008-07-23 21:30:01 -07:00
& & ( tmp ! = i2o_dev ) ) {
rc = sysfs_create_link ( & tmp - > device . kobj ,
& i2o_dev - > device . kobj , " parent " ) ;
if ( rc )
goto rmlink2 ;
}
2006-01-06 00:19:31 -08:00
i2o_driver_notify_device_add_all ( i2o_dev ) ;
2009-01-06 10:44:40 -08:00
pr_debug ( " i2o: device %s added \n " , dev_name ( & i2o_dev - > device ) ) ;
2006-01-06 00:19:31 -08:00
2006-12-06 20:35:31 -08:00
return 0 ;
2008-07-23 21:30:01 -07:00
rmlink2 :
/* If link creating failed halfway, we loop whole list to cleanup.
* And we don ' t care wrong removing of link , because sysfs_remove_link
* will take care of it .
*/
list_for_each_entry ( tmp , & c - > devices , list ) {
if ( tmp - > lct_data . parent_tid = = i2o_dev - > lct_data . tid )
sysfs_remove_link ( & tmp - > device . kobj , " parent " ) ;
}
sysfs_remove_link ( & i2o_dev - > device . kobj , " parent " ) ;
rmlink1 :
list_for_each_entry ( tmp , & c - > devices , list )
if ( tmp - > lct_data . user_tid = = i2o_dev - > lct_data . tid )
sysfs_remove_link ( & tmp - > device . kobj , " user " ) ;
sysfs_remove_link ( & i2o_dev - > device . kobj , " user " ) ;
unreg_dev :
list_del ( & i2o_dev - > list ) ;
device_unregister ( & i2o_dev - > device ) ;
2006-12-06 20:35:31 -08:00
err :
kfree ( i2o_dev ) ;
return rc ;
2005-09-15 02:01:32 -05:00
}
2005-04-16 15:20:36 -07:00
/**
* i2o_device_remove - remove an I2O device from the I2O core
2006-12-06 20:38:43 -08:00
* @ i2o_dev : I2O device which should be released
2005-04-16 15:20:36 -07:00
*
* Is used on I2O controller removal or LCT modification , when the device
* is removed from the system . Note that the device could still hang
* around until the refcount reaches 0.
*/
void i2o_device_remove ( struct i2o_device * i2o_dev )
{
2006-01-06 00:19:31 -08:00
struct i2o_device * tmp ;
struct i2o_controller * c = i2o_dev - > iop ;
2005-04-16 15:20:36 -07:00
i2o_driver_notify_device_remove_all ( i2o_dev ) ;
2006-01-06 00:19:31 -08:00
sysfs_remove_link ( & i2o_dev - > device . kobj , " parent " ) ;
sysfs_remove_link ( & i2o_dev - > device . kobj , " user " ) ;
list_for_each_entry ( tmp , & c - > devices , list ) {
if ( tmp - > lct_data . parent_tid = = i2o_dev - > lct_data . tid )
sysfs_remove_link ( & tmp - > device . kobj , " parent " ) ;
if ( tmp - > lct_data . user_tid = = i2o_dev - > lct_data . tid )
sysfs_remove_link ( & tmp - > device . kobj , " user " ) ;
}
2005-04-16 15:20:36 -07:00
list_del ( & i2o_dev - > list ) ;
2006-01-06 00:19:31 -08:00
2005-04-16 15:20:36 -07:00
device_unregister ( & i2o_dev - > device ) ;
2005-09-15 02:01:32 -05:00
}
2005-04-16 15:20:36 -07:00
/**
* i2o_device_parse_lct - Parse a previously fetched LCT and create devices
* @ c : I2O controller from which the LCT should be parsed .
*
* The Logical Configuration Table tells us what we can talk to on the
* board . For every entry we create an I2O device , which is registered in
* the I2O core .
*
* Returns 0 on success or negative error code on failure .
*/
int i2o_device_parse_lct ( struct i2o_controller * c )
{
struct i2o_device * dev , * tmp ;
i2o_lct * lct ;
2006-01-06 00:19:30 -08:00
u32 * dlct = c - > dlct . virt ;
int max = 0 , i = 0 ;
u16 table_size ;
u32 buf ;
2005-04-16 15:20:36 -07:00
2007-07-15 23:39:49 -07:00
mutex_lock ( & c - > lct_lock ) ;
2005-04-16 15:20:36 -07:00
2005-06-23 22:02:14 -07:00
kfree ( c - > lct ) ;
2005-04-16 15:20:36 -07:00
2006-01-06 00:19:30 -08:00
buf = le32_to_cpu ( * dlct + + ) ;
table_size = buf & 0xffff ;
2005-04-16 15:20:36 -07:00
2006-01-06 00:19:30 -08:00
lct = c - > lct = kmalloc ( table_size * 4 , GFP_KERNEL ) ;
if ( ! lct ) {
2007-07-15 23:39:49 -07:00
mutex_unlock ( & c - > lct_lock ) ;
2005-04-16 15:20:36 -07:00
return - ENOMEM ;
}
2006-01-06 00:19:30 -08:00
lct - > lct_ver = buf > > 28 ;
lct - > boot_tid = buf > > 16 & 0xfff ;
lct - > table_size = table_size ;
lct - > change_ind = le32_to_cpu ( * dlct + + ) ;
lct - > iop_flags = le32_to_cpu ( * dlct + + ) ;
2005-04-16 15:20:36 -07:00
2006-01-06 00:19:30 -08:00
table_size - = 3 ;
2005-04-16 15:20:36 -07:00
pr_debug ( " %s: LCT has %d entries (LCT size: %d) \n " , c - > name , max ,
lct - > table_size ) ;
2006-01-06 00:19:30 -08:00
while ( table_size > 0 ) {
i2o_lct_entry * entry = & lct - > lct_entry [ max ] ;
2005-04-16 15:20:36 -07:00
int found = 0 ;
2006-01-06 00:19:30 -08:00
buf = le32_to_cpu ( * dlct + + ) ;
entry - > entry_size = buf & 0xffff ;
entry - > tid = buf > > 16 & 0xfff ;
entry - > change_ind = le32_to_cpu ( * dlct + + ) ;
entry - > device_flags = le32_to_cpu ( * dlct + + ) ;
buf = le32_to_cpu ( * dlct + + ) ;
entry - > class_id = buf & 0xfff ;
entry - > version = buf > > 12 & 0xf ;
entry - > vendor_id = buf > > 16 ;
entry - > sub_class = le32_to_cpu ( * dlct + + ) ;
buf = le32_to_cpu ( * dlct + + ) ;
entry - > user_tid = buf & 0xfff ;
entry - > parent_tid = buf > > 12 & 0xfff ;
entry - > bios_info = buf > > 24 ;
memcpy ( & entry - > identity_tag , dlct , 8 ) ;
dlct + = 2 ;
entry - > event_capabilities = le32_to_cpu ( * dlct + + ) ;
/* add new devices, which are new in the LCT */
list_for_each_entry_safe ( dev , tmp , & c - > devices , list ) {
if ( entry - > tid = = dev - > lct_data . tid ) {
2005-04-16 15:20:36 -07:00
found = 1 ;
break ;
}
}
if ( ! found )
2006-01-06 00:19:30 -08:00
i2o_device_add ( c , entry ) ;
table_size - = 9 ;
max + + ;
2005-04-16 15:20:36 -07:00
}
2006-01-06 00:19:30 -08:00
/* remove devices, which are not in the LCT anymore */
list_for_each_entry_safe ( dev , tmp , & c - > devices , list ) {
2005-04-16 15:20:36 -07:00
int found = 0 ;
2006-01-06 00:19:30 -08:00
for ( i = 0 ; i < max ; i + + ) {
2005-04-16 15:20:36 -07:00
if ( lct - > lct_entry [ i ] . tid = = dev - > lct_data . tid ) {
found = 1 ;
break ;
}
}
if ( ! found )
2006-01-06 00:19:30 -08:00
i2o_device_remove ( dev ) ;
2005-04-16 15:20:36 -07:00
}
2006-01-06 00:19:30 -08:00
2007-07-15 23:39:49 -07:00
mutex_unlock ( & c - > lct_lock ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
2005-09-15 02:01:32 -05:00
}
2005-04-16 15:20:36 -07:00
/*
* Run time support routines
*/
/* Issue UTIL_PARAMS_GET or UTIL_PARAMS_SET
*
* This function can be used for all UtilParamsGet / Set operations .
* The OperationList is given in oplist - buffer ,
* and results are returned in reslist - buffer .
* Note that the minimum sized reslist is 8 bytes and contains
* ResultCount , ErrorInfoSize , BlockStatus and BlockSize .
*/
2005-06-23 22:02:26 -07:00
int i2o_parm_issue ( struct i2o_device * i2o_dev , int cmd , void * oplist ,
2006-01-06 00:19:29 -08:00
int oplen , void * reslist , int reslen )
2005-04-16 15:20:36 -07:00
{
2006-01-06 00:19:29 -08:00
struct i2o_message * msg ;
2005-04-16 15:20:36 -07:00
int i = 0 ;
int rc ;
struct i2o_dma res ;
struct i2o_controller * c = i2o_dev - > iop ;
struct device * dev = & c - > pdev - > dev ;
res . virt = NULL ;
2008-10-15 22:02:47 -07:00
if ( i2o_dma_alloc ( dev , & res , reslen ) )
2005-04-16 15:20:36 -07:00
return - ENOMEM ;
2006-01-06 00:19:29 -08:00
msg = i2o_msg_get_wait ( c , I2O_TIMEOUT_MESSAGE_GET ) ;
if ( IS_ERR ( msg ) ) {
2005-04-16 15:20:36 -07:00
i2o_dma_free ( dev , & res ) ;
2006-01-06 00:19:29 -08:00
return PTR_ERR ( msg ) ;
2005-04-16 15:20:36 -07:00
}
i = 0 ;
2006-01-06 00:19:29 -08:00
msg - > u . head [ 1 ] =
cpu_to_le32 ( cmd < < 24 | HOST_TID < < 12 | i2o_dev - > lct_data . tid ) ;
msg - > body [ i + + ] = cpu_to_le32 ( 0x00000000 ) ;
msg - > body [ i + + ] = cpu_to_le32 ( 0x4C000000 | oplen ) ; /* OperationList */
memcpy ( & msg - > body [ i ] , oplist , oplen ) ;
2005-04-16 15:20:36 -07:00
i + = ( oplen / 4 + ( oplen % 4 ? 1 : 0 ) ) ;
2006-01-06 00:19:29 -08:00
msg - > body [ i + + ] = cpu_to_le32 ( 0xD0000000 | res . len ) ; /* ResultList */
msg - > body [ i + + ] = cpu_to_le32 ( res . phys ) ;
2005-04-16 15:20:36 -07:00
2006-01-06 00:19:29 -08:00
msg - > u . head [ 0 ] =
cpu_to_le32 ( I2O_MESSAGE_SIZE ( i + sizeof ( struct i2o_message ) / 4 ) |
SGL_OFFSET_5 ) ;
2005-04-16 15:20:36 -07:00
2006-01-06 00:19:29 -08:00
rc = i2o_msg_post_wait_mem ( c , msg , 10 , & res ) ;
2005-04-16 15:20:36 -07:00
/* This only looks like a memory leak - don't "fix" it. */
if ( rc = = - ETIMEDOUT )
return rc ;
2005-06-23 22:02:21 -07:00
memcpy ( reslist , res . virt , res . len ) ;
2005-04-16 15:20:36 -07:00
i2o_dma_free ( dev , & res ) ;
2006-01-06 00:19:30 -08:00
return rc ;
2005-04-16 15:20:36 -07:00
}
/*
* Query one field group value or a whole scalar group .
*/
int i2o_parm_field_get ( struct i2o_device * i2o_dev , int group , int field ,
void * buf , int buflen )
{
2006-01-06 00:19:30 -08:00
u32 opblk [ ] = { cpu_to_le32 ( 0x00000001 ) ,
cpu_to_le32 ( ( u16 ) group < < 16 | I2O_PARAMS_FIELD_GET ) ,
cpu_to_le32 ( ( s16 ) field < < 16 | 0x00000001 )
} ;
2005-06-23 22:02:21 -07:00
u8 * resblk ; /* 8 bytes for header */
2006-01-06 00:19:30 -08:00
int rc ;
2005-04-16 15:20:36 -07:00
2007-07-09 12:00:07 -07:00
resblk = kmalloc ( buflen + 8 , GFP_KERNEL ) ;
2005-06-23 22:02:21 -07:00
if ( ! resblk )
return - ENOMEM ;
2006-01-06 00:19:30 -08:00
rc = i2o_parm_issue ( i2o_dev , I2O_CMD_UTIL_PARAMS_GET , opblk ,
sizeof ( opblk ) , resblk , buflen + 8 ) ;
2005-04-16 15:20:36 -07:00
memcpy ( buf , resblk + 8 , buflen ) ; /* cut off header */
2005-06-23 22:02:21 -07:00
kfree ( resblk ) ;
2005-04-16 15:20:36 -07:00
2006-01-06 00:19:30 -08:00
return rc ;
2005-04-16 15:20:36 -07:00
}
/*
2005-09-15 02:01:32 -05:00
* if oper = = I2O_PARAMS_TABLE_GET , get from all rows
* if fieldcount = = - 1 return all fields
2005-04-16 15:20:36 -07:00
* ibuf and ibuflen are unused ( use NULL , 0 )
2005-09-15 02:01:32 -05:00
* else return specific fields
* ibuf contains fieldindexes
2005-04-16 15:20:36 -07:00
*
2006-01-06 00:19:32 -08:00
* if oper = = I2O_PARAMS_LIST_GET , get from specific rows
* if fieldcount = = - 1 return all fields
2005-04-16 15:20:36 -07:00
* ibuf contains rowcount , keyvalues
2006-01-06 00:19:32 -08:00
* else return specific fields
2005-04-16 15:20:36 -07:00
* fieldcount is # of fieldindexes
2006-01-06 00:19:32 -08:00
* ibuf contains fieldindexes , rowcount , keyvalues
2005-04-16 15:20:36 -07:00
*
* You could also use directly function i2o_issue_params ( ) .
*/
int i2o_parm_table_get ( struct i2o_device * dev , int oper , int group ,
int fieldcount , void * ibuf , int ibuflen , void * resblk ,
int reslen )
{
u16 * opblk ;
int size ;
size = 10 + ibuflen ;
if ( size % 4 )
size + = 4 - size % 4 ;
opblk = kmalloc ( size , GFP_KERNEL ) ;
if ( opblk = = NULL ) {
printk ( KERN_ERR " i2o: no memory for query buffer. \n " ) ;
return - ENOMEM ;
}
opblk [ 0 ] = 1 ; /* operation count */
opblk [ 1 ] = 0 ; /* pad */
opblk [ 2 ] = oper ;
opblk [ 3 ] = group ;
opblk [ 4 ] = fieldcount ;
memcpy ( opblk + 5 , ibuf , ibuflen ) ; /* other params */
size = i2o_parm_issue ( dev , I2O_CMD_UTIL_PARAMS_GET , opblk ,
size , resblk , reslen ) ;
kfree ( opblk ) ;
if ( size > reslen )
return reslen ;
return size ;
}
EXPORT_SYMBOL ( i2o_device_claim ) ;
EXPORT_SYMBOL ( i2o_device_claim_release ) ;
EXPORT_SYMBOL ( i2o_parm_field_get ) ;
EXPORT_SYMBOL ( i2o_parm_table_get ) ;
EXPORT_SYMBOL ( i2o_parm_issue ) ;