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:
Subrata Banik 2017-11-13 14:54:37 +05:30 committed by Aaron Durbin
parent 93bbd41ea8
commit 5c08c73dd1
1 changed files with 75 additions and 55 deletions

View File

@ -27,6 +27,8 @@
#include <string.h> #include <string.h>
#include <timer.h> #include <timer.h>
#define MAX_HECI_MESSAGE_RETRY_COUNT 5
/* Wait up to 15 sec for HECI to get ready */ /* Wait up to 15 sec for HECI to get ready */
#define HECI_DELAY_READY (15 * 1000) #define HECI_DELAY_READY (15 * 1000)
/* Wait up to 100 usec between circullar buffer polls */ /* Wait up to 100 usec between circullar buffer polls */
@ -309,45 +311,54 @@ send_one_message(uint32_t hdr, const void *buff)
int int
heci_send(const void *msg, size_t len, uint8_t host_addr, uint8_t client_addr) heci_send(const void *msg, size_t len, uint8_t host_addr, uint8_t client_addr)
{ {
uint8_t retry;
uint32_t csr, hdr; uint32_t csr, hdr;
size_t sent = 0, remaining, cb_size, max_length; size_t sent, remaining, cb_size, max_length;
uint8_t *p = (uint8_t *) msg; const uint8_t *p;
if (!msg || !len) if (!msg || !len)
return 0; return 0;
clear_int(); clear_int();
if (!wait_heci_ready()) { for (retry = 0; retry < MAX_HECI_MESSAGE_RETRY_COUNT; retry++) {
printk(BIOS_ERR, "HECI: not ready\n"); p = msg;
return 0;
}
csr = read_cse_csr(); if (!wait_heci_ready()) {
cb_size = ((csr & CSR_CBD) >> CSR_CBD_START) * SLOT_SIZE; printk(BIOS_ERR, "HECI: not ready\n");
/* continue;
* 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;
/* csr = read_cse_csr();
* Fragment the message into smaller messages not exceeding useful cb_size = ((csr & CSR_CBD) >> CSR_CBD_START) * SLOT_SIZE;
* circullar buffer length. Mark last message complete. /*
*/ * Reserve one slot for the header. Limit max message
do { * length by 9 bits that are available in the header.
hdr = MIN(max_length, remaining) << MEI_HDR_LENGTH_START; */
hdr |= client_addr << MEI_HDR_CSE_ADDR_START; max_length = MIN(cb_size, (1 << MEI_HDR_LENGTH_SIZE) - 1)
hdr |= host_addr << MEI_HDR_HOST_ADDR_START; - SLOT_SIZE;
hdr |= (MIN(max_length, remaining) == remaining) ? 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; MEI_HDR_IS_COMPLETE : 0;
sent = send_one_message(hdr, p); sent = send_one_message(hdr, p);
p += sent; p += sent;
remaining -= sent; remaining -= sent;
} while (remaining > 0 && sent != 0); } while (remaining > 0 && sent != 0);
return remaining == 0; if (!remaining)
return 1;
}
return 0;
} }
static size_t static size_t
@ -383,6 +394,13 @@ recv_one_message(uint32_t *hdr, void *buff, size_t maxlen)
i += SLOT_SIZE; 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; remainder = recv_len % SLOT_SIZE;
if (remainder) { 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) int heci_receive(void *buff, size_t *maxlen)
{ {
uint8_t retry;
size_t left, received; size_t left, received;
uint32_t hdr = 0; uint32_t hdr = 0;
uint8_t *p = buff; uint8_t *p;
if (!buff || !maxlen || !*maxlen) if (!buff || !maxlen || !*maxlen)
return 0; return 0;
left = *maxlen;
clear_int(); clear_int();
if (!wait_heci_ready()) { for (retry = 0; retry < MAX_HECI_MESSAGE_RETRY_COUNT; retry++) {
printk(BIOS_ERR, "HECI: not ready\n"); p = buff;
return 0; 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;
}
} }
return 0;
/*
* 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);
} }
/* /*