X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fnet%2Fpcnet32.c;h=ff92aca0a7b37ad82daf35a38dfd9190353b356a;hb=0c3b091b9a7a5184011e75afa7f0206d288ddb06;hp=465485a3fbc642529c0c84a60c92ddd10b102b2e;hpb=bc06cffdec85d487c77109dffcd2f285bdc502d3;p=linux-2.6-omap-h63xx.git diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index 465485a3fbc..ff92aca0a7b 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -23,11 +23,11 @@ #define DRV_NAME "pcnet32" #ifdef CONFIG_PCNET32_NAPI -#define DRV_VERSION "1.33-NAPI" +#define DRV_VERSION "1.34-NAPI" #else -#define DRV_VERSION "1.33" +#define DRV_VERSION "1.34" #endif -#define DRV_RELDATE "27.Jun.2006" +#define DRV_RELDATE "14.Aug.2007" #define PFX DRV_NAME ": " static const char *const version = @@ -210,31 +210,31 @@ static int homepna[MAX_UNITS]; /* The PCNET32 Rx and Tx ring descriptors. */ struct pcnet32_rx_head { - u32 base; - s16 buf_length; /* two`s complement of length */ - s16 status; - u32 msg_length; - u32 reserved; + __le32 base; + __le16 buf_length; /* two`s complement of length */ + __le16 status; + __le32 msg_length; + __le32 reserved; }; struct pcnet32_tx_head { - u32 base; - s16 length; /* two`s complement of length */ - s16 status; - u32 misc; - u32 reserved; + __le32 base; + __le16 length; /* two`s complement of length */ + __le16 status; + __le32 misc; + __le32 reserved; }; /* The PCNET32 32-Bit initialization block, described in databook. */ struct pcnet32_init_block { - u16 mode; - u16 tlen_rlen; + __le16 mode; + __le16 tlen_rlen; u8 phys_addr[6]; - u16 reserved; - u32 filter[2]; + __le16 reserved; + __le32 filter[2]; /* Receive and transmit ring base, along with extra bits. */ - u32 rx_ring; - u32 tx_ring; + __le32 rx_ring; + __le32 tx_ring; }; /* PCnet32 access functions */ @@ -280,7 +280,8 @@ struct pcnet32_private { unsigned int dirty_rx, /* ring entries to be freed. */ dirty_tx; - struct net_device_stats stats; + struct net_device *dev; + struct napi_struct napi; char tx_full; char phycount; /* number of phys found */ int options; @@ -440,15 +441,25 @@ static struct pcnet32_access pcnet32_dwio = { static void pcnet32_netif_stop(struct net_device *dev) { +#ifdef CONFIG_PCNET32_NAPI + struct pcnet32_private *lp = netdev_priv(dev); +#endif dev->trans_start = jiffies; - netif_poll_disable(dev); +#ifdef CONFIG_PCNET32_NAPI + napi_disable(&lp->napi); +#endif netif_tx_disable(dev); } static void pcnet32_netif_start(struct net_device *dev) { +#ifdef CONFIG_PCNET32_NAPI + struct pcnet32_private *lp = netdev_priv(dev); +#endif netif_wake_queue(dev); - netif_poll_enable(dev); +#ifdef CONFIG_PCNET32_NAPI + napi_enable(&lp->napi); +#endif } /* @@ -602,9 +613,9 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev, new_dma_addr_list[new] = pci_map_single(lp->pci_dev, rx_skbuff->data, PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE); - new_rx_ring[new].base = (u32) le32_to_cpu(new_dma_addr_list[new]); - new_rx_ring[new].buf_length = le16_to_cpu(2 - PKT_BUF_SZ); - new_rx_ring[new].status = le16_to_cpu(0x8000); + new_rx_ring[new].base = cpu_to_le32(new_dma_addr_list[new]); + new_rx_ring[new].buf_length = cpu_to_le16(2 - PKT_BUF_SZ); + new_rx_ring[new].status = cpu_to_le16(0x8000); } /* and free any unneeded buffers */ for (; new < lp->rx_ring_size; new++) { @@ -816,7 +827,7 @@ static int pcnet32_set_ringparam(struct net_device *dev, if ((1 << i) != lp->rx_ring_size) pcnet32_realloc_rx_ring(dev, lp, i); - dev->weight = lp->rx_ring_size / 2; + lp->napi.weight = lp->rx_ring_size / 2; if (netif_running(dev)) { pcnet32_netif_start(dev); @@ -839,9 +850,14 @@ static void pcnet32_get_strings(struct net_device *dev, u32 stringset, memcpy(data, pcnet32_gstrings_test, sizeof(pcnet32_gstrings_test)); } -static int pcnet32_self_test_count(struct net_device *dev) +static int pcnet32_get_sset_count(struct net_device *dev, int sset) { - return PCNET32_TEST_LEN; + switch (sset) { + case ETH_SS_TEST: + return PCNET32_TEST_LEN; + default: + return -EOPNOTSUPP; + } } static void pcnet32_ethtool_test(struct net_device *dev, @@ -875,7 +891,7 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1) int x, i; /* counters */ int numbuffs = 4; /* number of TX/RX buffers and descs */ u16 status = 0x8300; /* TX ring status */ - u16 teststatus; /* test of ring status */ + __le16 teststatus; /* test of ring status */ int rc; /* return code */ int size; /* size of packets */ unsigned char *packet; /* source packet data */ @@ -922,7 +938,7 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1) packet = skb->data; skb_put(skb, size); /* create space for data */ lp->tx_skbuff[x] = skb; - lp->tx_ring[x].length = le16_to_cpu(-skb->len); + lp->tx_ring[x].length = cpu_to_le16(-skb->len); lp->tx_ring[x].misc = 0; /* put DA and SA into the skb */ @@ -942,10 +958,9 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1) lp->tx_dma_addr[x] = pci_map_single(lp->pci_dev, skb->data, skb->len, PCI_DMA_TODEVICE); - lp->tx_ring[x].base = - (u32) le32_to_cpu(lp->tx_dma_addr[x]); + lp->tx_ring[x].base = cpu_to_le32(lp->tx_dma_addr[x]); wmb(); /* Make sure owner changes after all others are visible */ - lp->tx_ring[x].status = le16_to_cpu(status); + lp->tx_ring[x].status = cpu_to_le16(status); } } @@ -956,7 +971,7 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1) x = a->read_csr(ioaddr, CSR15) & 0xfffc; lp->a.write_csr(ioaddr, CSR15, x | 0x0044); - teststatus = le16_to_cpu(0x8000); + teststatus = cpu_to_le16(0x8000); lp->a.write_csr(ioaddr, CSR0, CSR0_START); /* Set STRT bit */ /* Check status of descriptors */ @@ -1086,6 +1101,7 @@ static int pcnet32_phys_id(struct net_device *dev, u32 data) mod_timer(&lp->blink_timer, jiffies); set_current_state(TASK_INTERRUPTIBLE); + /* AV: the limit here makes no sense whatsoever */ if ((!data) || (data > (u32) (MAX_SCHEDULE_TIMEOUT / HZ))) data = (u32) (MAX_SCHEDULE_TIMEOUT / HZ); @@ -1165,15 +1181,15 @@ static void pcnet32_rx_entry(struct net_device *dev, * buffers, with only the last correctly noting the error. */ if (status & 0x01) /* Only count a general error at the */ - lp->stats.rx_errors++; /* end of a packet. */ + dev->stats.rx_errors++; /* end of a packet. */ if (status & 0x20) - lp->stats.rx_frame_errors++; + dev->stats.rx_frame_errors++; if (status & 0x10) - lp->stats.rx_over_errors++; + dev->stats.rx_over_errors++; if (status & 0x08) - lp->stats.rx_crc_errors++; + dev->stats.rx_crc_errors++; if (status & 0x04) - lp->stats.rx_fifo_errors++; + dev->stats.rx_fifo_errors++; return; } @@ -1184,13 +1200,13 @@ static void pcnet32_rx_entry(struct net_device *dev, if (netif_msg_drv(lp)) printk(KERN_ERR "%s: Impossible packet size %d!\n", dev->name, pkt_len); - lp->stats.rx_errors++; + dev->stats.rx_errors++; return; } if (pkt_len < 60) { if (netif_msg_rx_err(lp)) printk(KERN_ERR "%s: Runt packet!\n", dev->name); - lp->stats.rx_errors++; + dev->stats.rx_errors++; return; } @@ -1211,7 +1227,7 @@ static void pcnet32_rx_entry(struct net_device *dev, newskb->data, PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE); - rxp->base = le32_to_cpu(lp->rx_dma_addr[entry]); + rxp->base = cpu_to_le32(lp->rx_dma_addr[entry]); rx_in_place = 1; } else skb = NULL; @@ -1224,7 +1240,7 @@ static void pcnet32_rx_entry(struct net_device *dev, printk(KERN_ERR "%s: Memory squeeze, dropping packet.\n", dev->name); - lp->stats.rx_dropped++; + dev->stats.rx_dropped++; return; } skb->dev = dev; @@ -1243,7 +1259,7 @@ static void pcnet32_rx_entry(struct net_device *dev, pkt_len, PCI_DMA_FROMDEVICE); } - lp->stats.rx_bytes += skb->len; + dev->stats.rx_bytes += skb->len; skb->protocol = eth_type_trans(skb, dev); #ifdef CONFIG_PCNET32_NAPI netif_receive_skb(skb); @@ -1251,11 +1267,11 @@ static void pcnet32_rx_entry(struct net_device *dev, netif_rx(skb); #endif dev->last_rx = jiffies; - lp->stats.rx_packets++; + dev->stats.rx_packets++; return; } -static int pcnet32_rx(struct net_device *dev, int quota) +static int pcnet32_rx(struct net_device *dev, int budget) { struct pcnet32_private *lp = netdev_priv(dev); int entry = lp->cur_rx & lp->rx_mod_mask; @@ -1263,16 +1279,16 @@ static int pcnet32_rx(struct net_device *dev, int quota) int npackets = 0; /* If we own the next entry, it's a new packet. Send it up. */ - while (quota > npackets && (short)le16_to_cpu(rxp->status) >= 0) { + while (npackets < budget && (short)le16_to_cpu(rxp->status) >= 0) { pcnet32_rx_entry(dev, lp, rxp, entry); npackets += 1; /* * The docs say that the buffer length isn't touched, but Andrew * Boyd of QNX reports that some revs of the 79C965 clear it. */ - rxp->buf_length = le16_to_cpu(2 - PKT_BUF_SZ); + rxp->buf_length = cpu_to_le16(2 - PKT_BUF_SZ); wmb(); /* Make sure owner changes after others are visible */ - rxp->status = le16_to_cpu(0x8000); + rxp->status = cpu_to_le16(0x8000); entry = (++lp->cur_rx) & lp->rx_mod_mask; rxp = &lp->rx_ring[entry]; } @@ -1299,21 +1315,21 @@ static int pcnet32_tx(struct net_device *dev) if (status & 0x4000) { /* There was a major error, log it. */ int err_status = le32_to_cpu(lp->tx_ring[entry].misc); - lp->stats.tx_errors++; + dev->stats.tx_errors++; if (netif_msg_tx_err(lp)) printk(KERN_ERR "%s: Tx error status=%04x err_status=%08x\n", dev->name, status, err_status); if (err_status & 0x04000000) - lp->stats.tx_aborted_errors++; + dev->stats.tx_aborted_errors++; if (err_status & 0x08000000) - lp->stats.tx_carrier_errors++; + dev->stats.tx_carrier_errors++; if (err_status & 0x10000000) - lp->stats.tx_window_errors++; + dev->stats.tx_window_errors++; #ifndef DO_DXSUFLO if (err_status & 0x40000000) { - lp->stats.tx_fifo_errors++; + dev->stats.tx_fifo_errors++; /* Ackk! On FIFO errors the Tx unit is turned off! */ /* Remove this verbosity later! */ if (netif_msg_tx_err(lp)) @@ -1324,7 +1340,7 @@ static int pcnet32_tx(struct net_device *dev) } #else if (err_status & 0x40000000) { - lp->stats.tx_fifo_errors++; + dev->stats.tx_fifo_errors++; if (!lp->dxsuflo) { /* If controller doesn't recover ... */ /* Ackk! On FIFO errors the Tx unit is turned off! */ /* Remove this verbosity later! */ @@ -1338,8 +1354,8 @@ static int pcnet32_tx(struct net_device *dev) #endif } else { if (status & 0x1800) - lp->stats.collisions++; - lp->stats.tx_packets++; + dev->stats.collisions++; + dev->stats.tx_packets++; } /* We must free the original skb */ @@ -1379,15 +1395,16 @@ static int pcnet32_tx(struct net_device *dev) } #ifdef CONFIG_PCNET32_NAPI -static int pcnet32_poll(struct net_device *dev, int *budget) +static int pcnet32_poll(struct napi_struct *napi, int budget) { - struct pcnet32_private *lp = netdev_priv(dev); - int quota = min(dev->quota, *budget); + struct pcnet32_private *lp = container_of(napi, struct pcnet32_private, napi); + struct net_device *dev = lp->dev; unsigned long ioaddr = dev->base_addr; unsigned long flags; + int work_done; u16 val; - quota = pcnet32_rx(dev, quota); + work_done = pcnet32_rx(dev, budget); spin_lock_irqsave(&lp->lock, flags); if (pcnet32_tx(dev)) { @@ -1399,28 +1416,22 @@ static int pcnet32_poll(struct net_device *dev, int *budget) } spin_unlock_irqrestore(&lp->lock, flags); - *budget -= quota; - dev->quota -= quota; - - if (dev->quota == 0) { - return 1; - } - - netif_rx_complete(dev); - - spin_lock_irqsave(&lp->lock, flags); + if (work_done < budget) { + spin_lock_irqsave(&lp->lock, flags); - /* clear interrupt masks */ - val = lp->a.read_csr(ioaddr, CSR3); - val &= 0x00ff; - lp->a.write_csr(ioaddr, CSR3, val); + __netif_rx_complete(dev, napi); - /* Set interrupt enable. */ - lp->a.write_csr(ioaddr, CSR0, CSR0_INTEN); - mmiowb(); - spin_unlock_irqrestore(&lp->lock, flags); + /* clear interrupt masks */ + val = lp->a.read_csr(ioaddr, CSR3); + val &= 0x00ff; + lp->a.write_csr(ioaddr, CSR3, val); - return 0; + /* Set interrupt enable. */ + lp->a.write_csr(ioaddr, CSR0, CSR0_INTEN); + mmiowb(); + spin_unlock_irqrestore(&lp->lock, flags); + } + return work_done; } #endif @@ -1506,16 +1517,12 @@ static const struct ethtool_ops pcnet32_ethtool_ops = { .get_link = pcnet32_get_link, .get_ringparam = pcnet32_get_ringparam, .set_ringparam = pcnet32_set_ringparam, - .get_tx_csum = ethtool_op_get_tx_csum, - .get_sg = ethtool_op_get_sg, - .get_tso = ethtool_op_get_tso, .get_strings = pcnet32_get_strings, - .self_test_count = pcnet32_self_test_count, .self_test = pcnet32_ethtool_test, .phys_id = pcnet32_phys_id, .get_regs_len = pcnet32_get_regs_len, .get_regs = pcnet32_get_regs, - .get_perm_addr = ethtool_op_get_perm_addr, + .get_sset_count = pcnet32_get_sset_count, }; /* only probes for non-PCI devices, the rest are handled by @@ -1816,9 +1823,10 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) } lp->pci_dev = pdev; + lp->dev = dev; + spin_lock_init(&lp->lock); - SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); lp->name = chipname; lp->shared_irq = shared; @@ -1844,6 +1852,13 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) lp->mii_if.mdio_read = mdio_read; lp->mii_if.mdio_write = mdio_write; + /* napi.weight is used in both the napi and non-napi cases */ + lp->napi.weight = lp->rx_ring_size / 2; + +#ifdef CONFIG_PCNET32_NAPI + netif_napi_add(dev, &lp->napi, pcnet32_poll, lp->rx_ring_size / 2); +#endif + if (fdx && !(lp->options & PCNET32_PORT_ASEL) && ((cards_found >= MAX_UNITS) || full_duplex[cards_found])) lp->options |= PCNET32_PORT_FD; @@ -1866,15 +1881,15 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) && dev->dev_addr[2] == 0x75) lp->options = PCNET32_PORT_FD | PCNET32_PORT_GPSI; - lp->init_block->mode = le16_to_cpu(0x0003); /* Disable Rx and Tx. */ + lp->init_block->mode = cpu_to_le16(0x0003); /* Disable Rx and Tx. */ lp->init_block->tlen_rlen = - le16_to_cpu(lp->tx_len_bits | lp->rx_len_bits); + cpu_to_le16(lp->tx_len_bits | lp->rx_len_bits); for (i = 0; i < 6; i++) lp->init_block->phys_addr[i] = dev->dev_addr[i]; lp->init_block->filter[0] = 0x00000000; lp->init_block->filter[1] = 0x00000000; - lp->init_block->rx_ring = (u32) le32_to_cpu(lp->rx_ring_dma_addr); - lp->init_block->tx_ring = (u32) le32_to_cpu(lp->tx_ring_dma_addr); + lp->init_block->rx_ring = cpu_to_le32(lp->rx_ring_dma_addr); + lp->init_block->tx_ring = cpu_to_le32(lp->tx_ring_dma_addr); /* switch pcnet32 to 32bit mode */ a->write_bcr(ioaddr, 20, 2); @@ -1954,10 +1969,6 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) dev->ethtool_ops = &pcnet32_ethtool_ops; dev->tx_timeout = pcnet32_tx_timeout; dev->watchdog_timeo = (5 * HZ); - dev->weight = lp->rx_ring_size / 2; -#ifdef CONFIG_PCNET32_NAPI - dev->poll = pcnet32_poll; -#endif #ifdef CONFIG_NET_POLL_CONTROLLER dev->poll_controller = pcnet32_poll_controller; @@ -2269,7 +2280,7 @@ static int pcnet32_open(struct net_device *dev) #endif lp->init_block->mode = - le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7); + cpu_to_le16((lp->options & PCNET32_PORT_PORTSEL) << 7); pcnet32_load_multicast(dev); if (pcnet32_init_ring(dev)) { @@ -2277,6 +2288,10 @@ static int pcnet32_open(struct net_device *dev) goto err_free_ring; } +#ifdef CONFIG_PCNET32_NAPI + napi_enable(&lp->napi); +#endif + /* Re-initialize the PCNET32, and start it when done. */ lp->a.write_csr(ioaddr, 1, (lp->init_dma_addr & 0xffff)); lp->a.write_csr(ioaddr, 2, (lp->init_dma_addr >> 16)); @@ -2392,10 +2407,10 @@ static int pcnet32_init_ring(struct net_device *dev) lp->rx_dma_addr[i] = pci_map_single(lp->pci_dev, rx_skbuff->data, PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE); - lp->rx_ring[i].base = (u32) le32_to_cpu(lp->rx_dma_addr[i]); - lp->rx_ring[i].buf_length = le16_to_cpu(2 - PKT_BUF_SZ); + lp->rx_ring[i].base = cpu_to_le32(lp->rx_dma_addr[i]); + lp->rx_ring[i].buf_length = cpu_to_le16(2 - PKT_BUF_SZ); wmb(); /* Make sure owner changes after all others are visible */ - lp->rx_ring[i].status = le16_to_cpu(0x8000); + lp->rx_ring[i].status = cpu_to_le16(0x8000); } /* The Tx buffer address is filled in as needed, but we do need to clear * the upper ownership bit. */ @@ -2407,11 +2422,11 @@ static int pcnet32_init_ring(struct net_device *dev) } lp->init_block->tlen_rlen = - le16_to_cpu(lp->tx_len_bits | lp->rx_len_bits); + cpu_to_le16(lp->tx_len_bits | lp->rx_len_bits); for (i = 0; i < 6; i++) lp->init_block->phys_addr[i] = dev->dev_addr[i]; - lp->init_block->rx_ring = (u32) le32_to_cpu(lp->rx_ring_dma_addr); - lp->init_block->tx_ring = (u32) le32_to_cpu(lp->tx_ring_dma_addr); + lp->init_block->rx_ring = cpu_to_le32(lp->rx_ring_dma_addr); + lp->init_block->tx_ring = cpu_to_le32(lp->tx_ring_dma_addr); wmb(); /* Make sure all changes are visible */ return 0; } @@ -2462,7 +2477,7 @@ static void pcnet32_tx_timeout(struct net_device *dev) "%s: transmit timed out, status %4.4x, resetting.\n", dev->name, lp->a.read_csr(ioaddr, CSR0)); lp->a.write_csr(ioaddr, CSR0, CSR0_STOP); - lp->stats.tx_errors++; + dev->stats.tx_errors++; if (netif_msg_tx_err(lp)) { int i; printk(KERN_DEBUG @@ -2520,19 +2535,19 @@ static int pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Caution: the write order is important here, set the status * with the "ownership" bits last. */ - lp->tx_ring[entry].length = le16_to_cpu(-skb->len); + lp->tx_ring[entry].length = cpu_to_le16(-skb->len); lp->tx_ring[entry].misc = 0x00000000; lp->tx_skbuff[entry] = skb; lp->tx_dma_addr[entry] = pci_map_single(lp->pci_dev, skb->data, skb->len, PCI_DMA_TODEVICE); - lp->tx_ring[entry].base = (u32) le32_to_cpu(lp->tx_dma_addr[entry]); + lp->tx_ring[entry].base = cpu_to_le32(lp->tx_dma_addr[entry]); wmb(); /* Make sure owner changes after all others are visible */ - lp->tx_ring[entry].status = le16_to_cpu(status); + lp->tx_ring[entry].status = cpu_to_le16(status); lp->cur_tx++; - lp->stats.tx_bytes += skb->len; + dev->stats.tx_bytes += skb->len; /* Trigger an immediate send poll. */ lp->a.write_csr(ioaddr, CSR0, CSR0_INTEN | CSR0_TXPOLL); @@ -2577,7 +2592,7 @@ pcnet32_interrupt(int irq, void *dev_id) /* Log misc errors. */ if (csr0 & 0x4000) - lp->stats.tx_errors++; /* Tx babble. */ + dev->stats.tx_errors++; /* Tx babble. */ if (csr0 & 0x1000) { /* * This happens when our receive ring is full. This @@ -2590,7 +2605,7 @@ pcnet32_interrupt(int irq, void *dev_id) * don't get a rx interrupt, but a missed frame * interrupt sooner or later. */ - lp->stats.rx_errors++; /* Missed a Rx frame. */ + dev->stats.rx_errors++; /* Missed a Rx frame. */ } if (csr0 & 0x0800) { if (netif_msg_drv(lp)) @@ -2600,18 +2615,18 @@ pcnet32_interrupt(int irq, void *dev_id) /* unlike for the lance, there is no restart needed */ } #ifdef CONFIG_PCNET32_NAPI - if (netif_rx_schedule_prep(dev)) { + if (netif_rx_schedule_prep(dev, &lp->napi)) { u16 val; /* set interrupt masks */ val = lp->a.read_csr(ioaddr, CSR3); val |= 0x5f00; lp->a.write_csr(ioaddr, CSR3, val); mmiowb(); - __netif_rx_schedule(dev); + __netif_rx_schedule(dev, &lp->napi); break; } #else - pcnet32_rx(dev, dev->weight); + pcnet32_rx(dev, lp->napi.weight); if (pcnet32_tx(dev)) { /* reset the chip to clear the error condition, then restart */ lp->a.reset(ioaddr); @@ -2646,10 +2661,13 @@ static int pcnet32_close(struct net_device *dev) del_timer_sync(&lp->watchdog_timer); netif_stop_queue(dev); +#ifdef CONFIG_PCNET32_NAPI + napi_disable(&lp->napi); +#endif spin_lock_irqsave(&lp->lock, flags); - lp->stats.rx_missed_errors = lp->a.read_csr(ioaddr, 112); + dev->stats.rx_missed_errors = lp->a.read_csr(ioaddr, 112); if (netif_msg_ifdown(lp)) printk(KERN_DEBUG @@ -2686,10 +2704,10 @@ static struct net_device_stats *pcnet32_get_stats(struct net_device *dev) unsigned long flags; spin_lock_irqsave(&lp->lock, flags); - lp->stats.rx_missed_errors = lp->a.read_csr(ioaddr, 112); + dev->stats.rx_missed_errors = lp->a.read_csr(ioaddr, 112); spin_unlock_irqrestore(&lp->lock, flags); - return &lp->stats; + return &dev->stats; } /* taken from the sunlance driver, which it took from the depca driver */ @@ -2697,7 +2715,7 @@ static void pcnet32_load_multicast(struct net_device *dev) { struct pcnet32_private *lp = netdev_priv(dev); volatile struct pcnet32_init_block *ib = lp->init_block; - volatile u16 *mcast_table = (u16 *) & ib->filter; + volatile __le16 *mcast_table = (__le16 *)ib->filter; struct dev_mc_list *dmi = dev->mc_list; unsigned long ioaddr = dev->base_addr; char *addrs; @@ -2706,8 +2724,8 @@ static void pcnet32_load_multicast(struct net_device *dev) /* set all multicast bits */ if (dev->flags & IFF_ALLMULTI) { - ib->filter[0] = 0xffffffff; - ib->filter[1] = 0xffffffff; + ib->filter[0] = cpu_to_le32(~0U); + ib->filter[1] = cpu_to_le32(~0U); lp->a.write_csr(ioaddr, PCNET32_MC_FILTER, 0xffff); lp->a.write_csr(ioaddr, PCNET32_MC_FILTER+1, 0xffff); lp->a.write_csr(ioaddr, PCNET32_MC_FILTER+2, 0xffff); @@ -2729,9 +2747,7 @@ static void pcnet32_load_multicast(struct net_device *dev) crc = ether_crc_le(6, addrs); crc = crc >> 26; - mcast_table[crc >> 4] = - le16_to_cpu(le16_to_cpu(mcast_table[crc >> 4]) | - (1 << (crc & 0xf))); + mcast_table[crc >> 4] |= cpu_to_le16(1 << (crc & 0xf)); } for (i = 0; i < 4; i++) lp->a.write_csr(ioaddr, PCNET32_MC_FILTER + i, @@ -2757,12 +2773,12 @@ static void pcnet32_set_multicast_list(struct net_device *dev) printk(KERN_INFO "%s: Promiscuous mode enabled.\n", dev->name); lp->init_block->mode = - le16_to_cpu(0x8000 | (lp->options & PCNET32_PORT_PORTSEL) << + cpu_to_le16(0x8000 | (lp->options & PCNET32_PORT_PORTSEL) << 7); lp->a.write_csr(ioaddr, CSR15, csr15 | 0x8000); } else { lp->init_block->mode = - le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7); + cpu_to_le16((lp->options & PCNET32_PORT_PORTSEL) << 7); lp->a.write_csr(ioaddr, CSR15, csr15 & 0x7fff); pcnet32_load_multicast(dev); } @@ -2944,6 +2960,33 @@ static void pcnet32_watchdog(struct net_device *dev) mod_timer(&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT); } +static int pcnet32_pm_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct net_device *dev = pci_get_drvdata(pdev); + + if (netif_running(dev)) { + netif_device_detach(dev); + pcnet32_close(dev); + } + pci_save_state(pdev); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + return 0; +} + +static int pcnet32_pm_resume(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + + if (netif_running(dev)) { + pcnet32_open(dev); + netif_device_attach(dev); + } + return 0; +} + static void __devexit pcnet32_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); @@ -2967,6 +3010,8 @@ static struct pci_driver pcnet32_driver = { .probe = pcnet32_probe_pci, .remove = __devexit_p(pcnet32_remove_one), .id_table = pcnet32_pci_tbl, + .suspend = pcnet32_pm_suspend, + .resume = pcnet32_pm_resume, }; /* An additional parameter that may be passed in... */