From owner-svn-src-head@freebsd.org Sun Jul 17 13:43:02 2016 Return-Path: Delivered-To: svn-src-head@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 2351BB9CBB3; Sun, 17 Jul 2016 13:43: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 mx1.freebsd.org (Postfix) with ESMTPS id F1A0E1CA1; Sun, 17 Jul 2016 13:43:01 +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 u6HDh15W026196; Sun, 17 Jul 2016 13:43:01 GMT (envelope-from mmel@FreeBSD.org) Received: (from mmel@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u6HDh1dM026194; Sun, 17 Jul 2016 13:43:01 GMT (envelope-from mmel@FreeBSD.org) Message-Id: <201607171343.u6HDh1dM026194@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: mmel set sender to mmel@FreeBSD.org using -f From: Michal Meloun Date: Sun, 17 Jul 2016 13:43:01 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r302951 - head/sys/dev/ofw X-SVN-Group: head 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.22 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: Sun, 17 Jul 2016 13:43:02 -0000 Author: mmel Date: Sun Jul 17 13:43:00 2016 New Revision: 302951 URL: https://svnweb.freebsd.org/changeset/base/302951 Log: OFWPCI: Improve resource handling. - add new rman for prefetchable memory. Is used only if given 'ranges' property contains prefetchable memory range. - not all ranges in 'ranges' property are subject for rman's filling. Tegra for example, have two addition records which are used for 'pci 'register' -> 'assigned-address' -> 'ranges' machinery. Add sc_ranges_mask for masking not rman related ranges. - consistently pass unknown (not managed at this level) resources allocation/release/adjust requests to parent. MFC after: 3 weeks Modified: head/sys/dev/ofw/ofwpci.c head/sys/dev/ofw/ofwpci.h Modified: head/sys/dev/ofw/ofwpci.c ============================================================================== --- head/sys/dev/ofw/ofwpci.c Sun Jul 17 13:33:35 2016 (r302950) +++ head/sys/dev/ofw/ofwpci.c Sun Jul 17 13:43:00 2016 (r302951) @@ -94,6 +94,7 @@ static phandle_t ofw_pci_get_node(device * local methods */ static int ofw_pci_fill_ranges(phandle_t, struct ofw_pci_range *); +static struct rman *ofw_pci_get_rman(struct ofw_pci_softc *, int, u_int); /* * Driver methods. @@ -137,7 +138,7 @@ ofw_pci_init(device_t dev) phandle_t node; u_int32_t busrange[2]; struct ofw_pci_range *rp; - int error; + int i, error; struct ofw_pci_cell_info *cell_info; node = ofw_bus_get_node(dev); @@ -201,17 +202,27 @@ ofw_pci_init(device_t dev) } sc->sc_mem_rman.rm_type = RMAN_ARRAY; - sc->sc_mem_rman.rm_descr = "PCI Memory"; + sc->sc_mem_rman.rm_descr = "PCI Non Prefetchable Memory"; error = rman_init(&sc->sc_mem_rman); if (error != 0) { device_printf(dev, "rman_init() failed. error = %d\n", error); goto out; } - for (rp = sc->sc_range; rp < sc->sc_range + sc->sc_nrange && - rp->pci_hi != 0; rp++) { + sc->sc_pmem_rman.rm_type = RMAN_ARRAY; + sc->sc_pmem_rman.rm_descr = "PCI Prefetchable Memory"; + error = rman_init(&sc->sc_pmem_rman); + if (error != 0) { + device_printf(dev, "rman_init() failed. error = %d\n", error); + goto out; + } + + for (i = 0; i < sc->sc_nrange; i++) { error = 0; + rp = sc->sc_range + i; + if (sc->sc_range_mask & ((uint64_t)1 << i)) + continue; switch (rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) { case OFW_PCI_PHYS_HI_SPACE_CONFIG: break; @@ -221,8 +232,14 @@ ofw_pci_init(device_t dev) break; case OFW_PCI_PHYS_HI_SPACE_MEM32: case OFW_PCI_PHYS_HI_SPACE_MEM64: - error = rman_manage_region(&sc->sc_mem_rman, rp->pci, - rp->pci + rp->size - 1); + if (rp->pci_hi & OFW_PCI_PHYS_HI_PREFETCHABLE) { + sc->sc_have_pmem = 1; + error = rman_manage_region(&sc->sc_pmem_rman, + rp->pci, rp->pci + rp->size - 1); + } else { + error = rman_manage_region(&sc->sc_mem_rman, + rp->pci, rp->pci + rp->size - 1); + } break; } @@ -244,6 +261,7 @@ out: free(sc->sc_range, M_DEVBUF); rman_fini(&sc->sc_io_rman); rman_fini(&sc->sc_mem_rman); + rman_fini(&sc->sc_pmem_rman); return (error); } @@ -385,28 +403,16 @@ ofw_pci_alloc_resource(device_t bus, dev struct rman *rm; int needactivate; + needactivate = flags & RF_ACTIVE; flags &= ~RF_ACTIVE; sc = device_get_softc(bus); - switch (type) { - case SYS_RES_MEMORY: - rm = &sc->sc_mem_rman; - break; - - case SYS_RES_IOPORT: - rm = &sc->sc_io_rman; - break; - - case SYS_RES_IRQ: - return (bus_alloc_resource(bus, type, rid, start, end, count, - flags)); - - default: - device_printf(bus, "unknown resource request from %s\n", - device_get_nameunit(child)); - return (NULL); + rm = ofw_pci_get_rman(sc, type, flags); + if (rm == NULL) { + return (bus_generic_alloc_resource(bus, child, type, rid, + start, end, count, flags)); } rv = rman_reserve_resource(rm, start, end, count, flags, child); @@ -435,15 +441,24 @@ static int ofw_pci_release_resource(device_t bus, device_t child, int type, int rid, struct resource *res) { + struct ofw_pci_softc *sc; + struct rman *rm; + int error; - if (rman_get_flags(res) & RF_ACTIVE) { - int error; + sc = device_get_softc(bus); + + rm = ofw_pci_get_rman(sc, type, rman_get_flags(res)); + if (rm == NULL) { + return (bus_generic_release_resource(bus, child, type, rid, + res)); + } + KASSERT(rman_is_region_manager(res, rm), ("rman mismatch")); + if (rman_get_flags(res) & RF_ACTIVE) { error = bus_deactivate_resource(child, type, rid, res); if (error != 0) return (error); } - return (rman_release_resource(res)); } @@ -454,63 +469,62 @@ ofw_pci_activate_resource(device_t bus, struct ofw_pci_softc *sc; bus_space_handle_t handle; bus_space_tag_t tag; + struct ofw_pci_range *rp; + vm_paddr_t start; + int space; int rv; sc = device_get_softc(bus); - if (type == SYS_RES_IRQ) { - return (bus_activate_resource(bus, type, rid, res)); + if (type != SYS_RES_IOPORT && type != SYS_RES_MEMORY) { + return (bus_generic_activate_resource(bus, child, type, rid, + res)); } - if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) { - struct ofw_pci_range *rp; - vm_paddr_t start; - int space; - - start = (vm_paddr_t)rman_get_start(res); - - /* - * Map this through the ranges list - */ - for (rp = sc->sc_range; rp < sc->sc_range + sc->sc_nrange && - rp->pci_hi != 0; rp++) { - if (start < rp->pci || start >= rp->pci + rp->size) - continue; - - switch (rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) { - case OFW_PCI_PHYS_HI_SPACE_IO: - space = SYS_RES_IOPORT; - break; - case OFW_PCI_PHYS_HI_SPACE_MEM32: - case OFW_PCI_PHYS_HI_SPACE_MEM64: - space = SYS_RES_MEMORY; - break; - default: - space = -1; - } - if (type == space) { - start += (rp->host - rp->pci); - break; + start = (vm_paddr_t)rman_get_start(res); + + /* + * Map this through the ranges list + */ + for (rp = sc->sc_range; rp < sc->sc_range + sc->sc_nrange && + rp->pci_hi != 0; rp++) { + if (start < rp->pci || start >= rp->pci + rp->size) + continue; + + switch (rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) { + case OFW_PCI_PHYS_HI_SPACE_IO: + space = SYS_RES_IOPORT; + break; + case OFW_PCI_PHYS_HI_SPACE_MEM32: + case OFW_PCI_PHYS_HI_SPACE_MEM64: + space = SYS_RES_MEMORY; + break; + default: + space = -1; } + + if (type == space) { + start += (rp->host - rp->pci); + break; } + } - if (bootverbose) - printf("ofw_pci mapdev: start %jx, len %jd\n", - (rman_res_t)start, rman_get_size(res)); - - tag = BUS_GET_BUS_TAG(child, child); - if (tag == NULL) - return (ENOMEM); - - rman_set_bustag(res, tag); - rv = bus_space_map(tag, start, - rman_get_size(res), 0, &handle); - if (rv != 0) - return (ENOMEM); + if (bootverbose) + printf("ofw_pci mapdev: start %jx, len %jd\n", + (rman_res_t)start, rman_get_size(res)); + + tag = BUS_GET_BUS_TAG(child, child); + if (tag == NULL) + return (ENOMEM); + + rman_set_bustag(res, tag); + rv = bus_space_map(tag, start, + rman_get_size(res), 0, &handle); + if (rv != 0) + return (ENOMEM); - rman_set_bushandle(res, handle); - rman_set_virtual(res, (void *)handle); /* XXX for powerpc only ? */ - } + rman_set_bushandle(res, handle); + rman_set_virtual(res, (void *)handle); /* XXX for powerpc only ? */ return (rman_activate_resource(res)); } @@ -528,17 +542,19 @@ static int ofw_pci_deactivate_resource(device_t bus, device_t child, int type, int rid, struct resource *res) { + struct ofw_pci_softc *sc; + vm_size_t psize; - /* - * If this is a memory resource, unmap it. - */ - if ((type == SYS_RES_MEMORY) || (type == SYS_RES_IOPORT)) { - u_int32_t psize; + sc = device_get_softc(bus); - psize = rman_get_size(res); - pmap_unmapdev((vm_offset_t)rman_get_virtual(res), psize); + if (type != SYS_RES_IOPORT && type != SYS_RES_MEMORY) { + return (bus_generic_deactivate_resource(bus, child, type, rid, + res)); } + psize = rman_get_size(res); + pmap_unmapdev((vm_offset_t)rman_get_virtual(res), psize); + return (rman_deactivate_resource(res)); } @@ -550,24 +566,15 @@ ofw_pci_adjust_resource(device_t bus, de struct ofw_pci_softc *sc; sc = device_get_softc(bus); - KASSERT(!(rman_get_flags(res) & RF_ACTIVE), - ("active resources cannot be adjusted")); - if (rman_get_flags(res) & RF_ACTIVE) - return (EINVAL); - switch (type) { - case SYS_RES_MEMORY: - rm = &sc->sc_mem_rman; - break; - case SYS_RES_IOPORT: - rm = &sc->sc_io_rman; - break; - default: - return (ENXIO); + rm = ofw_pci_get_rman(sc, type, rman_get_flags(res)); + if (rm == NULL) { + return (bus_generic_adjust_resource(bus, child, type, res, + start, end)); } - - if (!rman_is_region_manager(res, rm)) - return (EINVAL); + KASSERT(rman_is_region_manager(res, rm), ("rman mismatch")); + KASSERT(!(rman_get_flags(res) & RF_ACTIVE), + ("active resources cannot be adjusted")); return (rman_adjust_resource(res, start, end)); } @@ -629,3 +636,22 @@ ofw_pci_fill_ranges(phandle_t node, stru free(base_ranges, M_DEVBUF); return (nranges); } + +static struct rman * +ofw_pci_get_rman(struct ofw_pci_softc *sc, int type, u_int flags) +{ + + switch (type) { + case SYS_RES_IOPORT: + return (&sc->sc_io_rman); + case SYS_RES_MEMORY: + if (sc->sc_have_pmem && (flags & RF_PREFETCHABLE)) + return (&sc->sc_pmem_rman); + else + return (&sc->sc_mem_rman); + default: + break; + } + + return (NULL); +} Modified: head/sys/dev/ofw/ofwpci.h ============================================================================== --- head/sys/dev/ofw/ofwpci.h Sun Jul 17 13:33:35 2016 (r302950) +++ head/sys/dev/ofw/ofwpci.h Sun Jul 17 13:43:00 2016 (r302951) @@ -60,13 +60,16 @@ struct ofw_pci_softc { int sc_bus; int sc_initialized; int sc_quirks; + int sc_have_pmem; struct ofw_pci_range *sc_range; int sc_nrange; + uint64_t sc_range_mask; struct ofw_pci_cell_info *sc_cell_info; struct rman sc_io_rman; struct rman sc_mem_rman; + struct rman sc_pmem_rman; bus_space_tag_t sc_memt; bus_dma_tag_t sc_dmat;