Changeset 576


Ignore:
Timestamp:
May 21, 2015, 3:03:39 PM (9 years ago)
Author:
bellefin
Message:

Improve hba driver : introduce the tables _hba_active_cmd and _hba_allocated_cmd, and a cmd allocator function which uses a lock (in descheduling mode) to get a free cmd index between 0 and 31

File:
1 edited

Legend:

Unmodified
Added
Removed
  • soft/giet_vm/giet_drivers/hba_driver.c

    r563 r576  
    2727///////////////////////////////////////////////////////////////////////////////////
    2828
    29 // global index ot the task, for each entry in the command list
    30 __attribute__((section(".kdata")))
    31 unsigned int _hba_gtid[32];
    32 
    33 // status of the command, for each entry in the command list
    34 __attribute__((section(".kdata")))
    35 unsigned int _hba_status[32];
     29//////////////////////////////////////////////////////////////////////////////////
     30// The global variable hba_boot_mode defines the way the HBA component is used
     31// and must be defined in both kernel_init.c and boot.c files.
     32// - during the boot phase, only one processor has access to the HBA in synchronous
     33//   mode, there is no need for the allocator to use a lock
     34// - after the boot phase, the HBA device can be used by several processors. The
     35//   allocator is protected by a sqt_lock.
     36//////////////////////////////////////////////////////////////////////////////////
     37       
     38extern unsigned int _hba_boot_mode;
     39
     40__attribute__((section(".kdata")))
     41sqt_lock_t          _hba_allocator_lock  __attribute__((aligned(64)));
     42
     43// state of each slot (allocated to a task or not)
     44// access must be protected by the allocator_lock in descheduling mode
     45__attribute__((section(".kdata")))
     46unsigned int        _hba_allocated_cmd[32];
     47
     48// state of the command (active or not), for each possible slot
     49// used only in descheduling mode
     50__attribute__((section(".kdata")))
     51unsigned int        _hba_active_cmd[32];
     52
     53// global index of the task, for each entry in the command list
     54__attribute__((section(".kdata")))
     55unsigned int        _hba_gtid[32];
     56
     57// status of HBA commands
     58__attribute__((section(".kdata")))
     59unsigned int        _hba_status;
    3660
    3761// command list : up to 32 commands
    3862__attribute__((section(".kdata")))
    39 hba_cmd_desc_t  _hba_cmd_list[32] __attribute__((aligned(0x40)));   
     63hba_cmd_desc_t      _hba_cmd_list[32] __attribute__((aligned(0x40)));   
    4064
    4165// command tables array : one command table per entry in command list
    4266__attribute__((section(".kdata")))
    43 hba_cmd_table_t _hba_cmd_table[32] __attribute__((aligned(0x40)));
    44 
    45 // command list write index : next slot to register a command
    46 __attribute__((section(".kdata")))
    47 unsigned int     _hba_cmd_ptw;
    48 
    49 // command list read index : next slot to poll a completed command
    50 __attribute__((section(".kdata")))
    51 unsigned int     _hba_cmd_ptr;
     67hba_cmd_table_t     _hba_cmd_table[32] __attribute__((aligned(0x40)));
     68
    5269
    5370//////////////////////////////////////////////////////////////////////////////
     
    7592
    7693///////////////////////////////////////////////////////////////////////////////
    77 // This function register a command in both the command list
    78 // and the command table, and updates the HBA_PXCI register.
     94// This blocking fonction allocates a free command index to the task.
     95// The hba_allocator_lock is used except in boot mode.
     96// It returns the allocated command index (between 0 and 31)
     97///////////////////////////////////////////////////////////////////////////////
     98unsigned int _hba_cmd_alloc()
     99{
     100    unsigned int found = 0;
     101    unsigned int c;           // command index for the loop
     102    unsigned int cmd_id = -1; // allocated command index when found
     103
     104    while ( found == 0)
     105    {
     106        if ( !_hba_boot_mode )
     107            _sqt_lock_acquire(&_hba_allocator_lock);
     108
     109        for ( c = 0; c < 32 ; c++ )
     110        {
     111            if (_hba_allocated_cmd[c] == 0)
     112            {
     113                found = 1;
     114                cmd_id = c;
     115                _hba_allocated_cmd[c] = 1;
     116                break;
     117            }
     118        }
     119
     120        if ( !_hba_boot_mode )
     121            _sqt_lock_release(&_hba_allocator_lock);
     122    }
     123
     124    return cmd_id;
     125}
     126
     127///////////////////////////////////////////////////////////////////////////////
     128// This function releases the command index in the hba_allocated_cmd table.
     129// There is no need to take the lock because only the task which owns the
     130// command can release it.
     131// return 0 if success, -1 if error
     132///////////////////////////////////////////////////////////////////////////////
     133unsigned int _hba_cmd_release(unsigned int cmd_id)
     134{
     135    if ( _hba_allocated_cmd[cmd_id] == 0 )
     136    {
     137        _printf("\n[HBA ERROR] in _hba_access() : ask to release a command which is not allocated\n");
     138        return -1;
     139    }
     140   
     141    _hba_allocated_cmd[cmd_id] = 0;
     142    return 0;
     143}
     144
     145
     146///////////////////////////////////////////////////////////////////////////////
     147// This function gets a command index with the hba_cmd_alloc function. Then it
     148// registers a command in both the command list and the command table. It
     149// updates the HBA_PXCI register and the hba_active_cmd in descheduling mode.
     150// At the end the command slot is released.
    79151// return 0 if success, -1 if error
    80152///////////////////////////////////////////////////////////////////////////////
     
    97169#endif
    98170
     171    unsigned int       cmd_id;            // command index
    99172    unsigned int       pxci;              // HBA_PXCI register value
    100     unsigned int       ptw;               // command list write pointer
    101173    unsigned int       pxis;              // HBA_PXIS register value
    102174    hba_cmd_desc_t*    cmd_desc;          // command descriptor pointer   
     
    111183
    112184    // get one entry in Command List
    113     // atomic increment on the _hba_cmd_ptw allocator
    114     // only the 5 LSB bits are used to index the Command List
    115     ptw = _atomic_increment( &_hba_cmd_ptw , 1 ) & 0x1F;
    116 
    117     // blocked until allocated entry in Command List is empty
    118     do
    119     {
    120         // get PXCI register
    121         pxci = _hba_get_register( HBA_PXCI );
    122     }
    123     while ( pxci & (1<<ptw) );
     185    cmd_id = _hba_cmd_alloc();
    124186
    125187    // compute pointers on command descriptor and command table   
    126     cmd_desc  = &_hba_cmd_list[ptw];
    127     cmd_table = &_hba_cmd_table[ptw];
     188    cmd_desc  = &_hba_cmd_list[cmd_id];
     189    cmd_table = &_hba_cmd_table[cmd_id];
    128190
    129191    // set  buffer descriptor in command table
     
    182244    {
    183245        // start HBA transfer
    184         _hba_set_register( HBA_PXCI, (1<<ptw) );
     246        _hba_set_register( HBA_PXCI, (1<<cmd_id) );
    185247
    186248#if GIET_DEBUG_IOC_DRIVER
     
    188250_printf("\n[DEBUG HBA] _hba_access() : P[%d,%d,%d] get slot %d in Cmd List "
    189251        " at cycle %d / polling\n",
    190         ptw , x , y , p , _get_proctime() );
     252        x , y , p , cmd_id, _get_proctime() );
    191253#endif
    192254        // disable IRQs in PXIE register
    193255        _hba_set_register( HBA_PXIE , 0 );
    194256
    195         // poll PXCI[ptw] until command completed by HBA
     257        // poll PXCI[cmd_id] until command completed by HBA
    196258        do
    197259        {
     
    204266#endif
    205267        }
    206         while( pxci & (1<<ptw) );
     268        while( pxci & (1<<cmd_id) );
    207269             
    208270        // get PXIS register
     
    227289_printf("\n[DEBUG HBA] _hba_access() : P[%d,%d,%d] get slot %d in Cmd List "
    228290        "at cycle %d / descheduling\n",
    229         ptw , x , y , p , _get_proctime() );
     291        x , y , p , cmd_id, _get_proctime() );
    230292#endif
    231293        unsigned int save_sr;
     
    235297        _hba_set_register( HBA_PXIE , 0x00000001 );
    236298
    237         // set _hba_gtid[ptw]
    238         _hba_gtid[ptw] = (procid<<16) + ltid;
     299        // set _hba_gtid[cmd_id]
     300        _hba_gtid[cmd_id] = (procid<<16) + ltid;
    239301
    240302        // enters critical section
     
    245307
    246308        // start HBA transfer
    247         _hba_set_register( HBA_PXCI, (1<<ptw) );
     309        _hba_set_register( HBA_PXCI, (1<<cmd_id) );
     310
     311        // set _hba_active_cmd[cmd_id]
     312        _hba_active_cmd[cmd_id] = 1;
    248313
    249314        // deschedule task
     
    260325
    261326        // get command status
    262         pxis = _hba_status[ptw];
    263     }   
    264 
    265 #if GIET_DEBUG_IOC_DRIVER
    266 if (_get_proctime() > GIET_DEBUG_IOC_DRIVER)
    267 _printf("\n[DEBUG HBA] _hba_access() : P[%d,%d,%d] exit at cycle %d\n",
    268         x , y , p , _get_proctime() );
    269 #endif
    270 
    271     if ( pxis & 0x40000000 ) return pxis;
    272     else                     return 0;
     327        pxis = _hba_status;
     328    }
     329   
     330    // release the cmd index
     331    unsigned int release_success;
     332    release_success = _hba_cmd_release(cmd_id);
     333
     334#if GIET_DEBUG_IOC_DRIVER
     335if (_get_proctime() > GIET_DEBUG_IOC_DRIVER)
     336_printf("\n[DEBUG HBA] _hba_access() : P[%d,%d,%d] release slot %d in Cmd List "
     337        "and exit at cycle %d\n",
     338        x , y , p, cmd_id,
     339        _get_proctime() );
     340#endif
     341
     342    if ( release_success != 0 )   return -1;
     343    else if ( pxis & 0x40000000 ) return pxis;
     344    else                          return 0;
    273345
    274346} // end _hba_access()
     
    298370    }
    299371
    300     // initialise Command List pointers
    301     _hba_cmd_ptw = 0;
    302     _hba_cmd_ptr = 0;
    303 
    304     // initialise Command Descriptors in Command List
     372    // initialise allocator lock if not in boot mode
     373    if ( !_hba_boot_mode )
     374        _sqt_lock_init(&_hba_allocator_lock);
     375
     376    // initialise Command Descriptors in Command List, allocated command table
     377    // and active command table
    305378    unsigned int         c;     
    306379    unsigned long long   paddr;
     
    310383        _hba_cmd_list[c].ctba  = (unsigned int)(paddr);
    311384        _hba_cmd_list[c].ctbau = (unsigned int)(paddr>>32);
     385        _hba_allocated_cmd[c] = 0;
     386        _hba_active_cmd[c] = 0;
    312387    }
    313388
     
    329404               unsigned int channel )   // unused
    330405{
     406    // save PXIS register if there is no previous error
     407    if ( !(_hba_status & 0x40000000))
     408        _hba_status = _hba_get_register( HBA_PXIS );
     409
     410    // reset PXIS register
     411    _hba_set_register( HBA_PXIS , 0 );
     412
     413    unsigned int cmd_id;  // cmd index for the loops
     414   
     415    // save the current list of active cmd in a 32 bits word
     416    unsigned int current_active_cmd = 0;
     417    for ( cmd_id = 0 ; cmd_id < 32 ; cmd_id ++ )
     418    {
     419        if ( _hba_active_cmd[cmd_id] == 1 ) current_active_cmd += (1 << cmd_id);
     420    }
     421   
    331422    // get HBA_PXCI containing commands status
    332     unsigned int pxci = _hba_get_register( HBA_PXCI );
    333 
    334     // we must handle all completed commands
    335     // active commands are between  (_hba_cmd_ptr) and (_hba_cmd_ptw-1)
    336     unsigned int current;
    337     for ( current = _hba_cmd_ptr ; current != _hba_cmd_ptw ; current++ )
    338     {
    339         unsigned int ptr = current & 0x1F;
    340        
    341         if ( (pxci & (1<<ptr)) == 0 )    // command completed
     423    unsigned int current_pxci = _hba_get_register( HBA_PXCI );
     424
     425    for ( cmd_id = 0 ; cmd_id < 32 ; cmd_id ++ )
     426    {
     427        if ( ( (current_active_cmd & (1<<cmd_id)) != 0) && // active command
     428             ( (current_pxci & (1<<cmd_id)) == 0 ) )       // completed command
    342429        {
    343             // increment the 32 bits variable _hba_cmd_ptr
    344             _hba_cmd_ptr = (_hba_cmd_ptr + 1);
    345 
    346             // save PXIS register
    347             _hba_status[ptr] = _hba_get_register( HBA_PXIS );
    348 
    349             // reset PXIS register
    350             _hba_set_register( HBA_PXIS , 0 );
    351  
     430            // desactivate the command
     431            _hba_active_cmd[cmd_id] = 0;
     432
    352433            // identify waiting task
    353             unsigned int remote_procid  = _hba_gtid[ptr]>>16;
    354             unsigned int ltid           = _hba_gtid[ptr] & 0xFFFF;
     434            unsigned int remote_procid  = _hba_gtid[cmd_id]>>16;
     435            unsigned int ltid           = _hba_gtid[cmd_id] & 0xFFFF;
    355436            unsigned int remote_cluster = remote_procid >> P_WIDTH;
    356437            unsigned int remote_x       = remote_cluster >> Y_WIDTH;
     
    374455if (_get_proctime() > GIET_DEBUG_IOC_DRIVER)
    375456_printf("\n[DEBUG HBA] _hba_isr() : command %d completed at cycle %d\n"
    376         "  resume task %d running on P[%d,%d,%d] / status = %x\n",
    377         ptr , _get_proctime() ,
    378         ltid , remote_x , remote_y , remote_p , _hba_status[ptr] );
    379 #endif
    380         }
    381         else                         // command non completed
    382         {
    383             break;
     457        "  resume task %d running on P[%d,%d,%d]\n",
     458        cmd_id , _get_proctime() ,
     459        ltid , remote_x , remote_y , remote_p );
     460#endif
    384461        }
    385462    }
Note: See TracChangeset for help on using the changeset viewer.