[Skiboot] [PATCH] ipmi: ensure forward progress on ipmi_queue_msg_sync()
Oliver
oohall at gmail.com
Fri May 10 14:52:46 AEST 2019
On Wed, May 1, 2019 at 5:06 PM Stewart Smith <stewart at linux.ibm.com> wrote:
>
> BT responses are handled using a timer doing the polling. To hope to
> get an answer to an IPMI synchronous message, the timer needs to run.
>
> We can't just check all timers though as there may be a timer that
> wants a lock that's held by a code path calling ipmi_queue_msg_sync(),
> and if we did enforce that as a requirement, it's a pretty subtle
> API that is asking to be broken.
>
> So, if we just run a poll function to crank anything that the IPMI
> backend needs, then we should be fine.
>
> This issue shows up very quickly under QEMU when loading the first
> flash resource with the IPMI HIOMAP backend.
>
> Reported-by: Cédric Le Goater <clg at kaod.org>
> Signed-off-by: Stewart Smith <stewart at linux.ibm.com>
Merged to master as of v6.3-2-gf01cd777adb1
I'm a little bit iffy on this since we adding hacks for specific
pollers seems kind of jank, but I don't have any better ideas right
now.
> ---
> core/ipmi.c | 12 +++++++++++-
> hw/bt.c | 6 ++++++
> hw/fsp/fsp-ipmi.c | 2 ++
> include/ipmi.h | 9 +++++++++
> 4 files changed, 28 insertions(+), 1 deletion(-)
>
> diff --git a/core/ipmi.c b/core/ipmi.c
> index 2bf3f4dabe19..9cf5aa626b02 100644
> --- a/core/ipmi.c
> +++ b/core/ipmi.c
> @@ -182,8 +182,18 @@ void ipmi_queue_msg_sync(struct ipmi_msg *msg)
> ipmi_queue_msg_head(msg);
> unlock(&sync_lock);
>
> - while (sync_msg == msg)
> + /*
> + * BT response handling relies on a timer. We can't just run all
> + * timers because we may have been called with a lock that a timer
> + * wants, and they're generally not written to cope with that.
> + * So, just run whatever the IPMI backend needs to make forward
> + * progress.
> + */
> + while (sync_msg == msg) {
> + if (msg->backend->poll)
> + msg->backend->poll();
> time_wait_ms(10);
> + }
> }
>
> static void ipmi_read_event_complete(struct ipmi_msg *msg)
> diff --git a/hw/bt.c b/hw/bt.c
> index 9febe8e5ce08..a0ff0db4c479 100644
> --- a/hw/bt.c
> +++ b/hw/bt.c
> @@ -526,6 +526,11 @@ static void bt_poll(struct timer *t __unused, void *data __unused,
> bt.irq_ok ? TIMER_POLL : msecs_to_tb(BT_DEFAULT_POLL_MS));
> }
>
> +static void bt_ipmi_poll(void)
> +{
> + bt_poll(NULL, NULL, mftb());
> +}
> +
> static void bt_add_msg(struct bt_msg *bt_msg)
> {
> bt_msg->tb = 0;
> @@ -647,6 +652,7 @@ static struct ipmi_backend bt_backend = {
> .queue_msg_head = bt_add_ipmi_msg_head,
> .dequeue_msg = bt_del_ipmi_msg,
> .disable_retry = bt_disable_ipmi_msg_retry,
> + .poll = bt_ipmi_poll,
> };
>
> static struct lpc_client bt_lpc_client = {
> diff --git a/hw/fsp/fsp-ipmi.c b/hw/fsp/fsp-ipmi.c
> index d262cee6591d..8c65e6c77f88 100644
> --- a/hw/fsp/fsp-ipmi.c
> +++ b/hw/fsp/fsp-ipmi.c
> @@ -254,6 +254,8 @@ static struct ipmi_backend fsp_ipmi_backend = {
> .queue_msg = fsp_ipmi_queue_msg,
> .queue_msg_head = fsp_ipmi_queue_msg_head,
> .dequeue_msg = fsp_ipmi_dequeue_msg,
> + /* FIXME if ever use ipmi_queue_msg_sync on FSP */
> + .poll = NULL,
> };
>
> static bool fsp_ipmi_send_response(uint32_t cmd)
> diff --git a/include/ipmi.h b/include/ipmi.h
> index 4999bb5a3f4c..ea5a0a971daf 100644
> --- a/include/ipmi.h
> +++ b/include/ipmi.h
> @@ -182,6 +182,15 @@ struct ipmi_backend {
> int (*queue_msg_head)(struct ipmi_msg *);
> int (*dequeue_msg)(struct ipmi_msg *);
> void (*disable_retry)(struct ipmi_msg *);
> + /*
> + * When processing a synchronous IPMI message, pollers may not run, and
> + * neither may timers (as the synchronous IPMI message may be being
> + * done with locks held, which a timer may then try to also take).
> + *
> + * So, ensure we have a way to drive any state machines that an IPMI
> + * backend may neeed to crank to ensure forward progress.
> + */
> + void (*poll)(void);
> };
>
> extern struct ipmi_backend *ipmi_backend;
> --
> 2.20.1
>
> _______________________________________________
> Skiboot mailing list
> Skiboot at lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/skiboot
More information about the Skiboot
mailing list