[ltp] Update: Input devices freezing; my take on pcmcia and yenta

Eric Blouin linux-thinkpad@www.bm-soft.com
Thu, 15 Nov 2001 11:22:38 -0500


I want to thank the list for the help on solving my input device freezing
problem.  Thomas Hood gave me the final clue when he said it sounded like
interrupt conflict.

First, a quick recap.  My 600x was suffering from frequent keyboard/mouse
lockups and the occasional hard hang.  There didn't appear to be any
pattern to the lookup and they occurred when not running X so I knew it
wasn't a desktop/X issue.  Strangely, if I ejected my pcmcia card the input
devices came back alive.  This worked every time except for the occasional
hard hang.  At one point I even put an ethernet card in that wasn't even
configured and ejecting that card would also bring the interface back to
life.  I could run all day without a card in the pcmcia slot with no
lockups or hangs.  My system derives from RH 7.1 and I've installed various
kernels thru 2.4.15-pre3 with no improvements.  The card I use is an IBM
token ring Auto16/4 Credit Card Adapter.  The APM settings seemed to make
no difference (but I did get suspend working along the way).

The solution.  Thomas' suggestion about interrupt conflicts sounded
promising so I started to poke around.  With the TR adapter operating, I:
cat /proc/interrupts:

           CPU0
  0:      83552          XT-PIC  timer
  1:       1172          XT-PIC  keyboard
  2:          0          XT-PIC  cascade
  3:       1190          XT-PIC  ibmtr_cs
 11:          2          XT-PIC  Texas Instruments PCI1450, Texas Instruments PCI1450 (#2), usb-uhci
 12:         34          XT-PIC  PS/2 Mouse
 14:       5601          XT-PIC  ide0
 15:          3          XT-PIC  ide1
NMI:          0
LOC:          0
ERR:          0
MIS:          0


OK, nothing looking in conflict there.  Try: lspci -vv | grep Interrupt

     Interrupt: pin A routed to IRQ 11
     Interrupt: pin B routed to IRQ 11
     Interrupt: pin A routed to IRQ 11
     Interrupt: pin A routed to IRQ 11
     Interrupt: pin D routed to IRQ 11
     Interrupt: pin ? routed to IRQ 9
     Interrupt: pin A routed to IRQ 11


OK, the interrupt 11 fits nicely with /proc/interrupts, but what about
interrupt 9 (ACPI on my machine)?  It's not in /proc/interrupts.  Hmm....
Let's think about that.  I know the /proc/interrupts is a "window" into the
kernel memory so that means /proc/interrupts reflects interrupts the kernel
is aware of; drivers (or kernel itself) have declared those interrupts
serviced -- yes sounds right.  So that means you could have HW devices that
generate interrupts that the kernel is not aware of?  Maybe those
interrupts were set up by BIOS or possibly PNP and in the old days HW
jumpers?  Yes... I think I'm beginning to grasp this.  So I could have a HW
device firing interrupts but ignored by the kernel (I pretty sure there's a
NOP service handler by default).  Now, I know my lockup problem goes away
when I don't have my TR ring card physically inserted.  Going on the
assumption that the interrupt used by my card (IRQ 3) is conflicting with
some other device, how can I have my card inserted physically, but not have
its interrupt installed?  What other device conflicts with it?  Well, the
first question is surprisingly difficult to answer.  I have to delve into
the workings of PCMCIA, Yenta, card services, card bus, and hot plug and
while I find plenty of information, it takes me a long time to put things
straight in my head.  More on that later.  It turns out that my TR card is
controlled thru cardmgr/cardctl user-land programs written by Dave Hinds.
Turn off the card in SW is easy: cardctl eject.  I virtually eject my card
and happily go hours without a lock-up, thus indicating my working theory
is holding up.  Now what of the second question: which device conflicts
with IRQ3.  Well I remember reading Thomas Hood's web page:

http://panoptic.csustan.edu/thood/tp600lnx.htm

and seeing something about the program tpctl.  I also remember reading
about IRQs for parallel and serial ports.  I know these can have
interrupts, but how do I know which interrupts they use?  Get tpctl, build
it and type: tpctl -rx and get:

resource state:                        ioaddr irq#   able? mode/power
   floppy controller:                   0x3f0 IRQ6  enable
   parallel port:                       0x3bc IRQ7  enable ext
   serial port 1:                       0x0   IRQ0 disable (error)
   serial port 2:                       0x3f8 IRQ4  enable

Hmm... At first glance nothing looks amiss, but what about serial port 1.
That looks suspicious.  An IRQ of zero?  I don' think so.  I surmise (and
later read in some documentation that comes with tpctl) that serial port 1
is probably using IRQ 3.  I think I have found my culprit.   Now I need to
figure out how to make my TR card avoid IRQ 3 (and 4, 6, and 7 too!).  It
turns out I can put (un-comment in the file have) the lines

exclude irq 3
exclude irq 4
exclude irq 6
exclude irq 7

in the file /etc/pcmcia/config.opts.  I do this, restart card services (on
RH: /etc/rc.d/init.d/pcmcia restart), and my /proc/interrupts now reads:

           CPU0
  0:      92485          XT-PIC  timer
  1:       1435          XT-PIC  keyboard
  2:          0          XT-PIC  cascade
  5:       6034          XT-PIC  ibmtr_cs
 11:          2          XT-PIC  Texas Instruments PCI1450, Texas Instruments PCI1450 (#2), usb-uhci
 12:         34          XT-PIC  PS/2 Mouse
 14:       5883          XT-PIC  ide0
 15:          3          XT-PIC  ide1
NMI:          0
LOC:          0
ERR:          0
MIS:          0

I have now gone two complete days without a lockup or hang!


Yenta, pcmcia, hot plug, card services, and the Linux kernel explained:

First, understand the evolution of the HW and some of the associated
terminology.  The original credit card sized slot on earlier laptops was
called a PCMCIA slot.  It was a 16bit interface.  People called them PCMCIA
cards.  Later the technology was improved to a 32bit interface and was
designed to look more like a PCI slot, but keeping the hot swap
functionality.  The terminology gets more muddled, but these newer slots
are generally referred to as CardBus capable slots.  A CardBus slot is also
backwards compatible with PCMCIA.  The cards that utilize the CardBus
technology generally have some reference to 32bit or CardBus.  So your
laptop may have a pure PCMCIA slot if it's quite a bit older or a CardBus
(32bit) slot if it's newer (don't ask me dates).

Second, understand the Linux kernel progression.  In the beginning there
was no support in the kernel for PCMCIA/CardBus.  To use such a card you
installed a package that provided individual drivers and some user-land
programs.  This package, which I will call the PCMCIA package, originally
supported PCMCIA cards and later CardBus cards as well.  Things changed
with the 2.4 kernel.  Two things happened.  First, Dave Hinds, manager of
the PCMCIA package enabled the option of compiling PCMCIA drivers as kernel
drivers.  Second, Linus wrote a driver referred to as Yenta that manages
the CardBus interface.  From a kernel perspective, a PCMCIA driver/card may
as well be an independent device.  If you have a 16bit PCMCIA card plugged
into your CardBus slot, electrically it shares much with the CardBus slot,
but logically it is a PCMCIA card.  The CardBus slot will share the PCI
IRQ.  Your 16bit card gets its own IRQ.  Yenta will get interrupts from
card insert and removal, but Yenta ignores 16bit card events (you will see
IRQ 11 counts go up in /proc/interrupts, but only for physical insert and
removal) because the PCMCIA driver does not register with the yenta driver.
To Yenta, there may as well be no card in the CardBus slot.  If your card
is CardBus, then chances are Yenta will be handling the interface.  Yenta
is a driver in the kernel and its big advantage is it makes a CardBus card
look like a conventional PCI card.  Chances are the chipset and logic on
you CardBus card are logically the same as a PCI version of your card.  The
main difference is the hot plug events.  The hot plug events
(insertion/ejection) are handled by Yenta and the rest of the events are
passed on to the PCI driver for that chip set.  Basically, the original PCI
drivers were slightly modified to be Yenta aware and now you have the same
driver for the PCI and CardBus version of the card.

Third,  understand how the insert/eject events for your card are handled
with the 2.4 kernel.  Refer to this document:

http://pcmcia-cs.sourceforge.net/ftp/README-2.4

If your card is handled by Yenta, your inserts and deletes will be "hot
plug" events.  This means when Yenta senses an insert or eject it calls a
user-land program which is normally /sbin/hotplug.  This external call can
be turned off or on when you build the kernel.  To learn about hot plug
see:

http://linux-hotplug.sourceforge.net/?selected=hotplug

If your card is handled by PCMCIA then you control insert and eject events
with Dave Hind's user-land program: cardmgr.  cardmgr runs as a daemon and
will call another program when it detects an insert/eject (there are also
some APM type things that can happen under both managers).  You can also
use cardctl to control events on your card.  On RH, cardmgr is configured
to refer to /etc/pcmcia for card information.  When a card event is
detected, cardmgr looks up information in /etc/pcmcia/config to see what
type of card it is.  In my case, my TR card is registered as a "network"
card.  cardmgr then looks for the script /etc/pcmcia/network and calls it
with the event as a parameter.  cardmgr is generally configured in
/etc/pcmcia/config.opts.  That's where I excluded the IRQ 3 to make my
system work.  On RH the cardmgr is started by the startup script
/etc/rc.d/init.d/pcmcia.

Hope this clears up some things for people.

Eric Blouin


----- The Linux ThinkPad mailing list -----
The linux-thinkpad mailing list home page is at:
http://www.bm-soft.com/~bm/tp_mailing.html