From owner-freebsd-hardware Tue May 20 20:45:40 1997 Return-Path: Received: (from root@localhost) by hub.freebsd.org (8.8.5/8.8.5) id UAA14657 for hardware-outgoing; Tue, 20 May 1997 20:45:40 -0700 (PDT) Received: from lariat.lariat.org (ppp0.lariat.org@[129.72.251.2]) by hub.freebsd.org (8.8.5/8.8.5) with ESMTP id UAA14652 for ; Tue, 20 May 1997 20:45:35 -0700 (PDT) Received: from solo.lariat.org ([129.72.251.10]) by lariat.lariat.org (8.8.5/8.8.5) with SMTP id VAA09057; Tue, 20 May 1997 21:45:08 -0600 (MDT) Message-Id: <3.0.1.32.19970520181142.00734e08@lariat.org> X-Sender: brett@lariat.org X-Mailer: Windows Eudora Pro Version 3.0.1 (32) Date: Tue, 20 May 1997 18:11:42 -0600 To: John-Mark Gurney From: Brett Glass Subject: Re: isa bus and boca multiport boards Cc: rberndt@nething.com, WELCHDW@wofford.edu, HARDWARE@FreeBSD.ORG In-Reply-To: <19970520194401.23424@hydrogen.nike.efn.org> References: <3.0.1.32.19970520125159.006dbe70@lariat.org> <8825649D.00771D31.00@IWND1.infoworld.com> <3.0.1.32.19970520125159.006dbe70@lariat.org> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Sender: owner-hardware@FreeBSD.ORG X-Loop: FreeBSD.org Precedence: bulk At 07:44 PM 5/20/97 -0700, you wrote: >well... this won't do any good... as right now when COM_MULTIPORT is >used all the sio ports are scanned until they scan without hitting any >change (input, signal change)... probably what should go in before this >is splitting the intrrupt routine to only scan the ports that are on a >certain board... this shouldn't be THAT hard to do... and I've thought >about doing it... I was under the impression that this is what was already done, but now that I look at it, I see that you're right! The code loops on a variable called "unit", incrementing it from 0 to the precompiled constant NSIO. This can waste a great deal of time, especially since the interrupts are edge-triggered and the list is scanned at least twice per interrupt. Here are some other improvements that could be made to the code, based on a quick analysis: 1) The code looks at a flag called "gone" on each and every port (present or not) during each and every interrupt service. Since the presence or absence of a port is determined at boot time, it'd be MUCH more efficient if the code worked down a linear list of only the ports that were present and on the relevant IRQ. The edge-catching algorithm is also less efficient than it might be. To make sure you haven't missed an edge, you must scan the UARTs and get ALL THE WAY AROUND THE LIST ONCE without finding any more ports to service. You can then return from the ISR. The two best ways to do this are (a) set a counter to the number of UARTS and decrement as you traverse the list circularly, or (b) store the number (or port address) of the last UART that had an interrupt pending. Scan the list in a circular manner until you get back to the same UART without finding anything else to service. The current code doesn't do this efficiently; it always does an end-to-end scan of the list instead of stopping at the point of the last interrupt service. In fact, it may scan as many as NSIO-1 extra ports on each interrupt. On a system with a many serial ports, this is a LOT of extra time. Also, rather than dereferencing the pointer "com" again and again, the ISR could selectively enregister parts of the record that contain the comm port's statistics. I also see a subroutine call that could be optimized out. Finally, some things are variables that needn't be, such as I/O port numbers. Memory accesses are expensive and increments and decrements are cheap (or free due to pipelining if instructions are ordered properly). So, in my code, I've found it's faster to load the interrupt status register port number for the UART, then increment and decrement as needed rather than doing more loads to obtain other register numbers. On the Intel processors, increments and decrements don't have many scheduling constraints; they've been optimized so that they rarely cause pipeline stalls. And eliminating the stored port numbers can reduce the record size dramatically, making it easy to enregister things. I don't know what the policy on ASM code is in FreeBSD, but this seems like an opportunity to do some VERY serious optimization where it's much needed! --Brett