src/occ_405/gpu/gpu.c
// Function Specification
//
// Name:  task_gpu_sm
//
// Description: GPU State Machine - Called from tick table to manage GPUs
//
// Task Flags: RTL_FLAG_ACTIVE
//
// End Function Specification
Function Specification
Name:  task_gpu_sm

GPU State Machine - Called from tick table to manage GPUs



End Function Specification
Function Specification Name : task_gpu_sm GPU State Machine - Called from tick table to manage GPUs End Function Specification
void task_gpu_sm(struct task *i_self)
{
    bool l_start_next_state = FALSE;
    bool l_next_state = FALSE;
    uint8_t l_gpu_id = 0;
    static bool L_occ_owns_lock = FALSE;
    static bool L_gpu_first_run = TRUE;
    static uint16_t L_numCallsForTempRead = 0;  
    static bool L_read_temp_start_needed = FALSE;  
    static bool L_mem_temp_needed = FALSE;  
    if(G_gpu_monitoring_allowed)
    {
        update_gpu_reset_status();
        if(L_gpu_first_run)
        {
            gpu_ipc_init();
            L_gpu_first_run = FALSE;
        }
        if(!L_read_temp_start_needed)
        {
            L_numCallsForTempRead++;
            if(L_numCallsForTempRead >= GPU_TEMP_READ_1S)
            {
                 L_read_temp_start_needed = TRUE;
                 L_mem_temp_needed = FALSE;  
            }
        }
        if( (L_occ_owns_lock == FALSE) || (G_gpu_state == GPU_STATE_NO_LOCK) )
        {
            L_occ_owns_lock = check_and_update_i2c_lock(GPU_I2C_ENGINE);
            if (L_occ_owns_lock)
            {
                G_gpu_state = GPU_STATE_RESET;
            }
            else
            {
                G_gpu_state = GPU_STATE_NO_LOCK;
            }
        }
        do
        {
           if(l_start_next_state)
           {
               l_next_state = TRUE;
           }
           if(!G_gpu_monitoring_allowed)
           {
              occ_i2c_lock_release(GPU_I2C_ENGINE);
              L_occ_owns_lock = FALSE;
              G_gpu_state = GPU_STATE_NO_LOCK;
           }
           switch(G_gpu_state)
           {
               case GPU_STATE_RESET:
                   if (gpu_reset_sm())
                   {
                      L_numCallsForTempRead = 0;  
                      L_read_temp_start_needed = FALSE;  
                      L_mem_temp_needed = FALSE;  
                      l_gpu_id = get_first_gpu();
                      if(l_gpu_id != 0xFF)
                      {
                          G_current_gpu_id = l_gpu_id;
                          G_gpu_state = GPU_STATE_READ_TEMP;
                          l_start_next_state = TRUE;
                      }
                      else  
                      {
                         occ_i2c_lock_release(GPU_I2C_ENGINE);
                         L_occ_owns_lock = FALSE;
                         G_gpu_state = GPU_STATE_NO_LOCK;
                         G_gpu_monitoring_allowed = FALSE;
                         l_start_next_state = FALSE;
                      }
                   }
                   break;
               case GPU_STATE_READ_TEMP:
                   if(gpu_read_temp_sm())
                   {
                      l_gpu_id = get_next_gpu();
                      if(l_gpu_id == 0xFF)
                      {
                         L_mem_temp_needed = TRUE;
                         G_gpu_state = GPU_STATE_IDLE;
                      }
                      else
                      {
                         G_current_gpu_id = l_gpu_id;
                      }
                      l_start_next_state = TRUE;
                   }
                   break;
               case GPU_STATE_READ_MEMORY_TEMP:
                   if(gpu_read_memory_temp_sm())
                   {
                      l_gpu_id = get_next_mem_temp_capable_gpu();
                      if(l_gpu_id == 0xFF)
                      {
                         G_gpu_state = GPU_STATE_IDLE;
                      }
                      else
                      {
                         G_current_gpu_id = l_gpu_id;
                      }
                      l_start_next_state = TRUE;
                   }
                   break;
               case GPU_STATE_CHECK_MEM_TEMP_CAPABLE:
                   if(gpu_read_mem_temp_capability_sm())
                   {
                      G_gpu_state = GPU_STATE_IDLE;
                      l_start_next_state = TRUE;
                   }
                   break;
               case GPU_STATE_CHECK_DRIVER_LOADED:
                   if(gpu_check_driver_loaded_sm())
                   {
                      G_gpu_state = GPU_STATE_IDLE;
                      l_start_next_state = TRUE;
                   }
                   break;
               case GPU_STATE_READ_PWR_LIMIT:
                   if(gpu_read_pwr_limit_sm())
                   {
                      G_gpu_state = GPU_STATE_IDLE;
                      l_start_next_state = TRUE;
                   }
                   break;
               case GPU_STATE_SET_PWR_LIMIT:
                   if(gpu_set_pwr_limit_sm())
                   {
                      G_gpu_state = GPU_STATE_IDLE;
                      l_start_next_state = TRUE;
                   }
                   break;
               case GPU_STATE_NO_LOCK:
                   l_start_next_state = FALSE;
                   break;
               default:
                   G_gpu_state = GPU_STATE_IDLE;
                   break;
           } 
           if(G_gpu_i2c_reset_required)
           {
               G_gpu_i2c_reset_required = FALSE;
               L_occ_owns_lock = check_and_update_i2c_lock(GPU_I2C_ENGINE);
               if (L_occ_owns_lock)
               {
                   G_gpu_state = GPU_STATE_RESET;
                   l_start_next_state = TRUE;
               }
               else
               {
                   G_gpu_state = GPU_STATE_NO_LOCK;
                   l_start_next_state = FALSE;
               }
               break;
           }
           else if(G_gpu_state == GPU_STATE_IDLE)
           {
               l_start_next_state = gpu_sm_handle_idle_state(L_read_temp_start_needed, L_mem_temp_needed);
               if(l_start_next_state)
               {
                  if(G_gpu_state == GPU_STATE_READ_TEMP)
                  {
                     L_numCallsForTempRead = 0;
                     L_read_temp_start_needed = FALSE; 
                     L_mem_temp_needed = FALSE;  
                  }
                  else if(G_gpu_state == GPU_STATE_READ_MEMORY_TEMP)
                  {
                     L_mem_temp_needed = FALSE;
                  }
               }
           }
        }while((l_start_next_state) && (!l_next_state));
    } 
}
void task_gpu_sm ( struct task * i_self ) { bool l_start_next_state = FALSE ; bool l_next_state = FALSE ; uint8_t l_gpu_id = 0 ; static bool L_occ_owns_lock = FALSE ; static bool L_gpu_first_run = TRUE ; static uint16_t L_numCallsForTempRead = 0 ; static bool L_read_temp_start_needed = FALSE ; static bool L_mem_temp_needed = FALSE ; if ( G_gpu_monitoring_allowed ) { update_gpu_reset_status ( ) ; if ( L_gpu_first_run ) { gpu_ipc_init ( ) ; L_gpu_first_run = FALSE ; } if ( ! L_read_temp_start_needed ) { L_numCallsForTempRead ++ ; if ( L_numCallsForTempRead >= GPU_TEMP_READ_1S ) { L_read_temp_start_needed = TRUE ; L_mem_temp_needed = FALSE ; } } if ( ( L_occ_owns_lock == FALSE ) || ( G_gpu_state == GPU_STATE_NO_LOCK ) ) { L_occ_owns_lock = check_and_update_i2c_lock ( GPU_I2C_ENGINE ) ; if ( L_occ_owns_lock ) { G_gpu_state = GPU_STATE_RESET ; } else { G_gpu_state = GPU_STATE_NO_LOCK ; } } do { if ( l_start_next_state ) { l_next_state = TRUE ; } if ( ! G_gpu_monitoring_allowed ) { occ_i2c_lock_release ( GPU_I2C_ENGINE ) ; L_occ_owns_lock = FALSE ; G_gpu_state = GPU_STATE_NO_LOCK ; } switch ( G_gpu_state ) { case GPU_STATE_RESET : if ( gpu_reset_sm ( ) ) { L_numCallsForTempRead = 0 ; L_read_temp_start_needed = FALSE ; L_mem_temp_needed = FALSE ; l_gpu_id = get_first_gpu ( ) ; if ( l_gpu_id != 0xFF ) { G_current_gpu_id = l_gpu_id ; G_gpu_state = GPU_STATE_READ_TEMP ; l_start_next_state = TRUE ; } else { occ_i2c_lock_release ( GPU_I2C_ENGINE ) ; L_occ_owns_lock = FALSE ; G_gpu_state = GPU_STATE_NO_LOCK ; G_gpu_monitoring_allowed = FALSE ; l_start_next_state = FALSE ; } } break ; case GPU_STATE_READ_TEMP : if ( gpu_read_temp_sm ( ) ) { l_gpu_id = get_next_gpu ( ) ; if ( l_gpu_id == 0xFF ) { L_mem_temp_needed = TRUE ; G_gpu_state = GPU_STATE_IDLE ; } else { G_current_gpu_id = l_gpu_id ; } l_start_next_state = TRUE ; } break ; case GPU_STATE_READ_MEMORY_TEMP : if ( gpu_read_memory_temp_sm ( ) ) { l_gpu_id = get_next_mem_temp_capable_gpu ( ) ; if ( l_gpu_id == 0xFF ) { G_gpu_state = GPU_STATE_IDLE ; } else { G_current_gpu_id = l_gpu_id ; } l_start_next_state = TRUE ; } break ; case GPU_STATE_CHECK_MEM_TEMP_CAPABLE : if ( gpu_read_mem_temp_capability_sm ( ) ) { G_gpu_state = GPU_STATE_IDLE ; l_start_next_state = TRUE ; } break ; case GPU_STATE_CHECK_DRIVER_LOADED : if ( gpu_check_driver_loaded_sm ( ) ) { G_gpu_state = GPU_STATE_IDLE ; l_start_next_state = TRUE ; } break ; case GPU_STATE_READ_PWR_LIMIT : if ( gpu_read_pwr_limit_sm ( ) ) { G_gpu_state = GPU_STATE_IDLE ; l_start_next_state = TRUE ; } break ; case GPU_STATE_SET_PWR_LIMIT : if ( gpu_set_pwr_limit_sm ( ) ) { G_gpu_state = GPU_STATE_IDLE ; l_start_next_state = TRUE ; } break ; case GPU_STATE_NO_LOCK : l_start_next_state = FALSE ; break ; default : G_gpu_state = GPU_STATE_IDLE ; break ; } if ( G_gpu_i2c_reset_required ) { G_gpu_i2c_reset_required = FALSE ; L_occ_owns_lock = check_and_update_i2c_lock ( GPU_I2C_ENGINE ) ; if ( L_occ_owns_lock ) { G_gpu_state = GPU_STATE_RESET ; l_start_next_state = TRUE ; } else { G_gpu_state = GPU_STATE_NO_LOCK ; l_start_next_state = FALSE ; } break ; } else if ( G_gpu_state == GPU_STATE_IDLE ) { l_start_next_state = gpu_sm_handle_idle_state ( L_read_temp_start_needed , L_mem_temp_needed ) ; if ( l_start_next_state ) { if ( G_gpu_state == GPU_STATE_READ_TEMP ) { L_numCallsForTempRead = 0 ; L_read_temp_start_needed = FALSE ; L_mem_temp_needed = FALSE ; } else if ( G_gpu_state == GPU_STATE_READ_MEMORY_TEMP ) { L_mem_temp_needed = FALSE ; } } } } while ( ( l_start_next_state ) && ( ! l_next_state ) ) ; } }
Function Specification
Name:  task_gpu_sm
Function Specification Name : task_gpu_sm
// # of calls since last temp read was started // set to true when it is time to start reading GPU temps // set to true after rading GPU core temp to read GPU memory temp // GPU monitoring is enabled if GPUs are present and will be disabled if no GPUs // are functional or GPU I2C interface is broken // Read and update reset status for all GPUs // Initialize the IPC commands if this is our first run // Check if time to start reading temperatures // GPU temperatures (core and memory) are only used for fan control which happens every 1s // so there is no need to read the GPU temperatures any faster than every 1s // will get set to TRUE when core temp reads finish // make sure OCC owns the lock in order to send commands to the GPU // Check if host gave up the I2C lock // We now own the lock start with reset and init state // Don't own the lock can't do anything this time // Process GPE response for what was scheduled on the last call // and if that state finished schedule GPE job to start next state // This means that this state machine can be ran twice // This is start of 2nd time processing state set next so we don't go thru here a 3rd time // make sure previous action didn't disable GPU monitoring // release I2C lock to the host for this engine and stop monitoring // Call the GPU Reset SM // Reset complete and GPUs are ready for communication // Start first with reading core temp of first functional GPU // to track start of next temp reading in 1s // start is no longer needed // will get set to TRUE when core temp reads finish // Read core temp for this GPU // no functional GPUs // release I2C lock to the host for this engine and stop monitoring // Call the read core GPU temperature SM for the current GPU being processed // Temp read complete for this GPU, move to next GPU // or memory temps if all GPU core temps were read // Done reading core temps, now read GPU memory temps // set state to IDLE first to check if a higher priority // action is needed before starting to read memory temps // Stay in temperature read state and read temp for next GPU // Call the read GPU memory temperature SM for the current GPU being processed // Temp read complete for this GPU, move to next GPU // or idle if all GPU memory temps were read // Done reading memory temps // Stay in memory read state and read memory temp for next GPU // Check if current GPU has memory temperature capability // Capability check complete for this GPU, go to IDLE state // to let IDLE SM decide what to do next // Check if driver is loaded for current GPU // Driver check complete for this GPU, // NOTE: Do not set status.checkDriverLoaded to false here, if driver is // not loaded we need to keep checking for driver to be loaded this is decided // inside gpu_check_driver_loaded_sm() // go to IDLE state to let IDLE SM decide what to do next // Read power limits for current GPU // Read power limits complete for this GPU, go to IDLE state // to let IDLE SM decide what to do next // Set power limit on current GPU // Set power limit complete for this GPU, go to IDLE state // to let IDLE SM decide what to do next // Host owns the I2C engine.  Need to wait until we get the lock // Nothing happened on last call // switch G_gpu_state // check if the previous action requires a reset // before starting the reset check if OPAL needs the lock // We still own the lock start the reset // We don't own the lock, the reset will happen when we get the lock back // time to decide what to do next // new state to read core temp reset temperature reading timer // start no longer needed // will get set to TRUE when core temp reads finish // new state to start reading memory temps, reset mem temp needed // GPU monitoring enabled