Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 28f26ac7 authored by Corey Minyard's avatar Corey Minyard
Browse files

ipmi: Dynamically fetch GUID periodically



This will catch if the GUID changes.

Signed-off-by: default avatarCorey Minyard <cminyard@mvista.com>
parent 39d3fb45
Loading
Loading
Loading
Loading
+42 −19
Original line number Diff line number Diff line
@@ -274,7 +274,8 @@ struct bmc_device {
	unsigned long          dyn_id_expiry;
	struct mutex           dyn_mutex; /* protects id & dyn* fields */
	u8                     guid[16];
	int                    guid_set;
	u8                     fetch_guid[16];
	int                    dyn_guid_set;
	struct kref	       usecount;
};
#define to_bmc_device(x) container_of((x), struct bmc_device, pdev.dev)
@@ -538,6 +539,8 @@ struct ipmi_smi {
};
#define to_si_intf_from_dev(device) container_of(device, struct ipmi_smi, dev)

static void __get_guid(ipmi_smi_t intf);

/**
 * The driver model view of the IPMI messaging driver.
 */
@@ -2198,7 +2201,7 @@ static int bmc_get_device_id(ipmi_smi_t intf, struct bmc_device *bmc,
			     bool *guid_set, u8 *guid)
{
	int rv = 0;
	int prev_dyn_id_set;
	int prev_dyn_id_set, prev_guid_set;

	if (!intf) {
		mutex_lock(&bmc->dyn_mutex);
@@ -2230,8 +2233,19 @@ static int bmc_get_device_id(ipmi_smi_t intf, struct bmc_device *bmc,
	if (bmc->dyn_id_set && time_is_after_jiffies(bmc->dyn_id_expiry))
		goto out;

	prev_dyn_id_set = bmc->dyn_id_set;
	prev_guid_set = bmc->dyn_guid_set;
	__get_guid(intf);

	if (bmc->dyn_guid_set)
		memcpy(bmc->guid, bmc->fetch_guid, 16);
	else if (prev_guid_set)
		/*
		 * The guid used to be valid and it failed to fetch,
		 * just use the cached value.
		 */
		bmc->dyn_guid_set = prev_guid_set;

	prev_dyn_id_set = bmc->dyn_id_set;
	rv = __get_device_id(intf, bmc);
	if (rv)
		goto out;
@@ -2250,9 +2264,9 @@ static int bmc_get_device_id(ipmi_smi_t intf, struct bmc_device *bmc,
		*id = bmc->id;

	if (guid_set)
		*guid_set = bmc->guid_set;
		*guid_set = bmc->dyn_guid_set;

	if (guid && bmc->guid_set)
	if (guid && bmc->dyn_guid_set)
		memcpy(guid, bmc->guid, 16);

	mutex_unlock(&bmc->dyn_mutex);
@@ -2845,7 +2859,7 @@ static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum)
	 * representing the interfaced BMC already
	 */
	mutex_lock(&ipmidriver_mutex);
	if (bmc->guid_set)
	if (bmc->dyn_guid_set)
		old_bmc = ipmi_find_bmc_guid(&ipmidriver.driver, bmc->guid);
	else
		old_bmc = ipmi_find_bmc_prod_dev_id(&ipmidriver.driver,
@@ -2997,9 +3011,10 @@ send_guid_cmd(ipmi_smi_t intf, int chan)
			      -1, 0);
}

static void
guid_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg)
static void guid_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg)
{
	struct bmc_device *bmc = intf->bmc;

	if ((msg->addr.addr_type != IPMI_SYSTEM_INTERFACE_ADDR_TYPE)
	    || (msg->msg.netfn != IPMI_NETFN_APP_RESPONSE)
	    || (msg->msg.cmd != IPMI_GET_DEVICE_GUID_CMD))
@@ -3008,12 +3023,12 @@ guid_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg)

	if (msg->msg.data[0] != 0) {
		/* Error from getting the GUID, the BMC doesn't have one. */
		intf->bmc->guid_set = 0;
		bmc->dyn_guid_set = 0;
		goto out;
	}

	if (msg->msg.data_len < 17) {
		intf->bmc->guid_set = 0;
		bmc->dyn_guid_set = 0;
		printk(KERN_WARNING PFX
		       "guid_handler: The GUID response from the BMC was too"
		       " short, it was %d but should have been 17.  Assuming"
@@ -3022,24 +3037,34 @@ guid_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg)
		goto out;
	}

	memcpy(intf->bmc->guid, msg->msg.data + 1, 16);
	intf->bmc->guid_set = 1;
	memcpy(bmc->fetch_guid, msg->msg.data + 1, 16);
	/*
	 * Make sure the guid data is available before setting
	 * dyn_guid_set.
	 */
	smp_wmb();
	bmc->dyn_guid_set = 1;
 out:
	wake_up(&intf->waitq);
}

static void
get_guid(ipmi_smi_t intf)
static void __get_guid(ipmi_smi_t intf)
{
	int rv;
	struct bmc_device *bmc = intf->bmc;

	intf->bmc->guid_set = 0x2;
	bmc->dyn_guid_set = 2;
	intf->null_user_handler = guid_handler;
	rv = send_guid_cmd(intf, 0);
	if (rv)
		/* Send failed, no GUID available. */
		intf->bmc->guid_set = 0;
	wait_event(intf->waitq, intf->bmc->guid_set != 2);
		bmc->dyn_guid_set = 0;

	wait_event(intf->waitq, bmc->dyn_guid_set != 2);

	/* dyn_guid_set makes the guid data available. */
	smp_rmb();

	intf->null_user_handler = NULL;
}

@@ -3254,8 +3279,6 @@ int ipmi_register_smi(const struct ipmi_smi_handlers *handlers,
	if (rv)
		goto out;

	get_guid(intf);

	rv = bmc_get_device_id(intf, NULL, &id, NULL, NULL);
	if (rv) {
		dev_err(si_dev, "Unable to get the device id: %d\n", rv);