Hi Joonwoo and Adam,
 
I tested your patches with the latest e1000 driver, for which I just created 
the patch to support Click polling, (it seemed easier to patch this latest 
driver than to fix the patch of the version 7.3.20). So, PollDevice now works, 
although there is an assertion issue when I install or uninstall a script, but 
apart from that packet forwarding seems to be stable. I'll trace this assertion 
problem...
 
I also tested Click multithreading, which also worked, but somehow all the 8 
cores I have in the machine seem to be busy (not all at 100%) even though I 
only have 6 Click threads. However, when I manually assign the threads each to 
a separate core, only 6 cores seem to be loaded (which is normal), so this 
might be somehow related to the Linux scheduler. Do you know whether they have 
changed anything in the Linux scheduler that makes this behaviour normal or the 
click patch is more likely to be incomplete? The performances look alright in 
both cases, at least with that single configuration I've tested so far.
 
If somebody could test the driver patch in his/her system and let me know how 
it works, that would be great.
 
Thanks,
Norbert

________________________________

From: [EMAIL PROTECTED] on behalf of Joonwoo Park
Sent: Tue 2/5/2008 08:11
To: [EMAIL PROTECTED]
Subject: [Click] [PATCH] patches for linux 2.6.24



Hi,
This is a version of click for the 2.6.24 linux.
Lots of the work was done by Adam Greenhalgh and I just peppered on it.
This is a very raw version, I think much more fix might be needed.

I didn't work for e1000 and platforms except the x86-32.
fyi, I'm attaching my config for linux

things tested (a few):
 build & install on my x86 laptop (thinkpad t60)
 simple FromDevice
 simple ToDevice

Thanks,
Joonwoo


diff -Naur e1000-7.6.15.orig/src/Makefile e1000-7.6.15/src/Makefile
--- e1000-7.6.15.orig/src/Makefile      2007-12-11 23:26:45.000000000 +0000
+++ e1000-7.6.15/src/Makefile   2008-02-07 15:49:53.000000000 +0000
@@ -164,7 +164,7 @@
             echo "-DMODVERSIONS -DEXPORT_SYMTAB \
                   -include $(KSRC)/include/linux/modversions.h")
 
-EXTRA_CFLAGS += $(CFLAGS_EXTRA)
+EXTRA_CFLAGS += -DCONFIG_E1000_NAPI $(CFLAGS_EXTRA)
 
 RHC := $(KSRC)/include/linux/rhconfig.h
 ifneq (,$(wildcard $(RHC)))
diff -Naur e1000-7.6.15.orig/src/e1000.h e1000-7.6.15/src/e1000.h
--- e1000-7.6.15.orig/src/e1000.h       2007-12-11 23:26:45.000000000 +0000
+++ e1000-7.6.15/src/e1000.h    2008-02-07 15:49:53.000000000 +0000
@@ -63,10 +63,10 @@
 #define E1000_MIN_TXD                       80
 #define E1000_MAX_82544_TXD               4096
 
-#define E1000_DEFAULT_RXD                  256
+#define E1000_DEFAULT_RXD                   64
 #define E1000_MAX_RXD                      256
 
-#define E1000_MIN_RXD                       80
+#define E1000_MIN_RXD                       64
 #define E1000_MAX_82544_RXD               4096
 
 #define E1000_MIN_ITR_USECS                 10 /* 100000 irq/sec */
@@ -225,6 +225,11 @@
 #define E1000_TX_DESC(R, i)            E1000_GET_DESC(R, i, e1000_tx_desc)
 #define E1000_CONTEXT_DESC(R, i)       E1000_GET_DESC(R, i, e1000_context_desc)
 
+#define E1000_RX_STATE_NORMAL 0
+#define E1000_RX_STATE_QUIET  1
+#define E1000_RX_STATE_LOCKUP 2
+
+
 #ifdef SIOCGMIIPHY
 /* PHY register snapshot values */
 struct e1000_phy_regs {
@@ -370,6 +375,15 @@
        /* hardware capability, feature, and workaround flags */
        unsigned int flags;
 
+       int do_poll_watchdog; /* Click polling */
+       
+       /* Receive Lockup detection and recovery */
+       int rx_state;                   /* can be either: NORMAL, QUIET, LOCKUP 
*/
+       int rx_lockup_recoveries;       /* # of times the recovery seq is 
invoked */
+       unsigned long rx_normal_jiffies;                /* jiffies timeout for 
the NORMAL state */
+       unsigned long rx_quiet_jiffies;         /* jiffies timeout for the 
QUIET state */
+       int prev_rdfh;                  /* prev value of Rcv Data Fifo Head 
register */
+       int prev_rdft;                  /* prev value of Rcv Data Fifo Tail 
register */
 };
 
 #define E1000_FLAG_HAS_SMBUS                (1 << 0)
diff -Naur e1000-7.6.15.orig/src/e1000_main.c e1000-7.6.15/src/e1000_main.c
--- e1000-7.6.15.orig/src/e1000_main.c  2007-12-11 23:26:45.000000000 +0000
+++ e1000-7.6.15/src/e1000_main.c       2008-02-07 17:06:54.000000000 +0000
@@ -188,6 +188,8 @@
 static void e1000_set_multi(struct net_device *netdev);
 static void e1000_update_phy_info(unsigned long data);
 static void e1000_watchdog(unsigned long data);
+static void e1000_watchdog_1(struct e1000_adapter *adapter);
+
 static void e1000_watchdog_task(struct work_struct *work);
 static void e1000_82547_tx_fifo_stall(unsigned long data);
 static int e1000_xmit_frame_ring(struct sk_buff *skb, struct net_device 
*netdev,
@@ -267,11 +269,28 @@
 };
 #endif
 
+/* For Click polling */
+static int e1000_tx_pqueue(struct net_device *dev, struct sk_buff *skb);
+static int e1000_tx_start(struct net_device *dev);
+static int e1000_rx_refill(struct net_device *dev, struct sk_buff **);
+static int e1000_tx_eob(struct net_device *dev);
+static struct sk_buff *e1000_tx_clean(struct net_device *dev);
+static struct sk_buff *e1000_rx_poll(struct net_device *dev, int *want);
+static int e1000_poll_on(struct net_device *dev);
+static int e1000_poll_off(struct net_device *dev);
+
 #ifdef CONFIG_NET_POLL_CONTROLLER
 /* for netdump / net console */
 static void e1000_netpoll (struct net_device *netdev);
 #endif
 
+#undef DEBUG_PRINT
+#ifdef DEBUG_PRINT
+static void e1000_print_rx_buffer_info(struct e1000_buffer *bi);
+static void e1000_print_rx_desc(struct e1000_rx_desc *rx_desc);
+static void e1000_print_skb(struct sk_buff* skb);
+#endif
+
 #define COPYBREAK_DEFAULT 256
 static unsigned int copybreak __read_mostly = COPYBREAK_DEFAULT;
 module_param(copybreak, uint, 0644);
@@ -331,6 +350,7 @@
        printk(KERN_INFO "%s - version %s\n",
               e1000_driver_string, e1000_driver_version);
 
+        printk(KERN_INFO " w/ Click polling\n");
        printk(KERN_INFO "%s\n", e1000_copyright);
 
        ret = pci_register_driver(&e1000_driver);
@@ -929,6 +949,9 @@
  * The OS initialization, configuring of the adapter private structure,
  * and a hardware reset occur.
  **/
+
+#define SHOW_INTERFACE(d) printk("Interface mac_type=%d\n", d->hw.mac.type)
+
 static int __devinit e1000_probe(struct pci_dev *pdev,
                                  const struct pci_device_id *ent)
 {
@@ -981,6 +1004,7 @@
        adapter->msg_enable = (1 << debug) - 1;
 
        err = -EIO;
+       SHOW_INTERFACE(adapter);
        adapter->hw.hw_addr = ioremap(pci_resource_start(pdev, BAR_0),
                                      pci_resource_len(pdev, BAR_0));
        if (!adapter->hw.hw_addr)
@@ -1016,6 +1040,18 @@
        netdev->vlan_rx_add_vid = e1000_vlan_rx_add_vid;
        netdev->vlan_rx_kill_vid = e1000_vlan_rx_kill_vid;
 #endif
+
+        /* Click - polling extensions */
+        netdev->polling = 0;
+        netdev->rx_poll = e1000_rx_poll;
+        netdev->rx_refill = e1000_rx_refill;
+        netdev->tx_queue = e1000_tx_pqueue;
+        netdev->tx_eob = e1000_tx_eob;
+        netdev->tx_start = e1000_tx_start;
+        netdev->tx_clean = e1000_tx_clean;
+        netdev->poll_off = e1000_poll_off;
+        netdev->poll_on = e1000_poll_on;
+
 #ifdef CONFIG_NET_POLL_CONTROLLER
        netdev->poll_controller = e1000_netpoll;
 #endif
@@ -1145,6 +1181,7 @@
        if (e1000_read_mac_addr(&adapter->hw))
                DPRINTK(PROBE, ERR, "NVM Read Error\n");
        memcpy(netdev->dev_addr, adapter->hw.mac.addr, netdev->addr_len);
+       SHOW_INTERFACE(adapter);
 #ifdef ETHTOOL_GPERMADDR
        memcpy(netdev->perm_addr, adapter->hw.mac.addr, netdev->addr_len);
 
@@ -2947,6 +2984,19 @@
 {
        struct e1000_adapter *adapter = container_of(work,
                                        struct e1000_adapter, watchdog_task);
+       if(adapter->netdev->polling){
+           adapter->do_poll_watchdog = 1;
+       } else {
+           e1000_watchdog_1(adapter);
+       }
+
+       if (!test_bit(__E1000_DOWN, &adapter->state))
+               mod_timer(&adapter->watchdog_timer, round_jiffies(jiffies + 2 * 
HZ));
+}
+
+static void
+e1000_watchdog_1(struct e1000_adapter *adapter)
+{
 
        struct net_device *netdev = adapter->netdev;
        struct e1000_mac_info *mac = &adapter->hw.mac;
@@ -3130,10 +3180,6 @@
         * reset from the other port. Set the appropriate LAA in RAR[0] */
        if (e1000_get_laa_state_82571(&adapter->hw) == TRUE)
                e1000_rar_set(&adapter->hw, adapter->hw.mac.addr, 0);
-
-       /* Reset the timer */
-       if (!test_bit(__E1000_DOWN, &adapter->state))
-               mod_timer(&adapter->watchdog_timer, round_jiffies(jiffies + 2 * 
HZ));
 }
 
 enum latency_range {
@@ -6270,5 +6316,455 @@
 
        kfree(hw->dev_spec);
 }
+ 
+/* Click polling support */
+
+static struct sk_buff *
+e1000_rx_poll(struct net_device *dev, int *want)
+{
+  struct e1000_adapter *adapter = dev->priv;
+  struct pci_dev *pdev = adapter->pdev;
+  struct e1000_rx_desc *rx_desc;
+  struct e1000_rx_ring *rx_ring = adapter->rx_ring;
+  struct sk_buff *skb_head = NULL, **skb;
+  uint32_t length;
+  int got, next;
+
+  skb = &skb_head;
+
+  for( got = 0, next = (rx_ring->next_to_clean + 1) % rx_ring->count;
+       got < *want && next != rx_ring->next_to_use;
+       got++, rx_ring->next_to_clean = next,
+        next = (rx_ring->next_to_clean + 1) % rx_ring->count) {
+
+    int i = rx_ring->next_to_clean;
+    rx_desc = E1000_RX_DESC(*rx_ring, i);
+    if(!(rx_desc->status & E1000_RXD_STAT_DD))
+      break;
+
+    pci_unmap_single(pdev, rx_ring->buffer_info[i].dma,
+                    adapter->rx_buffer_len,
+                    PCI_DMA_FROMDEVICE);
+
+    *skb = rx_ring->buffer_info[i].skb;
+    rx_ring->buffer_info[i].skb = NULL;
+    
+    if(!(rx_desc->status & E1000_RXD_STAT_EOP) ||
+       (rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) {
+      rx_desc->status = 0;
+      dev_kfree_skb(*skb);
+      *skb = NULL;
+      got--;
+      continue;
+    }
+    rx_desc->status = 0;
+
+    length = le16_to_cpu(rx_desc->length);
+    skb_put(*skb, length - ETHERNET_FCS_SIZE);
+    e1000_rx_checksum(adapter, 
+                     (uint32_t)(rx_desc->status) | 
((uint32_t)(rx_desc->errors) << 24),
+                     rx_desc->csum, *skb);
+    skb_pull(*skb, dev->hard_header_len);
+    
+    skb = &((*skb)->next);
+    *skb = NULL;
+  }
+
+  *want = got;
+
+  /* 
+   *  Receive Lockup detection and recovery
+   */
+  if (got) {
+    adapter->rx_state = E1000_RX_STATE_NORMAL;
+    adapter->rx_normal_jiffies = jiffies + HZ;
+  } else {
+    int rdfh;
+    int rdft;
+    switch (adapter->rx_state) {
+    case E1000_RX_STATE_NORMAL:
+      if (jiffies < adapter->rx_normal_jiffies)
+        break;
+      adapter->rx_state = E1000_RX_STATE_QUIET;
+      adapter->rx_quiet_jiffies = jiffies + HZ;
+      adapter->prev_rdfh = E1000_READ_REG(&adapter->hw, E1000_RDH(1));
+      adapter->prev_rdft = E1000_READ_REG(&adapter->hw, E1000_RDT(1));
+      break;
+    case E1000_RX_STATE_QUIET:
+      rdfh = E1000_READ_REG(&adapter->hw, E1000_RDH(1));
+      rdft = E1000_READ_REG(&adapter->hw, E1000_RDT(1));
+      if (adapter->prev_rdfh != rdfh ||
+          adapter->prev_rdft != rdft ||
+          adapter->prev_rdfh == adapter->prev_rdft) {
+        adapter->prev_rdfh = rdfh;
+        adapter->prev_rdft = rdft;
+        adapter->rx_quiet_jiffies = jiffies + HZ;
+        break;
+      }
+      if (jiffies < adapter->rx_quiet_jiffies)
+        break;
+      /* Fall into the lockup case */
+    case E1000_RX_STATE_LOCKUP:
+      /* Receive lockup detected: perform a recovery */
+      adapter->rx_lockup_recoveries++;
+      /* taken from e1000_down() */
+      e1000_reset(adapter);
+      e1000_clean_tx_ring(adapter, adapter->tx_ring);
+      e1000_clean_rx_ring(adapter, adapter->rx_ring);
+      /* taken from e1000_up() */
+      e1000_set_multi(dev);
+      e1000_configure_tx(adapter);
+      e1000_setup_rctl(adapter);
+      e1000_configure_rx(adapter);
+      e1000_alloc_rx_buffers(adapter, adapter->rx_ring,
+                            E1000_DESC_UNUSED(adapter->rx_ring));
+      /* reset the lockup detection */
+      adapter->rx_state = E1000_RX_STATE_NORMAL;
+      adapter->rx_normal_jiffies = jiffies + HZ;
+      break;
+    }
+  }
+
+  return skb_head;
+}
+
+int
+e1000_rx_refill(struct net_device *dev, struct sk_buff **skbs)
+{
+  struct e1000_adapter *adapter = dev->priv;
+  struct e1000_rx_ring *rx_ring = adapter->rx_ring;
+  struct pci_dev *pdev = adapter->pdev;
+  struct e1000_rx_desc *rx_desc;
+  struct sk_buff *skb;
+  int next;
+
+  /*
+   * Update statistics counters, check link.
+   * do_poll_watchdog is set by the timer interrupt e1000_watchdog(),
+   * but we don't want to do the work in an interrupt (since it may
+   * happen while polling code is active), so defer it to here.
+   */
+  if(adapter->do_poll_watchdog){
+    adapter->do_poll_watchdog = 0;
+    e1000_watchdog_1(adapter);
+  }
+
+  if (!netif_carrier_ok(dev))
+    return 0;
+
+  if(skbs == 0)
+    return E1000_DESC_UNUSED(rx_ring);
+
+  for( next = (rx_ring->next_to_use + 1) % rx_ring->count;
+       next != rx_ring->next_to_clean;
+       rx_ring->next_to_use = next,
+        next = (rx_ring->next_to_use + 1) % rx_ring->count ) {
+    int i = rx_ring->next_to_use;
+    if(rx_ring->buffer_info[i].skb != NULL)
+      break;
+    
+    if(!(skb = *skbs))
+      break;
+    *skbs = skb->next;
+    skb->next = NULL;
+    skb->dev = dev;
+    
+    rx_ring->buffer_info[i].skb = skb;
+//    rx_ring->buffer_info[i].length = adapter->rx_buffer_len;
+    rx_ring->buffer_info[i].dma =
+      pci_map_single(pdev,
+                    skb->data,
+                    adapter->rx_buffer_len,
+                    PCI_DMA_FROMDEVICE);
+
+    rx_desc = E1000_RX_DESC(*rx_ring, i);
+    rx_desc->buffer_addr = cpu_to_le64(rx_ring->buffer_info[i].dma);
+    
+    /* Intel documnetation says: "Software adds receive descriptors by
+     * writing the tail pointer with the index of the entry beyond the
+     * last valid descriptor." (ref 11337 p 27) */
+
+    E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), next);
+  }
+  
+  return E1000_DESC_UNUSED(adapter->rx_ring);
+}
+
+static int
+e1000_tx_pqueue(struct net_device *netdev, struct sk_buff *skb)
+{
+  /*
+   * This function is just a streamlined version of
+   * return e1000_xmit_frame(skb, netdev);
+   */
+
+  struct e1000_adapter *adapter = netdev->priv;
+  struct pci_dev *pdev = adapter->pdev;
+  struct e1000_tx_desc *tx_desc;
+  int i, len, offset, txd_needed;
+  uint32_t txd_upper, txd_lower;
+  unsigned int max_txd_pwr = E1000_MAX_TXD_PWR;
+
+  if(!netif_carrier_ok(netdev)) {
+    netif_stop_queue(netdev);
+    return -1;
+  }
+
+  txd_needed = TXD_USE_COUNT(skb->len, max_txd_pwr);
+
+  /* make sure there are enough Tx descriptors available in the ring */
+  if(E1000_DESC_UNUSED(adapter->tx_ring) <= (txd_needed + 1)) {
+    adapter->net_stats.tx_dropped++;
+    netif_stop_queue(netdev);
+    return -1;
+  }
+
+  txd_upper = 0;
+  txd_lower = adapter->txd_cmd;
+
+  if(e1000_tx_csum(adapter, adapter->tx_ring, skb)){
+    txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D;
+    txd_upper |= E1000_TXD_POPTS_TXSM << 8;
+  }
+
+  i = adapter->tx_ring->next_to_use;
+  tx_desc = E1000_TX_DESC(*(adapter->tx_ring), i);
+
+  len = skb->len;
+  offset = 0;
+
+//  adapter->tx_ring->buffer_info[i].length = len; TO DO: maybe 
adapter->rx_buffer_len needs to be put here
+  adapter->tx_ring->buffer_info[i].dma =
+    pci_map_page(pdev, virt_to_page(skb->data + offset),
+                 (unsigned long) (skb->data + offset) & ~PAGE_MASK, len,
+                 PCI_DMA_TODEVICE);
+  /* thanks Adam Greenhalgh and Beyers Cronje! */
+  adapter->tx_ring->buffer_info[i].time_stamp = jiffies;
+
+  tx_desc->buffer_addr = cpu_to_le64(adapter->tx_ring->buffer_info[i].dma);
+  tx_desc->lower.data = cpu_to_le32(txd_lower | len);
+  tx_desc->upper.data = cpu_to_le32(txd_upper);
+
+    /* EOP and SKB pointer go with the last fragment */
+  tx_desc->lower.data |= cpu_to_le32(E1000_TXD_CMD_EOP);
+  adapter->tx_ring->buffer_info[i].skb = skb;
+
+  i = i + 1;
+  if(i >= adapter->tx_ring->count)
+    i = 0;
+
+  /* Move the HW Tx Tail Pointer */
+  adapter->tx_ring->next_to_use = i;
+
+  netdev->trans_start = jiffies;
+
+  return 0;
+}
+
+static struct sk_buff *
+e1000_tx_clean(struct net_device *netdev)
+{
+  /*
+   * This function is a streamlined version of
+   * return e1000_clean_tx_irq(adapter, 1);
+   */
+
+  struct e1000_adapter *adapter = netdev->priv;
+  struct pci_dev *pdev = adapter->pdev;
+  int i;
+  struct e1000_tx_desc *tx_desc;
+  struct sk_buff *skb_head, *skb_last;
+
+  skb_head = skb_last = 0;
+
+  i = adapter->tx_ring->next_to_clean;
+  tx_desc = E1000_TX_DESC(*(adapter->tx_ring), i);
+
+  while(tx_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) {
+    if(adapter->tx_ring->buffer_info[i].dma != 0) {
+      pci_unmap_page(pdev, adapter->tx_ring->buffer_info[i].dma,
+                     adapter->tx_ring->buffer_info[i].length,
+                     PCI_DMA_TODEVICE);
+      adapter->tx_ring->buffer_info[i].dma = 0;
+    }
+
+    if(adapter->tx_ring->buffer_info[i].skb != NULL) {
+      struct sk_buff *skb = adapter->tx_ring->buffer_info[i].skb;
+      if (skb_head == 0) {
+        skb_head = skb;
+        skb_last = skb;
+        skb_last->next = NULL;
+      } else {
+        skb_last->next = skb;
+        skb->next = NULL;
+        skb_last = skb;
+      }
+      adapter->tx_ring->buffer_info[i].skb = NULL;
+    }
+    
+    i = (i + 1) % adapter->tx_ring->count;
+
+    tx_desc->upper.data = 0;
+    tx_desc = E1000_TX_DESC(*(adapter->tx_ring), i);
+  }
+
+  adapter->tx_ring->next_to_clean = i;
+
+  if(netif_queue_stopped(netdev) &&
+     (E1000_DESC_UNUSED(adapter->tx_ring) > E1000_TX_QUEUE_WAKE)) {
+    netif_start_queue(netdev);
+  }
+
+  return skb_head;
+}
+
+static int
+e1000_poll_on(struct net_device *dev)
+{
+  struct e1000_adapter *adapter = dev->priv;
+  unsigned long flags;
+
+  if (!dev->polling) {
+    printk("e1000_poll_on\n");
+    local_irq_save(flags);
+    local_irq_disable();
+    e1000_irq_disable(adapter);
+
+    /* reset the card - start in a clean state */
+
+    /* taken from e1000_down() */
+    e1000_reset(adapter);
+    e1000_clean_tx_ring(adapter, adapter->tx_ring);
+    e1000_clean_rx_ring(adapter, adapter->rx_ring);
+    /* taken from e1000_up() */
+    e1000_set_multi(dev);
+    e1000_configure_tx(adapter);
+    e1000_setup_rctl(adapter);
+    e1000_configure_rx(adapter);
+    e1000_alloc_rx_buffers(adapter, adapter->rx_ring,
+                          E1000_DESC_UNUSED(adapter->rx_ring));
+
+    dev->polling = 2;
+    local_irq_restore(flags);
+  }
+
+  return 0;
+}
+
+static int
+e1000_poll_off(struct net_device *dev)
+{
+  struct e1000_adapter *adapter = dev->priv;
+
+  if(dev->polling > 0){
+    dev->polling = 0;
+    e1000_irq_enable(adapter);
+    printk("e1000_poll_off\n");
+  }
+
+  return 0;
+}
+
+static int
+e1000_tx_eob(struct net_device *dev)
+{
+  struct e1000_adapter *adapter = dev->priv;
+  E1000_WRITE_REG(&adapter->hw, E1000_TDT(0), adapter->tx_ring->next_to_use);
+  return 0;
+}
+
+static int
+e1000_tx_start(struct net_device *dev)
+{
+  /*   printk("e1000_tx_start called\n"); */
+  e1000_tx_eob(dev);
+  return 0;
+}
+
+#ifdef DEBUG_PRINT
+
+/* debugging tools */
+
+#define PRT_HEX(str,value) printk("skb->%-10s = 0x%08x\n", str, (unsigned 
int)value);
+#define PRT_DEC(str,value) printk("skb->%-10s = %d\n", str, value);
+void e1000_print_skb(struct sk_buff* skb) 
+{
+  int i;
+  printk("========================\n");
+  printk("skb           = 0x%08x\n", (unsigned int)skb);
+  PRT_HEX("next",     skb->next);
+  PRT_HEX("prev",     skb->prev);
+  PRT_DEC("len",      skb->len);
+  PRT_HEX("data",     skb->data);
+  PRT_HEX("tail",     skb->tail);
+  PRT_HEX("dev",      skb->dev);
+  PRT_DEC("cloned",   skb->cloned);
+  PRT_DEC("pkt_type", skb->pkt_type);
+  PRT_DEC("users",    skb->users);
+  PRT_DEC("truesize", skb->truesize);
+  PRT_HEX("head",     skb->head);
+  PRT_HEX("end",      skb->end);
+  PRT_HEX("list",     skb->list);
+  PRT_DEC("data_len", skb->data_len);
+  PRT_HEX("csum",     skb->csum);
+  PRT_HEX("skb_shinfo", skb_shinfo(skb));
+  PRT_HEX("skb_shinfo->frag_list", skb_shinfo(skb)->frag_list);
+  PRT_DEC("skb_shinfo->nr_frags", skb_shinfo(skb)->nr_frags);
+  PRT_DEC("skb_shinfo->dataref", skb_shinfo(skb)->dataref);
+  for (i=0; i<skb_shinfo(skb)->nr_frags && i<8; ++i)
+    printk("skb->skb_shinfo->frags[%d]   = 0x%08x\n", i, 
skb_shinfo(skb)->frags[i]);
+}
+
+void e1000_print_rx_desc(struct e1000_rx_desc *rx_desc)
+{
+  printk("rx_desc = 0x%08x\n", rx_desc);
+  printk("rx_desc->buffer_addr = 0x%08x\n", rx_desc->buffer_addr);
+  printk("rx_desc->length      = %d\n",     rx_desc->length);
+  printk("rx_desc->csum        = 0x%04x\n", rx_desc->csum);
+  printk("rx_desc->status      = 0x%02x\n", rx_desc->status);
+  printk("rx_desc->errors      = 0x%02x\n", rx_desc->errors);
+  printk("rx_desc->special     = 0x%04x\n", rx_desc->special);
+}
+
+void e1000_print_rx_buffer_info(struct e1000_buffer *bi)
+{
+  printk("buffer_info             = 0x%08x\n", bi);
+  printk("buffer_info->skb        = 0x%08x\n", bi->skb);
+  printk("buffer_info->length     = 0x%08x (%d)\n", bi->length, bi->length);
+  printk("buffer_info->time_stamp = 0x%08x\n", bi->time_stamp);
+}
+
+void e1000_print_rx_desc_ring(struct e1000_desc_ring *desc_ring)
+{
+  int i;
+  struct e1000_buffer *bi;
+  struct e1000_rx_desc *desc;
+
+  printk("\n");
+  printk("desc_ring                = 0x%08x\n", desc_ring);
+  printk("desc_ring->desc          = 0x%08x\n", desc_ring->desc);
+  printk("desc_ring->dma           = 0x%08x\n", desc_ring->dma);
+  printk("desc_ring->size          = 0x%08x (%d)\n", desc_ring->size, 
desc_ring->size);
+  printk("desc_ring->count         = 0x%08x (%d)\n", desc_ring->count, 
desc_ring->count);
+  printk("desc_ring->next_to_use   = 0x%08x (%d)\n", desc_ring->next_to_use, 
desc_ring->next_to_use);
+  printk("desc_ring->next_to_clean = 0x%08x (%d)\n", desc_ring->next_to_clean, 
desc_ring->next_to_clean);
+  printk("desc_ring->buffer_info   = 0x%08x\n", desc_ring->buffer_info);
+
+  printk("\n");
+  bi = desc_ring->buffer_info;
+  desc = desc_ring->desc;
+  for (i=0; i<desc_ring->count; ++i) {
+    printk("===================================================== 
desc/buffer_info # %d\n", i);
+    e1000_print_rx_buffer_info(bi++);
+    e1000_print_rx_desc(desc++);
+  }
+
+}
+
+#undef PRT_HEX
+#undef PRT_DEC
+
+#endif
+
 
 /* e1000_main.c */
diff -Naur e1000-7.6.15.orig/src/e1000_param.c e1000-7.6.15/src/e1000_param.c
--- e1000-7.6.15.orig/src/e1000_param.c 2007-12-11 23:26:45.000000000 +0000
+++ e1000-7.6.15/src/e1000_param.c      2008-02-07 15:49:53.000000000 +0000
@@ -401,7 +401,7 @@
                        .type = list_option,
                        .name = "Flow Control",
                        .err  = "reading default settings from EEPROM",
-                       .def  = e1000_fc_default,
+                       .def  = e1000_fc_none,
                        .arg  = { .l = { .nr = ARRAY_SIZE(fc_list),
                                         .p = fc_list }}
                };
_______________________________________________
click mailing list
click@amsterdam.lcs.mit.edu
https://amsterdam.lcs.mit.edu/mailman/listinfo/click

Reply via email to