#define OLYMPIC_DEBUG 0
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/spinlock.h>
+#include <linux/bitops.h>
+#include <linux/jiffies.h>
#include <net/checksum.h>
#include <asm/io.h>
#include <asm/system.h>
-#include <asm/bitops.h>
#include "olympic.h"
*/
static int ringspeed[OLYMPIC_MAX_ADAPTERS] = {0,} ;
-MODULE_PARM(ringspeed, "1-" __MODULE_STRING(OLYMPIC_MAX_ADAPTERS) "i");
+module_param_array(ringspeed, int, NULL, 0);
/* Packet buffer size */
static int pkt_buf_sz[OLYMPIC_MAX_ADAPTERS] = {0,} ;
-MODULE_PARM(pkt_buf_sz, "1-" __MODULE_STRING(OLYMPIC_MAX_ADAPTERS) "i") ;
+module_param_array(pkt_buf_sz, int, NULL, 0) ;
/* Message Level */
static int message_level[OLYMPIC_MAX_ADAPTERS] = {0,} ;
-MODULE_PARM(message_level, "1-" __MODULE_STRING(OLYMPIC_MAX_ADAPTERS) "i") ;
+module_param_array(message_level, int, NULL, 0) ;
/* Change network_monitor to receive mac frames through the arb channel.
* Will also create a /proc/net/olympic_tr%d entry, where %d is the tr
* i.e. it will give you the source address of beaconers on the ring
*/
static int network_monitor[OLYMPIC_MAX_ADAPTERS] = {0,};
-MODULE_PARM(network_monitor, "1-" __MODULE_STRING(OLYMPIC_MAX_ADAPTERS) "i");
+module_param_array(network_monitor, int, NULL, 0);
static struct pci_device_id olympic_pci_tbl[] = {
{PCI_VENDOR_ID_IBM,PCI_DEVICE_ID_IBM_TR_WAKE,PCI_ANY_ID,PCI_ANY_ID,},
static int olympic_close(struct net_device *dev);
static void olympic_set_rx_mode(struct net_device *dev);
static void olympic_freemem(struct net_device *dev) ;
-static irqreturn_t olympic_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t olympic_interrupt(int irq, void *dev_id);
static struct net_device_stats * olympic_get_stats(struct net_device *dev);
static int olympic_set_mac_address(struct net_device *dev, void *addr) ;
static void olympic_arb_cmd(struct net_device *dev);
dev = alloc_trdev(sizeof(struct olympic_private)) ;
if (!dev) {
i = -ENOMEM;
- goto op_free_dev;
+ goto op_release_dev;
}
olympic_priv = dev->priv ;
+ spin_lock_init(&olympic_priv->olympic_lock) ;
+
init_waitqueue_head(&olympic_priv->srb_wait);
init_waitqueue_head(&olympic_priv->trb_wait);
#if OLYMPIC_DEBUG
if (olympic_priv->olympic_lap)
iounmap(olympic_priv->olympic_lap);
-op_free_dev:
free_netdev(dev);
+op_release_dev:
pci_release_regions(pdev);
op_disable_dev:
static int __devinit olympic_init(struct net_device *dev)
{
struct olympic_private *olympic_priv;
- u8 *olympic_mmio, *init_srb,*adapter_addr;
+ u8 __iomem *olympic_mmio, *init_srb,*adapter_addr;
unsigned long t;
unsigned int uaa_addr;
t=jiffies;
while((readl(olympic_mmio+BCTL)) & BCTL_SOFTRESET) {
schedule();
- if(jiffies-t > 40*HZ) {
+ if(time_after(jiffies, t + 40*HZ)) {
printk(KERN_ERR "IBM PCI tokenring card not responding.\n");
return -ENODEV;
}
}
- spin_lock_init(&olympic_priv->olympic_lock) ;
/* Needed for cardbus */
if(!(readl(olympic_mmio+BCTL) & BCTL_MODE_INDICATOR)) {
t=jiffies;
while (!readl(olympic_mmio+CLKCTL) & CLKCTL_PAUSE) {
schedule() ;
- if(jiffies-t > 2*HZ) {
+ if(time_after(jiffies, t + 2*HZ)) {
printk(KERN_ERR "IBM Cardbus tokenring adapter not responsing.\n") ;
return -ENODEV;
}
t=jiffies;
while(!((readl(olympic_mmio+SISR_RR)) & SISR_SRB_REPLY)) {
schedule();
- if(jiffies-t > 15*HZ) {
+ if(time_after(jiffies, t + 15*HZ)) {
printk(KERN_ERR "IBM PCI tokenring card not responding.\n");
return -ENODEV;
}
static int olympic_open(struct net_device *dev)
{
struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
- u8 *olympic_mmio=olympic_priv->olympic_mmio,*init_srb;
+ u8 __iomem *olympic_mmio=olympic_priv->olympic_mmio,*init_srb;
unsigned long flags, t;
- char open_error[255] ;
int i, open_finished = 1 ;
+ u8 resp, err;
DECLARE_WAITQUEUE(wait,current) ;
- if(request_irq(dev->irq, &olympic_interrupt, SA_SHIRQ , "olympic", dev)) {
+ olympic_init(dev);
+
+ if(request_irq(dev->irq, &olympic_interrupt, IRQF_SHARED , "olympic", dev)) {
return -EAGAIN;
}
olympic_priv->srb_queued=0;
break;
}
- if ((jiffies-t) > 10*HZ) {
+ if (time_after(jiffies, t + 10*HZ)) {
printk(KERN_WARNING "%s: SRB timed out. \n",dev->name) ;
olympic_priv->srb_queued=0;
break ;
* timed out.
*/
- if(readb(init_srb+2)== OLYMPIC_CLEAR_RET_CODE) {
+ switch (resp = readb(init_srb+2)) {
+ case OLYMPIC_CLEAR_RET_CODE:
printk(KERN_WARNING "%s: Adapter Open time out or error.\n", dev->name) ;
- return -EIO ;
- }
-
- if(readb(init_srb+2)!=0) {
- if (readb(init_srb+2) == 0x07) {
- if (!olympic_priv->olympic_ring_speed && open_finished) { /* Autosense , first time around */
- printk(KERN_WARNING "%s: Retrying at different ring speed \n", dev->name);
- open_finished = 0 ;
- } else {
+ goto out;
+ case 0:
+ open_finished = 1;
+ break;
+ case 0x07:
+ if (!olympic_priv->olympic_ring_speed && open_finished) { /* Autosense , first time around */
+ printk(KERN_WARNING "%s: Retrying at different ring speed \n", dev->name);
+ open_finished = 0 ;
+ continue;
+ }
+
+ err = readb(init_srb+7);
- strcpy(open_error, open_maj_error[(readb(init_srb+7) & 0xf0) >> 4]) ;
- strcat(open_error," - ") ;
- strcat(open_error, open_min_error[(readb(init_srb+7) & 0x0f)]) ;
+ if (!olympic_priv->olympic_ring_speed && ((err & 0x0f) == 0x0d)) {
+ printk(KERN_WARNING "%s: Tried to autosense ring speed with no monitors present\n",dev->name);
+ printk(KERN_WARNING "%s: Please try again with a specified ring speed \n",dev->name);
+ } else {
+ printk(KERN_WARNING "%s: %s - %s\n", dev->name,
+ open_maj_error[(err & 0xf0) >> 4],
+ open_min_error[(err & 0x0f)]);
+ }
+ goto out;
+
+ case 0x32:
+ printk(KERN_WARNING "%s: Invalid LAA: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ dev->name,
+ olympic_priv->olympic_laa[0],
+ olympic_priv->olympic_laa[1],
+ olympic_priv->olympic_laa[2],
+ olympic_priv->olympic_laa[3],
+ olympic_priv->olympic_laa[4],
+ olympic_priv->olympic_laa[5]) ;
+ goto out;
- if (!olympic_priv->olympic_ring_speed && ((readb(init_srb+7) & 0x0f) == 0x0d)) {
- printk(KERN_WARNING "%s: Tried to autosense ring speed with no monitors present\n",dev->name);
- printk(KERN_WARNING "%s: Please try again with a specified ring speed \n",dev->name);
- free_irq(dev->irq, dev);
- return -EIO ;
- }
+ default:
+ printk(KERN_WARNING "%s: Bad OPEN response: %x\n", dev->name, resp);
+ goto out;
- printk(KERN_WARNING "%s: %s\n",dev->name,open_error);
- free_irq(dev->irq,dev) ;
- return -EIO ;
-
- } /* if autosense && open_finished */
- } else if (init_srb[2] == 0x32) {
- printk(KERN_WARNING "%s: Invalid LAA: %02x:%02x:%02x:%02x:%02x:%02x\n",
- dev->name,
- olympic_priv->olympic_laa[0],
- olympic_priv->olympic_laa[1],
- olympic_priv->olympic_laa[2],
- olympic_priv->olympic_laa[3],
- olympic_priv->olympic_laa[4],
- olympic_priv->olympic_laa[5]) ;
- free_irq(dev->irq,dev) ;
- return -EIO ;
- } else {
- printk(KERN_WARNING "%s: Bad OPEN response: %x\n", dev->name,init_srb[2]);
- free_irq(dev->irq, dev);
- return -EIO;
- }
- } else
- open_finished = 1 ;
+ }
} while (!(open_finished)) ; /* Will only loop if ring speed mismatch re-open attempted && autosense is on */
if (readb(init_srb+18) & (1<<3))
if (i==0) {
printk(KERN_WARNING "%s: Not enough memory to allocate rx buffers. Adapter disabled\n",dev->name);
- free_irq(dev->irq, dev);
- return -EIO;
+ goto out;
}
olympic_priv->rx_ring_dma_addr = pci_map_single(olympic_priv->pdev,olympic_priv->olympic_rx_ring,
#endif
if (olympic_priv->olympic_network_monitor) {
- u8 *oat ;
- u8 *opt ;
- oat = (u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_addr_table_addr) ;
- opt = (u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_parms_addr) ;
+ u8 __iomem *oat ;
+ u8 __iomem *opt ;
+ oat = (olympic_priv->olympic_lap + olympic_priv->olympic_addr_table_addr) ;
+ opt = (olympic_priv->olympic_lap + olympic_priv->olympic_parms_addr) ;
printk("%s: Node Address: %02x:%02x:%02x:%02x:%02x:%02x\n",dev->name,
readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)),
netif_start_queue(dev);
return 0;
-
+
+out:
+ free_irq(dev->irq, dev);
+ return -EIO;
}
/*
static void olympic_rx(struct net_device *dev)
{
struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
- u8 *olympic_mmio=olympic_priv->olympic_mmio;
+ u8 __iomem *olympic_mmio=olympic_priv->olympic_mmio;
struct olympic_rx_status *rx_status;
struct olympic_rx_desc *rx_desc ;
int rx_ring_last_received,length, buffer_cnt, cpy_length, frag_len;
int i;
for(i=0;i<OLYMPIC_RX_RING_SIZE;i++) {
- dev_kfree_skb_irq(olympic_priv->rx_ring_skb[olympic_priv->rx_status_last_received]);
+ if (olympic_priv->rx_ring_skb[olympic_priv->rx_status_last_received] != NULL) {
+ dev_kfree_skb_irq(olympic_priv->rx_ring_skb[olympic_priv->rx_status_last_received]);
+ olympic_priv->rx_ring_skb[olympic_priv->rx_status_last_received] = NULL;
+ }
if (olympic_priv->olympic_rx_ring[olympic_priv->rx_status_last_received].buffer != 0xdeadbeef) {
pci_unmap_single(olympic_priv->pdev,
le32_to_cpu(olympic_priv->olympic_rx_ring[olympic_priv->rx_status_last_received].buffer),
return ;
}
-static irqreturn_t olympic_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t olympic_interrupt(int irq, void *dev_id)
{
struct net_device *dev= (struct net_device *)dev_id;
struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
- u8 *olympic_mmio=olympic_priv->olympic_mmio;
+ u8 __iomem *olympic_mmio=olympic_priv->olympic_mmio;
u32 sisr;
- u8 *adapter_check_area ;
+ u8 __iomem *adapter_check_area ;
/*
* Read sisr but don't reset it yet.
/* Hotswap gives us this on removal */
if (sisr == 0xffffffff) {
printk(KERN_WARNING "%s: Hotswap adapter removal.\n",dev->name) ;
- olympic_freemem(dev) ;
- free_irq(dev->irq, dev) ;
- dev->stop = NULL ;
spin_unlock(&olympic_priv->olympic_lock) ;
return IRQ_NONE;
}
printk(KERN_ERR "The adapter must be reset to clear this condition.\n") ;
printk(KERN_ERR "Please report this error to the driver maintainer and/\n") ;
printk(KERN_ERR "or the linux-tr mailing list.\n") ;
- olympic_freemem(dev) ;
- free_irq(dev->irq, dev) ;
- dev->stop = NULL ;
+ wake_up_interruptible(&olympic_priv->srb_wait);
spin_unlock(&olympic_priv->olympic_lock) ;
return IRQ_HANDLED;
} /* SISR_ERR */
writel(readl(olympic_mmio+LAPWWC),olympic_mmio+LAPA);
adapter_check_area = olympic_priv->olympic_lap + ((readl(olympic_mmio+LAPWWC)) & (~0xf800)) ;
printk(KERN_WARNING "%s: Bytes %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",dev->name, readb(adapter_check_area+0), readb(adapter_check_area+1), readb(adapter_check_area+2), readb(adapter_check_area+3), readb(adapter_check_area+4), readb(adapter_check_area+5), readb(adapter_check_area+6), readb(adapter_check_area+7)) ;
- olympic_freemem(dev) ;
- free_irq(dev->irq, dev) ;
- dev->stop = NULL ;
spin_unlock(&olympic_priv->olympic_lock) ;
return IRQ_HANDLED;
} /* SISR_ADAPTER_CHECK */
static int olympic_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
- u8 *olympic_mmio=olympic_priv->olympic_mmio;
+ u8 __iomem *olympic_mmio=olympic_priv->olympic_mmio;
unsigned long flags ;
spin_lock_irqsave(&olympic_priv->olympic_lock, flags);
static int olympic_close(struct net_device *dev)
{
struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
- u8 *olympic_mmio=olympic_priv->olympic_mmio,*srb;
+ u8 __iomem *olympic_mmio=olympic_priv->olympic_mmio,*srb;
unsigned long t,flags;
DECLARE_WAITQUEUE(wait,current) ;
writeb(0,srb+1);
writeb(OLYMPIC_CLEAR_RET_CODE,srb+2);
+ add_wait_queue(&olympic_priv->srb_wait,&wait) ;
+ set_current_state(TASK_INTERRUPTIBLE) ;
+
spin_lock_irqsave(&olympic_priv->olympic_lock,flags);
olympic_priv->srb_queued=1;
writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM);
spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags);
-
- t = jiffies ;
-
- add_wait_queue(&olympic_priv->srb_wait,&wait) ;
- set_current_state(TASK_INTERRUPTIBLE) ;
while(olympic_priv->srb_queued) {
- schedule() ;
+
+ t = schedule_timeout_interruptible(60*HZ);
+
if(signal_pending(current)) {
printk(KERN_WARNING "%s: SRB timed out.\n",dev->name);
printk(KERN_WARNING "SISR=%x MISR=%x\n",readl(olympic_mmio+SISR),readl(olympic_mmio+LISR));
olympic_priv->srb_queued=0;
break;
}
- if ((jiffies-t) > 60*HZ) {
+
+ if (t == 0) {
printk(KERN_WARNING "%s: SRB timed out. May not be fatal. \n",dev->name) ;
- olympic_priv->srb_queued=0;
- break ;
}
- set_current_state(TASK_INTERRUPTIBLE) ;
+ olympic_priv->srb_queued=0;
}
remove_wait_queue(&olympic_priv->srb_wait,&wait) ;
- set_current_state(TASK_RUNNING) ;
olympic_priv->rx_status_last_received++;
olympic_priv->rx_status_last_received&=OLYMPIC_RX_RING_SIZE-1;
static void olympic_set_rx_mode(struct net_device *dev)
{
struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ;
- u8 *olympic_mmio = olympic_priv->olympic_mmio ;
+ u8 __iomem *olympic_mmio = olympic_priv->olympic_mmio ;
u8 options = 0;
- u8 *srb;
+ u8 __iomem *srb;
struct dev_mc_list *dmi ;
unsigned char dev_mc_address[4] ;
int i ;
static void olympic_srb_bh(struct net_device *dev)
{
struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ;
- u8 *olympic_mmio = olympic_priv->olympic_mmio ;
- u8 *srb;
+ u8 __iomem *olympic_mmio = olympic_priv->olympic_mmio ;
+ u8 __iomem *srb;
writel(olympic_priv->srb,olympic_mmio+LAPA);
srb=olympic_priv->olympic_lap + (olympic_priv->srb & (~0xf800));
static void olympic_arb_cmd(struct net_device *dev)
{
struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv;
- u8 *olympic_mmio=olympic_priv->olympic_mmio;
- u8 *arb_block, *asb_block, *srb ;
+ u8 __iomem *olympic_mmio=olympic_priv->olympic_mmio;
+ u8 __iomem *arb_block, *asb_block, *srb ;
u8 header_len ;
u16 frame_len, buffer_len ;
struct sk_buff *mac_frame ;
- u8 *buf_ptr ;
- u8 *frame_data ;
+ u8 __iomem *buf_ptr ;
+ u8 __iomem *frame_data ;
u16 buff_off ;
u16 lan_status = 0, lan_status_diff ; /* Initialize to stop compiler warning */
u8 fdx_prot_error ;
u16 next_ptr;
- int i ;
- arb_block = (u8 *)(olympic_priv->olympic_lap + olympic_priv->arb) ;
- asb_block = (u8 *)(olympic_priv->olympic_lap + olympic_priv->asb) ;
- srb = (u8 *)(olympic_priv->olympic_lap + olympic_priv->srb) ;
+ arb_block = (olympic_priv->olympic_lap + olympic_priv->arb) ;
+ asb_block = (olympic_priv->olympic_lap + olympic_priv->asb) ;
+ srb = (olympic_priv->olympic_lap + olympic_priv->srb) ;
if (readb(arb_block+0) == ARB_RECEIVE_DATA) { /* Receive.data, MAC frames */
writel(readl(olympic_mmio+BCTL)&~(3<<13),olympic_mmio+BCTL);
netif_stop_queue(dev);
olympic_priv->srb = readw(olympic_priv->olympic_lap + LAPWWO) ;
- for(i=0;i<OLYMPIC_RX_RING_SIZE;i++) {
- dev_kfree_skb_irq(olympic_priv->rx_ring_skb[olympic_priv->rx_status_last_received]);
- if (olympic_priv->olympic_rx_ring[olympic_priv->rx_status_last_received].buffer != 0xdeadbeef) {
- pci_unmap_single(olympic_priv->pdev,
- le32_to_cpu(olympic_priv->olympic_rx_ring[olympic_priv->rx_status_last_received].buffer),
- olympic_priv->pkt_buf_sz, PCI_DMA_FROMDEVICE);
- }
- olympic_priv->rx_status_last_received++;
- olympic_priv->rx_status_last_received&=OLYMPIC_RX_RING_SIZE-1;
- }
- /* unmap rings */
- pci_unmap_single(olympic_priv->pdev, olympic_priv->rx_status_ring_dma_addr,
- sizeof(struct olympic_rx_status) * OLYMPIC_RX_RING_SIZE, PCI_DMA_FROMDEVICE);
- pci_unmap_single(olympic_priv->pdev, olympic_priv->rx_ring_dma_addr,
- sizeof(struct olympic_rx_desc) * OLYMPIC_RX_RING_SIZE, PCI_DMA_TODEVICE);
-
- pci_unmap_single(olympic_priv->pdev, olympic_priv->tx_status_ring_dma_addr,
- sizeof(struct olympic_tx_status) * OLYMPIC_TX_RING_SIZE, PCI_DMA_FROMDEVICE);
- pci_unmap_single(olympic_priv->pdev, olympic_priv->tx_ring_dma_addr,
- sizeof(struct olympic_tx_desc) * OLYMPIC_TX_RING_SIZE, PCI_DMA_TODEVICE);
-
- free_irq(dev->irq,dev);
- dev->stop=NULL;
printk(KERN_WARNING "%s: Adapter has been closed \n", dev->name) ;
} /* If serious error */
static void olympic_asb_bh(struct net_device *dev)
{
struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ;
- u8 *arb_block, *asb_block ;
+ u8 __iomem *arb_block, *asb_block ;
- arb_block = (u8 *)(olympic_priv->olympic_lap + olympic_priv->arb) ;
- asb_block = (u8 *)(olympic_priv->olympic_lap + olympic_priv->asb) ;
+ arb_block = (olympic_priv->olympic_lap + olympic_priv->arb) ;
+ asb_block = (olympic_priv->olympic_lap + olympic_priv->asb) ;
if (olympic_priv->asb_queued == 1) { /* Dropped through the first time */
{
struct net_device *dev = (struct net_device *)data ;
struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
- u8 *oat = (u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_addr_table_addr) ;
- u8 *opt = (u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_parms_addr) ;
+ u8 __iomem *oat = (olympic_priv->olympic_lap + olympic_priv->olympic_addr_table_addr) ;
+ u8 __iomem *opt = (olympic_priv->olympic_lap + olympic_priv->olympic_parms_addr) ;
int size = 0 ;
int len=0;
off_t begin=0;
static int __init olympic_pci_init(void)
{
- return pci_module_init (&olympic_driver) ;
+ return pci_register_driver(&olympic_driver) ;
}
static void __exit olympic_pci_cleanup(void)