#include "netxen_nic_phan_reg.h"
#include <linux/dma-mapping.h>
-#include <linux/vmalloc.h>
#include <net/ip.h>
MODULE_DESCRIPTION("NetXen Multi port (1/10) Gigabit Network Driver");
#define NETXEN_ADAPTER_UP_MAGIC 777
#define NETXEN_NIC_PEG_TUNE 0
-#define DMA_32BIT_MASK 0x00000000ffffffffULL
-#define DMA_35BIT_MASK 0x00000007ffffffffULL
-
/* Local functions to NetXen NIC driver */
static int __devinit netxen_nic_probe(struct pci_dev *pdev,
const struct pci_device_id *ent);
static void netxen_tx_timeout_task(struct work_struct *work);
static void netxen_watchdog(unsigned long);
static int netxen_handle_int(struct netxen_adapter *, struct net_device *);
-static int netxen_nic_poll(struct net_device *dev, int *budget);
+static int netxen_nic_poll(struct napi_struct *napi, int budget);
#ifdef CONFIG_NET_POLL_CONTROLLER
static void netxen_nic_poll_controller(struct net_device *netdev);
#endif
int valid_mac = 0;
u32 val;
int pci_func_id = PCI_FUNC(pdev->devfn);
+ DECLARE_MAC_BUF(mac);
printk(KERN_INFO "%s \n", netxen_nic_driver_string);
goto err_out_free_res;
}
- SET_MODULE_OWNER(netdev);
SET_NETDEV_DEV(netdev, &pdev->dev);
adapter = netdev->priv;
- memset(adapter, 0 , sizeof(struct netxen_adapter));
adapter->ahw.pdev = pdev;
adapter->ahw.pci_func = pci_func_id;
adapter->netdev = netdev;
adapter->pdev = pdev;
+ netif_napi_add(netdev, &adapter->napi,
+ netxen_nic_poll, NETXEN_NETDEV_WEIGHT);
+
/* this will be read from FW later */
adapter->intr_scheme = -1;
/* This will be reset for mezz cards */
adapter->portnum = pci_func_id;
adapter->status &= ~NETXEN_NETDEV_STATUS;
+ adapter->rx_csum = 1;
netdev->open = netxen_nic_open;
netdev->stop = netxen_nic_close;
netxen_nic_change_mtu(netdev, netdev->mtu);
SET_ETHTOOL_OPS(netdev, &netxen_nic_ethtool_ops);
- netdev->poll = netxen_nic_poll;
- netdev->weight = NETXEN_NETDEV_WEIGHT;
#ifdef CONFIG_NET_POLL_CONTROLLER
netdev->poll_controller = netxen_nic_poll_controller;
#endif
memcpy(netdev->perm_addr, netdev->dev_addr,
netdev->addr_len);
if (!is_valid_ether_addr(netdev->perm_addr)) {
- printk(KERN_ERR "%s: Bad MAC address "
- "%02x:%02x:%02x:%02x:%02x:%02x.\n",
- netxen_nic_driver_name,
- netdev->dev_addr[0],
- netdev->dev_addr[1],
- netdev->dev_addr[2],
- netdev->dev_addr[3],
- netdev->dev_addr[4],
- netdev->dev_addr[5]);
+ printk(KERN_ERR "%s: Bad MAC address %s.\n",
+ netxen_nic_driver_name,
+ print_mac(mac, netdev->dev_addr));
} else {
if (adapter->macaddr_set)
adapter->macaddr_set(adapter,
unregister_netdev(netdev);
- if (adapter->stop_port)
- adapter->stop_port(adapter);
-
- netxen_nic_disable_int(adapter);
-
if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) {
init_firmware_done++;
netxen_free_hw_resources(adapter);
if (!adapter->driver_mismatch)
mod_timer(&adapter->watchdog_timer, jiffies);
+ napi_enable(&adapter->napi);
+
netxen_nic_enable_int(adapter);
/* Done here again so that even if phantom sw overwrote it,
del_timer_sync(&adapter->watchdog_timer);
printk(KERN_ERR "%s: Failed to initialize port %d\n",
netxen_nic_driver_name, adapter->portnum);
+ napi_disable(&adapter->napi);
return -EIO;
}
if (adapter->macaddr_set)
netif_carrier_off(netdev);
netif_stop_queue(netdev);
+ napi_disable(&adapter->napi);
+
+ if (adapter->stop_port)
+ adapter->stop_port(adapter);
netxen_nic_disable_int(adapter);
return NETDEV_TX_OK;
}
- /*
- * Everything is set up. Now, we just need to transmit it out.
- * Note that we have to copy the contents of buffer over to
- * right place. Later on, this can be optimized out by de-coupling the
- * producer index from the buffer index.
- */
- retry_getting_window:
- spin_lock_bh(&adapter->tx_lock);
- if (adapter->total_threads >= MAX_XMIT_PRODUCERS) {
- spin_unlock_bh(&adapter->tx_lock);
- /*
- * Yield CPU
- */
- if (!in_atomic())
- schedule();
- else {
- for (i = 0; i < 20; i++)
- cpu_relax(); /*This a nop instr on i386 */
- }
- goto retry_getting_window;
- }
- local_producer = adapter->cmd_producer;
/* There 4 fragments per descriptor */
no_of_desc = (frag_count + 3) >> 2;
if (netdev->features & NETIF_F_TSO) {
}
}
}
+
+ spin_lock_bh(&adapter->tx_lock);
+ if (adapter->total_threads >= MAX_XMIT_PRODUCERS) {
+ goto out_requeue;
+ }
+ local_producer = adapter->cmd_producer;
k = adapter->cmd_producer;
max_tx_desc_count = adapter->max_tx_desc_count;
last_cmd_consumer = adapter->last_cmd_consumer;
if ((k + no_of_desc) >=
((last_cmd_consumer <= k) ? last_cmd_consumer + max_tx_desc_count :
last_cmd_consumer)) {
- netif_stop_queue(netdev);
- adapter->flags |= NETXEN_NETDEV_STATUS;
- spin_unlock_bh(&adapter->tx_lock);
- return NETDEV_TX_BUSY;
+ goto out_requeue;
}
k = get_index_range(k, max_tx_desc_count, no_of_desc);
adapter->cmd_producer = k;
adapter->max_tx_desc_count);
hwdesc = &hw->cmd_desc_head[producer];
memset(hwdesc, 0, sizeof(struct cmd_desc_type0));
+ pbuf = &adapter->cmd_buf_arr[producer];
+ pbuf->skb = NULL;
}
frag = &skb_shinfo(skb)->frags[i - 1];
len = frag->size;
}
/* copy the MAC/IP/TCP headers to the cmd descriptor list */
hwdesc = &hw->cmd_desc_head[producer];
+ pbuf = &adapter->cmd_buf_arr[producer];
+ pbuf->skb = NULL;
/* copy the first 64 bytes */
memcpy(((void *)hwdesc) + 2,
if (more_hdr) {
hwdesc = &hw->cmd_desc_head[producer];
+ pbuf = &adapter->cmd_buf_arr[producer];
+ pbuf->skb = NULL;
/* copy the next 64 bytes - should be enough except
* for pathological case
*/
}
}
- i = netxen_get_cmd_desc_totallength(&hw->cmd_desc_head[saved_producer]);
-
- hw->cmd_desc_head[saved_producer].flags_opcode =
- cpu_to_le16(hw->cmd_desc_head[saved_producer].flags_opcode);
- hw->cmd_desc_head[saved_producer].num_of_buffers_total_length =
- cpu_to_le32(hw->cmd_desc_head[saved_producer].
- num_of_buffers_total_length);
-
spin_lock_bh(&adapter->tx_lock);
- adapter->stats.txbytes += i;
+ adapter->stats.txbytes += skb->len;
/* Code to update the adapter considering how many producer threads
are currently working */
}
adapter->stats.xmitfinished++;
- spin_unlock_bh(&adapter->tx_lock);
-
netdev->trans_start = jiffies;
- DPRINTK(INFO, "wrote CMD producer %x to phantom\n", producer);
-
- DPRINTK(INFO, "Done. Send\n");
+ spin_unlock_bh(&adapter->tx_lock);
return NETDEV_TX_OK;
+
+out_requeue:
+ netif_stop_queue(netdev);
+ adapter->flags |= NETXEN_NETDEV_STATUS;
+
+ spin_unlock_bh(&adapter->tx_lock);
+ return NETDEV_TX_BUSY;
}
static void netxen_watchdog(unsigned long v)
netxen_nic_disable_int(adapter);
if (netxen_nic_rx_has_work(adapter) || netxen_nic_tx_has_work(adapter)) {
- if (netif_rx_schedule_prep(netdev)) {
+ if (netif_rx_schedule_prep(netdev, &adapter->napi)) {
/*
* Interrupts are already disabled.
*/
- __netif_rx_schedule(netdev);
+ __netif_rx_schedule(netdev, &adapter->napi);
} else {
static unsigned int intcount = 0;
if ((++intcount & 0xfff) == 0xfff)
*/
irqreturn_t netxen_intr(int irq, void *data)
{
- struct netxen_adapter *adapter;
- struct net_device *netdev;
+ struct netxen_adapter *adapter = data;
+ struct net_device *netdev = adapter->netdev;
u32 our_int = 0;
- if (unlikely(!irq)) {
- return IRQ_NONE; /* Not our interrupt */
- }
-
- adapter = (struct netxen_adapter *)data;
- netdev = adapter->netdev;
-
if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
our_int = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR));
/* not our interrupt */
return IRQ_HANDLED;
}
-static int netxen_nic_poll(struct net_device *netdev, int *budget)
+static int netxen_nic_poll(struct napi_struct *napi, int budget)
{
- struct netxen_adapter *adapter = netdev_priv(netdev);
- int work_to_do = min(*budget, netdev->quota);
+ struct netxen_adapter *adapter = container_of(napi, struct netxen_adapter, napi);
+ struct net_device *netdev = adapter->netdev;
int done = 1;
int ctx;
- int this_work_done;
- int work_done = 0;
+ int work_done;
DPRINTK(INFO, "polling for %d descriptors\n", *budget);
* packets are on one context, it gets only half of the quota,
* and ends up not processing it.
*/
- this_work_done = netxen_process_rcv_ring(adapter, ctx,
- work_to_do /
- MAX_RCV_CTX);
- work_done += this_work_done;
+ work_done += netxen_process_rcv_ring(adapter, ctx,
+ budget / MAX_RCV_CTX);
}
- netdev->quota -= work_done;
- *budget -= work_done;
-
- if (work_done >= work_to_do && netxen_nic_rx_has_work(adapter) != 0)
+ if (work_done >= budget)
done = 0;
if (netxen_process_cmd_ring((unsigned long)adapter) == 0)
DPRINTK(INFO, "new work_done: %d work_to_do: %d\n",
work_done, work_to_do);
if (done) {
- netif_rx_complete(netdev);
+ netif_rx_complete(netdev, napi);
netxen_nic_enable_int(adapter);
}
- return !done;
+ return work_done;
}
#ifdef CONFIG_NET_POLL_CONTROLLER