soc/intel/common: Add HECI message retry count
Send/Receive HECI message with 5 retry count in order to avoid HECI message failure. TEST=Build and boot eve/soraka/reef/cnl-rvp Change-Id: I76662f8080fe312caa77c83d1660faeee0bdbe7e Signed-off-by: Subrata Banik <subrata.banik@intel.com> Reviewed-on: https://review.coreboot.org/22443 Reviewed-by: Furquan Shaikh <furquan@google.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Aaron Durbin <adurbin@chromium.org>
This commit is contained in:
parent
93bbd41ea8
commit
5c08c73dd1
|
@ -27,6 +27,8 @@
|
|||
#include <string.h>
|
||||
#include <timer.h>
|
||||
|
||||
#define MAX_HECI_MESSAGE_RETRY_COUNT 5
|
||||
|
||||
/* Wait up to 15 sec for HECI to get ready */
|
||||
#define HECI_DELAY_READY (15 * 1000)
|
||||
/* Wait up to 100 usec between circullar buffer polls */
|
||||
|
@ -309,45 +311,54 @@ send_one_message(uint32_t hdr, const void *buff)
|
|||
int
|
||||
heci_send(const void *msg, size_t len, uint8_t host_addr, uint8_t client_addr)
|
||||
{
|
||||
uint8_t retry;
|
||||
uint32_t csr, hdr;
|
||||
size_t sent = 0, remaining, cb_size, max_length;
|
||||
uint8_t *p = (uint8_t *) msg;
|
||||
size_t sent, remaining, cb_size, max_length;
|
||||
const uint8_t *p;
|
||||
|
||||
if (!msg || !len)
|
||||
return 0;
|
||||
|
||||
clear_int();
|
||||
|
||||
if (!wait_heci_ready()) {
|
||||
printk(BIOS_ERR, "HECI: not ready\n");
|
||||
return 0;
|
||||
}
|
||||
for (retry = 0; retry < MAX_HECI_MESSAGE_RETRY_COUNT; retry++) {
|
||||
p = msg;
|
||||
|
||||
csr = read_cse_csr();
|
||||
cb_size = ((csr & CSR_CBD) >> CSR_CBD_START) * SLOT_SIZE;
|
||||
/*
|
||||
* Reserve one slot for the header. Limit max message length by 9
|
||||
* bits that are available in the header.
|
||||
*/
|
||||
max_length = MIN(cb_size, (1 << MEI_HDR_LENGTH_SIZE) - 1) - SLOT_SIZE;
|
||||
remaining = len;
|
||||
if (!wait_heci_ready()) {
|
||||
printk(BIOS_ERR, "HECI: not ready\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fragment the message into smaller messages not exceeding useful
|
||||
* circullar buffer length. Mark last message complete.
|
||||
*/
|
||||
do {
|
||||
hdr = MIN(max_length, remaining) << MEI_HDR_LENGTH_START;
|
||||
hdr |= client_addr << MEI_HDR_CSE_ADDR_START;
|
||||
hdr |= host_addr << MEI_HDR_HOST_ADDR_START;
|
||||
hdr |= (MIN(max_length, remaining) == remaining) ?
|
||||
csr = read_cse_csr();
|
||||
cb_size = ((csr & CSR_CBD) >> CSR_CBD_START) * SLOT_SIZE;
|
||||
/*
|
||||
* Reserve one slot for the header. Limit max message
|
||||
* length by 9 bits that are available in the header.
|
||||
*/
|
||||
max_length = MIN(cb_size, (1 << MEI_HDR_LENGTH_SIZE) - 1)
|
||||
- SLOT_SIZE;
|
||||
remaining = len;
|
||||
|
||||
/*
|
||||
* Fragment the message into smaller messages not exceeding
|
||||
* useful circullar buffer length. Mark last message complete.
|
||||
*/
|
||||
do {
|
||||
hdr = MIN(max_length, remaining)
|
||||
<< MEI_HDR_LENGTH_START;
|
||||
hdr |= client_addr << MEI_HDR_CSE_ADDR_START;
|
||||
hdr |= host_addr << MEI_HDR_HOST_ADDR_START;
|
||||
hdr |= (MIN(max_length, remaining) == remaining) ?
|
||||
MEI_HDR_IS_COMPLETE : 0;
|
||||
sent = send_one_message(hdr, p);
|
||||
p += sent;
|
||||
remaining -= sent;
|
||||
} while (remaining > 0 && sent != 0);
|
||||
sent = send_one_message(hdr, p);
|
||||
p += sent;
|
||||
remaining -= sent;
|
||||
} while (remaining > 0 && sent != 0);
|
||||
|
||||
return remaining == 0;
|
||||
if (!remaining)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t
|
||||
|
@ -383,6 +394,13 @@ recv_one_message(uint32_t *hdr, void *buff, size_t maxlen)
|
|||
i += SLOT_SIZE;
|
||||
}
|
||||
|
||||
/*
|
||||
* If ME is not ready, something went wrong and
|
||||
* we received junk
|
||||
*/
|
||||
if (!cse_ready())
|
||||
return 0;
|
||||
|
||||
remainder = recv_len % SLOT_SIZE;
|
||||
|
||||
if (remainder) {
|
||||
|
@ -395,42 +413,44 @@ recv_one_message(uint32_t *hdr, void *buff, size_t maxlen)
|
|||
|
||||
int heci_receive(void *buff, size_t *maxlen)
|
||||
{
|
||||
uint8_t retry;
|
||||
size_t left, received;
|
||||
uint32_t hdr = 0;
|
||||
uint8_t *p = buff;
|
||||
uint8_t *p;
|
||||
|
||||
if (!buff || !maxlen || !*maxlen)
|
||||
return 0;
|
||||
|
||||
left = *maxlen;
|
||||
|
||||
clear_int();
|
||||
|
||||
if (!wait_heci_ready()) {
|
||||
printk(BIOS_ERR, "HECI: not ready\n");
|
||||
return 0;
|
||||
for (retry = 0; retry < MAX_HECI_MESSAGE_RETRY_COUNT; retry++) {
|
||||
p = buff;
|
||||
left = *maxlen;
|
||||
|
||||
if (!wait_heci_ready()) {
|
||||
printk(BIOS_ERR, "HECI: not ready\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Receive multiple packets until we meet one marked
|
||||
* complete or we run out of space in caller-provided buffer.
|
||||
*/
|
||||
do {
|
||||
received = recv_one_message(&hdr, p, left);
|
||||
left -= received;
|
||||
p += received;
|
||||
/* If we read out everything ping to send more */
|
||||
if (!(hdr & MEI_HDR_IS_COMPLETE) && !cse_filled_slots())
|
||||
host_gen_interrupt();
|
||||
} while (received && !(hdr & MEI_HDR_IS_COMPLETE) && left > 0);
|
||||
|
||||
if ((hdr & MEI_HDR_IS_COMPLETE) && received) {
|
||||
*maxlen = p - (uint8_t *) buff;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Receive multiple packets until we meet one marked complete or we run
|
||||
* out of space in caller-provided buffer.
|
||||
*/
|
||||
do {
|
||||
received = recv_one_message(&hdr, p, left);
|
||||
left -= received;
|
||||
p += received;
|
||||
/* If we read out everything ping to send more */
|
||||
if (!(hdr & MEI_HDR_IS_COMPLETE) && !cse_filled_slots())
|
||||
host_gen_interrupt();
|
||||
} while (received && !(hdr & MEI_HDR_IS_COMPLETE) && left > 0);
|
||||
|
||||
*maxlen = p - (uint8_t *) buff;
|
||||
|
||||
/* If ME is not ready, something went wrong and we received junk */
|
||||
if (!cse_ready())
|
||||
return 0;
|
||||
|
||||
return !!((hdr & MEI_HDR_IS_COMPLETE) && received);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue