From owner-svn-src-all@freebsd.org Tue May 24 21:20:19 2016 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 04C8EB490A9; Tue, 24 May 2016 21:20:19 +0000 (UTC) (envelope-from adrian@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 mx1.freebsd.org (Postfix) with ESMTPS id 89E3F18A9; Tue, 24 May 2016 21:20:18 +0000 (UTC) (envelope-from adrian@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u4OLKHu0036441; Tue, 24 May 2016 21:20:17 GMT (envelope-from adrian@FreeBSD.org) Received: (from adrian@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u4OLKHuL036436; Tue, 24 May 2016 21:20:17 GMT (envelope-from adrian@FreeBSD.org) Message-Id: <201605242120.u4OLKHuL036436@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: adrian set sender to adrian@FreeBSD.org using -f From: Adrian Chadd Date: Tue, 24 May 2016 21:20:17 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r300628 - in head/sys/dev/bhnd: . bhndb cores/chipc cores/pci cores/pcie2 siba X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.22 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: Tue, 24 May 2016 21:20:19 -0000 Author: adrian Date: Tue May 24 21:20:17 2016 New Revision: 300628 URL: https://svnweb.freebsd.org/changeset/base/300628 Log: [bhnd] Normalize bhnd(4) device matching API This unifies handling of core, chip, and board-level device matching, and adds support for matching device drivers against the bus attach type (e.g. SoC vs WiFi adapter). Core-level quirks on Broadcom's chipsets generally are specific to some combination of chip model, core revision, chip package (e.g. 12x9 SMT package), SROM revision, etc. Unifying the match APIs for all three attribute types (core, chip, board/srom) allows defining a single device quirk table that matches across all of those attributes. Submitted by: Landon Fuller Differential Revision: https://reviews.freebsd.org/D6515 Added: head/sys/dev/bhnd/bhnd_match.h (contents, props changed) Modified: head/sys/dev/bhnd/bhnd.h head/sys/dev/bhnd/bhnd_subr.c head/sys/dev/bhnd/bhndb/bhndb.c head/sys/dev/bhnd/bhndb/bhndb_hwdata.c head/sys/dev/bhnd/bhndb/bhndb_pci_hwdata.c head/sys/dev/bhnd/bhndb/bhndb_subr.c head/sys/dev/bhnd/cores/chipc/chipc.c head/sys/dev/bhnd/cores/pci/bhnd_pci.c head/sys/dev/bhnd/cores/pci/bhnd_pci_hostb.c head/sys/dev/bhnd/cores/pcie2/bhnd_pcie2.c head/sys/dev/bhnd/cores/pcie2/bhnd_pcie2_hostb.c head/sys/dev/bhnd/siba/siba_bhndb.c Modified: head/sys/dev/bhnd/bhnd.h ============================================================================== --- head/sys/dev/bhnd/bhnd.h Tue May 24 21:13:33 2016 (r300627) +++ head/sys/dev/bhnd/bhnd.h Tue May 24 21:20:17 2016 (r300628) @@ -41,6 +41,7 @@ #include "bhnd_types.h" #include "bhnd_debug.h" #include "bhnd_bus_if.h" +#include "bhnd_match.h" extern devclass_t bhnd_devclass; extern devclass_t bhnd_hostb_devclass; @@ -169,17 +170,6 @@ struct bhnd_core_info { int unit; /**< bus-assigned core unit */ }; - -/** - * A hardware revision match descriptor. - */ -struct bhnd_hwrev_match { - uint16_t start; /**< first revision, or BHND_HWREV_INVALID - to match on any revision. */ - uint16_t end; /**< last revision, or BHND_HWREV_INVALID - to match on any revision. */ -}; - /** * A bhnd(4) bus resource. * @@ -193,223 +183,70 @@ struct bhnd_resource { * is MMIO accessible. */ }; -/** - * Wildcard hardware revision match descriptor. - */ -#define BHND_HWREV_ANY { BHND_HWREV_INVALID, BHND_HWREV_INVALID } -#define BHND_HWREV_IS_ANY(_m) \ - ((_m)->start == BHND_HWREV_INVALID && (_m)->end == BHND_HWREV_INVALID) - -/** - * Hardware revision match descriptor for an inclusive range. - * - * @param _start The first applicable hardware revision. - * @param _end The last applicable hardware revision, or BHND_HWREV_INVALID - * to match on any revision. - */ -#define BHND_HWREV_RANGE(_start, _end) { _start, _end } - -/** - * Hardware revision match descriptor for a single revision. - * - * @param _hwrev The hardware revision to match on. - */ -#define BHND_HWREV_EQ(_hwrev) BHND_HWREV_RANGE(_hwrev, _hwrev) - -/** - * Hardware revision match descriptor for any revision equal to or greater - * than @p _start. - * - * @param _start The first hardware revision to match on. - */ -#define BHND_HWREV_GTE(_start) BHND_HWREV_RANGE(_start, BHND_HWREV_INVALID) - -/** - * Hardware revision match descriptor for any revision equal to or less - * than @p _end. - * - * @param _end The last hardware revision to match on. - */ -#define BHND_HWREV_LTE(_end) BHND_HWREV_RANGE(0, _end) - - -/** A core match descriptor. */ -struct bhnd_core_match { - uint16_t vendor; /**< required JEP106 device vendor or BHND_MFGID_INVALID. */ - uint16_t device; /**< required core ID or BHND_COREID_INVALID */ - struct bhnd_hwrev_match hwrev; /**< matching revisions. */ - bhnd_devclass_t class; /**< required class or BHND_DEVCLASS_INVALID */ - int unit; /**< required core unit, or -1 */ -}; - -/** - * Core match descriptor matching against the given @p _vendor, @p _device, - * and @p _hwrev match descriptors. - */ -#define BHND_CORE_MATCH(_vendor, _device, _hwrev) \ - { _vendor, _device, _hwrev, BHND_DEVCLASS_INVALID, -1 } - -/** - * Wildcard core match descriptor. - */ -#define BHND_CORE_MATCH_ANY \ - { \ - .vendor = BHND_MFGID_INVALID, \ - .device = BHND_COREID_INVALID, \ - .hwrev = BHND_HWREV_ANY, \ - .class = BHND_DEVCLASS_INVALID, \ - .unit = -1 \ - } - /** - * A chipset match descriptor. - * - * @warning Matching on board/nvram attributes relies on NVRAM access, and will - * fail if a valid NVRAM device cannot be found, or is not yet attached. + * Device quirk table descriptor. */ -struct bhnd_chip_match { - /** Select fields to be matched */ - uint16_t - match_id:1, - match_rev:1, - match_pkg:1, - match_bvendor:1, - match_btype:1, - match_brev:1, - match_srom_rev:1, - match_any:1, - match_flags_unused:8; - - uint16_t chip_id; /**< required chip id */ - struct bhnd_hwrev_match chip_rev; /**< matching chip revisions */ - uint8_t chip_pkg; /**< required package */ - - uint16_t board_vendor; /**< required board vendor */ - uint16_t board_type; /**< required board type */ - struct bhnd_hwrev_match board_rev; /**< matching board revisions */ - - struct bhnd_hwrev_match board_srom_rev; /**< matching board srom revisions */ +struct bhnd_device_quirk { + struct bhnd_device_match desc; /**< device match descriptor */ + uint32_t quirks; /**< quirk flags */ }; -#define BHND_CHIP_MATCH_ANY \ - { .match_any = 1 } - -#define BHND_CHIP_MATCH_IS_ANY(_m) \ - ((_m)->match_any == 1) - -#define BHND_CHIP_MATCH_REQ_BOARD_INFO(_m) \ - ((_m)->match_srom_rev || (_m)->match_bvendor || \ - (_m)->match_btype || (_m)->match_brev) - -/** Set the required chip ID within a bhnd_chip_match instance */ -#define BHND_CHIP_ID(_cid) \ - .match_id = 1, .chip_id = BHND_CHIPID_BCM ## _cid - -/** Set the required chip revision range within a bhnd_chip_match instance */ -#define BHND_CHIP_REV(_rev) \ - .match_rev = 1, .chip_rev = BHND_ ## _rev +#define BHND_CORE_QUIRK(_rev, _flags) \ + {{ BHND_MATCH_CORE_REV(_rev) }, (_flags) } -/** Set the required package ID within a bhnd_chip_match instance */ -#define BHND_CHIP_PKG(_pkg) \ - .match_pkg = 1, .chip_pkg = BHND_PKGID_BCM ## _pkg +#define BHND_CHIP_QUIRK(_chip, _rev, _flags) \ + {{ BHND_CHIP_IR(BCM ## _chip, _rev) }, (_flags) } -/** Set the required board vendor within a bhnd_chip_match instance */ -#define BHND_CHIP_BVENDOR(_vend) \ - .match_bvendor = 1, .board_vendor = _vend +#define BHND_PKG_QUIRK(_chip, _pkg, _flags) \ + {{ BHND_CHIP_IP(BCM ## _chip, BCM ## _chip ## _pkg) }, (_flags) } -/** Set the required board type within a bhnd_chip_match instance */ -#define BHND_CHIP_BTYPE(_btype) \ - .match_btype = 1, .board_type = BHND_BOARD_ ## _btype +#define BHND_BOARD_QUIRK(_board, _flags) \ + {{ BHND_MATCH_BOARD_TYPE(_board) }, \ + (_flags) } -/** Set the required SROM revision range within a bhnd_chip_match instance */ -#define BHND_CHIP_SROMREV(_rev) \ - .match_srom_rev = 1, .board_srom_rev = BHND_ ## _rev - -/** Set the required board revision range within a bhnd_chip_match instance */ -#define BHND_CHIP_BREV(_rev) \ - .match_brev = 1, .board_rev = BHND_ ## _rev - -/** Set the required board vendor and type within a bhnd_chip_match instance */ -#define BHND_CHIP_BVT(_vend, _type) \ - BHND_CHIP_BVENDOR(_vend), BHND_CHIP_BTYPE(_type) - -/** Set the required board vendor, type, and revision within a bhnd_chip_match - * instance */ -#define BHND_CHIP_BVTR(_vend, _type, _rev) \ - BHND_CHIP_BVT(_vend, _type), BHND_CHIP_BREV(_rev) - -/** Set the required chip and package ID within a bhnd_chip_match instance */ -#define BHND_CHIP_IP(_cid, _pkg) \ - BHND_CHIP_ID(_cid), BHND_CHIP_PKG(_pkg) - -/** Set the required chip ID, package ID, and revision within a bhnd_chip_match - * instance */ -#define BHND_CHIP_IPR(_cid, _pkg, _rev) \ - BHND_CHIP_ID(_cid), BHND_CHIP_PKG(_pkg), BHND_CHIP_REV(_rev) - -/** Set the required chip ID and revision within a bhnd_chip_match - * instance */ -#define BHND_CHIP_IR(_cid, _rev) \ - BHND_CHIP_ID(_cid), BHND_CHIP_REV(_rev) - -/** - * Chipset quirk table descriptor. - */ -struct bhnd_chip_quirk { - const struct bhnd_chip_match chip; /**< chip match descriptor */ - uint32_t quirks; /**< quirk flags */ -}; - -#define BHND_CHIP_QUIRK_END { BHND_CHIP_MATCH_ANY, 0 } - -#define BHND_CHIP_QUIRK_IS_END(_q) \ - (BHND_CHIP_MATCH_IS_ANY(&(_q)->chip) && (_q)->quirks == 0) - -/** - * Device quirk table descriptor. - */ -struct bhnd_device_quirk { - struct bhnd_hwrev_match hwrev; /**< applicable hardware revisions */ - uint32_t quirks; /**< quirk flags */ -}; -#define BHND_DEVICE_QUIRK_END { BHND_HWREV_ANY, 0 } +#define BHND_DEVICE_QUIRK_END { { BHND_MATCH_ANY }, 0 } #define BHND_DEVICE_QUIRK_IS_END(_q) \ - (BHND_HWREV_IS_ANY(&(_q)->hwrev) && (_q)->quirks == 0) + (((_q)->desc.m.match_flags == 0) && (_q)->quirks == 0) enum { BHND_DF_ANY = 0, - BHND_DF_HOSTB = (1<<0) /**< core is serving as the bus' - * host bridge */ + BHND_DF_HOSTB = (1<<0), /**< core is serving as the bus' host + * bridge. implies BHND_DF_ADAPTER */ + BHND_DF_SOC = (1<<1), /**< core is attached to a native + bus (BHND_ATTACH_NATIVE) */ + BHND_DF_ADAPTER = (1<<2), /**< core is attached to a bridged + * adapter (BHND_ATTACH_ADAPTER) */ }; /** Device probe table descriptor */ struct bhnd_device { - const struct bhnd_core_match core; /**< core match descriptor */ - const char *desc; /**< device description, or NULL. */ - const struct bhnd_device_quirk *quirks_table; /**< quirks table for this device, or NULL */ - const struct bhnd_chip_quirk *chip_quirks_table; /**< chipset-specific quirks for this device, or NULL */ - uint32_t device_flags; /**< required BHND_DF_* flags */ + const struct bhnd_device_match core; /**< core match descriptor */ + const char *desc; /**< device description, or NULL. */ + const struct bhnd_device_quirk *quirks_table; /**< quirks table for this device, or NULL */ + uint32_t device_flags; /**< required BHND_DF_* flags */ }; -#define _BHND_DEVICE(_vendor, _device, _desc, _quirks, _chip_quirks, \ - _flags, ...) \ - { BHND_CORE_MATCH(BHND_MFGID_ ## _vendor, \ - BHND_COREID_ ## _device, BHND_HWREV_ANY), _desc, _quirks, \ - _chip_quirks, _flags } +#define _BHND_DEVICE(_vendor, _device, _desc, _quirks, \ + _flags, ...) \ + { { BHND_MATCH_CORE(BHND_MFGID_ ## _vendor, \ + BHND_COREID_ ## _device) }, _desc, _quirks, \ + _flags } -#define BHND_MIPS_DEVICE(_device, _desc, _quirks, _chip_quirks, ...) \ - _BHND_DEVICE(MIPS, _device, _desc, _quirks, _chip_quirks, \ +#define BHND_MIPS_DEVICE(_device, _desc, _quirks, ...) \ + _BHND_DEVICE(MIPS, _device, _desc, _quirks, \ ## __VA_ARGS__, 0) -#define BHND_ARM_DEVICE(_device, _desc, _quirks, _chip_quirks, ...) \ - _BHND_DEVICE(ARM, _device, _desc, _quirks, _chip_quirks, \ +#define BHND_ARM_DEVICE(_device, _desc, _quirks, ...) \ + _BHND_DEVICE(ARM, _device, _desc, _quirks, \ ## __VA_ARGS__, 0) -#define BHND_DEVICE(_device, _desc, _quirks, _chip_quirks, ...) \ - _BHND_DEVICE(BCM, _device, _desc, _quirks, _chip_quirks, \ +#define BHND_DEVICE(_device, _desc, _quirks, ...) \ + _BHND_DEVICE(BCM, _device, _desc, _quirks, \ ## __VA_ARGS__, 0) -#define BHND_DEVICE_END { BHND_CORE_MATCH_ANY, NULL, NULL, NULL, 0 } +#define BHND_DEVICE_END { { BHND_MATCH_ANY }, NULL, NULL, 0 } +#define BHND_DEVICE_IS_END(_d) \ + (BHND_MATCH_IS_ANY(&(_d)->core) && (_d)->desc == NULL) const char *bhnd_vendor_name(uint16_t vendor); const char *bhnd_port_type_name(bhnd_port_type port_type); @@ -447,17 +284,17 @@ bool bhnd_core_matches( bool bhnd_chip_matches( const struct bhnd_chipid *chipid, - const struct bhnd_board_info *binfo, const struct bhnd_chip_match *desc); +bool bhnd_board_matches( + const struct bhnd_board_info *info, + const struct bhnd_board_match *desc); + bool bhnd_hwrev_matches(uint16_t hwrev, const struct bhnd_hwrev_match *desc); -uint32_t bhnd_chip_quirks(device_t dev, - const struct bhnd_chip_quirk *table); - bool bhnd_device_matches(device_t dev, - const struct bhnd_core_match *desc); + const struct bhnd_device_match *desc); const struct bhnd_device *bhnd_device_lookup(device_t dev, const struct bhnd_device *table, @@ -469,7 +306,6 @@ uint32_t bhnd_device_quirks(device_t struct bhnd_core_info bhnd_get_core_info(device_t dev); - int bhnd_alloc_resources(device_t dev, struct resource_spec *rs, struct bhnd_resource **res); Added: head/sys/dev/bhnd/bhnd_match.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/dev/bhnd/bhnd_match.h Tue May 24 21:20:17 2016 (r300628) @@ -0,0 +1,291 @@ +/*- + * Copyright (c) 2015-2016 Landon Fuller + * All rights reserved. + * + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * $FreeBSD$ + */ + +#ifndef _BHND_BHND_MATCH_H_ +#define _BHND_BHND_MATCH_H_ + +#include "bhnd_types.h" + +/** + * A hardware revision match descriptor. + */ +struct bhnd_hwrev_match { + uint16_t start; /**< first revision, or BHND_HWREV_INVALID + to match on any revision. */ + uint16_t end; /**< last revision, or BHND_HWREV_INVALID + to match on any revision. */ +}; + +/* Copy match field @p _name from @p _src */ +#define _BHND_COPY_MATCH_FIELD(_src, _name) \ + .m.match._name = (_src)->m.match._name, \ + ._name = (_src)->_name + +/* Set match field @p _name with @p _value */ +#define _BHND_SET_MATCH_FIELD(_name, _value) \ + .m.match._name = 1, ._name = _value + +/** + * Wildcard hardware revision match descriptor. + */ +#define BHND_HWREV_ANY { BHND_HWREV_INVALID, BHND_HWREV_INVALID } +#define BHND_HWREV_IS_ANY(_m) \ + ((_m)->start == BHND_HWREV_INVALID && (_m)->end == BHND_HWREV_INVALID) + +/** + * Hardware revision match descriptor for an inclusive range. + * + * @param _start The first applicable hardware revision. + * @param _end The last applicable hardware revision, or BHND_HWREV_INVALID + * to match on any revision. + */ +#define BHND_HWREV_RANGE(_start, _end) { _start, _end } + +/** + * Hardware revision match descriptor for a single revision. + * + * @param _hwrev The hardware revision to match on. + */ +#define BHND_HWREV_EQ(_hwrev) BHND_HWREV_RANGE(_hwrev, _hwrev) + +/** + * Hardware revision match descriptor for any revision equal to or greater + * than @p _start. + * + * @param _start The first hardware revision to match on. + */ +#define BHND_HWREV_GTE(_start) BHND_HWREV_RANGE(_start, BHND_HWREV_INVALID) + +/** + * Hardware revision match descriptor for any revision equal to or less + * than @p _end. + * + * @param _end The last hardware revision to match on. + */ +#define BHND_HWREV_LTE(_end) BHND_HWREV_RANGE(0, _end) + +/** + * A bhnd(4) core match descriptor. + */ +struct bhnd_core_match { + /** Select fields to be matched */ + union { + uint8_t match_flags; + struct { + uint8_t + core_vendor:1, + core_id:1, + core_rev:1, + core_class:1, + core_unit:1, + flags_unused:3; + } match; + } m; + + uint16_t core_vendor; /**< required JEP106 device vendor */ + uint16_t core_id; /**< required core ID */ + struct bhnd_hwrev_match core_rev; /**< matching core revisions. */ + bhnd_devclass_t core_class; /**< required bhnd class */ + int core_unit; /**< required core unit */ +}; + +#define _BHND_CORE_MATCH_COPY(_src) \ + _BHND_COPY_MATCH_FIELD(_src, core_vendor), \ + _BHND_COPY_MATCH_FIELD(_src, core_id), \ + _BHND_COPY_MATCH_FIELD(_src, core_rev), \ + _BHND_COPY_MATCH_FIELD(_src, core_class), \ + _BHND_COPY_MATCH_FIELD(_src, core_unit) \ + +#define BHND_MATCH_CORE_VENDOR(_v) _BHND_SET_MATCH_FIELD(core_vendor, _v) +#define BHND_MATCH_CORE_ID(_id) _BHND_SET_MATCH_FIELD(core_id, _id) +#define BHND_MATCH_CORE_REV(_rev) _BHND_SET_MATCH_FIELD(core_rev, \ + BHND_ ## _rev) +#define BHND_MATCH_CORE_CLASS(_cls) _BHND_SET_MATCH_FIELD(core_class, _cls) +#define BHND_MATCH_CORE_UNIT(_unit) _BHND_SET_MATCH_FIELD(core_unit, _unit) + +/** + * Match against the given @p _vendor and @p _id, + */ +#define BHND_MATCH_CORE(_vendor, _id) \ + BHND_MATCH_CORE_VENDOR(_vendor), \ + BHND_MATCH_CORE_ID(_id) + +/** + * A bhnd(4) chip match descriptor. + */ +struct bhnd_chip_match { + /** Select fields to be matched */ + union { + uint8_t match_flags; + struct { + uint8_t + chip_id:1, + chip_rev:1, + chip_pkg:1, + flags_unused:5; + } match; + + } m; + + uint16_t chip_id; /**< required chip id */ + struct bhnd_hwrev_match chip_rev; /**< matching chip revisions */ + uint8_t chip_pkg; /**< required package */ +}; + +#define _BHND_CHIP_MATCH_COPY(_src) \ + _BHND_COPY_MATCH_FIELD(_src, chip_id), \ + _BHND_COPY_MATCH_FIELD(_src, chip_rev), \ + _BHND_COPY_MATCH_FIELD(_src, chip_pkg) \ + +/** Set the required chip ID within a bhnd match descriptor */ +#define BHND_CHIP_ID(_cid) _BHND_SET_MATCH_FIELD(chip_id, \ + BHND_CHIPID_ ## _cid) + +/** Set the required chip revision range within a bhnd match descriptor */ +#define BHND_CHIP_REV(_rev) _BHND_SET_MATCH_FIELD(chip_rev, \ + BHND_ ## _rev) + +/** Set the required package ID within a bhnd match descriptor */ +#define BHND_CHIP_PKG(_pkg) _BHND_SET_MATCH_FIELD(chip_pkg, \ + BHND_PKGID_ ## _pkg) + +/** Set the required chip and package ID within a bhnd match descriptor */ +#define BHND_CHIP_IP(_cid, _pkg) \ + BHND_CHIP_ID(_cid), BHND_CHIP_PKG(_pkg) + +/** Set the required chip ID, package ID, and revision within a bhnd_device_match + * instance */ +#define BHND_CHIP_IPR(_cid, _pkg, _rev) \ + BHND_CHIP_ID(_cid), BHND_CHIP_PKG(_pkg), BHND_CHIP_REV(_rev) + +/** Set the required chip ID and revision within a bhnd_device_match + * instance */ +#define BHND_CHIP_IR(_cid, _rev) \ + BHND_CHIP_ID(_cid), BHND_CHIP_REV(_rev) + +/** + * A bhnd(4) board match descriptor. + */ +struct bhnd_board_match { + /** Select fields to be matched */ + union { + uint8_t match_flags; + struct { + uint8_t + board_vendor:1, + board_type:1, + board_rev:1, + board_srom_rev:1, + flags_unused:4; + } match; + } m; + + uint16_t board_vendor; /**< required board vendor */ + uint16_t board_type; /**< required board type */ + struct bhnd_hwrev_match board_rev; /**< matching board revisions */ + struct bhnd_hwrev_match board_srom_rev; /**< matching board srom revisions */ +}; + +#define _BHND_BOARD_MATCH_COPY(_src) \ + _BHND_COPY_MATCH_FIELD(_src, board_vendor), \ + _BHND_COPY_MATCH_FIELD(_src, board_type), \ + _BHND_COPY_MATCH_FIELD(_src, board_rev), \ + _BHND_COPY_MATCH_FIELD(_src, board_srom_rev) + +/** Set the required board vendor within a bhnd match descriptor */ +#define BHND_MATCH_BOARD_VENDOR(_v) _BHND_SET_MATCH_FIELD(board_vendor, _v) + +/** Set the required board type within a bhnd match descriptor */ +#define BHND_MATCH_BOARD_TYPE(_type) _BHND_SET_MATCH_FIELD(board_type, \ + BHND_BOARD_ ## _type) +/** Set the required SROM revision range within a bhnd match descriptor */ +#define BHND_MATCH_SROMREV(_rev) _BHND_SET_MATCH_FIELD(board_srom_rev, \ + BHND_HWREV_ ## _rev) + +/** Set the required board revision range within a bhnd match descriptor */ +#define BHND_MATCH_BOARD_REV(_rev) _BHND_SET_MATCH_FIELD(board_rev, \ + BHND_ ## _rev) + +/** Set the required board vendor and type within a bhnd match descriptor */ +#define BHND_MATCH_BOARD(_vend, _type) \ + BHND_MATCH_BOARD_VENDOR(_vend), BHND_MATCH_BOARD_TYPE(_type) + + +/** + * A bhnd(4) device match descriptor. + * + * @warning Matching on board attributes relies on NVRAM access, and will + * fail if a valid NVRAM device cannot be found, or is not yet attached. + */ +struct bhnd_device_match { + /** Select fields to be matched */ + union { + uint16_t match_flags; + struct { + uint16_t + core_vendor:1, + core_id:1, + core_rev:1, + core_class:1, + core_unit:1, + chip_id:1, + chip_rev:1, + chip_pkg:1, + board_vendor:1, + board_type:1, + board_rev:1, + board_srom_rev:1, + flags_unused:2; + } match; + } m; + + uint16_t core_vendor; /**< required JEP106 device vendor */ + uint16_t core_id; /**< required core ID */ + struct bhnd_hwrev_match core_rev; /**< matching core revisions. */ + bhnd_devclass_t core_class; /**< required bhnd class */ + int core_unit; /**< required core unit */ + + uint16_t chip_id; /**< required chip id */ + struct bhnd_hwrev_match chip_rev; /**< matching chip revisions */ + uint8_t chip_pkg; /**< required package */ + + uint16_t board_vendor; /**< required board vendor */ + uint16_t board_type; /**< required board type */ + struct bhnd_hwrev_match board_rev; /**< matching board revisions */ + struct bhnd_hwrev_match board_srom_rev; /**< matching board srom revisions */ +}; + +/** Define a wildcard match requirement (matches on any device). */ +#define BHND_MATCH_ANY .m.match_flags = 0 +#define BHND_MATCH_IS_ANY(_m) \ + ((_m)->m.match_flags == 0) + +#endif /* _BHND_BHND_MATCH_H_ */ Modified: head/sys/dev/bhnd/bhnd_subr.c ============================================================================== --- head/sys/dev/bhnd/bhnd_subr.c Tue May 24 21:13:33 2016 (r300627) +++ head/sys/dev/bhnd/bhnd_subr.c Tue May 24 21:20:17 2016 (r300628) @@ -303,14 +303,13 @@ device_t bhnd_find_child(device_t dev, bhnd_devclass_t class, int unit) { struct bhnd_core_match md = { - .vendor = BHND_MFGID_INVALID, - .device = BHND_COREID_INVALID, - .hwrev.start = BHND_HWREV_INVALID, - .hwrev.end = BHND_HWREV_INVALID, - .class = class, - .unit = unit + BHND_MATCH_CORE_CLASS(class), + BHND_MATCH_CORE_UNIT(unit) }; + if (unit == -1) + md.m.match.core_unit = 0; + return bhnd_match_child(dev, &md); } @@ -337,9 +336,10 @@ bhnd_match_child(device_t dev, const str match = NULL; for (int i = 0; i < devcnt; i++) { - device_t dev = devlistp[i]; - if (bhnd_device_matches(dev, desc)) { - match = dev; + struct bhnd_core_info ci = bhnd_get_core_info(devlistp[i]); + + if (bhnd_core_matches(&ci, desc)) { + match = devlistp[i]; goto done; } } @@ -437,12 +437,7 @@ bhnd_find_core(const struct bhnd_core_in bhnd_devclass_t class) { struct bhnd_core_match md = { - .vendor = BHND_MFGID_INVALID, - .device = BHND_COREID_INVALID, - .hwrev.start = BHND_HWREV_INVALID, - .hwrev.end = BHND_HWREV_INVALID, - .class = class, - .unit = -1 + BHND_MATCH_CORE_CLASS(class) }; return bhnd_match_core(cores, num_cores, &md); @@ -461,22 +456,21 @@ bool bhnd_core_matches(const struct bhnd_core_info *core, const struct bhnd_core_match *desc) { - if (desc->vendor != BHND_MFGID_INVALID && - desc->vendor != core->vendor) + if (desc->m.match.core_vendor && desc->core_vendor != core->vendor) return (false); - if (desc->device != BHND_COREID_INVALID && - desc->device != core->device) + if (desc->m.match.core_id && desc->core_id != core->device) return (false); - if (desc->unit != -1 && desc->unit != core->unit) + if (desc->m.match.core_unit && desc->core_unit != core->unit) return (false); - if (!bhnd_hwrev_matches(core->hwrev, &desc->hwrev)) + if (desc->m.match.core_rev && + !bhnd_hwrev_matches(core->hwrev, &desc->core_rev)) return (false); - if (desc->class != BHND_DEVCLASS_INVALID && - desc->class != bhnd_core_class(core)) + if (desc->m.match.core_class && + desc->core_class != bhnd_core_class(core)) return (false); return true; @@ -486,7 +480,6 @@ bhnd_core_matches(const struct bhnd_core * Return true if the @p chip matches @p desc. * * @param chip A bhnd chip identifier. - * @param board The bhnd board info, or NULL if unavailable. * @param desc A match descriptor to compare against @p chip. * * @retval true if @p chip matches @p match @@ -494,46 +487,49 @@ bhnd_core_matches(const struct bhnd_core */ bool bhnd_chip_matches(const struct bhnd_chipid *chip, - const struct bhnd_board_info *board, const struct bhnd_chip_match *desc) { - /* Explicit wildcard match */ - if (desc->match_any) - return (true); - - /* If board_info is missing, but required, we cannot match. */ - if (BHND_CHIP_MATCH_REQ_BOARD_INFO(desc) && board == NULL) - return (false); - - - /* Chip matching */ - if (desc->match_id && chip->chip_id != desc->chip_id) + if (desc->m.match.chip_id && chip->chip_id != desc->chip_id) return (false); - if (desc->match_pkg && chip->chip_pkg != desc->chip_pkg) + if (desc->m.match.chip_pkg && chip->chip_pkg != desc->chip_pkg) return (false); - if (desc->match_rev && + if (desc->m.match.chip_rev && !bhnd_hwrev_matches(chip->chip_rev, &desc->chip_rev)) return (false); + return (true); +} - /* Board info matching */ - if (desc->match_srom_rev && +/** + * Return true if the @p board matches @p desc. + * + * @param board The bhnd board info. + * @param desc A match descriptor to compare against @p board. + * + * @retval true if @p chip matches @p match + * @retval false if @p chip does not match @p match. + */ +bool +bhnd_board_matches(const struct bhnd_board_info *board, + const struct bhnd_board_match *desc) +{ + if (desc->m.match.board_srom_rev && !bhnd_hwrev_matches(board->board_srom_rev, &desc->board_srom_rev)) return (false); - if (desc->match_bvendor && board->board_vendor != desc->board_vendor) + if (desc->m.match.board_vendor && + board->board_vendor != desc->board_vendor) return (false); - if (desc->match_btype && board->board_type != desc->board_type) + if (desc->m.match.board_type && board->board_type != desc->board_type) return (false); - if (desc->match_brev && + if (desc->m.match.board_rev && !bhnd_hwrev_matches(board->board_rev, &desc->board_rev)) return (false); - return (true); } @@ -570,16 +566,59 @@ bhnd_hwrev_matches(uint16_t hwrev, const * @retval false if @p dev does not match @p match. */ bool -bhnd_device_matches(device_t dev, const struct bhnd_core_match *desc) +bhnd_device_matches(device_t dev, const struct bhnd_device_match *desc) { - struct bhnd_core_info ci = { - .vendor = bhnd_get_vendor(dev), - .device = bhnd_get_device(dev), - .unit = bhnd_get_core_unit(dev), - .hwrev = bhnd_get_hwrev(dev) - }; + struct bhnd_core_info core; + const struct bhnd_chipid *chip; + struct bhnd_board_info board; + device_t parent; + int error; - return bhnd_core_matches(&ci, desc); + /* Construct individual match descriptors */ + struct bhnd_core_match m_core = { _BHND_CORE_MATCH_COPY(desc) }; + struct bhnd_chip_match m_chip = { _BHND_CHIP_MATCH_COPY(desc) }; + struct bhnd_board_match m_board = { _BHND_BOARD_MATCH_COPY(desc) }; + + /* Fetch and match core info */ + if (m_core.m.match_flags) { + /* Only applicable to bhnd-attached cores */ + parent = device_get_parent(dev); + if (device_get_devclass(parent) != bhnd_devclass) { + device_printf(dev, "attempting to match core " + "attributes against non-core device\n"); + return (false); + } + + core = bhnd_get_core_info(dev); + if (!bhnd_core_matches(&core, &m_core)) + return (false); + } + + /* Fetch and match chip info */ + if (m_chip.m.match_flags) { + chip = bhnd_get_chipid(dev); + + if (!bhnd_chip_matches(chip, &m_chip)) + return (false); + } + + /* Fetch and match board info. + * + * This is not available until after NVRAM is up; earlier device + * matches should not include board requirements */ + if (m_board.m.match_flags) { + if ((error = bhnd_read_board_info(dev, &board))) { + device_printf(dev, "failed to read required board info " + "during device matching: %d\n", error); + return (false); + } + + if (!bhnd_board_matches(&board, &m_board)) + return (false); + } + + /* All matched */ + return (true); } /** @@ -598,11 +637,14 @@ bhnd_device_lookup(device_t dev, const s { const struct bhnd_device *entry; device_t hostb, parent; + bhnd_attach_type attach_type; + uint32_t dflags; parent = device_get_parent(dev); hostb = bhnd_find_hostb_device(parent); + attach_type = bhnd_get_attach_type(dev); - for (entry = table; entry->desc != NULL; entry = + for (entry = table; !BHND_DEVICE_IS_END(entry); entry = (const struct bhnd_device *) ((const char *) entry + entry_size)) { /* match core info */ @@ -610,10 +652,23 @@ bhnd_device_lookup(device_t dev, const s continue; /* match device flags */ - if (entry->device_flags & BHND_DF_HOSTB) { + dflags = entry->device_flags; + + /* hostb implies BHND_ATTACH_ADAPTER requirement */ + if (dflags & BHND_DF_HOSTB) + dflags |= BHND_DF_ADAPTER; + + if (dflags & BHND_DF_ADAPTER) + if (attach_type != BHND_ATTACH_ADAPTER) + continue; + + if (dflags & BHND_DF_HOSTB) if (dev != hostb) continue; - } + + if (dflags & BHND_DF_SOC) + if (attach_type != BHND_ATTACH_NATIVE) + continue; /* device found */ return (entry); @@ -624,66 +679,10 @@ bhnd_device_lookup(device_t dev, const s } /** - * Scan @p table for all quirk flags applicable to @p dev's chip identifier - * (as returned by bhnd_get_chipid). - * - * @param dev A bhnd device. - * @param table The chip quirk table to search. - * - * @return returns all matching quirk flags. - */ -uint32_t -bhnd_chip_quirks(device_t dev, const struct bhnd_chip_quirk *table) -{ - struct bhnd_board_info bi, *board; - const struct bhnd_chipid *cid; - const struct bhnd_chip_quirk *qent; - uint32_t quirks; - int error; - bool need_boardinfo; - - cid = bhnd_get_chipid(dev); - quirks = 0; - need_boardinfo = 0; - board = NULL; - - /* Determine whether quirk matching requires board_info; we want to - * avoid fetching board_info for early devices (e.g. ChipCommon) - * that are brought up prior to NVRAM being readable. */ - for (qent = table; !BHND_CHIP_QUIRK_IS_END(qent); qent++) { - if (!BHND_CHIP_MATCH_REQ_BOARD_INFO(&qent->chip)) - continue; - - need_boardinfo = true; - break; - } - - /* If required, fetch board info */ - if (need_boardinfo) { - error = bhnd_read_board_info(dev, &bi); - if (!error) { - board = &bi; - } else { - device_printf(dev, "failed to read required board info " - "during quirk matching: %d\n", error); - } - } - - /* Apply all matching quirk flags */ - for (qent = table; !BHND_CHIP_QUIRK_IS_END(qent); qent++) { - if (bhnd_chip_matches(cid, board, &qent->chip)) - quirks |= qent->quirks; - } - - return (quirks); -} - -/** - * Scan @p table for all quirk flags applicable to @p dev. + * Scan the device @p table for all quirk flags applicable to @p dev. * * @param dev A bhnd device to match against @p table. * @param table The device table to search. - * @param entry_size The @p table entry size, in bytes. * * @return returns all matching quirk flags. */ @@ -692,32 +691,25 @@ bhnd_device_quirks(device_t dev, const s size_t entry_size) { const struct bhnd_device *dent; - const struct bhnd_device_quirk *qtable, *qent; + const struct bhnd_device_quirk *qent, *qtable; uint32_t quirks; - uint16_t hwrev; - hwrev = bhnd_get_hwrev(dev); - quirks = 0; + /* Locate the device entry */ + if ((dent = bhnd_device_lookup(dev, table, entry_size)) == NULL) + return (0); - /* Find the quirk table */ - if ((dent = bhnd_device_lookup(dev, table, entry_size)) == NULL) { - /* This is almost certainly a (caller) implementation bug */ - device_printf(dev, "quirk lookup did not match any device\n"); + /* Quirks table is optional */ + qtable = dent->quirks_table; + if (qtable == NULL) return (0); - } /* Collect matching device quirk entries */ - if ((qtable = dent->quirks_table) != NULL) { - for (qent = qtable; !BHND_DEVICE_QUIRK_IS_END(qent); qent++) { - if (bhnd_hwrev_matches(hwrev, &qent->hwrev)) - quirks |= qent->quirks; - } + quirks = 0; + for (qent = qtable; !BHND_DEVICE_QUIRK_IS_END(qent); qent++) { + if (bhnd_device_matches(dev, &qent->desc)) + quirks |= qent->quirks; } - /* Collect matching chip quirk entries */ - if (dent->chip_quirks_table != NULL) - quirks |= bhnd_chip_quirks(dev, dent->chip_quirks_table); - return (quirks); } Modified: head/sys/dev/bhnd/bhndb/bhndb.c ============================================================================== --- head/sys/dev/bhnd/bhndb/bhndb.c Tue May 24 21:13:33 2016 (r300627) +++ head/sys/dev/bhnd/bhndb/bhndb.c Tue May 24 21:20:17 2016 (r300628) @@ -194,13 +194,15 @@ bhndb_hw_matches(device_t *devlist, int { *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***