| 1 | /* | 
|---|
| 2 |  * dev_icu.c - ICU (Interrupt Controler Unit) generic device API implementation. | 
|---|
| 3 |  * | 
|---|
| 4 |  * Authors   Alain Greiner  (2016) | 
|---|
| 5 |  * | 
|---|
| 6 |  * Copyright (c) UPMC Sorbonne Universites | 
|---|
| 7 |  * | 
|---|
| 8 |  * This file is part of ALMOS-MKH. | 
|---|
| 9 |  * | 
|---|
| 10 |  * ALMOS-MKH is free software; you can redistribute it and/or modify it | 
|---|
| 11 |  * under the terms of the GNU General Public License as published by | 
|---|
| 12 |  * the Free Software Foundation; version 2.0 of the License. | 
|---|
| 13 |  * | 
|---|
| 14 |  * ALMOS-MKH is distributed in the hope that it will be useful, but | 
|---|
| 15 |  * WITHOUT ANY WARRANTY; without even the implied warranty of | 
|---|
| 16 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|---|
| 17 |  * General Public License for more details. | 
|---|
| 18 |  * | 
|---|
| 19 |  * You should have received a copy of the GNU General Public License | 
|---|
| 20 |  * along with ALMOS-MKH; if not, write to the Free Software Foundation, | 
|---|
| 21 |  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 
|---|
| 22 |  */ | 
|---|
| 23 |  | 
|---|
| 24 | #include <hal_types.h> | 
|---|
| 25 | #include <hal_special.h> | 
|---|
| 26 | #include <chdev.h> | 
|---|
| 27 | #include <thread.h> | 
|---|
| 28 | #include <cluster.h> | 
|---|
| 29 | #include <printk.h> | 
|---|
| 30 | #include <memcpy.h> | 
|---|
| 31 | #include <spinlock.h> | 
|---|
| 32 | #include <soclib_xcu.h> | 
|---|
| 33 | #include <dev_icu.h> | 
|---|
| 34 |  | 
|---|
| 35 | ///////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 36 | // Extern global variables | 
|---|
| 37 | ///////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 38 |  | 
|---|
| 39 | extern chdev_directory_t  chdev_dir;         // allocated in kernel_init.c | 
|---|
| 40 |  | 
|---|
| 41 | extern chdev_pic_input_t  chdev_pic_input;   // allocated in kernel_init.c | 
|---|
| 42 |  | 
|---|
| 43 | ///////////////////////////////// | 
|---|
| 44 | void dev_icu_init( chdev_t * icu, | 
|---|
| 45 |                    uint32_t  hwi_nr, | 
|---|
| 46 |                    uint32_t  wti_nr, | 
|---|
| 47 |                    uint32_t  pti_nr ) | 
|---|
| 48 | { | 
|---|
| 49 |     // set chdev name | 
|---|
| 50 |     snprintf( icu->name , 16 , "icu_%x" , local_cxy ); | 
|---|
| 51 |  | 
|---|
| 52 |     // set ICU chdev extension fields | 
|---|
| 53 |     icu->ext.icu.hwi_nr     = hwi_nr; | 
|---|
| 54 |     icu->ext.icu.wti_nr     = wti_nr; | 
|---|
| 55 |     icu->ext.icu.pti_nr     = pti_nr; | 
|---|
| 56 |     icu->ext.icu.wti_bitmap = 0; | 
|---|
| 57 |     spinlock_init( &icu->ext.icu.wti_lock ); | 
|---|
| 58 |     | 
|---|
| 59 |     // get implementation | 
|---|
| 60 |     uint32_t impl = icu->impl; | 
|---|
| 61 |  | 
|---|
| 62 |     // call the relevant driver init function | 
|---|
| 63 |     if( impl == IMPL_ICU_XCU ) | 
|---|
| 64 |     { | 
|---|
| 65 |         uint32_t  lid; | 
|---|
| 66 |         for( lid = 0 ; lid < LOCAL_CLUSTER->cores_nr ; lid++ ) | 
|---|
| 67 |         { | 
|---|
| 68 |             soclib_xcu_init( icu , lid ); | 
|---|
| 69 |         } | 
|---|
| 70 |     } | 
|---|
| 71 |     else | 
|---|
| 72 |     { | 
|---|
| 73 |         assert( false , __FUNCTION__ , "undefined ICU implementation" ); | 
|---|
| 74 |     } | 
|---|
| 75 | } // end dev_icu_init() | 
|---|
| 76 |  | 
|---|
| 77 | ///////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 78 | // This static function check the irq_type / irq_index arguments. | 
|---|
| 79 | // It is called by the dev_icu_enable_irq() & dev_icu_disable_irq() functions. | 
|---|
| 80 | ///////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 81 | static inline void dev_icu_check_irq( chdev_t  * icu, | 
|---|
| 82 |                                       uint32_t   irq_type, | 
|---|
| 83 |                                       uint32_t   irq_index ) | 
|---|
| 84 | { | 
|---|
| 85 |     if( irq_type == HWI_TYPE )  | 
|---|
| 86 |     { | 
|---|
| 87 |         if( irq_index >= icu->ext.icu.hwi_nr ) | 
|---|
| 88 |         { | 
|---|
| 89 |             printk("\n[PANIC] in %s : illegal HWI index = %d / max = %d\n",  | 
|---|
| 90 |                    __FUNCTION__ , irq_index , icu->ext.icu.hwi_nr ); | 
|---|
| 91 |             hal_core_sleep(); | 
|---|
| 92 |         } | 
|---|
| 93 |     } | 
|---|
| 94 |     else if( irq_type == WTI_TYPE ) | 
|---|
| 95 |     { | 
|---|
| 96 |         if( irq_index >= icu->ext.icu.wti_nr ) | 
|---|
| 97 |         { | 
|---|
| 98 |             printk("\n[PANIC] in %s : illegal WTI index = %d / max = %d\n",  | 
|---|
| 99 |                    __FUNCTION__ , irq_index , icu->ext.icu.wti_nr ); | 
|---|
| 100 |             hal_core_sleep(); | 
|---|
| 101 |         } | 
|---|
| 102 |     } | 
|---|
| 103 |     else  //  irq_type == PTI_TYPE  | 
|---|
| 104 |     { | 
|---|
| 105 |         if( irq_index >= icu->ext.icu.pti_nr ) | 
|---|
| 106 |         { | 
|---|
| 107 |             printk("\n[PANIC] in %s : illegal PTI index = %d / max = %d\n", | 
|---|
| 108 |                    __FUNCTION__ , irq_index , icu->ext.icu.pti_nr ); | 
|---|
| 109 |             hal_core_sleep(); | 
|---|
| 110 |         } | 
|---|
| 111 |     } | 
|---|
| 112 | }  // end dev_icu_check_irq() | 
|---|
| 113 |  | 
|---|
| 114 | //////////////////////////////////////// | 
|---|
| 115 | void dev_icu_enable_irq( lid_t      lid, | 
|---|
| 116 |                          uint32_t   irq_type, | 
|---|
| 117 |                          uint32_t   irq_index, | 
|---|
| 118 |                          chdev_t  * src_chdev ) | 
|---|
| 119 | { | 
|---|
| 120 |     // get local pointer on local ICU chdev | 
|---|
| 121 |     xptr_t    icu_xp = chdev_dir.icu[local_cxy]; | 
|---|
| 122 |     chdev_t * icu    = (chdev_t *)GET_PTR( icu_xp ); | 
|---|
| 123 |  | 
|---|
| 124 |     // check IRQ type and index | 
|---|
| 125 |     dev_icu_check_irq( icu , irq_type , irq_index ); | 
|---|
| 126 |  | 
|---|
| 127 |     // call implementation specific ICU driver to enable IRQ | 
|---|
| 128 |     if( icu->impl == IMPL_ICU_XCU )  | 
|---|
| 129 |     { | 
|---|
| 130 |          soclib_xcu_enable_irq( icu , 1<<irq_index , irq_type , lid ); | 
|---|
| 131 |     } | 
|---|
| 132 |  | 
|---|
| 133 |     // This is only done for an HWI, or for a WTI that is not an IPI | 
|---|
| 134 |     if( (irq_type != PTI_TYPE) && (src_chdev != NULL) ) | 
|---|
| 135 |     { | 
|---|
| 136 |         // get selected core local pointer, and register | 
|---|
| 137 |         // source chdev pointer in relevant interrupt vector | 
|---|
| 138 |         core_t * core = &LOCAL_CLUSTER->core_tbl[lid]; | 
|---|
| 139 |             core_set_irq_vector_entry( core , irq_type , irq_index , src_chdev ); | 
|---|
| 140 |  | 
|---|
| 141 |         // (3) register IRQ type and index in source chdev descriptor | 
|---|
| 142 |         src_chdev->irq_type = irq_type; | 
|---|
| 143 |         src_chdev->irq_id   = irq_index; | 
|---|
| 144 |     } | 
|---|
| 145 | }  // end dev_icu_enable_irq() | 
|---|
| 146 |  | 
|---|
| 147 | ///////////////////////////////////////// | 
|---|
| 148 | void dev_icu_disable_irq( lid_t      lid, | 
|---|
| 149 |                           uint32_t   irq_type, | 
|---|
| 150 |                           uint32_t   irq_index ) | 
|---|
| 151 | { | 
|---|
| 152 |     // get local pointer on local ICU chdev | 
|---|
| 153 |     xptr_t    icu_xp = chdev_dir.icu[local_cxy]; | 
|---|
| 154 |     chdev_t * icu    = (chdev_t *)GET_PTR( icu_xp ); | 
|---|
| 155 |  | 
|---|
| 156 |     // check IRQ type and index | 
|---|
| 157 |     dev_icu_check_irq( icu , irq_type , irq_index ); | 
|---|
| 158 |  | 
|---|
| 159 |     // call the implementation specific ICU driver to disable IRQ  | 
|---|
| 160 |     if( icu->impl == IMPL_ICU_XCU )  | 
|---|
| 161 |     { | 
|---|
| 162 |         soclib_xcu_disable_irq( icu , 1<<irq_index , irq_type , lid ); | 
|---|
| 163 |     } | 
|---|
| 164 |  | 
|---|
| 165 |     // This is only done for HWI or WTI that are not IPI | 
|---|
| 166 |     if( irq_type != PTI_TYPE ) | 
|---|
| 167 |     { | 
|---|
| 168 |         // get selected remote core local pointer, and remove | 
|---|
| 169 |         // the source chdev xptr from relevant interrupt vector | 
|---|
| 170 |         core_t * core = &LOCAL_CLUSTER->core_tbl[lid]; | 
|---|
| 171 |             core_set_irq_vector_entry( core , irq_type , irq_index , NULL ); | 
|---|
| 172 |     } | 
|---|
| 173 | } // end dev_icu_disable_irq() | 
|---|
| 174 |  | 
|---|
| 175 | /////////////////////////////////////// | 
|---|
| 176 | void dev_icu_get_masks( lid_t      lid, | 
|---|
| 177 |                         uint32_t * hwi_mask, | 
|---|
| 178 |                         uint32_t * wti_mask, | 
|---|
| 179 |                         uint32_t * pti_mask ) | 
|---|
| 180 | { | 
|---|
| 181 |     // get local pointer on local ICU chdev | 
|---|
| 182 |     xptr_t    icu_xp = chdev_dir.icu[local_cxy]; | 
|---|
| 183 |     chdev_t * icu    = (chdev_t *)GET_PTR( icu_xp ); | 
|---|
| 184 |  | 
|---|
| 185 |     if( icu->impl == IMPL_ICU_XCU ) | 
|---|
| 186 |     { | 
|---|
| 187 |         soclib_xcu_get_masks( icu , lid , hwi_mask , wti_mask , pti_mask ); | 
|---|
| 188 |     } | 
|---|
| 189 | } | 
|---|
| 190 |  | 
|---|
| 191 | ////////////////////////////////////////////// | 
|---|
| 192 | void dev_icu_set_period( uint32_t   pti_index, | 
|---|
| 193 |                          uint32_t   period ) | 
|---|
| 194 | { | 
|---|
| 195 |     // get local pointer on local ICU chdev | 
|---|
| 196 |     xptr_t    icu_xp = chdev_dir.icu[local_cxy]; | 
|---|
| 197 |     chdev_t * icu    = (chdev_t *)GET_PTR( icu_xp ); | 
|---|
| 198 |  | 
|---|
| 199 |     // check PTI index | 
|---|
| 200 |     assert( (pti_index < icu->ext.icu.pti_nr) , __FUNCTION__ , "illegal PTI index" );  | 
|---|
| 201 |  | 
|---|
| 202 |     // call the implementation specific driver ICU to set period  | 
|---|
| 203 |     if( icu->impl == IMPL_ICU_XCU )  | 
|---|
| 204 |     { | 
|---|
| 205 |         soclib_xcu_set_period( icu , pti_index , period ); | 
|---|
| 206 |     } | 
|---|
| 207 | }  // end dev_icu_set_period() | 
|---|
| 208 |  | 
|---|
| 209 | //////////////////////////////////////////// | 
|---|
| 210 | void dev_icu_ack_timer( uint32_t pti_index ) | 
|---|
| 211 | { | 
|---|
| 212 |     // get local pointer on local ICU chdev | 
|---|
| 213 |     xptr_t    icu_xp = chdev_dir.icu[local_cxy]; | 
|---|
| 214 |     chdev_t * icu    = (chdev_t *)GET_PTR( icu_xp ); | 
|---|
| 215 |  | 
|---|
| 216 |     // check PTI index | 
|---|
| 217 |     assert( (pti_index < icu->ext.icu.pti_nr) , __FUNCTION__ , "illegal PTI index" );  | 
|---|
| 218 |  | 
|---|
| 219 |     // call the implementation specific driver ICU to acknowledge PTI IRQ | 
|---|
| 220 |     if( icu->impl == IMPL_ICU_XCU )  | 
|---|
| 221 |     { | 
|---|
| 222 |         soclib_xcu_ack_timer( icu , pti_index ); | 
|---|
| 223 |     } | 
|---|
| 224 | }  // end dev_icu_ack_timer() | 
|---|
| 225 |  | 
|---|
| 226 | //////////////////////////////////// | 
|---|
| 227 | void dev_icu_send_ipi( cxy_t    cxy, | 
|---|
| 228 |                        lid_t    lid ) | 
|---|
| 229 | { | 
|---|
| 230 |     // check arguments  | 
|---|
| 231 |     cluster_t * cluster  = LOCAL_CLUSTER; | 
|---|
| 232 |     uint32_t    y_width  = cluster->y_width; | 
|---|
| 233 |     uint32_t    x_size   = cluster->x_size; | 
|---|
| 234 |     uint32_t    y_size   = cluster->y_size; | 
|---|
| 235 |     uint32_t    cores_nr = cluster->cores_nr; | 
|---|
| 236 |     uint32_t    x = cxy >> y_width; | 
|---|
| 237 |     uint32_t    y = cxy & ((1<<y_width)-1); | 
|---|
| 238 |  | 
|---|
| 239 |     assert( ((x < x_size) && (y < y_size)) , __FUNCTION__ , "illegal cluster identifier" ); | 
|---|
| 240 |  | 
|---|
| 241 |     assert( (lid < cores_nr) , __FUNCTION__ , "illegal core local index" ); | 
|---|
| 242 |  | 
|---|
| 243 |     // get extended pointer on target ICU chdev | 
|---|
| 244 |     xptr_t icu_xp = chdev_dir.icu[cxy]; | 
|---|
| 245 |  | 
|---|
| 246 |      // get target ICU cluster and local pointer | 
|---|
| 247 |     cxy_t     icu_cxy = GET_CXY( icu_xp ); | 
|---|
| 248 |     chdev_t * icu_ptr = (chdev_t *)GET_PTR( icu_xp ); | 
|---|
| 249 |  | 
|---|
| 250 |     // get implementation from remote ICU chdev | 
|---|
| 251 |     uint32_t impl = hal_remote_lw( XPTR( icu_cxy , &icu_ptr->impl ) );    | 
|---|
| 252 |  | 
|---|
| 253 |     // call the implementation specific ICU driver to send IPI | 
|---|
| 254 |     if( impl == IMPL_ICU_XCU )  | 
|---|
| 255 |     { | 
|---|
| 256 |         soclib_xcu_send_ipi( icu_xp , lid ); | 
|---|
| 257 |     } | 
|---|
| 258 | }  // end dev_icu_send_ipi() | 
|---|
| 259 |  | 
|---|
| 260 | ////////////////////////// | 
|---|
| 261 | void dev_icu_irq_handler() | 
|---|
| 262 | { | 
|---|
| 263 |     uint32_t   hwi_status;   // HWI index + 1  / no pending HWI if 0 | 
|---|
| 264 |     uint32_t   wti_status;   // WTI index + 1  / no pending WTI if 0 | 
|---|
| 265 |     uint32_t   pti_status;   // PTI index + 1  / no pending PTI if 0 | 
|---|
| 266 |     chdev_t  * src_chdev;    // pointer on source chdev descriptor | 
|---|
| 267 |     uint32_t   index;        // IRQ index | 
|---|
| 268 |  | 
|---|
| 269 |     core_t   * core = CURRENT_CORE; | 
|---|
| 270 |  | 
|---|
| 271 |     // get local pointer on local ICU chdev | 
|---|
| 272 |     xptr_t    icu_xp = chdev_dir.icu[local_cxy]; | 
|---|
| 273 |     chdev_t * icu    = (chdev_t *)GET_PTR( icu_xp ); | 
|---|
| 274 |  | 
|---|
| 275 |     // call the implementation specific ICU driver   | 
|---|
| 276 |     // to return highest priority pending IRQ of each type | 
|---|
| 277 |     if( icu->impl == IMPL_ICU_XCU ) | 
|---|
| 278 |     { | 
|---|
| 279 |         soclib_xcu_get_status( icu , core->lid , &hwi_status , &wti_status , &pti_status ); | 
|---|
| 280 |     } | 
|---|
| 281 |  | 
|---|
| 282 |     // analyse ICU status and handle up to 3 pending IRQ (one WTI, one HWI, one PTI) | 
|---|
| 283 |  | 
|---|
| 284 |     if( wti_status )          // pending WTI  | 
|---|
| 285 |         { | 
|---|
| 286 |         index = wti_status - 1; | 
|---|
| 287 |  | 
|---|
| 288 |         if( index < LOCAL_CLUSTER->cores_nr )   // it is an IPI | 
|---|
| 289 |         { | 
|---|
| 290 |             assert( (index == core->lid) , __FUNCTION__ , "illegal IPI index" ); | 
|---|
| 291 |  | 
|---|
| 292 |             // TODO acknowledge WTI [AG] | 
|---|
| 293 |  | 
|---|
| 294 |             // TODO force scheduling [AG] | 
|---|
| 295 |         } | 
|---|
| 296 |         else                                    // it is an external device | 
|---|
| 297 |         { | 
|---|
| 298 |             // get pointer on IRQ source chdev | 
|---|
| 299 |                     src_chdev = core->wti_vector[index]; | 
|---|
| 300 |  | 
|---|
| 301 |                     if( src_chdev == NULL )        // strange, but not fatal => disable IRQ | 
|---|
| 302 |                     { | 
|---|
| 303 |                 printk("\n[WARNING] in %s : no handler for WTI %d on core %d in cluster %x\n", | 
|---|
| 304 |                        __FUNCTION__ , index , core->lid , local_cxy ); | 
|---|
| 305 |                     core->spurious_irqs ++; | 
|---|
| 306 |                 dev_icu_disable_irq( core->lid , WTI_TYPE , index );  | 
|---|
| 307 |             } | 
|---|
| 308 |             else                                 // call relevant ISR | 
|---|
| 309 |             { | 
|---|
| 310 |                         icu_dmsg("\n[INFO] %s received WTI : index = %d for cpu %d in cluster %d\n", | 
|---|
| 311 |                          __FUNCTION__ , index , core->lid , local_cxy ); | 
|---|
| 312 |  | 
|---|
| 313 |                 // call ISR | 
|---|
| 314 |                     src_chdev->isr( src_chdev ); | 
|---|
| 315 |             } | 
|---|
| 316 |         } | 
|---|
| 317 |         } | 
|---|
| 318 |  | 
|---|
| 319 |         if( hwi_status )      // pending HWI | 
|---|
| 320 |         { | 
|---|
| 321 |         index = hwi_status - 1; | 
|---|
| 322 |  | 
|---|
| 323 |         // get pointer on IRQ source chdev | 
|---|
| 324 |                 src_chdev = core->hwi_vector[index]; | 
|---|
| 325 |  | 
|---|
| 326 |                 if( src_chdev == NULL )        // strange, but not fatal => disable IRQ | 
|---|
| 327 |                 { | 
|---|
| 328 |             printk("\n[WARNING] in %s : no handler for HWI %d on core %d in cluster %x\n", | 
|---|
| 329 |                    __FUNCTION__ , index , core->lid , local_cxy ); | 
|---|
| 330 |                 core->spurious_irqs ++; | 
|---|
| 331 |             dev_icu_disable_irq( core->lid , HWI_TYPE , index );  | 
|---|
| 332 |                 } | 
|---|
| 333 |         else                    // call relevant ISR | 
|---|
| 334 |         { | 
|---|
| 335 |                     icu_dmsg("\n[INFO] %s received HWI : index = %d for cpu %d in cluster %d\n", | 
|---|
| 336 |                      __FUNCTION__ , index , core->lid , local_cxy ); | 
|---|
| 337 |  | 
|---|
| 338 |             // call ISR | 
|---|
| 339 |                     src_chdev->isr( src_chdev ); | 
|---|
| 340 |         } | 
|---|
| 341 |         } | 
|---|
| 342 |  | 
|---|
| 343 |     if( pti_status )      // pending PTI | 
|---|
| 344 |         { | 
|---|
| 345 |         index = pti_status - 1; | 
|---|
| 346 |  | 
|---|
| 347 |                 icu_dmsg("\n[INFO] %s received PTI : index = %d for cpu %d in cluster %d\n", | 
|---|
| 348 |                  __FUNCTION__ , index , core->lid , local_cxy ); | 
|---|
| 349 |  | 
|---|
| 350 |         // acknowledge PTI | 
|---|
| 351 |         dev_icu_ack_timer( index ); | 
|---|
| 352 |  | 
|---|
| 353 |         if( index < LOCAL_CLUSTER->cores_nr )  // its a TICK event | 
|---|
| 354 |         { | 
|---|
| 355 |             // TODO execute all actions related to TICK event | 
|---|
| 356 |             core_clock( core ); | 
|---|
| 357 |         } | 
|---|
| 358 |         else | 
|---|
| 359 |         { | 
|---|
| 360 |             printk("\n[WARNING] in %s : no handler for PTI %d on core %d in cluster %x\n", | 
|---|
| 361 |                    __FUNCTION__ , index , core->lid , local_cxy ); | 
|---|
| 362 |                 core->spurious_irqs ++; | 
|---|
| 363 |             dev_icu_disable_irq( core->lid , PTI_TYPE , index );  | 
|---|
| 364 |         } | 
|---|
| 365 |         } | 
|---|
| 366 | }  // end dev_icu_irq_handler() | 
|---|
| 367 |  | 
|---|
| 368 | //////////////////////////// | 
|---|
| 369 | uint32_t dev_icu_wti_alloc() | 
|---|
| 370 | { | 
|---|
| 371 |     // get local pointer on local ICU chdev | 
|---|
| 372 |     xptr_t    icu_xp = chdev_dir.icu[local_cxy]; | 
|---|
| 373 |     chdev_t * icu    = (chdev_t *)GET_PTR( icu_xp ); | 
|---|
| 374 |  | 
|---|
| 375 |     // get bitmap pointer, lock pointer, and size | 
|---|
| 376 |     uint32_t   * bitmap = &icu->ext.icu.wti_bitmap; | 
|---|
| 377 |     spinlock_t * lock   = &icu->ext.icu.wti_lock; | 
|---|
| 378 |     uint32_t     size   =  icu->ext.icu.wti_nr; | 
|---|
| 379 |  | 
|---|
| 380 |     // get lock protecting WTI allocator | 
|---|
| 381 |     spinlock_lock( lock ); | 
|---|
| 382 |  | 
|---|
| 383 |     // get first free mailbox index | 
|---|
| 384 |     uint32_t index = (uint32_t)bitmap_ffc( bitmap , size ); | 
|---|
| 385 |    | 
|---|
| 386 |     // set bitmap entry if found | 
|---|
| 387 |     if( index < size ) bitmap_set( bitmap , index ); | 
|---|
| 388 |  | 
|---|
| 389 |     // release lock | 
|---|
| 390 |     spinlock_unlock( lock ); | 
|---|
| 391 |   | 
|---|
| 392 |     return index; | 
|---|
| 393 | }  // end dev_icu_wti_alloc() | 
|---|
| 394 |  | 
|---|
| 395 | ////////////////////////////////////////// | 
|---|
| 396 | void dev_icu_wti_release( uint32_t index ) | 
|---|
| 397 | { | 
|---|
| 398 |     // get pointer on local ICU chdev descriptor | 
|---|
| 399 |     xptr_t    icu_xp  = chdev_dir.icu[local_cxy]; | 
|---|
| 400 |     chdev_t * icu_ptr = (chdev_t *)GET_PTR( icu_xp ); | 
|---|
| 401 |  | 
|---|
| 402 |     // get bitmap pointer, lock, and size | 
|---|
| 403 |     bitmap_t   * bitmap = &icu_ptr->ext.icu.wti_bitmap; | 
|---|
| 404 |     spinlock_t * lock   = &icu_ptr->ext.icu.wti_lock; | 
|---|
| 405 |     uint32_t     size   =  icu_ptr->ext.icu.wti_nr; | 
|---|
| 406 |  | 
|---|
| 407 |     // check index | 
|---|
| 408 |     assert( (index < size) , __FUNCTION__ , "illegal WTI index" ); | 
|---|
| 409 |  | 
|---|
| 410 |     // get lock protecting WTI allocator | 
|---|
| 411 |     spinlock_lock( lock ); | 
|---|
| 412 |  | 
|---|
| 413 |     // clear bitmap entry  | 
|---|
| 414 |     bitmap_clear( bitmap , index ); | 
|---|
| 415 |  | 
|---|
| 416 |     // release lock | 
|---|
| 417 |     spinlock_unlock( lock ); | 
|---|
| 418 |  | 
|---|
| 419 | }  // end dev_icu_wti_release() | 
|---|
| 420 |  | 
|---|
| 421 | ////////////////////////////////////////////// | 
|---|
| 422 | uint32_t * dev_icu_wti_ptr( uint32_t  wti_id ) | 
|---|
| 423 | { | 
|---|
| 424 |     uint32_t *  wti_ptr = NULL; | 
|---|
| 425 |  | 
|---|
| 426 |     // get pointer on local ICU chdev descriptor | 
|---|
| 427 |     xptr_t    icu_xp  = chdev_dir.icu[local_cxy]; | 
|---|
| 428 |     chdev_t * icu     = (chdev_t *)GET_PTR( icu_xp ); | 
|---|
| 429 |  | 
|---|
| 430 |     // call implementation specific ICU driver | 
|---|
| 431 |     if( icu->impl == IMPL_ICU_XCU ) | 
|---|
| 432 |     { | 
|---|
| 433 |         wti_ptr = soclib_xcu_wti_ptr( icu , wti_id );    | 
|---|
| 434 |     } | 
|---|
| 435 |  | 
|---|
| 436 |     return wti_ptr; | 
|---|
| 437 | }   // end dev_icu_wti_xptr() | 
|---|
| 438 |  | 
|---|
| 439 |  | 
|---|