📄 idt77252.c
字号:
"(CDC: %08x)\n", card->name, len, rpp->len, readl(SAR_REG_CDC)); recycle_rx_pool_skb(card, rpp); atomic_inc(&vcc->stats->rx_err); return; } if (stat & SAR_RSQE_CRC) { RXPRINTK("%s: AAL5 CRC error.\n", card->name); recycle_rx_pool_skb(card, rpp); atomic_inc(&vcc->stats->rx_err); return; } if (rpp->count > 1) { struct sk_buff *sb; skb = dev_alloc_skb(rpp->len); if (!skb) { RXPRINTK("%s: Can't alloc RX skb.\n", card->name); recycle_rx_pool_skb(card, rpp); atomic_inc(&vcc->stats->rx_err); return; } if (!atm_charge(vcc, skb->truesize)) { recycle_rx_pool_skb(card, rpp); dev_kfree_skb(skb); return; } sb = rpp->first; for (i = 0; i < rpp->count; i++) { memcpy(skb_put(skb, sb->len), sb->data, sb->len); sb = sb->next; } recycle_rx_pool_skb(card, rpp); skb_trim(skb, len); ATM_SKB(skb)->vcc = vcc; skb->stamp = xtime; vcc->push(vcc, skb); atomic_inc(&vcc->stats->rx); return; } skb->next = NULL; flush_rx_pool(card, rpp); if (!atm_charge(vcc, skb->truesize)) { recycle_rx_skb(card, skb); return; } pci_unmap_single(card->pcidev, IDT77252_PRV_PADDR(skb), skb->end - skb->data, PCI_DMA_FROMDEVICE); sb_pool_remove(card, skb); skb_trim(skb, len); ATM_SKB(skb)->vcc = vcc; skb->stamp = xtime; vcc->push(vcc, skb); atomic_inc(&vcc->stats->rx); if (skb->truesize > SAR_FB_SIZE_3) add_rx_skb(card, 3, SAR_FB_SIZE_3, 1); else if (skb->truesize > SAR_FB_SIZE_2) add_rx_skb(card, 2, SAR_FB_SIZE_2, 1); else if (skb->truesize > SAR_FB_SIZE_1) add_rx_skb(card, 1, SAR_FB_SIZE_1, 1); else add_rx_skb(card, 0, SAR_FB_SIZE_0, 1); return; }}static voididt77252_rx(struct idt77252_dev *card){ struct rsq_entry *rsqe; if (card->rsq.next == card->rsq.last) rsqe = card->rsq.base; else rsqe = card->rsq.next + 1; if (!(le32_to_cpu(rsqe->word_4) & SAR_RSQE_VALID)) { RXPRINTK("%s: no entry in RSQ.\n", card->name); return; } do { dequeue_rx(card, rsqe); rsqe->word_4 = 0; card->rsq.next = rsqe; if (card->rsq.next == card->rsq.last) rsqe = card->rsq.base; else rsqe = card->rsq.next + 1; } while (le32_to_cpu(rsqe->word_4) & SAR_RSQE_VALID); writel((unsigned long) card->rsq.next - (unsigned long) card->rsq.base, SAR_REG_RSQH);}static voididt77252_rx_raw(struct idt77252_dev *card){ struct sk_buff *queue; u32 head, tail; struct atm_vcc *vcc; struct vc_map *vc; struct sk_buff *sb; if (card->raw_cell_head == NULL) { u32 handle = le32_to_cpu(*(card->raw_cell_hnd + 1)); card->raw_cell_head = sb_pool_skb(card, handle); } queue = card->raw_cell_head; if (!queue) return; head = IDT77252_PRV_PADDR(queue) + (queue->data - queue->head - 16); tail = readl(SAR_REG_RAWCT); pci_dma_sync_single(card->pcidev, IDT77252_PRV_PADDR(queue), queue->end - queue->head - 16, PCI_DMA_FROMDEVICE); while (head != tail) { unsigned int vpi, vci, pti; u32 header; header = le32_to_cpu(*(u32 *) &queue->data[0]); vpi = (header & ATM_HDR_VPI_MASK) >> ATM_HDR_VPI_SHIFT; vci = (header & ATM_HDR_VCI_MASK) >> ATM_HDR_VCI_SHIFT; pti = (header & ATM_HDR_PTI_MASK) >> ATM_HDR_PTI_SHIFT;#ifdef CONFIG_ATM_IDT77252_DEBUG if (debug & DBG_RAW_CELL) { int i; printk("%s: raw cell %x.%02x.%04x.%x.%x\n", card->name, (header >> 28) & 0x000f, (header >> 20) & 0x00ff, (header >> 4) & 0xffff, (header >> 1) & 0x0007, (header >> 0) & 0x0001); for (i = 16; i < 64; i++) printk(" %02x", queue->data[i]); printk("\n"); }#endif if (vpi >= (1<<card->vpibits) || vci >= (1<<card->vcibits)) { RPRINTK("%s: SDU received for out-of-range vc %u.%u\n", card->name, vpi, vci); goto drop; } vc = card->vcs[VPCI2VC(card, vpi, vci)]; if (!vc || !test_bit(VCF_RX, &vc->flags)) { RPRINTK("%s: SDU received on non RX vc %u.%u\n", card->name, vpi, vci); goto drop; } vcc = vc->rx_vcc; if (vcc->qos.aal != ATM_AAL0) { RPRINTK("%s: raw cell for non AAL0 vc %u.%u\n", card->name, vpi, vci); atomic_inc(&vcc->stats->rx_drop); goto drop; } if ((sb = dev_alloc_skb(64)) == NULL) { printk("%s: Can't allocate buffers for AAL0.\n", card->name); atomic_inc(&vcc->stats->rx_err); goto drop; } if ((vcc->sk != NULL) && !atm_charge(vcc, sb->truesize)) { RXPRINTK("%s: atm_charge() dropped AAL0 packets.\n", card->name); dev_kfree_skb(sb); goto drop; } *((u32 *) sb->data) = header; skb_put(sb, sizeof(u32)); memcpy(skb_put(sb, ATM_CELL_PAYLOAD), &(queue->data[16]), ATM_CELL_PAYLOAD); ATM_SKB(sb)->vcc = vcc; sb->stamp = xtime; vcc->push(vcc, sb); atomic_inc(&vcc->stats->rx);drop: skb_pull(queue, 64); head = IDT77252_PRV_PADDR(queue) + (queue->data - queue->head - 16); if (queue->len < 128) { struct sk_buff *next; u32 handle; head = le32_to_cpu(*(u32 *) &queue->data[0]); handle = le32_to_cpu(*(u32 *) &queue->data[4]); next = sb_pool_skb(card, handle); recycle_rx_skb(card, queue); if (next) { card->raw_cell_head = next; queue = card->raw_cell_head; pci_dma_sync_single(card->pcidev, IDT77252_PRV_PADDR(queue), queue->end - queue->data, PCI_DMA_FROMDEVICE); } else { card->raw_cell_head = NULL; printk("%s: raw cell queue overrun\n", card->name); break; } } }}/*****************************************************************************//* *//* TSQ Handling *//* *//*****************************************************************************/static intinit_tsq(struct idt77252_dev *card){ struct tsq_entry *tsqe; card->tsq.base = pci_alloc_consistent(card->pcidev, RSQSIZE, &card->tsq.paddr); if (card->tsq.base == NULL) { printk("%s: can't allocate TSQ.\n", card->name); return -1; } memset(card->tsq.base, 0, TSQSIZE); card->tsq.last = card->tsq.base + TSQ_NUM_ENTRIES - 1; card->tsq.next = card->tsq.last; for (tsqe = card->tsq.base; tsqe <= card->tsq.last; tsqe++) tsqe->word_2 = cpu_to_le32(SAR_TSQE_INVALID); writel(card->tsq.paddr, SAR_REG_TSQB); writel((unsigned long) card->tsq.next - (unsigned long) card->tsq.base, SAR_REG_TSQH); return 0;}static voiddeinit_tsq(struct idt77252_dev *card){ pci_free_consistent(card->pcidev, TSQSIZE, card->tsq.base, card->tsq.paddr);}static voididt77252_tx(struct idt77252_dev *card){ struct tsq_entry *tsqe; unsigned int vpi, vci; struct vc_map *vc; u32 conn, stat; if (card->tsq.next == card->tsq.last) tsqe = card->tsq.base; else tsqe = card->tsq.next + 1; TXPRINTK("idt77252_tx: tsq %p: base %p, next %p, last %p\n", tsqe, card->tsq.base, card->tsq.next, card->tsq.last); TXPRINTK("idt77252_tx: tsqb %08x, tsqt %08x, tsqh %08x, \n", readl(SAR_REG_TSQB), readl(SAR_REG_TSQT), readl(SAR_REG_TSQH)); stat = le32_to_cpu(tsqe->word_2); if (stat & SAR_TSQE_INVALID) return; do { TXPRINTK("tsqe: 0x%p [0x%08x 0x%08x]\n", tsqe, le32_to_cpu(tsqe->word_1), le32_to_cpu(tsqe->word_2)); switch (stat & SAR_TSQE_TYPE) { case SAR_TSQE_TYPE_TIMER: TXPRINTK("%s: Timer RollOver detected.\n", card->name); break; case SAR_TSQE_TYPE_IDLE: conn = le32_to_cpu(tsqe->word_1); if (SAR_TSQE_TAG(stat) == 0x10) {#ifdef NOTDEF printk("%s: Connection %d halted.\n", card->name, le32_to_cpu(tsqe->word_1) & 0x1fff);#endif break; } vc = card->vcs[conn & 0x1fff]; if (!vc) { printk("%s: could not find VC from conn %d\n", card->name, conn & 0x1fff); break; } printk("%s: Connection %d IDLE.\n", card->name, vc->index); set_bit(VCF_IDLE, &vc->flags); break; case SAR_TSQE_TYPE_TSR: conn = le32_to_cpu(tsqe->word_1); vc = card->vcs[conn & 0x1fff]; if (!vc) { printk("%s: no VC at index %d\n", card->name, le32_to_cpu(tsqe->word_1) & 0x1fff); break; } drain_scq(card, vc); break; case SAR_TSQE_TYPE_TBD_COMP: conn = le32_to_cpu(tsqe->word_1); vpi = (conn >> SAR_TBD_VPI_SHIFT) & 0x00ff; vci = (conn >> SAR_TBD_VCI_SHIFT) & 0xffff; if (vpi >= (1 << card->vpibits) || vci >= (1 << card->vcibits)) { printk("%s: TBD complete: " "out of range VPI.VCI %u.%u\n", card->name, vpi, vci); break; } vc = card->vcs[VPCI2VC(card, vpi, vci)]; if (!vc) { printk("%s: TBD complete: " "no VC at VPI.VCI %u.%u\n", card->name, vpi, vci); break; } drain_scq(card, vc); break; } tsqe->word_2 = cpu_to_le32(SAR_TSQE_INVALID); card->tsq.next = tsqe; if (card->tsq.next == card->tsq.last) tsqe = card->tsq.base; else tsqe = card->tsq.next + 1; TXPRINTK("tsqe: %p: base %p, next %p, last %p\n", tsqe, card->tsq.base, card->tsq.next, card->tsq.last); stat = le32_to_cpu(tsqe->word_2); } while (!(stat & SAR_TSQE_INVALID)); writel((unsigned long)card->tsq.next - (unsigned long)card->tsq.base, SAR_REG_TSQH); XPRINTK("idt77252_tx-after writel%d: TSQ head = 0x%x, tail = 0x%x, next = 0x%p.\n", card->index, readl(SAR_REG_TSQH), readl(SAR_REG_TSQT), card->tsq.next);}static voidtst_timer(unsigned long data){ struct idt77252_dev *card = (struct idt77252_dev *)data; unsigned long base, idle, jump; unsigned long flags; u32 pc; int e; spin_lock_irqsave(&card->tst_lock, flags); base = card->tst[card->tst_index]; idle = card->tst[card->tst_index ^ 1]; if (test_bit(TST_SWITCH_WAIT, &card->tst_state)) { jump = base + card->tst_size - 2; pc = readl(SAR_REG_NOW) >> 2; if ((pc ^ idle) & ~(card->tst_size - 1)) { mod_timer(&card->tst_timer, jiffies + 1); goto out; } clear_bit(TST_SWITCH_WAIT, &card->tst_state); card->tst_index ^= 1; write_sram(card, jump, TSTE_OPC_JMP | (base << 2)); base = card->tst[card->tst_index]; idle = card->tst[card->tst_index ^ 1]; for (e = 0; e < card->tst_size - 2; e++) { if (card->soft_tst[e].tste & TSTE_PUSH_IDLE) { write_sram(card, idle + e, card->soft_tst[e].tste & TSTE_MASK); card->soft_tst[e].tste &= ~(TSTE_PUSH_IDLE); } } } if (test_and_clear_bit(TST_SWITCH_PENDING, &card->tst_state)) { for (e = 0; e < card->tst_size - 2; e++) { if (card->soft_tst[e].tste & TSTE_PUSH_ACTIVE) { write_sram(card, idle + e, card->soft_tst[e].tste & TSTE_MASK); card->soft_tst[e].tste &= ~(TSTE_PUSH_ACTIVE); card->soft_tst[e].tste |= TSTE_PUSH_IDLE; } } jump = base + card->tst_size - 2; write_sram(card, jump, TSTE_OPC_NULL); set_bit(TST_SWITCH_WAIT, &card->tst_state); mod_timer(&card->tst_timer, jiffies + 1); }out: spin_unlock_irqrestore(&card->tst_lock, flags);}static int__fill_tst(struct idt77252_dev *card, struct vc_map *vc, int n, unsigned int opc){ unsigned long cl, avail; unsigned long idle; int e, r; u32 data; avail = card->tst_size - 2; for (e = 0; e < avail; e++) { if (card->soft_tst[e].vc == NULL) break; } if (e >= avail) { printk("%s: No free TST entries found\n", card->name); return -1; } NPRINTK("%s: conn %d: first TST entry at %d.\n", card->name, vc ? vc->index : -1, e); r = n; cl = avail; data = opc & TSTE_OPC_MASK; if (vc && (opc != TSTE_OPC_NULL)) data = opc | vc->index; idle = card->tst[card->tst_index ^ 1]; /* * Fill Soft TST. */ while (r > 0) { if ((cl >= avail) && (card->soft_tst[e].vc == NULL)) { if (vc) card->soft_tst[e].vc = vc; else card->soft_tst[e].vc = (void *)-1; card->soft_tst[e].tste = data; if (timer_pending(&card->tst_timer)) card->soft_tst[e].tste |= TSTE_PUSH_ACTIVE; else { write_sram(card, idle + e, data); card->soft_tst[e].tste |= TSTE_PUSH_IDLE; } cl -= card->tst_size; r--; } if (++e == avail) e = 0; cl += n; } return 0;}static intfill_tst(struct idt77252_dev *card, struct vc_map *vc, int n, unsigned int opc){ unsigned long flags; int res; spin_lock_irqsave(&card->tst_lock, flags); res = __fill_tst(card, vc, n, opc); set_bit(TST_SWITCH_PENDING, &card->tst_state); if (!timer_pending(&card->tst_timer)) mod_timer(&card->tst_timer, jiffies + 1); spin_unlock_irqrestore(&card->tst_lock, flags); return res;}static int__clear_tst(struct idt77252_dev *card, struct vc_map *vc){ unsigned long idle; int e; idle = card->tst[card->tst_index ^ 1]; for (e = 0; e < card->tst_size - 2; e++) { if (card->soft_tst[e].vc == vc) { card->soft_tst[e].vc = NULL; card->soft_tst[e].tste = TSTE_OPC_VAR; if (timer_pending(&card->tst_timer)) card->soft_tst[e].tste |= TSTE_PUSH_ACTIVE; else { write_sram(card, idle + e, TSTE_OPC_VAR); card->soft_tst[e].tste |= TSTE_PUSH_IDLE; } } } return 0;}static intclear_tst(struct idt77252_dev *card, struct vc_map *vc)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -