From owner-svn-src-all@freebsd.org Fri Mar 1 02:49:49 2019 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 48CE715003BC; Fri, 1 Mar 2019 02:49:49 +0000 (UTC) (envelope-from jhibbits@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) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id E02D76F9D8; Fri, 1 Mar 2019 02:49:48 +0000 (UTC) (envelope-from jhibbits@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id CDA34E5B8; Fri, 1 Mar 2019 02:49:48 +0000 (UTC) (envelope-from jhibbits@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id x212nmhm074587; Fri, 1 Mar 2019 02:49:48 GMT (envelope-from jhibbits@FreeBSD.org) Received: (from jhibbits@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id x212nloc074582; Fri, 1 Mar 2019 02:49:47 GMT (envelope-from jhibbits@FreeBSD.org) Message-Id: <201903010249.x212nloc074582@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: jhibbits set sender to jhibbits@FreeBSD.org using -f From: Justin Hibbits Date: Fri, 1 Mar 2019 02:49:47 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r344683 - in head/sys: conf powerpc/powernv X-SVN-Group: head X-SVN-Commit-Author: jhibbits X-SVN-Commit-Paths: in head/sys: conf powerpc/powernv X-SVN-Commit-Revision: 344683 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Rspamd-Queue-Id: E02D76F9D8 X-Spamd-Bar: -- Authentication-Results: mx1.freebsd.org X-Spamd-Result: default: False [-2.98 / 15.00]; local_wl_from(0.00)[FreeBSD.org]; NEURAL_HAM_MEDIUM(-1.00)[-0.999,0]; NEURAL_HAM_SHORT(-0.98)[-0.978,0]; ASN(0.00)[asn:11403, ipnet:2610:1c1:1::/48, country:US]; NEURAL_HAM_LONG(-1.00)[-1.000,0] X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 01 Mar 2019 02:49:49 -0000 Author: jhibbits Date: Fri Mar 1 02:49:47 2019 New Revision: 344683 URL: https://svnweb.freebsd.org/changeset/base/344683 Log: powerpc/powernv: Add asynchronous token management for powernv The OPAL firmware only supports a finite number of in-flight asynchronous operations. Rather than have each subsystem try to manage its own, use a central management service to hand out tokens. More work can be done to improve asynchronous behavior, such as funneling things through a future OPAL heartbeat handler, but capabilities will be added as needed. Augment the existing consumers (i2c and sensors) to use this new API. MFC after: 4 weeks Added: head/sys/powerpc/powernv/opal_async.c (contents, props changed) Modified: head/sys/conf/files.powerpc head/sys/powerpc/powernv/opal.h head/sys/powerpc/powernv/opal_dev.c head/sys/powerpc/powernv/opal_i2c.c head/sys/powerpc/powernv/opal_sensor.c Modified: head/sys/conf/files.powerpc ============================================================================== --- head/sys/conf/files.powerpc Fri Mar 1 02:43:30 2019 (r344682) +++ head/sys/conf/files.powerpc Fri Mar 1 02:49:47 2019 (r344683) @@ -189,6 +189,7 @@ powerpc/powermac/uninorth.c optional powermac powerpc/powermac/uninorthpci.c optional powermac pci powerpc/powermac/vcoregpio.c optional powermac powerpc/powernv/opal.c optional powernv +powerpc/powernv/opal_async.c optional powernv powerpc/powernv/opal_console.c optional powernv powerpc/powernv/opal_dev.c optional powernv powerpc/powernv/opal_i2c.c optional iicbus fdt powernv Modified: head/sys/powerpc/powernv/opal.h ============================================================================== --- head/sys/powerpc/powernv/opal.h Fri Mar 1 02:43:30 2019 (r344682) +++ head/sys/powerpc/powernv/opal.h Fri Mar 1 02:49:47 2019 (r344683) @@ -168,4 +168,9 @@ struct opal_ipmi_msg { uint8_t data[]; }; +int opal_init_async_tokens(int); +int opal_alloc_async_token(void); +void opal_free_async_token(int); +int opal_wait_completion(void *, uint64_t, uint64_t); + #endif Added: head/sys/powerpc/powernv/opal_async.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/powerpc/powernv/opal_async.c Fri Mar 1 02:49:47 2019 (r344683) @@ -0,0 +1,94 @@ +/*- + * Copyright (C) 2019 Justin Hibbits + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include "opal.h" + +/* + * Manage asynchronous tokens for the OPAL abstraction layer. + * + * Only a finite number of in-flight tokens are supported by OPAL, so we must be + * careful managing this. The basic design uses the vmem subsystem as a general + * purpose allocator, with wrappers to manage expected behaviors and + * requirements. + */ +static vmem_t *async_token_pool; + +/* Setup the token pool. */ +int +opal_init_async_tokens(int count) +{ + /* Only allow one initialization */ + if (async_token_pool != NULL) + return (EINVAL); + + async_token_pool = vmem_create("OPAL Async", 0, count, 1, 1, + M_WAITOK | M_FIRSTFIT); + + return (0); +} + +int +opal_alloc_async_token(void) +{ + vmem_addr_t token; + + vmem_alloc(async_token_pool, 1, M_FIRSTFIT | M_WAITOK, &token); + + return (token); +} + +void +opal_free_async_token(int token) +{ + + vmem_free(async_token_pool, token, 1); +} + +/* + * Wait for the operation watched by the token to complete. Return the result + * of the operation, error if it returns early. + */ +int +opal_wait_completion(void *buf, uint64_t size, uint64_t token) +{ + int err; + + do { + err = opal_call(OPAL_CHECK_ASYNC_COMPLETION, + vtophys(buf), size, token); + } while (err == OPAL_BUSY); + + return (err); +} Modified: head/sys/powerpc/powernv/opal_dev.c ============================================================================== --- head/sys/powerpc/powernv/opal_dev.c Fri Mar 1 02:43:30 2019 (r344682) +++ head/sys/powerpc/powernv/opal_dev.c Fri Mar 1 02:49:47 2019 (r344683) @@ -135,6 +135,7 @@ opaldev_attach(device_t dev) device_t cdev; uint64_t junk; int i, rv; + uint32_t async_count; struct ofw_bus_devinfo *dinfo; struct resource *irq; @@ -158,6 +159,10 @@ opaldev_attach(device_t dev) bus_setup_intr(dev, irq, INTR_TYPE_TTY | INTR_MPSAFE | INTR_ENTROPY, NULL, opal_intr, (void *)rman_get_start(irq), NULL); + + OF_getencprop(ofw_bus_get_node(dev), "opal-msg-async-num", + &async_count, sizeof(async_count)); + opal_init_async_tokens(async_count); for (child = OF_child(ofw_bus_get_node(dev)); child != 0; child = OF_peer(child)) { Modified: head/sys/powerpc/powernv/opal_i2c.c ============================================================================== --- head/sys/powerpc/powernv/opal_i2c.c Fri Mar 1 02:43:30 2019 (r344682) +++ head/sys/powerpc/powernv/opal_i2c.c Fri Mar 1 02:49:47 2019 (r344683) @@ -168,35 +168,28 @@ i2c_opal_send_request(uint32_t bus_id, struct opal_i2c { struct opal_msg msg; uint64_t token; - uint64_t msg_addr; int rc; - /* - * XXX: - * Async tokens should be managed globally. Since there are only a very - * few places now, use a punning of the stack address of the message. - */ - token = (uintptr_t)&msg; + token = opal_alloc_async_token(); memset(&msg, 0, sizeof(msg)); - msg_addr = pmap_kextract((vm_offset_t)&msg); rc = opal_call(OPAL_I2C_REQUEST, token, bus_id, - pmap_kextract((uint64_t)req)); + vtophys(req)); if (rc != OPAL_ASYNC_COMPLETION) - return (rc); + goto out; - do { - rc = opal_call(OPAL_CHECK_ASYNC_COMPLETION, - msg_addr, sizeof(msg), token); - } while (rc == OPAL_BUSY); + rc = opal_wait_completion(&msg, sizeof(msg), token); if (rc != OPAL_SUCCESS) - return (rc); + goto out; rc = opal_get_async_rc(msg); - return rc; +out: + opal_free_async_token(token); + + return (rc); } static int Modified: head/sys/powerpc/powernv/opal_sensor.c ============================================================================== --- head/sys/powerpc/powernv/opal_sensor.c Fri Mar 1 02:43:30 2019 (r344682) +++ head/sys/powerpc/powernv/opal_sensor.c Fri Mar 1 02:49:47 2019 (r344683) @@ -95,33 +95,28 @@ opal_sensor_get_val(uint32_t key, uint64_t *val) { struct opal_msg msg; uint32_t val32; - int i, rv; + int rv, token; - rv = opal_call(OPAL_SENSOR_READ, key, key, vtophys(&val32)); + token = opal_alloc_async_token(); + rv = opal_call(OPAL_SENSOR_READ, key, token, vtophys(&val32)); if (rv == OPAL_ASYNC_COMPLETION) { /* Sleep a little to let things settle. */ DELAY(100); bzero(&msg, sizeof(msg)); - i = 0; - do { - rv = opal_call(OPAL_CHECK_ASYNC_COMPLETION, - vtophys(&msg), sizeof(msg), key); - /* Sleep for ~100us if necessary. */ - if (rv == OPAL_BUSY) - DELAY(100); - } while (rv == OPAL_BUSY && ++i < 10); - if (rv != OPAL_SUCCESS) - return (EIO); - val32 = msg.params[0]; + rv = opal_wait_completion(&msg, sizeof(msg), token); + + if (rv == OPAL_SUCCESS) + val32 = msg.params[0]; } - if (rv != OPAL_SUCCESS) - return (EIO); - - *val = val32; + if (rv == OPAL_SUCCESS) + *val = val32; + else + rv = EIO; - return (0); + opal_free_async_token(token); + return (rv); } static int