Skip to content

Commit c86ba91

Browse files
committed
ipmi: Move BT capabilities detection to the detect call
The capabilities detection was being done as part of the normal state machine, but it was possible for it to be running while the upper layers of the IPMI driver were initializing the device, resulting in error and failure to initialize. Move the capabilities detection to the the detect function, so it's done before anything else runs on the device. This also simplifies the state machine and removes some code, as a bonus. Signed-off-by: Corey Minyard <[email protected]> Reported-by: Andrew Banman <[email protected]> Tested-by: Andrew Banman <[email protected]> Cc: <[email protected]>
1 parent 2512e40 commit c86ba91

File tree

1 file changed

+48
-44
lines changed

1 file changed

+48
-44
lines changed

drivers/char/ipmi/ipmi_bt_sm.c

Lines changed: 48 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,6 @@ enum bt_states {
5959
BT_STATE_RESET3,
6060
BT_STATE_RESTART,
6161
BT_STATE_PRINTME,
62-
BT_STATE_CAPABILITIES_BEGIN,
63-
BT_STATE_CAPABILITIES_END,
6462
BT_STATE_LONG_BUSY /* BT doesn't get hosed :-) */
6563
};
6664

@@ -86,7 +84,6 @@ struct si_sm_data {
8684
int error_retries; /* end of "common" fields */
8785
int nonzero_status; /* hung BMCs stay all 0 */
8886
enum bt_states complete; /* to divert the state machine */
89-
int BT_CAP_outreqs;
9087
long BT_CAP_req2rsp;
9188
int BT_CAP_retries; /* Recommended retries */
9289
};
@@ -137,8 +134,6 @@ static char *state2txt(unsigned char state)
137134
case BT_STATE_RESET3: return("RESET3");
138135
case BT_STATE_RESTART: return("RESTART");
139136
case BT_STATE_LONG_BUSY: return("LONG_BUSY");
140-
case BT_STATE_CAPABILITIES_BEGIN: return("CAP_BEGIN");
141-
case BT_STATE_CAPABILITIES_END: return("CAP_END");
142137
}
143138
return("BAD STATE");
144139
}
@@ -185,7 +180,6 @@ static unsigned int bt_init_data(struct si_sm_data *bt, struct si_sm_io *io)
185180
bt->complete = BT_STATE_IDLE; /* end here */
186181
bt->BT_CAP_req2rsp = BT_NORMAL_TIMEOUT * USEC_PER_SEC;
187182
bt->BT_CAP_retries = BT_NORMAL_RETRY_LIMIT;
188-
/* BT_CAP_outreqs == zero is a flag to read BT Capabilities */
189183
return 3; /* We claim 3 bytes of space; ought to check SPMI table */
190184
}
191185

@@ -451,7 +445,7 @@ static enum si_sm_result error_recovery(struct si_sm_data *bt,
451445

452446
static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
453447
{
454-
unsigned char status, BT_CAP[8];
448+
unsigned char status;
455449
static enum bt_states last_printed = BT_STATE_PRINTME;
456450
int i;
457451

@@ -504,12 +498,6 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
504498
if (status & BT_H_BUSY) /* clear a leftover H_BUSY */
505499
BT_CONTROL(BT_H_BUSY);
506500

507-
bt->timeout = bt->BT_CAP_req2rsp;
508-
509-
/* Read BT capabilities if it hasn't been done yet */
510-
if (!bt->BT_CAP_outreqs)
511-
BT_STATE_CHANGE(BT_STATE_CAPABILITIES_BEGIN,
512-
SI_SM_CALL_WITHOUT_DELAY);
513501
BT_SI_SM_RETURN(SI_SM_IDLE);
514502

515503
case BT_STATE_XACTION_START:
@@ -614,37 +602,6 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
614602
BT_STATE_CHANGE(BT_STATE_XACTION_START,
615603
SI_SM_CALL_WITH_DELAY);
616604

617-
/*
618-
* Get BT Capabilities, using timing of upper level state machine.
619-
* Set outreqs to prevent infinite loop on timeout.
620-
*/
621-
case BT_STATE_CAPABILITIES_BEGIN:
622-
bt->BT_CAP_outreqs = 1;
623-
{
624-
unsigned char GetBT_CAP[] = { 0x18, 0x36 };
625-
bt->state = BT_STATE_IDLE;
626-
bt_start_transaction(bt, GetBT_CAP, sizeof(GetBT_CAP));
627-
}
628-
bt->complete = BT_STATE_CAPABILITIES_END;
629-
BT_STATE_CHANGE(BT_STATE_XACTION_START,
630-
SI_SM_CALL_WITH_DELAY);
631-
632-
case BT_STATE_CAPABILITIES_END:
633-
i = bt_get_result(bt, BT_CAP, sizeof(BT_CAP));
634-
bt_init_data(bt, bt->io);
635-
if ((i == 8) && !BT_CAP[2]) {
636-
bt->BT_CAP_outreqs = BT_CAP[3];
637-
bt->BT_CAP_req2rsp = BT_CAP[6] * USEC_PER_SEC;
638-
bt->BT_CAP_retries = BT_CAP[7];
639-
} else
640-
printk(KERN_WARNING "IPMI BT: using default values\n");
641-
if (!bt->BT_CAP_outreqs)
642-
bt->BT_CAP_outreqs = 1;
643-
printk(KERN_WARNING "IPMI BT: req2rsp=%ld secs retries=%d\n",
644-
bt->BT_CAP_req2rsp / USEC_PER_SEC, bt->BT_CAP_retries);
645-
bt->timeout = bt->BT_CAP_req2rsp;
646-
return SI_SM_CALL_WITHOUT_DELAY;
647-
648605
default: /* should never occur */
649606
return error_recovery(bt,
650607
status,
@@ -655,6 +612,11 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
655612

656613
static int bt_detect(struct si_sm_data *bt)
657614
{
615+
unsigned char GetBT_CAP[] = { 0x18, 0x36 };
616+
unsigned char BT_CAP[8];
617+
enum si_sm_result smi_result;
618+
int rv;
619+
658620
/*
659621
* It's impossible for the BT status and interrupt registers to be
660622
* all 1's, (assuming a properly functioning, self-initialized BMC)
@@ -665,6 +627,48 @@ static int bt_detect(struct si_sm_data *bt)
665627
if ((BT_STATUS == 0xFF) && (BT_INTMASK_R == 0xFF))
666628
return 1;
667629
reset_flags(bt);
630+
631+
/*
632+
* Try getting the BT capabilities here.
633+
*/
634+
rv = bt_start_transaction(bt, GetBT_CAP, sizeof(GetBT_CAP));
635+
if (rv) {
636+
dev_warn(bt->io->dev,
637+
"Can't start capabilities transaction: %d\n", rv);
638+
goto out_no_bt_cap;
639+
}
640+
641+
smi_result = SI_SM_CALL_WITHOUT_DELAY;
642+
for (;;) {
643+
if (smi_result == SI_SM_CALL_WITH_DELAY ||
644+
smi_result == SI_SM_CALL_WITH_TICK_DELAY) {
645+
schedule_timeout_uninterruptible(1);
646+
smi_result = bt_event(bt, jiffies_to_usecs(1));
647+
} else if (smi_result == SI_SM_CALL_WITHOUT_DELAY) {
648+
smi_result = bt_event(bt, 0);
649+
} else
650+
break;
651+
}
652+
653+
rv = bt_get_result(bt, BT_CAP, sizeof(BT_CAP));
654+
bt_init_data(bt, bt->io);
655+
if (rv < 8) {
656+
dev_warn(bt->io->dev, "bt cap response too short: %d\n", rv);
657+
goto out_no_bt_cap;
658+
}
659+
660+
if (BT_CAP[2]) {
661+
dev_warn(bt->io->dev, "Error fetching bt cap: %x\n", BT_CAP[2]);
662+
out_no_bt_cap:
663+
dev_warn(bt->io->dev, "using default values\n");
664+
} else {
665+
bt->BT_CAP_req2rsp = BT_CAP[6] * USEC_PER_SEC;
666+
bt->BT_CAP_retries = BT_CAP[7];
667+
}
668+
669+
dev_info(bt->io->dev, "req2rsp=%ld secs retries=%d\n",
670+
bt->BT_CAP_req2rsp / USEC_PER_SEC, bt->BT_CAP_retries);
671+
668672
return 0;
669673
}
670674

0 commit comments

Comments
 (0)