*/
#define DRV_NAME "8139cp"
-#define DRV_VERSION "1.2"
+#define DRV_VERSION "1.3"
#define DRV_RELDATE "Mar 22, 2004"
u64 addr;
};
-struct ring_info {
- struct sk_buff *skb;
- u32 len;
-};
-
struct cp_dma_stats {
u64 tx_ok;
u64 rx_ok;
struct net_device_stats net_stats;
struct cp_extra_stats cp_stats;
- unsigned rx_tail ____cacheline_aligned;
+ unsigned rx_head ____cacheline_aligned;
+ unsigned rx_tail;
struct cp_desc *rx_ring;
- struct ring_info rx_skb[CP_RX_RING_SIZE];
- unsigned rx_buf_sz;
+ struct sk_buff *rx_skb[CP_RX_RING_SIZE];
unsigned tx_head ____cacheline_aligned;
unsigned tx_tail;
-
struct cp_desc *tx_ring;
- struct ring_info tx_skb[CP_TX_RING_SIZE];
- dma_addr_t ring_dma;
+ struct sk_buff *tx_skb[CP_TX_RING_SIZE];
+
+ unsigned rx_buf_sz;
+ unsigned wol_enabled : 1; /* Is Wake-on-LAN enabled? */
#if CP_VLAN_TAG_USED
struct vlan_group *vlgrp;
#endif
-
- unsigned int wol_enabled : 1; /* Is Wake-on-LAN enabled? */
+ dma_addr_t ring_dma;
struct mii_if_info mii_if;
};
struct ethtool_eeprom *eeprom, u8 *data);
static struct pci_device_id cp_pci_tbl[] = {
- { PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
- { PCI_VENDOR_ID_TTTECH, PCI_DEVICE_ID_TTTECH_MC322,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
+ { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139), },
+ { PCI_DEVICE(PCI_VENDOR_ID_TTTECH, PCI_DEVICE_ID_TTTECH_MC322), },
{ },
};
MODULE_DEVICE_TABLE(pci, cp_pci_tbl);
spin_lock_irqsave(&cp->lock, flags);
cp->cpcmd &= ~RxVlanOn;
cpw16(CpCmd, cp->cpcmd);
- if (cp->vlgrp)
- cp->vlgrp->vlan_devices[vid] = NULL;
+ vlan_group_set_device(cp->vlgrp, vid, NULL);
spin_unlock_irqrestore(&cp->lock, flags);
}
#endif /* CP_VLAN_TAG_USED */
struct cp_desc *desc;
unsigned buflen;
- skb = cp->rx_skb[rx_tail].skb;
+ skb = cp->rx_skb[rx_tail];
BUG_ON(!skb);
desc = &cp->rx_ring[rx_tail];
}
skb_reserve(new_skb, RX_OFFSET);
- new_skb->dev = dev;
pci_unmap_single(cp->pdev, mapping,
buflen, PCI_DMA_FROMDEVICE);
mapping = pci_map_single(cp->pdev, new_skb->data, buflen,
PCI_DMA_FROMDEVICE);
- cp->rx_skb[rx_tail].skb = new_skb;
+ cp->rx_skb[rx_tail] = new_skb;
cp_rx_skb(cp, skb, desc);
rx++;
* this round of polling
*/
if (rx_work) {
+ unsigned long flags;
+
if (cpr16(IntrStatus) & cp_rx_intr_mask)
goto rx_status_loop;
- local_irq_disable();
+ local_irq_save(flags);
cpw16_f(IntrMask, cp_intr_mask);
__netif_rx_complete(dev);
- local_irq_enable();
+ local_irq_restore(flags);
return 0; /* done */
}
return 1; /* not done */
}
-static irqreturn_t
-cp_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
+static irqreturn_t cp_interrupt (int irq, void *dev_instance)
{
struct net_device *dev = dev_instance;
struct cp_private *cp;
static void cp_poll_controller(struct net_device *dev)
{
disable_irq(dev->irq);
- cp_interrupt(dev->irq, dev, NULL);
+ cp_interrupt(dev->irq, dev);
enable_irq(dev->irq);
}
#endif
if (status & DescOwn)
break;
- skb = cp->tx_skb[tx_tail].skb;
+ skb = cp->tx_skb[tx_tail];
BUG_ON(!skb);
pci_unmap_single(cp->pdev, le64_to_cpu(txd->addr),
- cp->tx_skb[tx_tail].len, PCI_DMA_TODEVICE);
+ le32_to_cpu(txd->opts1) & 0xffff,
+ PCI_DMA_TODEVICE);
if (status & LastFrag) {
if (status & (TxError | TxFIFOUnder)) {
dev_kfree_skb_irq(skb);
}
- cp->tx_skb[tx_tail].skb = NULL;
+ cp->tx_skb[tx_tail] = NULL;
tx_tail = NEXT_TX(tx_tail);
}
struct cp_private *cp = netdev_priv(dev);
unsigned entry;
u32 eor, flags;
+ unsigned long intr_flags;
#if CP_VLAN_TAG_USED
u32 vlan_tag = 0;
#endif
int mss = 0;
- spin_lock_irq(&cp->lock);
+ spin_lock_irqsave(&cp->lock, intr_flags);
/* This is a hard error, log it. */
if (TX_BUFFS_AVAIL(cp) <= (skb_shinfo(skb)->nr_frags + 1)) {
netif_stop_queue(dev);
- spin_unlock_irq(&cp->lock);
+ spin_unlock_irqrestore(&cp->lock, intr_flags);
printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n",
dev->name);
return 1;
if (mss)
flags |= LargeSend | ((mss & MSSMask) << MSSShift);
- else if (skb->ip_summed == CHECKSUM_HW) {
- const struct iphdr *ip = skb->nh.iph;
+ else if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ const struct iphdr *ip = ip_hdr(skb);
if (ip->protocol == IPPROTO_TCP)
flags |= IPCS | TCPCS;
else if (ip->protocol == IPPROTO_UDP)
txd->opts1 = cpu_to_le32(flags);
wmb();
- cp->tx_skb[entry].skb = skb;
- cp->tx_skb[entry].len = len;
+ cp->tx_skb[entry] = skb;
entry = NEXT_TX(entry);
} else {
struct cp_desc *txd;
u32 first_len, first_eor;
dma_addr_t first_mapping;
int frag, first_entry = entry;
- const struct iphdr *ip = skb->nh.iph;
+ const struct iphdr *ip = ip_hdr(skb);
/* We must give this initial chunk to the device last.
* Otherwise we could race with the device.
first_len = skb_headlen(skb);
first_mapping = pci_map_single(cp->pdev, skb->data,
first_len, PCI_DMA_TODEVICE);
- cp->tx_skb[entry].skb = skb;
- cp->tx_skb[entry].len = first_len;
+ cp->tx_skb[entry] = skb;
entry = NEXT_TX(entry);
for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
if (mss)
ctrl |= LargeSend |
((mss & MSSMask) << MSSShift);
- else if (skb->ip_summed == CHECKSUM_HW) {
+ else if (skb->ip_summed == CHECKSUM_PARTIAL) {
if (ip->protocol == IPPROTO_TCP)
ctrl |= IPCS | TCPCS;
else if (ip->protocol == IPPROTO_UDP)
txd->opts1 = cpu_to_le32(ctrl);
wmb();
- cp->tx_skb[entry].skb = skb;
- cp->tx_skb[entry].len = len;
+ cp->tx_skb[entry] = skb;
entry = NEXT_TX(entry);
}
txd->addr = cpu_to_le64(first_mapping);
wmb();
- if (skb->ip_summed == CHECKSUM_HW) {
+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
if (ip->protocol == IPPROTO_TCP)
txd->opts1 = cpu_to_le32(first_eor | first_len |
FirstFrag | DescOwn |
if (TX_BUFFS_AVAIL(cp) <= (MAX_SKB_FRAGS + 1))
netif_stop_queue(dev);
- spin_unlock_irq(&cp->lock);
+ spin_unlock_irqrestore(&cp->lock, intr_flags);
cpw8(TxPoll, NormalTxPoll);
dev->trans_start = jiffies;
/* Note: do not reorder, GCC is clever about common statements. */
if (dev->flags & IFF_PROMISC) {
/* Unconditionally log net taps. */
- printk (KERN_NOTICE "%s: Promiscuous mode enabled.\n",
- dev->name);
rx_mode =
AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
AcceptAllPhys;
if (!skb)
goto err_out;
- skb->dev = cp->dev;
skb_reserve(skb, RX_OFFSET);
mapping = pci_map_single(cp->pdev, skb->data, cp->rx_buf_sz,
PCI_DMA_FROMDEVICE);
- cp->rx_skb[i].skb = skb;
+ cp->rx_skb[i] = skb;
cp->rx_ring[i].opts2 = 0;
cp->rx_ring[i].addr = cpu_to_le64(mapping);
unsigned i;
for (i = 0; i < CP_RX_RING_SIZE; i++) {
- if (cp->rx_skb[i].skb) {
+ if (cp->rx_skb[i]) {
desc = cp->rx_ring + i;
pci_unmap_single(cp->pdev, le64_to_cpu(desc->addr),
cp->rx_buf_sz, PCI_DMA_FROMDEVICE);
- dev_kfree_skb(cp->rx_skb[i].skb);
+ dev_kfree_skb(cp->rx_skb[i]);
}
}
for (i = 0; i < CP_TX_RING_SIZE; i++) {
- if (cp->tx_skb[i].skb) {
- struct sk_buff *skb = cp->tx_skb[i].skb;
+ if (cp->tx_skb[i]) {
+ struct sk_buff *skb = cp->tx_skb[i];
desc = cp->tx_ring + i;
pci_unmap_single(cp->pdev, le64_to_cpu(desc->addr),
- cp->tx_skb[i].len, PCI_DMA_TODEVICE);
+ le32_to_cpu(desc->opts1) & 0xffff,
+ PCI_DMA_TODEVICE);
if (le32_to_cpu(desc->opts1) & LastFrag)
dev_kfree_skb(skb);
cp->net_stats.tx_dropped++;
memset(cp->rx_ring, 0, sizeof(struct cp_desc) * CP_RX_RING_SIZE);
memset(cp->tx_ring, 0, sizeof(struct cp_desc) * CP_TX_RING_SIZE);
- memset(&cp->rx_skb, 0, sizeof(struct ring_info) * CP_RX_RING_SIZE);
- memset(&cp->tx_skb, 0, sizeof(struct ring_info) * CP_TX_RING_SIZE);
+ memset(cp->rx_skb, 0, sizeof(struct sk_buff *) * CP_RX_RING_SIZE);
+ memset(cp->tx_skb, 0, sizeof(struct sk_buff *) * CP_TX_RING_SIZE);
}
static void cp_free_rings (struct cp_private *cp)
pci_free_consistent(cp->pdev, sizeof(*nic_stats), nic_stats, dma);
}
-static struct ethtool_ops cp_ethtool_ops = {
+static const struct ethtool_ops cp_ethtool_ops = {
.get_drvinfo = cp_get_drvinfo,
.get_regs_len = cp_get_regs_len,
.get_stats_count = cp_get_stats_count,
struct net_device *dev = pci_get_drvdata(pdev);
struct cp_private *cp = netdev_priv(dev);
- BUG_ON(!dev);
unregister_netdev(dev);
iounmap(cp->regs);
if (cp->wol_enabled)
#ifdef CONFIG_PM
static int cp_suspend (struct pci_dev *pdev, pm_message_t state)
{
- struct net_device *dev;
- struct cp_private *cp;
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct cp_private *cp = netdev_priv(dev);
unsigned long flags;
- dev = pci_get_drvdata (pdev);
- cp = netdev_priv(dev);
-
- if (!dev || !netif_running (dev)) return 0;
+ if (!netif_running(dev))
+ return 0;
netif_device_detach (dev);
netif_stop_queue (dev);
#ifdef MODULE
printk("%s", version);
#endif
- return pci_module_init (&cp_driver);
+ return pci_register_driver(&cp_driver);
}
static void __exit cp_exit (void)