brintos

brintos / linux-shallow public Read only

0
0
Text · 13.7 KiB · 6a4f279 Raw
584 lines · c
1// SPDX-License-Identifier: GPL-2.02 3/*4 * Driver to talk to a remote management controller on IPMB.5 */6 7#include <linux/acpi.h>8#include <linux/errno.h>9#include <linux/i2c.h>10#include <linux/miscdevice.h>11#include <linux/module.h>12#include <linux/mutex.h>13#include <linux/poll.h>14#include <linux/slab.h>15#include <linux/spinlock.h>16#include <linux/semaphore.h>17#include <linux/kthread.h>18#include <linux/wait.h>19#include <linux/ipmi_msgdefs.h>20#include <linux/ipmi_smi.h>21 22#define DEVICE_NAME "ipmi-ipmb"23 24static int bmcaddr = 0x20;25module_param(bmcaddr, int, 0644);26MODULE_PARM_DESC(bmcaddr, "Address to use for BMC.");27 28static unsigned int retry_time_ms = 250;29module_param(retry_time_ms, uint, 0644);30MODULE_PARM_DESC(retry_time_ms, "Timeout time between retries, in milliseconds.");31 32static unsigned int max_retries = 1;33module_param(max_retries, uint, 0644);34MODULE_PARM_DESC(max_retries, "Max resends of a command before timing out.");35 36/* Add room for the two slave addresses, two checksums, and rqSeq. */37#define IPMB_MAX_MSG_LEN (IPMI_MAX_MSG_LENGTH + 5)38 39struct ipmi_ipmb_dev {40	struct ipmi_smi *intf;41	struct i2c_client *client;42	struct i2c_client *slave;43 44	struct ipmi_smi_handlers handlers;45 46	bool ready;47 48	u8 curr_seq;49 50	u8 bmcaddr;51	u32 retry_time_ms;52	u32 max_retries;53 54	struct ipmi_smi_msg *next_msg;55	struct ipmi_smi_msg *working_msg;56 57	/* Transmit thread. */58	struct task_struct *thread;59	struct semaphore wake_thread;60	struct semaphore got_rsp;61	spinlock_t lock;62	bool stopping;63 64	u8 xmitmsg[IPMB_MAX_MSG_LEN];65	unsigned int xmitlen;66 67	u8 rcvmsg[IPMB_MAX_MSG_LEN];68	unsigned int rcvlen;69	bool overrun;70};71 72static bool valid_ipmb(struct ipmi_ipmb_dev *iidev)73{74	u8 *msg = iidev->rcvmsg;75	u8 netfn;76 77	if (iidev->overrun)78		return false;79 80	/* Minimum message size. */81	if (iidev->rcvlen < 7)82		return false;83 84	/* Is it a response? */85	netfn = msg[1] >> 2;86	if (netfn & 1) {87		/* Response messages have an added completion code. */88		if (iidev->rcvlen < 8)89			return false;90	}91 92	if (ipmb_checksum(msg, 3) != 0)93		return false;94	if (ipmb_checksum(msg + 3, iidev->rcvlen - 3) != 0)95		return false;96 97	return true;98}99 100static void ipmi_ipmb_check_msg_done(struct ipmi_ipmb_dev *iidev)101{102	struct ipmi_smi_msg *imsg = NULL;103	u8 *msg = iidev->rcvmsg;104	bool is_cmd;105	unsigned long flags;106 107	if (iidev->rcvlen == 0)108		return;109	if (!valid_ipmb(iidev))110		goto done;111 112	is_cmd = ((msg[1] >> 2) & 1) == 0;113 114	if (is_cmd) {115		/* Ignore commands until we are up. */116		if (!iidev->ready)117			goto done;118 119		/* It's a command, allocate a message for it. */120		imsg = ipmi_alloc_smi_msg();121		if (!imsg)122			goto done;123		imsg->type = IPMI_SMI_MSG_TYPE_IPMB_DIRECT;124		imsg->data_size = 0;125	} else {126		spin_lock_irqsave(&iidev->lock, flags);127		if (iidev->working_msg) {128			u8 seq = msg[4] >> 2;129			bool xmit_rsp = (iidev->working_msg->data[0] >> 2) & 1;130 131			/*132			 * Responses should carry the sequence we sent133			 * them with.  If it's a transmitted response,134			 * ignore it.  And if the message hasn't been135			 * transmitted, ignore it.136			 */137			if (!xmit_rsp && seq == iidev->curr_seq) {138				iidev->curr_seq = (iidev->curr_seq + 1) & 0x3f;139 140				imsg = iidev->working_msg;141				iidev->working_msg = NULL;142			}143		}144		spin_unlock_irqrestore(&iidev->lock, flags);145	}146 147	if (!imsg)148		goto done;149 150	if (imsg->type == IPMI_SMI_MSG_TYPE_IPMB_DIRECT) {151		imsg->rsp[0] = msg[1]; /* NetFn/LUN */152		/*153		 * Keep the source address, rqSeq.  Drop the trailing154		 * checksum.155		 */156		memcpy(imsg->rsp + 1, msg + 3, iidev->rcvlen - 4);157		imsg->rsp_size = iidev->rcvlen - 3;158	} else {159		imsg->rsp[0] = msg[1]; /* NetFn/LUN */160		/*161		 * Skip the source address, rqSeq.  Drop the trailing162		 * checksum.163		 */164		memcpy(imsg->rsp + 1, msg + 5, iidev->rcvlen - 6);165		imsg->rsp_size = iidev->rcvlen - 5;166	}167	ipmi_smi_msg_received(iidev->intf, imsg);168	if (!is_cmd)169		up(&iidev->got_rsp);170 171done:172	iidev->overrun = false;173	iidev->rcvlen = 0;174}175 176/*177 * The IPMB protocol only supports i2c writes so there is no need to178 * support I2C_SLAVE_READ* events, except to know if the other end has179 * issued a read without going to stop mode.180 */181static int ipmi_ipmb_slave_cb(struct i2c_client *client,182			      enum i2c_slave_event event, u8 *val)183{184	struct ipmi_ipmb_dev *iidev = i2c_get_clientdata(client);185 186	switch (event) {187	case I2C_SLAVE_WRITE_REQUESTED:188		ipmi_ipmb_check_msg_done(iidev);189		/*190		 * First byte is the slave address, to ease the checksum191		 * calculation.192		 */193		iidev->rcvmsg[0] = client->addr << 1;194		iidev->rcvlen = 1;195		break;196 197	case I2C_SLAVE_WRITE_RECEIVED:198		if (iidev->rcvlen >= sizeof(iidev->rcvmsg))199			iidev->overrun = true;200		else201			iidev->rcvmsg[iidev->rcvlen++] = *val;202		break;203 204	case I2C_SLAVE_READ_REQUESTED:205	case I2C_SLAVE_STOP:206		ipmi_ipmb_check_msg_done(iidev);207		break;208 209	case I2C_SLAVE_READ_PROCESSED:210		break;211	}212 213	return 0;214}215 216static void ipmi_ipmb_send_response(struct ipmi_ipmb_dev *iidev,217				    struct ipmi_smi_msg *msg, u8 cc)218{219	if ((msg->data[0] >> 2) & 1) {220		/*221		 * It's a response being sent, we need to return a222		 * response to the response.  Fake a send msg command223		 * response with channel 0.  This will always be ipmb224		 * direct.225		 */226		msg->data[0] = (IPMI_NETFN_APP_REQUEST | 1) << 2;227		msg->data[3] = IPMI_SEND_MSG_CMD;228		msg->data[4] = cc;229		msg->data_size = 5;230	}231	msg->rsp[0] = msg->data[0] | (1 << 2);232	if (msg->type == IPMI_SMI_MSG_TYPE_IPMB_DIRECT) {233		msg->rsp[1] = msg->data[1];234		msg->rsp[2] = msg->data[2];235		msg->rsp[3] = msg->data[3];236		msg->rsp[4] = cc;237		msg->rsp_size = 5;238	} else {239		msg->rsp[1] = msg->data[1];240		msg->rsp[2] = cc;241		msg->rsp_size = 3;242	}243	ipmi_smi_msg_received(iidev->intf, msg);244}245 246static void ipmi_ipmb_format_for_xmit(struct ipmi_ipmb_dev *iidev,247				      struct ipmi_smi_msg *msg)248{249	if (msg->type == IPMI_SMI_MSG_TYPE_IPMB_DIRECT) {250		iidev->xmitmsg[0] = msg->data[1];251		iidev->xmitmsg[1] = msg->data[0];252		memcpy(iidev->xmitmsg + 4, msg->data + 2, msg->data_size - 2);253		iidev->xmitlen = msg->data_size + 2;254	} else {255		iidev->xmitmsg[0] = iidev->bmcaddr;256		iidev->xmitmsg[1] = msg->data[0];257		iidev->xmitmsg[4] = 0;258		memcpy(iidev->xmitmsg + 5, msg->data + 1, msg->data_size - 1);259		iidev->xmitlen = msg->data_size + 4;260	}261	iidev->xmitmsg[3] = iidev->slave->addr << 1;262	if (((msg->data[0] >> 2) & 1) == 0)263		/* If it's a command, put in our own sequence number. */264		iidev->xmitmsg[4] = ((iidev->xmitmsg[4] & 0x03) |265				     (iidev->curr_seq << 2));266 267	/* Now add on the final checksums. */268	iidev->xmitmsg[2] = ipmb_checksum(iidev->xmitmsg, 2);269	iidev->xmitmsg[iidev->xmitlen] =270		ipmb_checksum(iidev->xmitmsg + 3, iidev->xmitlen - 3);271	iidev->xmitlen++;272}273 274static int ipmi_ipmb_thread(void *data)275{276	struct ipmi_ipmb_dev *iidev = data;277 278	while (!kthread_should_stop()) {279		long ret;280		struct i2c_msg i2c_msg;281		struct ipmi_smi_msg *msg = NULL;282		unsigned long flags;283		unsigned int retries = 0;284 285		/* Wait for a message to send */286		ret = down_interruptible(&iidev->wake_thread);287		if (iidev->stopping)288			break;289		if (ret)290			continue;291 292		spin_lock_irqsave(&iidev->lock, flags);293		if (iidev->next_msg) {294			msg = iidev->next_msg;295			iidev->next_msg = NULL;296		}297		spin_unlock_irqrestore(&iidev->lock, flags);298		if (!msg)299			continue;300 301		ipmi_ipmb_format_for_xmit(iidev, msg);302 303retry:304		i2c_msg.len = iidev->xmitlen - 1;305		if (i2c_msg.len > 32) {306			ipmi_ipmb_send_response(iidev, msg,307						IPMI_REQ_LEN_EXCEEDED_ERR);308			continue;309		}310 311		i2c_msg.addr = iidev->xmitmsg[0] >> 1;312		i2c_msg.flags = 0;313		i2c_msg.buf = iidev->xmitmsg + 1;314 315		/* Rely on i2c_transfer for a barrier. */316		iidev->working_msg = msg;317 318		ret = i2c_transfer(iidev->client->adapter, &i2c_msg, 1);319 320		if ((msg->data[0] >> 2) & 1) {321			/*322			 * It's a response, nothing will be returned323			 * by the other end.324			 */325 326			iidev->working_msg = NULL;327			ipmi_ipmb_send_response(iidev, msg,328						ret < 0 ? IPMI_BUS_ERR : 0);329			continue;330		}331		if (ret < 0) {332			iidev->working_msg = NULL;333			ipmi_ipmb_send_response(iidev, msg, IPMI_BUS_ERR);334			continue;335		}336 337		/* A command was sent, wait for its response. */338		ret = down_timeout(&iidev->got_rsp,339				   msecs_to_jiffies(iidev->retry_time_ms));340 341		/*342		 * Grab the message if we can.  If the handler hasn't343		 * already handled it, the message will still be there.344		 */345		spin_lock_irqsave(&iidev->lock, flags);346		msg = iidev->working_msg;347		iidev->working_msg = NULL;348		spin_unlock_irqrestore(&iidev->lock, flags);349 350		if (!msg && ret) {351			/*352			 * If working_msg is not set and we timed out,353			 * that means the message grabbed by354			 * check_msg_done before we could grab it355			 * here.  Wait again for check_msg_done to up356			 * the semaphore.357			 */358			down(&iidev->got_rsp);359		} else if (msg && ++retries <= iidev->max_retries) {360			spin_lock_irqsave(&iidev->lock, flags);361			iidev->working_msg = msg;362			spin_unlock_irqrestore(&iidev->lock, flags);363			goto retry;364		}365 366		if (msg)367			ipmi_ipmb_send_response(iidev, msg, IPMI_TIMEOUT_ERR);368	}369 370	if (iidev->next_msg)371		/* Return an unspecified error. */372		ipmi_ipmb_send_response(iidev, iidev->next_msg, 0xff);373 374	return 0;375}376 377static int ipmi_ipmb_start_processing(void *send_info,378				      struct ipmi_smi *new_intf)379{380	struct ipmi_ipmb_dev *iidev = send_info;381 382	iidev->intf = new_intf;383	iidev->ready = true;384	return 0;385}386 387static void ipmi_ipmb_stop_thread(struct ipmi_ipmb_dev *iidev)388{389	if (iidev->thread) {390		struct task_struct *t = iidev->thread;391 392		iidev->thread = NULL;393		iidev->stopping = true;394		up(&iidev->wake_thread);395		up(&iidev->got_rsp);396		kthread_stop(t);397	}398}399 400static void ipmi_ipmb_shutdown(void *send_info)401{402	struct ipmi_ipmb_dev *iidev = send_info;403 404	ipmi_ipmb_stop_thread(iidev);405}406 407static void ipmi_ipmb_sender(void *send_info,408			     struct ipmi_smi_msg *msg)409{410	struct ipmi_ipmb_dev *iidev = send_info;411	unsigned long flags;412 413	spin_lock_irqsave(&iidev->lock, flags);414	BUG_ON(iidev->next_msg);415 416	iidev->next_msg = msg;417	spin_unlock_irqrestore(&iidev->lock, flags);418 419	up(&iidev->wake_thread);420}421 422static void ipmi_ipmb_request_events(void *send_info)423{424	/* We don't fetch events here. */425}426 427static void ipmi_ipmb_cleanup(struct ipmi_ipmb_dev *iidev)428{429	if (iidev->slave) {430		i2c_slave_unregister(iidev->slave);431		if (iidev->slave != iidev->client)432			i2c_unregister_device(iidev->slave);433	}434	iidev->slave = NULL;435	iidev->client = NULL;436	ipmi_ipmb_stop_thread(iidev);437}438 439static void ipmi_ipmb_remove(struct i2c_client *client)440{441	struct ipmi_ipmb_dev *iidev = i2c_get_clientdata(client);442 443	ipmi_ipmb_cleanup(iidev);444	ipmi_unregister_smi(iidev->intf);445}446 447static int ipmi_ipmb_probe(struct i2c_client *client)448{449	struct device *dev = &client->dev;450	struct ipmi_ipmb_dev *iidev;451	struct device_node *slave_np;452	struct i2c_adapter *slave_adap = NULL;453	struct i2c_client *slave = NULL;454	int rv;455 456	iidev = devm_kzalloc(&client->dev, sizeof(*iidev), GFP_KERNEL);457	if (!iidev)458		return -ENOMEM;459 460	if (of_property_read_u8(dev->of_node, "bmcaddr", &iidev->bmcaddr) != 0)461		iidev->bmcaddr = bmcaddr;462	if (iidev->bmcaddr == 0 || iidev->bmcaddr & 1) {463		/* Can't have the write bit set. */464		dev_notice(&client->dev,465			   "Invalid bmc address value %2.2x\n", iidev->bmcaddr);466		return -EINVAL;467	}468 469	if (of_property_read_u32(dev->of_node, "retry-time",470				 &iidev->retry_time_ms) != 0)471		iidev->retry_time_ms = retry_time_ms;472 473	if (of_property_read_u32(dev->of_node, "max-retries",474				 &iidev->max_retries) != 0)475		iidev->max_retries = max_retries;476 477	slave_np = of_parse_phandle(dev->of_node, "slave-dev", 0);478	if (slave_np) {479		slave_adap = of_get_i2c_adapter_by_node(slave_np);480		of_node_put(slave_np);481		if (!slave_adap) {482			dev_notice(&client->dev,483				   "Could not find slave adapter\n");484			return -EINVAL;485		}486	}487 488	iidev->client = client;489 490	if (slave_adap) {491		struct i2c_board_info binfo;492 493		memset(&binfo, 0, sizeof(binfo));494		strscpy(binfo.type, "ipmb-slave", I2C_NAME_SIZE);495		binfo.addr = client->addr;496		binfo.flags = I2C_CLIENT_SLAVE;497		slave = i2c_new_client_device(slave_adap, &binfo);498		i2c_put_adapter(slave_adap);499		if (IS_ERR(slave)) {500			rv = PTR_ERR(slave);501			dev_notice(&client->dev,502				   "Could not allocate slave device: %d\n", rv);503			return rv;504		}505		i2c_set_clientdata(slave, iidev);506	} else {507		slave = client;508	}509	i2c_set_clientdata(client, iidev);510	slave->flags |= I2C_CLIENT_SLAVE;511 512	rv = i2c_slave_register(slave, ipmi_ipmb_slave_cb);513	if (rv)514		goto out_err;515	iidev->slave = slave;516	slave = NULL;517 518	iidev->handlers.flags = IPMI_SMI_CAN_HANDLE_IPMB_DIRECT;519	iidev->handlers.start_processing = ipmi_ipmb_start_processing;520	iidev->handlers.shutdown = ipmi_ipmb_shutdown;521	iidev->handlers.sender = ipmi_ipmb_sender;522	iidev->handlers.request_events = ipmi_ipmb_request_events;523 524	spin_lock_init(&iidev->lock);525	sema_init(&iidev->wake_thread, 0);526	sema_init(&iidev->got_rsp, 0);527 528	iidev->thread = kthread_run(ipmi_ipmb_thread, iidev,529				    "kipmb%4.4x", client->addr);530	if (IS_ERR(iidev->thread)) {531		rv = PTR_ERR(iidev->thread);532		dev_notice(&client->dev,533			   "Could not start kernel thread: error %d\n", rv);534		goto out_err;535	}536 537	rv = ipmi_register_smi(&iidev->handlers,538			       iidev,539			       &client->dev,540			       iidev->bmcaddr);541	if (rv)542		goto out_err;543 544	return 0;545 546out_err:547	if (slave && slave != client)548		i2c_unregister_device(slave);549	ipmi_ipmb_cleanup(iidev);550	return rv;551}552 553#ifdef CONFIG_OF554static const struct of_device_id of_ipmi_ipmb_match[] = {555	{ .type = "ipmi", .compatible = DEVICE_NAME },556	{},557};558MODULE_DEVICE_TABLE(of, of_ipmi_ipmb_match);559#else560#define of_ipmi_ipmb_match NULL561#endif562 563static const struct i2c_device_id ipmi_ipmb_id[] = {564	{ DEVICE_NAME },565	{}566};567MODULE_DEVICE_TABLE(i2c, ipmi_ipmb_id);568 569static struct i2c_driver ipmi_ipmb_driver = {570	.class		= I2C_CLASS_HWMON,571	.driver = {572		.name = DEVICE_NAME,573		.of_match_table = of_ipmi_ipmb_match,574	},575	.probe		= ipmi_ipmb_probe,576	.remove		= ipmi_ipmb_remove,577	.id_table	= ipmi_ipmb_id,578};579module_i2c_driver(ipmi_ipmb_driver);580 581MODULE_AUTHOR("Corey Minyard");582MODULE_DESCRIPTION("IPMI IPMB driver");583MODULE_LICENSE("GPL v2");584