From patchwork Wed May 17 19:56:22 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Corey Minyard X-Patchwork-Id: 100009 Delivered-To: patch@linaro.org Received: by 10.140.96.100 with SMTP id j91csp392133qge; Wed, 17 May 2017 12:57:00 -0700 (PDT) X-Received: by 10.84.229.79 with SMTP id d15mr524696pln.93.1495051020151; Wed, 17 May 2017 12:57:00 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1495051020; cv=none; d=google.com; s=arc-20160816; b=UY+WI+2IN/v/rGHpZgoXdtcVVfUZBek9q2oN53l+FehslWSMlrZABGQN96Vm8+HgDw UMsrdpCBSKduKlRHPrxqN+9cu8X1EhPC6fLu1pz0zleoLh+SzPPszb6QlhigrRhZPaDa 6aXPOZ9bWi4nbwubioCkj32Gj0MwVemjzq5+fnijrGm6QTuqm1Bm3V5Lh2Ma6ZARRbK8 T3jJIXqU3jSUtYqX8FMU7yr+6rkqOlaBP4u+qPcA1VYAje6PuVaXOAoU89gL5VsdcrqD 05UUFvv76hk0/UeAeg8HyLzSfXDGF2blRCC/N9waxbTbPBQ+nLFDgYZzNrCYN5cIdSif 10DA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=xePd590STj4cp0mnWlaPm/mO1y8q/iSqP3RS1JCOkOY=; b=EAWCj9TvkzM4LZ6NsJOsG6OKFKAXaW5GwilC91FW3dCLTNNgVr6vJv/nKYRN5JvGqE 8JO0MVxRsLFP3yIHW437XtnGK7QorYUNk7cxiJguWLOzy8o/S1bb/AXt/nbL+L60VfdQ L7ulCTVq1GxhXTcw2berXDMF4kkhMJaUbihOxnKd9N9IzjoLLucLrVOkQEuQN7Q89jKZ 7h17w//rb1Ys8k6zccoQxF22Sz1teBFi6g10u+vapzfwoc6hWkGH9N21Cl6+WfTwjqZU CI+I13aHzx9VRtJMfaeaIC+wM9oNQ88ZsrcoKec7TKlYmWDvBXwOIU3epP3ffDi5L6XS 6k4w== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@gmail.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 l10si2972162pln.71.2017.05.17.12.56.59; Wed, 17 May 2017 12:57:00 -0700 (PDT) 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; dkim=fail header.i=@gmail.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 S1753972AbdEQT4s (ORCPT + 25 others); Wed, 17 May 2017 15:56:48 -0400 Received: from mail-oi0-f67.google.com ([209.85.218.67]:36666 "EHLO mail-oi0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753781AbdEQT4m (ORCPT ); Wed, 17 May 2017 15:56:42 -0400 Received: by mail-oi0-f67.google.com with SMTP id w138so3894616oiw.3 for ; Wed, 17 May 2017 12:56:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=xePd590STj4cp0mnWlaPm/mO1y8q/iSqP3RS1JCOkOY=; b=Z++hEaNmZJuBOmGS9k54ViYFcsR8c/toKIoGoFqJ5s6EBM2nIKbaenBO4EkywfLICz QSY7XkAlJiE9K1Cu0XWnq3VEp8P5yCUToxBXkLeK5LtC/Do0HM3zm8tR35xE5UMhRX6/ ipBQIiFDwASh7n8xWwQHylJaiUCu1cHR1uGCsfEgJViRnrnqcxQ76KUAUwMevlwhkqn5 3siVEaLV3DWnH0Ib6zT0yaoT1ZmCztJxa9I3MdsjdBbB9ckIAZLxdjV8w26FGlA7l6nv RA2hEuRupE6esK0X4oO0PJAWej7gE0jKKXtM59pKczIYXjCQLcz8V+xr3FlVsH4T3RBC wqpA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=xePd590STj4cp0mnWlaPm/mO1y8q/iSqP3RS1JCOkOY=; b=SED9E8VwoICwYUo0l1hq6AxT1RWJNEwZQoYPvycgl3IOhYo3s/6UafiOhWO4lkP9Wg WBwLU8FtxgTxDZM1HZ4i8sf0MKwfGxVSFBD78jFabce/35HtvEIKwpwy6uZ5TSRtkNtO gtgG/YKn+vl5Z7jgWHoD13HEaIhXnYHhVD4b9TJdZKMgXKUiKKgDMcfhr83Fgs4bRPF4 tqpOr7SwH6trkolVdzuIfzsPjrBOUSlNBVhSv3rMOIDsczLBxbd9GbFa2DdioLpSIL+3 4CTkbiGCgMur5iaTNiC8EEs1ftM6zB3nyZbGVxEFQrfHrAVovMP8/AOJjRRZ/Z+ysnEi Q7kQ== X-Gm-Message-State: AODbwcBecMsGuDIZ/AuJ2E0MxepkBumx7ezSgXcD5oz9Hp6CTtFVG4ca NH/NX2+1AdbE+A== X-Received: by 10.157.40.238 with SMTP id s101mr356070ota.88.1495050996567; Wed, 17 May 2017 12:56:36 -0700 (PDT) Received: from serve.minyard.net ([47.184.154.34]) by smtp.gmail.com with ESMTPSA id p3sm1519479oia.24.2017.05.17.12.56.33 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 17 May 2017 12:56:35 -0700 (PDT) Received: from t430.minyard.net (t430m.minyard.net [192.168.27.3]) by serve.minyard.net (Postfix) with ESMTPA id EFBE21370; Wed, 17 May 2017 14:56:30 -0500 (CDT) Received: by t430.minyard.net (Postfix, from userid 1000) id 246D33029B2; Wed, 17 May 2017 14:56:28 -0500 (CDT) From: minyard@acm.org To: Jean Delvare Cc: openipmi-developer@lists.sourceforge.net, linux-kernel@vger.kernel.org, Andy Lutomirski , Corey Minyard Subject: [PATCH v5 3/5] dmi: Add IPMI DMI scanning to the DMI code Date: Wed, 17 May 2017 14:56:22 -0500 Message-Id: <1495050984-5602-4-git-send-email-minyard@acm.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1495050984-5602-1-git-send-email-minyard@acm.org> References: <1495050984-5602-1-git-send-email-minyard@acm.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Corey Minyard It makes more sense to be there, and it's cleaner with the upcoming conversion of IPMI DMI to a platform device. Signed-off-by: Corey Minyard Cc: Jean Delvare Cc: Andy Lutomirski Tested-by: Andy Lutomirski --- drivers/firmware/dmi_scan.c | 108 ++++++++++++++++++++++++++++++++++++++++++-- include/linux/dmi.h | 26 +++++++++++ 2 files changed, 129 insertions(+), 5 deletions(-) -- 2.7.4 diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index 78ef357..96c0743 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -303,9 +303,105 @@ static void __init dmi_save_oem_strings_devices(const struct dmi_header *dm) } } +#define DMI_IPMI_MIN_LENGTH 0x10 +#define DMI_IPMI_VER2_LENGTH 0x12 +#define DMI_IPMI_TYPE 4 +#define DMI_IPMI_SLAVEADDR 6 +#define DMI_IPMI_ADDR 8 +#define DMI_IPMI_ACCESS 0x10 +#define DMI_IPMI_IRQ 0x11 +#define DMI_IPMI_IO_MASK 0xfffe + +static void __init dmi_decode_ipmi(struct dmi_dev_ipmi *dev, + const struct dmi_header *dm) +{ + const u8 *data = (const u8 *) dm; + unsigned long base_addr; + u8 len = dm->length; + bool slave_addr_set; + + if (len < DMI_IPMI_MIN_LENGTH) + return; + + dev->type = data[DMI_IPMI_TYPE]; + + memcpy(&base_addr, data + DMI_IPMI_ADDR, sizeof(unsigned long)); + if (len >= DMI_IPMI_VER2_LENGTH) { + if (dev->type == IPMI_DMI_TYPE_SSIF) { + if ((data[DMI_IPMI_ADDR] >> 1) == 0) { + /* + * Some broken systems put the I2C address in + * the slave address field. We try to + * accommodate them here. + */ + dev->base_addr = data[DMI_IPMI_SLAVEADDR] >> 1; + dev->slave_addr = 0; + slave_addr_set = true; + } else { + dev->base_addr = data[DMI_IPMI_ADDR] >> 1; + } + } else { + if (base_addr & 1) { + /* I/O */ + base_addr &= DMI_IPMI_IO_MASK; + dev->is_io_space = 1; + } else { + /* Memory */ + dev->is_io_space = 0; + } + + /* + * If bit 4 of byte 0x10 is set, then the lsb + * for the address is odd. + */ + base_addr |= (data[DMI_IPMI_ACCESS] >> 4) & 1; + + dev->base_addr = base_addr; + dev->irq = data[DMI_IPMI_IRQ]; + + /* + * The top two bits of byte 0x10 hold the + * register spacing. + */ + switch ((data[DMI_IPMI_ACCESS] >> 6) & 3) { + case 0: /* Byte boundaries */ + dev->offset = 1; + break; + case 1: /* 32-bit boundaries */ + dev->offset = 4; + break; + case 2: /* 16-byte boundaries */ + dev->offset = 16; + break; + default: + /* Leave 0 for undefined. */ + return; + } + } + } else { + /* Old DMI spec. */ + /* + * Note that technically, the lower bit of the base + * address should be 1 if the address is I/O and 0 if + * the address is in memory. So many systems get that + * wrong (and all that I have seen are I/O) so we just + * ignore that bit and assume I/O. Systems that use + * memory should use the newer spec, anyway. + */ + dev->base_addr = base_addr & DMI_IPMI_IO_MASK; + dev->is_io_space = 1; + dev->offset = 1; + } + + if (!slave_addr_set) + dev->slave_addr = data[DMI_IPMI_SLAVEADDR]; + + dev->good_data = 1; +} + static void __init dmi_save_ipmi_device(const struct dmi_header *dm) { - struct dmi_device *dev; + struct dmi_dev_ipmi *dev; void *data; data = dmi_alloc(dm->length); @@ -318,11 +414,13 @@ static void __init dmi_save_ipmi_device(const struct dmi_header *dm) if (!dev) return; - dev->type = DMI_DEV_TYPE_IPMI; - dev->name = "IPMI controller"; - dev->device_data = data; + dev->dev.type = DMI_DEV_TYPE_IPMI; + dev->dev.name = "IPMI controller"; + dev->dev.device_data = data; - dmi_devices_list_add(dev); + dmi_decode_ipmi(dev, dm); + + dmi_devices_list_add(&dev->dev); } static void __init dmi_save_dev_pciaddr(int instance, int segment, int bus, diff --git a/include/linux/dmi.h b/include/linux/dmi.h index c8dd5b8..96dc644 100644 --- a/include/linux/dmi.h +++ b/include/linux/dmi.h @@ -97,6 +97,24 @@ struct dmi_dev_onboard { int devfn; }; +/* Device data for an IPMI entry. */ +struct dmi_dev_ipmi { + struct dmi_device dev; + u8 good_data; + u8 type; + u8 is_io_space; + u8 irq; + u8 offset; + u8 slave_addr; + unsigned long base_addr; +}; + +/* dmi_ipmi_data type field */ +#define IPMI_DMI_TYPE_KCS 0x01 +#define IPMI_DMI_TYPE_SMIC 0x02 +#define IPMI_DMI_TYPE_BT 0x03 +#define IPMI_DMI_TYPE_SSIF 0x04 + extern struct kobject *dmi_kobj; extern int dmi_check_system(const struct dmi_system_id *list); const struct dmi_system_id *dmi_first_match(const struct dmi_system_id *list); @@ -127,6 +145,14 @@ static inline struct dmi_device *to_dmi_device(struct fwnode_handle *fwnode) return NULL; } +static inline struct dmi_dev_ipmi *to_dmi_dev_ipmi(struct dmi_device *dev) +{ + if (!dev || dev->type != DMI_DEV_TYPE_IPMI) + return NULL; + + return container_of(dev, struct dmi_dev_ipmi, dev); +} + #else static inline int dmi_check_system(const struct dmi_system_id *list) { return 0; }