in common/ipmi/ipmb.c [249:490]
void IPMB_TXTask(void *pvParameters, void *arvg0, void *arvg1)
{
struct ipmi_msg_cfg *current_msg_tx;
IPMB_config ipmb_cfg;
I2C_MSG *msg;
uint8_t ipmb_buffer_tx[IPMI_MSG_MAX_LENGTH + IPMB_RESP_HEADER_LENGTH], status = 0,
retry = 5;
memcpy(&ipmb_cfg, (IPMB_config *)pvParameters, sizeof(IPMB_config));
while (1) {
current_msg_tx = (struct ipmi_msg_cfg *)malloc(sizeof(struct ipmi_msg_cfg));
if (current_msg_tx == NULL) { // allocate memory fail, retry later
k_msleep(10);
continue;
}
k_msgq_get(&ipmb_txqueue[ipmb_cfg.index], (ipmi_msg_cfg *)current_msg_tx,
K_FOREVER); // Wait for OS queue send interrupt
if (IS_RESPONSE(current_msg_tx->buffer)) {
/* We're sending a response */
/**********************************/
/* Error checking */
/**********************************/
/* See if we've already tried sending this message 3 times */
if (current_msg_tx->retries > IPMB_MAX_RETRIES) {
/* Free the message buffer */
printf("IPMB IF %x write reach MAX retry\n",
current_msg_tx->buffer.InF_source);
if (current_msg_tx != NULL) {
free(current_msg_tx);
}
continue;
}
/**********************************/
/* Try sending the message */
/**********************************/
/* Fix IPMB target address */
current_msg_tx->buffer.dest_addr = ipmb_cfg.target_addr;
/* Encode the message buffer to the IPMB format */
ipmb_encode(&ipmb_buffer_tx[0], ¤t_msg_tx->buffer);
uint8_t resp_tx_size =
current_msg_tx->buffer.data_len + IPMB_RESP_HEADER_LENGTH;
if (ipmb_cfg.Inf == I2C_IF) {
msg = malloc(sizeof(I2C_MSG));
if (msg == NULL) { // allocate fail, retry allocate
k_msleep(10);
msg = malloc(sizeof(I2C_MSG));
if (msg == NULL) {
printk("IPMB_TXTask: Fail to malloc for i2c resp msg\n");
if (current_msg_tx != NULL) {
free(current_msg_tx);
}
continue;
}
}
msg->bus = ipmb_cfg.bus;
msg->slave_addr = ipmb_cfg.target_addr;
msg->tx_len = resp_tx_size;
memcpy(&msg->data[0], &ipmb_buffer_tx[1], resp_tx_size);
status = i2c_master_write(msg, retry);
if (msg != NULL) {
free(msg);
}
} else { // TODO: else if (ipmb_cfg.Inf == I3C_IF)
printf("IPMB %d using not support interface: %x\n", ipmb_cfg.index,
ipmb_cfg.Inf);
if (current_msg_tx != NULL) {
free(current_msg_tx);
}
continue;
}
if (status) {
/* Message couldn't be transmitted right now, increase retry counter and try again later */
current_msg_tx->retries++;
k_msgq_put(&ipmb_txqueue[ipmb_cfg.index], current_msg_tx,
K_NO_WAIT);
k_msleep(IPMB_RETRY_DELAY_ms);
} else {
/* Success case*/
/* Free the message buffer */
if (DEBUG_IPMI) {
printf("ipmb_txqueue[%x] resp netfn: %x, cmd: %x, CC: %x, target_addr: %x\n",
ipmb_cfg.index, current_msg_tx->buffer.netfn,
current_msg_tx->buffer.cmd,
current_msg_tx->buffer.completion_code,
ipmb_cfg.target_addr);
for (int i = 0; i < resp_tx_size + 1; i++) {
printf(" %x", ipmb_buffer_tx[i]);
}
printf("\n");
}
}
} else {
/***************************************/
/* Sending new outgoing request */
/***************************************/
ipmb_encode(&ipmb_buffer_tx[0], ¤t_msg_tx->buffer);
uint8_t req_tx_size =
current_msg_tx->buffer.data_len + IPMB_REQ_HEADER_LENGTH;
if (DEBUG_IPMI) {
uint8_t i;
printf("Tx send req: ");
for (i = 0; i < req_tx_size + 1; i++) {
printf(" %x", ipmb_buffer_tx[i]);
}
printf("\n");
}
if (ipmb_cfg.Inf == I2C_IF) {
msg = malloc(sizeof(I2C_MSG));
if (msg == NULL) { // allocate fail, retry allocate
k_msleep(10);
msg = malloc(sizeof(I2C_MSG));
if (msg == NULL) {
printk("IPMB_TXTask: Fail to malloc for i2c req msg\n");
if (current_msg_tx != NULL) {
free(current_msg_tx);
}
continue;
}
}
msg->bus = ipmb_cfg.bus;
msg->slave_addr = ipmb_cfg.target_addr;
msg->tx_len = req_tx_size;
memcpy(&msg->data[0], &ipmb_buffer_tx[1], req_tx_size);
status = i2c_master_write(msg, retry);
if (msg != NULL) {
free(msg);
}
} else { // TODO: else if (ipmb_cfg.Inf == I3C_IF)
printf("IPMB %d using not support interface: %x\n", ipmb_cfg.index,
ipmb_cfg.Inf);
if (current_msg_tx != NULL) {
free(current_msg_tx);
}
continue;
}
if (status) {
current_msg_tx->retries += 1;
if (current_msg_tx->retries > IPMB_MAX_RETRIES) {
/* Return fail status to request source */
if (current_msg_tx->buffer.InF_source == Reserve_IFs) {
printf("IPMB_TXTask: Bridging msg from reserve IFs\n");
} else if (current_msg_tx->buffer.InF_source == Self_IFs) {
printf("IPMB_TXTask: BIC sending command fail\n"); // Rain - Should record or notice command fail
#ifdef CONFIG_IPMI_KCS_ASPEED
} else if (current_msg_tx->buffer.InF_source ==
HOST_KCS_IFs) {
uint8_t *kcs_buff;
kcs_buff = malloc(KCS_buff_size * sizeof(uint8_t));
if (kcs_buff ==
NULL) { // allocate fail, retry allocate
k_msleep(10);
kcs_buff = malloc(KCS_buff_size *
sizeof(uint8_t));
if (kcs_buff == NULL) {
printk("IPMB_TXTask: Fail to malloc for kcs_buff\n");
free(current_msg_tx);
continue;
}
}
current_msg_tx->buffer.completion_code =
CC_CAN_NOT_RESPOND;
kcs_buff[0] = current_msg_tx->buffer.netfn << 2;
kcs_buff[1] = current_msg_tx->buffer.cmd;
kcs_buff[2] =
current_msg_tx->buffer.completion_code;
if (current_msg_tx->buffer.data_len > 0) {
memcpy(&kcs_buff[3],
¤t_msg_tx->buffer.data[0],
current_msg_tx->buffer.data_len);
}
kcs_write(kcs_buff,
current_msg_tx->buffer.data_len +
3); // data len + netfn + cmd + cc
if (kcs_buff != NULL) {
free(kcs_buff);
}
#endif
} else {
ipmb_error status;
current_msg_tx->buffer.data_len = 0;
current_msg_tx->buffer.netfn = NETFN_OEM_1S_REQ;
current_msg_tx->buffer.cmd = CMD_OEM_1S_MSG_OUT;
current_msg_tx->buffer.completion_code =
CC_NODE_BUSY;
status = ipmb_send_response(
¤t_msg_tx->buffer,
IPMB_inf_index_map[current_msg_tx->buffer
.InF_source]);
if (status != ipmb_error_success) {
printf("IPMB_TXTask: Send IPMB req fail status: %x",
status);
}
}
/* Free the message buffer */
printf("IPMB send fail after retry %d times, source: %x, cmd: 0x%x 0x%x\n",
current_msg_tx->retries,
current_msg_tx->buffer.InF_source,
current_msg_tx->buffer.netfn,
current_msg_tx->buffer.cmd);
} else {
k_msgq_put(&ipmb_txqueue[ipmb_cfg.index], current_msg_tx,
K_NO_WAIT);
k_msleep(IPMB_RETRY_DELAY_ms);
}
} else {
/* Request was successfully sent, keep a copy here for future comparison and clean the last used buffer */
// void insert_node(ipmi_msg_cfg *pnode, ipmi_msg *msg)
current_msg_tx->buffer.seq_target = current_msg_tx->buffer.seq;
insert_node(P_start[ipmb_cfg.index], ¤t_msg_tx->buffer,
ipmb_cfg.index);
if (DEBUG_IPMI) {
printf("Insert node[%x] seq_s: %x, seq_t: %x\n",
ipmb_cfg.Inf_source,
current_msg_tx->buffer.seq_source,
current_msg_tx->buffer.seq_target);
}
}
}
if (current_msg_tx != NULL) {
free(current_msg_tx);
}
k_msleep(10);
}
}