dect
/
linux-2.6
Archived
13
0
Fork 0

atm: [nicstar] remove virt_to_bus() and support 64-bit platforms

Signed-off-by: Chas Williams - CONTRACTOR <chas@cmf.nrl.navy.mil>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
chas williams - CONTRACTOR 2010-05-29 09:04:25 +00:00 committed by David S. Miller
parent 098fde114b
commit 864a3ff635
3 changed files with 236 additions and 174 deletions

View File

@ -177,7 +177,7 @@ config ATM_ZATM_DEBUG
config ATM_NICSTAR config ATM_NICSTAR
tristate "IDT 77201 (NICStAR) (ForeRunnerLE)" tristate "IDT 77201 (NICStAR) (ForeRunnerLE)"
depends on PCI && !64BIT && VIRT_TO_BUS depends on PCI
help help
The NICStAR chipset family is used in a large number of ATM NICs for The NICStAR chipset family is used in a large number of ATM NICs for
25 and for 155 Mbps, including IDT cards and the Fore ForeRunnerLE 25 and for 155 Mbps, including IDT cards and the Fore ForeRunnerLE

View File

@ -38,6 +38,7 @@
#include <linux/atmdev.h> #include <linux/atmdev.h>
#include <linux/atm.h> #include <linux/atm.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/dma-mapping.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/delay.h> #include <linux/delay.h>
@ -47,6 +48,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/idr.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/atomic.h> #include <asm/atomic.h>
@ -58,10 +60,6 @@
#include "idt77105.h" #include "idt77105.h"
#endif /* CONFIG_ATM_NICSTAR_USE_IDT77105 */ #endif /* CONFIG_ATM_NICSTAR_USE_IDT77105 */
#if BITS_PER_LONG != 32
# error FIXME: this driver requires a 32-bit platform
#endif
/* Additional code */ /* Additional code */
#include "nicstarmac.c" #include "nicstarmac.c"
@ -109,17 +107,15 @@
#define NS_DELAY mdelay(1) #define NS_DELAY mdelay(1)
#define ALIGN_BUS_ADDR(addr, alignment) \ #define PTR_DIFF(a, b) ((u32)((unsigned long)(a) - (unsigned long)(b)))
((((u32) (addr)) + (((u32) (alignment)) - 1)) & ~(((u32) (alignment)) - 1))
#define ALIGN_ADDRESS(addr, alignment) \
bus_to_virt(ALIGN_BUS_ADDR(virt_to_bus(addr), alignment))
#undef CEIL
#ifndef ATM_SKB #ifndef ATM_SKB
#define ATM_SKB(s) (&(s)->atm) #define ATM_SKB(s) (&(s)->atm)
#endif #endif
#define scq_virt_to_bus(scq, p) \
(scq->dma + ((unsigned long)(p) - (unsigned long)(scq)->org))
/* Function declarations */ /* Function declarations */
static u32 ns_read_sram(ns_dev * card, u32 sram_address); static u32 ns_read_sram(ns_dev * card, u32 sram_address);
@ -127,8 +123,8 @@ static void ns_write_sram(ns_dev * card, u32 sram_address, u32 * value,
int count); int count);
static int __devinit ns_init_card(int i, struct pci_dev *pcidev); static int __devinit ns_init_card(int i, struct pci_dev *pcidev);
static void __devinit ns_init_card_error(ns_dev * card, int error); static void __devinit ns_init_card_error(ns_dev * card, int error);
static scq_info *get_scq(int size, u32 scd); static scq_info *get_scq(ns_dev *card, int size, u32 scd);
static void free_scq(scq_info * scq, struct atm_vcc *vcc); static void free_scq(ns_dev *card, scq_info * scq, struct atm_vcc *vcc);
static void push_rxbufs(ns_dev *, struct sk_buff *); static void push_rxbufs(ns_dev *, struct sk_buff *);
static irqreturn_t ns_irq_handler(int irq, void *dev_id); static irqreturn_t ns_irq_handler(int irq, void *dev_id);
static int ns_open(struct atm_vcc *vcc); static int ns_open(struct atm_vcc *vcc);
@ -153,7 +149,9 @@ static void dequeue_sm_buf(ns_dev * card, struct sk_buff *sb);
static void dequeue_lg_buf(ns_dev * card, struct sk_buff *lb); static void dequeue_lg_buf(ns_dev * card, struct sk_buff *lb);
static int ns_proc_read(struct atm_dev *dev, loff_t * pos, char *page); static int ns_proc_read(struct atm_dev *dev, loff_t * pos, char *page);
static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void __user * arg); static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void __user * arg);
#ifdef EXTRA_DEBUG
static void which_list(ns_dev * card, struct sk_buff *skb); static void which_list(ns_dev * card, struct sk_buff *skb);
#endif
static void ns_poll(unsigned long arg); static void ns_poll(unsigned long arg);
static int ns_parse_mac(char *mac, unsigned char *esi); static int ns_parse_mac(char *mac, unsigned char *esi);
static short ns_h2i(char c); static short ns_h2i(char c);
@ -249,13 +247,17 @@ static void __devexit nicstar_remove_one(struct pci_dev *pcidev)
dev_kfree_skb_any(lb); dev_kfree_skb_any(lb);
while ((sb = skb_dequeue(&card->sbpool.queue)) != NULL) while ((sb = skb_dequeue(&card->sbpool.queue)) != NULL)
dev_kfree_skb_any(sb); dev_kfree_skb_any(sb);
free_scq(card->scq0, NULL); free_scq(card, card->scq0, NULL);
for (j = 0; j < NS_FRSCD_NUM; j++) { for (j = 0; j < NS_FRSCD_NUM; j++) {
if (card->scd2vc[j] != NULL) if (card->scd2vc[j] != NULL)
free_scq(card->scd2vc[j]->scq, card->scd2vc[j]->tx_vcc); free_scq(card, card->scd2vc[j]->scq, card->scd2vc[j]->tx_vcc);
} }
kfree(card->rsq.org); idr_remove_all(&card->idr);
kfree(card->tsq.org); idr_destroy(&card->idr);
pci_free_consistent(card->pcidev, NS_RSQSIZE + NS_RSQ_ALIGNMENT,
card->rsq.org, card->rsq.dma);
pci_free_consistent(card->pcidev, NS_TSQSIZE + NS_TSQ_ALIGNMENT,
card->tsq.org, card->tsq.dma);
free_irq(card->pcidev->irq, card); free_irq(card->pcidev->irq, card);
iounmap(card->membase); iounmap(card->membase);
kfree(card); kfree(card);
@ -371,6 +373,14 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev)
ns_init_card_error(card, error); ns_init_card_error(card, error);
return error; return error;
} }
if ((pci_set_dma_mask(pcidev, DMA_BIT_MASK(32)) != 0) ||
(pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(32)) != 0)) {
printk(KERN_WARNING
"nicstar%d: No suitable DMA available.\n", i);
error = 2;
ns_init_card_error(card, error);
return error;
}
if ((card = kmalloc(sizeof(ns_dev), GFP_KERNEL)) == NULL) { if ((card = kmalloc(sizeof(ns_dev), GFP_KERNEL)) == NULL) {
printk printk
@ -397,7 +407,7 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev)
ns_init_card_error(card, error); ns_init_card_error(card, error);
return error; return error;
} }
PRINTK("nicstar%d: membase at 0x%x.\n", i, card->membase); PRINTK("nicstar%d: membase at 0x%p.\n", i, card->membase);
pci_set_master(pcidev); pci_set_master(pcidev);
@ -528,54 +538,54 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev)
writel(0x00000000, card->membase + VPM); writel(0x00000000, card->membase + VPM);
/* Initialize TSQ */ /* Initialize TSQ */
card->tsq.org = kmalloc(NS_TSQSIZE + NS_TSQ_ALIGNMENT, GFP_KERNEL); card->tsq.org = pci_alloc_consistent(card->pcidev,
NS_TSQSIZE + NS_TSQ_ALIGNMENT,
&card->tsq.dma);
if (card->tsq.org == NULL) { if (card->tsq.org == NULL) {
printk("nicstar%d: can't allocate TSQ.\n", i); printk("nicstar%d: can't allocate TSQ.\n", i);
error = 10; error = 10;
ns_init_card_error(card, error); ns_init_card_error(card, error);
return error; return error;
} }
card->tsq.base = card->tsq.base = PTR_ALIGN(card->tsq.org, NS_TSQ_ALIGNMENT);
(ns_tsi *) ALIGN_ADDRESS(card->tsq.org, NS_TSQ_ALIGNMENT);
card->tsq.next = card->tsq.base; card->tsq.next = card->tsq.base;
card->tsq.last = card->tsq.base + (NS_TSQ_NUM_ENTRIES - 1); card->tsq.last = card->tsq.base + (NS_TSQ_NUM_ENTRIES - 1);
for (j = 0; j < NS_TSQ_NUM_ENTRIES; j++) for (j = 0; j < NS_TSQ_NUM_ENTRIES; j++)
ns_tsi_init(card->tsq.base + j); ns_tsi_init(card->tsq.base + j);
writel(0x00000000, card->membase + TSQH); writel(0x00000000, card->membase + TSQH);
writel((u32) virt_to_bus(card->tsq.base), card->membase + TSQB); writel(ALIGN(card->tsq.dma, NS_TSQ_ALIGNMENT), card->membase + TSQB);
PRINTK("nicstar%d: TSQ base at 0x%x 0x%x 0x%x.\n", i, PRINTK("nicstar%d: TSQ base at 0x%p.\n", i, card->tsq.base);
(u32) card->tsq.base, (u32) virt_to_bus(card->tsq.base),
readl(card->membase + TSQB));
/* Initialize RSQ */ /* Initialize RSQ */
card->rsq.org = kmalloc(NS_RSQSIZE + NS_RSQ_ALIGNMENT, GFP_KERNEL); card->rsq.org = pci_alloc_consistent(card->pcidev,
NS_RSQSIZE + NS_RSQ_ALIGNMENT,
&card->rsq.dma);
if (card->rsq.org == NULL) { if (card->rsq.org == NULL) {
printk("nicstar%d: can't allocate RSQ.\n", i); printk("nicstar%d: can't allocate RSQ.\n", i);
error = 11; error = 11;
ns_init_card_error(card, error); ns_init_card_error(card, error);
return error; return error;
} }
card->rsq.base = card->rsq.base = PTR_ALIGN(card->rsq.org, NS_RSQ_ALIGNMENT);
(ns_rsqe *) ALIGN_ADDRESS(card->rsq.org, NS_RSQ_ALIGNMENT);
card->rsq.next = card->rsq.base; card->rsq.next = card->rsq.base;
card->rsq.last = card->rsq.base + (NS_RSQ_NUM_ENTRIES - 1); card->rsq.last = card->rsq.base + (NS_RSQ_NUM_ENTRIES - 1);
for (j = 0; j < NS_RSQ_NUM_ENTRIES; j++) for (j = 0; j < NS_RSQ_NUM_ENTRIES; j++)
ns_rsqe_init(card->rsq.base + j); ns_rsqe_init(card->rsq.base + j);
writel(0x00000000, card->membase + RSQH); writel(0x00000000, card->membase + RSQH);
writel((u32) virt_to_bus(card->rsq.base), card->membase + RSQB); writel(ALIGN(card->rsq.dma, NS_RSQ_ALIGNMENT), card->membase + RSQB);
PRINTK("nicstar%d: RSQ base at 0x%x.\n", i, (u32) card->rsq.base); PRINTK("nicstar%d: RSQ base at 0x%p.\n", i, card->rsq.base);
/* Initialize SCQ0, the only VBR SCQ used */ /* Initialize SCQ0, the only VBR SCQ used */
card->scq1 = NULL; card->scq1 = NULL;
card->scq2 = NULL; card->scq2 = NULL;
card->scq0 = get_scq(VBR_SCQSIZE, NS_VRSCD0); card->scq0 = get_scq(card, VBR_SCQSIZE, NS_VRSCD0);
if (card->scq0 == NULL) { if (card->scq0 == NULL) {
printk("nicstar%d: can't get SCQ0.\n", i); printk("nicstar%d: can't get SCQ0.\n", i);
error = 12; error = 12;
ns_init_card_error(card, error); ns_init_card_error(card, error);
return error; return error;
} }
u32d[0] = (u32) virt_to_bus(card->scq0->base); u32d[0] = scq_virt_to_bus(card->scq0, card->scq0->base);
u32d[1] = (u32) 0x00000000; u32d[1] = (u32) 0x00000000;
u32d[2] = (u32) 0xffffffff; u32d[2] = (u32) 0xffffffff;
u32d[3] = (u32) 0x00000000; u32d[3] = (u32) 0x00000000;
@ -583,8 +593,7 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev)
ns_write_sram(card, NS_VRSCD1, u32d, 4); /* These last two won't be used */ ns_write_sram(card, NS_VRSCD1, u32d, 4); /* These last two won't be used */
ns_write_sram(card, NS_VRSCD2, u32d, 4); /* but are initialized, just in case... */ ns_write_sram(card, NS_VRSCD2, u32d, 4); /* but are initialized, just in case... */
card->scq0->scd = NS_VRSCD0; card->scq0->scd = NS_VRSCD0;
PRINTK("nicstar%d: VBR-SCQ0 base at 0x%x.\n", i, PRINTK("nicstar%d: VBR-SCQ0 base at 0x%p.\n", i, card->scq0->base);
(u32) card->scq0->base);
/* Initialize TSTs */ /* Initialize TSTs */
card->tst_addr = NS_TST0; card->tst_addr = NS_TST0;
@ -640,6 +649,8 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev)
card->efbie = 1; /* To prevent push_rxbufs from enabling the interrupt */ card->efbie = 1; /* To prevent push_rxbufs from enabling the interrupt */
idr_init(&card->idr);
/* Pre-allocate some huge buffers */ /* Pre-allocate some huge buffers */
skb_queue_head_init(&card->hbpool.queue); skb_queue_head_init(&card->hbpool.queue);
card->hbpool.count = 0; card->hbpool.count = 0;
@ -654,7 +665,7 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev)
ns_init_card_error(card, error); ns_init_card_error(card, error);
return error; return error;
} }
NS_SKB_CB(hb)->buf_type = BUF_NONE; NS_PRV_BUFTYPE(hb) = BUF_NONE;
skb_queue_tail(&card->hbpool.queue, hb); skb_queue_tail(&card->hbpool.queue, hb);
card->hbpool.count++; card->hbpool.count++;
} }
@ -673,14 +684,15 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev)
ns_init_card_error(card, error); ns_init_card_error(card, error);
return error; return error;
} }
NS_SKB_CB(lb)->buf_type = BUF_LG; NS_PRV_BUFTYPE(lb) = BUF_LG;
skb_queue_tail(&card->lbpool.queue, lb); skb_queue_tail(&card->lbpool.queue, lb);
skb_reserve(lb, NS_SMBUFSIZE); skb_reserve(lb, NS_SMBUFSIZE);
push_rxbufs(card, lb); push_rxbufs(card, lb);
/* Due to the implementation of push_rxbufs() this is 1, not 0 */ /* Due to the implementation of push_rxbufs() this is 1, not 0 */
if (j == 1) { if (j == 1) {
card->rcbuf = lb; card->rcbuf = lb;
card->rawch = (u32) virt_to_bus(lb->data); card->rawcell = (struct ns_rcqe *) lb->data;
card->rawch = NS_PRV_DMA(lb);
} }
} }
/* Test for strange behaviour which leads to crashes */ /* Test for strange behaviour which leads to crashes */
@ -708,7 +720,7 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev)
ns_init_card_error(card, error); ns_init_card_error(card, error);
return error; return error;
} }
NS_SKB_CB(sb)->buf_type = BUF_SM; NS_PRV_BUFTYPE(sb) = BUF_SM;
skb_queue_tail(&card->sbpool.queue, sb); skb_queue_tail(&card->sbpool.queue, sb);
skb_reserve(sb, NS_AAL0_HEADER); skb_reserve(sb, NS_AAL0_HEADER);
push_rxbufs(card, sb); push_rxbufs(card, sb);
@ -738,7 +750,7 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev)
ns_init_card_error(card, error); ns_init_card_error(card, error);
return error; return error;
} }
NS_SKB_CB(iovb)->buf_type = BUF_NONE; NS_PRV_BUFTYPE(iovb) = BUF_NONE;
skb_queue_tail(&card->iovpool.queue, iovb); skb_queue_tail(&card->iovpool.queue, iovb);
card->iovpool.count++; card->iovpool.count++;
} }
@ -825,7 +837,7 @@ static void __devinit ns_init_card_error(ns_dev * card, int error)
struct sk_buff *sb; struct sk_buff *sb;
while ((sb = skb_dequeue(&card->sbpool.queue)) != NULL) while ((sb = skb_dequeue(&card->sbpool.queue)) != NULL)
dev_kfree_skb_any(sb); dev_kfree_skb_any(sb);
free_scq(card->scq0, NULL); free_scq(card, card->scq0, NULL);
} }
if (error >= 14) { if (error >= 14) {
struct sk_buff *lb; struct sk_buff *lb;
@ -855,7 +867,7 @@ static void __devinit ns_init_card_error(ns_dev * card, int error)
} }
} }
static scq_info *get_scq(int size, u32 scd) static scq_info *get_scq(ns_dev *card, int size, u32 scd)
{ {
scq_info *scq; scq_info *scq;
int i; int i;
@ -864,22 +876,22 @@ static scq_info *get_scq(int size, u32 scd)
return NULL; return NULL;
scq = kmalloc(sizeof(scq_info), GFP_KERNEL); scq = kmalloc(sizeof(scq_info), GFP_KERNEL);
if (scq == NULL) if (!scq)
return NULL; return NULL;
scq->org = kmalloc(2 * size, GFP_KERNEL); scq->org = pci_alloc_consistent(card->pcidev, 2 * size, &scq->dma);
if (scq->org == NULL) { if (!scq->org) {
kfree(scq); kfree(scq);
return NULL; return NULL;
} }
scq->skb = kmalloc(sizeof(struct sk_buff *) * scq->skb = kmalloc(sizeof(struct sk_buff *) *
(size / NS_SCQE_SIZE), GFP_KERNEL); (size / NS_SCQE_SIZE), GFP_KERNEL);
if (scq->skb == NULL) { if (!scq->skb) {
kfree(scq->org); kfree(scq->org);
kfree(scq); kfree(scq);
return NULL; return NULL;
} }
scq->num_entries = size / NS_SCQE_SIZE; scq->num_entries = size / NS_SCQE_SIZE;
scq->base = (ns_scqe *) ALIGN_ADDRESS(scq->org, size); scq->base = PTR_ALIGN(scq->org, size);
scq->next = scq->base; scq->next = scq->base;
scq->last = scq->base + (scq->num_entries - 1); scq->last = scq->base + (scq->num_entries - 1);
scq->tail = scq->last; scq->tail = scq->last;
@ -897,7 +909,7 @@ static scq_info *get_scq(int size, u32 scd)
} }
/* For variable rate SCQ vcc must be NULL */ /* For variable rate SCQ vcc must be NULL */
static void free_scq(scq_info * scq, struct atm_vcc *vcc) static void free_scq(ns_dev *card, scq_info *scq, struct atm_vcc *vcc)
{ {
int i; int i;
@ -928,7 +940,10 @@ static void free_scq(scq_info * scq, struct atm_vcc *vcc)
} }
} }
kfree(scq->skb); kfree(scq->skb);
kfree(scq->org); pci_free_consistent(card->pcidev,
2 * (scq->num_entries == VBR_SCQ_NUM_ENTRIES ?
VBR_SCQSIZE : CBR_SCQSIZE),
scq->org, scq->dma);
kfree(scq); kfree(scq);
} }
@ -936,16 +951,23 @@ static void free_scq(scq_info * scq, struct atm_vcc *vcc)
or large buffer(s) cast to u32. */ or large buffer(s) cast to u32. */
static void push_rxbufs(ns_dev * card, struct sk_buff *skb) static void push_rxbufs(ns_dev * card, struct sk_buff *skb)
{ {
struct ns_skb_cb *cb = NS_SKB_CB(skb); struct sk_buff *handle1, *handle2;
u32 handle1, addr1; u32 id1 = 0, id2 = 0;
u32 handle2, addr2; u32 addr1, addr2;
u32 stat; u32 stat;
unsigned long flags; unsigned long flags;
int err;
/* *BARF* */ /* *BARF* */
handle2 = addr2 = 0; handle2 = NULL;
handle1 = (u32) skb; addr2 = 0;
addr1 = (u32) virt_to_bus(skb->data); handle1 = skb;
addr1 = pci_map_single(card->pcidev,
skb->data,
(NS_PRV_BUFTYPE(skb) == BUF_SM
? NS_SMSKBSIZE : NS_LGSKBSIZE),
PCI_DMA_TODEVICE);
NS_PRV_DMA(skb) = addr1; /* save so we can unmap later */
#ifdef GENERAL_DEBUG #ifdef GENERAL_DEBUG
if (!addr1) if (!addr1)
@ -956,7 +978,7 @@ static void push_rxbufs(ns_dev * card, struct sk_buff *skb)
stat = readl(card->membase + STAT); stat = readl(card->membase + STAT);
card->sbfqc = ns_stat_sfbqc_get(stat); card->sbfqc = ns_stat_sfbqc_get(stat);
card->lbfqc = ns_stat_lfbqc_get(stat); card->lbfqc = ns_stat_lfbqc_get(stat);
if (cb->buf_type == BUF_SM) { if (NS_PRV_BUFTYPE(skb) == BUF_SM) {
if (!addr2) { if (!addr2) {
if (card->sm_addr) { if (card->sm_addr) {
addr2 = card->sm_addr; addr2 = card->sm_addr;
@ -986,47 +1008,60 @@ static void push_rxbufs(ns_dev * card, struct sk_buff *skb)
} }
if (addr2) { if (addr2) {
if (cb->buf_type == BUF_SM) { if (NS_PRV_BUFTYPE(skb) == BUF_SM) {
if (card->sbfqc >= card->sbnr.max) { if (card->sbfqc >= card->sbnr.max) {
skb_unlink((struct sk_buff *)handle1, skb_unlink(handle1, &card->sbpool.queue);
&card->sbpool.queue); dev_kfree_skb_any(handle1);
dev_kfree_skb_any((struct sk_buff *)handle1); skb_unlink(handle2, &card->sbpool.queue);
skb_unlink((struct sk_buff *)handle2, dev_kfree_skb_any(handle2);
&card->sbpool.queue);
dev_kfree_skb_any((struct sk_buff *)handle2);
return; return;
} else } else
card->sbfqc += 2; card->sbfqc += 2;
} else { /* (buf_type == BUF_LG) */ } else { /* (buf_type == BUF_LG) */
if (card->lbfqc >= card->lbnr.max) { if (card->lbfqc >= card->lbnr.max) {
skb_unlink((struct sk_buff *)handle1, skb_unlink(handle1, &card->lbpool.queue);
&card->lbpool.queue); dev_kfree_skb_any(handle1);
dev_kfree_skb_any((struct sk_buff *)handle1); skb_unlink(handle2, &card->lbpool.queue);
skb_unlink((struct sk_buff *)handle2, dev_kfree_skb_any(handle2);
&card->lbpool.queue);
dev_kfree_skb_any((struct sk_buff *)handle2);
return; return;
} else } else
card->lbfqc += 2; card->lbfqc += 2;
} }
spin_lock_irqsave(&card->res_lock, flags); do {
if (!idr_pre_get(&card->idr, GFP_ATOMIC)) {
printk(KERN_ERR
"nicstar%d: no free memory for idr\n",
card->index);
goto out;
}
if (!id1)
err = idr_get_new_above(&card->idr, handle1, 0, &id1);
if (!id2 && err == 0)
err = idr_get_new_above(&card->idr, handle2, 0, &id2);
} while (err == -EAGAIN);
if (err)
goto out;
spin_lock_irqsave(&card->res_lock, flags);
while (CMD_BUSY(card)) ; while (CMD_BUSY(card)) ;
writel(addr2, card->membase + DR3); writel(addr2, card->membase + DR3);
writel(handle2, card->membase + DR2); writel(id2, card->membase + DR2);
writel(addr1, card->membase + DR1); writel(addr1, card->membase + DR1);
writel(handle1, card->membase + DR0); writel(id1, card->membase + DR0);
writel(NS_CMD_WRITE_FREEBUFQ | cb->buf_type, writel(NS_CMD_WRITE_FREEBUFQ | NS_PRV_BUFTYPE(skb),
card->membase + CMD); card->membase + CMD);
spin_unlock_irqrestore(&card->res_lock, flags); spin_unlock_irqrestore(&card->res_lock, flags);
XPRINTK("nicstar%d: Pushing %s buffers at 0x%x and 0x%x.\n", XPRINTK("nicstar%d: Pushing %s buffers at 0x%x and 0x%x.\n",
card->index, card->index,
(cb->buf_type == BUF_SM ? "small" : "large"), addr1, (NS_PRV_BUFTYPE(skb) == BUF_SM ? "small" : "large"),
addr2); addr1, addr2);
} }
if (!card->efbie && card->sbfqc >= card->sbnr.min && if (!card->efbie && card->sbfqc >= card->sbnr.min &&
@ -1036,6 +1071,7 @@ static void push_rxbufs(ns_dev * card, struct sk_buff *skb)
card->membase + CFG); card->membase + CFG);
} }
out:
return; return;
} }
@ -1131,21 +1167,21 @@ static irqreturn_t ns_irq_handler(int irq, void *dev_id)
next interrupt. As this preliminary support is only meant to next interrupt. As this preliminary support is only meant to
avoid buffer leakage, this is not an issue. */ avoid buffer leakage, this is not an issue. */
while (readl(card->membase + RAWCT) != card->rawch) { while (readl(card->membase + RAWCT) != card->rawch) {
ns_rcqe *rawcell;
rawcell = (ns_rcqe *) bus_to_virt(card->rawch); if (ns_rcqe_islast(card->rawcell)) {
if (ns_rcqe_islast(rawcell)) {
struct sk_buff *oldbuf; struct sk_buff *oldbuf;
oldbuf = card->rcbuf; oldbuf = card->rcbuf;
card->rcbuf = card->rcbuf = idr_find(&card->idr,
(struct sk_buff *) ns_rcqe_nextbufhandle(card->rawcell));
ns_rcqe_nextbufhandle(rawcell); card->rawch = NS_PRV_DMA(card->rcbuf);
card->rawch = card->rawcell = (struct ns_rcqe *)
(u32) virt_to_bus(card->rcbuf->data); card->rcbuf->data;
recycle_rx_buf(card, oldbuf); recycle_rx_buf(card, oldbuf);
} else } else {
card->rawch += NS_RCQE_SIZE; card->rawch += NS_RCQE_SIZE;
card->rawcell++;
}
} }
} }
@ -1165,7 +1201,7 @@ static irqreturn_t ns_irq_handler(int irq, void *dev_id)
card->efbie = 0; card->efbie = 0;
break; break;
} }
NS_SKB_CB(sb)->buf_type = BUF_SM; NS_PRV_BUFTYPE(sb) = BUF_SM;
skb_queue_tail(&card->sbpool.queue, sb); skb_queue_tail(&card->sbpool.queue, sb);
skb_reserve(sb, NS_AAL0_HEADER); skb_reserve(sb, NS_AAL0_HEADER);
push_rxbufs(card, sb); push_rxbufs(card, sb);
@ -1190,7 +1226,7 @@ static irqreturn_t ns_irq_handler(int irq, void *dev_id)
card->efbie = 0; card->efbie = 0;
break; break;
} }
NS_SKB_CB(lb)->buf_type = BUF_LG; NS_PRV_BUFTYPE(lb) = BUF_LG;
skb_queue_tail(&card->lbpool.queue, lb); skb_queue_tail(&card->lbpool.queue, lb);
skb_reserve(lb, NS_SMBUFSIZE); skb_reserve(lb, NS_SMBUFSIZE);
push_rxbufs(card, lb); push_rxbufs(card, lb);
@ -1338,7 +1374,7 @@ static int ns_open(struct atm_vcc *vcc)
vc->cbr_scd = NS_FRSCD + frscdi * NS_FRSCD_SIZE; vc->cbr_scd = NS_FRSCD + frscdi * NS_FRSCD_SIZE;
scq = get_scq(CBR_SCQSIZE, vc->cbr_scd); scq = get_scq(card, CBR_SCQSIZE, vc->cbr_scd);
if (scq == NULL) { if (scq == NULL) {
PRINTK("nicstar%d: can't get fixed rate SCQ.\n", PRINTK("nicstar%d: can't get fixed rate SCQ.\n",
card->index); card->index);
@ -1349,7 +1385,7 @@ static int ns_open(struct atm_vcc *vcc)
return -ENOMEM; return -ENOMEM;
} }
vc->scq = scq; vc->scq = scq;
u32d[0] = (u32) virt_to_bus(scq->base); u32d[0] = scq_virt_to_bus(scq, scq->base);
u32d[1] = (u32) 0x00000000; u32d[1] = (u32) 0x00000000;
u32d[2] = (u32) 0xffffffff; u32d[2] = (u32) 0xffffffff;
u32d[3] = (u32) 0x00000000; u32d[3] = (u32) 0x00000000;
@ -1434,9 +1470,8 @@ static void ns_close(struct atm_vcc *vcc)
card->index); card->index);
iovb = vc->rx_iov; iovb = vc->rx_iov;
recycle_iovec_rx_bufs(card, (struct iovec *)iovb->data, recycle_iovec_rx_bufs(card, (struct iovec *)iovb->data,
NS_SKB(iovb)->iovcnt); NS_PRV_IOVCNT(iovb));
NS_SKB(iovb)->iovcnt = 0; NS_PRV_IOVCNT(iovb) = 0;
NS_SKB(iovb)->vcc = NULL;
spin_lock_irqsave(&card->int_lock, flags); spin_lock_irqsave(&card->int_lock, flags);
recycle_iov_buf(card, iovb); recycle_iov_buf(card, iovb);
spin_unlock_irqrestore(&card->int_lock, flags); spin_unlock_irqrestore(&card->int_lock, flags);
@ -1487,7 +1522,7 @@ static void ns_close(struct atm_vcc *vcc)
scq->next = scq->base; scq->next = scq->base;
else else
scq->next++; scq->next++;
data = (u32) virt_to_bus(scq->next); data = scq_virt_to_bus(scq, scq->next);
ns_write_sram(card, scq->scd, &data, 1); ns_write_sram(card, scq->scd, &data, 1);
} }
spin_unlock_irqrestore(&scq->lock, flags); spin_unlock_irqrestore(&scq->lock, flags);
@ -1506,7 +1541,7 @@ static void ns_close(struct atm_vcc *vcc)
} }
card->scd2vc[(vc->cbr_scd - NS_FRSCD) / NS_FRSCD_SIZE] = NULL; card->scd2vc[(vc->cbr_scd - NS_FRSCD) / NS_FRSCD_SIZE] = NULL;
free_scq(vc->scq, vcc); free_scq(card, vc->scq, vcc);
} }
/* remove all references to vcc before deleting it */ /* remove all references to vcc before deleting it */
@ -1539,13 +1574,13 @@ static void ns_close(struct atm_vcc *vcc)
cfg = readl(card->membase + CFG); cfg = readl(card->membase + CFG);
printk("STAT = 0x%08X CFG = 0x%08X \n", stat, cfg); printk("STAT = 0x%08X CFG = 0x%08X \n", stat, cfg);
printk printk
("TSQ: base = 0x%08X next = 0x%08X last = 0x%08X TSQT = 0x%08X \n", ("TSQ: base = 0x%p next = 0x%p last = 0x%p TSQT = 0x%08X \n",
(u32) card->tsq.base, (u32) card->tsq.next, card->tsq.base, card->tsq.next,
(u32) card->tsq.last, readl(card->membase + TSQT)); card->tsq.last, readl(card->membase + TSQT));
printk printk
("RSQ: base = 0x%08X next = 0x%08X last = 0x%08X RSQT = 0x%08X \n", ("RSQ: base = 0x%p next = 0x%p last = 0x%p RSQT = 0x%08X \n",
(u32) card->rsq.base, (u32) card->rsq.next, card->rsq.base, card->rsq.next,
(u32) card->rsq.last, readl(card->membase + RSQT)); card->rsq.last, readl(card->membase + RSQT));
printk("Empty free buffer queue interrupt %s \n", printk("Empty free buffer queue interrupt %s \n",
card->efbie ? "enabled" : "disabled"); card->efbie ? "enabled" : "disabled");
printk("SBCNT = %d count = %d LBCNT = %d count = %d \n", printk("SBCNT = %d count = %d LBCNT = %d count = %d \n",
@ -1651,11 +1686,14 @@ static int ns_send(struct atm_vcc *vcc, struct sk_buff *skb)
ATM_SKB(skb)->vcc = vcc; ATM_SKB(skb)->vcc = vcc;
NS_PRV_DMA(skb) = pci_map_single(card->pcidev, skb->data,
skb->len, PCI_DMA_TODEVICE);
if (vcc->qos.aal == ATM_AAL5) { if (vcc->qos.aal == ATM_AAL5) {
buflen = (skb->len + 47 + 8) / 48 * 48; /* Multiple of 48 */ buflen = (skb->len + 47 + 8) / 48 * 48; /* Multiple of 48 */
flags = NS_TBD_AAL5; flags = NS_TBD_AAL5;
scqe.word_2 = cpu_to_le32((u32) virt_to_bus(skb->data)); scqe.word_2 = cpu_to_le32(NS_PRV_DMA(skb));
scqe.word_3 = cpu_to_le32((u32) skb->len); scqe.word_3 = cpu_to_le32(skb->len);
scqe.word_4 = scqe.word_4 =
ns_tbd_mkword_4(0, (u32) vcc->vpi, (u32) vcc->vci, 0, ns_tbd_mkword_4(0, (u32) vcc->vpi, (u32) vcc->vci, 0,
ATM_SKB(skb)-> ATM_SKB(skb)->
@ -1665,8 +1703,7 @@ static int ns_send(struct atm_vcc *vcc, struct sk_buff *skb)
buflen = ATM_CELL_PAYLOAD; /* i.e., 48 bytes */ buflen = ATM_CELL_PAYLOAD; /* i.e., 48 bytes */
flags = NS_TBD_AAL0; flags = NS_TBD_AAL0;
scqe.word_2 = scqe.word_2 = cpu_to_le32(NS_PRV_DMA(skb) + NS_AAL0_HEADER);
cpu_to_le32((u32) virt_to_bus(skb->data) + NS_AAL0_HEADER);
scqe.word_3 = cpu_to_le32(0x00000000); scqe.word_3 = cpu_to_le32(0x00000000);
if (*skb->data & 0x02) /* Payload type 1 - end of pdu */ if (*skb->data & 0x02) /* Payload type 1 - end of pdu */
flags |= NS_TBD_EOPDU; flags |= NS_TBD_EOPDU;
@ -1733,12 +1770,12 @@ static int push_scqe(ns_dev * card, vc_map * vc, scq_info * scq, ns_scqe * tbd,
*scq->next = *tbd; *scq->next = *tbd;
index = (int)(scq->next - scq->base); index = (int)(scq->next - scq->base);
scq->skb[index] = skb; scq->skb[index] = skb;
XPRINTK("nicstar%d: sending skb at 0x%x (pos %d).\n", XPRINTK("nicstar%d: sending skb at 0x%p (pos %d).\n",
card->index, (u32) skb, index); card->index, skb, index);
XPRINTK("nicstar%d: TBD written:\n0x%x\n0x%x\n0x%x\n0x%x\n at 0x%x.\n", XPRINTK("nicstar%d: TBD written:\n0x%x\n0x%x\n0x%x\n0x%x\n at 0x%p.\n",
card->index, le32_to_cpu(tbd->word_1), le32_to_cpu(tbd->word_2), card->index, le32_to_cpu(tbd->word_1), le32_to_cpu(tbd->word_2),
le32_to_cpu(tbd->word_3), le32_to_cpu(tbd->word_4), le32_to_cpu(tbd->word_3), le32_to_cpu(tbd->word_4),
(u32) scq->next); scq->next);
if (scq->next == scq->last) if (scq->next == scq->last)
scq->next = scq->base; scq->next = scq->base;
else else
@ -1757,7 +1794,7 @@ static int push_scqe(ns_dev * card, vc_map * vc, scq_info * scq, ns_scqe * tbd,
while (scq->tail == scq->next) { while (scq->tail == scq->next) {
if (in_interrupt()) { if (in_interrupt()) {
data = (u32) virt_to_bus(scq->next); data = scq_virt_to_bus(scq, scq->next);
ns_write_sram(card, scq->scd, &data, 1); ns_write_sram(card, scq->scd, &data, 1);
spin_unlock_irqrestore(&scq->lock, flags); spin_unlock_irqrestore(&scq->lock, flags);
printk("nicstar%d: Error pushing TSR.\n", printk("nicstar%d: Error pushing TSR.\n",
@ -1789,10 +1826,10 @@ static int push_scqe(ns_dev * card, vc_map * vc, scq_info * scq, ns_scqe * tbd,
index = (int)scqi; index = (int)scqi;
scq->skb[index] = NULL; scq->skb[index] = NULL;
XPRINTK XPRINTK
("nicstar%d: TSR written:\n0x%x\n0x%x\n0x%x\n0x%x\n at 0x%x.\n", ("nicstar%d: TSR written:\n0x%x\n0x%x\n0x%x\n0x%x\n at 0x%p.\n",
card->index, le32_to_cpu(tsr.word_1), card->index, le32_to_cpu(tsr.word_1),
le32_to_cpu(tsr.word_2), le32_to_cpu(tsr.word_3), le32_to_cpu(tsr.word_2), le32_to_cpu(tsr.word_3),
le32_to_cpu(tsr.word_4), (u32) scq->next); le32_to_cpu(tsr.word_4), scq->next);
if (scq->next == scq->last) if (scq->next == scq->last)
scq->next = scq->base; scq->next = scq->base;
else else
@ -1803,7 +1840,7 @@ static int push_scqe(ns_dev * card, vc_map * vc, scq_info * scq, ns_scqe * tbd,
PRINTK("nicstar%d: Timeout pushing TSR.\n", PRINTK("nicstar%d: Timeout pushing TSR.\n",
card->index); card->index);
} }
data = (u32) virt_to_bus(scq->next); data = scq_virt_to_bus(scq, scq->next);
ns_write_sram(card, scq->scd, &data, 1); ns_write_sram(card, scq->scd, &data, 1);
spin_unlock_irqrestore(&scq->lock, flags); spin_unlock_irqrestore(&scq->lock, flags);
@ -1881,10 +1918,9 @@ static void process_tsq(ns_dev * card)
two_ahead = one_ahead + 1; two_ahead = one_ahead + 1;
} }
if (serviced_entries) { if (serviced_entries)
writel((((u32) previous) - ((u32) card->tsq.base)), writel(PTR_DIFF(previous, card->tsq.base),
card->membase + TSQH); card->membase + TSQH);
}
} }
static void drain_scq(ns_dev * card, scq_info * scq, int pos) static void drain_scq(ns_dev * card, scq_info * scq, int pos)
@ -1894,8 +1930,8 @@ static void drain_scq(ns_dev * card, scq_info * scq, int pos)
int i; int i;
unsigned long flags; unsigned long flags;
XPRINTK("nicstar%d: drain_scq() called, scq at 0x%x, pos %d.\n", XPRINTK("nicstar%d: drain_scq() called, scq at 0x%p, pos %d.\n",
card->index, (u32) scq, pos); card->index, scq, pos);
if (pos >= scq->num_entries) { if (pos >= scq->num_entries) {
printk("nicstar%d: Bad index on drain_scq().\n", card->index); printk("nicstar%d: Bad index on drain_scq().\n", card->index);
return; return;
@ -1907,9 +1943,13 @@ static void drain_scq(ns_dev * card, scq_info * scq, int pos)
i = 0; i = 0;
while (i != pos) { while (i != pos) {
skb = scq->skb[i]; skb = scq->skb[i];
XPRINTK("nicstar%d: freeing skb at 0x%x (index %d).\n", XPRINTK("nicstar%d: freeing skb at 0x%p (index %d).\n",
card->index, (u32) skb, i); card->index, skb, i);
if (skb != NULL) { if (skb != NULL) {
pci_unmap_single(card->pcidev,
NS_PRV_DMA(skb),
skb->len,
PCI_DMA_TODEVICE);
vcc = ATM_SKB(skb)->vcc; vcc = ATM_SKB(skb)->vcc;
if (vcc && vcc->pop != NULL) { if (vcc && vcc->pop != NULL) {
vcc->pop(vcc, skb); vcc->pop(vcc, skb);
@ -1940,8 +1980,7 @@ static void process_rsq(ns_dev * card)
else else
card->rsq.next++; card->rsq.next++;
} while (ns_rsqe_valid(card->rsq.next)); } while (ns_rsqe_valid(card->rsq.next));
writel((((u32) previous) - ((u32) card->rsq.base)), writel(PTR_DIFF(previous, card->rsq.base), card->membase + RSQH);
card->membase + RSQH);
} }
static void dequeue_rx(ns_dev * card, ns_rsqe * rsqe) static void dequeue_rx(ns_dev * card, ns_rsqe * rsqe)
@ -1955,12 +1994,30 @@ static void dequeue_rx(ns_dev * card, ns_rsqe * rsqe)
unsigned short aal5_len; unsigned short aal5_len;
int len; int len;
u32 stat; u32 stat;
u32 id;
stat = readl(card->membase + STAT); stat = readl(card->membase + STAT);
card->sbfqc = ns_stat_sfbqc_get(stat); card->sbfqc = ns_stat_sfbqc_get(stat);
card->lbfqc = ns_stat_lfbqc_get(stat); card->lbfqc = ns_stat_lfbqc_get(stat);
skb = (struct sk_buff *)le32_to_cpu(rsqe->buffer_handle); id = le32_to_cpu(rsqe->buffer_handle);
skb = idr_find(&card->idr, id);
if (!skb) {
RXPRINTK(KERN_ERR
"nicstar%d: idr_find() failed!\n", card->index);
return;
}
idr_remove(&card->idr, id);
pci_dma_sync_single_for_cpu(card->pcidev,
NS_PRV_DMA(skb),
(NS_PRV_BUFTYPE(skb) == BUF_SM
? NS_SMSKBSIZE : NS_LGSKBSIZE),
PCI_DMA_FROMDEVICE);
pci_unmap_single(card->pcidev,
NS_PRV_DMA(skb),
(NS_PRV_BUFTYPE(skb) == BUF_SM
? NS_SMSKBSIZE : NS_LGSKBSIZE),
PCI_DMA_FROMDEVICE);
vpi = ns_rsqe_vpi(rsqe); vpi = ns_rsqe_vpi(rsqe);
vci = ns_rsqe_vci(rsqe); vci = ns_rsqe_vci(rsqe);
if (vpi >= 1UL << card->vpibits || vci >= 1UL << card->vcibits) { if (vpi >= 1UL << card->vpibits || vci >= 1UL << card->vcibits) {
@ -2034,43 +2091,42 @@ static void dequeue_rx(ns_dev * card, ns_rsqe * rsqe)
recycle_rx_buf(card, skb); recycle_rx_buf(card, skb);
return; return;
} }
NS_SKB_CB(iovb)->buf_type = BUF_NONE; NS_PRV_BUFTYPE(iovb) = BUF_NONE;
} else if (--card->iovpool.count < card->iovnr.min) { } else if (--card->iovpool.count < card->iovnr.min) {
struct sk_buff *new_iovb; struct sk_buff *new_iovb;
if ((new_iovb = if ((new_iovb =
alloc_skb(NS_IOVBUFSIZE, GFP_ATOMIC)) != NULL) { alloc_skb(NS_IOVBUFSIZE, GFP_ATOMIC)) != NULL) {
NS_SKB_CB(iovb)->buf_type = BUF_NONE; NS_PRV_BUFTYPE(iovb) = BUF_NONE;
skb_queue_tail(&card->iovpool.queue, new_iovb); skb_queue_tail(&card->iovpool.queue, new_iovb);
card->iovpool.count++; card->iovpool.count++;
} }
} }
vc->rx_iov = iovb; vc->rx_iov = iovb;
NS_SKB(iovb)->iovcnt = 0; NS_PRV_IOVCNT(iovb) = 0;
iovb->len = 0; iovb->len = 0;
iovb->data = iovb->head; iovb->data = iovb->head;
skb_reset_tail_pointer(iovb); skb_reset_tail_pointer(iovb);
NS_SKB(iovb)->vcc = vcc;
/* IMPORTANT: a pointer to the sk_buff containing the small or large /* IMPORTANT: a pointer to the sk_buff containing the small or large
buffer is stored as iovec base, NOT a pointer to the buffer is stored as iovec base, NOT a pointer to the
small or large buffer itself. */ small or large buffer itself. */
} else if (NS_SKB(iovb)->iovcnt >= NS_MAX_IOVECS) { } else if (NS_PRV_IOVCNT(iovb) >= NS_MAX_IOVECS) {
printk("nicstar%d: received too big AAL5 SDU.\n", card->index); printk("nicstar%d: received too big AAL5 SDU.\n", card->index);
atomic_inc(&vcc->stats->rx_err); atomic_inc(&vcc->stats->rx_err);
recycle_iovec_rx_bufs(card, (struct iovec *)iovb->data, recycle_iovec_rx_bufs(card, (struct iovec *)iovb->data,
NS_MAX_IOVECS); NS_MAX_IOVECS);
NS_SKB(iovb)->iovcnt = 0; NS_PRV_IOVCNT(iovb) = 0;
iovb->len = 0; iovb->len = 0;
iovb->data = iovb->head; iovb->data = iovb->head;
skb_reset_tail_pointer(iovb); skb_reset_tail_pointer(iovb);
NS_SKB(iovb)->vcc = vcc;
} }
iov = &((struct iovec *)iovb->data)[NS_SKB(iovb)->iovcnt++]; iov = &((struct iovec *)iovb->data)[NS_PRV_IOVCNT(iovb)++];
iov->iov_base = (void *)skb; iov->iov_base = (void *)skb;
iov->iov_len = ns_rsqe_cellcount(rsqe) * 48; iov->iov_len = ns_rsqe_cellcount(rsqe) * 48;
iovb->len += iov->iov_len; iovb->len += iov->iov_len;
if (NS_SKB(iovb)->iovcnt == 1) { #ifdef EXTRA_DEBUG
if (NS_SKB_CB(skb)->buf_type != BUF_SM) { if (NS_PRV_IOVCNT(iovb) == 1) {
if (NS_PRV_BUFTYPE(skb) != BUF_SM) {
printk printk
("nicstar%d: Expected a small buffer, and this is not one.\n", ("nicstar%d: Expected a small buffer, and this is not one.\n",
card->index); card->index);
@ -2081,26 +2137,27 @@ static void dequeue_rx(ns_dev * card, ns_rsqe * rsqe)
recycle_iov_buf(card, iovb); recycle_iov_buf(card, iovb);
return; return;
} }
} else { /* NS_SKB(iovb)->iovcnt >= 2 */ } else { /* NS_PRV_IOVCNT(iovb) >= 2 */
if (NS_SKB_CB(skb)->buf_type != BUF_LG) { if (NS_PRV_BUFTYPE(skb) != BUF_LG) {
printk printk
("nicstar%d: Expected a large buffer, and this is not one.\n", ("nicstar%d: Expected a large buffer, and this is not one.\n",
card->index); card->index);
which_list(card, skb); which_list(card, skb);
atomic_inc(&vcc->stats->rx_err); atomic_inc(&vcc->stats->rx_err);
recycle_iovec_rx_bufs(card, (struct iovec *)iovb->data, recycle_iovec_rx_bufs(card, (struct iovec *)iovb->data,
NS_SKB(iovb)->iovcnt); NS_PRV_IOVCNT(iovb));
vc->rx_iov = NULL; vc->rx_iov = NULL;
recycle_iov_buf(card, iovb); recycle_iov_buf(card, iovb);
return; return;
} }
} }
#endif /* EXTRA_DEBUG */
if (ns_rsqe_eopdu(rsqe)) { if (ns_rsqe_eopdu(rsqe)) {
/* This works correctly regardless of the endianness of the host */ /* This works correctly regardless of the endianness of the host */
unsigned char *L1L2 = (unsigned char *)((u32) skb->data + unsigned char *L1L2 = (unsigned char *)
iov->iov_len - 6); (skb->data + iov->iov_len - 6);
aal5_len = L1L2[0] << 8 | L1L2[1]; aal5_len = L1L2[0] << 8 | L1L2[1];
len = (aal5_len == 0x0000) ? 0x10000 : aal5_len; len = (aal5_len == 0x0000) ? 0x10000 : aal5_len;
if (ns_rsqe_crcerr(rsqe) || if (ns_rsqe_crcerr(rsqe) ||
@ -2112,7 +2169,7 @@ static void dequeue_rx(ns_dev * card, ns_rsqe * rsqe)
printk(".\n"); printk(".\n");
atomic_inc(&vcc->stats->rx_err); atomic_inc(&vcc->stats->rx_err);
recycle_iovec_rx_bufs(card, (struct iovec *)iovb->data, recycle_iovec_rx_bufs(card, (struct iovec *)iovb->data,
NS_SKB(iovb)->iovcnt); NS_PRV_IOVCNT(iovb));
vc->rx_iov = NULL; vc->rx_iov = NULL;
recycle_iov_buf(card, iovb); recycle_iov_buf(card, iovb);
return; return;
@ -2120,7 +2177,7 @@ static void dequeue_rx(ns_dev * card, ns_rsqe * rsqe)
/* By this point we (hopefully) have a complete SDU without errors. */ /* By this point we (hopefully) have a complete SDU without errors. */
if (NS_SKB(iovb)->iovcnt == 1) { /* Just a small buffer */ if (NS_PRV_IOVCNT(iovb) == 1) { /* Just a small buffer */
/* skb points to a small buffer */ /* skb points to a small buffer */
if (!atm_charge(vcc, skb->truesize)) { if (!atm_charge(vcc, skb->truesize)) {
push_rxbufs(card, skb); push_rxbufs(card, skb);
@ -2136,7 +2193,7 @@ static void dequeue_rx(ns_dev * card, ns_rsqe * rsqe)
vcc->push(vcc, skb); vcc->push(vcc, skb);
atomic_inc(&vcc->stats->rx); atomic_inc(&vcc->stats->rx);
} }
} else if (NS_SKB(iovb)->iovcnt == 2) { /* One small plus one large buffer */ } else if (NS_PRV_IOVCNT(iovb) == 2) { /* One small plus one large buffer */
struct sk_buff *sb; struct sk_buff *sb;
sb = (struct sk_buff *)(iov - 1)->iov_base; sb = (struct sk_buff *)(iov - 1)->iov_base;
@ -2202,8 +2259,7 @@ static void dequeue_rx(ns_dev * card, ns_rsqe * rsqe)
recycle_iovec_rx_bufs(card, recycle_iovec_rx_bufs(card,
(struct iovec *) (struct iovec *)
iovb->data, iovb->data,
NS_SKB(iovb)-> NS_PRV_IOVCNT(iovb));
iovcnt);
vc->rx_iov = NULL; vc->rx_iov = NULL;
recycle_iov_buf(card, iovb); recycle_iov_buf(card, iovb);
return; return;
@ -2217,12 +2273,12 @@ static void dequeue_rx(ns_dev * card, ns_rsqe * rsqe)
card->hbpool.count++; card->hbpool.count++;
} }
} }
NS_SKB_CB(hb)->buf_type = BUF_NONE; NS_PRV_BUFTYPE(hb) = BUF_NONE;
} else if (--card->hbpool.count < card->hbnr.min) { } else if (--card->hbpool.count < card->hbnr.min) {
struct sk_buff *new_hb; struct sk_buff *new_hb;
if ((new_hb = if ((new_hb =
dev_alloc_skb(NS_HBUFSIZE)) != NULL) { dev_alloc_skb(NS_HBUFSIZE)) != NULL) {
NS_SKB_CB(new_hb)->buf_type = BUF_NONE; NS_PRV_BUFTYPE(new_hb) = BUF_NONE;
skb_queue_tail(&card->hbpool.queue, skb_queue_tail(&card->hbpool.queue,
new_hb); new_hb);
card->hbpool.count++; card->hbpool.count++;
@ -2231,7 +2287,7 @@ static void dequeue_rx(ns_dev * card, ns_rsqe * rsqe)
if ((new_hb = if ((new_hb =
dev_alloc_skb(NS_HBUFSIZE)) != dev_alloc_skb(NS_HBUFSIZE)) !=
NULL) { NULL) {
NS_SKB_CB(new_hb)->buf_type = NS_PRV_BUFTYPE(new_hb) =
BUF_NONE; BUF_NONE;
skb_queue_tail(&card->hbpool. skb_queue_tail(&card->hbpool.
queue, new_hb); queue, new_hb);
@ -2244,7 +2300,7 @@ static void dequeue_rx(ns_dev * card, ns_rsqe * rsqe)
if (!atm_charge(vcc, hb->truesize)) { if (!atm_charge(vcc, hb->truesize)) {
recycle_iovec_rx_bufs(card, iov, recycle_iovec_rx_bufs(card, iov,
NS_SKB(iovb)->iovcnt); NS_PRV_IOVCNT(iovb));
if (card->hbpool.count < card->hbnr.max) { if (card->hbpool.count < card->hbnr.max) {
skb_queue_tail(&card->hbpool.queue, hb); skb_queue_tail(&card->hbpool.queue, hb);
card->hbpool.count++; card->hbpool.count++;
@ -2263,7 +2319,7 @@ static void dequeue_rx(ns_dev * card, ns_rsqe * rsqe)
push_rxbufs(card, sb); push_rxbufs(card, sb);
/* Copy all large buffers to the huge buffer and free them */ /* Copy all large buffers to the huge buffer and free them */
for (j = 1; j < NS_SKB(iovb)->iovcnt; j++) { for (j = 1; j < NS_PRV_IOVCNT(iovb); j++) {
lb = (struct sk_buff *)iov->iov_base; lb = (struct sk_buff *)iov->iov_base;
tocopy = tocopy =
min_t(int, remaining, iov->iov_len); min_t(int, remaining, iov->iov_len);
@ -2313,7 +2369,7 @@ static void ns_sb_destructor(struct sk_buff *sb)
sb = __dev_alloc_skb(NS_SMSKBSIZE, GFP_KERNEL); sb = __dev_alloc_skb(NS_SMSKBSIZE, GFP_KERNEL);
if (sb == NULL) if (sb == NULL)
break; break;
NS_SKB_CB(sb)->buf_type = BUF_SM; NS_PRV_BUFTYPE(sb) = BUF_SM;
skb_queue_tail(&card->sbpool.queue, sb); skb_queue_tail(&card->sbpool.queue, sb);
skb_reserve(sb, NS_AAL0_HEADER); skb_reserve(sb, NS_AAL0_HEADER);
push_rxbufs(card, sb); push_rxbufs(card, sb);
@ -2334,7 +2390,7 @@ static void ns_lb_destructor(struct sk_buff *lb)
lb = __dev_alloc_skb(NS_LGSKBSIZE, GFP_KERNEL); lb = __dev_alloc_skb(NS_LGSKBSIZE, GFP_KERNEL);
if (lb == NULL) if (lb == NULL)
break; break;
NS_SKB_CB(lb)->buf_type = BUF_LG; NS_PRV_BUFTYPE(lb) = BUF_LG;
skb_queue_tail(&card->lbpool.queue, lb); skb_queue_tail(&card->lbpool.queue, lb);
skb_reserve(lb, NS_SMBUFSIZE); skb_reserve(lb, NS_SMBUFSIZE);
push_rxbufs(card, lb); push_rxbufs(card, lb);
@ -2351,7 +2407,7 @@ static void ns_hb_destructor(struct sk_buff *hb)
hb = __dev_alloc_skb(NS_HBUFSIZE, GFP_KERNEL); hb = __dev_alloc_skb(NS_HBUFSIZE, GFP_KERNEL);
if (hb == NULL) if (hb == NULL)
break; break;
NS_SKB_CB(hb)->buf_type = BUF_NONE; NS_PRV_BUFTYPE(hb) = BUF_NONE;
skb_queue_tail(&card->hbpool.queue, hb); skb_queue_tail(&card->hbpool.queue, hb);
card->hbpool.count++; card->hbpool.count++;
} }
@ -2361,9 +2417,7 @@ static void ns_hb_destructor(struct sk_buff *hb)
static void recycle_rx_buf(ns_dev * card, struct sk_buff *skb) static void recycle_rx_buf(ns_dev * card, struct sk_buff *skb)
{ {
struct ns_skb_cb *cb = NS_SKB_CB(skb); if (unlikely(NS_PRV_BUFTYPE(skb) == BUF_NONE)) {
if (unlikely(cb->buf_type == BUF_NONE)) {
printk("nicstar%d: What kind of rx buffer is this?\n", printk("nicstar%d: What kind of rx buffer is this?\n",
card->index); card->index);
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
@ -2395,7 +2449,7 @@ static void dequeue_sm_buf(ns_dev * card, struct sk_buff *sb)
if (card->sbfqc < card->sbnr.init) { if (card->sbfqc < card->sbnr.init) {
struct sk_buff *new_sb; struct sk_buff *new_sb;
if ((new_sb = dev_alloc_skb(NS_SMSKBSIZE)) != NULL) { if ((new_sb = dev_alloc_skb(NS_SMSKBSIZE)) != NULL) {
NS_SKB_CB(new_sb)->buf_type = BUF_SM; NS_PRV_BUFTYPE(new_sb) = BUF_SM;
skb_queue_tail(&card->sbpool.queue, new_sb); skb_queue_tail(&card->sbpool.queue, new_sb);
skb_reserve(new_sb, NS_AAL0_HEADER); skb_reserve(new_sb, NS_AAL0_HEADER);
push_rxbufs(card, new_sb); push_rxbufs(card, new_sb);
@ -2406,7 +2460,7 @@ static void dequeue_sm_buf(ns_dev * card, struct sk_buff *sb)
{ {
struct sk_buff *new_sb; struct sk_buff *new_sb;
if ((new_sb = dev_alloc_skb(NS_SMSKBSIZE)) != NULL) { if ((new_sb = dev_alloc_skb(NS_SMSKBSIZE)) != NULL) {
NS_SKB_CB(new_sb)->buf_type = BUF_SM; NS_PRV_BUFTYPE(new_sb) = BUF_SM;
skb_queue_tail(&card->sbpool.queue, new_sb); skb_queue_tail(&card->sbpool.queue, new_sb);
skb_reserve(new_sb, NS_AAL0_HEADER); skb_reserve(new_sb, NS_AAL0_HEADER);
push_rxbufs(card, new_sb); push_rxbufs(card, new_sb);
@ -2423,7 +2477,7 @@ static void dequeue_lg_buf(ns_dev * card, struct sk_buff *lb)
if (card->lbfqc < card->lbnr.init) { if (card->lbfqc < card->lbnr.init) {
struct sk_buff *new_lb; struct sk_buff *new_lb;
if ((new_lb = dev_alloc_skb(NS_LGSKBSIZE)) != NULL) { if ((new_lb = dev_alloc_skb(NS_LGSKBSIZE)) != NULL) {
NS_SKB_CB(new_lb)->buf_type = BUF_LG; NS_PRV_BUFTYPE(new_lb) = BUF_LG;
skb_queue_tail(&card->lbpool.queue, new_lb); skb_queue_tail(&card->lbpool.queue, new_lb);
skb_reserve(new_lb, NS_SMBUFSIZE); skb_reserve(new_lb, NS_SMBUFSIZE);
push_rxbufs(card, new_lb); push_rxbufs(card, new_lb);
@ -2434,7 +2488,7 @@ static void dequeue_lg_buf(ns_dev * card, struct sk_buff *lb)
{ {
struct sk_buff *new_lb; struct sk_buff *new_lb;
if ((new_lb = dev_alloc_skb(NS_LGSKBSIZE)) != NULL) { if ((new_lb = dev_alloc_skb(NS_LGSKBSIZE)) != NULL) {
NS_SKB_CB(new_lb)->buf_type = BUF_LG; NS_PRV_BUFTYPE(new_lb) = BUF_LG;
skb_queue_tail(&card->lbpool.queue, new_lb); skb_queue_tail(&card->lbpool.queue, new_lb);
skb_reserve(new_lb, NS_SMBUFSIZE); skb_reserve(new_lb, NS_SMBUFSIZE);
push_rxbufs(card, new_lb); push_rxbufs(card, new_lb);
@ -2625,7 +2679,7 @@ static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void __user * arg)
sb = __dev_alloc_skb(NS_SMSKBSIZE, GFP_KERNEL); sb = __dev_alloc_skb(NS_SMSKBSIZE, GFP_KERNEL);
if (sb == NULL) if (sb == NULL)
return -ENOMEM; return -ENOMEM;
NS_SKB_CB(sb)->buf_type = BUF_SM; NS_PRV_BUFTYPE(sb) = BUF_SM;
skb_queue_tail(&card->sbpool.queue, sb); skb_queue_tail(&card->sbpool.queue, sb);
skb_reserve(sb, NS_AAL0_HEADER); skb_reserve(sb, NS_AAL0_HEADER);
push_rxbufs(card, sb); push_rxbufs(card, sb);
@ -2639,7 +2693,7 @@ static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void __user * arg)
lb = __dev_alloc_skb(NS_LGSKBSIZE, GFP_KERNEL); lb = __dev_alloc_skb(NS_LGSKBSIZE, GFP_KERNEL);
if (lb == NULL) if (lb == NULL)
return -ENOMEM; return -ENOMEM;
NS_SKB_CB(lb)->buf_type = BUF_LG; NS_PRV_BUFTYPE(lb) = BUF_LG;
skb_queue_tail(&card->lbpool.queue, lb); skb_queue_tail(&card->lbpool.queue, lb);
skb_reserve(lb, NS_SMBUFSIZE); skb_reserve(lb, NS_SMBUFSIZE);
push_rxbufs(card, lb); push_rxbufs(card, lb);
@ -2668,7 +2722,7 @@ static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void __user * arg)
hb = __dev_alloc_skb(NS_HBUFSIZE, GFP_KERNEL); hb = __dev_alloc_skb(NS_HBUFSIZE, GFP_KERNEL);
if (hb == NULL) if (hb == NULL)
return -ENOMEM; return -ENOMEM;
NS_SKB_CB(hb)->buf_type = BUF_NONE; NS_PRV_BUFTYPE(hb) = BUF_NONE;
spin_lock_irqsave(&card->int_lock, flags); spin_lock_irqsave(&card->int_lock, flags);
skb_queue_tail(&card->hbpool.queue, hb); skb_queue_tail(&card->hbpool.queue, hb);
card->hbpool.count++; card->hbpool.count++;
@ -2698,7 +2752,7 @@ static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void __user * arg)
iovb = alloc_skb(NS_IOVBUFSIZE, GFP_KERNEL); iovb = alloc_skb(NS_IOVBUFSIZE, GFP_KERNEL);
if (iovb == NULL) if (iovb == NULL)
return -ENOMEM; return -ENOMEM;
NS_SKB_CB(iovb)->buf_type = BUF_NONE; NS_PRV_BUFTYPE(iovb) = BUF_NONE;
spin_lock_irqsave(&card->int_lock, flags); spin_lock_irqsave(&card->int_lock, flags);
skb_queue_tail(&card->iovpool.queue, iovb); skb_queue_tail(&card->iovpool.queue, iovb);
card->iovpool.count++; card->iovpool.count++;
@ -2723,10 +2777,12 @@ static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void __user * arg)
} }
} }
#ifdef EXTRA_DEBUG
static void which_list(ns_dev * card, struct sk_buff *skb) static void which_list(ns_dev * card, struct sk_buff *skb)
{ {
printk("skb buf_type: 0x%08x\n", NS_SKB_CB(skb)->buf_type); printk("skb buf_type: 0x%08x\n", NS_PRV_BUFTYPE(skb));
} }
#endif /* EXTRA_DEBUG */
static void ns_poll(unsigned long arg) static void ns_poll(unsigned long arg)
{ {
@ -2803,7 +2859,7 @@ static void ns_phy_put(struct atm_dev *dev, unsigned char value,
card = dev->dev_data; card = dev->dev_data;
spin_lock_irqsave(&card->res_lock, flags); spin_lock_irqsave(&card->res_lock, flags);
while (CMD_BUSY(card)) ; while (CMD_BUSY(card)) ;
writel((unsigned long)value, card->membase + DR0); writel((u32) value, card->membase + DR0);
writel(NS_CMD_WRITE_UTILITY | 0x00000200 | (addr & 0x000000FF), writel(NS_CMD_WRITE_UTILITY | 0x00000200 | (addr & 0x000000FF),
card->membase + CMD); card->membase + CMD);
spin_unlock_irqrestore(&card->res_lock, flags); spin_unlock_irqrestore(&card->res_lock, flags);
@ -2813,7 +2869,7 @@ static unsigned char ns_phy_get(struct atm_dev *dev, unsigned long addr)
{ {
ns_dev *card; ns_dev *card;
unsigned long flags; unsigned long flags;
unsigned long data; u32 data;
card = dev->dev_data; card = dev->dev_data;
spin_lock_irqsave(&card->res_lock, flags); spin_lock_irqsave(&card->res_lock, flags);

View File

@ -16,6 +16,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/idr.h>
#include <linux/uio.h> #include <linux/uio.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/atmdev.h> #include <linux/atmdev.h>
@ -636,14 +637,22 @@ enum ns_regs {
/* Device driver structures */ /* Device driver structures */
struct ns_skb_cb { struct ns_skb_prv {
u32 buf_type; /* BUF_SM/BUF_LG/BUF_NONE */ u32 buf_type; /* BUF_SM/BUF_LG/BUF_NONE */
u32 dma;
int iovcnt;
}; };
#define NS_SKB_CB(skb) ((struct ns_skb_cb *)((skb)->cb)) #define NS_PRV_BUFTYPE(skb) \
(((struct ns_skb_prv *)(ATM_SKB(skb)+1))->buf_type)
#define NS_PRV_DMA(skb) \
(((struct ns_skb_prv *)(ATM_SKB(skb)+1))->dma)
#define NS_PRV_IOVCNT(skb) \
(((struct ns_skb_prv *)(ATM_SKB(skb)+1))->iovcnt)
typedef struct tsq_info { typedef struct tsq_info {
void *org; void *org;
dma_addr_t dma;
ns_tsi *base; ns_tsi *base;
ns_tsi *next; ns_tsi *next;
ns_tsi *last; ns_tsi *last;
@ -651,6 +660,7 @@ typedef struct tsq_info {
typedef struct scq_info { typedef struct scq_info {
void *org; void *org;
dma_addr_t dma;
ns_scqe *base; ns_scqe *base;
ns_scqe *last; ns_scqe *last;
ns_scqe *next; ns_scqe *next;
@ -668,6 +678,7 @@ typedef struct scq_info {
typedef struct rsq_info { typedef struct rsq_info {
void *org; void *org;
dma_addr_t dma;
ns_rsqe *base; ns_rsqe *base;
ns_rsqe *next; ns_rsqe *next;
ns_rsqe *last; ns_rsqe *last;
@ -693,13 +704,6 @@ typedef struct vc_map {
int tbd_count; int tbd_count;
} vc_map; } vc_map;
struct ns_skb_data {
struct atm_vcc *vcc;
int iovcnt;
};
#define NS_SKB(skb) (((struct ns_skb_data *) (skb)->cb))
typedef struct ns_dev { typedef struct ns_dev {
int index; /* Card ID to the device driver */ int index; /* Card ID to the device driver */
int sram_size; /* In k x 32bit words. 32 or 128 */ int sram_size; /* In k x 32bit words. 32 or 128 */
@ -709,6 +713,7 @@ typedef struct ns_dev {
int vpibits; int vpibits;
int vcibits; int vcibits;
struct pci_dev *pcidev; struct pci_dev *pcidev;
struct idr idr;
struct atm_dev *atmdev; struct atm_dev *atmdev;
tsq_info tsq; tsq_info tsq;
rsq_info rsq; rsq_info rsq;
@ -729,11 +734,12 @@ typedef struct ns_dev {
buf_nr iovnr; buf_nr iovnr;
int sbfqc; int sbfqc;
int lbfqc; int lbfqc;
u32 sm_handle; struct sk_buff *sm_handle;
u32 sm_addr; u32 sm_addr;
u32 lg_handle; struct sk_buff *lg_handle;
u32 lg_addr; u32 lg_addr;
struct sk_buff *rcbuf; /* Current raw cell buffer */ struct sk_buff *rcbuf; /* Current raw cell buffer */
struct ns_rcqe *rawcell;
u32 rawch; /* Raw cell queue head */ u32 rawch; /* Raw cell queue head */
unsigned intcnt; /* Interrupt counter */ unsigned intcnt; /* Interrupt counter */
spinlock_t int_lock; /* Interrupt lock */ spinlock_t int_lock; /* Interrupt lock */