From owner-svn-src-head@FreeBSD.ORG Thu Dec 23 17:08:40 2010 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 14F941065670; Thu, 23 Dec 2010 17:08:40 +0000 (UTC) (envelope-from ganbold@gmail.com) Received: from mail-px0-f182.google.com (mail-px0-f182.google.com [209.85.212.182]) by mx1.freebsd.org (Postfix) with ESMTP id C32268FC15; Thu, 23 Dec 2010 17:08:39 +0000 (UTC) Received: by pxi1 with SMTP id 1so1187644pxi.13 for ; Thu, 23 Dec 2010 09:08:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:message-id:date:from :user-agent:mime-version:to:cc:subject:references:in-reply-to :content-type:content-transfer-encoding; bh=2nb1ds9x6JWbzTG0CFCBLIOv6Z1gKU+5WJifAFuCMVs=; b=lYvhLxXLrIXo4hKA4cquWXZheM9BnRdXHrlssjNvcjggBRJPkTQ70oElFOaV/mfDEq a4/kPlwXILUEqW4J7q7FLuO5qI91iM2/4/u9lEQLzhP3tR9fQaGDa3/i9MmjUqOzegiS 4XweaRKOc1gqhEDu+wWLrVzXRjWNN1A4EWjxA= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:user-agent:mime-version:to:cc:subject :references:in-reply-to:content-type:content-transfer-encoding; b=ObSNTWYRrP9cVUJSbwwyub/5KMILoxlOJplwyT5+r+i/Ln3csq3GeNZEyu5uro2rc+ PF+cQbhxKc5OG9enHiZV9tGRCaGMrtz7STsCk6CfVUkj7hcCs16hn2zotlyuHdmPeSZT JJ7MgD9I1HNTlsAM+y5J9hVsaISmRcwH1qyeE= Received: by 10.142.171.17 with SMTP id t17mr6766922wfe.88.1293122516534; Thu, 23 Dec 2010 08:41:56 -0800 (PST) Received: from beastie.micom.mng.net ([202.179.15.54]) by mx.google.com with ESMTPS id q13sm10925978wfc.17.2010.12.23.08.41.51 (version=TLSv1/SSLv3 cipher=RC4-MD5); Thu, 23 Dec 2010 08:41:54 -0800 (PST) Message-ID: <4D137BC2.80705@gmail.com> Date: Fri, 24 Dec 2010 00:41:38 +0800 From: Ganbold User-Agent: Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.9.2.12) Gecko/20101030 Thunderbird/3.1.6 MIME-Version: 1.0 To: John Baldwin References: <201012222027.oBMKRKEL033534@svn.freebsd.org> In-Reply-To: <201012222027.oBMKRKEL033534@svn.freebsd.org> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit Cc: svn-src-head@freebsd.org, svn-src-all@freebsd.org, src-committers@freebsd.org, Ganbold Tsagaankhuu Subject: Re: svn commit: r216674 - head/sys/dev/acpica X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 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: Thu, 23 Dec 2010 17:08:40 -0000 John, On 12/23/10 04:27, John Baldwin wrote: > Author: jhb > Date: Wed Dec 22 20:27:20 2010 > New Revision: 216674 > URL: http://svn.freebsd.org/changeset/base/216674 > > Log: > Use resource_list_reserve() to reserve I/O port and memory resources for > ACPI devices even if they are not allocated by a device driver since the > resources are in use and should not be allocated to another device. Looks like either my laptop's BIOS/firmware is crappy or this commit breaks booting. Following are the images I captured, although it may not be useful: http://people.freebsd.org/~ganbold/crash1.jpg http://people.freebsd.org/~ganbold/crash2.jpg dmesg (without this commit): http://people.freebsd.org/~ganbold/dmesg.txt thanks, Ganbold > Modified: > head/sys/dev/acpica/acpi.c > head/sys/dev/acpica/acpivar.h > > Modified: head/sys/dev/acpica/acpi.c > ============================================================================== > --- head/sys/dev/acpica/acpi.c Wed Dec 22 19:57:03 2010 (r216673) > +++ head/sys/dev/acpica/acpi.c Wed Dec 22 20:27:20 2010 (r216674) > @@ -116,7 +116,10 @@ static int acpi_read_ivar(device_t dev, > static int acpi_write_ivar(device_t dev, device_t child, int index, > uintptr_t value); > static struct resource_list *acpi_get_rlist(device_t dev, device_t child); > +static void acpi_reserve_resources(device_t dev); > static int acpi_sysres_alloc(device_t dev); > +static int acpi_set_resource(device_t dev, device_t child, int type, > + int rid, u_long start, u_long count); > static struct resource *acpi_alloc_resource(device_t bus, device_t child, > int type, int *rid, u_long start, u_long end, > u_long count, u_int flags); > @@ -187,7 +190,7 @@ static device_method_t acpi_methods[] = > DEVMETHOD(bus_read_ivar, acpi_read_ivar), > DEVMETHOD(bus_write_ivar, acpi_write_ivar), > DEVMETHOD(bus_get_resource_list, acpi_get_rlist), > - DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource), > + DEVMETHOD(bus_set_resource, acpi_set_resource), > DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), > DEVMETHOD(bus_alloc_resource, acpi_alloc_resource), > DEVMETHOD(bus_release_resource, acpi_release_resource), > @@ -1109,73 +1112,144 @@ acpi_sysres_alloc(device_t dev) > return (0); > } > > -static struct resource * > -acpi_alloc_resource(device_t bus, device_t child, int type, int *rid, > - u_long start, u_long end, u_long count, u_int flags) > +static char *pcilink_ids[] = { "PNP0C0F", NULL }; > +static char *sysres_ids[] = { "PNP0C01", "PNP0C02", NULL }; > + > +/* > + * Reserve declared resources for devices found during attach once system > + * resources have been allocated. > + */ > +static void > +acpi_reserve_resources(device_t dev) > { > - ACPI_RESOURCE ares; > - struct acpi_device *ad = device_get_ivars(child); > - struct resource_list *rl =&ad->ad_rl; > struct resource_list_entry *rle; > - struct resource *res; > - struct rman *rm; > + struct resource_list *rl; > + struct acpi_device *ad; > + struct acpi_softc *sc; > + device_t *children; > + int child_count, i; > > - res = NULL; > + sc = device_get_softc(dev); > + if (device_get_children(dev,&children,&child_count) != 0) > + return; > + for (i = 0; i< child_count; i++) { > + ad = device_get_ivars(children[i]); > + rl =&ad->ad_rl; > > - /* We only handle memory and IO resources through rman. */ > - switch (type) { > - case SYS_RES_IOPORT: > - rm =&acpi_rman_io; > - break; > - case SYS_RES_MEMORY: > - rm =&acpi_rman_mem; > - break; > - default: > - rm = NULL; > + /* Don't reserve system resources. */ > + if (ACPI_ID_PROBE(dev, children[i], sysres_ids) != NULL) > + continue; > + > + STAILQ_FOREACH(rle, rl, link) { > + /* > + * Don't reserve IRQ resources. There are many sticky things > + * to get right otherwise (e.g. IRQs for psm, atkbd, and HPET > + * when using legacy routing). > + */ > + if (rle->type == SYS_RES_IRQ) > + continue; > + > + /* > + * Try to reserve the resource from our parent. If this > + * fails because the resource is a system resource, just > + * let it be. The resource range is already reserved so > + * that other devices will not use it. If the driver > + * needs to allocate the resource, then > + * acpi_alloc_resource() will sub-alloc from the system > + * resource. > + */ > + resource_list_reserve(rl, dev, children[i], rle->type,&rle->rid, > + rle->start, rle->end, rle->count, 0); > + } > } > - > - ACPI_SERIAL_BEGIN(acpi); > + free(children, M_TEMP); > + sc->acpi_resources_reserved = 1; > +} > + > +static int > +acpi_set_resource(device_t dev, device_t child, int type, int rid, > + u_long start, u_long count) > +{ > + struct acpi_softc *sc = device_get_softc(dev); > + struct acpi_device *ad = device_get_ivars(child); > + struct resource_list *rl =&ad->ad_rl; > + u_long end; > + > + /* Ignore IRQ resources for PCI link devices. */ > + if (type == SYS_RES_IRQ&& ACPI_ID_PROBE(dev, child, pcilink_ids) != NULL) > + return (0); > + > + /* If the resource is already allocated, fail. */ > + if (resource_list_busy(rl, type, rid)) > + return (EBUSY); > + > + /* If the resource is already reserved, release it. */ > + if (resource_list_reserved(rl, type, rid)) > + resource_list_unreserve(rl, dev, child, type, rid); > + > + /* Add the resource. */ > + end = (start + count - 1); > + resource_list_add(rl, type, rid, start, end, count); > + > + /* Don't reserve resources until the system resources are allocated. */ > + if (!sc->acpi_resources_reserved) > + return (0); > + > + /* Don't reserve system resources. */ > + if (ACPI_ID_PROBE(dev, child, sysres_ids) != NULL) > + return (0); > > /* > - * If this is an allocation of the "default" range for a given RID, and > - * we know what the resources for this device are (i.e., they're on the > - * child's resource list), use those start/end values. > - */ > - if (bus == device_get_parent(child)&& start == 0UL&& end == ~0UL) { > - rle = resource_list_find(rl, type, *rid); > - if (rle == NULL) > - goto out; > - start = rle->start; > - end = rle->end; > - count = rle->count; > - } > + * Don't reserve IRQ resources. There are many sticky things to > + * get right otherwise (e.g. IRQs for psm, atkbd, and HPET when > + * using legacy routing). > + */ > + if (type == SYS_RES_IRQ) > + return (0); > > /* > - * If this is an allocation of a specific range, see if we can satisfy > - * the request from our system resource regions. If we can't, pass the > - * request up to the parent. > + * Reserve the resource. > + * > + * XXX: Ignores failure for now. Failure here is probably a > + * BIOS/firmware bug? > */ > - if (start + count - 1 == end&& rm != NULL) > - res = rman_reserve_resource(rm, start, end, count, flags& ~RF_ACTIVE, > - child); > - if (res == NULL) { > - res = BUS_ALLOC_RESOURCE(device_get_parent(bus), child, type, rid, > - start, end, count, flags); > - } else { > - rman_set_rid(res, *rid); > + resource_list_reserve(rl, dev, child, type,&rid, start, end, count, 0); > + return (0); > +} > > - /* If requested, activate the resource using the parent's method. */ > - if (flags& RF_ACTIVE) > - if (bus_activate_resource(child, type, *rid, res) != 0) { > - rman_release_resource(res); > - res = NULL; > - goto out; > - } > - } > +static struct resource * > +acpi_alloc_resource(device_t bus, device_t child, int type, int *rid, > + u_long start, u_long end, u_long count, u_int flags) > +{ > + ACPI_RESOURCE ares; > + struct acpi_device *ad; > + struct resource_list_entry *rle; > + struct resource_list *rl; > + struct resource *res; > + struct rman *rm; > + int isdefault = (start == 0UL&& end == ~0UL); > > - if (res != NULL&& device_get_parent(child) == bus) > - switch (type) { > - case SYS_RES_IRQ: > + /* > + * First attempt at allocating the resource. For direct children, > + * use resource_list_alloc() to handle reserved resources. For > + * other dveices, pass the request up to our parent. > + */ > + if (bus == device_get_parent(child)) { > + ad = device_get_ivars(child); > + rl =&ad->ad_rl; > + > + /* > + * Simulate the behavior of the ISA bus for direct children > + * devices. That is, if a non-default range is specified for > + * a resource that doesn't exist, use bus_set_resource() to > + * add the resource before allocating it. Note that these > + * resources will not be reserved. > + */ > + if (!isdefault&& resource_list_find(rl, type, *rid) == NULL) > + resource_list_add(rl, type, *rid, start, end, count); > + res = resource_list_alloc(rl, bus, child, type, rid, start, end, count, > + flags); > + if (res != NULL&& type == SYS_RES_IRQ) { > /* > * Since bus_config_intr() takes immediate effect, we cannot > * configure the interrupt associated with a device when we > @@ -1186,11 +1260,59 @@ acpi_alloc_resource(device_t bus, device > */ > if (ACPI_SUCCESS(acpi_lookup_irq_resource(child, *rid, res,&ares))) > acpi_config_intr(child,&ares); > - break; > } > > -out: > - ACPI_SERIAL_END(acpi); > + /* > + * If this is an allocation of the "default" range for a given > + * RID, fetch the exact bounds for this resource from the > + * resource list entry to try to allocate the range from the > + * system resource regions. > + */ > + if (res == NULL&& isdefault) { > + rle = resource_list_find(rl, type, *rid); > + if (rle != NULL) { > + start = rle->start; > + end = rle->end; > + count = rle->count; > + } > + } > + } else > + res = BUS_ALLOC_RESOURCE(device_get_parent(bus), child, type, rid, > + start, end, count, flags); > + if (res != NULL || start + count - 1 != end) > + return (res); > + > + /* > + * If the first attempt failed and this is an allocation of a > + * specific range, try to satisfy the request via a suballocation > + * from our system resource regions. Note that we only handle > + * memory and I/O port system resources. > + */ > + switch (type) { > + case SYS_RES_IOPORT: > + rm =&acpi_rman_io; > + break; > + case SYS_RES_MEMORY: > + rm =&acpi_rman_mem; > + break; > + default: > + return (NULL); > + } > + > + res = rman_reserve_resource(rm, start, end, count, flags& ~RF_ACTIVE, > + child); > + if (res == NULL) > + return (NULL); > + > + rman_set_rid(res, *rid); > + > + /* If requested, activate the resource using the parent's method. */ > + if (flags& RF_ACTIVE) > + if (bus_activate_resource(child, type, *rid, res) != 0) { > + rman_release_resource(res); > + return (NULL); > + } > + > return (res); > } > > @@ -1213,26 +1335,20 @@ acpi_release_resource(device_t bus, devi > rm = NULL; > } > > - ACPI_SERIAL_BEGIN(acpi); > - > /* > * If this resource belongs to one of our internal managers, > - * deactivate it and release it to the local pool. If it doesn't, > - * pass this request up to the parent. > + * deactivate it and release it to the local pool. > */ > if (rm != NULL&& rman_is_region_manager(r, rm)) { > if (rman_get_flags(r)& RF_ACTIVE) { > ret = bus_deactivate_resource(child, type, rid, r); > if (ret != 0) > - goto out; > + return (ret); > } > - ret = rman_release_resource(r); > - } else > - ret = BUS_RELEASE_RESOURCE(device_get_parent(bus), child, type, rid, r); > + return (rman_release_resource(r)); > + } > > -out: > - ACPI_SERIAL_END(acpi); > - return (ret); > + return (bus_generic_rl_release_resource(bus, child, type, rid, r)); > } > > static void > @@ -1241,6 +1357,12 @@ acpi_delete_resource(device_t bus, devic > struct resource_list *rl; > > rl = acpi_get_rlist(bus, child); > + if (resource_list_busy(rl, type, rid)) { > + device_printf(bus, "delete_resource: Resource still owned by child" > + " (type=%d, rid=%d)\n", type, rid); > + return; > + } > + resource_list_unreserve(rl, bus, child, type, rid); > resource_list_delete(rl, type, rid); > } > > @@ -1629,6 +1751,9 @@ acpi_probe_children(device_t bus) > /* Pre-allocate resources for our rman from any sysresource devices. */ > acpi_sysres_alloc(bus); > > + /* Reserve resources already allocated to children. */ > + acpi_reserve_resources(bus); > + > /* Create any static children by calling device identify methods. */ > ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "device identify routines\n")); > bus_generic_probe(bus); > > Modified: head/sys/dev/acpica/acpivar.h > ============================================================================== > --- head/sys/dev/acpica/acpivar.h Wed Dec 22 19:57:03 2010 (r216673) > +++ head/sys/dev/acpica/acpivar.h Wed Dec 22 20:27:20 2010 (r216674) > @@ -58,6 +58,7 @@ struct acpi_softc { > int acpi_enabled; > int acpi_sstate; > int acpi_sleep_disabled; > + int acpi_resources_reserved; > > struct sysctl_ctx_list acpi_sysctl_ctx; > struct sysctl_oid *acpi_sysctl_tree; > _______________________________________________ > svn-src-all@freebsd.org mailing list > http://lists.freebsd.org/mailman/listinfo/svn-src-all > To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org" >