*/
#include <linux/crc32.h>
#include <linux/ethtool.h>
+#include <linux/gfp.h>
#include <linux/mii.h>
#include <linux/mutex.h>
#define ipg_r16(reg) ioread16(ioaddr + (reg))
#define ipg_r8(reg) ioread8(ioaddr + (reg))
-#define JUMBO_FRAME_4k_ONLY
enum {
netdev_io_size = 128
};
MODULE_LICENSE("GPL");
/*
+ * Defaults
+ */
+#define IPG_MAX_RXFRAME_SIZE 0x0600
+#define IPG_RXFRAG_SIZE 0x0600
+#define IPG_RXSUPPORT_SIZE 0x0600
+#define IPG_IS_JUMBO false
+
+/*
* Variable record -- index by leading revision/length
* Revision/Length(=N*4), Address1, Data1, Address2, Data2,...,AddressN,DataN
*/
"Sundance Technology ST2021 based NIC",
"Tamarack Microelectronics TC9020/9021 based NIC",
"Tamarack Microelectronics TC9020/9021 based NIC",
- "D-Link NIC",
"D-Link NIC IP1000A"
};
-static struct pci_device_id ipg_pci_tbl[] __devinitdata = {
+static DEFINE_PCI_DEVICE_TABLE(ipg_pci_tbl) = {
{ PCI_VDEVICE(SUNDANCE, 0x1023), 0 },
{ PCI_VDEVICE(SUNDANCE, 0x2021), 1 },
{ PCI_VDEVICE(SUNDANCE, 0x1021), 2 },
{ PCI_VDEVICE(DLINK, 0x9021), 3 },
- { PCI_VDEVICE(DLINK, 0x4000), 4 },
- { PCI_VDEVICE(DLINK, 0x4020), 5 },
+ { PCI_VDEVICE(DLINK, 0x4020), 4 },
{ 0, }
};
receivemode = IPG_RM_RECEIVEALLFRAMES;
} else if ((dev->flags & IFF_ALLMULTI) ||
((dev->flags & IFF_MULTICAST) &&
- (dev->mc_count > IPG_MULTICAST_HASHTABLE_SIZE))) {
+ (netdev_mc_count(dev) > IPG_MULTICAST_HASHTABLE_SIZE))) {
/* NIC to be configured to receive all multicast
* frames. */
receivemode |= IPG_RM_RECEIVEMULTICAST;
- } else if ((dev->flags & IFF_MULTICAST) && (dev->mc_count > 0)) {
+ } else if ((dev->flags & IFF_MULTICAST) && !netdev_mc_empty(dev)) {
/* NIC to be configured to receive selected
* multicast addresses. */
receivemode |= IPG_RM_RECEIVEMULTICASTHASH;
hashtable[1] = 0x00000000;
/* Cycle through all multicast addresses to filter. */
- for (mc_list_ptr = dev->mc_list;
- mc_list_ptr != NULL; mc_list_ptr = mc_list_ptr->next) {
+ netdev_for_each_mc_addr(mc_list_ptr, dev) {
/* Calculate CRC result for each multicast address. */
hashindex = crc32_le(0xffffffff, mc_list_ptr->dmi_addr,
ETH_ALEN);
static int ipg_io_config(struct net_device *dev)
{
+ struct ipg_nic_private *sp = netdev_priv(dev);
void __iomem *ioaddr = ipg_ioaddr(dev);
u32 origmacctrl;
u32 restoremacctrl;
/* Set RECEIVEMODE register. */
ipg_nic_set_multicast_list(dev);
- ipg_w16(IPG_MAX_RXFRAME_SIZE, MAX_FRAME_SIZE);
+ ipg_w16(sp->max_rxframe_size, MAX_FRAME_SIZE);
ipg_w8(IPG_RXDMAPOLLPERIOD_VALUE, RX_DMA_POLL_PERIOD);
ipg_w8(IPG_RXDMAURGENTTHRESH_VALUE, RX_DMA_URGENT_THRESH);
IPG_DEBUG_MSG("_get_rxbuff\n");
- skb = netdev_alloc_skb(dev, IPG_RXSUPPORT_SIZE + NET_IP_ALIGN);
+ skb = netdev_alloc_skb_ip_align(dev, sp->rxsupport_size);
if (!skb) {
sp->rx_buff[entry] = NULL;
return -ENOMEM;
}
- /* Adjust the data start location within the buffer to
- * align IP address field to a 16 byte boundary.
- */
- skb_reserve(skb, NET_IP_ALIGN);
-
/* Associate the receive buffer with the IPG NIC. */
skb->dev = dev;
struct ipg_rx *rxfd = sp->rxd + entry;
pci_unmap_single(sp->pdev,
- le64_to_cpu(rxfd->frag_info & ~IPG_RFI_FRAGLEN),
+ le64_to_cpu(rxfd->frag_info) & ~IPG_RFI_FRAGLEN,
sp->rx_buf_sz, PCI_DMA_FROMDEVICE);
dev_kfree_skb_irq(sp->rx_buff[entry]);
sp->rx_buff[entry] = NULL;
*/
if (sp->rx_buff[entry]) {
pci_unmap_single(sp->pdev,
- le64_to_cpu(rxfd->frag_info & ~IPG_RFI_FRAGLEN),
+ le64_to_cpu(rxfd->frag_info) & ~IPG_RFI_FRAGLEN,
sp->rx_buf_sz, PCI_DMA_FROMDEVICE);
dev_kfree_skb_irq(sp->rx_buff[entry]);
skb->protocol = eth_type_trans(skb, dev);
skb->ip_summed = CHECKSUM_NONE;
netif_rx(skb);
- dev->last_rx = jiffies;
sp->rx_buff[entry] = NULL;
}
if (jumbo->found_start)
dev_kfree_skb_irq(jumbo->skb);
- pci_unmap_single(pdev, le64_to_cpu(rxfd->frag_info & ~IPG_RFI_FRAGLEN),
+ pci_unmap_single(pdev, le64_to_cpu(rxfd->frag_info) & ~IPG_RFI_FRAGLEN,
sp->rx_buf_sz, PCI_DMA_FROMDEVICE);
skb_put(skb, sp->rxfrag_size);
jumbo->skb = skb;
sp->rx_buff[entry] = NULL;
- dev->last_rx = jiffies;
}
static void ipg_nic_rx_with_end(struct net_device *dev,
framelen = le64_to_cpu(rxfd->rfs) & IPG_RFS_RXFRAMELEN;
endframelen = framelen - jumbo->current_size;
- if (framelen > IPG_RXSUPPORT_SIZE)
+ if (framelen > sp->rxsupport_size)
dev_kfree_skb_irq(jumbo->skb);
else {
memcpy(skb_put(jumbo->skb, endframelen),
}
}
- dev->last_rx = jiffies;
jumbo->found_start = 0;
jumbo->current_size = 0;
jumbo->skb = NULL;
if (skb) {
if (jumbo->found_start) {
jumbo->current_size += sp->rxfrag_size;
- if (jumbo->current_size <= IPG_RXSUPPORT_SIZE) {
+ if (jumbo->current_size <= sp->rxsupport_size) {
memcpy(skb_put(jumbo->skb,
sp->rxfrag_size),
skb->data, sp->rxfrag_size);
}
}
- dev->last_rx = jiffies;
ipg_nic_rx_free_skb(dev);
}
} else {
unsigned int entry = curr % IPG_RFDLIST_LENGTH;
struct ipg_rx *rxfd = sp->rxd + entry;
- if (!(rxfd->rfs & le64_to_cpu(IPG_RFS_RFDDONE)))
+ if (!(rxfd->rfs & cpu_to_le64(IPG_RFS_RFDDONE)))
break;
switch (ipg_nic_rx_check_frame_type(dev)) {
* when processing completes.
*/
netif_rx(skb);
-
- /* Record frame receive time (jiffies = Linux
- * kernel current time stamp).
- */
- dev->last_rx = jiffies;
}
/* Assure RX buffer is not reused by IPG. */
IPG_DEBUG_MSG("_nic_open\n");
- sp->rx_buf_sz = IPG_RXSUPPORT_SIZE;
+ sp->rx_buf_sz = sp->rxsupport_size;
/* Check for interrupt line conflicts, and request interrupt
* line for IPG.
/* Register the interrupt line to be used by the IPG within
* the Linux system.
*/
- rc = request_irq(pdev->irq, &ipg_interrupt_handler, IRQF_SHARED,
+ rc = request_irq(pdev->irq, ipg_interrupt_handler, IRQF_SHARED,
dev->name, dev);
if (rc < 0) {
printk(KERN_INFO "%s: Error when requesting interrupt.\n",
sp->jumbo.current_size = 0;
sp->jumbo.skb = NULL;
- if (IPG_TXFRAG_SIZE)
- dev->mtu = IPG_TXFRAG_SIZE;
-
/* Enable transmit and receive operation of the IPG. */
ipg_w32((ipg_r32(MAC_CTRL) | IPG_MC_RX_ENABLE | IPG_MC_TX_ENABLE) &
IPG_MC_RSVD_MASK, MAC_CTRL);
return 0;
}
-static int ipg_nic_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t ipg_nic_hard_start_xmit(struct sk_buff *skb,
+ struct net_device *dev)
{
struct ipg_nic_private *sp = netdev_priv(dev);
void __iomem *ioaddr = sp->ioaddr;
static int ipg_nic_change_mtu(struct net_device *dev, int new_mtu)
{
+ struct ipg_nic_private *sp = netdev_priv(dev);
+ int err;
+
/* Function to accomodate changes to Maximum Transfer Unit
* (or MTU) of IPG NIC. Cannot use default function since
* the default will not allow for MTU > 1500 bytes.
IPG_DEBUG_MSG("_nic_change_mtu\n");
- /* Check that the new MTU value is between 68 (14 byte header, 46
- * byte payload, 4 byte FCS) and IPG_MAX_RXFRAME_SIZE, which
- * corresponds to the MAXFRAMESIZE register in the IPG.
+ /*
+ * Check that the new MTU value is between 68 (14 byte header, 46 byte
+ * payload, 4 byte FCS) and 10 KB, which is the largest supported MTU.
*/
- if ((new_mtu < 68) || (new_mtu > IPG_MAX_RXFRAME_SIZE))
+ if (new_mtu < 68 || new_mtu > 10240)
return -EINVAL;
+ err = ipg_nic_stop(dev);
+ if (err)
+ return err;
+
dev->mtu = new_mtu;
- return 0;
+ sp->max_rxframe_size = new_mtu;
+
+ sp->rxfrag_size = new_mtu;
+ if (sp->rxfrag_size > 4088)
+ sp->rxfrag_size = 4088;
+
+ sp->rxsupport_size = sp->max_rxframe_size;
+
+ if (new_mtu > 0x0600)
+ sp->is_jumbo = true;
+ else
+ sp->is_jumbo = false;
+
+ return ipg_nic_open(dev);
}
static int ipg_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
return rc;
}
-static struct ethtool_ops ipg_ethtool_ops = {
+static const struct ethtool_ops ipg_ethtool_ops = {
.get_settings = ipg_get_settings,
.set_settings = ipg_set_settings,
.nway_reset = ipg_nway_reset,
pci_set_drvdata(pdev, NULL);
}
+static const struct net_device_ops ipg_netdev_ops = {
+ .ndo_open = ipg_nic_open,
+ .ndo_stop = ipg_nic_stop,
+ .ndo_start_xmit = ipg_nic_hard_start_xmit,
+ .ndo_get_stats = ipg_nic_get_stats,
+ .ndo_set_multicast_list = ipg_nic_set_multicast_list,
+ .ndo_do_ioctl = ipg_ioctl,
+ .ndo_tx_timeout = ipg_tx_timeout,
+ .ndo_change_mtu = ipg_nic_change_mtu,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+};
+
static int __devinit ipg_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
pci_set_master(pdev);
- rc = pci_set_dma_mask(pdev, DMA_40BIT_MASK);
+ rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(40));
if (rc < 0) {
- rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
if (rc < 0) {
printk(KERN_ERR "%s: DMA config failed.\n",
pci_name(pdev));
spin_lock_init(&sp->lock);
mutex_init(&sp->mii_mutex);
- sp->is_jumbo = IPG_JUMBO;
+ sp->is_jumbo = IPG_IS_JUMBO;
sp->rxfrag_size = IPG_RXFRAG_SIZE;
+ sp->rxsupport_size = IPG_RXSUPPORT_SIZE;
+ sp->max_rxframe_size = IPG_MAX_RXFRAME_SIZE;
/* Declare IPG NIC functions for Ethernet device methods.
*/
- dev->open = &ipg_nic_open;
- dev->stop = &ipg_nic_stop;
- dev->hard_start_xmit = &ipg_nic_hard_start_xmit;
- dev->get_stats = &ipg_nic_get_stats;
- dev->set_multicast_list = &ipg_nic_set_multicast_list;
- dev->do_ioctl = ipg_ioctl;
- dev->tx_timeout = ipg_tx_timeout;
- dev->change_mtu = &ipg_nic_change_mtu;
-
+ dev->netdev_ops = &ipg_netdev_ops;
SET_NETDEV_DEV(dev, &pdev->dev);
SET_ETHTOOL_OPS(dev, &ipg_ethtool_ops);