misc mumblings about if_cs.c card interrupt / card status

Holger Schurig hs4233 at mail.mn-solutions.de
Mon May 26 03:56:42 EDT 2008


Just writing this as mail in case anybody wants to google it :-)


The 5.0.16 GPL driver from Marvell did the following:

* at interrupt time, disable interrupts (we don't currently do
  this) by writing 0x1f into the host-int-mask register.
* get card-int-cause and store it away
* get card-status and store it away
* run callback into what is now libertas.ko
* clear bits in card-int-case
* enable interrupt by writing into the host-in-mask register
* the thread did use the stored away values, e.g. to
  call the sbi_host_to_card() function.

We now try to do all of this in the interrupt handler and have
various hickups right now, especially when we execute commands
while transfering lot's of frames.


card-in-cause is a register where I can clear bits by writing
the bitmask of bits-to-clear back.

card-status just tells me what the card allows currently.


When a command response is available, I get an interrupt with 
card-int-case 0x0008, meaning IF_CS_RESP_READY. Card-status is 
0x000d = (IF_CS_C_S_TX_DNLD_RDY,IF_CS_C_S_CMD_DNLD_RDY, 
IF_CS_C_S_CMD_UPLD_RDY). The latter means that I can
* send a TX frame to the card
* send a command to the card
* receive a response from the card.

When I receive a frame, I get an interrupt with card-int-case 
0x0002, meaning IF_CS_RX_AVAIL. Card-status is 0x0007 = 
(IF_CS_C_S_TX_DNLD_RDY, IF_CS_C_S_RX_UPLD_RDY, 
IF_CS_C_S_CMD_DNLD_RDY). So this time I can
* send a TX frame to the card
* get a RX frame from the card
* send a command to the card

When I send a frame, I get an interrupt with card-int-casue 
0x0001, meaning IF_CS_TX_DONE. Card-status is 0x0005 
(IF_CS_C_S_TX_DNLD_RDY, IF_CS_C_S_CMD_DNLD_RDY). So this time I 
can
* send a TX frame to the card
* send a command to the card

When the card has an event for me, I get an interrupt with 
card-int-status is 0x0010, meaning IF_CS_C_S_CARDEVENT. 
card-status was in my case 0x0815. The high byte contains the 
event, here 0x08. This time I can:
* send a TX frame to the card
* send a command to the card
* get? (maybe clear) a card event



cause = if_cs_read16(card, IF_CS_C_STATUS) & IF_CS_C_S_MASK;
if (cause & IF_CS_H_IC_TX_OVER) {
  lbs_deb_cs("tx over\n");
  lbs_host_to_card_done(priv);
}

is definitely erraneous, because IF_CS_H_IC_TX_OVER is always 
set, it just means "Hey, the buffer in the card is free, you can 
send a TX frame to the card". It does NOT mean that the card 
successfully sent a TX frame.

While I think that card-int-case makes much more sense, I might 
need to resort to card-status because of the strange lockups I 
notices. If I have to use card-status, then I can really only 
use that register for:
* get a command response from the card
* get an rx-frame from the card
* reading card event


I also think that currently I don't really check the card-status 
for IF_CS_C_S_TX_DNLD_RDY bit, e.g. I just stuff data down into 
the card, no matter if that is OK or not.



More information about the libertas-dev mailing list