Beispiel #1
0
static int
thunder_pem_adjust_resource(device_t dev, device_t child, int type,
    struct resource *res, rman_res_t start, rman_res_t end)
{
	struct thunder_pem_softc *sc;
	struct rman *rm;

	sc = device_get_softc(dev);
#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
	if (type == PCI_RES_BUS)
		return (pci_domain_adjust_bus(sc->id, child, res, start, end));
#endif

	rm = thunder_pem_rman(sc, type);
	if (rm == NULL)
		return (bus_generic_adjust_resource(dev, child, type, res,
		    start, end));
	if (!rman_is_region_manager(res, rm))
		/*
		 * This means a child device has a memory or I/O
		 * resource not from you which shouldn't happen.
		 */
		return (EINVAL);
	return (rman_adjust_resource(res, start, end));
}
static struct resource *
thunder_pem_alloc_resource(device_t dev, device_t child, int type, int *rid,
    rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
{
	struct thunder_pem_softc *sc = device_get_softc(dev);
	struct rman *rm = NULL;
	struct resource *res;
	device_t parent_dev;

	rm = thunder_pem_rman(sc, type);
	if (rm == NULL) {
		/* Find parent device. On ThunderX we know an exact path. */
		parent_dev = device_get_parent(device_get_parent(dev));
		return (BUS_ALLOC_RESOURCE(parent_dev, dev, type, rid, start,
		    end, count, flags));
	}


	if (!RMAN_IS_DEFAULT_RANGE(start, end)) {
		/*
		 * We might get PHYS addresses here inherited from EFI.
		 * Convert to PCI if necessary.
		 */
		if (range_addr_is_phys(sc->ranges, start, count)) {
			start = range_addr_phys_to_pci(sc->ranges, start);
			end = start + count - 1;
		}

	}

	if (bootverbose) {
		device_printf(dev,
		    "thunder_pem_alloc_resource: start=%#lx, end=%#lx, count=%#lx\n",
		    start, end, count);
	}

	res = rman_reserve_resource(rm, start, end, count, flags, child);
	if (res == NULL)
		goto fail;

	rman_set_rid(res, *rid);

	if (flags & RF_ACTIVE)
		if (bus_activate_resource(child, type, *rid, res)) {
			rman_release_resource(res);
			goto fail;
		}

	return (res);

fail:
	if (bootverbose) {
		device_printf(dev, "%s FAIL: type=%d, rid=%d, "
		    "start=%016lx, end=%016lx, count=%016lx, flags=%x\n",
		    __func__, type, *rid, start, end, count, flags);
	}

	return (NULL);
}
static int
thunder_pem_adjust_resource(device_t dev, device_t child, int type,
    struct resource *res, rman_res_t start, rman_res_t end)
{
	struct thunder_pem_softc *sc;
	struct rman *rm;

	sc = device_get_softc(dev);

	rm = thunder_pem_rman(sc, type);
	if (rm == NULL)
		return (bus_generic_adjust_resource(dev, child, type, res,
		    start, end));
	if (!rman_is_region_manager(res, rm))
		/*
		 * This means a child device has a memory or I/O
		 * resource not from you which shouldn't happen.
		 */
		return (EINVAL);
	return (rman_adjust_resource(res, start, end));
}
Beispiel #4
0
static int
thunder_pem_attach(device_t dev)
{
	devclass_t pci_class;
	device_t parent;
	struct thunder_pem_softc *sc;
	int error;
	int rid;
	int tuple;
	uint64_t base, size;
	struct rman *rman;

	sc = device_get_softc(dev);
	sc->dev = dev;

	/* Allocate memory for resource */
	pci_class = devclass_find("pci");
	parent = device_get_parent(dev);
	if (device_get_devclass(parent) == pci_class)
		rid = PCIR_BAR(0);
	else
		rid = RID_PEM_SPACE;

	sc->reg = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
	    &rid, RF_ACTIVE);
	if (sc->reg == NULL) {
		device_printf(dev, "Failed to allocate resource\n");
		return (ENXIO);
	}
	sc->reg_bst = rman_get_bustag(sc->reg);
	sc->reg_bsh = rman_get_bushandle(sc->reg);

	/* Map SLI, do it only once */
	if (!sli0_s2m_regx_base) {
		bus_space_map(sc->reg_bst, SLIX_S2M_REGX_ACC,
		    SLIX_S2M_REGX_ACC_SIZE, 0, &sli0_s2m_regx_base);
	}
	if (!sli1_s2m_regx_base) {
		bus_space_map(sc->reg_bst, SLIX_S2M_REGX_ACC +
		    SLIX_S2M_REGX_ACC_SPACING, SLIX_S2M_REGX_ACC_SIZE, 0,
		    &sli1_s2m_regx_base);
	}

	if ((sli0_s2m_regx_base == 0) || (sli1_s2m_regx_base == 0)) {
		device_printf(dev,
		    "bus_space_map failed to map slix_s2m_regx_base\n");
		goto fail;
	}

	/* Identify PEM */
	if (thunder_pem_identify(dev) != 0)
		goto fail;

	/* Initialize rman and allocate regions */
	sc->mem_rman.rm_type = RMAN_ARRAY;
	sc->mem_rman.rm_descr = "PEM PCIe Memory";
	error = rman_init(&sc->mem_rman);
	if (error != 0) {
		device_printf(dev, "memory rman_init() failed. error = %d\n",
		    error);
		goto fail;
	}
	sc->io_rman.rm_type = RMAN_ARRAY;
	sc->io_rman.rm_descr = "PEM PCIe IO";
	error = rman_init(&sc->io_rman);
	if (error != 0) {
		device_printf(dev, "IO rman_init() failed. error = %d\n",
		    error);
		goto fail_mem;
	}

	/*
	 * We ignore the values that may have been provided in FDT
	 * and configure ranges according to the below formula
	 * for all types of devices. This is because some DTBs provided
	 * by EFI do not have proper ranges property or don't have them
	 * at all.
	 */
	/* Fill memory window */
	sc->ranges[0].pci_base = PCI_MEMORY_BASE;
	sc->ranges[0].size = PCI_MEMORY_SIZE;
	sc->ranges[0].phys_base = sc->sli_window_base + SLI_PCI_OFFSET +
	    sc->ranges[0].pci_base;
	sc->ranges[0].flags = SYS_RES_MEMORY;

	/* Fill IO window */
	sc->ranges[1].pci_base = PCI_IO_BASE;
	sc->ranges[1].size = PCI_IO_SIZE;
	sc->ranges[1].phys_base = sc->sli_window_base + SLI_PCI_OFFSET +
	    sc->ranges[1].pci_base;
	sc->ranges[1].flags = SYS_RES_IOPORT;

	for (tuple = 0; tuple < MAX_RANGES_TUPLES; tuple++) {
		base = sc->ranges[tuple].pci_base;
		size = sc->ranges[tuple].size;
		if (size == 0)
			continue; /* empty range element */

		rman = thunder_pem_rman(sc, sc->ranges[tuple].flags);
		if (rman != NULL)
			error = rman_manage_region(rman, base,
			    base + size - 1);
		else
			error = EINVAL;
		if (error) {
			device_printf(dev,
			    "rman_manage_region() failed. error = %d\n", error);
			rman_fini(&sc->mem_rman);
			return (error);
		}
		if (bootverbose) {
			device_printf(dev,
			    "\tPCI addr: 0x%jx, CPU addr: 0x%jx, Size: 0x%jx, Flags:0x%jx\n",
			    sc->ranges[tuple].pci_base,
			    sc->ranges[tuple].phys_base,
			    sc->ranges[tuple].size,
			    sc->ranges[tuple].flags);
		}
	}

	if (thunder_pem_init(sc)) {
		device_printf(dev, "Failure during PEM init\n");
		goto fail_io;
	}

	device_add_child(dev, "pci", -1);

	return (bus_generic_attach(dev));

fail_io:
	rman_fini(&sc->io_rman);
fail_mem:
	rman_fini(&sc->mem_rman);
fail:
	bus_free_resource(dev, SYS_RES_MEMORY, sc->reg);
	return (ENXIO);
}