Re: [RFC v1 1/4] ipmi_bmc: framework for BT IPMI on BMCs
On Thu, Aug 10, 2017 at 6:58 AM, Corey Minyardwrote: > On 08/07/2017 10:52 PM, Brendan Higgins wrote: >> >> From: Benjamin Fair >> >> This patch introduces a framework for writing IPMI drivers which run on >> a Board Management Controller. It is similar in function to OpenIPMI. >> The framework handles registering devices and routing messages. > > > Ok, I think I understand this. I have a few nitpicky comments inline. The > RCU usage > looks correct, and the basic design seems sound. Sweet > > This piece of code takes a communication interface, called a bus, and > muxes/demuxes > messages on that bus to various users, called devices. The name "devices" > confused > me for a bit, because I was thinking they were physical devices, what Linux > would > call a device. I don't have a good suggestion for another name, though. We could maybe do "*_interface" instead of "*_bus" and "*_handler" instead of "*_device"; admittedly, it is not the best name ever: handler has some connotations. > > > > I assume you would create one of these per bus for handling multiple busses, > which > you will obviously need to do in the future when IPMB comes. Yep, that is the intention. I was planning on adding support to use the device infrastructure so that multiple busses could be declared using device tree, etc. I do not have that now, but I thought that was a lot of work and I would want to get general buy-in before doing that. We just did enough to make code that achieves feature parity to what we have now and the core of the new proposed features. > > I can see two big problems with the way the "match_request" is done: > * If multiple users want to handle the same request, only one of them will > get it > and they will not know they have conflicted. > * Doing this for userland interfaces will be hard. > The other way to do this is for each user to register for each request type > and > manage it all in this code, which is kind of messy to use, but avoids the > above problems. Right, we considered this; however, I thought this is best because we also want to handle routing of OEM messages; I suppose we could register a type for OEM messages and then have a secondary set of handlers there; this would have some drawbacks though, the default handler interface would become a lot more complicated. On the other hand, now that I am thinking about it; having a common kernel interface for OEM messages could be really useful; this has definitely caused us some grief. > > In thinking about the bigger picture here, you will need something like this > for every > communication interface the BMC supports: the system interface, LAN, IPMB, > ICMB > (let's hope not), and serial/modem interfaces (let's hope not, too, but > people really > use these in the field). Maybe ICMB and serial aren't on your radar, but > I'd expect > LAN is pretty important, and you have already mentioned IPMB. Right, we are thinking about IPMB right now; I agree that the other stuff should be considered, but we don't really have a need for it now. My hope would be to make a similar interface for IPMB. > > If you are thinking you will have a separate one of these for LAN in > userspace, I > would say just do it all in userspace. For LAN you will have something that > has > to mux/demux all the messages from the LAN interface to the various users, > the > same code could sit on top of the current BT interface (and IPMB, etc.). So right now we do have handlers for a lot of basic commands in user space; this is why I have the default device file interface. However, it is incomplete and I am starting to look at commands that make more sense being implemented in the kernel. I have kind of danced around your point so far, for LAN, as far as I know we only support a REST interface right now; we should have the option of the LAN interface, but I don't think anyone has really tackled that yet. Basically, the way I see this now is sort of a mirror of what is done on the host side, we will have a kernel and a userland interface and then we will evolve it as necessary. In any case, I think there is probably a lot of room for additional discussion here. > > I guess I'm trying to figure out how you expect all this work out in the > end. What > you have now is a message mux/demux that can only have on thing underneath > it and one thing above it, which obviously isn't very useful. Are you > thinking you > can have other in-kernel things that can handle specific messages? I'm > having > a hard time imagining that's the case. Or are you thinking that you will Yes, I as I mentioned above, having handlers in the kernel is a prime motivator for this. I have been working on an interface for doing flash updates over IPMI. IPMI is not really a great way to do this in terms of performance or the interface it provides; however, IPMI is great in the sense that all platforms have it, so I want to have alternative backends
Re: [RFC v1 1/4] ipmi_bmc: framework for BT IPMI on BMCs
On Thu, Aug 10, 2017 at 6:58 AM, Corey Minyard wrote: > On 08/07/2017 10:52 PM, Brendan Higgins wrote: >> >> From: Benjamin Fair >> >> This patch introduces a framework for writing IPMI drivers which run on >> a Board Management Controller. It is similar in function to OpenIPMI. >> The framework handles registering devices and routing messages. > > > Ok, I think I understand this. I have a few nitpicky comments inline. The > RCU usage > looks correct, and the basic design seems sound. Sweet > > This piece of code takes a communication interface, called a bus, and > muxes/demuxes > messages on that bus to various users, called devices. The name "devices" > confused > me for a bit, because I was thinking they were physical devices, what Linux > would > call a device. I don't have a good suggestion for another name, though. We could maybe do "*_interface" instead of "*_bus" and "*_handler" instead of "*_device"; admittedly, it is not the best name ever: handler has some connotations. > > > > I assume you would create one of these per bus for handling multiple busses, > which > you will obviously need to do in the future when IPMB comes. Yep, that is the intention. I was planning on adding support to use the device infrastructure so that multiple busses could be declared using device tree, etc. I do not have that now, but I thought that was a lot of work and I would want to get general buy-in before doing that. We just did enough to make code that achieves feature parity to what we have now and the core of the new proposed features. > > I can see two big problems with the way the "match_request" is done: > * If multiple users want to handle the same request, only one of them will > get it > and they will not know they have conflicted. > * Doing this for userland interfaces will be hard. > The other way to do this is for each user to register for each request type > and > manage it all in this code, which is kind of messy to use, but avoids the > above problems. Right, we considered this; however, I thought this is best because we also want to handle routing of OEM messages; I suppose we could register a type for OEM messages and then have a secondary set of handlers there; this would have some drawbacks though, the default handler interface would become a lot more complicated. On the other hand, now that I am thinking about it; having a common kernel interface for OEM messages could be really useful; this has definitely caused us some grief. > > In thinking about the bigger picture here, you will need something like this > for every > communication interface the BMC supports: the system interface, LAN, IPMB, > ICMB > (let's hope not), and serial/modem interfaces (let's hope not, too, but > people really > use these in the field). Maybe ICMB and serial aren't on your radar, but > I'd expect > LAN is pretty important, and you have already mentioned IPMB. Right, we are thinking about IPMB right now; I agree that the other stuff should be considered, but we don't really have a need for it now. My hope would be to make a similar interface for IPMB. > > If you are thinking you will have a separate one of these for LAN in > userspace, I > would say just do it all in userspace. For LAN you will have something that > has > to mux/demux all the messages from the LAN interface to the various users, > the > same code could sit on top of the current BT interface (and IPMB, etc.). So right now we do have handlers for a lot of basic commands in user space; this is why I have the default device file interface. However, it is incomplete and I am starting to look at commands that make more sense being implemented in the kernel. I have kind of danced around your point so far, for LAN, as far as I know we only support a REST interface right now; we should have the option of the LAN interface, but I don't think anyone has really tackled that yet. Basically, the way I see this now is sort of a mirror of what is done on the host side, we will have a kernel and a userland interface and then we will evolve it as necessary. In any case, I think there is probably a lot of room for additional discussion here. > > I guess I'm trying to figure out how you expect all this work out in the > end. What > you have now is a message mux/demux that can only have on thing underneath > it and one thing above it, which obviously isn't very useful. Are you > thinking you > can have other in-kernel things that can handle specific messages? I'm > having > a hard time imagining that's the case. Or are you thinking that you will Yes, I as I mentioned above, having handlers in the kernel is a prime motivator for this. I have been working on an interface for doing flash updates over IPMI. IPMI is not really a great way to do this in terms of performance or the interface it provides; however, IPMI is great in the sense that all platforms have it, so I want to have alternative backends for this flash interface and provide an
Re: [RFC v1 1/4] ipmi_bmc: framework for BT IPMI on BMCs
On 08/07/2017 10:52 PM, Brendan Higgins wrote: From: Benjamin FairThis patch introduces a framework for writing IPMI drivers which run on a Board Management Controller. It is similar in function to OpenIPMI. The framework handles registering devices and routing messages. Ok, I think I understand this. I have a few nitpicky comments inline. The RCU usage looks correct, and the basic design seems sound. This piece of code takes a communication interface, called a bus, and muxes/demuxes messages on that bus to various users, called devices. The name "devices" confused me for a bit, because I was thinking they were physical devices, what Linux would call a device. I don't have a good suggestion for another name, though. I assume you would create one of these per bus for handling multiple busses, which you will obviously need to do in the future when IPMB comes. I can see two big problems with the way the "match_request" is done: * If multiple users want to handle the same request, only one of them will get it and they will not know they have conflicted. * Doing this for userland interfaces will be hard. The other way to do this is for each user to register for each request type and manage it all in this code, which is kind of messy to use, but avoids the above problems. In thinking about the bigger picture here, you will need something like this for every communication interface the BMC supports: the system interface, LAN, IPMB, ICMB (let's hope not), and serial/modem interfaces (let's hope not, too, but people really use these in the field). Maybe ICMB and serial aren't on your radar, but I'd expect LAN is pretty important, and you have already mentioned IPMB. If you are thinking you will have a separate one of these for LAN in userspace, I would say just do it all in userspace. For LAN you will have something that has to mux/demux all the messages from the LAN interface to the various users, the same code could sit on top of the current BT interface (and IPMB, etc.). I guess I'm trying to figure out how you expect all this work out in the end. What you have now is a message mux/demux that can only have on thing underneath it and one thing above it, which obviously isn't very useful. Are you thinking you can have other in-kernel things that can handle specific messages? I'm having a hard time imagining that's the case. Or are you thinking that you will create a userland interface to create a bus and then when a LAN connection comes in you create one of these BMC contexts and route the LAN traffic through this code? That's kind of clever, but I'm wondering if there would be better ways to do this than this design. -corey Signed-off-by: Benjamin Fair Signed-off-by: Brendan Higgins --- drivers/char/ipmi_bmc/Makefile | 1 + drivers/char/ipmi_bmc/ipmi_bmc.c | 294 +++ include/linux/ipmi_bmc.h | 184 3 files changed, 479 insertions(+) create mode 100644 drivers/char/ipmi_bmc/ipmi_bmc.c diff --git a/drivers/char/ipmi_bmc/Makefile b/drivers/char/ipmi_bmc/Makefile index 8bff32b55c24..9c7cd48d899f 100644 --- a/drivers/char/ipmi_bmc/Makefile +++ b/drivers/char/ipmi_bmc/Makefile @@ -2,5 +2,6 @@ # Makefile for the ipmi bmc drivers. # +obj-$(CONFIG_IPMI_BMC) += ipmi_bmc.o obj-$(CONFIG_IPMI_BMC_BT_I2C) += ipmi_bmc_bt_i2c.o obj-$(CONFIG_ASPEED_BT_IPMI_BMC) += ipmi_bmc_bt_aspeed.o diff --git a/drivers/char/ipmi_bmc/ipmi_bmc.c b/drivers/char/ipmi_bmc/ipmi_bmc.c new file mode 100644 index ..c1324ac9a83c --- /dev/null +++ b/drivers/char/ipmi_bmc/ipmi_bmc.c This is not really a BMC, it's a BMC message router, or something like that. @@ -0,0 +1,294 @@ +/* + * Copyright 2017 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PFX "IPMI BMC core: " + +struct ipmi_bmc_ctx *ipmi_bmc_get_global_ctx() +{ + static struct ipmi_bmc_ctx global_ctx; + + return _ctx; +} + +int ipmi_bmc_send_response(struct ipmi_bmc_ctx *ctx, + struct bt_msg *bt_response) +{ + struct ipmi_bmc_bus *bus; + int ret = -ENODEV; + + rcu_read_lock(); + bus = rcu_dereference(ctx->bus); + + if (bus) + ret = bus->send_response(bus, bt_response); + + rcu_read_unlock(); + return ret; +}
Re: [RFC v1 1/4] ipmi_bmc: framework for BT IPMI on BMCs
On 08/07/2017 10:52 PM, Brendan Higgins wrote: From: Benjamin Fair This patch introduces a framework for writing IPMI drivers which run on a Board Management Controller. It is similar in function to OpenIPMI. The framework handles registering devices and routing messages. Ok, I think I understand this. I have a few nitpicky comments inline. The RCU usage looks correct, and the basic design seems sound. This piece of code takes a communication interface, called a bus, and muxes/demuxes messages on that bus to various users, called devices. The name "devices" confused me for a bit, because I was thinking they were physical devices, what Linux would call a device. I don't have a good suggestion for another name, though. I assume you would create one of these per bus for handling multiple busses, which you will obviously need to do in the future when IPMB comes. I can see two big problems with the way the "match_request" is done: * If multiple users want to handle the same request, only one of them will get it and they will not know they have conflicted. * Doing this for userland interfaces will be hard. The other way to do this is for each user to register for each request type and manage it all in this code, which is kind of messy to use, but avoids the above problems. In thinking about the bigger picture here, you will need something like this for every communication interface the BMC supports: the system interface, LAN, IPMB, ICMB (let's hope not), and serial/modem interfaces (let's hope not, too, but people really use these in the field). Maybe ICMB and serial aren't on your radar, but I'd expect LAN is pretty important, and you have already mentioned IPMB. If you are thinking you will have a separate one of these for LAN in userspace, I would say just do it all in userspace. For LAN you will have something that has to mux/demux all the messages from the LAN interface to the various users, the same code could sit on top of the current BT interface (and IPMB, etc.). I guess I'm trying to figure out how you expect all this work out in the end. What you have now is a message mux/demux that can only have on thing underneath it and one thing above it, which obviously isn't very useful. Are you thinking you can have other in-kernel things that can handle specific messages? I'm having a hard time imagining that's the case. Or are you thinking that you will create a userland interface to create a bus and then when a LAN connection comes in you create one of these BMC contexts and route the LAN traffic through this code? That's kind of clever, but I'm wondering if there would be better ways to do this than this design. -corey Signed-off-by: Benjamin Fair Signed-off-by: Brendan Higgins --- drivers/char/ipmi_bmc/Makefile | 1 + drivers/char/ipmi_bmc/ipmi_bmc.c | 294 +++ include/linux/ipmi_bmc.h | 184 3 files changed, 479 insertions(+) create mode 100644 drivers/char/ipmi_bmc/ipmi_bmc.c diff --git a/drivers/char/ipmi_bmc/Makefile b/drivers/char/ipmi_bmc/Makefile index 8bff32b55c24..9c7cd48d899f 100644 --- a/drivers/char/ipmi_bmc/Makefile +++ b/drivers/char/ipmi_bmc/Makefile @@ -2,5 +2,6 @@ # Makefile for the ipmi bmc drivers. # +obj-$(CONFIG_IPMI_BMC) += ipmi_bmc.o obj-$(CONFIG_IPMI_BMC_BT_I2C) += ipmi_bmc_bt_i2c.o obj-$(CONFIG_ASPEED_BT_IPMI_BMC) += ipmi_bmc_bt_aspeed.o diff --git a/drivers/char/ipmi_bmc/ipmi_bmc.c b/drivers/char/ipmi_bmc/ipmi_bmc.c new file mode 100644 index ..c1324ac9a83c --- /dev/null +++ b/drivers/char/ipmi_bmc/ipmi_bmc.c This is not really a BMC, it's a BMC message router, or something like that. @@ -0,0 +1,294 @@ +/* + * Copyright 2017 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PFX "IPMI BMC core: " + +struct ipmi_bmc_ctx *ipmi_bmc_get_global_ctx() +{ + static struct ipmi_bmc_ctx global_ctx; + + return _ctx; +} + +int ipmi_bmc_send_response(struct ipmi_bmc_ctx *ctx, + struct bt_msg *bt_response) +{ + struct ipmi_bmc_bus *bus; + int ret = -ENODEV; + + rcu_read_lock(); + bus = rcu_dereference(ctx->bus); + + if (bus) + ret = bus->send_response(bus, bt_response); + + rcu_read_unlock(); + return ret; +} +EXPORT_SYMBOL(ipmi_bmc_send_response); + +bool ipmi_bmc_is_response_open(struct ipmi_bmc_ctx *ctx) +{ +
[RFC v1 1/4] ipmi_bmc: framework for BT IPMI on BMCs
From: Benjamin FairThis patch introduces a framework for writing IPMI drivers which run on a Board Management Controller. It is similar in function to OpenIPMI. The framework handles registering devices and routing messages. Signed-off-by: Benjamin Fair Signed-off-by: Brendan Higgins --- drivers/char/ipmi_bmc/Makefile | 1 + drivers/char/ipmi_bmc/ipmi_bmc.c | 294 +++ include/linux/ipmi_bmc.h | 184 3 files changed, 479 insertions(+) create mode 100644 drivers/char/ipmi_bmc/ipmi_bmc.c diff --git a/drivers/char/ipmi_bmc/Makefile b/drivers/char/ipmi_bmc/Makefile index 8bff32b55c24..9c7cd48d899f 100644 --- a/drivers/char/ipmi_bmc/Makefile +++ b/drivers/char/ipmi_bmc/Makefile @@ -2,5 +2,6 @@ # Makefile for the ipmi bmc drivers. # +obj-$(CONFIG_IPMI_BMC) += ipmi_bmc.o obj-$(CONFIG_IPMI_BMC_BT_I2C) += ipmi_bmc_bt_i2c.o obj-$(CONFIG_ASPEED_BT_IPMI_BMC) += ipmi_bmc_bt_aspeed.o diff --git a/drivers/char/ipmi_bmc/ipmi_bmc.c b/drivers/char/ipmi_bmc/ipmi_bmc.c new file mode 100644 index ..c1324ac9a83c --- /dev/null +++ b/drivers/char/ipmi_bmc/ipmi_bmc.c @@ -0,0 +1,294 @@ +/* + * Copyright 2017 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PFX "IPMI BMC core: " + +struct ipmi_bmc_ctx *ipmi_bmc_get_global_ctx() +{ + static struct ipmi_bmc_ctx global_ctx; + + return _ctx; +} + +int ipmi_bmc_send_response(struct ipmi_bmc_ctx *ctx, + struct bt_msg *bt_response) +{ + struct ipmi_bmc_bus *bus; + int ret = -ENODEV; + + rcu_read_lock(); + bus = rcu_dereference(ctx->bus); + + if (bus) + ret = bus->send_response(bus, bt_response); + + rcu_read_unlock(); + return ret; +} +EXPORT_SYMBOL(ipmi_bmc_send_response); + +bool ipmi_bmc_is_response_open(struct ipmi_bmc_ctx *ctx) +{ + struct ipmi_bmc_bus *bus; + bool ret = false; + + rcu_read_lock(); + bus = rcu_dereference(ctx->bus); + + if (bus) + ret = bus->is_response_open(bus); + + rcu_read_unlock(); + return ret; +} +EXPORT_SYMBOL(ipmi_bmc_is_response_open); + +int ipmi_bmc_register_device(struct ipmi_bmc_ctx *ctx, +struct ipmi_bmc_device *device_in) +{ + struct ipmi_bmc_device *device; + + mutex_lock(>drivers_mutex); + /* Make sure it hasn't already been registered. */ + list_for_each_entry(device, >devices, link) { + if (device == device_in) { + mutex_unlock(>drivers_mutex); + return -EINVAL; + } + } + + list_add_rcu(_in->link, >devices); + mutex_unlock(>drivers_mutex); + + return 0; +} +EXPORT_SYMBOL(ipmi_bmc_register_device); + +int ipmi_bmc_unregister_device(struct ipmi_bmc_ctx *ctx, + struct ipmi_bmc_device *device_in) +{ + struct ipmi_bmc_device *device; + bool found = false; + + mutex_lock(>drivers_mutex); + /* Make sure it is currently registered. */ + list_for_each_entry(device, >devices, link) { + if (device == device_in) { + found = true; + break; + } + } + if (!found) { + mutex_unlock(>drivers_mutex); + return -ENXIO; + } + + list_del_rcu(_in->link); + mutex_unlock(>drivers_mutex); + synchronize_rcu(); + + return 0; +} +EXPORT_SYMBOL(ipmi_bmc_unregister_device); + +int ipmi_bmc_register_default_device(struct ipmi_bmc_ctx *ctx, +struct ipmi_bmc_device *device) +{ + int ret; + + mutex_lock(>drivers_mutex); + if (!ctx->default_device) { + ctx->default_device = device; + ret = 0; + } else { + ret = -EBUSY; + } + mutex_unlock(>drivers_mutex); + + return ret; +} +EXPORT_SYMBOL(ipmi_bmc_register_default_device); + +int ipmi_bmc_unregister_default_device(struct ipmi_bmc_ctx *ctx, + struct ipmi_bmc_device *device) +{ + int ret; + + mutex_lock(>drivers_mutex); + if (ctx->default_device == device) { + ctx->default_device = NULL; + ret = 0; + } else { + ret = -ENXIO; + } +
[RFC v1 1/4] ipmi_bmc: framework for BT IPMI on BMCs
From: Benjamin Fair This patch introduces a framework for writing IPMI drivers which run on a Board Management Controller. It is similar in function to OpenIPMI. The framework handles registering devices and routing messages. Signed-off-by: Benjamin Fair Signed-off-by: Brendan Higgins --- drivers/char/ipmi_bmc/Makefile | 1 + drivers/char/ipmi_bmc/ipmi_bmc.c | 294 +++ include/linux/ipmi_bmc.h | 184 3 files changed, 479 insertions(+) create mode 100644 drivers/char/ipmi_bmc/ipmi_bmc.c diff --git a/drivers/char/ipmi_bmc/Makefile b/drivers/char/ipmi_bmc/Makefile index 8bff32b55c24..9c7cd48d899f 100644 --- a/drivers/char/ipmi_bmc/Makefile +++ b/drivers/char/ipmi_bmc/Makefile @@ -2,5 +2,6 @@ # Makefile for the ipmi bmc drivers. # +obj-$(CONFIG_IPMI_BMC) += ipmi_bmc.o obj-$(CONFIG_IPMI_BMC_BT_I2C) += ipmi_bmc_bt_i2c.o obj-$(CONFIG_ASPEED_BT_IPMI_BMC) += ipmi_bmc_bt_aspeed.o diff --git a/drivers/char/ipmi_bmc/ipmi_bmc.c b/drivers/char/ipmi_bmc/ipmi_bmc.c new file mode 100644 index ..c1324ac9a83c --- /dev/null +++ b/drivers/char/ipmi_bmc/ipmi_bmc.c @@ -0,0 +1,294 @@ +/* + * Copyright 2017 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PFX "IPMI BMC core: " + +struct ipmi_bmc_ctx *ipmi_bmc_get_global_ctx() +{ + static struct ipmi_bmc_ctx global_ctx; + + return _ctx; +} + +int ipmi_bmc_send_response(struct ipmi_bmc_ctx *ctx, + struct bt_msg *bt_response) +{ + struct ipmi_bmc_bus *bus; + int ret = -ENODEV; + + rcu_read_lock(); + bus = rcu_dereference(ctx->bus); + + if (bus) + ret = bus->send_response(bus, bt_response); + + rcu_read_unlock(); + return ret; +} +EXPORT_SYMBOL(ipmi_bmc_send_response); + +bool ipmi_bmc_is_response_open(struct ipmi_bmc_ctx *ctx) +{ + struct ipmi_bmc_bus *bus; + bool ret = false; + + rcu_read_lock(); + bus = rcu_dereference(ctx->bus); + + if (bus) + ret = bus->is_response_open(bus); + + rcu_read_unlock(); + return ret; +} +EXPORT_SYMBOL(ipmi_bmc_is_response_open); + +int ipmi_bmc_register_device(struct ipmi_bmc_ctx *ctx, +struct ipmi_bmc_device *device_in) +{ + struct ipmi_bmc_device *device; + + mutex_lock(>drivers_mutex); + /* Make sure it hasn't already been registered. */ + list_for_each_entry(device, >devices, link) { + if (device == device_in) { + mutex_unlock(>drivers_mutex); + return -EINVAL; + } + } + + list_add_rcu(_in->link, >devices); + mutex_unlock(>drivers_mutex); + + return 0; +} +EXPORT_SYMBOL(ipmi_bmc_register_device); + +int ipmi_bmc_unregister_device(struct ipmi_bmc_ctx *ctx, + struct ipmi_bmc_device *device_in) +{ + struct ipmi_bmc_device *device; + bool found = false; + + mutex_lock(>drivers_mutex); + /* Make sure it is currently registered. */ + list_for_each_entry(device, >devices, link) { + if (device == device_in) { + found = true; + break; + } + } + if (!found) { + mutex_unlock(>drivers_mutex); + return -ENXIO; + } + + list_del_rcu(_in->link); + mutex_unlock(>drivers_mutex); + synchronize_rcu(); + + return 0; +} +EXPORT_SYMBOL(ipmi_bmc_unregister_device); + +int ipmi_bmc_register_default_device(struct ipmi_bmc_ctx *ctx, +struct ipmi_bmc_device *device) +{ + int ret; + + mutex_lock(>drivers_mutex); + if (!ctx->default_device) { + ctx->default_device = device; + ret = 0; + } else { + ret = -EBUSY; + } + mutex_unlock(>drivers_mutex); + + return ret; +} +EXPORT_SYMBOL(ipmi_bmc_register_default_device); + +int ipmi_bmc_unregister_default_device(struct ipmi_bmc_ctx *ctx, + struct ipmi_bmc_device *device) +{ + int ret; + + mutex_lock(>drivers_mutex); + if (ctx->default_device == device) { + ctx->default_device = NULL; + ret = 0; + } else { + ret = -ENXIO; + } + mutex_unlock(>drivers_mutex); + synchronize_rcu(); + + return