Comments (3)
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.
from hostboot.
OK, got it, thanks!
from hostboot.
Related Issues (20)
- What do "Group" and "chip id" mean HOT 1
- How to determine the mapping relationship between physical addresses and storage units in DIMMs HOT 1
- In the p9 error injection trial, it took 20 minutes to generate a system checkstop HOT 3
- Power10 small core cpu checkstop HOT 4
- Can I map the memory to within 128TB HOT 2
- CPU is limited to wofbase frequency HOT 1
- The impact of MCC memory availability on stream performance: HOT 1
- Is the memory stream performance related to Signal integrity HOT 32
- Small core CPU report checkstop error when wof enabled HOT 6
- Does hostboot only read Lid files from running DIR? HOT 1
- About Simics HOT 2
- How can I trigger this function HOT 10
- Hostboot boot fail without inserting TPM card HOT 15
- checkstop: PC timebase Facility HOT 1
- About libconsole.so HOT 3
- Why do different L2 caches react differently to the same data in the "L2 Error Injection Register" after error injection? HOT 5
- About istep16.01 "host_activate_boot_core" HOT 1
- What is the purpose of calling the ”platCreateGardRecord“ function to create Ephemeral gard records for BMC system? HOT 2
- Is there a register on P10 that can directly adjust "write delay values for one of the MEMINTDnnB pins" HOT 2
- About intvect_system_reset_external HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from hostboot.