Coder Social home page Coder Social logo

Comments (3)

crgeddes avatar crgeddes commented on August 16, 2024 1

No, we probably should not enable TX if the BMC is reporting that it is not active. Really we should be returning a bad RC back out to the caller of mctp_register_bus and triggering a shutdown or retry in this case.

Up until this point, as the BMC is the one who triggers the host to boot, we have assumed that the BMC is ready.

Here is a rough call stack of the MCTP initialization flow as an FYI :

First, the module gets loaded

96  #if defined(CONFIG_MCTP) || defined(CONFIG_MCTP_TESTCASES)
97          /**
98           * @brief   libmctp
99           */
100          {
101                  "libmctp.so" ,                      // taskname
102                  NULL,                               // no pointer to fn
103                  {
104                          START_TASK,
105                          BASE_IMAGE,                  // Base Module
106                  }
107          },
108  #endif

513  // Set the function that will be called when mctp.so is loaded
514  TASK_ENTRY_MACRO( MctpRP::init );



449  void MctpRP::init(errlHndl_t& o_errl)
450  {
451      // This will call the MctpRP construction which initializes MCTP
452      // polling loops
453      return Singleton<MctpRP>::instance()._init();;
454  }
455  

474  void MctpRP::_init(void)
475  {
476      TRACFCOMP(g_trac_mctp, "MctpRP::_init entry");
477  
478      msg_q_register(iv_inboundMsgQ, VFS_ROOT_MSG_MCTP_IN);
479      msg_q_register(iv_outboundMsgQ, VFS_ROOT_MSG_MCTP_OUT);
480  
481      // Get the virtual address for the LPC bar and add the offsets
482      // to the MCTP/PLDM space within  the FW Space of the LPC window.
483      auto l_bar = LPC::get_lpc_virtual_bar() +
484                          LPC::LPCHC_FW_SPACE +
485                          LPC::LPCHC_MCTP_PLDM_BASE;
486  
487      // Initialize the host-lpc binding for hostboot
488      iv_hostlpc = mctp_hostlpc_init_hostboot(l_bar);
489  
490      // Start cmd daemon first because we want it ready if poll daemon finds
491      // something right away
492      task_create(handle_outbound_messages_task, NULL);
493  
494      // Set the receive function to be rx_message which
495      // will handle the message in the RX space accordingly
496      mctp_set_rx_all(iv_mctp, rx_message, NULL);
497  
498      TRACFCOMP(g_trac_mctp, "MctpRP::_init exit");
499      return;
500  }

249  
250  // Public interface used to trigger the initialization of the hostlpc
251  // mctp binding
252  struct mctp_binding_hostlpc *mctp_hostlpc_init_hostboot(uint64_t i_mctpVaddr)
253  {
254    struct mctp_binding_hostlpc *hostlpc;
255  
256    hostlpc = __mctp_hostlpc_init();
257    if (!hostlpc)
258      return NULL;
259  
260    /* Set internal operations for kcs and lpc */
261    hostlpc->ops.kcs_read  = __mctp_hostlpc_hostboot_kcs_read;
262    hostlpc->ops.kcs_write = __mctp_hostlpc_hostboot_kcs_write;
263    hostlpc->ops.lpc_read  = __mctp_hostlpc_hostboot_lpc_read;
264    hostlpc->ops.lpc_write = __mctp_hostlpc_hostboot_lpc_write;
265    hostlpc->ops.nanosleep = __mctp_hostlpc_hostboot_nanosleep;
266    hostlpc->ops_data = hostlpc;
267  
268    // Set LPC map pointer to Hostboot's Virtual Address of
269    // the MCTP section in the LPC space
270    hostlpc->lpc_map = (void *)(i_mctpVaddr);
271  
272    return hostlpc;
273  }


226  /* allocate and basic initialisation */
227  static struct mctp_binding_hostlpc *__mctp_hostlpc_init(void)
228  {
229      struct mctp_binding_hostlpc *hostlpc;
230  
231      hostlpc = __mctp_alloc(sizeof(*hostlpc));
232      memset(hostlpc, 0, sizeof(*hostlpc));
233      hostlpc->binding.name = "hostlpc";
234      hostlpc->binding.version = HOST_VER_CUR;
235      hostlpc->binding.tx = mctp_binding_hostlpc_tx;
236      hostlpc->binding.start = mctp_binding_hostlpc_start_hb;
237      hostlpc->binding.pkt_size = MCTP_BMTU;
238      hostlpc->binding.pkt_pad = 0;
239      hostlpc->lpc_map = NULL;
240  
241      return hostlpc;
242  }
243  


/// end of MCTP module load


// Then in PLDM base module load ...

59      // Notify MCTP layer that they can register the bus
60      // and start MCTP traffic
61      MCTP::register_mctp_bus();


457  void MctpRP::register_mctp_bus(void)
458  {
459  
460      // Register the binding to the LPC bus we are using for this
461      // MCTP configuration. NOTE this will trigger the "start" function
462      // associated with the iv_hostlpc binding which starts the
463      // KCS init handshake with the BMC
464      mctp_register_bus(iv_mctp, &iv_hostlpc->binding, HOST_EID);
465  
466      // Start the poll kcs status daemon which will read the KCS status reg
467      // every 1 ms and if we see that the OBF bit in the KCS status register is
468      // set we will read the OBR KCS data reg and send a message to the
469      // handle_obf_status daemon
470      task_create(poll_kcs_status_task, NULL);
471      return;
472  }


288  int mctp_register_bus(struct mctp *mctp,
289      struct mctp_binding *binding,
290      mctp_eid_t eid)
291  {
292    /* todo: multiple busses */
293    assert(mctp->n_busses == 0);
294    mctp->n_busses = 1;
295    mctp->busses = __mctp_alloc(sizeof(struct mctp_bus));
296    memset(mctp->busses, 0, sizeof(struct mctp_bus));
297    mctp->busses[0].binding = binding;
298    mctp->busses[0].eid = eid;
299    binding->bus = &mctp->busses[0];
300    binding->mctp = mctp;
301    mctp->route_policy = ROUTE_ENDPOINT;
302  
303    if (binding->start)
304      binding->start(binding);
305  
306    return 0;
307  }


217  // Wrapper for mctp_hostlpc_init_hb, see comments for that func
218  static int mctp_binding_hostlpc_start_hb(struct mctp_binding *b)
219  {
220      struct mctp_binding_hostlpc *hostlpc = container_of(b,
221          struct mctp_binding_hostlpc, binding);
222  
223      return mctp_hostlpc_init_hb(hostlpc);
224  }


184  static int mctp_hostlpc_init_hb(struct mctp_binding_hostlpc *hostlpc)
185  {
186      int rc = 0;
187      uint8_t l_data;
188  
189      rc = hostlpc->ops.kcs_read(hostlpc->ops_data,
190                                  MCTP_LPC_KCS_REG_STATUS,
191                                  &l_data);
192  
193      if( (l_data & KCS_STATUS_BMC_READY) && rc == 0)
194      {
195          struct mctp_lpcmap_hdr *hdr = hostlpc->lpc_hdr;
196  
197          // check if mtu negotiation is supported
198          if(hdr->bmc_ver_cur >= 2)
199          {
200              hdr->rx_size = HOST_DESIRED_MTU;
201          }
202          hdr->host_ver_min = htobe16(HOST_VER_MIN);
203          hdr->host_ver_cur = htobe16(HOST_VER_CUR);
204          mctp_hostlpc_kcs_send(hostlpc, KCS_INIT);
205      }
206      else
207      {
208          mctp_prwarn("bmc is not setup");
209      }
210  
211      // initialize the tx space to say the host is ready to use it
212      mctp_binding_set_tx_enabled(&hostlpc->binding, true);
213  
214      return rc;
215  }



101  void MctpRP::poll_kcs_status(void)
102  {
103      task_detach();
104      errlHndl_t l_errl = nullptr;
105      msg_t* msg = nullptr;
106      uint8_t l_status = 0;
107      size_t l_size = sizeof(uint8_t);
108  
109      while(1)
110      {
111          // Perform an LPC read on the KCS status register to see if the BMC has
112          // sent the Host a message. We know that the BMC has sent a message if
113          // the OBF bit in the status reg is set.
114          l_errl =
115              DeviceFW::deviceRead(
116                              TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
117                              &l_status,
118                              l_size,
119                              DEVICE_LPC_ADDRESS(LPC::TRANS_IO,
120                                                 LPC::KCS_STATUS_REG));
121          // If there was an error reading the status reg then something is wrong
122          // and we should exit
123          if(l_errl)
124          {
125              // TODO RTC: 249716
126              // Do something.. ? fail ? retry ?
127              errlCommit(l_errl, MCTP_COMP_ID);
128              break;
129          }
130  
131          // If we found that the OBF bit is not set then wait 1 ms and try
132          // poll again
133          if(!(l_status & KCS_STATUS_OBF))
134          {
135              nanosleep(0,1 * NS_PER_MSEC);
136              continue;
137          }
138  
139          // otherwise read the ODR and send a message to the mctp_cmd_daemon
140          // when the host reads this register it will clear the OBF bit in the
141          // status register
142          l_errl =
143              DeviceFW::deviceRead(
144                              TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
145                              &l_status,
146                              l_size,
147                              DEVICE_LPC_ADDRESS(LPC::TRANS_IO,
148                                                 LPC::KCS_DATA_REG));
149  
150          if(l_errl)
151          {
152              // TODO RTC: 249716
153              // Do something.. ? fail ? retry ?
154              errlCommit(l_errl, MCTP_COMP_ID);
155              break;
156          }
157  
158          switch(l_status)
159          {
160            case MSG_INIT:
161                TRACFCOMP(g_trac_mctp,
162                          "Found kcs msg type: MCTP::MSG_INIT which we do not support, ignoring it",
163                          msg->type);
164                break;
165            case MSG_TX_BEGIN:
166                TRACDCOMP(g_trac_mctp, "BMC has sent us a message we need to read");
167                mctp_hostlpc_rx_start(iv_hostlpc);
168                break;
169            case MSG_RX_COMPLETE:
170                // BMC has completed receiving the message we sent
171                TRACDCOMP(g_trac_mctp, "BMC says they are complete reading what we sent");
172                lock_and_mctp_hostlpc_tx_complete(iv_hostlpc, iv_mctp_mutex);
173                break;
174            case MSG_DUMMY:
175  
176                // The BMC will send us this message after writing the status
177                // register during the initization sequence to notify us they
178                // have filled out info in the config section of the lpc space
179                // and has activated the KCS interface
180                l_errl = this->_mctp_channel_init();
181  
182                if(l_errl)
183                {
184                    uint32_t l_fatalEid = l_errl->eid();
185                    errlCommit(l_errl, MCTP_COMP_ID);
186  #ifdef CONFIG_CONSOLE
187                    CONSOLE::displayf(NULL,
188                                      "MCTP initialization failed! The commited error log 0x%X will be in hostboot dump but will not make it to BMC",
189                                      l_fatalEid);
190  #endif
191  
192                    // 2nd param "true" indicates we want to the call the
193                    // function to trigger a shutdown in a separate thread.
194                    // This allows us to register for and handle shutdown events
195                    // in this thread.
196                    INITSERVICE::doShutdown(l_fatalEid, true);
197                }
198                break;
199            default:
200                // Just leave a trace and move on with our life
201                TRACFCOMP(g_trac_mctp,
202                          "Found invalid kcs msg type: 0x%.02x, ignoring it",
203                          msg->type);
204                break;
205          }
206      }
207  }



373  errlHndl_t MctpRP::_mctp_channel_init(void)
374  {
375      errlHndl_t l_errl = nullptr;
376  do
377  {
378      uint8_t l_status = 0;
379      size_t l_size = sizeof(uint8_t);
380      // Perform an LPC read on the KCS status register to verify the channel is
381      // active and that the BMC has written the negotiated MCTP version
382      l_errl = DeviceFW::deviceRead(
383                                TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
384                                &l_status,
385                                l_size,
386                                DEVICE_LPC_ADDRESS(LPC::TRANS_IO,
387                                                   LPC::KCS_STATUS_REG));
388  
389      if(l_errl)
390      {
391          break;
392      }
393  
394      // Verify that the channel is active
395      if(iv_channelActive && !(l_status & KCS_STATUS_CHANNEL_ACTIVE))
396      {
397          TRACFCOMP(g_trac_mctp,
398                    "_mctp_channel_init: Error ! KCS status reports channel as inactive when HB thinks its active!" );
399          /*@errorlog
400          * @errortype       ERRL_SEV_UNRECOVERABLE
401          * @moduleid        MOD_MCTP_CHANNEL_INIT
402          * @reasoncode      RC_CHANNEL_INACTIVE
403          * @userdata1       kcs status register value
404          * @userdata2       mctp version
405          *                  (should not have been set but might be useful)
406          *
407          * @devdesc         Initialization of MCTP protocol between Host and
408          *                  BMC failed
409          * @custdesc        A problem occurred during the IPL of the system
410          *
411          */
412          l_errl = new ErrlEntry(ERRL_SEV_UNRECOVERABLE, // severity
413                                 MOD_MCTP_CHANNEL_INIT,   // moduleid
414                                 RC_CHANNEL_INACTIVE,    // reason code
415                                 l_status, // KCS status register value
416                                 iv_hostlpc->lpc_hdr->negotiated_ver, // version
417                                 ErrlEntry::ADD_SW_CALLOUT);
418      }
419      else if(!iv_channelActive && (l_status & KCS_STATUS_CHANNEL_ACTIVE))
420      {
421          iv_channelActive = true;
422          // Read the negotiated version from the lpcmap hdr that the bmc should
423          // have set prior to setting the KCS_STATUS_CHANNEL_ACTIVE bit
424          iv_mctpVersion = iv_hostlpc->lpc_hdr->negotiated_ver;
425          TRACFCOMP(g_trac_mctp,
426                    "_mctp_channel_init: Negotiated version is : %d",
427                    iv_mctpVersion);
428  
429          if(iv_hostlpc->lpc_hdr->negotiated_ver >= 2)
430          {
431              TRACFCOMP(g_trac_mctp,
432                    "_mctp_channel_init: Setting packet size to be %ld",
433                        iv_hostlpc->lpc_hdr->rx_size );
434              iv_hostlpc->binding.pkt_size = iv_hostlpc->lpc_hdr->rx_size;
435          }
436          printk("MCTP Version : %d    packet size : %d \n",
437                 iv_hostlpc->lpc_hdr->negotiated_ver,
438                 iv_hostlpc->binding.pkt_size);
439  
440      }
441  
442      //else if none of the conditions above are met, the DUMMY_COMMAND is a no op
443  
444  }while(0);
445  
446    return l_errl;
447  }

from hostboot.

dcrowell77 avatar dcrowell77 commented on August 16, 2024

@crgeddes ?

from hostboot.

Grubby0624 avatar Grubby0624 commented on August 16, 2024

OK, got it, thanks!

from hostboot.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.