2007-04-27 18:01:34 +04:00
/*
* Copyright IBM Corp . 2007
* Author ( s ) : Peter Oberparleiter < peter . oberparleiter @ de . ibm . com >
*/
2008-08-01 18:39:14 +04:00
# include <linux/vmalloc.h>
2007-10-19 10:40:25 +04:00
# include <linux/bitops.h>
2007-04-27 18:01:34 +04:00
# include "idset.h"
# include "css.h"
struct idset {
int num_ssid ;
int num_id ;
unsigned long bitmap [ 0 ] ;
} ;
static inline unsigned long bitmap_size ( int num_ssid , int num_id )
{
return __BITOPS_WORDS ( num_ssid * num_id ) * sizeof ( unsigned long ) ;
}
static struct idset * idset_new ( int num_ssid , int num_id )
{
struct idset * set ;
2008-08-01 18:39:14 +04:00
set = vmalloc ( sizeof ( struct idset ) + bitmap_size ( num_ssid , num_id ) ) ;
2007-04-27 18:01:34 +04:00
if ( set ) {
set - > num_ssid = num_ssid ;
set - > num_id = num_id ;
2008-08-01 18:39:14 +04:00
memset ( set - > bitmap , 0 , bitmap_size ( num_ssid , num_id ) ) ;
2007-04-27 18:01:34 +04:00
}
return set ;
}
void idset_free ( struct idset * set )
{
2008-08-01 18:39:14 +04:00
vfree ( set ) ;
2007-04-27 18:01:34 +04:00
}
void idset_clear ( struct idset * set )
{
memset ( set - > bitmap , 0 , bitmap_size ( set - > num_ssid , set - > num_id ) ) ;
}
void idset_fill ( struct idset * set )
{
memset ( set - > bitmap , 0xff , bitmap_size ( set - > num_ssid , set - > num_id ) ) ;
}
static inline void idset_add ( struct idset * set , int ssid , int id )
{
set_bit ( ssid * set - > num_id + id , set - > bitmap ) ;
}
static inline void idset_del ( struct idset * set , int ssid , int id )
{
clear_bit ( ssid * set - > num_id + id , set - > bitmap ) ;
}
static inline int idset_contains ( struct idset * set , int ssid , int id )
{
return test_bit ( ssid * set - > num_id + id , set - > bitmap ) ;
}
static inline int idset_get_first ( struct idset * set , int * ssid , int * id )
{
int bitnum ;
bitnum = find_first_bit ( set - > bitmap , set - > num_ssid * set - > num_id ) ;
if ( bitnum > = set - > num_ssid * set - > num_id )
return 0 ;
* ssid = bitnum / set - > num_id ;
* id = bitnum % set - > num_id ;
return 1 ;
}
struct idset * idset_sch_new ( void )
{
2009-09-23 00:58:37 +04:00
return idset_new ( max_ssid + 1 , __MAX_SUBCHANNEL + 1 ) ;
2007-04-27 18:01:34 +04:00
}
void idset_sch_add ( struct idset * set , struct subchannel_id schid )
{
idset_add ( set , schid . ssid , schid . sch_no ) ;
}
void idset_sch_del ( struct idset * set , struct subchannel_id schid )
{
idset_del ( set , schid . ssid , schid . sch_no ) ;
}
int idset_sch_contains ( struct idset * set , struct subchannel_id schid )
{
return idset_contains ( set , schid . ssid , schid . sch_no ) ;
}
int idset_sch_get_first ( struct idset * set , struct subchannel_id * schid )
{
int ssid = 0 ;
int id = 0 ;
int rc ;
rc = idset_get_first ( set , & ssid , & id ) ;
if ( rc ) {
init_subchannel_id ( schid ) ;
schid - > ssid = ssid ;
schid - > sch_no = id ;
}
return rc ;
}
2009-09-23 00:58:34 +04:00
int idset_is_empty ( struct idset * set )
{
int bitnum ;
bitnum = find_first_bit ( set - > bitmap , set - > num_ssid * set - > num_id ) ;
if ( bitnum > = set - > num_ssid * set - > num_id )
return 1 ;
return 0 ;
}
2009-09-23 00:58:38 +04:00
void idset_add_set ( struct idset * to , struct idset * from )
{
unsigned long i , len ;
len = min ( __BITOPS_WORDS ( to - > num_ssid * to - > num_id ) ,
__BITOPS_WORDS ( from - > num_ssid * from - > num_id ) ) ;
for ( i = 0 ; i < len ; i + + )
to - > bitmap [ i ] | = from - > bitmap [ i ] ;
}