patch-2.3.99-pre3 linux/drivers/atm/fore200e.c
Next file: linux/drivers/atm/fore200e.h
Previous file: linux/drivers/atm/eni.h
Back to the patch index
Back to the overall index
- Lines: 502
- Date:
Tue Mar 21 23:38:26 2000
- Orig file:
v2.3.99-pre2/linux/drivers/atm/fore200e.c
- Orig date:
Sat Feb 26 22:31:43 2000
diff -u --recursive --new-file v2.3.99-pre2/linux/drivers/atm/fore200e.c linux/drivers/atm/fore200e.c
@@ -1,5 +1,5 @@
/*
- $Id: fore200e.c,v 1.1 2000/02/21 16:04:31 davem Exp $
+ $Id: fore200e.c,v 1.2 2000/03/21 21:19:24 davem Exp $
A FORE Systems 200E-series driver for ATM on Linux.
Christophe Lizzi (lizzi@cnam.fr), October 1999-February 2000.
@@ -35,6 +35,7 @@
#include <linux/atmdev.h>
#include <linux/sonet.h>
#include <linux/atm_suni.h>
+#include <linux/bitops.h>
#include <asm/io.h>
#include <asm/string.h>
#include <asm/segment.h>
@@ -43,6 +44,7 @@
#include <asm/dma.h>
#include <asm/byteorder.h>
#include <asm/uaccess.h>
+#include <asm/atomic.h>
#ifdef CONFIG_ATM_FORE200E_PCA
#include <linux/pci.h>
@@ -67,7 +69,7 @@
#define FORE200E_52BYTE_AAL0_SDU
#endif
-#define FORE200E_VERSION "0.2a"
+#define FORE200E_VERSION "0.2b"
#define FORE200E "fore200e: "
@@ -187,10 +189,10 @@
/* allocate and align a chunk of memory intended to hold the data behing exchanged
- between the driver and the adapter (using streaming DVMA on SBUS hosts) */
+ between the driver and the adapter (using streaming DVMA) */
static int
-fore200e_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk, int size, int alignment)
+fore200e_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk, int size, int alignment, int direction)
{
unsigned long offset = 0;
@@ -199,6 +201,7 @@
chunk->alloc_size = size + alignment;
chunk->align_size = size;
+ chunk->direction = direction;
chunk->alloc_addr = fore200e_kmalloc(chunk->alloc_size, GFP_KERNEL | GFP_DMA);
if (chunk->alloc_addr == NULL)
@@ -209,7 +212,7 @@
chunk->align_addr = chunk->alloc_addr + offset;
- chunk->dma_addr = fore200e->bus->dma_map(fore200e, chunk->align_addr, chunk->align_size);
+ chunk->dma_addr = fore200e->bus->dma_map(fore200e, chunk->align_addr, chunk->align_size, direction);
return 0;
}
@@ -220,7 +223,7 @@
static void
fore200e_chunk_free(struct fore200e* fore200e, struct chunk* chunk)
{
- fore200e->bus->dma_unmap(fore200e, chunk->dma_addr, chunk->dma_size);
+ fore200e->bus->dma_unmap(fore200e, chunk->dma_addr, chunk->dma_size, chunk->direction);
fore200e_kfree(chunk->alloc_addr);
}
@@ -463,34 +466,32 @@
static u32
-fore200e_pca_dma_map(struct fore200e* fore200e, void* virt_addr, int size)
+fore200e_pca_dma_map(struct fore200e* fore200e, void* virt_addr, int size, int direction)
{
- u32 dma_addr = pci_map_single((struct pci_dev*)fore200e->bus_dev, virt_addr, size, PCI_DMA_BIDIRECTIONAL);
+ u32 dma_addr = pci_map_single((struct pci_dev*)fore200e->bus_dev, virt_addr, size, direction);
- DPRINTK(3, "PCI DVMA mapping: virt_addr = 0x%p, size = %d --> dma_addr = 0x%08x\n",
- virt_addr, size, dma_addr);
+ DPRINTK(3, "PCI DVMA mapping: virt_addr = 0x%p, size = %d, direction = %d, --> dma_addr = 0x%08x\n",
+ virt_addr, size, direction, dma_addr);
return dma_addr;
}
static void
-fore200e_pca_dma_unmap(struct fore200e* fore200e, u32 dma_addr, int size)
+fore200e_pca_dma_unmap(struct fore200e* fore200e, u32 dma_addr, int size, int direction)
{
- DPRINTK(3, "PCI DVMA unmapping: dma_addr = 0x%08x, size = %d\n", dma_addr, size);
+ DPRINTK(3, "PCI DVMA unmapping: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction);
- pci_unmap_single((struct pci_dev*)fore200e->bus_dev, dma_addr, size,
- PCI_DMA_BIDIRECTIONAL);
+ pci_unmap_single((struct pci_dev*)fore200e->bus_dev, dma_addr, size, direction);
}
static void
-fore200e_pca_dma_sync(struct fore200e* fore200e, u32 dma_addr, int size)
+fore200e_pca_dma_sync(struct fore200e* fore200e, u32 dma_addr, int size, int direction)
{
- DPRINTK(3, "PCI DVMA sync: dma_addr = 0x%08x, size = %d\n", dma_addr, size);
+ DPRINTK(3, "PCI DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction);
- pci_dma_sync_single((struct pci_dev*)fore200e->bus_dev, dma_addr, size,
- PCI_DMA_BIDIRECTIONAL);
+ pci_dma_sync_single((struct pci_dev*)fore200e->bus_dev, dma_addr, size, direction);
}
@@ -511,10 +512,8 @@
chunk->align_addr = chunk->alloc_addr;
#else
- if (fore200e_chunk_alloc(fore200e, chunk, size * nbr, alignment) < 0)
+ if (fore200e_chunk_alloc(fore200e, chunk, size * nbr, alignment, FORE200E_DMA_BIDIRECTIONAL) < 0)
return -ENOMEM;
-
- chunk->dma_addr = fore200e_pca_dma_map(fore200e, chunk->align_addr, chunk->align_size);
#endif
return 0;
@@ -532,8 +531,6 @@
chunk->alloc_addr,
chunk->dma_addr);
#else
- fore200e_pca_dma_unmap(fore200e, chunk->dma_addr, chunk->dma_size);
-
fore200e_chunk_free(fore200e, chunk);
#endif
}
@@ -685,7 +682,7 @@
opcode.opcode = OPCODE_GET_PROM;
opcode.pad = 0;
- prom_dma = fore200e->bus->dma_map(fore200e, prom, sizeof(struct prom_data));
+ prom_dma = fore200e->bus->dma_map(fore200e, prom, sizeof(struct prom_data), FORE200E_DMA_FROMDEVICE);
fore200e->bus->write(prom_dma, &entry->cp_entry->cmd.prom_block.prom_haddr);
@@ -697,7 +694,7 @@
*entry->status = STATUS_FREE;
- fore200e->bus->dma_unmap(fore200e, prom_dma, sizeof(struct prom_data));
+ fore200e->bus->dma_unmap(fore200e, prom_dma, sizeof(struct prom_data), FORE200E_DMA_FROMDEVICE);
if (ok == 0) {
printk(FORE200E "unable to get PROM data from device %s\n", fore200e->name);
@@ -748,31 +745,32 @@
static u32
-fore200e_sba_dma_map(struct fore200e* fore200e, void* virt_addr, int size)
+fore200e_sba_dma_map(struct fore200e* fore200e, void* virt_addr, int size, int direction)
{
- u32 dma_addr = sbus_map_single((struct sbus_dev*)fore200e->bus_dev, virt_addr, size);
+ u32 dma_addr = sbus_map_single((struct sbus_dev*)fore200e->bus_dev, virt_addr, size, direction);
- DPRINTK(3, "SBUS DVMA mapping: virt_addr = 0x%p, size = %d --> dma_addr = 0x%08x\n", virt_addr, size, dma_addr);
+ DPRINTK(3, "SBUS DVMA mapping: virt_addr = 0x%p, size = %d, direction = %d --> dma_addr = 0x%08x\n",
+ virt_addr, size, direction, dma_addr);
return dma_addr;
}
static void
-fore200e_sba_dma_unmap(struct fore200e* fore200e, u32 dma_addr, int size)
+fore200e_sba_dma_unmap(struct fore200e* fore200e, u32 dma_addr, int size, int direction)
{
- DPRINTK(3, "SBUS DVMA unmapping: dma_addr = 0x%08x, size = %d\n", dma_addr, size);
+ DPRINTK(3, "SBUS DVMA unmapping: dma_addr = 0x%08x, size = %d, direction = %d,\n", dma_addr, size, direction);
- sbus_unmap_single((struct sbus_dev*)fore200e->bus_dev, dma_addr, size);
+ sbus_unmap_single((struct sbus_dev*)fore200e->bus_dev, dma_addr, size, direction);
}
static void
-fore200e_sba_dma_sync(struct fore200e* fore200e, u32 dma_addr, int size)
+fore200e_sba_dma_sync(struct fore200e* fore200e, u32 dma_addr, int size, int direction)
{
- DPRINTK(3, "SBUS DVMA sync: dma_addr = 0x%08x, size = %d\n", dma_addr, size);
+ DPRINTK(3, "SBUS DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction);
- sbus_dma_sync_single((struct sbus_dev*)fore200e->bus_dev, dma_addr, size);
+ sbus_dma_sync_single((struct sbus_dev*)fore200e->bus_dev, dma_addr, size, direction);
}
@@ -1002,7 +1000,8 @@
kfree(entry->data);
/* remove DMA mapping */
- fore200e->bus->dma_unmap(fore200e, entry->tpd->tsd[ 0 ].buffer, entry->tpd->tsd[ 0 ].length);
+ fore200e->bus->dma_unmap(fore200e, entry->tpd->tsd[ 0 ].buffer, entry->tpd->tsd[ 0 ].length,
+ FORE200E_DMA_TODEVICE);
/* notify tx completion */
if (entry->vcc->pop)
@@ -1012,9 +1011,9 @@
/* check error condition */
if (*entry->status & STATUS_ERROR)
- entry->vcc->stats->tx_err++;
+ atomic_inc(&entry->vcc->stats->tx_err);
else
- entry->vcc->stats->tx++;
+ atomic_inc(&entry->vcc->stats->tx);
*entry->status = STATUS_FREE;
@@ -1127,7 +1126,7 @@
if (skb == NULL) {
printk(FORE200E "unable to alloc new skb, rx PDU length = %d\n", pdu_len);
- vcc->stats->rx_drop++;
+ atomic_inc(&vcc->stats->rx_drop);
return;
}
@@ -1146,7 +1145,7 @@
buffer = FORE200E_HDL2BUF(rpd->rsd[ i ].handle);
/* ensure DMA synchronisation */
- fore200e->bus->dma_sync(fore200e, buffer->data.dma_addr, rpd->rsd[ i ].length);
+ fore200e->bus->dma_sync(fore200e, buffer->data.dma_addr, rpd->rsd[ i ].length, FORE200E_DMA_FROMDEVICE);
memcpy(skb_put(skb, rpd->rsd[ i ].length), buffer->data.align_addr, rpd->rsd[ i ].length);
}
@@ -1169,7 +1168,7 @@
}
vcc->push(vcc, skb);
- vcc->stats->rx++;
+ atomic_inc(&vcc->stats->rx);
}
@@ -1404,7 +1403,7 @@
if (vci == ATM_VCI_UNSPEC || vpi == ATM_VPI_UNSPEC)
return 0;
- vcc->flags |= ATM_VF_ADDR;
+ set_bit(ATM_VF_ADDR,&vcc->flags);
vcc->itf = vcc->dev->number;
DPRINTK(2, "opening %d.%d.%d:%d QoS = (tx: cl=%s, pcr=%d-%d, cdv=%d, max_sdu=%d; "
@@ -1467,7 +1466,7 @@
fore200e_vcc->tx_min_pdu = fore200e_vcc->rx_min_pdu = 65536;
fore200e_vcc->tx_max_pdu = fore200e_vcc->rx_max_pdu = 0;
- vcc->flags |= ATM_VF_READY;
+ clear_bit(ATM_VF_READY,&vcc->flags);
return 0;
}
@@ -1552,11 +1551,14 @@
if(--retry > 0)
goto retry_here;
- vcc->stats->tx_err++;
+ atomic_inc(&vcc->stats->tx_err);
printk(FORE200E "tx queue of device %s is saturated, PDU dropped - heartbeat is %08x\n",
fore200e->name, fore200e->cp_queues->heartbeat);
-
+ if (vcc->pop)
+ vcc->pop(vcc, skb);
+ else
+ dev_kfree_skb(skb);
return -EIO;
}
}
@@ -1584,6 +1586,10 @@
if (entry->data == NULL) {
spin_unlock_irqrestore(&fore200e->tx_lock, flags);
+ if (vcc->pop)
+ vcc->pop(vcc, skb);
+ else
+ dev_kfree_skb(skb);
return -ENOMEM;
}
@@ -1591,11 +1597,11 @@
if (skb_len < tx_len)
memset(entry->data + skb_len, 0x00, tx_len - skb_len);
- tpd->tsd[ 0 ].buffer = fore200e->bus->dma_map(fore200e, entry->data, tx_len);
+ tpd->tsd[ 0 ].buffer = fore200e->bus->dma_map(fore200e, entry->data, tx_len, FORE200E_DMA_TODEVICE);
}
else {
entry->data = NULL;
- tpd->tsd[ 0 ].buffer = fore200e->bus->dma_map(fore200e, skb_data, tx_len);
+ tpd->tsd[ 0 ].buffer = fore200e->bus->dma_map(fore200e, skb_data, tx_len, FORE200E_DMA_TODEVICE);
}
tpd->tsd[ 0 ].length = tx_len;
@@ -1606,7 +1612,7 @@
spin_unlock_irqrestore(&fore200e->tx_lock, flags);
/* ensure DMA synchronisation */
- fore200e->bus->dma_sync(fore200e, tpd->tsd[ 0 ].buffer, tpd->tsd[ 0 ].length);
+ fore200e->bus->dma_sync(fore200e, tpd->tsd[ 0 ].buffer, tpd->tsd[ 0 ].length, FORE200E_DMA_TODEVICE);
DPRINTK(3, "tx on %d.%d.%d:%d, len = %u (%u)\n",
vcc->itf, vcc->vpi, vcc->vci, fore200e_atm2fore_aal(vcc->qos.aal),
@@ -1661,27 +1667,29 @@
{
int ok = fore200e_poll(fore200e, entry->status, STATUS_COMPLETE, 10);
- fore200e->bus->dma_unmap(fore200e, entry->tpd->tsd[ 0 ].buffer, entry->tpd->tsd[ 0 ].length);
+ fore200e->bus->dma_unmap(fore200e, entry->tpd->tsd[ 0 ].buffer, entry->tpd->tsd[ 0 ].length,
+ FORE200E_DMA_TODEVICE);
- if (ok == 0) {
- printk(FORE200E "synchronous tx on %d:%d:%d failed\n", vcc->itf, vcc->vpi, vcc->vci);
-
- entry->vcc->stats->tx_err++;
- return -EIO;
- }
- entry->vcc->stats->tx++;
-
- DPRINTK(3, "synchronous tx on %d:%d:%d succeeded\n", vcc->itf, vcc->vpi, vcc->vci);
-
/* free tmp copy of misaligned data */
if (entry->data)
kfree(entry->data);
-
+
/* notify tx completion */
if (vcc->pop)
vcc->pop(vcc, skb);
else
dev_kfree_skb(skb);
+
+ if (ok == 0) {
+ printk(FORE200E "synchronous tx on %d:%d:%d failed\n", vcc->itf, vcc->vpi, vcc->vci);
+
+ atomic_inc(&entry->vcc->stats->tx_err);
+ return -EIO;
+ }
+ atomic_inc(&entry->vcc->stats->tx);
+
+ DPRINTK(3, "synchronous tx on %d:%d:%d succeeded\n", vcc->itf, vcc->vpi, vcc->vci);
+
}
#endif
@@ -1704,7 +1712,7 @@
return -ENOMEM;
}
- stats_dma_addr = fore200e->bus->dma_map(fore200e, fore200e->stats, sizeof(struct stats));
+ stats_dma_addr = fore200e->bus->dma_map(fore200e, fore200e->stats, sizeof(struct stats), FORE200E_DMA_FROMDEVICE);
FORE200E_NEXT_ENTRY(cmdq->head, QUEUE_SIZE_CMD);
@@ -1721,7 +1729,7 @@
*entry->status = STATUS_FREE;
- fore200e->bus->dma_unmap(fore200e, stats_dma_addr, sizeof(struct stats));
+ fore200e->bus->dma_unmap(fore200e, stats_dma_addr, sizeof(struct stats), FORE200E_DMA_FROMDEVICE);
if (ok == 0) {
printk(FORE200E "unable to get statistics from device %s\n", fore200e->name);
@@ -1766,7 +1774,7 @@
int ok;
u32 oc3_regs_dma_addr;
- oc3_regs_dma_addr = fore200e->bus->dma_map(fore200e, regs, sizeof(struct oc3_regs));
+ oc3_regs_dma_addr = fore200e->bus->dma_map(fore200e, regs, sizeof(struct oc3_regs), FORE200E_DMA_FROMDEVICE);
FORE200E_NEXT_ENTRY(cmdq->head, QUEUE_SIZE_CMD);
@@ -1785,7 +1793,7 @@
*entry->status = STATUS_FREE;
- fore200e->bus_dma_unmap(fore200e, oc3_regs_dma_addr, sizeof(struct oc3_regs));
+ fore200e->bus->dma_unmap(fore200e, oc3_regs_dma_addr, sizeof(struct oc3_regs), FORE200E_DMA_FROMDEVICE);
if (ok == 0) {
printk(FORE200E "unable to get OC-3 regs of device %s\n", fore200e->name);
@@ -1842,16 +1850,16 @@
switch (loop_mode) {
- case SUNI_LM_NONE:
+ case ATM_LM_NONE:
mct_value = 0;
mct_mask = SUNI_MCT_DLE | SUNI_MCT_LLE;
break;
- case SUNI_LM_DIAG:
+ case ATM_LM_LOC_PHY:
mct_value = mct_mask = SUNI_MCT_DLE;
break;
- case SUNI_LM_LOOP:
+ case ATM_LM_RMT_PHY:
mct_value = mct_mask = SUNI_MCT_LLE;
break;
@@ -1921,12 +1929,16 @@
case SONET_GETDIAG:
return put_user(0, (int*)arg) ? -EFAULT : 0;
-
- case SUNI_SETLOOP:
+
+ case ATM_SETLOOP:
return fore200e_setloop(fore200e, (int)(unsigned long)arg);
- case SUNI_GETLOOP:
+ case ATM_GETLOOP:
return put_user(fore200e->loop_mode, (int*)arg) ? -EFAULT : 0;
+
+ case ATM_QUERYLOOP:
+ return put_user(ATM_LM_LOC_PHY | ATM_LM_RMT_PHY, (int*)arg) ?
+ -EFAULT : 0;
}
return -ENOSYS; /* not implemented */
@@ -1967,7 +1979,7 @@
/* update rate control parameters */
fore200e_rate_ctrl(qos, &fore200e_vcc->rate);
- vcc->flags |= ATM_VF_HASQOS;
+ set_bit(ATM_VF_HASQOS,&vcc->flags);
return 0;
}
@@ -2051,7 +2063,8 @@
/* allocate the receive buffer body */
if (fore200e_chunk_alloc(fore200e,
- &buffer[ i ].data, size, fore200e->bus->buffer_alignment) < 0) {
+ &buffer[ i ].data, size, fore200e->bus->buffer_alignment,
+ FORE200E_DMA_FROMDEVICE) < 0) {
while (i > 0)
fore200e_chunk_free(fore200e, &buffer[ --i ].data);
@@ -2485,7 +2498,8 @@
DPRINTK(2, "device %s being registered\n", fore200e->name);
- atm_dev = atm_dev_register(fore200e->bus->proc_name, &fore200e_ops, -1, 0);
+ atm_dev = atm_dev_register(fore200e->bus->proc_name, &fore200e_ops, -1,
+ NULL);
if (atm_dev == NULL) {
printk(FORE200E "unable to register device %s\n", fore200e->name);
return -ENODEV;
@@ -2690,17 +2704,29 @@
static const char* oc3_mode[] = {
"normal operation",
"diagnostic loopback",
- "line loopback"
+ "line loopback",
+ "unknown"
};
u32 fw_release = fore200e->bus->read(&fore200e->cp_queues->fw_release);
u32 mon960_release = fore200e->bus->read(&fore200e->cp_queues->mon960_release);
u32 oc3_revision = fore200e->bus->read(&fore200e->cp_queues->oc3_revision);
u32 media_index = FORE200E_MEDIA_INDEX(fore200e->bus->read(&fore200e->cp_queues->media_type));
+ u32 oc3_index;
if (media_index < 0 || media_index > 4)
media_index = 5;
+ switch(fore200e->loop_mode) {
+ case ATM_LM_NONE: oc3_index = 0;
+ break;
+ case ATM_LM_LOC_PHY: oc3_index = 1;
+ break;
+ case ATM_LM_RMT_PHY: oc3_index = 2;
+ break;
+ default: oc3_index = 3;
+ }
+
return sprintf(page,
" firmware release:\t\t%d.%d.%d\n"
" monitor release:\t\t%d.%d\n"
@@ -2711,7 +2737,7 @@
mon960_release >> 16, mon960_release << 16 >> 16,
media_name[ media_index ],
oc3_revision,
- oc3_mode[ fore200e->loop_mode ]);
+ oc3_mode[ oc3_index ]);
}
if (!left--) {
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)