From owner-freebsd-mips@freebsd.org Tue Nov 14 22:50:19 2017 Return-Path: Delivered-To: freebsd-mips@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 907FADDFD13 for ; Tue, 14 Nov 2017 22:50:19 +0000 (UTC) (envelope-from landon@landonf.org) Received: from smtp.office.plausible.coop (static-108-51-93-21.washdc.fios.verizon.net [108.51.93.21]) by mx1.freebsd.org (Postfix) with ESMTP id 75BE47299D for ; Tue, 14 Nov 2017 22:50:18 +0000 (UTC) (envelope-from landon@landonf.org) Received: from [172.16.51.10] (unknown [172.16.51.10]) by smtp.office.plausible.coop (Postfix) with ESMTPSA id 6D96450801E for ; Tue, 14 Nov 2017 14:50:11 -0800 (PST) Date: Tue, 14 Nov 2017 15:50:08 -0700 From: Landon J Fuller Subject: MIPS INTRNG changes To: freebsd-mips@freebsd.org Message-Id: <1510699808.25350.3@smtp.office.plausible.coop> X-Mailer: geary/0.10.0 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed X-BeenThere: freebsd-mips@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: Porting FreeBSD to MIPS List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 14 Nov 2017 22:50:19 -0000 Howdy - To support nested INTRNG interrupt controllers on non-FDT MIPS targets, I've implemented a replacement for the cpu_establish_[hard|soft]intr() workaround introduced in r305527 (D7692); I'll be commiting this in three days unless anyone objects: https://reviews.freebsd.org/D12385 Background: Since non-FDT INTRNG targets do not have an equivalent to OFW_BUS_MAP_INTR(), it is necessary for the MIPS nexus driver to implicitly establish INTRNG interrupt mappings on behalf of child devices. The workaround introduced in r305527 implements this as follows, on non-FDT INTRNG MIPS targets: - mips/nexus.c assumes that all bus interrupt requests are for a MIPS interrupt managed by mips/mips_pic.c - Call mips_pic's cpu_create_intr_map() from nexus_activate_resource() to allocate a new interrupt mapping on-demand. - Call mips_pic's cpu_get_irq_resource() from nexus_setup_intr() to fetch a shared IRQ struct resource for the MIPS interrupt. In addition to assuming that all IRQs are owned by mips_pic, on-demand IRQ mapping in the BUS_ACTIVATE_RESOURCE() path produces some unexpected behavior: - Any child bus that uses bus_generic_rl_alloc_resource() or resource_list_alloc() to implement BUS_ALLOC_RESOURCE() will update the child device's resource list entry to reference the newly mapped IRQ -- but only if the resource is allocated with the RF_ACTIVE flag, resulting in BUS_ACTIVATE_RESOURCE() being called from BUS_ALLOC_RESOURCE() before the resource_list_entry update is performed. - BUS_ACTIVATE_RESOURCE() is itself not resource_list-aware; if RF_ACTIVE is not set during allocation, and bus_activate_resource() is instead called directly, the child's resource list entry will _not_ updated to the newly mapped IRQ. Since the resource_list_entry _may_ be updated to reference the IRQ mapping, IRQs mappings implicitly created in nexus_activate_resource() cannot be implicitly unmapped in nexus_deactivate_resource() and must be leaked, as references to the mapping may remain in a child's resource_list_entry. Rather than performing on-demand mapping during resource activation, my changes preemptively produce (on non-FDT targets) a set of IRQ mappings for all MIPS IRQs in nexus_attach(), using a fixed range of INTRNG IRQ assignments (0-7) that may be statically referenced by child devices. With D12385, the mips nexus behavior will now be: - On non-FDT MIPS INTRNG targets, produce a set of fixed MIPS IRQ mappings in nexus_attach() for the MIPS IRQ range. - On all MIPS INTRNG targets, call mips_pic_activate_intr() from nexus_activate_resource() to perform activation; this will either perform mips_pic-specific activation if the IRQ is found in mips_pic' table of MIPS IRQ mappings, or will call intr_activate_irq() for IRQs not managed by mips_pic (e.g. IRQs mapped by a child PIC). - On all MIPS INTRNG targets, call mips_pic_deactivate_intr() from nexus_deactivate_resource(); this will either perform mips_pic-specific deactivation, or call intr_deactivate_irq() for IRQs not managed by mips_pic. Cheers, Landon