Commit 6d23b118 authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

[PATCH] drag ATM into the 21st century , part 1

parent 6321043b
...@@ -40,7 +40,7 @@ ifeq ($(CONFIG_ATM_FORE200E_PCA),y) ...@@ -40,7 +40,7 @@ ifeq ($(CONFIG_ATM_FORE200E_PCA),y)
fore_200e-objs += fore200e_pca_fw.o fore_200e-objs += fore200e_pca_fw.o
# guess the target endianess to choose the right PCA-200E firmware image # guess the target endianess to choose the right PCA-200E firmware image
ifeq ($(CONFIG_ATM_FORE200E_PCA_DEFAULT_FW),y) ifeq ($(CONFIG_ATM_FORE200E_PCA_DEFAULT_FW),y)
CONFIG_ATM_FORE200E_PCA_FW = $(shell if test -n "`$(CC) -E -dM $(src)/../../include/asm/byteorder.h | grep ' __LITTLE_ENDIAN '`"; then echo pca200e.bin; else echo pca200e_ecd.bin2; fi) CONFIG_ATM_FORE200E_PCA_FW = $(shell if test -n "`$(CC) -E -dM $(src)/../../include/asm/byteorder.h | grep ' __LITTLE_ENDIAN '`"; then echo $(obj)/pca200e.bin; else echo $(obj)/pca200e_ecd.bin2; fi)
endif endif
endif endif
......
...@@ -118,7 +118,7 @@ static void ia_enque_head_rtn_q (IARTN_Q *que, IARTN_Q * data) ...@@ -118,7 +118,7 @@ static void ia_enque_head_rtn_q (IARTN_Q *que, IARTN_Q * data)
} }
static int ia_enque_rtn_q (IARTN_Q *que, struct desc_tbl_t data) { static int ia_enque_rtn_q (IARTN_Q *que, struct desc_tbl_t data) {
IARTN_Q *entry = kmalloc(sizeof(*entry), GFP_KERNEL); IARTN_Q *entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
if (!entry) return -1; if (!entry) return -1;
entry->data = data; entry->data = data;
entry->next = NULL; entry->next = NULL;
...@@ -202,8 +202,7 @@ static u16 get_desc (IADEV *dev, struct ia_vcc *iavcc) { ...@@ -202,8 +202,7 @@ static u16 get_desc (IADEV *dev, struct ia_vcc *iavcc) {
ltimeout = dev->desc_tbl[i].iavcc->ltimeout; ltimeout = dev->desc_tbl[i].iavcc->ltimeout;
delta = jiffies - dev->desc_tbl[i].timestamp; delta = jiffies - dev->desc_tbl[i].timestamp;
if (delta >= ltimeout) { if (delta >= ltimeout) {
IF_ABR(printk("RECOVER run!! desc_tbl %d = %d delta = %ld, IF_ABR(printk("RECOVER run!! desc_tbl %d = %d delta = %ld, time = %ld\n", i,dev->desc_tbl[i].timestamp, delta, jiffies);)
time = %ld\n", i,dev->desc_tbl[i].timestamp, delta, jiffies);)
if (dev->ffL.tcq_rd == dev->ffL.tcq_st) if (dev->ffL.tcq_rd == dev->ffL.tcq_st)
dev->ffL.tcq_rd = dev->ffL.tcq_ed; dev->ffL.tcq_rd = dev->ffL.tcq_ed;
else else
...@@ -624,6 +623,7 @@ static int ia_que_tx (IADEV *iadev) { ...@@ -624,6 +623,7 @@ static int ia_que_tx (IADEV *iadev) {
struct ia_vcc *iavcc; struct ia_vcc *iavcc;
static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb); static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb);
num_desc = ia_avail_descs(iadev); num_desc = ia_avail_descs(iadev);
while (num_desc && (skb = skb_dequeue(&iadev->tx_backlog))) { while (num_desc && (skb = skb_dequeue(&iadev->tx_backlog))) {
if (!(vcc = ATM_SKB(skb)->vcc)) { if (!(vcc = ATM_SKB(skb)->vcc)) {
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
...@@ -643,6 +643,7 @@ static int ia_que_tx (IADEV *iadev) { ...@@ -643,6 +643,7 @@ static int ia_que_tx (IADEV *iadev) {
} }
return 0; return 0;
} }
void ia_tx_poll (IADEV *iadev) { void ia_tx_poll (IADEV *iadev) {
struct atm_vcc *vcc = NULL; struct atm_vcc *vcc = NULL;
struct sk_buff *skb = NULL, *skb1 = NULL; struct sk_buff *skb = NULL, *skb1 = NULL;
...@@ -1086,6 +1087,7 @@ static int rx_pkt(struct atm_dev *dev) ...@@ -1086,6 +1087,7 @@ static int rx_pkt(struct atm_dev *dev)
int len; int len;
struct sk_buff *skb; struct sk_buff *skb;
u_int buf_addr, dma_addr; u_int buf_addr, dma_addr;
iadev = INPH_IA_DEV(dev); iadev = INPH_IA_DEV(dev);
if (iadev->rfL.pcq_rd == (readw(iadev->reass_reg+PCQ_WR_PTR)&0xffff)) if (iadev->rfL.pcq_rd == (readw(iadev->reass_reg+PCQ_WR_PTR)&0xffff))
{ {
...@@ -1171,7 +1173,8 @@ static int rx_pkt(struct atm_dev *dev) ...@@ -1171,7 +1173,8 @@ static int rx_pkt(struct atm_dev *dev)
/* Build the DLE structure */ /* Build the DLE structure */
wr_ptr = iadev->rx_dle_q.write; wr_ptr = iadev->rx_dle_q.write;
wr_ptr->sys_pkt_addr = virt_to_bus(skb->data); wr_ptr->sys_pkt_addr = pci_map_single(iadev->pci, skb->data,
len, PCI_DMA_FROMDEVICE);
wr_ptr->local_pkt_addr = buf_addr; wr_ptr->local_pkt_addr = buf_addr;
wr_ptr->bytes = len; /* We don't know this do we ?? */ wr_ptr->bytes = len; /* We don't know this do we ?? */
wr_ptr->mode = DMA_INT_ENABLE; wr_ptr->mode = DMA_INT_ENABLE;
...@@ -1290,6 +1293,9 @@ static void rx_dle_intr(struct atm_dev *dev) ...@@ -1290,6 +1293,9 @@ static void rx_dle_intr(struct atm_dev *dev)
struct cpcs_trailer *trailer; struct cpcs_trailer *trailer;
u_short length; u_short length;
struct ia_vcc *ia_vcc; struct ia_vcc *ia_vcc;
pci_unmap_single(iadev->pci, iadev->rx_dle_q.write->sys_pkt_addr,
len, PCI_DMA_FROMDEVICE);
/* no VCC related housekeeping done as yet. lets see */ /* no VCC related housekeeping done as yet. lets see */
vcc = ATM_SKB(skb)->vcc; vcc = ATM_SKB(skb)->vcc;
if (!vcc) { if (!vcc) {
...@@ -1401,7 +1407,7 @@ static int rx_init(struct atm_dev *dev) ...@@ -1401,7 +1407,7 @@ static int rx_init(struct atm_dev *dev)
IADEV *iadev; IADEV *iadev;
struct rx_buf_desc *buf_desc_ptr; struct rx_buf_desc *buf_desc_ptr;
unsigned long rx_pkt_start = 0; unsigned long rx_pkt_start = 0;
u32 *odle_addr, *dle_addr; void *dle_addr;
struct abr_vc_table *abr_vc_table; struct abr_vc_table *abr_vc_table;
u16 *vc_table; u16 *vc_table;
u16 *reass_table; u16 *reass_table;
...@@ -1412,25 +1418,14 @@ static int rx_init(struct atm_dev *dev) ...@@ -1412,25 +1418,14 @@ static int rx_init(struct atm_dev *dev)
iadev = INPH_IA_DEV(dev); iadev = INPH_IA_DEV(dev);
// spin_lock_init(&iadev->rx_lock); // spin_lock_init(&iadev->rx_lock);
/* I need to initialize the DLEs somewhere. Lets see what I
need to do for this, hmmm...
- allocate memory for 256 DLEs. make sure that it starts
on a 4k byte address boundary. Program the start address
in Receive List address register. ..... to do for TX also
To make sure that it is a 4k byte boundary - allocate 8k and find
4k byte boundary within.
( (addr + (4k-1)) & ~(4k-1) )
*/
/* allocate 8k bytes */ /* Allocate 4k bytes - more aligned than needed (4k boundary) */
odle_addr = kmalloc(2*sizeof(struct dle)*DLE_ENTRIES, GFP_KERNEL); dle_addr = pci_alloc_consistent(iadev->pci, DLE_TOTAL_SIZE,
if (!odle_addr) &iadev->rx_dle_dma);
{ if (!dle_addr) {
printk(KERN_ERR DEV_LABEL "can't allocate DLEs\n"); printk(KERN_ERR DEV_LABEL "can't allocate DLEs\n");
return -ENOMEM; goto err_out;
} }
/* find 4k byte boundary within the 8k allocated */
dle_addr = (u32*)( ((u32)odle_addr+(4096-1)) & ~(4096-1) );
iadev->rx_dle_q.start = (struct dle*)dle_addr; iadev->rx_dle_q.start = (struct dle*)dle_addr;
iadev->rx_dle_q.read = iadev->rx_dle_q.start; iadev->rx_dle_q.read = iadev->rx_dle_q.start;
iadev->rx_dle_q.write = iadev->rx_dle_q.start; iadev->rx_dle_q.write = iadev->rx_dle_q.start;
...@@ -1439,7 +1434,8 @@ static int rx_init(struct atm_dev *dev) ...@@ -1439,7 +1434,8 @@ static int rx_init(struct atm_dev *dev)
DLE that can be used. */ DLE that can be used. */
/* write the upper 20 bits of the start address to rx list address register */ /* write the upper 20 bits of the start address to rx list address register */
writel(virt_to_bus(dle_addr) & 0xfffff000, iadev->dma+IPHASE5575_RX_LIST_ADDR); writel(iadev->rx_dle_dma & 0xfffff000,
iadev->dma + IPHASE5575_RX_LIST_ADDR);
IF_INIT(printk("Tx Dle list addr: 0x%08x value: 0x%0x\n", IF_INIT(printk("Tx Dle list addr: 0x%08x value: 0x%0x\n",
(u32)(iadev->dma+IPHASE5575_TX_LIST_ADDR), (u32)(iadev->dma+IPHASE5575_TX_LIST_ADDR),
*(u32*)(iadev->dma+IPHASE5575_TX_LIST_ADDR)); *(u32*)(iadev->dma+IPHASE5575_TX_LIST_ADDR));
...@@ -1613,8 +1609,7 @@ static int rx_init(struct atm_dev *dev) ...@@ -1613,8 +1609,7 @@ static int rx_init(struct atm_dev *dev)
{ {
printk(KERN_ERR DEV_LABEL "itf %d couldn't get free page\n", printk(KERN_ERR DEV_LABEL "itf %d couldn't get free page\n",
dev->number); dev->number);
kfree(odle_addr); goto err_free_dle;
return -ENOMEM;
} }
memset(iadev->rx_open, 0, 4*iadev->num_vc); memset(iadev->rx_open, 0, 4*iadev->num_vc);
iadev->rxing = 1; iadev->rxing = 1;
...@@ -1622,6 +1617,12 @@ static int rx_init(struct atm_dev *dev) ...@@ -1622,6 +1617,12 @@ static int rx_init(struct atm_dev *dev)
/* Mode Register */ /* Mode Register */
writew(R_ONLINE, iadev->reass_reg+MODE_REG); writew(R_ONLINE, iadev->reass_reg+MODE_REG);
return 0; return 0;
err_free_dle:
pci_free_consistent(iadev->pci, DLE_TOTAL_SIZE, iadev->rx_dle_q.start,
iadev->rx_dle_dma);
err_out:
return -ENOMEM;
} }
...@@ -1686,6 +1687,12 @@ static void tx_dle_intr(struct atm_dev *dev) ...@@ -1686,6 +1687,12 @@ static void tx_dle_intr(struct atm_dev *dev)
/* free the DMAed skb */ /* free the DMAed skb */
skb = skb_dequeue(&iadev->tx_dma_q); skb = skb_dequeue(&iadev->tx_dma_q);
if (!skb) break; if (!skb) break;
/* Revenge of the 2 dle (skb + trailer) used in ia_pkt_tx() */
if (!((dle - iadev->tx_dle_q.start)%(2*sizeof(struct dle)))) {
pci_unmap_single(iadev->pci, dle->sys_pkt_addr, skb->len,
PCI_DMA_TODEVICE);
}
vcc = ATM_SKB(skb)->vcc; vcc = ATM_SKB(skb)->vcc;
if (!vcc) { if (!vcc) {
printk("tx_dle_intr: vcc is null\n"); printk("tx_dle_intr: vcc is null\n");
...@@ -1878,7 +1885,7 @@ static int tx_init(struct atm_dev *dev) ...@@ -1878,7 +1885,7 @@ static int tx_init(struct atm_dev *dev)
IADEV *iadev; IADEV *iadev;
struct tx_buf_desc *buf_desc_ptr; struct tx_buf_desc *buf_desc_ptr;
unsigned int tx_pkt_start; unsigned int tx_pkt_start;
u32 *dle_addr; void *dle_addr;
int i; int i;
u_short tcq_st_adr; u_short tcq_st_adr;
u_short *tcq_start; u_short *tcq_start;
...@@ -1894,24 +1901,22 @@ static int tx_init(struct atm_dev *dev) ...@@ -1894,24 +1901,22 @@ static int tx_init(struct atm_dev *dev)
IF_INIT(printk("Tx MASK REG: 0x%0x\n", IF_INIT(printk("Tx MASK REG: 0x%0x\n",
readw(iadev->seg_reg+SEG_MASK_REG));) readw(iadev->seg_reg+SEG_MASK_REG));)
/*---------- Initializing Transmit DLEs ----------*/
/* allocating 8k memory for transmit DLEs */ /* Allocate 4k (boundary aligned) bytes */
dle_addr = kmalloc(2*sizeof(struct dle)*DLE_ENTRIES, GFP_KERNEL); dle_addr = pci_alloc_consistent(iadev->pci, DLE_TOTAL_SIZE,
if (!dle_addr) &iadev->tx_dle_dma);
{ if (!dle_addr) {
printk(KERN_ERR DEV_LABEL "can't allocate TX DLEs\n"); printk(KERN_ERR DEV_LABEL "can't allocate DLEs\n");
return -ENOMEM; goto err_out;
} }
/* find 4k byte boundary within the 8k allocated */
dle_addr = (u32*)(((u32)dle_addr+(4096-1)) & ~(4096-1));
iadev->tx_dle_q.start = (struct dle*)dle_addr; iadev->tx_dle_q.start = (struct dle*)dle_addr;
iadev->tx_dle_q.read = iadev->tx_dle_q.start; iadev->tx_dle_q.read = iadev->tx_dle_q.start;
iadev->tx_dle_q.write = iadev->tx_dle_q.start; iadev->tx_dle_q.write = iadev->tx_dle_q.start;
iadev->tx_dle_q.end = (struct dle*)((u32)dle_addr+sizeof(struct dle)*DLE_ENTRIES); iadev->tx_dle_q.end = (struct dle*)((u32)dle_addr+sizeof(struct dle)*DLE_ENTRIES);
/* write the upper 20 bits of the start address to tx list address register */ /* write the upper 20 bits of the start address to tx list address register */
writel(virt_to_bus(dle_addr) & 0xfffff000, iadev->dma+IPHASE5575_TX_LIST_ADDR); writel(iadev->tx_dle_dma & 0xfffff000,
iadev->dma + IPHASE5575_TX_LIST_ADDR);
writew(0xffff, iadev->seg_reg+SEG_MASK_REG); writew(0xffff, iadev->seg_reg+SEG_MASK_REG);
writew(0, iadev->seg_reg+MODE_REG_0); writew(0, iadev->seg_reg+MODE_REG_0);
writew(RESET_SEG, iadev->seg_reg+SEG_COMMAND_REG); writew(RESET_SEG, iadev->seg_reg+SEG_COMMAND_REG);
...@@ -1955,26 +1960,29 @@ static int tx_init(struct atm_dev *dev) ...@@ -1955,26 +1960,29 @@ static int tx_init(struct atm_dev *dev)
buf_desc_ptr++; buf_desc_ptr++;
tx_pkt_start += iadev->tx_buf_sz; tx_pkt_start += iadev->tx_buf_sz;
} }
iadev->tx_buf = kmalloc(iadev->num_tx_desc*sizeof(caddr_t), GFP_KERNEL); iadev->tx_buf = kmalloc(iadev->num_tx_desc*sizeof(struct cpcs_trailer_desc), GFP_KERNEL);
if (!iadev->tx_buf) { if (!iadev->tx_buf) {
printk(KERN_ERR DEV_LABEL " couldn't get mem\n"); printk(KERN_ERR DEV_LABEL " couldn't get mem\n");
return -EAGAIN; goto err_free_dle;
} }
for (i= 0; i< iadev->num_tx_desc; i++) for (i= 0; i< iadev->num_tx_desc; i++)
{ {
struct cpcs_trailer *cpcs;
iadev->tx_buf[i] = kmalloc(sizeof(struct cpcs_trailer), cpcs = kmalloc(sizeof(*cpcs), GFP_KERNEL|GFP_DMA);
GFP_KERNEL|GFP_DMA); if(!cpcs) {
if(!iadev->tx_buf[i]) {
printk(KERN_ERR DEV_LABEL " couldn't get freepage\n"); printk(KERN_ERR DEV_LABEL " couldn't get freepage\n");
return -EAGAIN; goto err_free_tx_bufs;
} }
iadev->tx_buf[i].cpcs = cpcs;
iadev->tx_buf[i].dma_addr = pci_map_single(iadev->pci,
cpcs, sizeof(*cpcs), PCI_DMA_TODEVICE);
} }
iadev->desc_tbl = kmalloc(iadev->num_tx_desc * iadev->desc_tbl = kmalloc(iadev->num_tx_desc *
sizeof(struct desc_tbl_t), GFP_KERNEL); sizeof(struct desc_tbl_t), GFP_KERNEL);
if (!iadev->desc_tbl) { if (!iadev->desc_tbl) {
printk(KERN_ERR DEV_LABEL " couldn't get mem\n"); printk(KERN_ERR DEV_LABEL " couldn't get mem\n");
return -EAGAIN; goto err_free_all_tx_bufs;
} }
/* Communication Queues base address */ /* Communication Queues base address */
...@@ -2103,7 +2111,7 @@ static int tx_init(struct atm_dev *dev) ...@@ -2103,7 +2111,7 @@ static int tx_init(struct atm_dev *dev)
iadev->testTable = kmalloc(sizeof(long)*iadev->num_vc, GFP_KERNEL); iadev->testTable = kmalloc(sizeof(long)*iadev->num_vc, GFP_KERNEL);
if (!iadev->testTable) { if (!iadev->testTable) {
printk("Get freepage failed\n"); printk("Get freepage failed\n");
return -EAGAIN; goto err_free_desc_tbl;
} }
for(i=0; i<iadev->num_vc; i++) for(i=0; i<iadev->num_vc; i++)
{ {
...@@ -2112,7 +2120,7 @@ static int tx_init(struct atm_dev *dev) ...@@ -2112,7 +2120,7 @@ static int tx_init(struct atm_dev *dev)
iadev->testTable[i] = kmalloc(sizeof(struct testTable_t), iadev->testTable[i] = kmalloc(sizeof(struct testTable_t),
GFP_KERNEL); GFP_KERNEL);
if (!iadev->testTable[i]) if (!iadev->testTable[i])
return -ENOMEM; goto err_free_test_tables;
iadev->testTable[i]->lastTime = 0; iadev->testTable[i]->lastTime = 0;
iadev->testTable[i]->fract = 0; iadev->testTable[i]->fract = 0;
iadev->testTable[i]->vc_status = VC_UBR; iadev->testTable[i]->vc_status = VC_UBR;
...@@ -2163,7 +2171,30 @@ static int tx_init(struct atm_dev *dev) ...@@ -2163,7 +2171,30 @@ static int tx_init(struct atm_dev *dev)
iadev->tx_pkt_cnt = 0; iadev->tx_pkt_cnt = 0;
iadev->rate_limit = iadev->LineRate / 3; iadev->rate_limit = iadev->LineRate / 3;
return 0; return 0;
err_free_test_tables:
while (--i >= 0)
kfree(iadev->testTable[i]);
kfree(iadev->testTable);
err_free_desc_tbl:
kfree(iadev->desc_tbl);
err_free_all_tx_bufs:
i = iadev->num_tx_desc;
err_free_tx_bufs:
while (--i >= 0) {
struct cpcs_trailer_desc *desc = iadev->tx_buf + i;
pci_unmap_single(iadev->pci, desc->dma_addr,
sizeof(*desc->cpcs), PCI_DMA_TODEVICE);
kfree(desc->cpcs);
}
kfree(iadev->tx_buf);
err_free_dle:
pci_free_consistent(iadev->pci, DLE_TOTAL_SIZE, iadev->tx_dle_q.start,
iadev->tx_dle_dma);
err_out:
return -ENOMEM;
} }
static void ia_int(int irq, void *dev_id, struct pt_regs *regs) static void ia_int(int irq, void *dev_id, struct pt_regs *regs)
...@@ -2421,10 +2452,37 @@ static unsigned char ia_phy_get(struct atm_dev *dev, unsigned long addr) ...@@ -2421,10 +2452,37 @@ static unsigned char ia_phy_get(struct atm_dev *dev, unsigned long addr)
return readl(INPH_IA_DEV(dev)->phy+addr); return readl(INPH_IA_DEV(dev)->phy+addr);
} }
static void ia_free_tx(IADEV *iadev)
{
int i;
kfree(iadev->desc_tbl);
for (i = 0; i < iadev->num_vc; i++)
kfree(iadev->testTable[i]);
kfree(iadev->testTable);
for (i = 0; i < iadev->num_tx_desc; i++) {
struct cpcs_trailer_desc *desc = iadev->tx_buf + i;
pci_unmap_single(iadev->pci, desc->dma_addr,
sizeof(*desc->cpcs), PCI_DMA_TODEVICE);
kfree(desc->cpcs);
}
kfree(iadev->tx_buf);
pci_free_consistent(iadev->pci, DLE_TOTAL_SIZE, iadev->tx_dle_q.start,
iadev->tx_dle_dma);
}
static void ia_free_rx(IADEV *iadev)
{
kfree(iadev->rx_open);
pci_free_consistent(iadev->pci, DLE_TOTAL_SIZE, iadev->rx_dle_q.start,
iadev->rx_dle_dma);
}
static int __init ia_start(struct atm_dev *dev) static int __init ia_start(struct atm_dev *dev)
{ {
IADEV *iadev; IADEV *iadev;
int error = 1; int error;
unsigned char phy; unsigned char phy;
u32 ctrl_reg; u32 ctrl_reg;
IF_EVENT(printk(">ia_start\n");) IF_EVENT(printk(">ia_start\n");)
...@@ -2432,7 +2490,8 @@ static int __init ia_start(struct atm_dev *dev) ...@@ -2432,7 +2490,8 @@ static int __init ia_start(struct atm_dev *dev)
if (request_irq(iadev->irq, &ia_int, SA_SHIRQ, DEV_LABEL, dev)) { if (request_irq(iadev->irq, &ia_int, SA_SHIRQ, DEV_LABEL, dev)) {
printk(KERN_ERR DEV_LABEL "(itf %d): IRQ%d is already in use\n", printk(KERN_ERR DEV_LABEL "(itf %d): IRQ%d is already in use\n",
dev->number, iadev->irq); dev->number, iadev->irq);
return -EAGAIN; error = -EAGAIN;
goto err_out;
} }
/* @@@ should release IRQ on error */ /* @@@ should release IRQ on error */
/* enabling memory + master */ /* enabling memory + master */
...@@ -2442,8 +2501,8 @@ static int __init ia_start(struct atm_dev *dev) ...@@ -2442,8 +2501,8 @@ static int __init ia_start(struct atm_dev *dev)
{ {
printk(KERN_ERR DEV_LABEL "(itf %d): can't enable memory+" printk(KERN_ERR DEV_LABEL "(itf %d): can't enable memory+"
"master (0x%x)\n",dev->number, error); "master (0x%x)\n",dev->number, error);
free_irq(iadev->irq, dev); error = -EIO;
return -EIO; goto err_free_irq;
} }
udelay(10); udelay(10);
...@@ -2477,15 +2536,11 @@ static int __init ia_start(struct atm_dev *dev) ...@@ -2477,15 +2536,11 @@ static int __init ia_start(struct atm_dev *dev)
ia_hw_type(iadev); ia_hw_type(iadev);
error = tx_init(dev); error = tx_init(dev);
if (error) { if (error)
free_irq(iadev->irq, dev); goto err_free_irq;
return error;
}
error = rx_init(dev); error = rx_init(dev);
if (error) { if (error)
free_irq(iadev->irq, dev); goto err_free_tx;
return error;
}
ctrl_reg = readl(iadev->reg+IPHASE5575_BUS_CONTROL_REG); ctrl_reg = readl(iadev->reg+IPHASE5575_BUS_CONTROL_REG);
writel(ctrl_reg | CTRL_FE_RST, iadev->reg+IPHASE5575_BUS_CONTROL_REG); writel(ctrl_reg | CTRL_FE_RST, iadev->reg+IPHASE5575_BUS_CONTROL_REG);
...@@ -2498,35 +2553,38 @@ static int __init ia_start(struct atm_dev *dev) ...@@ -2498,35 +2553,38 @@ static int __init ia_start(struct atm_dev *dev)
else else
printk("IA: utopia,rev.%0x\n",phy);) printk("IA: utopia,rev.%0x\n",phy);)
if (iadev->phy_type & FE_25MBIT_PHY) { if (iadev->phy_type & FE_25MBIT_PHY)
ia_mb25_init(iadev); ia_mb25_init(iadev);
return 0; else if (iadev->phy_type & (FE_DS3_PHY | FE_E3_PHY))
}
if (iadev->phy_type & (FE_DS3_PHY | FE_E3_PHY)) {
ia_suni_pm7345_init(iadev); ia_suni_pm7345_init(iadev);
return 0; else {
} error = suni_init(dev);
if (error)
error = suni_init(dev); goto err_free_rx;
if (error) { /*
free_irq(iadev->irq, dev); * Enable interrupt on loss of signal
return error; * SUNI_RSOP_CIE - 0x10
} * SUNI_RSOP_CIE_LOSE - 0x04
*/
/* Enable interrupt on loss of signal SUNI_RSOP_CIE 0x10 ia_phy_put(dev, ia_phy_get(dev, 0x10) | 0x04, 0x10);
SUNI_RSOP_CIE_LOSE - 0x04 #ifndef MODULE
*/ error = dev->phy->start(dev);
ia_phy_put(dev, ia_phy_get(dev,0x10) | 0x04, 0x10); if (error)
#if 0 goto err_free_rx;
error = dev->phy->start(dev);
if (error) {
free_irq(iadev->irq, dev);
return error;
}
#endif #endif
/* Get iadev->carrier_detect status */ /* Get iadev->carrier_detect status */
IaFrontEndIntr(iadev); IaFrontEndIntr(iadev);
return 0; }
return 0;
err_free_rx:
ia_free_rx(iadev);
err_free_tx:
ia_free_tx(iadev);
err_free_irq:
free_irq(iadev->irq, dev);
err_out:
return error;
} }
static void ia_close(struct atm_vcc *vcc) static void ia_close(struct atm_vcc *vcc)
...@@ -2835,10 +2893,10 @@ static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb) { ...@@ -2835,10 +2893,10 @@ static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb) {
struct tx_buf_desc *buf_desc_ptr; struct tx_buf_desc *buf_desc_ptr;
int desc; int desc;
int comp_code; int comp_code;
unsigned int addr;
int total_len, pad, last; int total_len, pad, last;
struct cpcs_trailer *trailer; struct cpcs_trailer *trailer;
struct ia_vcc *iavcc; struct ia_vcc *iavcc;
iadev = INPH_IA_DEV(vcc->dev); iadev = INPH_IA_DEV(vcc->dev);
iavcc = INPH_IA_VCC(vcc); iavcc = INPH_IA_VCC(vcc);
if (!iavcc->txing) { if (!iavcc->txing) {
...@@ -2923,13 +2981,9 @@ static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb) { ...@@ -2923,13 +2981,9 @@ static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb) {
IF_TX(printk("ia packet len:%d padding:%d\n", total_len, pad);) IF_TX(printk("ia packet len:%d padding:%d\n", total_len, pad);)
/* Put the packet in a tx buffer */ /* Put the packet in a tx buffer */
if (!iadev->tx_buf[desc-1]) trailer = iadev->tx_buf[desc-1].cpcs;
printk("couldn't get free page\n");
IF_TX(printk("Sent: skb = 0x%x skb->data: 0x%x len: %d, desc: %d\n", IF_TX(printk("Sent: skb = 0x%x skb->data: 0x%x len: %d, desc: %d\n",
(u32)skb, (u32)skb->data, skb->len, desc);) (u32)skb, (u32)skb->data, skb->len, desc);)
addr = virt_to_bus(skb->data);
trailer = (struct cpcs_trailer*)iadev->tx_buf[desc-1];
trailer->control = 0; trailer->control = 0;
/*big endian*/ /*big endian*/
trailer->length = ((skb->len & 0xff) << 8) | ((skb->len & 0xff00) >> 8); trailer->length = ((skb->len & 0xff) << 8) | ((skb->len & 0xff00) >> 8);
...@@ -2945,6 +2999,7 @@ static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb) { ...@@ -2945,6 +2999,7 @@ static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb) {
buf_desc_ptr = (struct tx_buf_desc *)(iadev->seg_ram+TX_DESC_BASE); buf_desc_ptr = (struct tx_buf_desc *)(iadev->seg_ram+TX_DESC_BASE);
buf_desc_ptr += desc; /* points to the corresponding entry */ buf_desc_ptr += desc; /* points to the corresponding entry */
buf_desc_ptr->desc_mode = AAL5 | EOM_EN | APP_CRC32 | CMPL_INT; buf_desc_ptr->desc_mode = AAL5 | EOM_EN | APP_CRC32 | CMPL_INT;
/* Huh ? p.115 of users guide describes this as a read-only register */
writew(TRANSMIT_DONE, iadev->seg_reg+SEG_INTR_STATUS_REG); writew(TRANSMIT_DONE, iadev->seg_reg+SEG_INTR_STATUS_REG);
buf_desc_ptr->vc_index = vcc->vci; buf_desc_ptr->vc_index = vcc->vci;
buf_desc_ptr->bytes = total_len; buf_desc_ptr->bytes = total_len;
...@@ -2955,7 +3010,8 @@ static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb) { ...@@ -2955,7 +3010,8 @@ static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb) {
/* Build the DLE structure */ /* Build the DLE structure */
wr_ptr = iadev->tx_dle_q.write; wr_ptr = iadev->tx_dle_q.write;
memset((caddr_t)wr_ptr, 0, sizeof(*wr_ptr)); memset((caddr_t)wr_ptr, 0, sizeof(*wr_ptr));
wr_ptr->sys_pkt_addr = addr; wr_ptr->sys_pkt_addr = pci_map_single(iadev->pci, skb->data,
skb->len, PCI_DMA_TODEVICE);
wr_ptr->local_pkt_addr = (buf_desc_ptr->buf_start_hi << 16) | wr_ptr->local_pkt_addr = (buf_desc_ptr->buf_start_hi << 16) |
buf_desc_ptr->buf_start_lo; buf_desc_ptr->buf_start_lo;
/* wr_ptr->bytes = swap(total_len); didn't seem to affect ?? */ /* wr_ptr->bytes = swap(total_len); didn't seem to affect ?? */
...@@ -2973,7 +3029,7 @@ static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb) { ...@@ -2973,7 +3029,7 @@ static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb) {
wr_ptr = iadev->tx_dle_q.start; wr_ptr = iadev->tx_dle_q.start;
/* Build trailer dle */ /* Build trailer dle */
wr_ptr->sys_pkt_addr = virt_to_bus(iadev->tx_buf[desc-1]); wr_ptr->sys_pkt_addr = iadev->tx_buf[desc-1].dma_addr;
wr_ptr->local_pkt_addr = ((buf_desc_ptr->buf_start_hi << 16) | wr_ptr->local_pkt_addr = ((buf_desc_ptr->buf_start_hi << 16) |
buf_desc_ptr->buf_start_lo) + total_len - sizeof(struct cpcs_trailer); buf_desc_ptr->buf_start_lo) + total_len - sizeof(struct cpcs_trailer);
...@@ -3124,128 +3180,130 @@ static const struct atmdev_ops ops = { ...@@ -3124,128 +3180,130 @@ static const struct atmdev_ops ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
static int __devinit ia_init_one(struct pci_dev *pdev,
static int __init ia_detect(void) const struct pci_device_id *ent)
{ {
struct atm_dev *dev; struct atm_dev *dev;
IADEV *iadev; IADEV *iadev;
unsigned long flags; unsigned long flags;
int index = 0; int ret;
struct pci_dev *prev_dev;
if (!pci_present()) {
printk(KERN_ERR DEV_LABEL " driver but no PCI BIOS ?\n");
return 0;
}
iadev = kmalloc(sizeof(*iadev), GFP_KERNEL); iadev = kmalloc(sizeof(*iadev), GFP_KERNEL);
if (!iadev) return -ENOMEM; if (!iadev) {
memset((char*)iadev, 0, sizeof(*iadev)); ret = -ENOMEM;
prev_dev = NULL; goto err_out;
while((iadev->pci = pci_find_device(PCI_VENDOR_ID_IPHASE, }
PCI_DEVICE_ID_IPHASE_5575, prev_dev))) { memset(iadev, 0, sizeof(*iadev));
IF_INIT(printk("ia detected at bus:%d dev: %d function:%d\n", iadev->pci = pdev;
iadev->pci->bus->number, PCI_SLOT(iadev->pci->devfn),
PCI_FUNC(iadev->pci->devfn));) IF_INIT(printk("ia detected at bus:%d dev: %d function:%d\n",
if (pci_enable_device(iadev->pci)) break; pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));)
dev = atm_dev_register(DEV_LABEL, &ops, -1, NULL); if (pci_enable_device(pdev)) {
if (!dev) break; ret = -ENODEV;
IF_INIT(printk(DEV_LABEL "registered at (itf :%d)\n", goto err_out_free_iadev;
dev->number);) }
INPH_IA_DEV(dev) = iadev; dev = atm_dev_register(DEV_LABEL, &ops, -1, NULL);
// TODO: multi_board using ia_boards logic in cleanup_module if (!dev) {
ia_dev[index] = iadev; ret = -ENOMEM;
_ia_dev[index] = dev; goto err_out_disable_dev;
IF_INIT(printk("dev_id = 0x%x iadev->LineRate = %d \n", }
(u32)dev, iadev->LineRate);) INPH_IA_DEV(dev) = iadev;
iadev_count++; IF_INIT(printk(DEV_LABEL "registered at (itf :%d)\n", dev->number);)
spin_lock_init(&iadev->misc_lock); IF_INIT(printk("dev_id = 0x%x iadev->LineRate = %d \n", (u32)dev,
spin_lock_irqsave(&iadev->misc_lock, flags); iadev->LineRate);)
if (ia_init(dev) || ia_start(dev)) {
atm_dev_deregister(dev); ia_dev[iadev_count] = iadev;
IF_INIT(printk("IA register failed!\n");) _ia_dev[iadev_count] = dev;
ia_dev[index] = NULL; iadev_count++;
_ia_dev[index] = NULL; spin_lock_init(&iadev->misc_lock);
iadev_count--; /* First fixes first. I don't want to think about this now. */
spin_unlock_irqrestore(&iadev->misc_lock, flags); spin_lock_irqsave(&iadev->misc_lock, flags);
return -EINVAL; if (ia_init(dev) || ia_start(dev)) {
} IF_INIT(printk("IA register failed!\n");)
spin_unlock_irqrestore(&iadev->misc_lock, flags); iadev_count--;
IF_EVENT(printk("iadev_count = %d\n", iadev_count);) ia_dev[iadev_count] = NULL;
prev_dev = iadev->pci; _ia_dev[iadev_count] = NULL;
iadev->next_board = ia_boards; spin_unlock_irqrestore(&iadev->misc_lock, flags);
ia_boards = dev; ret = -EINVAL;
iadev = kmalloc(sizeof(*iadev), GFP_KERNEL); goto err_out_deregister_dev;
if (!iadev) break; }
memset((char*)iadev, 0, sizeof(*iadev)); spin_unlock_irqrestore(&iadev->misc_lock, flags);
index++; IF_EVENT(printk("iadev_count = %d\n", iadev_count);)
dev = NULL;
} iadev->next_board = ia_boards;
return index; ia_boards = dev;
}
pci_set_drvdata(pdev, dev);
return 0;
err_out_deregister_dev:
atm_dev_deregister(dev);
err_out_disable_dev:
pci_disable_device(pdev);
err_out_free_iadev:
kfree(iadev);
err_out:
return ret;
}
static void __devexit ia_remove_one(struct pci_dev *pdev)
{
struct atm_dev *dev = pci_get_drvdata(pdev);
IADEV *iadev = INPH_IA_DEV(dev);
ia_phy_put(dev, ia_phy_get(dev,0x10) & ~(0x4), 0x10);
udelay(1);
/* De-register device */
free_irq(iadev->irq, dev);
iadev_count--;
ia_dev[iadev_count] = NULL;
_ia_dev[iadev_count] = NULL;
atm_dev_deregister(dev);
IF_EVENT(printk("iav deregistered at (itf:%d)\n", dev->number);)
iounmap((void *) iadev->base);
pci_disable_device(pdev);
ia_free_rx(iadev);
ia_free_tx(iadev);
kfree(iadev);
}
static struct pci_device_id ia_pci_tbl[] __devinitdata = {
{ PCI_VENDOR_ID_IPHASE, 0x0008, PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_IPHASE, 0x0009, PCI_ANY_ID, PCI_ANY_ID, },
{ 0,}
};
MODULE_DEVICE_TABLE(pci, ia_pci_tbl);
static struct pci_driver ia_driver = {
.name = DEV_LABEL,
.id_table = ia_pci_tbl,
.probe = ia_init_one,
.remove = ia_remove_one,
};
static int __init ia_module_init(void) static int __init ia_module_init(void)
{ {
IF_EVENT(printk(">ia init_module\n");) int ret;
if (!ia_detect()) {
ret = pci_module_init(&ia_driver);
if (ret >= 0) {
ia_timer.expires = jiffies + 3*HZ;
add_timer(&ia_timer);
} else
printk(KERN_ERR DEV_LABEL ": no adapter found\n"); printk(KERN_ERR DEV_LABEL ": no adapter found\n");
return -ENXIO; return ret;
} }
ia_timer.expires = jiffies + 3*HZ;
add_timer(&ia_timer);
return 0;
}
static void __exit ia_module_exit(void) static void __exit ia_module_exit(void)
{ {
struct atm_dev *dev; pci_unregister_driver(&ia_driver);
IADEV *iadev;
unsigned short command;
int i, j= 0;
IF_EVENT(printk(">ia cleanup_module\n");)
if (MOD_IN_USE)
printk("ia: module in use\n");
del_timer(&ia_timer); del_timer(&ia_timer);
while(ia_dev[j])
{
dev = ia_boards;
iadev = INPH_IA_DEV(dev);
ia_boards = iadev->next_board;
/* disable interrupt of lost signal */
ia_phy_put(dev, ia_phy_get(dev,0x10) & ~(0x4), 0x10);
udelay(1);
/* De-register device */
atm_dev_deregister(dev);
IF_EVENT(printk("iav deregistered at (itf:%d)\n", dev->number);)
for (i= 0; i< iadev->num_tx_desc; i++)
kfree(iadev->tx_buf[i]);
kfree(iadev->tx_buf);
/* Disable memory mapping and busmastering */
if (pci_read_config_word(iadev->pci,
PCI_COMMAND, &command) != 0)
{
printk("ia: can't read PCI_COMMAND.\n");
}
command &= ~(PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
if (pci_write_config_word(iadev->pci,
PCI_COMMAND, command) != 0)
{
printk("ia: can't write PCI_COMMAND.\n");
}
free_irq(iadev->irq, dev);
iounmap((void *) iadev->base);
kfree(iadev);
j++;
}
/* and voila whatever we tried seems to work. I don't know if it will
fix suni errors though. Really doubt that. */
for (i = 0; i<8; i++) {
ia_dev[i] = NULL;
_ia_dev[i] = NULL;
}
} }
module_init(ia_module_init); module_init(ia_module_init);
......
...@@ -200,7 +200,13 @@ struct cpcs_trailer ...@@ -200,7 +200,13 @@ struct cpcs_trailer
u_short length; u_short length;
u_int crc32; u_int crc32;
}; };
struct cpcs_trailer_desc
{
struct cpcs_trailer *cpcs;
dma_addr_t dma_addr;
};
struct ia_vcc struct ia_vcc
{ {
int rxing; int rxing;
...@@ -272,6 +278,7 @@ struct ext_vc ...@@ -272,6 +278,7 @@ struct ext_vc
#define DLE_ENTRIES 256 #define DLE_ENTRIES 256
#define DMA_INT_ENABLE 0x0002 /* use for both Tx and Rx */ #define DMA_INT_ENABLE 0x0002 /* use for both Tx and Rx */
#define TX_DLE_PSI 0x0001 #define TX_DLE_PSI 0x0001
#define DLE_TOTAL_SIZE (sizeof(struct dle)*DLE_ENTRIES)
/* Descriptor List Entries (DLE) */ /* Descriptor List Entries (DLE) */
struct dle struct dle
...@@ -1017,7 +1024,7 @@ typedef struct iadev_t { ...@@ -1017,7 +1024,7 @@ typedef struct iadev_t {
struct wait_queue *close_wait; struct wait_queue *close_wait;
struct wait_queue *timeout_wait; struct wait_queue *timeout_wait;
#endif #endif
caddr_t *tx_buf; struct cpcs_trailer_desc *tx_buf;
u16 num_tx_desc, tx_buf_sz, rate_limit; u16 num_tx_desc, tx_buf_sz, rate_limit;
u32 tx_cell_cnt, tx_pkt_cnt; u32 tx_cell_cnt, tx_pkt_cnt;
u32 MAIN_VC_TABLE_ADDR, EXT_VC_TABLE_ADDR, ABR_SCHED_TABLE_ADDR; u32 MAIN_VC_TABLE_ADDR, EXT_VC_TABLE_ADDR, ABR_SCHED_TABLE_ADDR;
...@@ -1063,7 +1070,9 @@ typedef struct iadev_t { ...@@ -1063,7 +1070,9 @@ typedef struct iadev_t {
struct desc_tbl_t *desc_tbl; struct desc_tbl_t *desc_tbl;
u_short host_tcq_wr; u_short host_tcq_wr;
struct testTable_t **testTable; struct testTable_t **testTable;
} IADEV; dma_addr_t tx_dle_dma;
dma_addr_t rx_dle_dma;
} IADEV;
#define INPH_IA_DEV(d) ((IADEV *) (d)->dev_data) #define INPH_IA_DEV(d) ((IADEV *) (d)->dev_data)
......
...@@ -2108,8 +2108,7 @@ static inline int __init lanai_pci_start(struct lanai_dev *lanai) ...@@ -2108,8 +2108,7 @@ static inline int __init lanai_pci_start(struct lanai_dev *lanai)
} }
result = pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &w); result = pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &w);
if (result != PCIBIOS_SUCCESSFUL) { if (result != PCIBIOS_SUCCESSFUL) {
printk(KERN_ERR DEV_LABEL "(itf %d): can't read "" printk(KERN_ERR DEV_LABEL "(itf %d): can't read PCI_SUBSYSTEM_ID: %d\n", lanai->number, result);
PCI_SUBSYSTEM_ID: %d\n", lanai->number, result);
return -EINVAL; return -EINVAL;
} }
if ((result = check_board_id_and_rev("PCI", w, NULL)) != 0) if ((result = check_board_id_and_rev("PCI", w, NULL)) != 0)
......
...@@ -1260,13 +1260,13 @@ static void zatm_int(int irq,void *dev_id,struct pt_regs *regs) ...@@ -1260,13 +1260,13 @@ static void zatm_int(int irq,void *dev_id,struct pt_regs *regs)
/* don't handle RD */ /* don't handle RD */
if (reason & uPD98401_INT_SPE) if (reason & uPD98401_INT_SPE)
printk(KERN_ALERT DEV_LABEL "(itf %d): system parity " printk(KERN_ALERT DEV_LABEL "(itf %d): system parity "
"error at 0x%08x\n",dev->number,zin(ADDR)); "error at 0x%08lx\n",dev->number,zin(ADDR));
if (reason & uPD98401_INT_CPE) if (reason & uPD98401_INT_CPE)
printk(KERN_ALERT DEV_LABEL "(itf %d): control memory " printk(KERN_ALERT DEV_LABEL "(itf %d): control memory "
"parity error at 0x%08x\n",dev->number,zin(ADDR)); "parity error at 0x%08lx\n",dev->number,zin(ADDR));
if (reason & uPD98401_INT_SBE) { if (reason & uPD98401_INT_SBE) {
printk(KERN_ALERT DEV_LABEL "(itf %d): system bus " printk(KERN_ALERT DEV_LABEL "(itf %d): system bus "
"error at 0x%08x\n",dev->number,zin(ADDR)); "error at 0x%08lx\n",dev->number,zin(ADDR));
event_dump(); event_dump();
} }
/* don't handle IND */ /* don't handle IND */
...@@ -1448,7 +1448,7 @@ static int __init zatm_init(struct atm_dev *dev) ...@@ -1448,7 +1448,7 @@ static int __init zatm_init(struct atm_dev *dev)
} }
while (t0 > t1 || t1 > t2); /* loop if wrapping ... */ while (t0 > t1 || t1 > t2); /* loop if wrapping ... */
zatm_dev->khz = t2-2*t1+t0; zatm_dev->khz = t2-2*t1+t0;
printk(KERN_NOTICE DEV_LABEL "(itf %d): uPD98401 %d.%d at %d.%03d " printk(KERN_NOTICE DEV_LABEL "(itf %d): uPD98401 %ld.%ld at %d.%03d "
"MHz\n",dev->number, "MHz\n",dev->number,
(zin(VER) & uPD98401_MAJOR) >> uPD98401_MAJOR_SHIFT, (zin(VER) & uPD98401_MAJOR) >> uPD98401_MAJOR_SHIFT,
zin(VER) & uPD98401_MINOR,zatm_dev->khz/1000,zatm_dev->khz % 1000); zin(VER) & uPD98401_MINOR,zatm_dev->khz/1000,zatm_dev->khz % 1000);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment