From owner-svn-src-head@freebsd.org Fri Sep 25 16:44:02 2020 Return-Path: Delivered-To: svn-src-head@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id C999C3FC9C7; Fri, 25 Sep 2020 16:44:02 +0000 (UTC) (envelope-from mmel@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 "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4Byd6B4yGtz4DGq; Fri, 25 Sep 2020 16:44:02 +0000 (UTC) (envelope-from mmel@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 8DC7616475; Fri, 25 Sep 2020 16:44:02 +0000 (UTC) (envelope-from mmel@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 08PGi29t041382; Fri, 25 Sep 2020 16:44:02 GMT (envelope-from mmel@FreeBSD.org) Received: (from mmel@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 08PGi2Qg041379; Fri, 25 Sep 2020 16:44:02 GMT (envelope-from mmel@FreeBSD.org) Message-Id: <202009251644.08PGi2Qg041379@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: mmel set sender to mmel@FreeBSD.org using -f From: Michal Meloun Date: Fri, 25 Sep 2020 16:44:02 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r366161 - head/sys/dev/extres/syscon X-SVN-Group: head X-SVN-Commit-Author: mmel X-SVN-Commit-Paths: head/sys/dev/extres/syscon X-SVN-Commit-Revision: 366161 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.33 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 25 Sep 2020 16:44:02 -0000 Author: mmel Date: Fri Sep 25 16:44:01 2020 New Revision: 366161 URL: https://svnweb.freebsd.org/changeset/base/366161 Log: Refine locking inside of syscon driver. In some cases, the syscon driver may be used by consumer requiring better control about locking (ie. it may be used as registe file provider for clock driver which needs locked access to multiple registers). Add fine locking protocol methods together with bunch of helper functions in syscon driver and implement this functionality in syscon_generic driver. MFC after: 4 weeks Modified: head/sys/dev/extres/syscon/syscon.c head/sys/dev/extres/syscon/syscon_generic.c head/sys/dev/extres/syscon/syscon_if.m Modified: head/sys/dev/extres/syscon/syscon.c ============================================================================== --- head/sys/dev/extres/syscon/syscon.c Fri Sep 25 16:34:42 2020 (r366160) +++ head/sys/dev/extres/syscon/syscon.c Fri Sep 25 16:44:01 2020 (r366161) @@ -67,7 +67,13 @@ typedef TAILQ_HEAD(syscon_list, syscon) syscon_list_t; */ static int syscon_method_init(struct syscon *syscon); static int syscon_method_uninit(struct syscon *syscon); +static uint32_t syscon_method_read_4(struct syscon *syscon, bus_size_t offset); +static int syscon_method_write_4(struct syscon *syscon, bus_size_t offset, + uint32_t val); +static int syscon_method_modify_4(struct syscon *syscon, bus_size_t offset, + uint32_t clear_bits, uint32_t set_bits); + MALLOC_DEFINE(M_SYSCON, "syscon", "Syscon driver"); static syscon_list_t syscon_list = TAILQ_HEAD_INITIALIZER(syscon_list); @@ -80,6 +86,9 @@ SX_SYSINIT(syscon_topology, &syscon_topo_lock, "Syscon static syscon_method_t syscon_methods[] = { SYSCONMETHOD(syscon_init, syscon_method_init), SYSCONMETHOD(syscon_uninit, syscon_method_uninit), + SYSCONMETHOD(syscon_read_4, syscon_method_read_4), + SYSCONMETHOD(syscon_write_4, syscon_method_write_4), + SYSCONMETHOD(syscon_modify_4, syscon_method_modify_4), SYSCONMETHOD_END }; @@ -115,6 +124,39 @@ syscon_get_softc(struct syscon *syscon) return (syscon->softc); }; +static uint32_t +syscon_method_read_4(struct syscon *syscon, bus_size_t offset) +{ + uint32_t val; + + SYSCON_DEVICE_LOCK(syscon->pdev); + val = SYSCON_UNLOCKED_READ_4(syscon, offset); + SYSCON_DEVICE_UNLOCK(syscon->pdev); + return(val); +} + +static int +syscon_method_write_4(struct syscon *syscon, bus_size_t offset, uint32_t val) +{ + int rv; + + SYSCON_DEVICE_LOCK(syscon->pdev); + rv = SYSCON_UNLOCKED_WRITE_4(syscon, offset, val); + SYSCON_DEVICE_UNLOCK(syscon->pdev); + return(rv); +} + +static int +syscon_method_modify_4(struct syscon *syscon, bus_size_t offset, + uint32_t clear_bits, uint32_t set_bits) +{ + int rv; + + SYSCON_DEVICE_LOCK(syscon->pdev); + rv = SYSCON_UNLOCKED_MODIFY_4(syscon, offset, clear_bits, set_bits); + SYSCON_DEVICE_UNLOCK(syscon->pdev); + return(rv); +} /* * Create and initialize syscon object, but do not register it. */ @@ -254,14 +296,3 @@ syscon_get_by_ofw_property(device_t cdev, phandle_t cn return (0); } #endif - -int -syscon_get_handle_default(device_t dev, struct syscon **syscon) -{ - device_t parent; - - parent = device_get_parent(dev); - if (parent == NULL) - return (ENODEV); - return (SYSCON_GET_HANDLE(parent, syscon)); -} Modified: head/sys/dev/extres/syscon/syscon_generic.c ============================================================================== --- head/sys/dev/extres/syscon/syscon_generic.c Fri Sep 25 16:34:42 2020 (r366160) +++ head/sys/dev/extres/syscon/syscon_generic.c Fri Sep 25 16:44:01 2020 (r366161) @@ -55,11 +55,12 @@ __FBSDID("$FreeBSD$"); MALLOC_DECLARE(M_SYSCON); -static uint32_t syscon_generic_read_4(struct syscon *syscon, bus_size_t offset); -static int syscon_generic_write_4(struct syscon *syscon, bus_size_t offset, - uint32_t val); -static int syscon_generic_modify_4(struct syscon *syscon, bus_size_t offset, - uint32_t clear_bits, uint32_t set_bits); +static uint32_t syscon_generic_unlocked_read_4(struct syscon *syscon, + bus_size_t offset); +static int syscon_generic_unlocked_write_4(struct syscon *syscon, + bus_size_t offset, uint32_t val); +static int syscon_generic_unlocked_modify_4(struct syscon *syscon, + bus_size_t offset, uint32_t clear_bits, uint32_t set_bits); static int syscon_generic_detach(device_t dev); /* * Generic syscon driver (FDT) @@ -78,9 +79,9 @@ static struct ofw_compat_data compat_data[] = { #define SYSCON_ASSERT_UNLOCKED(_sc) mtx_assert(&(_sc)->mtx, MA_NOTOWNED); static syscon_method_t syscon_generic_methods[] = { - SYSCONMETHOD(syscon_read_4, syscon_generic_read_4), - SYSCONMETHOD(syscon_write_4, syscon_generic_write_4), - SYSCONMETHOD(syscon_modify_4, syscon_generic_modify_4), + SYSCONMETHOD(syscon_unlocked_read_4, syscon_generic_unlocked_read_4), + SYSCONMETHOD(syscon_unlocked_write_4, syscon_generic_unlocked_write_4), + SYSCONMETHOD(syscon_unlocked_modify_4, syscon_generic_unlocked_modify_4), SYSCONMETHOD_END }; @@ -88,50 +89,62 @@ DEFINE_CLASS_1(syscon_generic, syscon_generic_class, s 0, syscon_class); static uint32_t -syscon_generic_read_4(struct syscon *syscon, bus_size_t offset) +syscon_generic_unlocked_read_4(struct syscon *syscon, bus_size_t offset) { struct syscon_generic_softc *sc; uint32_t val; sc = device_get_softc(syscon->pdev); - - SYSCON_LOCK(sc); + SYSCON_ASSERT_UNLOCKED(sc); val = bus_read_4(sc->mem_res, offset); - SYSCON_UNLOCK(sc); return (val); } static int -syscon_generic_write_4(struct syscon *syscon, bus_size_t offset, uint32_t val) +syscon_generic_unlocked_write_4(struct syscon *syscon, bus_size_t offset, uint32_t val) { struct syscon_generic_softc *sc; sc = device_get_softc(syscon->pdev); - - SYSCON_LOCK(sc); + SYSCON_ASSERT_UNLOCKED(sc); bus_write_4(sc->mem_res, offset, val); - SYSCON_UNLOCK(sc); return (0); } static int -syscon_generic_modify_4(struct syscon *syscon, bus_size_t offset, +syscon_generic_unlocked_modify_4(struct syscon *syscon, bus_size_t offset, uint32_t clear_bits, uint32_t set_bits) { struct syscon_generic_softc *sc; uint32_t val; sc = device_get_softc(syscon->pdev); - - SYSCON_LOCK(sc); + SYSCON_ASSERT_UNLOCKED(sc); val = bus_read_4(sc->mem_res, offset); val &= ~clear_bits; val |= set_bits; bus_write_4(sc->mem_res, offset, val); - SYSCON_UNLOCK(sc); return (0); } +static void +syscon_generic_lock(device_t dev) +{ + struct syscon_generic_softc *sc; + + sc = device_get_softc(dev); + SYSCON_LOCK(sc); +} + +static void +syscon_generic_unlock(device_t dev) +{ + struct syscon_generic_softc *sc; + + sc = device_get_softc(dev); + SYSCON_UNLOCK(sc); +} + static int syscon_generic_probe(device_t dev) { @@ -210,6 +223,9 @@ static device_method_t syscon_generic_dmethods[] = { DEVMETHOD(device_probe, syscon_generic_probe), DEVMETHOD(device_attach, syscon_generic_attach), DEVMETHOD(device_detach, syscon_generic_detach), + + DEVMETHOD(syscon_device_lock, syscon_generic_lock), + DEVMETHOD(syscon_device_unlock, syscon_generic_unlock), DEVMETHOD_END }; Modified: head/sys/dev/extres/syscon/syscon_if.m ============================================================================== --- head/sys/dev/extres/syscon/syscon_if.m Fri Sep 25 16:34:42 2020 (r366160) +++ head/sys/dev/extres/syscon/syscon_if.m Fri Sep 25 16:44:01 2020 (r366161) @@ -35,6 +35,36 @@ HEADER { int syscon_get_handle_default(device_t dev, struct syscon **syscon); } +CODE { + #include + #include + + int + syscon_get_handle_default(device_t dev, struct syscon **syscon) + { + device_t parent; + + parent = device_get_parent(dev); + if (parent == NULL) + return (ENODEV); + return (SYSCON_GET_HANDLE(parent, syscon)); + } + + static void + syscon_device_lock_default(device_t dev) + { + + panic("syscon_device_lock is not implemented"); + }; + + static void + syscon_device_unlock_default(device_t dev) + { + + panic("syscon_device_unlock is not implemented"); + }; +} + METHOD int init { struct syscon *syscon; }; @@ -63,6 +93,38 @@ METHOD int modify_4 { uint32_t clear_bits; uint32_t set_bits; }; + +/** + * Unlocked verion of access function + */ +METHOD uint32_t unlocked_read_4 { + struct syscon *syscon; + bus_size_t offset; +}; + +METHOD int unlocked_write_4 { + struct syscon *syscon; + bus_size_t offset; + uint32_t val; +}; + +METHOD int unlocked_modify_4 { + struct syscon *syscon; + bus_size_t offset; + uint32_t clear_bits; + uint32_t set_bits; +}; + +/** +* Locking for exclusive access to underlying device +*/ +METHOD void device_lock { + device_t dev; +} DEFAULT syscon_device_lock_default; + +METHOD void device_unlock { + device_t dev; +} DEFAULT syscon_device_unlock_default; /** * Get syscon handle from parent driver