Lines Matching +full:ipmi +full:- +full:ipmb

1 // SPDX-License-Identifier: GPL-2.0
4 * Driver to talk to a remote management controller on IPMB.
22 #define DEVICE_NAME "ipmi-ipmb"
74 u8 *msg = iidev->rcvmsg; in valid_ipmb()
77 if (iidev->overrun) in valid_ipmb()
81 if (iidev->rcvlen < 7) in valid_ipmb()
88 if (iidev->rcvlen < 8) in valid_ipmb()
94 if (ipmb_checksum(msg + 3, iidev->rcvlen - 3) != 0) in valid_ipmb()
103 u8 *msg = iidev->rcvmsg; in ipmi_ipmb_check_msg_done()
107 if (iidev->rcvlen == 0) in ipmi_ipmb_check_msg_done()
116 if (!iidev->ready) in ipmi_ipmb_check_msg_done()
123 imsg->type = IPMI_SMI_MSG_TYPE_IPMB_DIRECT; in ipmi_ipmb_check_msg_done()
124 imsg->data_size = 0; in ipmi_ipmb_check_msg_done()
126 spin_lock_irqsave(&iidev->lock, flags); in ipmi_ipmb_check_msg_done()
127 if (iidev->working_msg) { in ipmi_ipmb_check_msg_done()
129 bool xmit_rsp = (iidev->working_msg->data[0] >> 2) & 1; in ipmi_ipmb_check_msg_done()
137 if (!xmit_rsp && seq == iidev->curr_seq) { in ipmi_ipmb_check_msg_done()
138 iidev->curr_seq = (iidev->curr_seq + 1) & 0x3f; in ipmi_ipmb_check_msg_done()
140 imsg = iidev->working_msg; in ipmi_ipmb_check_msg_done()
141 iidev->working_msg = NULL; in ipmi_ipmb_check_msg_done()
144 spin_unlock_irqrestore(&iidev->lock, flags); in ipmi_ipmb_check_msg_done()
150 if (imsg->type == IPMI_SMI_MSG_TYPE_IPMB_DIRECT) { in ipmi_ipmb_check_msg_done()
151 imsg->rsp[0] = msg[1]; /* NetFn/LUN */ in ipmi_ipmb_check_msg_done()
156 memcpy(imsg->rsp + 1, msg + 3, iidev->rcvlen - 4); in ipmi_ipmb_check_msg_done()
157 imsg->rsp_size = iidev->rcvlen - 3; in ipmi_ipmb_check_msg_done()
159 imsg->rsp[0] = msg[1]; /* NetFn/LUN */ in ipmi_ipmb_check_msg_done()
164 memcpy(imsg->rsp + 1, msg + 5, iidev->rcvlen - 6); in ipmi_ipmb_check_msg_done()
165 imsg->rsp_size = iidev->rcvlen - 5; in ipmi_ipmb_check_msg_done()
167 ipmi_smi_msg_received(iidev->intf, imsg); in ipmi_ipmb_check_msg_done()
169 up(&iidev->got_rsp); in ipmi_ipmb_check_msg_done()
172 iidev->overrun = false; in ipmi_ipmb_check_msg_done()
173 iidev->rcvlen = 0; in ipmi_ipmb_check_msg_done()
177 * The IPMB protocol only supports i2c writes so there is no need to
193 iidev->rcvmsg[0] = client->addr << 1; in ipmi_ipmb_slave_cb()
194 iidev->rcvlen = 1; in ipmi_ipmb_slave_cb()
198 if (iidev->rcvlen >= sizeof(iidev->rcvmsg)) in ipmi_ipmb_slave_cb()
199 iidev->overrun = true; in ipmi_ipmb_slave_cb()
201 iidev->rcvmsg[iidev->rcvlen++] = *val; in ipmi_ipmb_slave_cb()
219 if ((msg->data[0] >> 2) & 1) { in ipmi_ipmb_send_response()
223 * response with channel 0. This will always be ipmb in ipmi_ipmb_send_response()
226 msg->data[0] = (IPMI_NETFN_APP_REQUEST | 1) << 2; in ipmi_ipmb_send_response()
227 msg->data[3] = IPMI_SEND_MSG_CMD; in ipmi_ipmb_send_response()
228 msg->data[4] = cc; in ipmi_ipmb_send_response()
229 msg->data_size = 5; in ipmi_ipmb_send_response()
231 msg->rsp[0] = msg->data[0] | (1 << 2); in ipmi_ipmb_send_response()
232 if (msg->type == IPMI_SMI_MSG_TYPE_IPMB_DIRECT) { in ipmi_ipmb_send_response()
233 msg->rsp[1] = msg->data[1]; in ipmi_ipmb_send_response()
234 msg->rsp[2] = msg->data[2]; in ipmi_ipmb_send_response()
235 msg->rsp[3] = msg->data[3]; in ipmi_ipmb_send_response()
236 msg->rsp[4] = cc; in ipmi_ipmb_send_response()
237 msg->rsp_size = 5; in ipmi_ipmb_send_response()
239 msg->rsp[1] = msg->data[1]; in ipmi_ipmb_send_response()
240 msg->rsp[2] = cc; in ipmi_ipmb_send_response()
241 msg->rsp_size = 3; in ipmi_ipmb_send_response()
243 ipmi_smi_msg_received(iidev->intf, msg); in ipmi_ipmb_send_response()
249 if (msg->type == IPMI_SMI_MSG_TYPE_IPMB_DIRECT) { in ipmi_ipmb_format_for_xmit()
250 iidev->xmitmsg[0] = msg->data[1]; in ipmi_ipmb_format_for_xmit()
251 iidev->xmitmsg[1] = msg->data[0]; in ipmi_ipmb_format_for_xmit()
252 memcpy(iidev->xmitmsg + 4, msg->data + 2, msg->data_size - 2); in ipmi_ipmb_format_for_xmit()
253 iidev->xmitlen = msg->data_size + 2; in ipmi_ipmb_format_for_xmit()
255 iidev->xmitmsg[0] = iidev->bmcaddr; in ipmi_ipmb_format_for_xmit()
256 iidev->xmitmsg[1] = msg->data[0]; in ipmi_ipmb_format_for_xmit()
257 iidev->xmitmsg[4] = 0; in ipmi_ipmb_format_for_xmit()
258 memcpy(iidev->xmitmsg + 5, msg->data + 1, msg->data_size - 1); in ipmi_ipmb_format_for_xmit()
259 iidev->xmitlen = msg->data_size + 4; in ipmi_ipmb_format_for_xmit()
261 iidev->xmitmsg[3] = iidev->slave->addr << 1; in ipmi_ipmb_format_for_xmit()
262 if (((msg->data[0] >> 2) & 1) == 0) in ipmi_ipmb_format_for_xmit()
264 iidev->xmitmsg[4] = ((iidev->xmitmsg[4] & 0x03) | in ipmi_ipmb_format_for_xmit()
265 (iidev->curr_seq << 2)); in ipmi_ipmb_format_for_xmit()
268 iidev->xmitmsg[2] = ipmb_checksum(iidev->xmitmsg, 2); in ipmi_ipmb_format_for_xmit()
269 iidev->xmitmsg[iidev->xmitlen] = in ipmi_ipmb_format_for_xmit()
270 ipmb_checksum(iidev->xmitmsg + 3, iidev->xmitlen - 3); in ipmi_ipmb_format_for_xmit()
271 iidev->xmitlen++; in ipmi_ipmb_format_for_xmit()
286 ret = down_interruptible(&iidev->wake_thread); in ipmi_ipmb_thread()
287 if (iidev->stopping) in ipmi_ipmb_thread()
292 spin_lock_irqsave(&iidev->lock, flags); in ipmi_ipmb_thread()
293 if (iidev->next_msg) { in ipmi_ipmb_thread()
294 msg = iidev->next_msg; in ipmi_ipmb_thread()
295 iidev->next_msg = NULL; in ipmi_ipmb_thread()
297 spin_unlock_irqrestore(&iidev->lock, flags); in ipmi_ipmb_thread()
304 i2c_msg.len = iidev->xmitlen - 1; in ipmi_ipmb_thread()
311 i2c_msg.addr = iidev->xmitmsg[0] >> 1; in ipmi_ipmb_thread()
313 i2c_msg.buf = iidev->xmitmsg + 1; in ipmi_ipmb_thread()
316 iidev->working_msg = msg; in ipmi_ipmb_thread()
318 ret = i2c_transfer(iidev->client->adapter, &i2c_msg, 1); in ipmi_ipmb_thread()
320 if ((msg->data[0] >> 2) & 1) { in ipmi_ipmb_thread()
326 iidev->working_msg = NULL; in ipmi_ipmb_thread()
332 iidev->working_msg = NULL; in ipmi_ipmb_thread()
338 ret = down_timeout(&iidev->got_rsp, in ipmi_ipmb_thread()
339 msecs_to_jiffies(iidev->retry_time_ms)); in ipmi_ipmb_thread()
345 spin_lock_irqsave(&iidev->lock, flags); in ipmi_ipmb_thread()
346 msg = iidev->working_msg; in ipmi_ipmb_thread()
347 iidev->working_msg = NULL; in ipmi_ipmb_thread()
348 spin_unlock_irqrestore(&iidev->lock, flags); in ipmi_ipmb_thread()
358 down(&iidev->got_rsp); in ipmi_ipmb_thread()
359 } else if (msg && ++retries <= iidev->max_retries) { in ipmi_ipmb_thread()
360 spin_lock_irqsave(&iidev->lock, flags); in ipmi_ipmb_thread()
361 iidev->working_msg = msg; in ipmi_ipmb_thread()
362 spin_unlock_irqrestore(&iidev->lock, flags); in ipmi_ipmb_thread()
370 if (iidev->next_msg) in ipmi_ipmb_thread()
372 ipmi_ipmb_send_response(iidev, iidev->next_msg, 0xff); in ipmi_ipmb_thread()
382 iidev->intf = new_intf; in ipmi_ipmb_start_processing()
383 iidev->ready = true; in ipmi_ipmb_start_processing()
389 if (iidev->thread) { in ipmi_ipmb_stop_thread()
390 struct task_struct *t = iidev->thread; in ipmi_ipmb_stop_thread()
392 iidev->thread = NULL; in ipmi_ipmb_stop_thread()
393 iidev->stopping = true; in ipmi_ipmb_stop_thread()
394 up(&iidev->wake_thread); in ipmi_ipmb_stop_thread()
395 up(&iidev->got_rsp); in ipmi_ipmb_stop_thread()
413 spin_lock_irqsave(&iidev->lock, flags); in ipmi_ipmb_sender()
414 BUG_ON(iidev->next_msg); in ipmi_ipmb_sender()
416 iidev->next_msg = msg; in ipmi_ipmb_sender()
417 spin_unlock_irqrestore(&iidev->lock, flags); in ipmi_ipmb_sender()
419 up(&iidev->wake_thread); in ipmi_ipmb_sender()
429 if (iidev->slave) { in ipmi_ipmb_cleanup()
430 i2c_slave_unregister(iidev->slave); in ipmi_ipmb_cleanup()
431 if (iidev->slave != iidev->client) in ipmi_ipmb_cleanup()
432 i2c_unregister_device(iidev->slave); in ipmi_ipmb_cleanup()
434 iidev->slave = NULL; in ipmi_ipmb_cleanup()
435 iidev->client = NULL; in ipmi_ipmb_cleanup()
444 ipmi_unregister_smi(iidev->intf); in ipmi_ipmb_remove()
449 struct device *dev = &client->dev; in ipmi_ipmb_probe()
456 iidev = devm_kzalloc(&client->dev, sizeof(*iidev), GFP_KERNEL); in ipmi_ipmb_probe()
458 return -ENOMEM; in ipmi_ipmb_probe()
460 if (of_property_read_u8(dev->of_node, "bmcaddr", &iidev->bmcaddr) != 0) in ipmi_ipmb_probe()
461 iidev->bmcaddr = bmcaddr; in ipmi_ipmb_probe()
462 if (iidev->bmcaddr == 0 || iidev->bmcaddr & 1) { in ipmi_ipmb_probe()
464 dev_notice(&client->dev, in ipmi_ipmb_probe()
465 "Invalid bmc address value %2.2x\n", iidev->bmcaddr); in ipmi_ipmb_probe()
466 return -EINVAL; in ipmi_ipmb_probe()
469 if (of_property_read_u32(dev->of_node, "retry-time", in ipmi_ipmb_probe()
470 &iidev->retry_time_ms) != 0) in ipmi_ipmb_probe()
471 iidev->retry_time_ms = retry_time_ms; in ipmi_ipmb_probe()
473 if (of_property_read_u32(dev->of_node, "max-retries", in ipmi_ipmb_probe()
474 &iidev->max_retries) != 0) in ipmi_ipmb_probe()
475 iidev->max_retries = max_retries; in ipmi_ipmb_probe()
477 slave_np = of_parse_phandle(dev->of_node, "slave-dev", 0); in ipmi_ipmb_probe()
482 dev_notice(&client->dev, in ipmi_ipmb_probe()
484 return -EINVAL; in ipmi_ipmb_probe()
488 iidev->client = client; in ipmi_ipmb_probe()
494 strscpy(binfo.type, "ipmb-slave", I2C_NAME_SIZE); in ipmi_ipmb_probe()
495 binfo.addr = client->addr; in ipmi_ipmb_probe()
501 dev_notice(&client->dev, in ipmi_ipmb_probe()
510 slave->flags |= I2C_CLIENT_SLAVE; in ipmi_ipmb_probe()
515 iidev->slave = slave; in ipmi_ipmb_probe()
518 iidev->handlers.flags = IPMI_SMI_CAN_HANDLE_IPMB_DIRECT; in ipmi_ipmb_probe()
519 iidev->handlers.start_processing = ipmi_ipmb_start_processing; in ipmi_ipmb_probe()
520 iidev->handlers.shutdown = ipmi_ipmb_shutdown; in ipmi_ipmb_probe()
521 iidev->handlers.sender = ipmi_ipmb_sender; in ipmi_ipmb_probe()
522 iidev->handlers.request_events = ipmi_ipmb_request_events; in ipmi_ipmb_probe()
524 spin_lock_init(&iidev->lock); in ipmi_ipmb_probe()
525 sema_init(&iidev->wake_thread, 0); in ipmi_ipmb_probe()
526 sema_init(&iidev->got_rsp, 0); in ipmi_ipmb_probe()
528 iidev->thread = kthread_run(ipmi_ipmb_thread, iidev, in ipmi_ipmb_probe()
529 "kipmb%4.4x", client->addr); in ipmi_ipmb_probe()
530 if (IS_ERR(iidev->thread)) { in ipmi_ipmb_probe()
531 rv = PTR_ERR(iidev->thread); in ipmi_ipmb_probe()
532 dev_notice(&client->dev, in ipmi_ipmb_probe()
537 rv = ipmi_register_smi(&iidev->handlers, in ipmi_ipmb_probe()
539 &client->dev, in ipmi_ipmb_probe()
540 iidev->bmcaddr); in ipmi_ipmb_probe()
555 { .type = "ipmi", .compatible = DEVICE_NAME },
582 MODULE_DESCRIPTION("IPMI IPMB driver");