Lines Matching +full:io +full:- +full:reset
1 // SPDX-License-Identifier: GPL-2.0+
5 * The state machine for an Open IPMI BT sub-driver under ipmi_si.c, part
35 * Typical "Get BT Capabilities" values are 2-3 retries, 5-10 seconds,
38 * Since the Open IPMI architecture is single-message oriented at this
44 #define BT_RESET_DELAY 6 /* seconds after warm reset */
64 BT_STATE_LONG_BUSY /* BT doesn't get hosed :-) */
72 #define BT_STATE_CHANGE(X, Y) { bt->state = X; return Y; }
79 struct si_sm_io *io; member
110 #define BT_STATUS bt->io->inputb(bt->io, 0)
111 #define BT_CONTROL(x) bt->io->outputb(bt->io, 0, x)
113 #define BMC2HOST bt->io->inputb(bt->io, 1)
114 #define HOST2BMC(x) bt->io->outputb(bt->io, 1, x)
116 #define BT_INTMASK_R bt->io->inputb(bt->io, 2)
117 #define BT_INTMASK_W(x) bt->io->outputb(bt->io, 2, x)
120 * Convenience routines for debugging. These are not multi-open safe!
142 #define STATE2TXT state2txt(bt->state)
173 static unsigned int bt_init_data(struct si_sm_data *bt, struct si_sm_io *io) in bt_init_data() argument
176 if (bt->io != io) { in bt_init_data()
177 /* external: one-time only things */ in bt_init_data()
178 bt->io = io; in bt_init_data()
179 bt->seq = 0; in bt_init_data()
181 bt->state = BT_STATE_IDLE; /* start here */ in bt_init_data()
182 bt->complete = BT_STATE_IDLE; /* end here */ in bt_init_data()
183 bt->BT_CAP_req2rsp = BT_NORMAL_TIMEOUT * USEC_PER_SEC; in bt_init_data()
184 bt->BT_CAP_retries = BT_NORMAL_RETRY_LIMIT; in bt_init_data()
192 bt->read_data[0] = 4; /* # following bytes */ in force_result()
193 bt->read_data[1] = bt->write_data[1] | 4; /* Odd NetFn/LUN */ in force_result()
194 bt->read_data[2] = bt->write_data[2]; /* seq (ignored) */ in force_result()
195 bt->read_data[3] = bt->write_data[3]; /* Command */ in force_result()
196 bt->read_data[4] = completion_code; in force_result()
197 bt->read_count = 5; in force_result()
213 if (bt->state == BT_STATE_LONG_BUSY) in bt_start_transaction()
216 if (bt->state != BT_STATE_IDLE) { in bt_start_transaction()
217 dev_warn(bt->io->dev, "BT in invalid state %d\n", bt->state); in bt_start_transaction()
222 dev_dbg(bt->io->dev, "+++++++++++++++++ New command\n"); in bt_start_transaction()
223 dev_dbg(bt->io->dev, "NetFn/LUN CMD [%d data]:", size - 2); in bt_start_transaction()
228 bt->write_data[0] = size + 1; /* all data plus seq byte */ in bt_start_transaction()
229 bt->write_data[1] = *data; /* NetFn/LUN */ in bt_start_transaction()
230 bt->write_data[2] = bt->seq++; in bt_start_transaction()
231 memcpy(bt->write_data + 3, data + 1, size - 1); in bt_start_transaction()
232 bt->write_count = size + 2; in bt_start_transaction()
233 bt->error_retries = 0; in bt_start_transaction()
234 bt->nonzero_status = 0; in bt_start_transaction()
235 bt->truncated = 0; in bt_start_transaction()
236 bt->state = BT_STATE_XACTION_START; in bt_start_transaction()
237 bt->timeout = bt->BT_CAP_req2rsp; in bt_start_transaction()
253 msg_len = bt->read_count - 2; /* account for length & seq */ in bt_get_result()
258 data[0] = bt->read_data[1]; in bt_get_result()
259 data[1] = bt->read_data[3]; in bt_get_result()
260 if (length < msg_len || bt->truncated) { in bt_get_result()
264 memcpy(data + 2, bt->read_data + 4, msg_len - 2); in bt_get_result()
267 dev_dbg(bt->io->dev, "result %d bytes:", msg_len); in bt_get_result()
281 dev_dbg(bt->io->dev, "flag reset %s\n", status2txt(BT_STATUS)); in reset_flags()
284 BT_CONTROL(BT_CLR_WR_PTR); /* always reset */ in reset_flags()
305 BT_CONTROL(BT_CLR_RD_PTR); /* always reset */ in drain_BMC2HOST()
307 dev_dbg(bt->io->dev, "stale response %s; ", in drain_BMC2HOST()
322 dev_dbg(bt->io->dev, "write %d bytes seq=0x%02X", in write_all_bytes()
323 bt->write_count, bt->seq); in write_all_bytes()
324 for (i = 0; i < bt->write_count; i++) in write_all_bytes()
325 pr_cont(" %02x", bt->write_data[i]); in write_all_bytes()
328 for (i = 0; i < bt->write_count; i++) in write_all_bytes()
329 HOST2BMC(bt->write_data[i]); in write_all_bytes()
341 bt->read_data[0] = BMC2HOST; in read_all_bytes()
342 bt->read_count = bt->read_data[0]; in read_all_bytes()
344 if (bt->read_count < 4 || bt->read_count >= IPMI_MAX_MSG_LENGTH) { in read_all_bytes()
346 dev_dbg(bt->io->dev, in read_all_bytes()
347 "bad raw rsp len=%d\n", bt->read_count); in read_all_bytes()
348 bt->truncated = 1; in read_all_bytes()
351 for (i = 1; i <= bt->read_count; i++) in read_all_bytes()
352 bt->read_data[i] = BMC2HOST; in read_all_bytes()
353 bt->read_count++; /* Account internally for length byte */ in read_all_bytes()
356 int max = bt->read_count; in read_all_bytes()
358 dev_dbg(bt->io->dev, in read_all_bytes()
359 "got %d bytes seq=0x%02X", max, bt->read_data[2]); in read_all_bytes()
363 pr_cont(" %02x", bt->read_data[i]); in read_all_bytes()
364 pr_cont("%s\n", bt->read_count == max ? "" : " ..."); in read_all_bytes()
368 if ((bt->read_data[3] == bt->write_data[3]) && in read_all_bytes()
369 (bt->read_data[2] == bt->write_data[2]) && in read_all_bytes()
370 ((bt->read_data[1] & 0xF8) == (bt->write_data[1] & 0xF8))) in read_all_bytes()
374 dev_dbg(bt->io->dev, in read_all_bytes()
376 bt->write_data[1] | 0x04, bt->write_data[2], in read_all_bytes()
377 bt->write_data[3], in read_all_bytes()
378 bt->read_data[1], bt->read_data[2], bt->read_data[3]); in read_all_bytes()
390 bt->timeout = bt->BT_CAP_req2rsp; in error_recovery()
401 dev_warn(bt->io->dev, "IPMI BT: %s in %s %s ", /* open-ended line */ in error_recovery()
408 (bt->error_retries)++; in error_recovery()
409 if (bt->error_retries < bt->BT_CAP_retries) { in error_recovery()
411 bt->BT_CAP_retries - bt->error_retries); in error_recovery()
412 bt->state = BT_STATE_RESTART; in error_recovery()
416 dev_warn(bt->io->dev, "failed %d retries, sending error response\n", in error_recovery()
417 bt->BT_CAP_retries); in error_recovery()
418 if (!bt->nonzero_status) in error_recovery()
419 dev_err(bt->io->dev, "stuck, try power cycle\n"); in error_recovery()
422 else if (bt->seq <= (unsigned char)(bt->BT_CAP_retries & 0xFF)) { in error_recovery()
423 dev_warn(bt->io->dev, "BT reset (takes 5 secs)\n"); in error_recovery()
424 bt->state = BT_STATE_RESET1; in error_recovery()
433 bt->state = BT_STATE_IDLE; in error_recovery()
438 bt->state = BT_STATE_LONG_BUSY; in error_recovery()
457 bt->nonzero_status |= status; in bt_event()
458 if ((bt_debug & BT_DEBUG_STATES) && (bt->state != last_printed)) { in bt_event()
459 dev_dbg(bt->io->dev, "BT: %s %s TO=%ld - %ld\n", in bt_event()
462 bt->timeout, in bt_event()
464 last_printed = bt->state; in bt_event()
471 * it will be rejected by its (now-forgotten) seq number. in bt_event()
474 if ((bt->state < BT_STATE_WRITE_BYTES) && (status & BT_B2H_ATN)) { in bt_event()
479 if ((bt->state != BT_STATE_IDLE) && in bt_event()
480 (bt->state < BT_STATE_PRINTME)) { in bt_event()
482 bt->timeout -= time; in bt_event()
483 if ((bt->timeout < 0) && (bt->state < BT_STATE_RESET1)) in bt_event()
489 switch (bt->state) { in bt_event()
539 * some BMCs don't clear B2H_ATN with one hit. Fast-path a in bt_event()
566 bt->state = bt->complete; in bt_event()
567 return bt->state == BT_STATE_IDLE ? /* where to next? */ in bt_event()
574 bt_init_data(bt, bt->io); in bt_event()
584 case BT_STATE_RESET2: /* Send a soft reset */ in bt_event()
589 HOST2BMC(3); /* Cmd == Soft reset */ in bt_event()
591 bt->timeout = BT_RESET_DELAY * USEC_PER_SEC; in bt_event()
596 if (bt->timeout > 0) in bt_event()
602 case BT_STATE_RESTART: /* don't reset retries or seq! */ in bt_event()
603 bt->read_count = 0; in bt_event()
604 bt->nonzero_status = 0; in bt_event()
605 bt->timeout = bt->BT_CAP_req2rsp; in bt_event()
626 * all 1's, (assuming a properly functioning, self-initialized BMC) in bt_detect()
640 dev_warn(bt->io->dev, in bt_detect()
658 bt_init_data(bt, bt->io); in bt_detect()
660 dev_warn(bt->io->dev, "bt cap response too short: %d\n", rv); in bt_detect()
665 dev_warn(bt->io->dev, "Error fetching bt cap: %x\n", BT_CAP[2]); in bt_detect()
667 dev_warn(bt->io->dev, "using default values\n"); in bt_detect()
669 bt->BT_CAP_req2rsp = BT_CAP[6] * USEC_PER_SEC; in bt_detect()
670 bt->BT_CAP_retries = BT_CAP[7]; in bt_detect()
673 dev_info(bt->io->dev, "req2rsp=%ld secs retries=%d\n", in bt_detect()
674 bt->BT_CAP_req2rsp / USEC_PER_SEC, bt->BT_CAP_retries); in bt_detect()