linux/drivers/isdn/hisax/hfc_2bs0.c
Julia Lawall eeb4e6d166 isdn: fix misspelling of current function in string
Replace a misspelled function name by %s and then __func__.

In the first case, the print is just dropped, because kmalloc itself does
enough error reporting.

This was done using Coccinelle, including the use of Levenshtein distance,
as proposed by Rasmus Villemoes.

Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-12-09 16:18:46 -05:00

591 lines
15 KiB
C

/* $Id: hfc_2bs0.c,v 1.20.2.6 2004/02/11 13:21:33 keil Exp $
*
* specific routines for CCD's HFC 2BS0
*
* Author Karsten Keil
* Copyright by Karsten Keil <keil@isdn4linux.de>
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include <linux/init.h>
#include "hisax.h"
#include "hfc_2bs0.h"
#include "isac.h"
#include "isdnl1.h"
#include <linux/interrupt.h>
#include <linux/slab.h>
static inline int
WaitForBusy(struct IsdnCardState *cs)
{
int to = 130;
u_char val;
while (!(cs->BC_Read_Reg(cs, HFC_STATUS, 0) & HFC_BUSY) && to) {
val = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2 |
(cs->hw.hfc.cip & 3));
udelay(1);
to--;
}
if (!to) {
printk(KERN_WARNING "HiSax: %s timeout\n", __func__);
return (0);
} else
return (to);
}
static inline int
WaitNoBusy(struct IsdnCardState *cs)
{
int to = 125;
while ((cs->BC_Read_Reg(cs, HFC_STATUS, 0) & HFC_BUSY) && to) {
udelay(1);
to--;
}
if (!to) {
printk(KERN_WARNING "HiSax: waitforBusy timeout\n");
return (0);
} else
return (to);
}
static int
GetFreeFifoBytes(struct BCState *bcs)
{
int s;
if (bcs->hw.hfc.f1 == bcs->hw.hfc.f2)
return (bcs->cs->hw.hfc.fifosize);
s = bcs->hw.hfc.send[bcs->hw.hfc.f1] - bcs->hw.hfc.send[bcs->hw.hfc.f2];
if (s <= 0)
s += bcs->cs->hw.hfc.fifosize;
s = bcs->cs->hw.hfc.fifosize - s;
return (s);
}
static int
ReadZReg(struct BCState *bcs, u_char reg)
{
int val;
WaitNoBusy(bcs->cs);
val = 256 * bcs->cs->BC_Read_Reg(bcs->cs, HFC_DATA, reg | HFC_CIP | HFC_Z_HIGH);
WaitNoBusy(bcs->cs);
val += bcs->cs->BC_Read_Reg(bcs->cs, HFC_DATA, reg | HFC_CIP | HFC_Z_LOW);
return (val);
}
static void
hfc_clear_fifo(struct BCState *bcs)
{
struct IsdnCardState *cs = bcs->cs;
int idx, cnt;
int rcnt, z1, z2;
u_char cip, f1, f2;
if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
debugl1(cs, "hfc_clear_fifo");
cip = HFC_CIP | HFC_F1 | HFC_REC | HFC_CHANNEL(bcs->channel);
if ((cip & 0xc3) != (cs->hw.hfc.cip & 0xc3)) {
cs->BC_Write_Reg(cs, HFC_STATUS, cip, cip);
WaitForBusy(cs);
}
WaitNoBusy(cs);
f1 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
cip = HFC_CIP | HFC_F2 | HFC_REC | HFC_CHANNEL(bcs->channel);
WaitNoBusy(cs);
f2 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
z1 = ReadZReg(bcs, HFC_Z1 | HFC_REC | HFC_CHANNEL(bcs->channel));
z2 = ReadZReg(bcs, HFC_Z2 | HFC_REC | HFC_CHANNEL(bcs->channel));
cnt = 32;
while (((f1 != f2) || (z1 != z2)) && cnt--) {
if (cs->debug & L1_DEB_HSCX)
debugl1(cs, "hfc clear %d f1(%d) f2(%d)",
bcs->channel, f1, f2);
rcnt = z1 - z2;
if (rcnt < 0)
rcnt += cs->hw.hfc.fifosize;
if (rcnt)
rcnt++;
if (cs->debug & L1_DEB_HSCX)
debugl1(cs, "hfc clear %d z1(%x) z2(%x) cnt(%d)",
bcs->channel, z1, z2, rcnt);
cip = HFC_CIP | HFC_FIFO_OUT | HFC_REC | HFC_CHANNEL(bcs->channel);
idx = 0;
while ((idx < rcnt) && WaitNoBusy(cs)) {
cs->BC_Read_Reg(cs, HFC_DATA_NODEB, cip);
idx++;
}
if (f1 != f2) {
WaitNoBusy(cs);
cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC |
HFC_CHANNEL(bcs->channel));
WaitForBusy(cs);
}
cip = HFC_CIP | HFC_F1 | HFC_REC | HFC_CHANNEL(bcs->channel);
WaitNoBusy(cs);
f1 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
cip = HFC_CIP | HFC_F2 | HFC_REC | HFC_CHANNEL(bcs->channel);
WaitNoBusy(cs);
f2 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
z1 = ReadZReg(bcs, HFC_Z1 | HFC_REC | HFC_CHANNEL(bcs->channel));
z2 = ReadZReg(bcs, HFC_Z2 | HFC_REC | HFC_CHANNEL(bcs->channel));
}
return;
}
static struct sk_buff
*
hfc_empty_fifo(struct BCState *bcs, int count)
{
u_char *ptr;
struct sk_buff *skb;
struct IsdnCardState *cs = bcs->cs;
int idx;
int chksum;
u_char stat, cip;
if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
debugl1(cs, "hfc_empty_fifo");
idx = 0;
if (count > HSCX_BUFMAX + 3) {
if (cs->debug & L1_DEB_WARN)
debugl1(cs, "hfc_empty_fifo: incoming packet too large");
cip = HFC_CIP | HFC_FIFO_OUT | HFC_REC | HFC_CHANNEL(bcs->channel);
while ((idx++ < count) && WaitNoBusy(cs))
cs->BC_Read_Reg(cs, HFC_DATA_NODEB, cip);
WaitNoBusy(cs);
stat = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC |
HFC_CHANNEL(bcs->channel));
WaitForBusy(cs);
return (NULL);
}
if ((count < 4) && (bcs->mode != L1_MODE_TRANS)) {
if (cs->debug & L1_DEB_WARN)
debugl1(cs, "hfc_empty_fifo: incoming packet too small");
cip = HFC_CIP | HFC_FIFO_OUT | HFC_REC | HFC_CHANNEL(bcs->channel);
while ((idx++ < count) && WaitNoBusy(cs))
cs->BC_Read_Reg(cs, HFC_DATA_NODEB, cip);
WaitNoBusy(cs);
stat = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC |
HFC_CHANNEL(bcs->channel));
WaitForBusy(cs);
#ifdef ERROR_STATISTIC
bcs->err_inv++;
#endif
return (NULL);
}
if (bcs->mode == L1_MODE_TRANS)
count -= 1;
else
count -= 3;
if (!(skb = dev_alloc_skb(count)))
printk(KERN_WARNING "HFC: receive out of memory\n");
else {
ptr = skb_put(skb, count);
idx = 0;
cip = HFC_CIP | HFC_FIFO_OUT | HFC_REC | HFC_CHANNEL(bcs->channel);
while ((idx < count) && WaitNoBusy(cs)) {
*ptr++ = cs->BC_Read_Reg(cs, HFC_DATA_NODEB, cip);
idx++;
}
if (idx != count) {
debugl1(cs, "RFIFO BUSY error");
printk(KERN_WARNING "HFC FIFO channel %d BUSY Error\n", bcs->channel);
dev_kfree_skb_any(skb);
if (bcs->mode != L1_MODE_TRANS) {
WaitNoBusy(cs);
stat = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC |
HFC_CHANNEL(bcs->channel));
WaitForBusy(cs);
}
return (NULL);
}
if (bcs->mode != L1_MODE_TRANS) {
WaitNoBusy(cs);
chksum = (cs->BC_Read_Reg(cs, HFC_DATA, cip) << 8);
WaitNoBusy(cs);
chksum += cs->BC_Read_Reg(cs, HFC_DATA, cip);
WaitNoBusy(cs);
stat = cs->BC_Read_Reg(cs, HFC_DATA, cip);
if (cs->debug & L1_DEB_HSCX)
debugl1(cs, "hfc_empty_fifo %d chksum %x stat %x",
bcs->channel, chksum, stat);
if (stat) {
debugl1(cs, "FIFO CRC error");
dev_kfree_skb_any(skb);
skb = NULL;
#ifdef ERROR_STATISTIC
bcs->err_crc++;
#endif
}
WaitNoBusy(cs);
stat = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC |
HFC_CHANNEL(bcs->channel));
WaitForBusy(cs);
}
}
return (skb);
}
static void
hfc_fill_fifo(struct BCState *bcs)
{
struct IsdnCardState *cs = bcs->cs;
int idx, fcnt;
int count;
int z1, z2;
u_char cip;
if (!bcs->tx_skb)
return;
if (bcs->tx_skb->len <= 0)
return;
cip = HFC_CIP | HFC_F1 | HFC_SEND | HFC_CHANNEL(bcs->channel);
if ((cip & 0xc3) != (cs->hw.hfc.cip & 0xc3)) {
cs->BC_Write_Reg(cs, HFC_STATUS, cip, cip);
WaitForBusy(cs);
}
WaitNoBusy(cs);
if (bcs->mode != L1_MODE_TRANS) {
bcs->hw.hfc.f1 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
cip = HFC_CIP | HFC_F2 | HFC_SEND | HFC_CHANNEL(bcs->channel);
WaitNoBusy(cs);
bcs->hw.hfc.f2 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
bcs->hw.hfc.send[bcs->hw.hfc.f1] = ReadZReg(bcs, HFC_Z1 | HFC_SEND | HFC_CHANNEL(bcs->channel));
if (cs->debug & L1_DEB_HSCX)
debugl1(cs, "hfc_fill_fifo %d f1(%d) f2(%d) z1(%x)",
bcs->channel, bcs->hw.hfc.f1, bcs->hw.hfc.f2,
bcs->hw.hfc.send[bcs->hw.hfc.f1]);
fcnt = bcs->hw.hfc.f1 - bcs->hw.hfc.f2;
if (fcnt < 0)
fcnt += 32;
if (fcnt > 30) {
if (cs->debug & L1_DEB_HSCX)
debugl1(cs, "hfc_fill_fifo more as 30 frames");
return;
}
count = GetFreeFifoBytes(bcs);
}
else {
WaitForBusy(cs);
z1 = ReadZReg(bcs, HFC_Z1 | HFC_REC | HFC_CHANNEL(bcs->channel));
z2 = ReadZReg(bcs, HFC_Z2 | HFC_REC | HFC_CHANNEL(bcs->channel));
count = z1 - z2;
if (count < 0)
count += cs->hw.hfc.fifosize;
} /* L1_MODE_TRANS */
if (cs->debug & L1_DEB_HSCX)
debugl1(cs, "hfc_fill_fifo %d count(%u/%d)",
bcs->channel, bcs->tx_skb->len,
count);
if (count < bcs->tx_skb->len) {
if (cs->debug & L1_DEB_HSCX)
debugl1(cs, "hfc_fill_fifo no fifo mem");
return;
}
cip = HFC_CIP | HFC_FIFO_IN | HFC_SEND | HFC_CHANNEL(bcs->channel);
idx = 0;
while ((idx < bcs->tx_skb->len) && WaitNoBusy(cs))
cs->BC_Write_Reg(cs, HFC_DATA_NODEB, cip, bcs->tx_skb->data[idx++]);
if (idx != bcs->tx_skb->len) {
debugl1(cs, "FIFO Send BUSY error");
printk(KERN_WARNING "HFC S FIFO channel %d BUSY Error\n", bcs->channel);
} else {
count = bcs->tx_skb->len;
bcs->tx_cnt -= count;
if (PACKET_NOACK == bcs->tx_skb->pkt_type)
count = -1;
dev_kfree_skb_any(bcs->tx_skb);
bcs->tx_skb = NULL;
if (bcs->mode != L1_MODE_TRANS) {
WaitForBusy(cs);
WaitNoBusy(cs);
cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F1_INC | HFC_SEND | HFC_CHANNEL(bcs->channel));
}
if (test_bit(FLG_LLI_L1WAKEUP, &bcs->st->lli.flag) &&
(count >= 0)) {
u_long flags;
spin_lock_irqsave(&bcs->aclock, flags);
bcs->ackcnt += count;
spin_unlock_irqrestore(&bcs->aclock, flags);
schedule_event(bcs, B_ACKPENDING);
}
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
}
return;
}
void
main_irq_hfc(struct BCState *bcs)
{
struct IsdnCardState *cs = bcs->cs;
int z1, z2, rcnt;
u_char f1, f2, cip;
int receive, transmit, count = 5;
struct sk_buff *skb;
Begin:
count--;
cip = HFC_CIP | HFC_F1 | HFC_REC | HFC_CHANNEL(bcs->channel);
if ((cip & 0xc3) != (cs->hw.hfc.cip & 0xc3)) {
cs->BC_Write_Reg(cs, HFC_STATUS, cip, cip);
WaitForBusy(cs);
}
WaitNoBusy(cs);
receive = 0;
if (bcs->mode == L1_MODE_HDLC) {
f1 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
cip = HFC_CIP | HFC_F2 | HFC_REC | HFC_CHANNEL(bcs->channel);
WaitNoBusy(cs);
f2 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
if (f1 != f2) {
if (cs->debug & L1_DEB_HSCX)
debugl1(cs, "hfc rec %d f1(%d) f2(%d)",
bcs->channel, f1, f2);
receive = 1;
}
}
if (receive || (bcs->mode == L1_MODE_TRANS)) {
WaitForBusy(cs);
z1 = ReadZReg(bcs, HFC_Z1 | HFC_REC | HFC_CHANNEL(bcs->channel));
z2 = ReadZReg(bcs, HFC_Z2 | HFC_REC | HFC_CHANNEL(bcs->channel));
rcnt = z1 - z2;
if (rcnt < 0)
rcnt += cs->hw.hfc.fifosize;
if ((bcs->mode == L1_MODE_HDLC) || (rcnt)) {
rcnt++;
if (cs->debug & L1_DEB_HSCX)
debugl1(cs, "hfc rec %d z1(%x) z2(%x) cnt(%d)",
bcs->channel, z1, z2, rcnt);
/* sti(); */
if ((skb = hfc_empty_fifo(bcs, rcnt))) {
skb_queue_tail(&bcs->rqueue, skb);
schedule_event(bcs, B_RCVBUFREADY);
}
}
receive = 1;
}
if (bcs->tx_skb) {
transmit = 1;
test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
hfc_fill_fifo(bcs);
if (test_bit(BC_FLG_BUSY, &bcs->Flag))
transmit = 0;
} else {
if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
transmit = 1;
test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
hfc_fill_fifo(bcs);
if (test_bit(BC_FLG_BUSY, &bcs->Flag))
transmit = 0;
} else {
transmit = 0;
schedule_event(bcs, B_XMTBUFREADY);
}
}
if ((receive || transmit) && count)
goto Begin;
return;
}
static void
mode_hfc(struct BCState *bcs, int mode, int bc)
{
struct IsdnCardState *cs = bcs->cs;
if (cs->debug & L1_DEB_HSCX)
debugl1(cs, "HFC 2BS0 mode %d bchan %d/%d",
mode, bc, bcs->channel);
bcs->mode = mode;
bcs->channel = bc;
switch (mode) {
case (L1_MODE_NULL):
if (bc) {
cs->hw.hfc.ctmt &= ~1;
cs->hw.hfc.isac_spcr &= ~0x03;
}
else {
cs->hw.hfc.ctmt &= ~2;
cs->hw.hfc.isac_spcr &= ~0x0c;
}
break;
case (L1_MODE_TRANS):
cs->hw.hfc.ctmt &= ~(1 << bc); /* set HDLC mode */
cs->BC_Write_Reg(cs, HFC_STATUS, cs->hw.hfc.ctmt, cs->hw.hfc.ctmt);
hfc_clear_fifo(bcs); /* complete fifo clear */
if (bc) {
cs->hw.hfc.ctmt |= 1;
cs->hw.hfc.isac_spcr &= ~0x03;
cs->hw.hfc.isac_spcr |= 0x02;
} else {
cs->hw.hfc.ctmt |= 2;
cs->hw.hfc.isac_spcr &= ~0x0c;
cs->hw.hfc.isac_spcr |= 0x08;
}
break;
case (L1_MODE_HDLC):
if (bc) {
cs->hw.hfc.ctmt &= ~1;
cs->hw.hfc.isac_spcr &= ~0x03;
cs->hw.hfc.isac_spcr |= 0x02;
} else {
cs->hw.hfc.ctmt &= ~2;
cs->hw.hfc.isac_spcr &= ~0x0c;
cs->hw.hfc.isac_spcr |= 0x08;
}
break;
}
cs->BC_Write_Reg(cs, HFC_STATUS, cs->hw.hfc.ctmt, cs->hw.hfc.ctmt);
cs->writeisac(cs, ISAC_SPCR, cs->hw.hfc.isac_spcr);
if (mode == L1_MODE_HDLC)
hfc_clear_fifo(bcs);
}
static void
hfc_l2l1(struct PStack *st, int pr, void *arg)
{
struct BCState *bcs = st->l1.bcs;
struct sk_buff *skb = arg;
u_long flags;
switch (pr) {
case (PH_DATA | REQUEST):
spin_lock_irqsave(&bcs->cs->lock, flags);
if (bcs->tx_skb) {
skb_queue_tail(&bcs->squeue, skb);
} else {
bcs->tx_skb = skb;
test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
bcs->cs->BC_Send_Data(bcs);
}
spin_unlock_irqrestore(&bcs->cs->lock, flags);
break;
case (PH_PULL | INDICATION):
spin_lock_irqsave(&bcs->cs->lock, flags);
if (bcs->tx_skb) {
printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n");
} else {
test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
bcs->tx_skb = skb;
bcs->cs->BC_Send_Data(bcs);
}
spin_unlock_irqrestore(&bcs->cs->lock, flags);
break;
case (PH_PULL | REQUEST):
if (!bcs->tx_skb) {
test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
} else
test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
break;
case (PH_ACTIVATE | REQUEST):
spin_lock_irqsave(&bcs->cs->lock, flags);
test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag);
mode_hfc(bcs, st->l1.mode, st->l1.bc);
spin_unlock_irqrestore(&bcs->cs->lock, flags);
l1_msg_b(st, pr, arg);
break;
case (PH_DEACTIVATE | REQUEST):
l1_msg_b(st, pr, arg);
break;
case (PH_DEACTIVATE | CONFIRM):
spin_lock_irqsave(&bcs->cs->lock, flags);
test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
mode_hfc(bcs, 0, st->l1.bc);
spin_unlock_irqrestore(&bcs->cs->lock, flags);
st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
break;
}
}
static void
close_hfcstate(struct BCState *bcs)
{
mode_hfc(bcs, 0, bcs->channel);
if (test_bit(BC_FLG_INIT, &bcs->Flag)) {
skb_queue_purge(&bcs->rqueue);
skb_queue_purge(&bcs->squeue);
if (bcs->tx_skb) {
dev_kfree_skb_any(bcs->tx_skb);
bcs->tx_skb = NULL;
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
}
}
test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
}
static int
open_hfcstate(struct IsdnCardState *cs, struct BCState *bcs)
{
if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
skb_queue_head_init(&bcs->rqueue);
skb_queue_head_init(&bcs->squeue);
}
bcs->tx_skb = NULL;
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
bcs->event = 0;
bcs->tx_cnt = 0;
return (0);
}
static int
setstack_hfc(struct PStack *st, struct BCState *bcs)
{
bcs->channel = st->l1.bc;
if (open_hfcstate(st->l1.hardware, bcs))
return (-1);
st->l1.bcs = bcs;
st->l2.l2l1 = hfc_l2l1;
setstack_manager(st);
bcs->st = st;
setstack_l1_B(st);
return (0);
}
static void
init_send(struct BCState *bcs)
{
int i;
if (!(bcs->hw.hfc.send = kmalloc(32 * sizeof(unsigned int), GFP_ATOMIC))) {
printk(KERN_WARNING
"HiSax: No memory for hfc.send\n");
return;
}
for (i = 0; i < 32; i++)
bcs->hw.hfc.send[i] = 0x1fff;
}
void
inithfc(struct IsdnCardState *cs)
{
init_send(&cs->bcs[0]);
init_send(&cs->bcs[1]);
cs->BC_Send_Data = &hfc_fill_fifo;
cs->bcs[0].BC_SetStack = setstack_hfc;
cs->bcs[1].BC_SetStack = setstack_hfc;
cs->bcs[0].BC_Close = close_hfcstate;
cs->bcs[1].BC_Close = close_hfcstate;
mode_hfc(cs->bcs, 0, 0);
mode_hfc(cs->bcs + 1, 0, 0);
}
void
releasehfc(struct IsdnCardState *cs)
{
kfree(cs->bcs[0].hw.hfc.send);
cs->bcs[0].hw.hfc.send = NULL;
kfree(cs->bcs[1].hw.hfc.send);
cs->bcs[1].hw.hfc.send = NULL;
}