aboutsummaryrefslogtreecommitdiff
path: root/drivers/atm/eni.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/atm/eni.c')
-rw-r--r--drivers/atm/eni.c192
1 files changed, 108 insertions, 84 deletions
diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c
index c13c4d736ef..b1955ba40d6 100644
--- a/drivers/atm/eni.c
+++ b/drivers/atm/eni.c
@@ -4,7 +4,6 @@
#include <linux/module.h>
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/pci.h>
@@ -19,9 +18,9 @@
#include <linux/init.h>
#include <linux/atm_eni.h>
#include <linux/bitops.h>
-#include <asm/system.h>
+#include <linux/slab.h>
#include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/uaccess.h>
#include <asm/string.h>
#include <asm/byteorder.h>
@@ -156,9 +155,6 @@ static int tx_complete = 0,dma_complete = 0,queued = 0,requeued = 0,
static struct atm_dev *eni_boards = NULL;
-static u32 *cpu_zeroes = NULL; /* aligned "magic" zeroes */
-static dma_addr_t zeroes;
-
/* Read/write registers on card */
#define eni_in(r) readl(eni_dev->reg+(r)*4)
#define eni_out(v,r) writel((v),eni_dev->reg+(r)*4)
@@ -537,7 +533,7 @@ static int rx_aal0(struct atm_vcc *vcc)
return 0;
}
skb_put(skb,length);
- skb_set_timestamp(skb, &eni_vcc->timestamp);
+ skb->tstamp = eni_vcc->timestamp;
DPRINTK("got len %ld\n",length);
if (do_rx_dma(vcc,skb,1,length >> 2,length >> 2)) return 1;
eni_vcc->rxing++;
@@ -702,7 +698,7 @@ static void get_service(struct atm_dev *dev)
DPRINTK("Grr, servicing VCC %ld twice\n",vci);
continue;
}
- do_gettimeofday(&ENI_VCC(vcc)->timestamp);
+ ENI_VCC(vcc)->timestamp = ktime_get_real();
ENI_VCC(vcc)->next = NULL;
if (vcc->qos.rxtp.traffic_class == ATM_CBR) {
if (eni_dev->fast)
@@ -913,7 +909,6 @@ static int start_rx(struct atm_dev *dev)
free_page((unsigned long) eni_dev->free_list);
return -ENOMEM;
}
- memset(eni_dev->rx_map,0,PAGE_SIZE);
eni_dev->rx_mult = DEFAULT_RX_MULT;
eni_dev->fast = eni_dev->last_fast = NULL;
eni_dev->slow = eni_dev->last_slow = NULL;
@@ -1132,14 +1127,17 @@ DPRINTK("doing direct send\n"); /* @@@ well, this doesn't work anyway */
if (i == -1)
put_dma(tx->index,eni_dev->dma,&j,(unsigned long)
skb->data,
- skb->len - skb->data_len);
+ skb_headlen(skb));
else
put_dma(tx->index,eni_dev->dma,&j,(unsigned long)
- skb_shinfo(skb)->frags[i].page + skb_shinfo(skb)->frags[i].page_offset,
- skb_shinfo(skb)->frags[i].size);
+ skb_frag_page(&skb_shinfo(skb)->frags[i]) +
+ skb_shinfo(skb)->frags[i].page_offset,
+ skb_frag_size(&skb_shinfo(skb)->frags[i]));
+ }
+ if (skb->len & 3) {
+ put_dma(tx->index, eni_dev->dma, &j, eni_dev->zero.dma,
+ 4 - (skb->len & 3));
}
- if (skb->len & 3)
- put_dma(tx->index,eni_dev->dma,&j,zeroes,4-(skb->len & 3));
/* JK for AAL5 trailer - AAL0 doesn't need it, but who cares ... */
eni_dev->dma[j++] = (((tx->tx_pos+size) & (tx->words-1)) <<
MID_DMA_COUNT_SHIFT) | (tx->index << MID_DMA_CHAN_SHIFT) |
@@ -1272,7 +1270,7 @@ static int comp_tx(struct eni_dev *eni_dev,int *pcr,int reserved,int *pre,
if (*pre < 3) (*pre)++; /* else fail later */
div = pre_div[*pre]*-*pcr;
DPRINTK("max div %d\n",div);
- *res = (TS_CLOCK+div-1)/div-1;
+ *res = DIV_ROUND_UP(TS_CLOCK, div)-1;
}
if (*res < 0) *res = 0;
if (*res > MID_SEG_MAX_RATE) *res = MID_SEG_MAX_RATE;
@@ -1470,10 +1468,7 @@ if (eni_boards) printk(KERN_INFO "loss: %ld\n",ENI_DEV(eni_boards)->lost);
static void bug_int(struct atm_dev *dev,unsigned long reason)
{
- struct eni_dev *eni_dev;
-
DPRINTK(">bug_int\n");
- eni_dev = ENI_DEV(dev);
if (reason & MID_DMA_ERR_ACK)
printk(KERN_CRIT DEV_LABEL "(itf %d): driver error - DMA "
"error\n",dev->number);
@@ -1489,7 +1484,7 @@ static void bug_int(struct atm_dev *dev,unsigned long reason)
}
-static irqreturn_t eni_int(int irq,void *dev_id,struct pt_regs *regs)
+static irqreturn_t eni_int(int irq,void *dev_id)
{
struct atm_dev *dev;
struct eni_dev *eni_dev;
@@ -1572,7 +1567,7 @@ tx_complete++;
/*--------------------------------- entries ---------------------------------*/
-static const char *media_name[] __devinitdata = {
+static char * const media_name[] = {
"MMF", "SMF", "MMF", "03?", /* 0- 3 */
"UTP", "05?", "06?", "07?", /* 4- 7 */
"TAXI","09?", "10?", "11?", /* 8-11 */
@@ -1596,7 +1591,7 @@ static const char *media_name[] __devinitdata = {
} })
-static int __devinit get_esi_asic(struct atm_dev *dev)
+static int get_esi_asic(struct atm_dev *dev)
{
struct eni_dev *eni_dev;
unsigned char tonga;
@@ -1688,7 +1683,7 @@ static int __devinit get_esi_asic(struct atm_dev *dev)
#undef GET_SEPROM
-static int __devinit get_esi_fpga(struct atm_dev *dev, void __iomem *base)
+static int get_esi_fpga(struct atm_dev *dev, void __iomem *base)
{
void __iomem *mac_base;
int i;
@@ -1699,14 +1694,13 @@ static int __devinit get_esi_fpga(struct atm_dev *dev, void __iomem *base)
}
-static int __devinit eni_do_init(struct atm_dev *dev)
+static int eni_do_init(struct atm_dev *dev)
{
struct midway_eprom __iomem *eprom;
struct eni_dev *eni_dev;
struct pci_dev *pci_dev;
unsigned long real_base;
void __iomem *base;
- unsigned char revision;
int error,i,last;
DPRINTK(">eni_init\n");
@@ -1717,12 +1711,6 @@ static int __devinit eni_do_init(struct atm_dev *dev)
pci_dev = eni_dev->pci_dev;
real_base = pci_resource_start(pci_dev, 0);
eni_dev->irq = pci_dev->irq;
- error = pci_read_config_byte(pci_dev,PCI_REVISION_ID,&revision);
- if (error) {
- printk(KERN_ERR DEV_LABEL "(itf %d): init error 0x%02x\n",
- dev->number,error);
- return -EINVAL;
- }
if ((error = pci_write_config_word(pci_dev,PCI_COMMAND,
PCI_COMMAND_MEMORY |
(eni_dev->asic ? PCI_COMMAND_PARITY | PCI_COMMAND_SERR : 0)))) {
@@ -1731,23 +1719,26 @@ static int __devinit eni_do_init(struct atm_dev *dev)
return -EIO;
}
printk(KERN_NOTICE DEV_LABEL "(itf %d): rev.%d,base=0x%lx,irq=%d,",
- dev->number,revision,real_base,eni_dev->irq);
+ dev->number,pci_dev->revision,real_base,eni_dev->irq);
if (!(base = ioremap_nocache(real_base,MAP_MAX_SIZE))) {
printk("\n");
printk(KERN_ERR DEV_LABEL "(itf %d): can't set up page "
"mapping\n",dev->number);
return error;
}
+ eni_dev->ioaddr = base;
eni_dev->base_diff = real_base - (unsigned long) base;
/* id may not be present in ASIC Tonga boards - check this @@@ */
if (!eni_dev->asic) {
eprom = (base+EPROM_SIZE-sizeof(struct midway_eprom));
if (readl(&eprom->magic) != ENI155_MAGIC) {
printk("\n");
- printk(KERN_ERR KERN_ERR DEV_LABEL "(itf %d): bad "
- "magic - expected 0x%x, got 0x%x\n",dev->number,
- ENI155_MAGIC,(unsigned) readl(&eprom->magic));
- return -EINVAL;
+ printk(KERN_ERR DEV_LABEL
+ "(itf %d): bad magic - expected 0x%x, got 0x%x\n",
+ dev->number, ENI155_MAGIC,
+ (unsigned)readl(&eprom->magic));
+ error = -EINVAL;
+ goto unmap;
}
}
eni_dev->phy = base+PHY_BASE;
@@ -1774,21 +1765,39 @@ static int __devinit eni_do_init(struct atm_dev *dev)
printk(")\n");
printk(KERN_ERR DEV_LABEL "(itf %d): ERROR - wrong id 0x%x\n",
dev->number,(unsigned) eni_in(MID_RES_ID_MCON));
- return -EINVAL;
+ error = -EINVAL;
+ goto unmap;
}
error = eni_dev->asic ? get_esi_asic(dev) : get_esi_fpga(dev,base);
- if (error) return error;
+ if (error)
+ goto unmap;
for (i = 0; i < ESI_LEN; i++)
printk("%s%02X",i ? "-" : "",dev->esi[i]);
printk(")\n");
printk(KERN_NOTICE DEV_LABEL "(itf %d): %s,%s\n",dev->number,
eni_in(MID_RES_ID_MCON) & 0x200 ? "ASIC" : "FPGA",
media_name[eni_in(MID_RES_ID_MCON) & DAUGTHER_ID]);
- return suni_init(dev);
+
+ error = suni_init(dev);
+ if (error)
+ goto unmap;
+out:
+ return error;
+unmap:
+ iounmap(base);
+ goto out;
}
+static void eni_do_release(struct atm_dev *dev)
+{
+ struct eni_dev *ed = ENI_DEV(dev);
+
+ dev->phy->stop(dev);
+ dev->phy = NULL;
+ iounmap(ed->ioaddr);
+}
-static int __devinit eni_start(struct atm_dev *dev)
+static int eni_start(struct atm_dev *dev)
{
struct eni_dev *eni_dev;
@@ -1798,7 +1807,7 @@ static int __devinit eni_start(struct atm_dev *dev)
DPRINTK(">eni_start\n");
eni_dev = ENI_DEV(dev);
- if (request_irq(eni_dev->irq,&eni_int,SA_SHIRQ,DEV_LABEL,dev)) {
+ if (request_irq(eni_dev->irq,&eni_int,IRQF_SHARED,DEV_LABEL,dev)) {
printk(KERN_ERR DEV_LABEL "(itf %d): IRQ%d is already in use\n",
dev->number,eni_dev->irq);
error = -EAGAIN;
@@ -1833,7 +1842,7 @@ static int __devinit eni_start(struct atm_dev *dev)
/* initialize memory management */
buffer_mem = eni_dev->mem - (buf - eni_dev->ram);
eni_dev->free_list_size = buffer_mem/MID_MIN_BUF_SIZE/2;
- eni_dev->free_list = (struct eni_free *) kmalloc(
+ eni_dev->free_list = kmalloc(
sizeof(struct eni_free)*(eni_dev->free_list_size+1),GFP_KERNEL);
if (!eni_dev->free_list) {
printk(KERN_ERR DEV_LABEL "(itf %d): couldn't get free page\n",
@@ -1871,7 +1880,7 @@ free_list:
kfree(eni_dev->free_list);
free_irq:
- free_irq(eni_dev->irq, eni_dev);
+ free_irq(eni_dev->irq, dev);
out:
return error;
@@ -1896,7 +1905,6 @@ static void eni_close(struct atm_vcc *vcc)
static int eni_open(struct atm_vcc *vcc)
{
- struct eni_dev *eni_dev;
struct eni_vcc *eni_vcc;
int error;
short vpi = vcc->vpi;
@@ -1906,7 +1914,6 @@ static int eni_open(struct atm_vcc *vcc)
EVENT("eni_open\n",0,0);
if (!test_bit(ATM_VF_PARTIAL,&vcc->flags))
vcc->dev_data = NULL;
- eni_dev = ENI_DEV(vcc->dev);
if (vci != ATM_VPI_UNSPEC && vpi != ATM_VCI_UNSPEC)
set_bit(ATM_VF_ADDR,&vcc->flags);
if (vcc->qos.aal != ATM_AAL0 && vcc->qos.aal != ATM_AAL5)
@@ -2029,7 +2036,7 @@ static int eni_getsockopt(struct atm_vcc *vcc,int level,int optname,
static int eni_setsockopt(struct atm_vcc *vcc,int level,int optname,
- void __user *optval,int optlen)
+ void __user *optval,unsigned int optlen)
{
return -EINVAL;
}
@@ -2086,7 +2093,6 @@ static unsigned char eni_phy_get(struct atm_dev *dev,unsigned long addr)
static int eni_proc_read(struct atm_dev *dev,loff_t *pos,char *page)
{
- struct hlist_node *node;
struct sock *s;
static const char *signal[] = { "LOST","unknown","okay" };
struct eni_dev *eni_dev = ENI_DEV(dev);
@@ -2164,7 +2170,7 @@ static int eni_proc_read(struct atm_dev *dev,loff_t *pos,char *page)
for(i = 0; i < VCC_HTABLE_SIZE; ++i) {
struct hlist_head *head = &vcc_hash[i];
- sk_for_each(s, node, head) {
+ sk_for_each(s, head) {
struct eni_vcc *eni_vcc;
int length;
@@ -2219,65 +2225,83 @@ static const struct atmdev_ops ops = {
};
-static int __devinit eni_init_one(struct pci_dev *pci_dev,
- const struct pci_device_id *ent)
+static int eni_init_one(struct pci_dev *pci_dev,
+ const struct pci_device_id *ent)
{
struct atm_dev *dev;
struct eni_dev *eni_dev;
- int error = -ENOMEM;
+ struct eni_zero *zero;
+ int rc;
- DPRINTK("eni_init_one\n");
+ rc = pci_enable_device(pci_dev);
+ if (rc < 0)
+ goto out;
- if (pci_enable_device(pci_dev)) {
- error = -EIO;
- goto out0;
- }
+ rc = -ENOMEM;
+ eni_dev = kmalloc(sizeof(struct eni_dev), GFP_KERNEL);
+ if (!eni_dev)
+ goto err_disable;
- eni_dev = (struct eni_dev *) kmalloc(sizeof(struct eni_dev),GFP_KERNEL);
- if (!eni_dev) goto out0;
- if (!cpu_zeroes) {
- cpu_zeroes = pci_alloc_consistent(pci_dev,ENI_ZEROES_SIZE,
- &zeroes);
- if (!cpu_zeroes) goto out1;
- }
- dev = atm_dev_register(DEV_LABEL,&ops,-1,NULL);
- if (!dev) goto out2;
+ zero = &eni_dev->zero;
+ zero->addr = pci_alloc_consistent(pci_dev, ENI_ZEROES_SIZE, &zero->dma);
+ if (!zero->addr)
+ goto err_kfree;
+
+ dev = atm_dev_register(DEV_LABEL, &pci_dev->dev, &ops, -1, NULL);
+ if (!dev)
+ goto err_free_consistent;
+
+ dev->dev_data = eni_dev;
pci_set_drvdata(pci_dev, dev);
eni_dev->pci_dev = pci_dev;
- dev->dev_data = eni_dev;
eni_dev->asic = ent->driver_data;
- error = eni_do_init(dev);
- if (error) goto out3;
- error = eni_start(dev);
- if (error) goto out3;
+
+ rc = eni_do_init(dev);
+ if (rc < 0)
+ goto err_unregister;
+
+ rc = eni_start(dev);
+ if (rc < 0)
+ goto err_eni_release;
+
eni_dev->more = eni_boards;
eni_boards = dev;
- return 0;
-out3:
+out:
+ return rc;
+
+err_eni_release:
+ eni_do_release(dev);
+err_unregister:
atm_dev_deregister(dev);
-out2:
- pci_free_consistent(eni_dev->pci_dev,ENI_ZEROES_SIZE,cpu_zeroes,zeroes);
- cpu_zeroes = NULL;
-out1:
+err_free_consistent:
+ pci_free_consistent(pci_dev, ENI_ZEROES_SIZE, zero->addr, zero->dma);
+err_kfree:
kfree(eni_dev);
-out0:
- return error;
+err_disable:
+ pci_disable_device(pci_dev);
+ goto out;
}
static struct pci_device_id eni_pci_tbl[] = {
- { PCI_VENDOR_ID_EF, PCI_DEVICE_ID_EF_ATM_FPGA, PCI_ANY_ID, PCI_ANY_ID,
- 0, 0, 0 /* FPGA */ },
- { PCI_VENDOR_ID_EF, PCI_DEVICE_ID_EF_ATM_ASIC, PCI_ANY_ID, PCI_ANY_ID,
- 0, 0, 1 /* ASIC */ },
+ { PCI_VDEVICE(EF, PCI_DEVICE_ID_EF_ATM_FPGA), 0 /* FPGA */ },
+ { PCI_VDEVICE(EF, PCI_DEVICE_ID_EF_ATM_ASIC), 1 /* ASIC */ },
{ 0, }
};
MODULE_DEVICE_TABLE(pci,eni_pci_tbl);
-static void __devexit eni_remove_one(struct pci_dev *pci_dev)
+static void eni_remove_one(struct pci_dev *pdev)
{
- /* grrr */
+ struct atm_dev *dev = pci_get_drvdata(pdev);
+ struct eni_dev *ed = ENI_DEV(dev);
+ struct eni_zero *zero = &ed->zero;
+
+ eni_do_release(dev);
+ atm_dev_deregister(dev);
+ pci_free_consistent(pdev, ENI_ZEROES_SIZE, zero->addr, zero->dma);
+ kfree(ed);
+ pci_disable_device(pdev);
}
@@ -2285,7 +2309,7 @@ static struct pci_driver eni_driver = {
.name = DEV_LABEL,
.id_table = eni_pci_tbl,
.probe = eni_init_one,
- .remove = __devexit_p(eni_remove_one),
+ .remove = eni_remove_one,
};