common/util/hal_snoop.c (194 lines of code) (raw):
#include <zephyr.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/printk.h>
#include <device.h>
#include <drivers/misc/aspeed/snoop_aspeed.h>
#include "hal_snoop.h"
#include "plat_func.h"
#include "ipmi.h"
const struct device *snoop_dev;
uint8_t *snoop_data;
static uint8_t *snoop_read_buffer;
int snoop_read_num = 0;
int send_postcode_start_position = 0;
static bool proc_postcode_ok = false;
K_THREAD_STACK_DEFINE(snoop_thread, SNOOP_STACK_SIZE);
struct k_thread snoop_thread_handler;
k_tid_t snoop_tid;
K_THREAD_STACK_DEFINE(send_postcode_thread, SENDPOSTCODE_STACK_SIZE);
struct k_thread send_postcode_thread_handler;
k_tid_t send_postcode_tid;
struct k_mutex snoop_mutex;
void snoop_init()
{
snoop_dev = device_get_binding(DT_LABEL(DT_NODELABEL(snoop)));
if (!snoop_dev) {
printk("No snoop device found\n");
return;
}
return;
}
void copy_snoop_read_buffer(uint8_t offset, int size_num, uint8_t *buffer, uint8_t copy_mode)
{
if (size_num > SNOOP_MAX_LEN) {
printk("copy snoop buffer size exceeded\n");
return;
}
if (!k_mutex_lock(&snoop_mutex, K_MSEC(1000))) {
if (copy_mode == copy_all_postcode) {
memcpy(&buffer[0], &snoop_read_buffer[offset], size_num - offset);
memcpy(&buffer[size_num - offset], &snoop_read_buffer[0], offset);
} else {
if (offset + size_num > SNOOP_MAX_LEN) {
memcpy(&buffer[0], &snoop_read_buffer[offset],
SNOOP_MAX_LEN - offset);
memcpy(&buffer[SNOOP_MAX_LEN - offset], &snoop_read_buffer[0],
size_num - (SNOOP_MAX_LEN - offset));
} else {
memcpy(&buffer[0], &snoop_read_buffer[offset], size_num);
}
}
} else {
printk("copy snoop buffer lock fail\n");
}
if (k_mutex_unlock(&snoop_mutex)) {
printk("copy snoop buffer unlock fail\n");
}
}
bool get_postcode_ok()
{
return proc_postcode_ok;
}
void reset_postcode_ok()
{
proc_postcode_ok = false;
}
void snoop_read()
{
int rc;
if (snoop_read_buffer == NULL) {
snoop_read_buffer = malloc(sizeof(uint8_t) * SNOOP_MAX_LEN);
}
if (snoop_read_buffer == NULL) {
printk("snoop read buffer alloc fail\n");
return;
}
while (1) {
rc = snoop_aspeed_read(snoop_dev, 0, snoop_data, true);
if (rc == 0) {
proc_postcode_ok = true;
if (!k_mutex_lock(&snoop_mutex, K_MSEC(1000))) {
snoop_read_buffer[snoop_read_num % SNOOP_MAX_LEN] = *snoop_data;
snoop_read_num++;
} else {
printk("snoop read lock fail\n");
}
if (k_mutex_unlock(&snoop_mutex)) {
printk("snoop read unlock fail\n");
}
}
}
}
void init_snoop_thread()
{
snoop_init();
snoop_read_num = 0;
if (snoop_tid != NULL && strcmp(k_thread_state_str(snoop_tid), "dead") != 0) {
return;
}
snoop_tid = k_thread_create(&snoop_thread_handler, snoop_thread,
K_THREAD_STACK_SIZEOF(snoop_thread), snoop_read, NULL, NULL,
NULL, CONFIG_MAIN_THREAD_PRIORITY, 0, K_NO_WAIT);
k_thread_name_set(&snoop_thread_handler, "snoop_thread");
}
void abort_snoop_thread()
{
if (snoop_tid != NULL && strcmp(k_thread_state_str(snoop_tid), "dead") != 0) {
k_thread_abort(snoop_tid);
}
}
void send_post_code_to_BMC()
{
int send_postcode_end_position;
ipmi_msg *send_postcode_msg;
ipmb_error status;
while (1) {
k_msleep(100); // send post code to BMC once 100 ms
send_postcode_end_position = snoop_read_num;
if (get_DC_status() == 0) {
return;
}
if (send_postcode_start_position != send_postcode_end_position) {
send_postcode_msg = (ipmi_msg *)malloc(sizeof(ipmi_msg));
static uint8_t alloc_sendmsg_retry = 0;
if (send_postcode_msg == NULL) {
if (get_post_status()) {
alloc_sendmsg_retry += 1;
if (alloc_sendmsg_retry > 3) {
printk("post complete and send post code thread alloc fail three times continuously\n");
return;
} else {
continue;
}
} else {
printk("send post code thread alloc fail\n");
continue;
}
}
alloc_sendmsg_retry = 0;
if (send_postcode_end_position - send_postcode_start_position >
SNOOP_MAX_LEN) {
send_postcode_end_position =
send_postcode_start_position + SNOOP_MAX_LEN;
}
memset(send_postcode_msg, 0, sizeof(ipmi_msg));
send_postcode_msg->InF_source = Self_IFs;
send_postcode_msg->InF_target = BMC_IPMB_IFs;
send_postcode_msg->netfn = NETFN_OEM_1S_REQ;
send_postcode_msg->cmd = CMD_OEM_1S_SEND_POST_CODE_TO_BMC;
send_postcode_msg->data_len =
send_postcode_end_position - send_postcode_start_position + 4;
send_postcode_msg->data[0] = WW_IANA_ID & 0xFF;
send_postcode_msg->data[1] = (WW_IANA_ID >> 8) & 0xFF;
send_postcode_msg->data[2] = (WW_IANA_ID >> 16) & 0xFF;
send_postcode_msg->data[3] =
send_postcode_end_position - send_postcode_start_position;
copy_snoop_read_buffer(send_postcode_start_position % SNOOP_MAX_LEN,
send_postcode_msg->data[3],
&send_postcode_msg->data[4], copy_specific_postcode);
status = ipmb_read(send_postcode_msg,
IPMB_inf_index_map[send_postcode_msg->InF_target]);
if (send_postcode_msg != NULL) {
free(send_postcode_msg);
}
if (status == ipmb_error_failure) {
printf("Fail to post msg to txqueue for send post code from %d to %d\n",
send_postcode_start_position, send_postcode_end_position);
continue;
} else if (status == ipmb_error_get_messageQueue) {
printf("No response from bmc for send post code\n");
continue;
}
send_postcode_start_position = send_postcode_end_position;
} else {
if (CPU_power_good() == false) {
return;
}
}
}
}
void init_send_postcode_thread()
{
send_postcode_start_position = 0;
if (send_postcode_tid != NULL &&
strcmp(k_thread_state_str(send_postcode_tid), "dead") != 0) {
return;
}
send_postcode_tid =
k_thread_create(&send_postcode_thread_handler, send_postcode_thread,
K_THREAD_STACK_SIZEOF(send_postcode_thread), send_post_code_to_BMC,
NULL, NULL, NULL, CONFIG_MAIN_THREAD_PRIORITY, 0, K_NO_WAIT);
k_thread_name_set(&send_postcode_thread_handler, "send_postcode_thread");
}