Advanced e1000 modifications.

This commit is contained in:
Florian Pose 2007-07-17 18:47:12 +00:00
parent ce4c658cc4
commit 9cfe5f1121
2 changed files with 69 additions and 39 deletions

View File

@ -2368,7 +2368,8 @@ e1000_watchdog(unsigned long data)
link = E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU;
if (link) {
if (!netif_carrier_ok(netdev)) {
if ((adapter->ecdev && !ecdev_link_up(adapter->ecdev))
|| (!adapter->ecdev && !netif_carrier_ok(netdev))) {
boolean_t txb2b = 1;
e1000_get_speed_and_duplex(&adapter->hw,
&adapter->link_speed,
@ -2434,18 +2435,27 @@ e1000_watchdog(unsigned long data)
tctl |= E1000_TCTL_EN;
E1000_WRITE_REG(&adapter->hw, TCTL, tctl);
netif_carrier_on(netdev);
netif_wake_queue(netdev);
if (adapter->ecdev) {
ecdev_link_state(1);
} else {
netif_carrier_on(netdev);
netif_wake_queue(netdev);
}
mod_timer(&adapter->phy_info_timer, jiffies + 2 * HZ);
adapter->smartspeed = 0;
}
} else {
if (netif_carrier_ok(netdev)) {
if ((adapter->ecdev && ecdev_link_up(adapter->ecdev))
|| (!adapter->ecdev && netif_carrier_ok(netdev))) {
adapter->link_speed = 0;
adapter->link_duplex = 0;
DPRINTK(LINK, INFO, "NIC Link is Down\n");
netif_carrier_off(netdev);
netif_stop_queue(netdev);
if (adapter->ecdev) {
ecdev_link_state(0);
} else {
netif_carrier_off(netdev);
netif_stop_queue(netdev);
}
mod_timer(&adapter->phy_info_timer, jiffies + 2 * HZ);
/* 80003ES2LAN workaround--
@ -2476,7 +2486,8 @@ e1000_watchdog(unsigned long data)
e1000_update_adaptive(&adapter->hw);
if (!netif_carrier_ok(netdev)) {
if ((adapter->ecdev && !ecdev_link_up(adapter->ecdev))
|| (!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
@ -2893,7 +2904,8 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
tx_ring = adapter->tx_ring;
if (unlikely(skb->len <= 0)) {
dev_kfree_skb_any(skb);
if (!adapter->ecdev)
dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
}
@ -2925,7 +2937,8 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
if (!__pskb_pull_tail(skb, pull_size)) {
DPRINTK(DRV, ERR,
"__pskb_pull_tail failed.\n");
dev_kfree_skb_any(skb);
if (!adapter->ecdev)
dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
}
len = skb->len - skb->data_len;
@ -2976,26 +2989,32 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
(adapter->hw.mac_type == e1000_82573))
e1000_transfer_dhcp_info(adapter, skb);
local_irq_save(flags);
if (!spin_trylock(&tx_ring->tx_lock)) {
/* Collision - tell upper layer to requeue */
local_irq_restore(flags);
return NETDEV_TX_LOCKED;
}
if (!adapter->ecdev) {
local_irq_save(flags);
if (!spin_trylock(&tx_ring->tx_lock)) {
/* Collision - tell upper layer to requeue */
local_irq_restore(flags);
return NETDEV_TX_LOCKED;
}
}
/* need: count + 2 desc gap to keep tail from touching
* head, otherwise try next time */
if (unlikely(E1000_DESC_UNUSED(tx_ring) < count + 2)) {
netif_stop_queue(netdev);
spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
if (!adapter->ecdev) {
netif_stop_queue(netdev);
spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
}
return NETDEV_TX_BUSY;
}
if (unlikely(adapter->hw.mac_type == e1000_82547)) {
if (unlikely(e1000_82547_fifo_workaround(adapter, skb))) {
netif_stop_queue(netdev);
if (!adapter->ecdev)
netif_stop_queue(netdev);
mod_timer(&adapter->tx_fifo_stall_timer, jiffies);
spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
if (!adapter->ecdev)
spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
return NETDEV_TX_BUSY;
}
}
@ -3009,8 +3028,10 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
tso = e1000_tso(adapter, tx_ring, skb);
if (tso < 0) {
dev_kfree_skb_any(skb);
spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
if (!adapter->ecdev) {
dev_kfree_skb_any(skb);
spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
}
return NETDEV_TX_OK;
}
@ -3033,10 +3054,12 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
netdev->trans_start = jiffies;
/* Make sure there is space in the ring for the next send. */
if (unlikely(E1000_DESC_UNUSED(tx_ring) < MAX_SKB_FRAGS + 2))
if (!adapter->ecdev) {
if (unlikely(E1000_DESC_UNUSED(tx_ring) < MAX_SKB_FRAGS + 2))
netif_stop_queue(netdev);
spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
}
return NETDEV_TX_OK;
}
@ -3166,7 +3189,7 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu)
netdev->mtu = new_mtu;
if (netif_running(netdev))
if (adapter->ecdev || netif_running(netdev))
e1000_reinit_locked(adapter);
adapter->hw.max_frame_size = max_frame;
@ -3198,7 +3221,8 @@ e1000_update_stats(struct e1000_adapter *adapter)
if (pdev->error_state && pdev->error_state != pci_channel_io_normal)
return;
spin_lock_irqsave(&adapter->stats_lock, flags);
if (!adapter->ecdev)
spin_lock_irqsave(&adapter->stats_lock, flags);
/* these counters are modified from e1000_adjust_tbi_stats,
* called from the interrupt context, so they must only
@ -3339,7 +3363,8 @@ e1000_update_stats(struct e1000_adapter *adapter)
adapter->phy_stats.receive_errors += phy_tmp;
}
spin_unlock_irqrestore(&adapter->stats_lock, flags);
if (!adapter->ecdev)
spin_unlock_irqrestore(&adapter->stats_lock, flags);
}
/**
@ -3369,7 +3394,7 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
if (unlikely(!icr)) {
#ifdef CONFIG_E1000_NAPI
if (hw->mac_type >= e1000_82571)
if (!adapter->ecdev && hw->mac_type >= e1000_82571)
e1000_irq_enable(adapter);
#endif
return IRQ_NONE; /* Not our interrupt */
@ -3382,7 +3407,8 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
* disable receives here in the ISR and
* reset adapter in watchdog
*/
if (netif_carrier_ok(netdev) &&
if (((adapter->ecdev && ecdev_link_up(adapter->ecdev))
|| (!adapter->ecdev && netif_carrier_ok(netdev))) &&
(adapter->hw.mac_type == e1000_80003es2lan)) {
/* disable receives */
rctl = E1000_READ_REG(hw, RCTL);
@ -3397,13 +3423,15 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
E1000_WRITE_REG(hw, IMC, ~0);
E1000_WRITE_FLUSH(hw);
}
if (likely(netif_rx_schedule_prep(netdev)))
__netif_rx_schedule(netdev);
else
e1000_irq_enable(adapter);
if (!adapter->ecdev) {
if (likely(netif_rx_schedule_prep(netdev)))
__netif_rx_schedule(netdev);
else
e1000_irq_enable(adapter);
}
#else
/* Writing IMC and IMS is needed for 82547.
* Due to Hub Link bus being occupied, an interrupt
/* Writing IMC and IMS is needed for 82547.
* Due to Hub Link bus being occupied, an interrupt
* de-assertion message is not able to be sent.
* When an interrupt assertion message is generated later,
* two messages are re-ordered and sent out.
@ -3422,7 +3450,8 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
!e1000_clean_tx_irq(adapter, adapter->tx_ring)))
break;
if (hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2)
if (!adapter->ecdev
&& (hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2))
e1000_irq_enable(adapter);
#endif
@ -3437,7 +3466,7 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
**/
static int
e1000_clean(struct net_device *poll_dev, int *budget)
e1000_clean(struct net_device *poll_dev, int *budget) // never called for EtherCAT
{
struct e1000_adapter *adapter;
int work_to_do = min(*budget, poll_dev->quota);
@ -3526,7 +3555,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
tx_ring->next_to_clean = i;
#define TX_WAKE_THRESHOLD 32
if (unlikely(cleaned && netif_queue_stopped(netdev) &&
if (unlikely(!adapter->ecdev && cleaned && netif_queue_stopped(netdev) &&
netif_carrier_ok(netdev))) {
spin_lock(&tx_ring->tx_lock);
if (netif_queue_stopped(netdev) &&
@ -3695,7 +3724,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
goto next_desc;
}
if (unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) {
if (!adapter->ecdev && unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) {
last_byte = *(skb->data + length - 1);
if (TBI_ACCEPT(&adapter->hw, status,
rx_desc->errors, length, last_byte)) {
@ -3717,7 +3746,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
* performance for small packets with large amounts
* of reassembly being done in the stack */
#define E1000_CB_LENGTH 256
if (length < E1000_CB_LENGTH) {
if (!adapter->ecdev && length < E1000_CB_LENGTH) {
struct sk_buff *new_skb =
netdev_alloc_skb(netdev, length + NET_IP_ALIGN);
if (new_skb) {

View File

@ -77,6 +77,7 @@ int ecdev_open(ec_device_t *device);
void ecdev_close(ec_device_t *device);
void ecdev_receive(ec_device_t *device, const void *data, size_t size);
void ecdev_link_state(ec_device_t *device, uint8_t newstate);
uint8_t ecdev_link_up(ec_device_t *device);
/*****************************************************************************/