[etherlab-users] e1000 driver for linux kernel 3.18

Wilfried Holzke etherlab-users at holzke.net
Wed Aug 10 19:54:52 CEST 2016


Hi,

I want to use the etherlabmaster for the linux kernel 3.18. Due to the 
fact that I found no driver I tried to create one. While creating a new 
driver for the e1000e is straight forward, there are two parts in the 
source code which changed in a way that I don't know I there are any 
changes needed.

file: e1000_main-3.16-ethercat.c

in procedure: e1000_clean_jumbo_rx_irq



line 4149:

	if (!adapter->ecdev) {

		buffer_info->skb = NULL;

	}



line 4271:

	if (!adapter->ecdev) {

		dev_kfree_skb(skb);	

	}


All other parts are more or less directly found in the corresponding lines.

My change as a diff:


--- e1000_main-3.18-orig.c	2016-06-29 10:16:00.000000000 +0200
+++ e1000_main-3.18-ethercat.c	2016-06-29 11:42:54.000000000 +0200
@@ -26,14 +26,14 @@

 
*******************************************************************************/

-#include "e1000.h"
+#include "e1000-3.18-ethercat.h"
  #include <net/ip6_checksum.h>
  #include <linux/io.h>
  #include <linux/prefetch.h>
  #include <linux/bitops.h>
  #include <linux/if_vlan.h>

-char e1000_driver_name[] = "e1000";
+char e1000_driver_name[] = "ec_e1000";
  static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
  #define DRV_VERSION "7.3.21-k8-NAPI"
  const char e1000_driver_version[] = DRV_VERSION;
@@ -88,7 +88,7 @@
  	{0,}
  };

-MODULE_DEVICE_TABLE(pci, e1000_pci_tbl);
+//MODULE_DEVICE_TABLE(pci, e1000_pci_tbl);

  int e1000_up(struct e1000_adapter *adapter);
  void e1000_down(struct e1000_adapter *adapter);
@@ -220,7 +220,7 @@
  };

  MODULE_AUTHOR("Intel Corporation, <linux.nics at intel.com>");
-MODULE_DESCRIPTION("Intel(R) PRO/1000 Network Driver");
+MODULE_DESCRIPTION("EtherCAT-capable Intel(R) PRO/1000 Network Driver");
  MODULE_LICENSE("GPL");
  MODULE_VERSION(DRV_VERSION);

@@ -286,6 +286,10 @@
  	int irq_flags = IRQF_SHARED;
  	int err;

+	if (adapter->ecdev) {
+		return 0;
+	}
+	
  	err = request_irq(adapter->pdev->irq, handler, irq_flags, netdev->name,
  	                  netdev);
  	if (err) {
@@ -298,6 +302,10 @@
  static void e1000_free_irq(struct e1000_adapter *adapter)
  {
  	struct net_device *netdev = adapter->netdev;
+	
+	if (adapter->ecdev) {
+		return;
+	}

  	free_irq(adapter->pdev->irq, netdev);
  }
@@ -310,6 +318,10 @@
  {
  	struct e1000_hw *hw = &adapter->hw;

+	if (adapter->ecdev) {
+		return;
+	}
+	
  	ew32(IMC, ~0);
  	E1000_WRITE_FLUSH();
  	synchronize_irq(adapter->pdev->irq);
@@ -323,6 +335,10 @@
  {
  	struct e1000_hw *hw = &adapter->hw;

+	if (adapter->ecdev) {
+		return;
+	}
+	
  	ew32(IMS, IMS_ENABLE_MASK);
  	E1000_WRITE_FLUSH();
  }
@@ -406,8 +422,14 @@
  	 */
  	for (i = 0; i < adapter->num_rx_queues; i++) {
  		struct e1000_rx_ring *ring = &adapter->rx_ring[i];
-		adapter->alloc_rx_buf(adapter, ring,
+		if (adapter->ecdev) {
+			/* fill rx ring completely! */
+			adapter->alloc_rx_buf(adapter, ring, ring->count);
+		} else {
+			/* this one leavees the last ring element unallocated */
+			adapter->alloc_rx_buf(adapter, ring,
  				      E1000_DESC_UNUSED(ring));
+		}
  	}
  }

@@ -420,14 +442,16 @@

  	clear_bit(__E1000_DOWN, &adapter->flags);

-	napi_enable(&adapter->napi);
+	if (!adapter->ecdev) {
+		napi_enable(&adapter->napi);

-	e1000_irq_enable(adapter);
+		e1000_irq_enable(adapter);

-	netif_wake_queue(adapter->netdev);
+		netif_wake_queue(adapter->netdev);

-	/* fire a link change interrupt to start the watchdog */
-	ew32(ICS, E1000_ICS_LSC);
+		/* fire a link change interrupt to start the watchdog */
+		ew32(ICS, E1000_ICS_LSC);
+	}
  	return 0;
  }

@@ -499,7 +523,9 @@
  {
  	set_bit(__E1000_DOWN, &adapter->flags);

-	cancel_delayed_work_sync(&adapter->watchdog_task);
+	if (!adapter->ecdev) {
+		cancel_delayed_work_sync(&adapter->watchdog_task);
+	}

  	/*
  	 * Since the watchdog task can reschedule other tasks, we should cancel
@@ -507,11 +533,13 @@
  	 * still running after the adapter has been turned down.
  	 */

-	cancel_delayed_work_sync(&adapter->phy_info_task);
-	cancel_delayed_work_sync(&adapter->fifo_stall_task);
+	if (!adapter->ecdev) {
+		cancel_delayed_work_sync(&adapter->phy_info_task);
+		cancel_delayed_work_sync(&adapter->fifo_stall_task);
+	}

  	/* Only kill reset task if adapter is not resetting */
-	if (!test_bit(__E1000_RESETTING, &adapter->flags))
+	if (!adapter->ecdev && !test_bit(__E1000_RESETTING, &adapter->flags))
  		cancel_work_sync(&adapter->reset_task);
  }

@@ -525,9 +553,11 @@
  	/* disable receives in the hardware */
  	rctl = er32(RCTL);
  	ew32(RCTL, rctl & ~E1000_RCTL_EN);
-	/* flush and sleep below */

-	netif_tx_disable(netdev);
+	if (!adapter->ecdev) {
+		/* flush and sleep below */
+		netif_tx_disable(netdev);
+	}

  	/* disable transmits in the hardware */
  	tctl = er32(TCTL);
@@ -537,9 +567,11 @@
  	E1000_WRITE_FLUSH();
  	msleep(10);

-	napi_disable(&adapter->napi);
+	if (!adapter->ecdev) {
+		napi_disable(&adapter->napi);

-	e1000_irq_disable(adapter);
+		e1000_irq_disable(adapter);
+	}

  	/* Setting DOWN must be after irq_disable to prevent
  	 * a screaming interrupt.  Setting DOWN also prevents
@@ -549,7 +581,10 @@

  	adapter->link_speed = 0;
  	adapter->link_duplex = 0;
-	netif_carrier_off(netdev);
+	
+	if (!adapter->ecdev) {
+		netif_carrier_off(netdev);
+	}

  	e1000_reset(adapter);
  	e1000_clean_all_tx_rings(adapter);
@@ -1211,10 +1246,20 @@
  	/* reset the hardware with the new settings */
  	e1000_reset(adapter);

-	strcpy(netdev->name, "eth%d");
-	err = register_netdev(netdev);
-	if (err)
-		goto err_register;
+	// offer device to EtherCAT master module
+	adapter->ecdev = ecdev_offer(netdev, ec_poll, THIS_MODULE);
+	if (adapter->ecdev) {
+		err = ecdev_open(adapter->ecdev);
+		if (err) {
+			ecdev_withdraw(adapter->ecdev);
+			goto err_register;
+		}
+	} else {
+		strcpy(netdev->name, "eth%d");
+		err = register_netdev(netdev);
+		if (err)
+			goto err_register;
+	}

  	e1000_vlan_filter_on_off(adapter, false);

@@ -1228,8 +1273,10 @@
  	       ((hw->bus_width == e1000_bus_width_64) ? 64 : 32),
  	       netdev->dev_addr);

-	/* carrier off reporting is important to ethtool even BEFORE open */
-	netif_carrier_off(netdev);
+	if (!adapter->ecdev) {
+		/* carrier off reporting is important to ethtool even BEFORE open */
+		netif_carrier_off(netdev);
+	}

  	e_info(probe, "Intel(R) PRO/1000 Network Connection\n");

@@ -1276,7 +1323,12 @@
  	e1000_down_and_stop(adapter);
  	e1000_release_manageability(adapter);

-	unregister_netdev(netdev);
+	if (adapter->ecdev) {
+		ecdev_close(adapter->ecdev);
+		ecdev_withdraw(adapter->ecdev);	
+	} else {
+		unregister_netdev(netdev);
+	}

  	e1000_phy_hw_reset(hw);

@@ -1404,11 +1456,13 @@
  	/* From here on the code is the same as e1000_up() */
  	clear_bit(__E1000_DOWN, &adapter->flags);

-	napi_enable(&adapter->napi);
+	if (!adapter->ecdev) {
+		napi_enable(&adapter->napi);

-	e1000_irq_enable(adapter);
+		e1000_irq_enable(adapter);

-	netif_start_queue(netdev);
+		netif_start_queue(netdev);
+	}

  	/* fire a link status change interrupt to start the watchdog */
  	ew32(ICS, E1000_ICS_LSC);
@@ -2170,7 +2224,7 @@
  	E1000_WRITE_FLUSH();
  	mdelay(5);

-	if (netif_running(netdev))
+	if (!adapter->ecdev && netif_running(netdev))
  		e1000_clean_all_rx_rings(adapter);
  }

@@ -2189,11 +2243,17 @@
  	if (hw->pci_cmd_word & PCI_COMMAND_INVALIDATE)
  		e1000_pci_set_mwi(hw);

-	if (netif_running(netdev)) {
+	if (!adapter->netdev && netif_running(netdev)) {
  		/* No need to loop, because 82542 supports only 1 queue */
  		struct e1000_rx_ring *ring = &adapter->rx_ring[0];
  		e1000_configure_rx(adapter);
-		adapter->alloc_rx_buf(adapter, ring, E1000_DESC_UNUSED(ring));
+		if (adapter->ecdev) {
+			/* fill rx ring completely */
+			adapter->alloc_rx_buf(adapter, ring, ring->count);
+		} else {
+			/* this one leaves the last ring element unallocated! */
+			adapter->alloc_rx_buf(adapter, ring, E1000_DESC_UNUSED(ring));
+		}
  	}
  }

@@ -2442,13 +2502,14 @@
  	u32 link, tctl;

  	link = e1000_has_link(adapter);
-	if ((netif_carrier_ok(netdev)) && link)
+	if (!adapter->ecdev && (netif_carrier_ok(netdev)) && link)
  		goto link_up;

  	if (link) {
-		if (!netif_carrier_ok(netdev)) {
+		if ((adatper->ecdev && !ecdev_get_link(adapter->ecdev))
+			|| (!adapter->ecdev && !netif_carrier_ok(netdev))) {
  			u32 ctrl;
-			bool txb2b = true;
+			bool txb2b __attribute__ ((unused)) = true;
  			/* update snapshot of PHY registers on LSC */
  			e1000_get_speed_and_duplex(hw,
  						   &adapter->link_speed,
@@ -2483,24 +2544,34 @@
  			tctl = er32(TCTL);
  			tctl |= E1000_TCTL_EN;
  			ew32(TCTL, tctl);
-
-			netif_carrier_on(netdev);
-			if (!test_bit(__E1000_DOWN, &adapter->flags))
-				schedule_delayed_work(&adapter->phy_info_task,
+			
+			if (adapter->ecdev) {
+				ecdev_set_link(adapter->ecdev, 1);
+			} else {
+				netif_carrier_on(netdev);
+				if (!test_bit(__E1000_DOWN, &adapter->flags))
+					schedule_delayed_work(&adapter->phy_info_task,
  						      2 * HZ);
+			}
  			adapter->smartspeed = 0;
  		}
  	} else {
-		if (netif_carrier_ok(netdev)) {
+		if ((adapter->ecdev && ecdev_get_link(adapter->ecdev))
+			|| (!adapter->ecdev && netif_carrier_ok(netdev))) {
  			adapter->link_speed = 0;
  			adapter->link_duplex = 0;
  			pr_info("%s NIC Link is Down\n",
  				netdev->name);
-			netif_carrier_off(netdev);
+				
+			if (adapter->ecdev) {
+				ecdev_set_link(dapter->ecdev, 0);
+			} else {
+				netif_carrier_off(netdev);

-			if (!test_bit(__E1000_DOWN, &adapter->flags))
-				schedule_delayed_work(&adapter->phy_info_task,
+				if (!test_bit(__E1000_DOWN, &adapter->flags))
+					schedule_delayed_work(&adapter->phy_info_task,
  						      2 * HZ);
+			}
  		}

  		e1000_smartspeed(adapter);
@@ -2521,7 +2592,7 @@

  	e1000_update_adaptive(hw);

-	if (!netif_carrier_ok(netdev)) {
+	if (!adapter->ecdev && !netif_carrier_ok(netdev)) {
  		if (E1000_DESC_UNUSED(txdr) + 1 < txdr->count) {
  			/* We've lost link, so the controller stops DMA,
  			 * but we've got queued Tx work that's never going
@@ -2557,7 +2628,7 @@
  	adapter->detect_tx_hung = true;

  	/* Reschedule the task */
-	if (!test_bit(__E1000_DOWN, &adapter->flags))
+	if (!adapter->ecdev && !test_bit(__E1000_DOWN, &adapter->flags))
  		schedule_delayed_work(&adapter->watchdog_task, 2 * HZ);
  }

@@ -3085,6 +3156,10 @@
  	struct e1000_adapter *adapter = netdev_priv(netdev);
  	struct e1000_tx_ring *tx_ring = adapter->tx_ring;

+	if (adapter->ecdev) {
+		return -EBUSY;
+	}
+	
  	netif_stop_queue(netdev);
  	/* Herbert's original patch had:
  	 *  smp_mb__after_netif_stop_queue();
@@ -3181,7 +3256,9 @@
  				if (!__pskb_pull_tail(skb, pull_size)) {
  					e_err(drv, "__pskb_pull_tail "
  					      "failed.\n");
-					dev_kfree_skb_any(skb);
+					if (!adapter->ecdev) {
+						dev_kfree_skb_any(skb);
+					}
  					return NETDEV_TX_OK;
  				}
  				len = skb_headlen(skb);
@@ -3229,9 +3306,11 @@

  	if (unlikely((hw->mac_type == e1000_82547) &&
  		     (e1000_82547_fifo_workaround(adapter, skb)))) {
-		netif_stop_queue(netdev);
-		if (!test_bit(__E1000_DOWN, &adapter->flags))
-			schedule_delayed_work(&adapter->fifo_stall_task, 1);
+		if (!adapter->ecdev) {
+			netif_stop_queue(netdev);
+			if (!test_bit(__E1000_DOWN, &adapter->flags))
+				schedule_delayed_work(&adapter->fifo_stall_task, 1);
+		}
  		return NETDEV_TX_BUSY;
  	}

@@ -3244,7 +3323,9 @@

  	tso = e1000_tso(adapter, tx_ring, skb, protocol);
  	if (tso < 0) {
-		dev_kfree_skb_any(skb);
+		if (!adapter->ecdev) {
+			dev_kfree_skb_any(skb);
+		}
  		return NETDEV_TX_OK;
  	}

@@ -3269,11 +3350,15 @@
  		skb_tx_timestamp(skb);

  		e1000_tx_queue(adapter, tx_ring, tx_flags, count);
-		/* Make sure there is space in the ring for the next send. */
-		e1000_maybe_stop_tx(netdev, tx_ring, MAX_SKB_FRAGS + 2);
+		if (!adapter->ecdev) {
+			/* Make sure there is space in the ring for the next send. */
+			e1000_maybe_stop_tx(netdev, tx_ring, MAX_SKB_FRAGS + 2);
+		}

  	} else {
-		dev_kfree_skb_any(skb);
+		if (!adapter->ecdev) {
+			dev_kfree_skb_any(skb);
+		}
  		tx_ring->buffer_info[first].time_stamp = 0;
  		tx_ring->next_to_use = first;
  	}
@@ -3533,6 +3618,10 @@
  	struct e1000_adapter *adapter = netdev_priv(netdev);
  	struct e1000_hw *hw = &adapter->hw;
  	int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
+	
+	if (adapter->ecdev) {
+		return -EBUSY;
+	}

  	if ((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
  	    (max_frame > MAX_JUMBO_FRAME_SIZE)) {
@@ -3609,7 +3698,7 @@
  	struct net_device *netdev = adapter->netdev;
  	struct e1000_hw *hw = &adapter->hw;
  	struct pci_dev *pdev = adapter->pdev;
-	unsigned long flags;
+	unsigned long flags = 0;
  	u16 phy_tmp;

  #define PHY_IDLE_ERROR_COUNT_MASK 0x00FF
@@ -3622,7 +3711,9 @@
  	if (pci_channel_offline(pdev))
  		return;

-	spin_lock_irqsave(&adapter->stats_lock, flags);
+	if (!adapter->ecdev) {
+		spin_lock_irqsave(&adapter->stats_lock, flags);
+	}

  	/* these counters are modified from e1000_tbi_adjust_stats,
  	 * called from the interrupt context, so they must only
@@ -3751,7 +3842,20 @@
  		adapter->stats.mgpdc += er32(MGTPDC);
  	}

-	spin_unlock_irqrestore(&adapter->stats_lock, flags);
+	if (!adapter->ecdev) {
+		spin_unlock_irqrestore(&adapter->stats_lock, flags);
+	}
+}
+
+void ec_poll(struct net_device *netdev)
+{
+	struct e1000_adapter *adapter = netdev_priv(netdev);
+	if (jiffies - adapter->ec_watchdog_jiffies >= 2 * HZ) {
+		e1000_watchdog(&adapter->watchdog_task.work);
+		adapter->ec_watchdog_jiffies = jiffies;
+	}
+
+	e1000_intr(0, netdev);
  }

  /**
@@ -3779,26 +3883,37 @@
  	if (unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) {
  		hw->get_link_status = 1;
  		/* guard against interrupt when we're going down */
-		if (!test_bit(__E1000_DOWN, &adapter->flags))
+		if (!adapter->ecdev && !test_bit(__E1000_DOWN, &adapter->flags))
  			schedule_delayed_work(&adapter->watchdog_task, 1);
  	}

-	/* disable interrupts, without the synchronize_irq bit */
-	ew32(IMC, ~0);
-	E1000_WRITE_FLUSH();
-
-	if (likely(napi_schedule_prep(&adapter->napi))) {
-		adapter->total_tx_bytes = 0;
-		adapter->total_tx_packets = 0;
-		adapter->total_rx_bytes = 0;
-		adapter->total_rx_packets = 0;
-		__napi_schedule(&adapter->napi);
+	if (adapter->ecdev) {
+		int i, ec_work_done = 0;
+		for (i = 0; i < E1000_MAX_INTR; i++) {
+			if (unlikely(!adapter->clean_rx(adapter, adapter->rx_ring,
+							&ec_work_done, 100) &&
+						!e1000_clean_tx_irq(adapter, adapter->tx_ring))) {
+				break;
+			}
+		}		
  	} else {
-		/* this really should not happen! if it does it is basically a
-		 * bug, but not a hard error, so enable ints and continue
-		 */
-		if (!test_bit(__E1000_DOWN, &adapter->flags))
-			e1000_irq_enable(adapter);
+		/* disable interrupts, without the synchronize_irq bit */
+		ew32(IMC, ~0);
+		E1000_WRITE_FLUSH();
+
+		if (likely(napi_schedule_prep(&adapter->napi))) {
+			adapter->total_tx_bytes = 0;
+			adapter->total_tx_packets = 0;
+			adapter->total_rx_bytes = 0;
+			adapter->total_rx_packets = 0;
+			__napi_schedule(&adapter->napi);
+		} else {
+			/* this really should not happen! if it does it is basically a
+			* bug, but not a hard error, so enable ints and continue
+			*/
+			if (!test_bit(__E1000_DOWN, &adapter->flags))
+				e1000_irq_enable(adapter);
+		}
  	}

  	return IRQ_HANDLED;
@@ -3807,6 +3922,7 @@
  /**
   * e1000_clean - NAPI Rx polling callback
   * @adapter: board private structure
+ * EtherCAT: never called
   **/
  static int e1000_clean(struct napi_struct *napi, int budget)
  {
@@ -3883,10 +3999,12 @@

  	tx_ring->next_to_clean = i;

-	netdev_completed_queue(netdev, pkts_compl, bytes_compl);
+	if (!adapter->ecdev) {
+		netdev_completed_queue(netdev, pkts_compl, bytes_compl);
+	}

  #define TX_WAKE_THRESHOLD 32
-	if (unlikely(count && netif_carrier_ok(netdev) &&
+	if (!adapter->ecdev && unlikely(count && netif_carrier_ok(netdev) &&
  		     E1000_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD)) {
  		/* Make sure that anybody stopping the queue after this
  		 * sees the new next_to_clean.
@@ -3900,7 +4018,7 @@
  		}
  	}

-	if (adapter->detect_tx_hung) {
+	if (!adapter->ecdev && adapter->detect_tx_hung) {
  		/* Detect a transmit hang in hardware, this serializes the
  		 * check with the clearing of time_stamp and movement of i
  		 */
@@ -4173,7 +4291,8 @@
  		length = le16_to_cpu(rx_desc->length);

  		/* errors is only valid for DD + EOP descriptors */
-		if (unlikely((status & E1000_RXD_STAT_EOP) &&
+		if (!adapter->ecdev &&
+			unlikely((status & E1000_RXD_STAT_EOP) &&
  		    (rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK))) {
  			u8 *mapped = page_address(buffer_info->rxbuf.page);

@@ -4187,7 +4306,7 @@
  				/* an error means any chain goes out the window
  				 * too
  				 */
-				if (rx_ring->rx_skb_top)
+				if (!adapter->ecdev && rx_ring->rx_skb_top)
  					dev_kfree_skb(rx_ring->rx_skb_top);
  				rx_ring->rx_skb_top = NULL;
  				goto next_desc;
@@ -4255,8 +4374,16 @@
  					total_rx_bytes += skb->len;
  					total_rx_packets++;

-					e1000_receive_skb(adapter, status,
+					if (adapter->ecdev) {
+						ecdev_receive(adapter->ecdev, skb->data, length);
+						
+						// No need to detect link status as
+						// long as frames are received: Reset watchdog.
+						adapter->ec_watchdog_jiffies = jiffies;
+					} else {
+						e1000_receive_skb(adapter, status,
  							  rx_desc->special, skb);
+					}
  					goto next_desc;
  				} else {
  					skb = napi_get_frags(&adapter->napi);
@@ -4327,7 +4454,7 @@
  {
  	struct sk_buff *skb;

-	if (length > copybreak)
+	if (adapter->ecdev || length > copybreak)
  		return NULL;

  	skb = e1000_alloc_rx_skb(adapter, length);
@@ -5065,6 +5192,10 @@
  	int retval = 0;
  #endif

+	if (adapter->ecdev) {
+		return -EBUSY;
+	}
+
  	netif_device_detach(netdev);

  	if (netif_running(netdev)) {
@@ -5169,6 +5300,10 @@
  	struct e1000_hw *hw = &adapter->hw;
  	u32 err;

+	if (adapter->ecdev) {
+		return -EBUSY;
+	}
+	
  	pci_set_power_state(pdev, PCI_D0);
  	pci_restore_state(pdev);
  	pci_save_state(pdev);
@@ -5201,7 +5336,9 @@
  	if (netif_running(netdev))
  		e1000_up(adapter);

-	netif_device_attach(netdev);
+	if (!adapter->ecdev) {
+		netif_device_attach(netdev);
+	}

  	return 0;
  }
------------------

My question is, are there new procedures which are replacing the two 
lines above or are the changes in a way that there are no changes 
naccessary in the new kernel module for version 3.18?

Thanks for any hints and help.

regards

   W. Holzke









More information about the Etherlab-users mailing list