Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp2988434imu; Sun, 9 Dec 2018 14:24:16 -0800 (PST) X-Google-Smtp-Source: AFSGD/X03lpeQ2SKFlrjYxAjTAPRiAXHqtA3p7K3btrPEA0guqC0rxgNvS63bZhkH32ngHRvg03q X-Received: by 2002:a63:4665:: with SMTP id v37mr9004926pgk.425.1544394256533; Sun, 09 Dec 2018 14:24:16 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1544394256; cv=none; d=google.com; s=arc-20160816; b=K/iVLmSCQk/DDkLvAiHlaIKcZO/C3U7sKJvtEDoj7BlIr3p47GkMh9q3dgebTkY0+U W1pifHvH6uBCdGQB5BR7ixEQFqMG2nTb//EI7nDOecoD4J6bZaX+PpN9wm8VmyWld/N5 xZlYCFync25CR6ptCnDT+y7Jvf1hdKC9J6x/s5kV59pfhCVucjYER6i3wTLuWkK4fzcT KLhn4Ll9tit7mKxttmUiL4x26JO8TZiICTjpmCKSs7bTL3zQJ4q7bb/IR2jnDoJx9R36 KsypxbWziOB/e3sopj7apmLWrxdsXyI1s1AhJplqs9Szmjt58f6r39PQWgFuFm85owAN enmw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:in-reply-to:subject:message-id:date:cc:to :from:mime-version:content-transfer-encoding:content-disposition; bh=5TqAggGp/3/aO2k+NL6rPb35JNApgn5AXjgBe6pc2jw=; b=yh8+170JFOX0XLjfTrEsXIsoQ4/7YI70NPWkRMeyu/0ipe8uR4sNvcfUyr9nle/YCO nDGRbiN4NSedonqTtdnjGLYoRB7eDcAw2lspq3Jveh3mIE/Ktx9YmJohYStsYue6M+fF PpifzKOWp9kamIRgDAAJBi+9EHdBlWQXXzl6WBRrctu9lnItfrAwwhjwMQzAOCrJ03jU BB2mLR0GL22mdagdNvLi/EtJFvDrab0vHmPnxM6L12kw0FSqA6WFjJP1fWltYHXaK7uK 27A15i+rpNqlqUpTyYp2T4eH5zQCTMc3Po9+CxKq0yiva8CWhdLsFZFUivFYpjDHBJaQ 3cPQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id v83si9093963pfk.264.2018.12.09.14.24.01; Sun, 09 Dec 2018 14:24:16 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726985AbeLIWWd (ORCPT + 99 others); Sun, 9 Dec 2018 17:22:33 -0500 Received: from shadbolt.e.decadent.org.uk ([88.96.1.126]:35184 "EHLO shadbolt.e.decadent.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726513AbeLIVzV (ORCPT ); Sun, 9 Dec 2018 16:55:21 -0500 Received: from pub.yeoldevic.com ([81.174.156.145] helo=deadeye) by shadbolt.decadent.org.uk with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89) (envelope-from ) id 1gW72h-0002ir-Qo; Sun, 09 Dec 2018 21:55:16 +0000 Received: from ben by deadeye with local (Exim 4.91) (envelope-from ) id 1gW72e-0003SK-TN; Sun, 09 Dec 2018 21:55:12 +0000 Content-Type: text/plain; charset="UTF-8" Content-Disposition: inline Content-Transfer-Encoding: 8bit MIME-Version: 1.0 From: Ben Hutchings To: linux-kernel@vger.kernel.org, stable@vger.kernel.org CC: akpm@linux-foundation.org, "Corey Minyard" , "Andrew Banman" Date: Sun, 09 Dec 2018 21:50:33 +0000 Message-ID: X-Mailer: LinuxStableQueue (scripts by bwh) X-Patchwork-Hint: ignore Subject: [PATCH 3.16 175/328] ipmi: Move BT capabilities detection to the detect call In-Reply-To: X-SA-Exim-Connect-IP: 81.174.156.145 X-SA-Exim-Mail-From: ben@decadent.org.uk X-SA-Exim-Scanned: No (on shadbolt.decadent.org.uk); SAEximRunCond expanded to false Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 3.16.62-rc1 review patch. If anyone has any objections, please let me know. ------------------ From: Corey Minyard commit c86ba91be75702c013bbf7379542920b6920e98f upstream. 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 Reported-by: Andrew Banman Tested-by: Andrew Banman [bwh: Backported to 3.16: - struct si_sm_data doesn't include a dev pointer, so use pr_* functions for logging - Include for schedule_timeout_uninterruptible()] Signed-off-by: Ben Hutchings --- --- a/drivers/char/ipmi/ipmi_bt_sm.c +++ b/drivers/char/ipmi/ipmi_bt_sm.c @@ -31,6 +31,7 @@ #include #include #include /* for completion codes */ +#include #include "ipmi_si_sm.h" #define BT_DEBUG_OFF 0 /* Used in production */ @@ -77,8 +78,6 @@ enum bt_states { BT_STATE_RESET3, BT_STATE_RESTART, BT_STATE_PRINTME, - BT_STATE_CAPABILITIES_BEGIN, - BT_STATE_CAPABILITIES_END, BT_STATE_LONG_BUSY /* BT doesn't get hosed :-) */ }; @@ -104,7 +103,6 @@ struct si_sm_data { int error_retries; /* end of "common" fields */ int nonzero_status; /* hung BMCs stay all 0 */ enum bt_states complete; /* to divert the state machine */ - int BT_CAP_outreqs; long BT_CAP_req2rsp; int BT_CAP_retries; /* Recommended retries */ }; @@ -155,8 +153,6 @@ static char *state2txt(unsigned char sta case BT_STATE_RESET3: return("RESET3"); case BT_STATE_RESTART: return("RESTART"); case BT_STATE_LONG_BUSY: return("LONG_BUSY"); - case BT_STATE_CAPABILITIES_BEGIN: return("CAP_BEGIN"); - case BT_STATE_CAPABILITIES_END: return("CAP_END"); } return("BAD STATE"); } @@ -203,7 +199,6 @@ static unsigned int bt_init_data(struct bt->complete = BT_STATE_IDLE; /* end here */ bt->BT_CAP_req2rsp = BT_NORMAL_TIMEOUT * USEC_PER_SEC; bt->BT_CAP_retries = BT_NORMAL_RETRY_LIMIT; - /* BT_CAP_outreqs == zero is a flag to read BT Capabilities */ return 3; /* We claim 3 bytes of space; ought to check SPMI table */ } @@ -469,7 +464,7 @@ static enum si_sm_result error_recovery( static enum si_sm_result bt_event(struct si_sm_data *bt, long time) { - unsigned char status, BT_CAP[8]; + unsigned char status; static enum bt_states last_printed = BT_STATE_PRINTME; int i; @@ -522,12 +517,6 @@ static enum si_sm_result bt_event(struct if (status & BT_H_BUSY) /* clear a leftover H_BUSY */ BT_CONTROL(BT_H_BUSY); - bt->timeout = bt->BT_CAP_req2rsp; - - /* Read BT capabilities if it hasn't been done yet */ - if (!bt->BT_CAP_outreqs) - BT_STATE_CHANGE(BT_STATE_CAPABILITIES_BEGIN, - SI_SM_CALL_WITHOUT_DELAY); BT_SI_SM_RETURN(SI_SM_IDLE); case BT_STATE_XACTION_START: @@ -632,37 +621,6 @@ static enum si_sm_result bt_event(struct BT_STATE_CHANGE(BT_STATE_XACTION_START, SI_SM_CALL_WITH_DELAY); - /* - * Get BT Capabilities, using timing of upper level state machine. - * Set outreqs to prevent infinite loop on timeout. - */ - case BT_STATE_CAPABILITIES_BEGIN: - bt->BT_CAP_outreqs = 1; - { - unsigned char GetBT_CAP[] = { 0x18, 0x36 }; - bt->state = BT_STATE_IDLE; - bt_start_transaction(bt, GetBT_CAP, sizeof(GetBT_CAP)); - } - bt->complete = BT_STATE_CAPABILITIES_END; - BT_STATE_CHANGE(BT_STATE_XACTION_START, - SI_SM_CALL_WITH_DELAY); - - case BT_STATE_CAPABILITIES_END: - i = bt_get_result(bt, BT_CAP, sizeof(BT_CAP)); - bt_init_data(bt, bt->io); - if ((i == 8) && !BT_CAP[2]) { - bt->BT_CAP_outreqs = BT_CAP[3]; - bt->BT_CAP_req2rsp = BT_CAP[6] * USEC_PER_SEC; - bt->BT_CAP_retries = BT_CAP[7]; - } else - printk(KERN_WARNING "IPMI BT: using default values\n"); - if (!bt->BT_CAP_outreqs) - bt->BT_CAP_outreqs = 1; - printk(KERN_WARNING "IPMI BT: req2rsp=%ld secs retries=%d\n", - bt->BT_CAP_req2rsp / USEC_PER_SEC, bt->BT_CAP_retries); - bt->timeout = bt->BT_CAP_req2rsp; - return SI_SM_CALL_WITHOUT_DELAY; - default: /* should never occur */ return error_recovery(bt, status, @@ -673,6 +631,11 @@ static enum si_sm_result bt_event(struct static int bt_detect(struct si_sm_data *bt) { + unsigned char GetBT_CAP[] = { 0x18, 0x36 }; + unsigned char BT_CAP[8]; + enum si_sm_result smi_result; + int rv; + /* * It's impossible for the BT status and interrupt registers to be * all 1's, (assuming a properly functioning, self-initialized BMC) @@ -683,6 +646,47 @@ static int bt_detect(struct si_sm_data * if ((BT_STATUS == 0xFF) && (BT_INTMASK_R == 0xFF)) return 1; reset_flags(bt); + + /* + * Try getting the BT capabilities here. + */ + rv = bt_start_transaction(bt, GetBT_CAP, sizeof(GetBT_CAP)); + if (rv) { + pr_warn("BT: Can't start capabilities transaction: %d\n", rv); + goto out_no_bt_cap; + } + + smi_result = SI_SM_CALL_WITHOUT_DELAY; + for (;;) { + if (smi_result == SI_SM_CALL_WITH_DELAY || + smi_result == SI_SM_CALL_WITH_TICK_DELAY) { + schedule_timeout_uninterruptible(1); + smi_result = bt_event(bt, jiffies_to_usecs(1)); + } else if (smi_result == SI_SM_CALL_WITHOUT_DELAY) { + smi_result = bt_event(bt, 0); + } else + break; + } + + rv = bt_get_result(bt, BT_CAP, sizeof(BT_CAP)); + bt_init_data(bt, bt->io); + if (rv < 8) { + pr_warn("BT: bt cap response too short: %d\n", rv); + goto out_no_bt_cap; + } + + if (BT_CAP[2]) { + pr_warn("BT: Error fetching bt cap: %x\n", BT_CAP[2]); +out_no_bt_cap: + pr_warn("BT: using default values\n"); + } else { + bt->BT_CAP_req2rsp = BT_CAP[6] * USEC_PER_SEC; + bt->BT_CAP_retries = BT_CAP[7]; + } + + pr_info("BT: req2rsp=%ld secs retries=%d\n", + bt->BT_CAP_req2rsp / USEC_PER_SEC, bt->BT_CAP_retries); + return 0; }