mirror of
https://github.com/torvalds/linux.git
synced 2024-12-01 00:21:32 +00:00
NET: sa11x0-ir: move SIR and FIR interrupt support
Move the interrupt handlers to the SIR and FIR sections of the file. This improves the localization of the protocol handlers. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
This commit is contained in:
parent
374f77390c
commit
a6b2ea66d6
@ -164,6 +164,100 @@ static int sa1100_irda_sir_tx_start(struct sk_buff *skb, struct net_device *dev,
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
static irqreturn_t sa1100_irda_sir_irq(struct net_device *dev, struct sa1100_irda *si)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = Ser2UTSR0;
|
||||
|
||||
/*
|
||||
* Deal with any receive errors first. The bytes in error may be
|
||||
* the only bytes in the receive FIFO, so we do this first.
|
||||
*/
|
||||
while (status & UTSR0_EIF) {
|
||||
int stat, data;
|
||||
|
||||
stat = Ser2UTSR1;
|
||||
data = Ser2UTDR;
|
||||
|
||||
if (stat & (UTSR1_FRE | UTSR1_ROR)) {
|
||||
dev->stats.rx_errors++;
|
||||
if (stat & UTSR1_FRE)
|
||||
dev->stats.rx_frame_errors++;
|
||||
if (stat & UTSR1_ROR)
|
||||
dev->stats.rx_fifo_errors++;
|
||||
} else
|
||||
async_unwrap_char(dev, &dev->stats, &si->rx_buff, data);
|
||||
|
||||
status = Ser2UTSR0;
|
||||
}
|
||||
|
||||
/*
|
||||
* We must clear certain bits.
|
||||
*/
|
||||
Ser2UTSR0 = status & (UTSR0_RID | UTSR0_RBB | UTSR0_REB);
|
||||
|
||||
if (status & UTSR0_RFS) {
|
||||
/*
|
||||
* There are at least 4 bytes in the FIFO. Read 3 bytes
|
||||
* and leave the rest to the block below.
|
||||
*/
|
||||
async_unwrap_char(dev, &dev->stats, &si->rx_buff, Ser2UTDR);
|
||||
async_unwrap_char(dev, &dev->stats, &si->rx_buff, Ser2UTDR);
|
||||
async_unwrap_char(dev, &dev->stats, &si->rx_buff, Ser2UTDR);
|
||||
}
|
||||
|
||||
if (status & (UTSR0_RFS | UTSR0_RID)) {
|
||||
/*
|
||||
* Fifo contains more than 1 character.
|
||||
*/
|
||||
do {
|
||||
async_unwrap_char(dev, &dev->stats, &si->rx_buff,
|
||||
Ser2UTDR);
|
||||
} while (Ser2UTSR1 & UTSR1_RNE);
|
||||
|
||||
}
|
||||
|
||||
if (status & UTSR0_TFS && si->tx_buff.len) {
|
||||
/*
|
||||
* Transmitter FIFO is not full
|
||||
*/
|
||||
do {
|
||||
Ser2UTDR = *si->tx_buff.data++;
|
||||
si->tx_buff.len -= 1;
|
||||
} while (Ser2UTSR1 & UTSR1_TNF && si->tx_buff.len);
|
||||
|
||||
if (si->tx_buff.len == 0) {
|
||||
dev->stats.tx_packets++;
|
||||
dev->stats.tx_bytes += si->tx_buff.data -
|
||||
si->tx_buff.head;
|
||||
|
||||
/*
|
||||
* We need to ensure that the transmitter has
|
||||
* finished.
|
||||
*/
|
||||
do
|
||||
rmb();
|
||||
while (Ser2UTSR1 & UTSR1_TBY);
|
||||
|
||||
/*
|
||||
* Ok, we've finished transmitting. Now enable
|
||||
* the receiver. Sometimes we get a receive IRQ
|
||||
* immediately after a transmit...
|
||||
*/
|
||||
Ser2UTSR0 = UTSR0_REB | UTSR0_RBB | UTSR0_RID;
|
||||
Ser2UTCR3 = UTCR3_RIE | UTCR3_RXE | UTCR3_TXE;
|
||||
|
||||
sa1100_irda_check_speed(si);
|
||||
|
||||
/* I'm hungry! */
|
||||
netif_wake_queue(dev);
|
||||
}
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIR format support.
|
||||
*/
|
||||
@ -198,8 +292,128 @@ static int sa1100_irda_fir_tx_start(struct sk_buff *skb, struct net_device *dev,
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
static irqreturn_t sa1100_irda_sir_irq(struct net_device *, struct sa1100_irda *);
|
||||
static irqreturn_t sa1100_irda_fir_irq(struct net_device *, struct sa1100_irda *);
|
||||
static void sa1100_irda_fir_error(struct sa1100_irda *si, struct net_device *dev)
|
||||
{
|
||||
struct sk_buff *skb = si->dma_rx.skb;
|
||||
dma_addr_t dma_addr;
|
||||
unsigned int len, stat, data;
|
||||
|
||||
if (!skb) {
|
||||
printk(KERN_ERR "sa1100_ir: SKB is NULL!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the current data position.
|
||||
*/
|
||||
dma_addr = sa1100_get_dma_pos(si->dma_rx.regs);
|
||||
len = dma_addr - si->dma_rx.dma;
|
||||
if (len > HPSIR_MAX_RXLEN)
|
||||
len = HPSIR_MAX_RXLEN;
|
||||
dma_unmap_single(si->dev, si->dma_rx.dma, len, DMA_FROM_DEVICE);
|
||||
|
||||
do {
|
||||
/*
|
||||
* Read Status, and then Data.
|
||||
*/
|
||||
stat = Ser2HSSR1;
|
||||
rmb();
|
||||
data = Ser2HSDR;
|
||||
|
||||
if (stat & (HSSR1_CRE | HSSR1_ROR)) {
|
||||
dev->stats.rx_errors++;
|
||||
if (stat & HSSR1_CRE)
|
||||
dev->stats.rx_crc_errors++;
|
||||
if (stat & HSSR1_ROR)
|
||||
dev->stats.rx_frame_errors++;
|
||||
} else
|
||||
skb->data[len++] = data;
|
||||
|
||||
/*
|
||||
* If we hit the end of frame, there's
|
||||
* no point in continuing.
|
||||
*/
|
||||
if (stat & HSSR1_EOF)
|
||||
break;
|
||||
} while (Ser2HSSR0 & HSSR0_EIF);
|
||||
|
||||
if (stat & HSSR1_EOF) {
|
||||
si->dma_rx.skb = NULL;
|
||||
|
||||
skb_put(skb, len);
|
||||
skb->dev = dev;
|
||||
skb_reset_mac_header(skb);
|
||||
skb->protocol = htons(ETH_P_IRDA);
|
||||
dev->stats.rx_packets++;
|
||||
dev->stats.rx_bytes += len;
|
||||
|
||||
/*
|
||||
* Before we pass the buffer up, allocate a new one.
|
||||
*/
|
||||
sa1100_irda_rx_alloc(si);
|
||||
|
||||
netif_rx(skb);
|
||||
} else {
|
||||
/*
|
||||
* Remap the buffer - it was previously mapped, and we
|
||||
* hope that this succeeds.
|
||||
*/
|
||||
si->dma_rx.dma = dma_map_single(si->dev, si->dma_rx.skb->data,
|
||||
HPSIR_MAX_RXLEN,
|
||||
DMA_FROM_DEVICE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We only have to handle RX events here; transmit events go via the TX
|
||||
* DMA handler. We disable RX, process, and the restart RX.
|
||||
*/
|
||||
static irqreturn_t sa1100_irda_fir_irq(struct net_device *dev, struct sa1100_irda *si)
|
||||
{
|
||||
/*
|
||||
* Stop RX DMA
|
||||
*/
|
||||
sa1100_stop_dma(si->dma_rx.regs);
|
||||
|
||||
/*
|
||||
* Framing error - we throw away the packet completely.
|
||||
* Clearing RXE flushes the error conditions and data
|
||||
* from the fifo.
|
||||
*/
|
||||
if (Ser2HSSR0 & (HSSR0_FRE | HSSR0_RAB)) {
|
||||
dev->stats.rx_errors++;
|
||||
|
||||
if (Ser2HSSR0 & HSSR0_FRE)
|
||||
dev->stats.rx_frame_errors++;
|
||||
|
||||
/*
|
||||
* Clear out the DMA...
|
||||
*/
|
||||
Ser2HSCR0 = si->hscr0 | HSCR0_HSSP;
|
||||
|
||||
/*
|
||||
* Clear selected status bits now, so we
|
||||
* don't miss them next time around.
|
||||
*/
|
||||
Ser2HSSR0 = HSSR0_FRE | HSSR0_RAB;
|
||||
}
|
||||
|
||||
/*
|
||||
* Deal with any receive errors. The any of the lowest
|
||||
* 8 bytes in the FIFO may contain an error. We must read
|
||||
* them one by one. The "error" could even be the end of
|
||||
* packet!
|
||||
*/
|
||||
if (Ser2HSSR0 & HSSR0_EIF)
|
||||
sa1100_irda_fir_error(si, dev);
|
||||
|
||||
/*
|
||||
* No matter what happens, we must restart reception.
|
||||
*/
|
||||
sa1100_irda_rx_dma_start(si);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the IrDA communications speed.
|
||||
@ -306,228 +520,6 @@ sa1100_set_power(struct sa1100_irda *si, unsigned int state)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* HP-SIR format interrupt service routines.
|
||||
*/
|
||||
static irqreturn_t sa1100_irda_sir_irq(struct net_device *dev, struct sa1100_irda *si)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = Ser2UTSR0;
|
||||
|
||||
/*
|
||||
* Deal with any receive errors first. The bytes in error may be
|
||||
* the only bytes in the receive FIFO, so we do this first.
|
||||
*/
|
||||
while (status & UTSR0_EIF) {
|
||||
int stat, data;
|
||||
|
||||
stat = Ser2UTSR1;
|
||||
data = Ser2UTDR;
|
||||
|
||||
if (stat & (UTSR1_FRE | UTSR1_ROR)) {
|
||||
dev->stats.rx_errors++;
|
||||
if (stat & UTSR1_FRE)
|
||||
dev->stats.rx_frame_errors++;
|
||||
if (stat & UTSR1_ROR)
|
||||
dev->stats.rx_fifo_errors++;
|
||||
} else
|
||||
async_unwrap_char(dev, &dev->stats, &si->rx_buff, data);
|
||||
|
||||
status = Ser2UTSR0;
|
||||
}
|
||||
|
||||
/*
|
||||
* We must clear certain bits.
|
||||
*/
|
||||
Ser2UTSR0 = status & (UTSR0_RID | UTSR0_RBB | UTSR0_REB);
|
||||
|
||||
if (status & UTSR0_RFS) {
|
||||
/*
|
||||
* There are at least 4 bytes in the FIFO. Read 3 bytes
|
||||
* and leave the rest to the block below.
|
||||
*/
|
||||
async_unwrap_char(dev, &dev->stats, &si->rx_buff, Ser2UTDR);
|
||||
async_unwrap_char(dev, &dev->stats, &si->rx_buff, Ser2UTDR);
|
||||
async_unwrap_char(dev, &dev->stats, &si->rx_buff, Ser2UTDR);
|
||||
}
|
||||
|
||||
if (status & (UTSR0_RFS | UTSR0_RID)) {
|
||||
/*
|
||||
* Fifo contains more than 1 character.
|
||||
*/
|
||||
do {
|
||||
async_unwrap_char(dev, &dev->stats, &si->rx_buff,
|
||||
Ser2UTDR);
|
||||
} while (Ser2UTSR1 & UTSR1_RNE);
|
||||
|
||||
}
|
||||
|
||||
if (status & UTSR0_TFS && si->tx_buff.len) {
|
||||
/*
|
||||
* Transmitter FIFO is not full
|
||||
*/
|
||||
do {
|
||||
Ser2UTDR = *si->tx_buff.data++;
|
||||
si->tx_buff.len -= 1;
|
||||
} while (Ser2UTSR1 & UTSR1_TNF && si->tx_buff.len);
|
||||
|
||||
if (si->tx_buff.len == 0) {
|
||||
dev->stats.tx_packets++;
|
||||
dev->stats.tx_bytes += si->tx_buff.data -
|
||||
si->tx_buff.head;
|
||||
|
||||
/*
|
||||
* We need to ensure that the transmitter has
|
||||
* finished.
|
||||
*/
|
||||
do
|
||||
rmb();
|
||||
while (Ser2UTSR1 & UTSR1_TBY);
|
||||
|
||||
/*
|
||||
* Ok, we've finished transmitting. Now enable
|
||||
* the receiver. Sometimes we get a receive IRQ
|
||||
* immediately after a transmit...
|
||||
*/
|
||||
Ser2UTSR0 = UTSR0_REB | UTSR0_RBB | UTSR0_RID;
|
||||
Ser2UTCR3 = UTCR3_RIE | UTCR3_RXE | UTCR3_TXE;
|
||||
|
||||
sa1100_irda_check_speed(si);
|
||||
|
||||
/* I'm hungry! */
|
||||
netif_wake_queue(dev);
|
||||
}
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void sa1100_irda_fir_error(struct sa1100_irda *si, struct net_device *dev)
|
||||
{
|
||||
struct sk_buff *skb = si->dma_rx.skb;
|
||||
dma_addr_t dma_addr;
|
||||
unsigned int len, stat, data;
|
||||
|
||||
if (!skb) {
|
||||
printk(KERN_ERR "sa1100_ir: SKB is NULL!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the current data position.
|
||||
*/
|
||||
dma_addr = sa1100_get_dma_pos(si->dma_rx.regs);
|
||||
len = dma_addr - si->dma_rx.dma;
|
||||
if (len > HPSIR_MAX_RXLEN)
|
||||
len = HPSIR_MAX_RXLEN;
|
||||
dma_unmap_single(si->dev, si->dma_rx.dma, len, DMA_FROM_DEVICE);
|
||||
|
||||
do {
|
||||
/*
|
||||
* Read Status, and then Data.
|
||||
*/
|
||||
stat = Ser2HSSR1;
|
||||
rmb();
|
||||
data = Ser2HSDR;
|
||||
|
||||
if (stat & (HSSR1_CRE | HSSR1_ROR)) {
|
||||
dev->stats.rx_errors++;
|
||||
if (stat & HSSR1_CRE)
|
||||
dev->stats.rx_crc_errors++;
|
||||
if (stat & HSSR1_ROR)
|
||||
dev->stats.rx_frame_errors++;
|
||||
} else
|
||||
skb->data[len++] = data;
|
||||
|
||||
/*
|
||||
* If we hit the end of frame, there's
|
||||
* no point in continuing.
|
||||
*/
|
||||
if (stat & HSSR1_EOF)
|
||||
break;
|
||||
} while (Ser2HSSR0 & HSSR0_EIF);
|
||||
|
||||
if (stat & HSSR1_EOF) {
|
||||
si->dma_rx.skb = NULL;
|
||||
|
||||
skb_put(skb, len);
|
||||
skb->dev = dev;
|
||||
skb_reset_mac_header(skb);
|
||||
skb->protocol = htons(ETH_P_IRDA);
|
||||
dev->stats.rx_packets++;
|
||||
dev->stats.rx_bytes += len;
|
||||
|
||||
/*
|
||||
* Before we pass the buffer up, allocate a new one.
|
||||
*/
|
||||
sa1100_irda_rx_alloc(si);
|
||||
|
||||
netif_rx(skb);
|
||||
} else {
|
||||
/*
|
||||
* Remap the buffer - it was previously mapped, and we
|
||||
* hope that this succeeds.
|
||||
*/
|
||||
si->dma_rx.dma = dma_map_single(si->dev, si->dma_rx.skb->data,
|
||||
HPSIR_MAX_RXLEN,
|
||||
DMA_FROM_DEVICE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* FIR format interrupt service routine. We only have to
|
||||
* handle RX events; transmit events go via the TX DMA handler.
|
||||
*
|
||||
* No matter what, we disable RX, process, and the restart RX.
|
||||
*/
|
||||
static irqreturn_t sa1100_irda_fir_irq(struct net_device *dev, struct sa1100_irda *si)
|
||||
{
|
||||
/*
|
||||
* Stop RX DMA
|
||||
*/
|
||||
sa1100_stop_dma(si->dma_rx.regs);
|
||||
|
||||
/*
|
||||
* Framing error - we throw away the packet completely.
|
||||
* Clearing RXE flushes the error conditions and data
|
||||
* from the fifo.
|
||||
*/
|
||||
if (Ser2HSSR0 & (HSSR0_FRE | HSSR0_RAB)) {
|
||||
dev->stats.rx_errors++;
|
||||
|
||||
if (Ser2HSSR0 & HSSR0_FRE)
|
||||
dev->stats.rx_frame_errors++;
|
||||
|
||||
/*
|
||||
* Clear out the DMA...
|
||||
*/
|
||||
Ser2HSCR0 = si->hscr0 | HSCR0_HSSP;
|
||||
|
||||
/*
|
||||
* Clear selected status bits now, so we
|
||||
* don't miss them next time around.
|
||||
*/
|
||||
Ser2HSSR0 = HSSR0_FRE | HSSR0_RAB;
|
||||
}
|
||||
|
||||
/*
|
||||
* Deal with any receive errors. The any of the lowest
|
||||
* 8 bytes in the FIFO may contain an error. We must read
|
||||
* them one by one. The "error" could even be the end of
|
||||
* packet!
|
||||
*/
|
||||
if (Ser2HSSR0 & HSSR0_EIF)
|
||||
sa1100_irda_fir_error(si, dev);
|
||||
|
||||
/*
|
||||
* No matter what happens, we must restart reception.
|
||||
*/
|
||||
sa1100_irda_rx_dma_start(si);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t sa1100_irda_irq(int irq, void *dev_id)
|
||||
{
|
||||
struct net_device *dev = dev_id;
|
||||
|
Loading…
Reference in New Issue
Block a user