1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720
|
// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
/*
* Block Transfer, typically what IPMI goes over
*
* Copyright 2013-2019 IBM Corp.
*/
#define pr_fmt(fmt) "BT: " fmt
#include <skiboot.h>
#include <lpc.h>
#include <lock.h>
#include <device.h>
#include <timebase.h>
#include <ipmi.h>
#include <bt.h>
#include <timer.h>
#include <ipmi.h>
#include <timebase.h>
#include <chip.h>
#include <interrupts.h>
/* BT registers */
#define BT_CTRL 0
#define BT_CTRL_B_BUSY 0x80
#define BT_CTRL_H_BUSY 0x40
#define BT_CTRL_OEM0 0x20
#define BT_CTRL_SMS_ATN 0x10
#define BT_CTRL_B2H_ATN 0x08
#define BT_CTRL_H2B_ATN 0x04
#define BT_CTRL_CLR_RD_PTR 0x02
#define BT_CTRL_CLR_WR_PTR 0x01
#define BT_HOST2BMC 1
#define BT_INTMASK 2
#define BT_INTMASK_B2H_IRQEN 0x01
#define BT_INTMASK_B2H_IRQ 0x02
#define BT_INTMASK_BMC_HWRST 0x80
/* Maximum size of the HW FIFO */
#define BT_FIFO_LEN 64
/* Default poll interval before interrupts are working */
#define BT_DEFAULT_POLL_MS 200
/*
* Minimum size of an IPMI request/response including
* mandatory headers.
*/
#define BT_MIN_REQ_LEN 3
#define BT_MIN_RESP_LEN 4
/* How long (in uS) to poll for new ipmi data. */
#define POLL_TIMEOUT 10000
/* Maximum number of outstanding messages to allow in the queue. */
#define BT_MAX_QUEUE_LEN 10
/* How long (in seconds) before a message is timed out. */
#define BT_MSG_TIMEOUT 3
/* Maximum number of times to attempt sending a message before giving up. */
#define BT_MAX_RETRIES 1
/* Macro to enable printing BT message queue for debug */
#define BT_QUEUE_DEBUG 0
/* BT message logging macros */
#define _BT_Q_LOG(level, msg, fmt, args...) \
do { if (msg) \
prlog(level, "seq 0x%02x netfn 0x%02x cmd 0x%02x: " fmt "\n", \
(msg)->seq, ((msg)->ipmi_msg.netfn >> 2), (msg)->ipmi_msg.cmd, ##args); \
else \
prlog(level, "seq 0x?? netfn 0x?? cmd 0x??: " fmt "\n", ##args); \
} while (0)
#define BT_Q_ERR(msg, fmt, args...) \
_BT_Q_LOG(PR_ERR, msg, fmt, ##args)
#define BT_Q_DBG(msg, fmt, args...) \
_BT_Q_LOG(PR_DEBUG, msg, fmt, ##args)
#define BT_Q_TRACE(msg, fmt, args...) \
_BT_Q_LOG(PR_TRACE, msg, fmt, ##args)
struct bt_msg {
struct list_node link;
unsigned long tb;
uint8_t seq;
uint8_t send_count;
bool disable_retry;
struct ipmi_msg ipmi_msg;
};
struct bt_caps {
uint8_t num_requests;
uint16_t input_buf_len;
uint16_t output_buf_len;
uint8_t msg_timeout;
uint8_t max_retries;
};
struct bt {
uint32_t base_addr;
struct lock lock;
struct list_head msgq;
struct list_head msgq_sync; /* separate list for synchronous messages */
struct timer poller;
bool irq_ok;
int queue_len;
struct bt_caps caps;
};
static struct bt bt;
static struct bt_msg *inflight_bt_msg; /* Holds in flight message */
static int ipmi_seq;
static inline uint8_t bt_inb(uint32_t reg)
{
return lpc_inb(bt.base_addr + reg);
}
static inline void bt_outb(uint8_t data, uint32_t reg)
{
lpc_outb(data, bt.base_addr + reg);
}
static inline void bt_set_h_busy(bool value)
{
uint8_t rval;
rval = bt_inb(BT_CTRL);
if (value != !!(rval & BT_CTRL_H_BUSY))
bt_outb(BT_CTRL_H_BUSY, BT_CTRL);
}
static inline void bt_assert_h_busy(void)
{
uint8_t rval;
rval = bt_inb(BT_CTRL);
assert(rval & BT_CTRL_H_BUSY);
}
static void get_bt_caps_complete(struct ipmi_msg *msg)
{
/* Ignore errors, we'll fallback to using the defaults, no big deal */
if (msg->data[0] == 0) {
prlog(PR_DEBUG, "Got illegal BMC BT capability\n");
goto out;
}
if (msg->data[1] != BT_FIFO_LEN) {
prlog(PR_DEBUG, "Got a input buffer len (%u) cap which differs from the default\n",
msg->data[1]);
}
if (msg->data[2] != BT_FIFO_LEN) {
prlog(PR_DEBUG, "Got a output buffer len (%u) cap which differs from the default\n",
msg->data[2]);
}
/*
* IPMI Spec says that the value for buffer sizes are:
* "the largest value allowed in first byte"
* Therefore we want to add one to what we get
*/
bt.caps.num_requests = msg->data[0];
bt.caps.input_buf_len = msg->data[1] + 1;
bt.caps.output_buf_len = msg->data[2] + 1;
bt.caps.msg_timeout = msg->data[3];
bt.caps.max_retries = msg->data[4];
prlog(PR_DEBUG, "BMC BT capabilities received:\n");
prlog(PR_DEBUG, "buffer sizes: %d input %d output\n",
bt.caps.input_buf_len, bt.caps.output_buf_len);
prlog(PR_DEBUG, "number of requests: %d\n", bt.caps.num_requests);
prlog(PR_DEBUG, "msg timeout: %d max retries: %d\n",
bt.caps.msg_timeout, bt.caps.max_retries);
out:
ipmi_free_msg(msg);
}
static void get_bt_caps(void)
{
struct ipmi_msg *bmc_caps;
/*
* Didn't sent a message, now is a good time to ask the BMC for its
* capabilities.
*/
bmc_caps = ipmi_mkmsg(IPMI_DEFAULT_INTERFACE, IPMI_GET_BT_CAPS,
get_bt_caps_complete, NULL, NULL, 0, sizeof(struct bt_caps));
if (!bmc_caps)
prerror("Couldn't create BMC BT capabilities msg\n");
if (bmc_caps && ipmi_queue_msg(bmc_caps))
prerror("Couldn't enqueue request for BMC BT capabilities\n");
/* Ignore errors, we'll fallback to using the defaults, no big deal */
}
static inline bool bt_idle(void)
{
uint8_t bt_ctrl = bt_inb(BT_CTRL);
return !(bt_ctrl & BT_CTRL_B_BUSY) && !(bt_ctrl & BT_CTRL_H2B_ATN);
}
/* Must be called with bt.lock held */
static void bt_msg_del(struct bt_msg *bt_msg)
{
list_del(&bt_msg->link);
bt.queue_len--;
/* once inflight_bt_msg out of list, it should be emptyed */
if (bt_msg == inflight_bt_msg)
inflight_bt_msg = NULL;
unlock(&bt.lock);
ipmi_cmd_done(bt_msg->ipmi_msg.cmd,
IPMI_NETFN_RETURN_CODE(bt_msg->ipmi_msg.netfn),
IPMI_TIMEOUT_ERR, &bt_msg->ipmi_msg);
lock(&bt.lock);
}
static void bt_init_interface(void)
{
/* Clear interrupt condition & enable irq */
bt_outb(BT_INTMASK_B2H_IRQ | BT_INTMASK_B2H_IRQEN, BT_INTMASK);
/* Take care of a stable H_BUSY if any */
bt_set_h_busy(false);
}
static void bt_reset_interface(void)
{
bt_outb(BT_INTMASK_BMC_HWRST, BT_INTMASK);
bt_init_interface();
}
/*
* Try and send a message from the message queue. Caller must hold
* bt.bt_lock and bt.lock and ensue the message queue is not
* empty.
*/
static void bt_send_msg(struct bt_msg *bt_msg)
{
int i;
struct ipmi_msg *ipmi_msg;
ipmi_msg = &bt_msg->ipmi_msg;
/* Send the message */
bt_outb(BT_CTRL_CLR_WR_PTR, BT_CTRL);
/* Byte 1 - Length */
bt_outb(ipmi_msg->req_size + BT_MIN_REQ_LEN, BT_HOST2BMC);
/* Byte 2 - NetFn/LUN */
bt_outb(ipmi_msg->netfn, BT_HOST2BMC);
/* Byte 3 - Seq */
bt_outb(bt_msg->seq, BT_HOST2BMC);
/* Byte 4 - Cmd */
bt_outb(ipmi_msg->cmd, BT_HOST2BMC);
/* Byte 5:N - Data */
for (i = 0; i < ipmi_msg->req_size; i++)
bt_outb(ipmi_msg->data[i], BT_HOST2BMC);
BT_Q_TRACE(bt_msg, "Message sent to host");
bt_msg->send_count++;
bt_outb(BT_CTRL_H2B_ATN, BT_CTRL);
return;
}
static void bt_clear_fifo(void)
{
int i;
for (i = 0; i < bt.caps.input_buf_len; i++)
bt_outb(0xff, BT_HOST2BMC);
}
static void bt_flush_msg(void)
{
bt_assert_h_busy();
bt_outb(BT_CTRL_B2H_ATN | BT_CTRL_CLR_RD_PTR | BT_CTRL_CLR_WR_PTR, BT_CTRL);
bt_clear_fifo();
/* Can't hurt to clear the write pointer again, just to be sure */
bt_outb(BT_CTRL_CLR_WR_PTR, BT_CTRL);
bt_set_h_busy(false);
}
static void bt_get_resp(void)
{
int i;
struct ipmi_msg *ipmi_msg;
uint8_t resp_len, netfn, seq, cmd;
uint8_t cc = IPMI_CC_NO_ERROR;
/* Indicate to the BMC that we are busy */
bt_set_h_busy(true);
/* Clear B2H_ATN and read pointer */
bt_outb(BT_CTRL_B2H_ATN, BT_CTRL);
bt_outb(BT_CTRL_CLR_RD_PTR, BT_CTRL);
/* Read the response */
/* Byte 1 - Length (includes header size) */
resp_len = bt_inb(BT_HOST2BMC) - BT_MIN_RESP_LEN;
/* Byte 2 - NetFn/LUN */
netfn = bt_inb(BT_HOST2BMC);
/* Byte 3 - Seq */
seq = bt_inb(BT_HOST2BMC);
/* Byte 4 - Cmd */
cmd = bt_inb(BT_HOST2BMC);
/* Byte 5 - Completion Code */
cc = bt_inb(BT_HOST2BMC);
/* Find the corresponding message */
if (inflight_bt_msg == NULL || inflight_bt_msg->seq != seq) {
/* A response to a message we no longer care about. */
prlog(PR_INFO, "Nobody cared about a response to an BT/IPMI message"
"(seq 0x%02x netfn 0x%02x cmd 0x%02x)\n", seq, (netfn >> 2), cmd);
bt_flush_msg();
return;
}
ipmi_msg = &inflight_bt_msg->ipmi_msg;
/*
* Make sure we have enough room to store the response. As all values
* are unsigned we will also trigger this error if
* bt_inb(BT_HOST2BMC) < BT_MIN_RESP_LEN (which should never occur).
*/
if (resp_len > ipmi_msg->resp_size) {
BT_Q_ERR(inflight_bt_msg, "Invalid resp_len %d", resp_len);
resp_len = ipmi_msg->resp_size;
cc = IPMI_ERR_MSG_TRUNCATED;
}
ipmi_msg->resp_size = resp_len;
/* Byte 6:N - Data */
for (i = 0; i < resp_len; i++)
ipmi_msg->data[i] = bt_inb(BT_HOST2BMC);
bt_set_h_busy(false);
BT_Q_TRACE(inflight_bt_msg, "IPMI MSG done");
list_del(&inflight_bt_msg->link);
/* Ready to send next message */
inflight_bt_msg = NULL;
bt.queue_len--;
unlock(&bt.lock);
/* Call IPMI layer to finish processing the message. */
ipmi_cmd_done(cmd, netfn, cc, ipmi_msg);
lock(&bt.lock);
return;
}
static void bt_expire_old_msg(uint64_t tb)
{
struct bt_msg *bt_msg = inflight_bt_msg;
if (bt_msg && bt_msg->tb > 0 && !chip_quirk(QUIRK_SIMICS) &&
(tb_compare(tb, bt_msg->tb +
secs_to_tb(bt.caps.msg_timeout)) == TB_AAFTERB)) {
if (bt_msg->send_count <= bt.caps.max_retries &&
!bt_msg->disable_retry) {
/* A message timeout is usually due to the BMC
* clearing the H2B_ATN flag without actually
* doing anything. The data will still be in the
* FIFO so just reset the flag.*/
BT_Q_ERR(bt_msg, "Retry sending message");
/* This means we have started message timeout, but not
* yet sent message to BMC as driver was not free to
* send message. Lets resend message.
*/
if (bt_msg->send_count == 0)
bt_send_msg(bt_msg);
else
bt_outb(BT_CTRL_H2B_ATN, BT_CTRL);
bt_msg->send_count++;
bt_msg->tb = tb;
} else {
BT_Q_ERR(bt_msg, "Timeout sending message");
bt_msg_del(bt_msg);
/*
* Timing out a message is inherently racy as the BMC
* may start writing just as we decide to kill the
* message. Hopefully resetting the interface is
* sufficient to guard against such things.
*/
bt_reset_interface();
}
}
}
#if BT_QUEUE_DEBUG
static void print_debug_queue_info(void)
{
struct bt_msg *msg;
static bool printed;
if (!list_empty(&bt.msgq_sync) || !list_empty(&bt.msgq)) {
printed = false;
prlog(PR_DEBUG, "-------- BT Sync Msg Queue -------\n");
list_for_each(&bt.msgq_sync, msg, link) {
BT_Q_DBG(msg, "[ sent %d ]", msg->send_count);
}
prlog(PR_DEBUG, "---------- BT Msg Queue ----------\n");
list_for_each(&bt.msgq, msg, link) {
BT_Q_DBG(msg, "[ sent %d ]", msg->send_count);
}
prlog(PR_DEBUG, "----------------------------------\n");
} else if (!printed) {
printed = true;
prlog(PR_DEBUG, "------- BT Msg Queue Empty -------\n");
}
}
#endif
static void bt_send_and_unlock(void)
{
/* Busy? */
if (inflight_bt_msg)
goto out_unlock;
if (!lpc_ok())
goto out_unlock;
/* Synchronous messages gets priority over normal message */
if (!list_empty(&bt.msgq_sync))
inflight_bt_msg = list_top(&bt.msgq_sync, struct bt_msg, link);
else if (!list_empty(&bt.msgq))
inflight_bt_msg = list_top(&bt.msgq, struct bt_msg, link);
else
goto out_unlock;
assert(inflight_bt_msg);
/*
* Start the message timeout once it gets to the top
* of the queue. This will ensure we timeout messages
* in the case of a broken bt interface as occurs when
* the BMC is not responding to any IPMI messages.
*/
if (inflight_bt_msg->tb == 0)
inflight_bt_msg->tb = mftb();
/*
* Only send it if we haven't already.
* Timeouts and retries happen in bt_expire_old_msg()
* called from bt_poll()
*/
if (bt_idle() && inflight_bt_msg->send_count == 0)
bt_send_msg(inflight_bt_msg);
out_unlock:
unlock(&bt.lock);
}
static void bt_poll(struct timer *t __unused, void *data __unused,
uint64_t now)
{
uint8_t bt_ctrl;
/* Don't do anything if the LPC bus is offline */
if (!lpc_ok())
return;
/*
* If we can't get the lock assume someone else will notice
* the new message and process it.
*/
lock(&bt.lock);
#if BT_QUEUE_DEBUG
print_debug_queue_info();
#endif
bt_ctrl = bt_inb(BT_CTRL);
/* Is there a response waiting for us? */
if (bt_ctrl & BT_CTRL_B2H_ATN)
bt_get_resp();
bt_expire_old_msg(now);
/* Check for sms_atn */
if (bt_inb(BT_CTRL) & BT_CTRL_SMS_ATN) {
bt_outb(BT_CTRL_SMS_ATN, BT_CTRL);
unlock(&bt.lock);
ipmi_sms_attention();
lock(&bt.lock);
}
/*
* Send messages if we can. If the BMC was really quick we
* could loop back to the start and check for a response
* instead of unlocking, but testing shows the BMC isn't that
* fast so we will wait for the IRQ or a call to the pollers instead.
*/
bt_send_and_unlock();
schedule_timer(&bt.poller,
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;
bt_msg->seq = ipmi_seq++;
bt_msg->send_count = 0;
bt.queue_len++;
if (bt.queue_len > BT_MAX_QUEUE_LEN) {
/* Maximum queue length exceeded, remove oldest messages. */
BT_Q_ERR(bt_msg, "Maximum queue length exceeded");
/* First try to remove message from normal queue */
if (!list_empty(&bt.msgq))
bt_msg = list_tail(&bt.msgq, struct bt_msg, link);
else if (!list_empty(&bt.msgq_sync))
bt_msg = list_tail(&bt.msgq_sync, struct bt_msg, link);
assert(bt_msg);
BT_Q_ERR(bt_msg, "Removed from queue");
bt_msg_del(bt_msg);
}
}
/* Add message to synchronous message list */
static int bt_add_ipmi_msg_head(struct ipmi_msg *ipmi_msg)
{
struct bt_msg *bt_msg = container_of(ipmi_msg, struct bt_msg, ipmi_msg);
lock(&bt.lock);
bt_add_msg(bt_msg);
list_add_tail(&bt.msgq_sync, &bt_msg->link);
bt_send_and_unlock();
return 0;
}
static int bt_add_ipmi_msg(struct ipmi_msg *ipmi_msg)
{
struct bt_msg *bt_msg = container_of(ipmi_msg, struct bt_msg, ipmi_msg);
lock(&bt.lock);
bt_add_msg(bt_msg);
list_add_tail(&bt.msgq, &bt_msg->link);
bt_send_and_unlock();
return 0;
}
static void bt_irq(uint32_t chip_id __unused, uint32_t irq_mask __unused)
{
uint8_t ireg;
ireg = bt_inb(BT_INTMASK);
bt.irq_ok = true;
if (ireg & BT_INTMASK_B2H_IRQ) {
bt_outb(BT_INTMASK_B2H_IRQ | BT_INTMASK_B2H_IRQEN, BT_INTMASK);
bt_poll(NULL, NULL, mftb());
}
}
/*
* Allocate an ipmi message and bt container and return the ipmi
* message struct. Allocates enough space for the request and response
* data.
*/
static struct ipmi_msg *bt_alloc_ipmi_msg(size_t request_size, size_t response_size)
{
struct bt_msg *bt_msg;
bt_msg = zalloc(sizeof(struct bt_msg) + MAX(request_size, response_size));
if (!bt_msg)
return NULL;
bt_msg->ipmi_msg.req_size = request_size;
bt_msg->ipmi_msg.resp_size = response_size;
bt_msg->ipmi_msg.data = (uint8_t *) (bt_msg + 1);
return &bt_msg->ipmi_msg;
}
/*
* Free a previously allocated ipmi message.
*/
static void bt_free_ipmi_msg(struct ipmi_msg *ipmi_msg)
{
struct bt_msg *bt_msg = container_of(ipmi_msg, struct bt_msg, ipmi_msg);
free(bt_msg);
}
/*
* Do not resend IPMI messages to BMC.
*/
static void bt_disable_ipmi_msg_retry(struct ipmi_msg *ipmi_msg)
{
struct bt_msg *bt_msg = container_of(ipmi_msg, struct bt_msg, ipmi_msg);
bt_msg->disable_retry = true;
}
/*
* Remove a message from the queue. The memory allocated for the ipmi message
* will need to be freed by the caller with bt_free_ipmi_msg() as it will no
* longer be in the queue of messages.
*/
static int bt_del_ipmi_msg(struct ipmi_msg *ipmi_msg)
{
struct bt_msg *bt_msg = container_of(ipmi_msg, struct bt_msg, ipmi_msg);
lock(&bt.lock);
list_del(&bt_msg->link);
bt.queue_len--;
bt_send_and_unlock();
return 0;
}
static struct ipmi_backend bt_backend = {
.alloc_msg = bt_alloc_ipmi_msg,
.free_msg = bt_free_ipmi_msg,
.queue_msg = bt_add_ipmi_msg,
.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 = {
.interrupt = bt_irq,
};
void bt_init(void)
{
struct dt_node *n;
const struct dt_property *prop;
uint32_t irq;
/* Set sane capability defaults */
bt.caps.num_requests = 1;
bt.caps.input_buf_len = BT_FIFO_LEN;
bt.caps.output_buf_len = BT_FIFO_LEN;
bt.caps.msg_timeout = BT_MSG_TIMEOUT;
bt.caps.max_retries = BT_MAX_RETRIES;
/* We support only one */
n = dt_find_compatible_node(dt_root, NULL, "ipmi-bt");
if (!n) {
prerror("No BT device\n");
return;
}
/* Get IO base */
prop = dt_find_property(n, "reg");
if (!prop) {
prerror("Can't find reg property\n");
return;
}
if (dt_property_get_cell(prop, 0) != OPAL_LPC_IO) {
prerror("Only supports IO addresses\n");
return;
}
bt.base_addr = dt_property_get_cell(prop, 1);
init_timer(&bt.poller, bt_poll, NULL);
bt_init_interface();
init_lock(&bt.lock);
/*
* The iBT interface comes up in the busy state until the daemon has
* initialised it.
*/
list_head_init(&bt.msgq);
list_head_init(&bt.msgq_sync);
inflight_bt_msg = NULL;
bt.queue_len = 0;
prlog(PR_INFO, "Interface initialized, IO 0x%04x\n", bt.base_addr);
ipmi_register_backend(&bt_backend);
/*
* We initially schedule the poller as a relatively fast timer, at
* least until we have at least one interrupt occurring at which
* point we turn it into a background poller
*/
schedule_timer(&bt.poller, msecs_to_tb(BT_DEFAULT_POLL_MS));
irq = dt_prop_get_u32(n, "interrupts");
bt_lpc_client.interrupts = LPC_IRQ(irq);
lpc_register_client(dt_get_chip_id(n), &bt_lpc_client,
IRQ_ATTR_TARGET_OPAL);
/* Enqueue an IPMI message to ask the BMC about its BT capabilities */
get_bt_caps();
prlog(PR_DEBUG, "Using LPC IRQ %d\n", irq);
}
|