From nobody Mon Jul 11 03:15:19 2022 X-Original-To: dev-commits-src-branches@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 80B851D0DD49; Mon, 11 Jul 2022 03:15:19 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4Lh8CC2FR8z3jNB; Mon, 11 Jul 2022 03:15:19 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1657509319; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=iF4+CcqOT/SNaJ2v9z/KjRCm2YrfNlA2QzZs8x8paEo=; b=bMiM3gPdfwJZ5EH/jhlVJI3XGNxJCxUA323UDSRFZrPO2323trGSk+Ulc7OdgsxZh0QjM4 XxXABXzKn9Ciu5ToSXZqP5if5BXAA0a/3IeLHIWWBHaTECvEq+WV23KhLPmDHATRnms17y pxkEoOlPZq3arVnUQSoTze8bJn6TsvQwImCBIlvry3bkviYqSR1DpgMTXcIcVjOCRhi94Y 77EcL7MAlPJJwXa0gd+xN9FScMjTU490vJsnUt5H8rLpx/r3VvTiq63zj4bX6RgRw2zHst ivQCKu8VqOYS5BTAiKa/99BfbmMkbIkIH/PgKvplHF9i/2rTUrmdYc4AoZ74Ew== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4Lh8CC1DkBzpRH; Mon, 11 Jul 2022 03:15:19 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 26B3FJwq046226; Mon, 11 Jul 2022 03:15:19 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 26B3FJEF046225; Mon, 11 Jul 2022 03:15:19 GMT (envelope-from git) Date: Mon, 11 Jul 2022 03:15:19 GMT Message-Id: <202207110315.26B3FJEF046225@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Philip Paeps Subject: git: 1549a6172f9d - stable/13 - ipmi: correctly handle ipmb requests List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-branches@freebsd.org X-BeenThere: dev-commits-src-branches@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: philip X-Git-Repository: src X-Git-Refname: refs/heads/stable/13 X-Git-Reftype: branch X-Git-Commit: 1549a6172f9d2957e023398d01a675912683afb9 Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1657509319; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=iF4+CcqOT/SNaJ2v9z/KjRCm2YrfNlA2QzZs8x8paEo=; b=qC8ELGgZ6VdLcGuYvnCRPCmjzUJ1/NfnMjUcqulrcyhrTG+mPR6pcrtTGxRMFTEeOVXk7y XPNX3XdLXsTtMZKfRzqeFWKf8YkuHvaEjQV0D78zusvdohO/Q8Yj1lfDX0hWTSrJACJeWT 5/i1mx9ng+XUQTGfC09P1xbvVIOn7A6bQUWIk3EK4NvCbuMU+YZocY+qAxexBxW/S6/A+z DVEr4ZQpNs9uOVdA7mELLS7Nivk7AbAYsas7sHf2rF7XteB6Ek2ZeMFJ0xaDw6W196kAxT B259z1ZiwF6cmM79+P+2VGMzf+zFtrt+CpV3qXCexg1aLfYBnSthhqLI6KflcA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1657509319; a=rsa-sha256; cv=none; b=Qe2NyJvAeYRuaAI5/4xslvBYO3Zcwdd53qum3BKmyMwYwRWri8pYsZwmQlJYZY5aLcpmFy 84sL+BOMAlBSbnOK44NTIqEIQpbc0pFlYUfc3KhFoRso/ORoAW6cLirJCYVuPGwZVyykhA kCS3DNycIXSur9KyTJXH1t3bSFyL1hCciW0KbOd0525aG2ZyYPCjubPKGArPUbH7uPFX0O DmkxhJlYor5QbgGUZQSW2NRPJ5n9gEWBCiRSwgvKt2Et+CZKHCEyWJ++xYDty4hD6oSH6E osuOtmE6Uqx9+mpZ8U0YfZZ8Zx9jdiJj+k6J0E7Z33bdJVZvWSHVv0n23GbZ5g== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch stable/13 has been updated by philip: URL: https://cgit.FreeBSD.org/src/commit/?id=1549a6172f9d2957e023398d01a675912683afb9 commit 1549a6172f9d2957e023398d01a675912683afb9 Author: Yuri AuthorDate: 2022-07-04 04:55:18 +0000 Commit: Philip Paeps CommitDate: 2022-07-11 03:10:05 +0000 ipmi: correctly handle ipmb requests Handle IPMB requests using SEND_MSG (sent as driver request as we do not need to return anything back to userland for this) and GET_MSG (sent as usual request so we can return the data for RECEIVE_MSG ioctl) pair. This fixes fetching complete sensor data from boards (e.g. HP ProLiant DL380 Gen10). Reviewed by: philip Differential Revision: https://reviews.freebsd.org/D35605 (cherry picked from commit 18db96dbfd4a09063a0abcefd51fa8d2aeb115d6) (cherry picked from commit c4995b69db93fdab5fe375eae129aeff1cbca1bb) --- sys/dev/ipmi/ipmi.c | 184 ++++++++++++++++++++---------------------------- sys/dev/ipmi/ipmivars.h | 13 ++-- sys/sys/ipmi.h | 4 +- 3 files changed, 85 insertions(+), 116 deletions(-) diff --git a/sys/dev/ipmi/ipmi.c b/sys/dev/ipmi/ipmi.c index 3a9fb80fc208..3666b8dd2033 100644 --- a/sys/dev/ipmi/ipmi.c +++ b/sys/dev/ipmi/ipmi.c @@ -76,12 +76,6 @@ __FBSDID("$FreeBSD$"); IPMI_INIT_DRIVER_REQUEST((req), (addr), (cmd), (reqlen), \ (replylen)) -#ifdef IPMB -static int ipmi_ipmb_checksum(u_char, int); -static int ipmi_ipmb_send_message(device_t, u_char, u_char, u_char, - u_char, u_char, int) -#endif - static d_ioctl_t ipmi_ioctl; static d_poll_t ipmi_poll; static d_open_t ipmi_open; @@ -245,83 +239,16 @@ ipmi_dtor(void *arg) free(dev, M_IPMI); } -#ifdef IPMB -static int +static u_char ipmi_ipmb_checksum(u_char *data, int len) { u_char sum = 0; - for (; len; len--) { + for (; len; len--) sum += *data++; - } return (-sum); } -/* XXX: Needs work */ -static int -ipmi_ipmb_send_message(device_t dev, u_char channel, u_char netfn, - u_char command, u_char seq, u_char *data, int data_len) -{ - struct ipmi_softc *sc = device_get_softc(dev); - struct ipmi_request *req; - u_char slave_addr = 0x52; - int error; - - IPMI_ALLOC_DRIVER_REQUEST(req, IPMI_ADDR(IPMI_APP_REQUEST, 0), - IPMI_SEND_MSG, data_len + 8, 0); - req->ir_request[0] = channel; - req->ir_request[1] = slave_addr; - req->ir_request[2] = IPMI_ADDR(netfn, 0); - req->ir_request[3] = ipmi_ipmb_checksum(&req->ir_request[1], 2); - req->ir_request[4] = sc->ipmi_address; - req->ir_request[5] = IPMI_ADDR(seq, sc->ipmi_lun); - req->ir_request[6] = command; - - bcopy(data, &req->ir_request[7], data_len); - temp[data_len + 7] = ipmi_ipmb_checksum(&req->ir_request[4], - data_len + 3); - - ipmi_submit_driver_request(sc, req); - error = req->ir_error; - - return (error); -} - -static int -ipmi_handle_attn(struct ipmi_softc *sc) -{ - struct ipmi_request *req; - int error; - - device_printf(sc->ipmi_dev, "BMC has a message\n"); - IPMI_ALLOC_DRIVER_REQUEST(req, IPMI_ADDR(IPMI_APP_REQUEST, 0), - IPMI_GET_MSG_FLAGS, 0, 1); - - ipmi_submit_driver_request(sc, req); - - if (req->ir_error == 0 && req->ir_compcode == 0) { - if (req->ir_reply[0] & IPMI_MSG_BUFFER_FULL) { - device_printf(sc->ipmi_dev, "message buffer full"); - } - if (req->ir_reply[0] & IPMI_WDT_PRE_TIMEOUT) { - device_printf(sc->ipmi_dev, - "watchdog about to go off"); - } - if (req->ir_reply[0] & IPMI_MSG_AVAILABLE) { - IPMI_ALLOC_DRIVER_REQUEST(req, - IPMI_ADDR(IPMI_APP_REQUEST, 0), IPMI_GET_MSG, 0, - 16); - - device_printf(sc->ipmi_dev, "throw out message "); - dump_buf(temp, 16); - } - } - error = req->ir_error; - - return (error); -} -#endif - static int ipmi_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int flags, struct thread *td) @@ -377,38 +304,68 @@ ipmi_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, case IPMICTL_SEND_COMMAND_32: #endif case IPMICTL_SEND_COMMAND: - /* - * XXX: Need to add proper handling of this. - */ error = copyin(req->addr, &addr, sizeof(addr)); if (error) return (error); - IPMI_LOCK(sc); - /* clear out old stuff in queue of stuff done */ - /* XXX: This seems odd. */ - while ((kreq = TAILQ_FIRST(&dev->ipmi_completed_requests))) { - TAILQ_REMOVE(&dev->ipmi_completed_requests, kreq, - ir_link); - dev->ipmi_requests--; - ipmi_free_request(kreq); + if (addr.addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE) { + kreq = ipmi_alloc_request(dev, req->msgid, + IPMI_ADDR(req->msg.netfn, 0), req->msg.cmd, + req->msg.data_len, IPMI_MAX_RX); + error = copyin(req->msg.data, kreq->ir_request, + req->msg.data_len); + if (error) { + ipmi_free_request(kreq); + return (error); + } + IPMI_LOCK(sc); + dev->ipmi_requests++; + error = sc->ipmi_enqueue_request(sc, kreq); + IPMI_UNLOCK(sc); + if (error) + return (error); + break; } - IPMI_UNLOCK(sc); - kreq = ipmi_alloc_request(dev, req->msgid, - IPMI_ADDR(req->msg.netfn, 0), req->msg.cmd, - req->msg.data_len, IPMI_MAX_RX); - error = copyin(req->msg.data, kreq->ir_request, - req->msg.data_len); - if (error) { - ipmi_free_request(kreq); - return (error); + /* Special processing for IPMB commands */ + struct ipmi_ipmb_addr *iaddr = (struct ipmi_ipmb_addr *)&addr; + + IPMI_ALLOC_DRIVER_REQUEST(kreq, IPMI_ADDR(IPMI_APP_REQUEST, 0), + IPMI_SEND_MSG, req->msg.data_len + 8, IPMI_MAX_RX); + /* Construct the SEND MSG header */ + kreq->ir_request[0] = iaddr->channel; + kreq->ir_request[1] = iaddr->slave_addr; + kreq->ir_request[2] = IPMI_ADDR(req->msg.netfn, iaddr->lun); + kreq->ir_request[3] = + ipmi_ipmb_checksum(&kreq->ir_request[1], 2); + kreq->ir_request[4] = dev->ipmi_address; + kreq->ir_request[5] = IPMI_ADDR(0, dev->ipmi_lun); + kreq->ir_request[6] = req->msg.cmd; + /* Copy the message data */ + if (req->msg.data_len > 0) { + error = copyin(req->msg.data, &kreq->ir_request[7], + req->msg.data_len); + if (error != 0) + return (error); } + kreq->ir_request[req->msg.data_len + 7] = + ipmi_ipmb_checksum(&kreq->ir_request[4], + req->msg.data_len + 3); + error = ipmi_submit_driver_request(sc, kreq, MAX_TIMEOUT); + if (error != 0) + return (error); + + kreq = ipmi_alloc_request(dev, req->msgid, + IPMI_ADDR(IPMI_APP_REQUEST, 0), IPMI_GET_MSG, + 0, IPMI_MAX_RX); + kreq->ir_ipmb = true; + kreq->ir_ipmb_addr = IPMI_ADDR(req->msg.netfn, 0); + kreq->ir_ipmb_command = req->msg.cmd; IPMI_LOCK(sc); dev->ipmi_requests++; error = sc->ipmi_enqueue_request(sc, kreq); IPMI_UNLOCK(sc); - if (error) + if (error != 0) return (error); break; #ifdef IPMICTL_SEND_COMMAND_32 @@ -427,14 +384,8 @@ ipmi_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, IPMI_UNLOCK(sc); return (EAGAIN); } - addr.channel = IPMI_BMC_CHANNEL; - /* XXX */ - recv->recv_type = IPMI_RESPONSE_RECV_TYPE; - recv->msgid = kreq->ir_msgid; - recv->msg.netfn = IPMI_REPLY_ADDR(kreq->ir_addr) >> 2; - recv->msg.cmd = kreq->ir_command; - error = kreq->ir_error; - if (error) { + if (kreq->ir_error != 0) { + error = kreq->ir_error; TAILQ_REMOVE(&dev->ipmi_completed_requests, kreq, ir_link); dev->ipmi_requests--; @@ -442,11 +393,30 @@ ipmi_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, ipmi_free_request(kreq); return (error); } - len = kreq->ir_replylen + 1; + + recv->recv_type = IPMI_RESPONSE_RECV_TYPE; + recv->msgid = kreq->ir_msgid; + if (kreq->ir_ipmb) { + addr.channel = IPMI_IPMB_CHANNEL; + recv->msg.netfn = + IPMI_REPLY_ADDR(kreq->ir_ipmb_addr) >> 2; + recv->msg.cmd = kreq->ir_ipmb_command; + /* Get the compcode of response */ + kreq->ir_compcode = kreq->ir_reply[6]; + /* Move the reply head past response header */ + kreq->ir_reply += 7; + len = kreq->ir_replylen - 7; + } else { + addr.channel = IPMI_BMC_CHANNEL; + recv->msg.netfn = IPMI_REPLY_ADDR(kreq->ir_addr) >> 2; + recv->msg.cmd = kreq->ir_command; + len = kreq->ir_replylen + 1; + } + if (recv->msg.data_len < len && (cmd == IPMICTL_RECEIVE_MSG #ifdef IPMICTL_RECEIVE_MSG_32 - || cmd == IPMICTL_RECEIVE_MSG_32 + || cmd == IPMICTL_RECEIVE_MSG_32 #endif )) { IPMI_UNLOCK(sc); @@ -521,7 +491,7 @@ ipmi_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, * Request management. */ -static __inline void +__inline void ipmi_init_request(struct ipmi_request *req, struct ipmi_device *dev, long msgid, uint8_t addr, uint8_t command, size_t requestlen, size_t replylen) { diff --git a/sys/dev/ipmi/ipmivars.h b/sys/dev/ipmi/ipmivars.h index 7a1346655983..8c6a716adb9c 100644 --- a/sys/dev/ipmi/ipmivars.h +++ b/sys/dev/ipmi/ipmivars.h @@ -54,6 +54,9 @@ struct ipmi_request { uint8_t ir_addr; uint8_t ir_command; uint8_t ir_compcode; + bool ir_ipmb; + uint8_t ir_ipmb_addr; + uint8_t ir_ipmb_command; }; #define MAX_RES 3 @@ -128,10 +131,6 @@ struct ipmi_softc { #define ipmi_ssif_smbus_address _iface.ssif.smbus_address #define ipmi_ssif_smbus _iface.ssif.smbus -struct ipmi_ipmb { - u_char foo; -}; - #define KCS_MODE 0x01 #define SMIC_MODE 0x02 #define BT_MODE 0x03 @@ -230,6 +229,8 @@ int ipmi_detach(device_t); void ipmi_release_resources(device_t); /* Manage requests. */ +void ipmi_init_request(struct ipmi_request *, struct ipmi_device *, long, + uint8_t, uint8_t, size_t, size_t); struct ipmi_request *ipmi_alloc_request(struct ipmi_device *, long, uint8_t, uint8_t, size_t, size_t); void ipmi_complete_request(struct ipmi_softc *, struct ipmi_request *); @@ -251,10 +252,6 @@ int ipmi_kcs_probe_align(struct ipmi_softc *); int ipmi_smic_attach(struct ipmi_softc *); int ipmi_ssif_attach(struct ipmi_softc *, device_t, int); -#ifdef IPMB -int ipmi_handle_attn(struct ipmi_softc *); -#endif - extern devclass_t ipmi_devclass; extern int ipmi_attached; diff --git a/sys/sys/ipmi.h b/sys/sys/ipmi.h index 3c805bac099d..9b46d1869101 100644 --- a/sys/sys/ipmi.h +++ b/sys/sys/ipmi.h @@ -33,9 +33,11 @@ #define IPMI_MAX_ADDR_SIZE 0x20 #define IPMI_MAX_RX 1024 -#define IPMI_BMC_SLAVE_ADDR 0x20 /* Linux Default slave address */ + #define IPMI_BMC_CHANNEL 0x0f /* Linux BMC channel */ +#define IPMI_IPMB_CHANNEL 0x00 +#define IPMI_BMC_SLAVE_ADDR 0x20 /* Linux Default slave address */ #define IPMI_BMC_SMS_LUN 0x02 #define IPMI_SYSTEM_INTERFACE_ADDR_TYPE 0x0c