/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
-#include <linux/config.h>
#include <linux/module.h>
-#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/pci.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/delay.h>
-#include <linux/ioport.h> /* for request_region */
#include <linux/uio.h>
#include <linux/init.h>
+#include <linux/dma-mapping.h>
#include <linux/atm_zatm.h>
#include <linux/capability.h>
#include <linux/bitops.h>
#include <linux/wait.h>
+#include <linux/slab.h>
#include <asm/byteorder.h>
#include <asm/system.h>
#include <asm/string.h>
EVENT("error code 0x%x/0x%x\n",(here[3] & uPD98401_AAL5_ES) >>
uPD98401_AAL5_ES_SHIFT,error);
skb = ((struct rx_buffer_head *) bus_to_virt(here[2]))->skb;
- do_gettimeofday(&skb->stamp);
+ __net_timestamp(skb);
#if 0
printk("[-3..0] 0x%08lx 0x%08lx 0x%08lx 0x%08lx\n",((unsigned *) skb->data)[-3],
((unsigned *) skb->data)[-2],((unsigned *) skb->data)[-1],
chan = (here[3] & uPD98401_AAL5_CHAN) >>
uPD98401_AAL5_CHAN_SHIFT;
if (chan < zatm_dev->chans && zatm_dev->rx_map[chan]) {
+ int pos;
vcc = zatm_dev->rx_map[chan];
- if (skb == zatm_dev->last_free[ZATM_VCC(vcc)->pool])
- zatm_dev->last_free[ZATM_VCC(vcc)->pool] = NULL;
- skb_unlink(skb);
+ pos = ZATM_VCC(vcc)->pool;
+ if (skb == zatm_dev->last_free[pos])
+ zatm_dev->last_free[pos] = NULL;
+ skb_unlink(skb, zatm_dev->pool + pos);
}
else {
printk(KERN_ERR DEV_LABEL "(itf %d): RX indication "
vcc->qos.rxtp.max_sdu = 65464;
/* fix this - we may want to receive 64kB SDUs
later */
- cells = (vcc->qos.rxtp.max_sdu+ATM_AAL5_TRAILER+
- ATM_CELL_PAYLOAD-1)/ATM_CELL_PAYLOAD;
+ cells = DIV_ROUND_UP(vcc->qos.rxtp.max_sdu + ATM_AAL5_TRAILER,
+ ATM_CELL_PAYLOAD);
zatm_vcc->pool = pool_index(cells*ATM_CELL_PAYLOAD);
}
else {
DPRINTK("start_rx\n");
zatm_dev = ZATM_DEV(dev);
size = sizeof(struct atm_vcc *)*zatm_dev->chans;
- zatm_dev->rx_map = (struct atm_vcc **) kmalloc(size,GFP_KERNEL);
+ zatm_dev->rx_map = kzalloc(size,GFP_KERNEL);
if (!zatm_dev->rx_map) return -ENOMEM;
- memset(zatm_dev->rx_map,0,size);
/* set VPI/VCI split (use all VCIs and give what's left to VPIs) */
zpokel(zatm_dev,(1 << dev->ci_range.vci_bits)-1,uPD98401_VRR);
/* prepare free buffer pools */
u32 *put;
int i;
- dsc = (u32 *) kmalloc(uPD98401_TXPD_SIZE*2+
- uPD98401_TXBD_SIZE*ATM_SKB(skb)->iovcnt,GFP_ATOMIC);
+ dsc = kmalloc(uPD98401_TXPD_SIZE * 2 +
+ uPD98401_TXBD_SIZE * ATM_SKB(skb)->iovcnt, GFP_ATOMIC);
if (!dsc) {
- if (vcc->pop) vcc->pop(vcc,skb);
- else dev_kfree_skb_irq(skb);
+ if (vcc->pop)
+ vcc->pop(vcc, skb);
+ else
+ dev_kfree_skb_irq(skb);
return -EAGAIN;
}
/* @@@ should check alignment */
(ATM_SKB(skb)->atm_options & ATM_ATMOPT_CLP ?
uPD98401_CLPM_1 : uPD98401_CLPM_0));
dsc[1] = 0;
- dsc[2] = ATM_SKB(skb)->iovcnt*uPD98401_TXBD_SIZE;
+ dsc[2] = ATM_SKB(skb)->iovcnt * uPD98401_TXBD_SIZE;
dsc[3] = virt_to_bus(put);
for (i = 0; i < ATM_SKB(skb)->iovcnt; i++) {
*put++ = ((struct iovec *) skb->data)[i].iov_len;
i = m = 1;
zatm_dev->ubr_ref_cnt++;
zatm_dev->ubr = shaper;
+ *pcr = 0;
}
else {
if (min) {
}
else {
i = 255;
- m = (ATM_OC3_PCR*255+max-1)/max;
+ m = DIV_ROUND_UP(ATM_OC3_PCR*255, max);
}
}
if (i > m) {
unsigned long flags;
u32 *loop;
unsigned short chan;
- int pcr,unlimited;
+ int unlimited;
DPRINTK("open_tx_first\n");
zatm_dev = ZATM_DEV(vcc->dev);
vcc->qos.txtp.max_pcr >= ATM_OC3_PCR);
if (unlimited && zatm_dev->ubr != -1) zatm_vcc->shaper = zatm_dev->ubr;
else {
+ int uninitialized_var(pcr);
+
if (unlimited) vcc->qos.txtp.max_sdu = ATM_MAX_AAL5_PDU;
if ((zatm_vcc->shaper = alloc_shaper(vcc->dev,&pcr,
vcc->qos.txtp.min_pcr,vcc->qos.txtp.max_pcr,unlimited))
skb_queue_head_init(&zatm_vcc->tx_queue);
init_waitqueue_head(&zatm_vcc->tx_wait);
/* initialize ring */
- zatm_vcc->ring = kmalloc(RING_SIZE,GFP_KERNEL);
+ zatm_vcc->ring = kzalloc(RING_SIZE,GFP_KERNEL);
if (!zatm_vcc->ring) return -ENOMEM;
- memset(zatm_vcc->ring,0,RING_SIZE);
loop = zatm_vcc->ring+RING_ENTRIES*RING_WORDS;
loop[0] = uPD98401_TXPD_V;
loop[1] = loop[2] = 0;
DPRINTK("start_tx\n");
zatm_dev = ZATM_DEV(dev);
- zatm_dev->tx_map = (struct atm_vcc **) kmalloc(sizeof(struct atm_vcc *)*
+ zatm_dev->tx_map = kmalloc(sizeof(struct atm_vcc *)*
zatm_dev->chans,GFP_KERNEL);
if (!zatm_dev->tx_map) return -ENOMEM;
zatm_dev->tx_bw = ATM_OC3_PCR;
/*------------------------------- interrupts --------------------------------*/
-static irqreturn_t zatm_int(int irq,void *dev_id,struct pt_regs *regs)
+static irqreturn_t zatm_int(int irq,void *dev_id)
{
struct atm_dev *dev;
struct zatm_dev *zatm_dev;
/*--------------------------------- entries ---------------------------------*/
-static int __init zatm_init(struct atm_dev *dev)
+static int __devinit zatm_init(struct atm_dev *dev)
{
struct zatm_dev *zatm_dev;
struct pci_dev *pci_dev;
unsigned short command;
- unsigned char revision;
int error,i,last;
unsigned long t0,t1,t2;
pci_dev = zatm_dev->pci_dev;
zatm_dev->base = pci_resource_start(pci_dev, 0);
zatm_dev->irq = pci_dev->irq;
- if ((error = pci_read_config_word(pci_dev,PCI_COMMAND,&command)) ||
- (error = pci_read_config_byte(pci_dev,PCI_REVISION_ID,&revision))) {
+ if ((error = pci_read_config_word(pci_dev,PCI_COMMAND,&command))) {
printk(KERN_ERR DEV_LABEL "(itf %d): init error 0x%02x\n",
dev->number,error);
return -EINVAL;
}
eprom_get_esi(dev);
printk(KERN_NOTICE DEV_LABEL "(itf %d): rev.%d,base=0x%x,irq=%d,",
- dev->number,revision,zatm_dev->base,zatm_dev->irq);
+ dev->number,pci_dev->revision,zatm_dev->base,zatm_dev->irq);
/* reset uPD98401 */
zout(0,SWR);
while (!(zin(GSR) & uPD98401_INT_IND));
}
-static int __init zatm_start(struct atm_dev *dev)
+static int __devinit zatm_start(struct atm_dev *dev)
{
- struct zatm_dev *zatm_dev;
+ struct zatm_dev *zatm_dev = ZATM_DEV(dev);
+ struct pci_dev *pdev = zatm_dev->pci_dev;
unsigned long curr;
int pools,vccs,rx;
- int error,i,ld;
+ int error, i, ld;
DPRINTK("zatm_start\n");
- zatm_dev = ZATM_DEV(dev);
zatm_dev->rx_map = zatm_dev->tx_map = NULL;
- for (i = 0; i < NR_MBX; i++)
- zatm_dev->mbx_start[i] = 0;
- if (request_irq(zatm_dev->irq,&zatm_int,SA_SHIRQ,DEV_LABEL,dev)) {
- printk(KERN_ERR DEV_LABEL "(itf %d): IRQ%d is already in use\n",
- dev->number,zatm_dev->irq);
- return -EAGAIN;
+ for (i = 0; i < NR_MBX; i++)
+ zatm_dev->mbx_start[i] = 0;
+ error = request_irq(zatm_dev->irq, zatm_int, IRQF_SHARED, DEV_LABEL, dev);
+ if (error < 0) {
+ printk(KERN_ERR DEV_LABEL "(itf %d): IRQ%d is already in use\n",
+ dev->number,zatm_dev->irq);
+ goto done;
}
- request_region(zatm_dev->base,uPD98401_PORTS,DEV_LABEL);
/* define memory regions */
pools = NR_POOLS;
if (NR_SHAPERS*SHAPER_SIZE > pools*POOL_SIZE)
"%ld VCs\n",dev->number,NR_SHAPERS,pools,rx,
(zatm_dev->mem-curr*4)/VC_SIZE);
/* create mailboxes */
- for (i = 0; i < NR_MBX; i++)
- if (mbx_entries[i]) {
- unsigned long here;
-
- here = (unsigned long) kmalloc(2*MBX_SIZE(i),
- GFP_KERNEL);
- if (!here) {
- error = -ENOMEM;
- goto out;
- }
- if ((here^(here+MBX_SIZE(i))) & ~0xffffUL)/* paranoia */
- here = (here & ~0xffffUL)+0x10000;
- zatm_dev->mbx_start[i] = here;
- if ((here^virt_to_bus((void *) here)) & 0xffff) {
- printk(KERN_ERR DEV_LABEL "(itf %d): system "
- "bus incompatible with driver\n",
- dev->number);
- error = -ENODEV;
- goto out;
- }
- DPRINTK("mbx@0x%08lx-0x%08lx\n",here,here+MBX_SIZE(i));
- zatm_dev->mbx_end[i] = (here+MBX_SIZE(i)) & 0xffff;
- zout(virt_to_bus((void *) here) >> 16,MSH(i));
- zout(virt_to_bus((void *) here),MSL(i));
- zout((here+MBX_SIZE(i)) & 0xffff,MBA(i));
- zout(here & 0xffff,MTA(i));
- zout(here & 0xffff,MWA(i));
+ for (i = 0; i < NR_MBX; i++) {
+ void *mbx;
+ dma_addr_t mbx_dma;
+
+ if (!mbx_entries[i])
+ continue;
+ mbx = pci_alloc_consistent(pdev, 2*MBX_SIZE(i), &mbx_dma);
+ if (!mbx) {
+ error = -ENOMEM;
+ goto out;
}
+ /*
+ * Alignment provided by pci_alloc_consistent() isn't enough
+ * for this device.
+ */
+ if (((unsigned long)mbx ^ mbx_dma) & 0xffff) {
+ printk(KERN_ERR DEV_LABEL "(itf %d): system "
+ "bus incompatible with driver\n", dev->number);
+ pci_free_consistent(pdev, 2*MBX_SIZE(i), mbx, mbx_dma);
+ error = -ENODEV;
+ goto out;
+ }
+ DPRINTK("mbx@0x%08lx-0x%08lx\n", mbx, mbx + MBX_SIZE(i));
+ zatm_dev->mbx_start[i] = (unsigned long)mbx;
+ zatm_dev->mbx_dma[i] = mbx_dma;
+ zatm_dev->mbx_end[i] = (zatm_dev->mbx_start[i] + MBX_SIZE(i)) &
+ 0xffff;
+ zout(mbx_dma >> 16, MSH(i));
+ zout(mbx_dma, MSL(i));
+ zout(zatm_dev->mbx_end[i], MBA(i));
+ zout((unsigned long)mbx & 0xffff, MTA(i));
+ zout((unsigned long)mbx & 0xffff, MWA(i));
+ }
error = start_tx(dev);
- if (error) goto out;
+ if (error)
+ goto out;
error = start_rx(dev);
- if (error) goto out;
+ if (error)
+ goto out_tx;
error = dev->phy->start(dev);
- if (error) goto out;
+ if (error)
+ goto out_rx;
zout(0xffffffff,IMR); /* enable interrupts */
/* enable TX & RX */
zout(zin(GMR) | uPD98401_GMR_SE | uPD98401_GMR_RE,GMR);
- return 0;
- out:
- for (i = 0; i < NR_MBX; i++)
- kfree(&zatm_dev->mbx_start[i]);
+done:
+ return error;
+
+out_rx:
kfree(zatm_dev->rx_map);
+out_tx:
kfree(zatm_dev->tx_map);
+out:
+ while (i-- > 0) {
+ pci_free_consistent(pdev, 2*MBX_SIZE(i),
+ (void *)zatm_dev->mbx_start[i],
+ zatm_dev->mbx_dma[i]);
+ }
free_irq(zatm_dev->irq, dev);
- return error;
+ goto done;
}
static int zatm_setsockopt(struct atm_vcc *vcc,int level,int optname,
- void __user *optval,int optlen)
+ void __user *optval,unsigned int optlen)
{
return -EINVAL;
}
struct zatm_dev *zatm_dev;
int ret = -ENOMEM;
- zatm_dev = (struct zatm_dev *) kmalloc(sizeof(*zatm_dev), GFP_KERNEL);
+ zatm_dev = kmalloc(sizeof(*zatm_dev), GFP_KERNEL);
if (!zatm_dev) {
printk(KERN_EMERG "%s: memory shortage\n", DEV_LABEL);
goto out;