[Skiboot] [PATCH 5/5] hw/bt: Ask the BMC for its BT interface capabilities

Alistair Popple alistair at popple.id.au
Thu Oct 29 12:32:28 AEDT 2015


Question below, but otherwise:

Acked-by: Alistair Popple <alistair at popple.id.au>

On Thu, 29 Oct 2015 11:24:09 Cyril Bur wrote:
> Signed-off-by: Cyril Bur <cyril.bur at au1.ibm.com>
> ---
>  hw/bt.c        | 87 
++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
>  include/ipmi.h |  1 +
>  2 files changed, 85 insertions(+), 3 deletions(-)
> 
> diff --git a/hw/bt.c b/hw/bt.c
> index 1185412..e3b16d8 100644
> --- a/hw/bt.c
> +++ b/hw/bt.c
> @@ -22,6 +22,7 @@
>  #include <ipmi.h>
>  #include <bt.h>
>  #include <timer.h>
> +#include <ipmi.h>
>  
>  /* BT registers */
>  #define BT_CTRL			0
> @@ -108,6 +109,14 @@ struct bt_msg {
>  	struct ipmi_msg ipmi_msg;
>  };
>  
> +struct bt_caps {
> +	uint8_t num_requests;
> +	uint8_t input_buf_len;
> +	uint8_t output_buf_len;
> +	uint8_t msg_timeout;
> +	uint8_t num_retries;
> +};
> +
>  struct bt {
>  	uint32_t base_addr;
>  	struct lock lock;
> @@ -115,7 +124,9 @@ struct bt {
>  	struct timer poller;
>  	bool irq_ok;
>  	int queue_len;
> +	struct bt_caps caps;
>  };
> +
>  static struct bt bt;
>  
>  static int ipmi_seq;
> @@ -146,6 +157,66 @@ static inline void bt_assert_h_busy(void)
>  	assert(rval & BT_CTRL_H_BUSY);
>  }
>  
> +static void get_bt_caps_complete(struct ipmi_msg *msg)
> +{
> +	/* Ignore errors, we'll fallback to using the defaults, no big deal */
> +
> +	if (msg->data[0] == 0) {
> +		prerror("Got illegal BMC BT capability\n");
> +		goto out;
> +	}
> +
> +	if (msg->data[3] + 1 != BT_FIFO_LEN) {
> +		prerror("Got a input buffer len (%d) cap which differs from 
the default\n",
> +				msg->data[3]);
> +		goto out;
> +	}
> +
> +	if (msg->data[4] + 1 != BT_FIFO_LEN) {
> +		prerror("Got a output buffer len (%d) cap which differs from 
the default\n",
> +				msg->data[4]);
> +		goto out;
> +	}
> +
> +	memcpy(&bt.caps, msg->data, sizeof(struct bt_caps));
> +
> +	/*
> +	 * IPMI Spec says that the value for buffer sizes are:
> +	 * "the largest value allowed in first byte"
> +	 * Therefore we want to add one to what we get
> +	 */
> +	bt.caps.input_buf_len++;
> +	bt.caps.output_buf_len++;
> +	prlog(PR_DEBUG, "BMC BT capabilities received:\n");
> +	prlog(PR_DEBUG, "buffer sizes: %d input %d output\n",
> +			bt.caps.input_buf_len, bt.caps.output_buf_len);
> +	prlog(PR_DEBUG, "number of requests: %d\n", bt.caps.num_requests);
> +	prlog(PR_DEBUG, "msg timeout: %d max retries: %d\n",
> +			bt.caps.msg_timeout, bt.caps.num_retries);
> +
> +out:
> +	ipmi_free_msg(msg);
> +}
> +
> +static void get_bt_caps(void)
> +{
> +
> +	struct ipmi_msg *bmc_caps;
> +	/*
> +	 * Didn't sent a message, now is a good time to ask the BMC for its
> +	 * capabilities.
> +	 */
> +	bmc_caps = ipmi_mkmsg(IPMI_DEFAULT_INTERFACE, IPMI_GET_BT_CAPS,
> +			get_bt_caps_complete, NULL, NULL, 0, sizeof(struct 
bt_caps));
> +	if (!bmc_caps)
> +		prerror("Couldn't create BMC BT capabilities msg\n");
> +
> +	if (bmc_caps && ipmi_queue_msg(bmc_caps))
> +		prerror("Couldn't enqueue request for BMC BT capabilities\n");
> +
> +	/* Ignore errors, we'll fallback to using the defaults, no big deal */

Does the default IPMI error handler print anything to the console? Given AMI 
doesn't support this command we want to make sure we don't litter the console 
with spurious error messages.

> +}
> +
>  static inline bool bt_idle(void)
>  {
>  	uint8_t bt_ctrl = bt_inb(BT_CTRL);
> @@ -220,7 +291,7 @@ static void bt_clear_fifo(void)
>  {
>  	int i;
>  
> -	for (i = 0; i < BT_FIFO_LEN; i++)
> +	for (i = 0; i < bt.caps.input_buf_len; i++)
>  		bt_outb(0xff, BT_HOST2BMC);
>  }
>  
> @@ -321,7 +392,7 @@ static void bt_expire_old_msg(uint64_t tb)
>  
>  	bt_msg = list_top(&bt.msgq, struct bt_msg, link);
>  
> -	if (bt_msg && bt_msg->tb > 0 && (bt_msg->tb + BT_MSG_TIMEOUT) < tb) {
> +	if (bt_msg && bt_msg->tb > 0 && (bt_msg->tb + bt.caps.msg_timeout) < 
tb) {
>  		if (bt_msg->send_count < BT_MAX_SEND_COUNT) {
>  			/* A message timeout is usually due to the BMC
>  			clearing the H2B_ATN flag without actually
> @@ -391,7 +462,6 @@ static void bt_send_and_unlock(void)
>  	}
>  
>  	unlock(&bt.lock);
> -	return;
>  }
>  
>  static void bt_poll(struct timer *t __unused, void *data __unused,
> @@ -554,6 +624,13 @@ void bt_init(void)
>  	const struct dt_property *prop;
>  	uint32_t irq;
>  
> +	/* Set sane capability defaults */
> +	bt.caps.num_requests = 1;
> +	bt.caps.input_buf_len = BT_FIFO_LEN;
> +	bt.caps.output_buf_len = BT_FIFO_LEN;
> +	bt.caps.msg_timeout = BT_MSG_TIMEOUT;
> +	bt.caps.num_retries = 1;
> +
>  	/* We support only one */
>  	n = dt_find_compatible_node(dt_root, NULL, "ipmi-bt");
>  	if (!n)
> @@ -595,5 +672,9 @@ void bt_init(void)
>  	irq = dt_prop_get_u32(n, "interrupts");
>  	bt_lpc_client.interrupts = LPC_IRQ(irq);
>  	lpc_register_client(dt_get_chip_id(n), &bt_lpc_client);
> +
> +	/* Enqueue an IPMI message to ask the BMC about its BT capabilities */
> +	get_bt_caps();
> +
>  	prlog(PR_DEBUG, "BT: Using LPC IRQ %d\n", irq);
>  }
> diff --git a/include/ipmi.h b/include/ipmi.h
> index 99a9094..6aeacb0 100644
> --- a/include/ipmi.h
> +++ b/include/ipmi.h
> @@ -117,6 +117,7 @@
>  #define IPMI_GET_MESSAGE_FLAGS		IPMI_CODE(IPMI_NETFN_APP, 
0x31)
>  #define IPMI_GET_MESSAGE		IPMI_CODE(IPMI_NETFN_APP, 0x33)
>  #define IPMI_READ_EVENT			IPMI_CODE(IPMI_NETFN_APP, 
0x35)
> +#define IPMI_GET_BT_CAPS		IPMI_CODE(IPMI_NETFN_APP, 0x56)
>  #define IPMI_SET_SENSOR_READING		IPMI_CODE(IPMI_NETFN_SE, 0x30)
>  
>  /* AMI OEM comamnds. AMI uses NETFN 0x3a and 0x32 */
> 



More information about the Skiboot mailing list