📄 he.c
字号:
he_writel(he_dev, 0x006f, G6_INMQ_S); he_writel(he_dev, 0x206f, G6_INMQ_L); he_writel(he_dev, 0x007f, G7_INMQ_S); he_writel(he_dev, 0x207f, G7_INMQ_L); } else { he_writel(he_dev, 0x0000, G0_INMQ_S); he_writel(he_dev, 0x0008, G0_INMQ_L); he_writel(he_dev, 0x0001, G1_INMQ_S); he_writel(he_dev, 0x0009, G1_INMQ_L); he_writel(he_dev, 0x0002, G2_INMQ_S); he_writel(he_dev, 0x000a, G2_INMQ_L); he_writel(he_dev, 0x0003, G3_INMQ_S); he_writel(he_dev, 0x000b, G3_INMQ_L); he_writel(he_dev, 0x0004, G4_INMQ_S); he_writel(he_dev, 0x000c, G4_INMQ_L); he_writel(he_dev, 0x0005, G5_INMQ_S); he_writel(he_dev, 0x000d, G5_INMQ_L); he_writel(he_dev, 0x0006, G6_INMQ_S); he_writel(he_dev, 0x000e, G6_INMQ_L); he_writel(he_dev, 0x0007, G7_INMQ_S); he_writel(he_dev, 0x000f, G7_INMQ_L); } /* 5.1.6 application tunable parameters */ he_writel(he_dev, 0x0, MCC); he_writel(he_dev, 0x0, OEC); he_writel(he_dev, 0x0, DCC); he_writel(he_dev, 0x0, CEC); /* 5.1.7 cs block initialization */ he_init_cs_block(he_dev); /* 5.1.8 cs block connection memory initialization */ if (he_init_cs_block_rcm(he_dev) < 0) return -ENOMEM; /* 5.1.10 initialize host structures */ he_init_tpdrq(he_dev);#ifdef USE_TPD_POOL he_dev->tpd_pool = pci_pool_create("tpd", he_dev->pci_dev, sizeof(struct he_tpd), TPD_ALIGNMENT, 0); if (he_dev->tpd_pool == NULL) { hprintk("unable to create tpd pci_pool\n"); return -ENOMEM; } INIT_LIST_HEAD(&he_dev->outstanding_tpds);#else he_dev->tpd_base = (void *) pci_alloc_consistent(he_dev->pci_dev, CONFIG_NUMTPDS * sizeof(struct he_tpd), &he_dev->tpd_base_phys); if (!he_dev->tpd_base) return -ENOMEM; for (i = 0; i < CONFIG_NUMTPDS; ++i) { he_dev->tpd_base[i].status = (i << TPD_ADDR_SHIFT); he_dev->tpd_base[i].inuse = 0; } he_dev->tpd_head = he_dev->tpd_base; he_dev->tpd_end = &he_dev->tpd_base[CONFIG_NUMTPDS - 1];#endif if (he_init_group(he_dev, 0) != 0) return -ENOMEM; for (group = 1; group < HE_NUM_GROUPS; ++group) { he_writel(he_dev, 0x0, G0_RBPS_S + (group * 32)); he_writel(he_dev, 0x0, G0_RBPS_T + (group * 32)); he_writel(he_dev, 0x0, G0_RBPS_QI + (group * 32)); he_writel(he_dev, RBP_THRESH(0x1) | RBP_QSIZE(0x0), G0_RBPS_BS + (group * 32)); he_writel(he_dev, 0x0, G0_RBPL_S + (group * 32)); he_writel(he_dev, 0x0, G0_RBPL_T + (group * 32)); he_writel(he_dev, RBP_THRESH(0x1) | RBP_QSIZE(0x0), G0_RBPL_QI + (group * 32)); he_writel(he_dev, 0x0, G0_RBPL_BS + (group * 32)); he_writel(he_dev, 0x0, G0_RBRQ_ST + (group * 16)); he_writel(he_dev, 0x0, G0_RBRQ_H + (group * 16)); he_writel(he_dev, RBRQ_THRESH(0x1) | RBRQ_SIZE(0x0), G0_RBRQ_Q + (group * 16)); he_writel(he_dev, 0x0, G0_RBRQ_I + (group * 16)); he_writel(he_dev, 0x0, G0_TBRQ_B_T + (group * 16)); he_writel(he_dev, 0x0, G0_TBRQ_H + (group * 16)); he_writel(he_dev, TBRQ_THRESH(0x1), G0_TBRQ_THRESH + (group * 16)); he_writel(he_dev, 0x0, G0_TBRQ_S + (group * 16)); } /* host status page */ he_dev->hsp = pci_alloc_consistent(he_dev->pci_dev, sizeof(struct he_hsp), &he_dev->hsp_phys); if (he_dev->hsp == NULL) { hprintk("failed to allocate host status page\n"); return -ENOMEM; } memset(he_dev->hsp, 0, sizeof(struct he_hsp)); he_writel(he_dev, he_dev->hsp_phys, HSP_BA); /* initialize framer */#ifdef CONFIG_ATM_HE_USE_SUNI suni_init(he_dev->atm_dev); if (he_dev->atm_dev->phy && he_dev->atm_dev->phy->start) he_dev->atm_dev->phy->start(he_dev->atm_dev);#endif /* CONFIG_ATM_HE_USE_SUNI */ if (sdh) { /* this really should be in suni.c but for now... */ int val; val = he_phy_get(he_dev->atm_dev, SUNI_TPOP_APM); val = (val & ~SUNI_TPOP_APM_S) | (SUNI_TPOP_S_SDH << SUNI_TPOP_APM_S_SHIFT); he_phy_put(he_dev->atm_dev, val, SUNI_TPOP_APM); } /* 5.1.12 enable transmit and receive */ reg = he_readl_mbox(he_dev, CS_ERCTL0); reg |= TX_ENABLE|ER_ENABLE; he_writel_mbox(he_dev, reg, CS_ERCTL0); reg = he_readl(he_dev, RC_CONFIG); reg |= RX_ENABLE; he_writel(he_dev, reg, RC_CONFIG); for (i = 0; i < HE_NUM_CS_STPER; ++i) { he_dev->cs_stper[i].inuse = 0; he_dev->cs_stper[i].pcr = -1; } he_dev->total_bw = 0; /* atm linux initialization */ he_dev->atm_dev->ci_range.vpi_bits = he_dev->vpibits; he_dev->atm_dev->ci_range.vci_bits = he_dev->vcibits; he_dev->irq_peak = 0; he_dev->rbrq_peak = 0; he_dev->rbpl_peak = 0; he_dev->tbrq_peak = 0; HPRINTK("hell bent for leather!\n"); return 0;}static voidhe_stop(struct he_dev *he_dev){ u16 command; u32 gen_cntl_0, reg; struct pci_dev *pci_dev; pci_dev = he_dev->pci_dev; /* disable interrupts */ if (he_dev->membase) { pci_read_config_dword(pci_dev, GEN_CNTL_0, &gen_cntl_0); gen_cntl_0 &= ~(INT_PROC_ENBL | INIT_ENB); pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0);#ifdef USE_TASKLET tasklet_disable(&he_dev->tasklet);#endif /* disable recv and transmit */ reg = he_readl_mbox(he_dev, CS_ERCTL0); reg &= ~(TX_ENABLE|ER_ENABLE); he_writel_mbox(he_dev, reg, CS_ERCTL0); reg = he_readl(he_dev, RC_CONFIG); reg &= ~(RX_ENABLE); he_writel(he_dev, reg, RC_CONFIG); }#ifdef CONFIG_ATM_HE_USE_SUNI if (he_dev->atm_dev->phy && he_dev->atm_dev->phy->stop) he_dev->atm_dev->phy->stop(he_dev->atm_dev);#endif /* CONFIG_ATM_HE_USE_SUNI */ if (he_dev->irq) free_irq(he_dev->irq, he_dev); if (he_dev->irq_base) pci_free_consistent(he_dev->pci_dev, (CONFIG_IRQ_SIZE+1) * sizeof(struct he_irq), he_dev->irq_base, he_dev->irq_phys); if (he_dev->hsp) pci_free_consistent(he_dev->pci_dev, sizeof(struct he_hsp), he_dev->hsp, he_dev->hsp_phys); if (he_dev->rbpl_base) {#ifdef USE_RBPL_POOL for (i = 0; i < CONFIG_RBPL_SIZE; ++i) { void *cpuaddr = he_dev->rbpl_virt[i].virt; dma_addr_t dma_handle = he_dev->rbpl_base[i].phys; pci_pool_free(he_dev->rbpl_pool, cpuaddr, dma_handle); }#else pci_free_consistent(he_dev->pci_dev, CONFIG_RBPL_SIZE * CONFIG_RBPL_BUFSIZE, he_dev->rbpl_pages, he_dev->rbpl_pages_phys);#endif pci_free_consistent(he_dev->pci_dev, CONFIG_RBPL_SIZE * sizeof(struct he_rbp), he_dev->rbpl_base, he_dev->rbpl_phys); }#ifdef USE_RBPL_POOL if (he_dev->rbpl_pool) pci_pool_destroy(he_dev->rbpl_pool);#endif#ifdef USE_RBPS if (he_dev->rbps_base) {#ifdef USE_RBPS_POOL for (i = 0; i < CONFIG_RBPS_SIZE; ++i) { void *cpuaddr = he_dev->rbps_virt[i].virt; dma_addr_t dma_handle = he_dev->rbps_base[i].phys; pci_pool_free(he_dev->rbps_pool, cpuaddr, dma_handle); }#else pci_free_consistent(he_dev->pci_dev, CONFIG_RBPS_SIZE * CONFIG_RBPS_BUFSIZE, he_dev->rbps_pages, he_dev->rbps_pages_phys);#endif pci_free_consistent(he_dev->pci_dev, CONFIG_RBPS_SIZE * sizeof(struct he_rbp), he_dev->rbps_base, he_dev->rbps_phys); }#ifdef USE_RBPS_POOL if (he_dev->rbps_pool) pci_pool_destroy(he_dev->rbps_pool);#endif#endif /* USE_RBPS */ if (he_dev->rbrq_base) pci_free_consistent(he_dev->pci_dev, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), he_dev->rbrq_base, he_dev->rbrq_phys); if (he_dev->tbrq_base) pci_free_consistent(he_dev->pci_dev, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), he_dev->tbrq_base, he_dev->tbrq_phys); if (he_dev->tpdrq_base) pci_free_consistent(he_dev->pci_dev, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), he_dev->tpdrq_base, he_dev->tpdrq_phys);#ifdef USE_TPD_POOL if (he_dev->tpd_pool) pci_pool_destroy(he_dev->tpd_pool);#else if (he_dev->tpd_base) pci_free_consistent(he_dev->pci_dev, CONFIG_NUMTPDS * sizeof(struct he_tpd), he_dev->tpd_base, he_dev->tpd_base_phys);#endif if (he_dev->pci_dev) { pci_read_config_word(he_dev->pci_dev, PCI_COMMAND, &command); command &= ~(PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); pci_write_config_word(he_dev->pci_dev, PCI_COMMAND, command); } if (he_dev->membase) iounmap(he_dev->membase);}static struct he_tpd *__alloc_tpd(struct he_dev *he_dev){#ifdef USE_TPD_POOL struct he_tpd *tpd; dma_addr_t dma_handle; tpd = pci_pool_alloc(he_dev->tpd_pool, GFP_ATOMIC|GFP_DMA, &dma_handle); if (tpd == NULL) return NULL; tpd->status = TPD_ADDR(dma_handle); tpd->reserved = 0; tpd->iovec[0].addr = 0; tpd->iovec[0].len = 0; tpd->iovec[1].addr = 0; tpd->iovec[1].len = 0; tpd->iovec[2].addr = 0; tpd->iovec[2].len = 0; return tpd;#else int i; for (i = 0; i < CONFIG_NUMTPDS; ++i) { ++he_dev->tpd_head; if (he_dev->tpd_head > he_dev->tpd_end) { he_dev->tpd_head = he_dev->tpd_base; } if (!he_dev->tpd_head->inuse) { he_dev->tpd_head->inuse = 1; he_dev->tpd_head->status &= TPD_MASK; he_dev->tpd_head->iovec[0].addr = 0; he_dev->tpd_head->iovec[0].len = 0; he_dev->tpd_head->iovec[1].addr = 0; he_dev->tpd_head->iovec[1].len = 0; he_dev->tpd_head->iovec[2].addr = 0; he_dev->tpd_head->iovec[2].len = 0; return he_dev->tpd_head; } } hprintk("out of tpds -- increase CONFIG_NUMTPDS (%d)\n", CONFIG_NUMTPDS); return NULL;#endif}#define AAL5_LEN(buf,len) \ ((((unsigned char *)(buf))[(len)-6] << 8) | \ (((unsigned char *)(buf))[(len)-5]))/* 2.10.1.2 receive * * aal5 packets can optionally return the tcp checksum in the lower * 16 bits of the crc (RSR0_TCP_CKSUM) */#define TCP_CKSUM(buf,len) \ ((((unsigned char *)(buf))[(len)-2] << 8) | \ (((unsigned char *)(buf))[(len-1)]))static inthe_service_rbrq(struct he_dev *he_dev, int group){ struct he_rbrq *rbrq_tail = (struct he_rbrq *) ((unsigned long)he_dev->rbrq_base | he_dev->hsp->group[group].rbrq_tail); struct he_rbp *rbp = NULL; unsigned cid, lastcid = -1; unsigned buf_len = 0; struct sk_buff *skb; struct atm_vcc *vcc = NULL; struct he_vcc *he_vcc; struct he_iovec *iov; int pdus_assembled = 0; int updated = 0; read_lock(&vcc_sklist_lock); while (he_dev->rbrq_head != rbrq_tail) { ++updated; HPRINTK("%p rbrq%d 0x%x len=%d cid=0x%x %s%s%s%s%s%s\n", he_dev->rbrq_head, group, RBRQ_ADDR(he_dev->rbrq_head), RBRQ_BUFLEN(he_dev->rbrq_head), RBRQ_CID(he_dev->rbrq_head), RBRQ_CRC_ERR(he_dev->rbrq_head) ? " CRC_ERR" : "", RBRQ_LEN_ERR(he_dev->rbrq_head) ? " LEN_ERR" : "", RBRQ_END_PDU(he_dev->rbrq_head) ? " END_PDU" : "", RBRQ_AAL5_PROT(he_dev->rbrq_head) ? " AAL5_PROT" : "", RBRQ_CON_CLOSED(he_dev->rbrq_head) ? " CON_CLOSED" : "", RBRQ_HBUF_ERR(he_dev->rbrq_head) ? " HBUF_ERR" : "");#ifdef USE_RBPS if (RBRQ_ADDR(he_dev->rbrq_head) & RBP_SMALLBUF) rbp = &he_dev->rbps_base[RBP_INDEX(RBRQ_ADDR(he_dev->rbrq_head))]; else#endif rbp = &he_dev->rbpl_base[RBP_INDEX(RBRQ_ADDR(he_dev->rbrq_head))]; buf_len = RBRQ_BUFLEN(he_dev->rbrq_head) * 4; cid = RBRQ_CID(he_dev->rbrq_head); if (cid != lastcid) vcc = __find_vcc(he_dev, cid); lastcid = cid; if (vcc == NULL) { hprintk("vcc == NULL (cid 0x%x)\n", cid); if (!RBRQ_HBUF_ERR(he_dev->rbrq_head)) rbp->status &= ~RBP_LOANED; goto next_rbrq_entry; } he_vcc = HE_VCC(vcc); if (he_vcc == NULL) { hprintk("he_vcc == NULL (cid 0x%x)\n", cid); if (!RBRQ_HBUF_ERR(he_dev->rbrq_head)) rbp->status &= ~RBP_LOANED; goto next_rbrq_entry; } if (RBRQ_HBUF_ERR(he_dev->rbrq_head)) { hprintk("HBUF_ERR! (cid 0x%x)\n", cid); atomic_inc(&vcc->stats->rx_drop); goto return_host_buffers; } he_vcc->iov_tail->iov_base = RBRQ_ADDR(he_dev->rbrq_head); he_vcc->iov_tail->iov_len = buf_len; he_vcc->pdu_len += buf_len; ++he_vcc->iov_tail; if (RBRQ_CON_CLOSED(he_dev->rbrq_head)) { lastcid = -1; HPRINTK("wake_up rx_waitq (cid 0x%x)\n", cid); wake_up(&he_vcc->rx_waitq); goto return_host_buffers; }#ifdef notdef if ((he_vcc->iov_tail - he_vcc->iov_head) > HE_MAXIOV) { hprintk("iovec full! cid 0x%x\n", cid); goto return_host_buffers; }#endif if (!RBRQ_END_PDU(he_dev->rbrq_head)) goto next_rbrq_entry; if (RBRQ_LEN_ERR(he_dev->rbrq_head) || RBRQ_CRC_ERR(he_dev->rbrq_head)) { HPRINTK("%s%s (%d.%d)\n", RBRQ_CRC_ERR(he_dev->rbrq_head) ? "CRC_ERR " : "", RBRQ_LEN_ERR(he_dev->rbrq_head) ? "LEN_ERR" : "", vcc->vpi, vcc->vci); atomic_inc(&vcc->stats->rx_err); goto return_host_buffers; } skb = atm_alloc_charge(vcc, he_vcc->pdu_len + rx_skb_reserve, GFP_ATOMIC); if (!skb) { HPRINTK("charge failed (%d.%d)\n", vcc->vpi, vcc->vci); goto return_host_buffers; } if (rx_skb_reserve > 0) skb_reserve(skb, rx_skb_reserve); __net_timestamp(skb); for (iov = he_vcc->iov_head; iov < he_vcc->iov_tail; ++iov) {#ifdef USE_RBPS if (iov->iov_base & RBP_SMALLBUF) memcpy(skb_put(skb, iov->iov_len), he_dev->rbps_virt[RBP_INDEX(iov->iov_base)].virt, iov->iov_len); else#endif memcpy(skb_put(skb, iov->iov_len), he_dev->rbpl_virt[RBP_INDEX(iov->iov_base)].virt, iov->iov_len); } switch (vcc->qos.aal) { case ATM_AAL0: /* 2.10.1.5 raw cell receive */ skb->len = ATM_AAL0_SDU; skb_set_tail_pointer(skb, skb->len); break; case ATM_AAL5: /* 2.10.1.2 aal5 receive */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -