[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