WARN_ONCE on querying ecdev before ecdev_offer for igc

This commit is contained in:
Bjarne von Horn 2024-02-05 15:19:37 +01:00
parent 995e41ee6a
commit f388bde39a
9 changed files with 182 additions and 136 deletions

View File

@ -48,6 +48,10 @@ ifeq (@ENABLE_IGC@,1)
igc_ethtool-@KERNEL_IGC@-ethercat.o \ igc_ethtool-@KERNEL_IGC@-ethercat.o \
igc_nvm-@KERNEL_IGC@-ethercat.o igc_nvm-@KERNEL_IGC@-ethercat.o
ifeq (@ENABLE_DRIVER_RESOURCE_VERIFYING@,1)
ccflags-y := -DEC_ENABLE_DRIVER_RESOURCE_VERIFYING
endif
CFLAGS_igc_main-@KERNEL_IGC@-ethercat.o = -DREV=$(REV) CFLAGS_igc_main-@KERNEL_IGC@-ethercat.o = -DREV=$(REV)
endif endif

View File

@ -249,7 +249,7 @@ struct igc_adapter {
static inline ec_device_t *get_ecdev(struct igc_adapter *adapter) static inline ec_device_t *get_ecdev(struct igc_adapter *adapter)
{ {
#if 0 #ifdef EC_ENABLE_DRIVER_RESOURCE_VERIFYING
WARN_ON(!adapter->ecdev_initialized); WARN_ON(!adapter->ecdev_initialized);
#endif #endif
return adapter->ecdev_; return adapter->ecdev_;

View File

@ -254,11 +254,20 @@ struct igc_adapter {
} perout[IGC_N_PEROUT]; } perout[IGC_N_PEROUT];
/* EtherCAT device variables */ /* EtherCAT device variables */
ec_device_t *ecdev; ec_device_t *ecdev_;
unsigned long ec_watchdog_jiffies; unsigned long ec_watchdog_jiffies;
struct irq_work ec_watchdog_kicker; struct irq_work ec_watchdog_kicker;
bool ecdev_initialized;
}; };
static inline ec_device_t *get_ecdev(struct igc_adapter *adapter)
{
#ifdef EC_ENABLE_DRIVER_RESOURCE_VERIFYING
WARN_ON(!adapter->ecdev_initialized);
#endif
return adapter->ecdev_;
}
void igc_up(struct igc_adapter *adapter); void igc_up(struct igc_adapter *adapter);
void igc_down(struct igc_adapter *adapter); void igc_down(struct igc_adapter *adapter);
int igc_open(struct net_device *netdev); int igc_open(struct net_device *netdev);

View File

@ -267,11 +267,20 @@ struct igc_adapter {
} perout[IGC_N_PEROUT]; } perout[IGC_N_PEROUT];
/* EtherCAT device variables */ /* EtherCAT device variables */
ec_device_t *ecdev; ec_device_t *ecdev_;
unsigned long ec_watchdog_jiffies; unsigned long ec_watchdog_jiffies;
struct irq_work ec_watchdog_kicker; struct irq_work ec_watchdog_kicker;
bool ecdev_initialized;
}; };
static inline ec_device_t *get_ecdev(struct igc_adapter *adapter)
{
#ifdef EC_ENABLE_DRIVER_RESOURCE_VERIFYING
WARN_ON(!adapter->ecdev_initialized);
#endif
return adapter->ecdev_;
}
void igc_up(struct igc_adapter *adapter); void igc_up(struct igc_adapter *adapter);
void igc_down(struct igc_adapter *adapter); void igc_down(struct igc_adapter *adapter);
int igc_open(struct net_device *netdev); int igc_open(struct net_device *netdev);

View File

@ -282,11 +282,20 @@ struct igc_adapter {
} perout[IGC_N_PEROUT]; } perout[IGC_N_PEROUT];
/* EtherCAT device variables */ /* EtherCAT device variables */
ec_device_t *ecdev; ec_device_t *ecdev_;
unsigned long ec_watchdog_jiffies; unsigned long ec_watchdog_jiffies;
struct irq_work ec_watchdog_kicker; struct irq_work ec_watchdog_kicker;
bool ecdev_initialized;
}; };
static inline ec_device_t *get_ecdev(struct igc_adapter *adapter)
{
#ifdef EC_ENABLE_DRIVER_RESOURCE_VERIFYING
WARN_ON(!adapter->ecdev_initialized);
#endif
return adapter->ecdev_;
}
void igc_up(struct igc_adapter *adapter); void igc_up(struct igc_adapter *adapter);
void igc_down(struct igc_adapter *adapter); void igc_down(struct igc_adapter *adapter);
int igc_open(struct net_device *netdev); int igc_open(struct net_device *netdev);

View File

@ -4023,6 +4023,9 @@ static int igc_poll(struct napi_struct *napi, int budget)
bool clean_complete = true; bool clean_complete = true;
int work_done = 0; int work_done = 0;
if (get_ecdev(q_vector->adapter))
return -EBUSY;
if (q_vector->tx.ring) if (q_vector->tx.ring)
clean_complete = igc_clean_tx_irq(q_vector, budget); clean_complete = igc_clean_tx_irq(q_vector, budget);

View File

@ -212,7 +212,7 @@ static void igc_clean_tx_ring(struct igc_ring *tx_ring)
case IGC_TX_BUFFER_TYPE_SKB: case IGC_TX_BUFFER_TYPE_SKB:
{ {
struct igc_adapter *adapter = netdev_priv(tx_ring->netdev); struct igc_adapter *adapter = netdev_priv(tx_ring->netdev);
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
/* skb is reused in EtherCAT TX operation */ /* skb is reused in EtherCAT TX operation */
dev_kfree_skb_any(tx_buffer->skb); dev_kfree_skb_any(tx_buffer->skb);
} }
@ -1201,7 +1201,7 @@ static int __igc_maybe_stop_tx(struct igc_ring *tx_ring, const u16 size)
{ {
struct net_device *netdev = tx_ring->netdev; struct net_device *netdev = tx_ring->netdev;
struct igc_adapter *adapter = netdev_priv(netdev); struct igc_adapter *adapter = netdev_priv(netdev);
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
netif_stop_subqueue(netdev, tx_ring->queue_index); netif_stop_subqueue(netdev, tx_ring->queue_index);
} }
@ -1215,7 +1215,7 @@ static int __igc_maybe_stop_tx(struct igc_ring *tx_ring, const u16 size)
return -EBUSY; return -EBUSY;
/* A reprieve! */ /* A reprieve! */
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
netif_wake_subqueue(netdev, tx_ring->queue_index); netif_wake_subqueue(netdev, tx_ring->queue_index);
} }
@ -1413,7 +1413,7 @@ dma_error:
if (dma_unmap_len(tx_buffer, len)) if (dma_unmap_len(tx_buffer, len))
igc_unmap_tx_buffer(tx_ring->dev, tx_buffer); igc_unmap_tx_buffer(tx_ring->dev, tx_buffer);
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
dev_kfree_skb_any(tx_buffer->skb); dev_kfree_skb_any(tx_buffer->skb);
tx_buffer->skb = NULL; tx_buffer->skb = NULL;
} }
@ -1584,7 +1584,7 @@ done:
first->bytecount = skb->len; first->bytecount = skb->len;
first->gso_segs = 1; first->gso_segs = 1;
if (unlikely(!adapter->ecdev && if (unlikely(!get_ecdev(adapter) &&
skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) { skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
/* FIXME: add support for retrieving timestamps from /* FIXME: add support for retrieving timestamps from
* the other timer registers before skipping the * the other timer registers before skipping the
@ -1623,7 +1623,7 @@ done:
return NETDEV_TX_OK; return NETDEV_TX_OK;
out_drop: out_drop:
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
dev_kfree_skb_any(first->skb); dev_kfree_skb_any(first->skb);
first->skb = NULL; first->skb = NULL;
} }
@ -2568,10 +2568,10 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget)
total_packets++; total_packets++;
total_bytes += size; total_bytes += size;
} }
else if (adapter->ecdev) { else if (get_ecdev(adapter)) {
unsigned char *va = page_address(rx_buffer->page) + rx_buffer->page_offset; unsigned char *va = page_address(rx_buffer->page) + rx_buffer->page_offset;
unsigned int size = le16_to_cpu(rx_desc->wb.upper.length); unsigned int size = le16_to_cpu(rx_desc->wb.upper.length);
ecdev_receive(adapter->ecdev, va, size); ecdev_receive(get_ecdev(adapter), va, size);
adapter->ec_watchdog_jiffies = jiffies; adapter->ec_watchdog_jiffies = jiffies;
igc_reuse_rx_page(rx_ring, rx_buffer); igc_reuse_rx_page(rx_ring, rx_buffer);
} }
@ -2600,7 +2600,7 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget)
continue; continue;
if (adapter->ecdev) { if (get_ecdev(adapter)) {
total_packets++; total_packets++;
continue; continue;
} }
@ -2913,7 +2913,7 @@ static bool igc_clean_tx_irq(struct igc_q_vector *q_vector, int napi_budget)
igc_unmap_tx_buffer(tx_ring->dev, tx_buffer); igc_unmap_tx_buffer(tx_ring->dev, tx_buffer);
break; break;
case IGC_TX_BUFFER_TYPE_SKB: case IGC_TX_BUFFER_TYPE_SKB:
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
napi_consume_skb(tx_buffer->skb, napi_budget); napi_consume_skb(tx_buffer->skb, napi_budget);
} }
igc_unmap_tx_buffer(tx_ring->dev, tx_buffer); igc_unmap_tx_buffer(tx_ring->dev, tx_buffer);
@ -2956,7 +2956,7 @@ static bool igc_clean_tx_irq(struct igc_q_vector *q_vector, int napi_budget)
budget--; budget--;
} while (likely(budget)); } while (likely(budget));
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
netdev_tx_completed_queue(txring_txq(tx_ring), netdev_tx_completed_queue(txring_txq(tx_ring),
total_packets, total_bytes); total_packets, total_bytes);
} }
@ -2974,7 +2974,7 @@ static bool igc_clean_tx_irq(struct igc_q_vector *q_vector, int napi_budget)
igc_xdp_xmit_zc(tx_ring); igc_xdp_xmit_zc(tx_ring);
} }
if (!adapter->ecdev && if (!get_ecdev(adapter) &&
test_bit(IGC_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags)) { test_bit(IGC_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags)) {
struct igc_hw *hw = &adapter->hw; struct igc_hw *hw = &adapter->hw;
@ -3019,7 +3019,7 @@ static bool igc_clean_tx_irq(struct igc_q_vector *q_vector, int napi_budget)
} }
#define TX_WAKE_THRESHOLD (DESC_NEEDED * 2) #define TX_WAKE_THRESHOLD (DESC_NEEDED * 2)
if (unlikely(!adapter->ecdev && total_packets && if (unlikely(!get_ecdev(adapter) && total_packets &&
netif_carrier_ok(tx_ring->netdev) && netif_carrier_ok(tx_ring->netdev) &&
igc_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD)) { igc_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD)) {
/* Make sure that anybody stopping the queue after this /* Make sure that anybody stopping the queue after this
@ -3989,7 +3989,7 @@ static void igc_configure_msix(struct igc_adapter *adapter)
*/ */
static void igc_irq_enable(struct igc_adapter *adapter) static void igc_irq_enable(struct igc_adapter *adapter)
{ {
if (adapter->ecdev) { if (get_ecdev(adapter)) {
/* skip enabling interrupts */ /* skip enabling interrupts */
return; return;
} }
@ -4032,7 +4032,7 @@ static void igc_irq_disable(struct igc_adapter *adapter)
wr32(IGC_IMC, ~0); wr32(IGC_IMC, ~0);
wrfl(); wrfl();
if (adapter->ecdev) { if (get_ecdev(adapter)) {
/* skip synchonizing IRQs */ /* skip synchonizing IRQs */
return; return;
} }
@ -4503,6 +4503,9 @@ static int igc_poll(struct napi_struct *napi, int budget)
bool clean_complete = true; bool clean_complete = true;
int work_done = 0; int work_done = 0;
if (get_ecdev(q_vector->adapter))
return -EBUSY;
if (q_vector->tx.ring) if (q_vector->tx.ring)
clean_complete = igc_clean_tx_irq(q_vector, budget); clean_complete = igc_clean_tx_irq(q_vector, budget);
@ -4794,7 +4797,7 @@ void igc_up(struct igc_adapter *adapter)
igc_configure(adapter); igc_configure(adapter);
clear_bit(__IGC_DOWN, &adapter->state); clear_bit(__IGC_DOWN, &adapter->state);
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
for (i = 0; i < adapter->num_q_vectors; i++) for (i = 0; i < adapter->num_q_vectors; i++)
napi_enable(&adapter->q_vector[i]->napi); napi_enable(&adapter->q_vector[i]->napi);
} }
@ -4807,7 +4810,7 @@ void igc_up(struct igc_adapter *adapter)
rd32(IGC_ICR); rd32(IGC_ICR);
igc_irq_enable(adapter); igc_irq_enable(adapter);
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
netif_tx_start_all_queues(adapter->netdev); netif_tx_start_all_queues(adapter->netdev);
/* start the watchdog. */ /* start the watchdog. */
@ -5005,7 +5008,7 @@ void igc_down(struct igc_adapter *adapter)
} }
/* set trans_start so we don't get spurious watchdogs during reset */ /* set trans_start so we don't get spurious watchdogs during reset */
netif_trans_update(netdev); netif_trans_update(netdev);
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
netif_carrier_off(netdev); netif_carrier_off(netdev);
netif_tx_stop_all_queues(netdev); netif_tx_stop_all_queues(netdev);
} }
@ -5025,7 +5028,7 @@ void igc_down(struct igc_adapter *adapter)
adapter->flags &= ~IGC_FLAG_NEED_LINK_UPDATE; adapter->flags &= ~IGC_FLAG_NEED_LINK_UPDATE;
for (i = 0; i < adapter->num_q_vectors; i++) { for (i = 0; i < adapter->num_q_vectors; i++) {
if (!adapter->ecdev && adapter->q_vector[i]) { if (!get_ecdev(adapter) && adapter->q_vector[i]) {
napi_synchronize(&adapter->q_vector[i]->napi); napi_synchronize(&adapter->q_vector[i]->napi);
napi_disable(&adapter->q_vector[i]->napi); napi_disable(&adapter->q_vector[i]->napi);
} }
@ -5384,7 +5387,7 @@ static int igc_request_msix(struct igc_adapter *adapter)
unsigned int num_q_vectors = adapter->num_q_vectors; unsigned int num_q_vectors = adapter->num_q_vectors;
int i = 0, err = 0, vector = 0, free_vector = 0; int i = 0, err = 0, vector = 0, free_vector = 0;
struct net_device *netdev = adapter->netdev; struct net_device *netdev = adapter->netdev;
if (adapter->ecdev) { if (get_ecdev(adapter)) {
/* avoid requesting MSI-X. */ /* avoid requesting MSI-X. */
return 0; return 0;
} }
@ -5519,13 +5522,13 @@ static void igc_watchdog_task(struct work_struct *work)
u32 link; u32 link;
int i; int i;
if (adapter->ecdev) if (get_ecdev(adapter))
hw->mac.get_link_status = true; hw->mac.get_link_status = true;
link = igc_has_link(adapter); link = igc_has_link(adapter);
if (adapter->ecdev) { if (get_ecdev(adapter)) {
ecdev_set_link(adapter->ecdev, link); ecdev_set_link(get_ecdev(adapter), link);
return; return;
} }
@ -5782,7 +5785,7 @@ static irqreturn_t igc_intr(int irq, void *data)
static void igc_free_irq(struct igc_adapter *adapter) static void igc_free_irq(struct igc_adapter *adapter)
{ {
if (adapter->ecdev) { if (get_ecdev(adapter)) {
/* no IRQ to free in EtherCAT operation */ /* no IRQ to free in EtherCAT operation */
return; return;
} }
@ -5832,7 +5835,7 @@ static int igc_request_irq(struct igc_adapter *adapter)
igc_assign_vector(adapter->q_vector[0], 0); igc_assign_vector(adapter->q_vector[0], 0);
if (!adapter->ecdev && adapter->flags & IGC_FLAG_HAS_MSI) { if (!get_ecdev(adapter) && adapter->flags & IGC_FLAG_HAS_MSI) {
err = request_irq(pdev->irq, &igc_intr_msi, 0, err = request_irq(pdev->irq, &igc_intr_msi, 0,
netdev->name, adapter); netdev->name, adapter);
if (!err) if (!err)
@ -5843,7 +5846,7 @@ static int igc_request_irq(struct igc_adapter *adapter)
adapter->flags &= ~IGC_FLAG_HAS_MSI; adapter->flags &= ~IGC_FLAG_HAS_MSI;
} }
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
err = request_irq(pdev->irq, &igc_intr, IRQF_SHARED, err = request_irq(pdev->irq, &igc_intr, IRQF_SHARED,
netdev->name, adapter); netdev->name, adapter);
@ -5885,8 +5888,8 @@ static int __igc_open(struct net_device *netdev, bool resuming)
if (!resuming) if (!resuming)
pm_runtime_get_sync(&pdev->dev); pm_runtime_get_sync(&pdev->dev);
if (adapter->ecdev) { if (get_ecdev(adapter)) {
ecdev_set_link(adapter->ecdev, 0); ecdev_set_link(get_ecdev(adapter), 0);
} }
else { else {
netif_carrier_off(netdev); netif_carrier_off(netdev);
@ -5910,7 +5913,7 @@ static int __igc_open(struct net_device *netdev, bool resuming)
if (err) if (err)
goto err_req_irq; goto err_req_irq;
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
/* Notify the stack of the actual queue counts. */ /* Notify the stack of the actual queue counts. */
err = netif_set_real_num_tx_queues(netdev, adapter->num_tx_queues); err = netif_set_real_num_tx_queues(netdev, adapter->num_tx_queues);
if (err) if (err)
@ -5922,7 +5925,7 @@ static int __igc_open(struct net_device *netdev, bool resuming)
} }
clear_bit(__IGC_DOWN, &adapter->state); clear_bit(__IGC_DOWN, &adapter->state);
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
for (i = 0; i < adapter->num_q_vectors; i++) for (i = 0; i < adapter->num_q_vectors; i++)
napi_enable(&adapter->q_vector[i]->napi); napi_enable(&adapter->q_vector[i]->napi);
} }
@ -5934,11 +5937,11 @@ static int __igc_open(struct net_device *netdev, bool resuming)
if (!resuming) if (!resuming)
pm_runtime_put(&pdev->dev); pm_runtime_put(&pdev->dev);
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
netif_tx_start_all_queues(netdev); netif_tx_start_all_queues(netdev);
} }
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
/* start the watchdog. */ /* start the watchdog. */
hw->mac.get_link_status = true; hw->mac.get_link_status = true;
schedule_work(&adapter->watchdog_task); schedule_work(&adapter->watchdog_task);
@ -6739,12 +6742,13 @@ static int igc_probe(struct pci_dev *pdev,
*/ */
igc_get_hw_control(adapter); igc_get_hw_control(adapter);
adapter->ecdev = ecdev_offer(netdev, ec_poll, THIS_MODULE); adapter->ecdev_ = ecdev_offer(netdev, ec_poll, THIS_MODULE);
if (adapter->ecdev) { adapter->ecdev_initialized = true;
if (get_ecdev(adapter)) {
init_irq_work(&adapter->ec_watchdog_kicker, ec_kick_watchdog); init_irq_work(&adapter->ec_watchdog_kicker, ec_kick_watchdog);
err = ecdev_open(adapter->ecdev); err = ecdev_open(get_ecdev(adapter));
if (err) { if (err) {
ecdev_withdraw(adapter->ecdev); ecdev_withdraw(get_ecdev(adapter));
goto err_register; goto err_register;
} }
adapter->ec_watchdog_jiffies = jiffies; adapter->ec_watchdog_jiffies = jiffies;
@ -6807,10 +6811,10 @@ static void igc_remove(struct pci_dev *pdev)
struct net_device *netdev = pci_get_drvdata(pdev); struct net_device *netdev = pci_get_drvdata(pdev);
struct igc_adapter *adapter = netdev_priv(netdev); struct igc_adapter *adapter = netdev_priv(netdev);
if (adapter->ecdev) { if (get_ecdev(adapter)) {
ecdev_close(adapter->ecdev); ecdev_close(get_ecdev(adapter));
irq_work_sync(&adapter->ec_watchdog_kicker); irq_work_sync(&adapter->ec_watchdog_kicker);
ecdev_withdraw(adapter->ecdev); ecdev_withdraw(get_ecdev(adapter));
} }
pm_runtime_get_noresume(&pdev->dev); pm_runtime_get_noresume(&pdev->dev);
@ -6834,7 +6838,7 @@ static void igc_remove(struct pci_dev *pdev)
* would have already happened in close and is redundant. * would have already happened in close and is redundant.
*/ */
igc_release_hw_control(adapter); igc_release_hw_control(adapter);
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
unregister_netdev(netdev); unregister_netdev(netdev);
} }
@ -6859,8 +6863,8 @@ static int __igc_shutdown(struct pci_dev *pdev, bool *enable_wake,
u32 ctrl, rctl, status; u32 ctrl, rctl, status;
bool wake; bool wake;
if (adapter->ecdev) { if (get_ecdev(adapter)) {
ecdev_close(adapter->ecdev); ecdev_close(get_ecdev(adapter));
} else { } else {
rtnl_lock(); rtnl_lock();
netif_device_detach(netdev); netif_device_detach(netdev);
@ -7000,8 +7004,8 @@ static int __maybe_unused igc_resume(struct device *dev)
wr32(IGC_WUS, ~0); wr32(IGC_WUS, ~0);
if (adapter->ecdev) { if (get_ecdev(adapter)) {
ecdev_open(adapter->ecdev); ecdev_open(get_ecdev(adapter));
} else { } else {
rtnl_lock(); rtnl_lock();
if (!err && netif_running(netdev)) if (!err && netif_running(netdev))

View File

@ -211,7 +211,7 @@ static void igc_clean_tx_ring(struct igc_ring *tx_ring)
case IGC_TX_BUFFER_TYPE_SKB: case IGC_TX_BUFFER_TYPE_SKB:
{ {
struct igc_adapter *adapter = netdev_priv(tx_ring->netdev); struct igc_adapter *adapter = netdev_priv(tx_ring->netdev);
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
/* skb is reused in EtherCAT TX operation */ /* skb is reused in EtherCAT TX operation */
dev_kfree_skb_any(tx_buffer->skb); dev_kfree_skb_any(tx_buffer->skb);
} }
@ -1202,7 +1202,7 @@ static int __igc_maybe_stop_tx(struct igc_ring *tx_ring, const u16 size)
{ {
struct net_device *netdev = tx_ring->netdev; struct net_device *netdev = tx_ring->netdev;
struct igc_adapter *adapter = netdev_priv(netdev); struct igc_adapter *adapter = netdev_priv(netdev);
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
netif_stop_subqueue(netdev, tx_ring->queue_index); netif_stop_subqueue(netdev, tx_ring->queue_index);
} }
@ -1216,7 +1216,7 @@ static int __igc_maybe_stop_tx(struct igc_ring *tx_ring, const u16 size)
return -EBUSY; return -EBUSY;
/* A reprieve! */ /* A reprieve! */
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
netif_wake_subqueue(netdev, tx_ring->queue_index); netif_wake_subqueue(netdev, tx_ring->queue_index);
} }
@ -1414,7 +1414,7 @@ dma_error:
if (dma_unmap_len(tx_buffer, len)) if (dma_unmap_len(tx_buffer, len))
igc_unmap_tx_buffer(tx_ring->dev, tx_buffer); igc_unmap_tx_buffer(tx_ring->dev, tx_buffer);
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
dev_kfree_skb_any(tx_buffer->skb); dev_kfree_skb_any(tx_buffer->skb);
tx_buffer->skb = NULL; tx_buffer->skb = NULL;
} }
@ -1593,7 +1593,7 @@ done:
goto out_drop; goto out_drop;
} }
if (unlikely(!adapter->ecdev && if (unlikely(!get_ecdev(adapter) &&
test_bit(IGC_RING_FLAG_TX_HWTSTAMP, &tx_ring->flags) && test_bit(IGC_RING_FLAG_TX_HWTSTAMP, &tx_ring->flags) &&
(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP))) { (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP))) {
/* FIXME: add support for retrieving timestamps from /* FIXME: add support for retrieving timestamps from
@ -1636,7 +1636,7 @@ done:
return NETDEV_TX_OK; return NETDEV_TX_OK;
out_drop: out_drop:
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
dev_kfree_skb_any(first->skb); dev_kfree_skb_any(first->skb);
first->skb = NULL; first->skb = NULL;
} }
@ -2606,10 +2606,10 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget)
total_packets++; total_packets++;
total_bytes += size; total_bytes += size;
} }
else if (adapter->ecdev) { else if (get_ecdev(adapter)) {
unsigned char *va = page_address(rx_buffer->page) + rx_buffer->page_offset; unsigned char *va = page_address(rx_buffer->page) + rx_buffer->page_offset;
unsigned int size = le16_to_cpu(rx_desc->wb.upper.length); unsigned int size = le16_to_cpu(rx_desc->wb.upper.length);
ecdev_receive(adapter->ecdev, va, size); ecdev_receive(get_ecdev(adapter), va, size);
adapter->ec_watchdog_jiffies = jiffies; adapter->ec_watchdog_jiffies = jiffies;
igc_reuse_rx_page(rx_ring, rx_buffer); igc_reuse_rx_page(rx_ring, rx_buffer);
} }
@ -2638,7 +2638,7 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget)
continue; continue;
if (adapter->ecdev) { if (get_ecdev(adapter)) {
total_packets++; total_packets++;
continue; continue;
} }
@ -2964,7 +2964,7 @@ static bool igc_clean_tx_irq(struct igc_q_vector *q_vector, int napi_budget)
igc_unmap_tx_buffer(tx_ring->dev, tx_buffer); igc_unmap_tx_buffer(tx_ring->dev, tx_buffer);
break; break;
case IGC_TX_BUFFER_TYPE_SKB: case IGC_TX_BUFFER_TYPE_SKB:
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
napi_consume_skb(tx_buffer->skb, napi_budget); napi_consume_skb(tx_buffer->skb, napi_budget);
} }
igc_unmap_tx_buffer(tx_ring->dev, tx_buffer); igc_unmap_tx_buffer(tx_ring->dev, tx_buffer);
@ -3007,7 +3007,7 @@ static bool igc_clean_tx_irq(struct igc_q_vector *q_vector, int napi_budget)
budget--; budget--;
} while (likely(budget)); } while (likely(budget));
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
netdev_tx_completed_queue(txring_txq(tx_ring), netdev_tx_completed_queue(txring_txq(tx_ring),
total_packets, total_bytes); total_packets, total_bytes);
} }
@ -3025,7 +3025,7 @@ static bool igc_clean_tx_irq(struct igc_q_vector *q_vector, int napi_budget)
igc_xdp_xmit_zc(tx_ring); igc_xdp_xmit_zc(tx_ring);
} }
if (!adapter->ecdev && if (!get_ecdev(adapter) &&
test_bit(IGC_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags)) { test_bit(IGC_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags)) {
struct igc_hw *hw = &adapter->hw; struct igc_hw *hw = &adapter->hw;
@ -3070,7 +3070,7 @@ static bool igc_clean_tx_irq(struct igc_q_vector *q_vector, int napi_budget)
} }
#define TX_WAKE_THRESHOLD (DESC_NEEDED * 2) #define TX_WAKE_THRESHOLD (DESC_NEEDED * 2)
if (unlikely(!adapter->ecdev && total_packets && if (unlikely(!get_ecdev(adapter) && total_packets &&
netif_carrier_ok(tx_ring->netdev) && netif_carrier_ok(tx_ring->netdev) &&
igc_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD)) { igc_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD)) {
/* Make sure that anybody stopping the queue after this /* Make sure that anybody stopping the queue after this
@ -4040,7 +4040,7 @@ static void igc_configure_msix(struct igc_adapter *adapter)
*/ */
static void igc_irq_enable(struct igc_adapter *adapter) static void igc_irq_enable(struct igc_adapter *adapter)
{ {
if (adapter->ecdev) { if (get_ecdev(adapter)) {
/* skip enabling interrupts */ /* skip enabling interrupts */
return; return;
} }
@ -4083,7 +4083,7 @@ static void igc_irq_disable(struct igc_adapter *adapter)
wr32(IGC_IMC, ~0); wr32(IGC_IMC, ~0);
wrfl(); wrfl();
if (adapter->ecdev) { if (get_ecdev(adapter)) {
/* skip synchonizing IRQs */ /* skip synchonizing IRQs */
return; return;
} }
@ -4554,6 +4554,9 @@ static int igc_poll(struct napi_struct *napi, int budget)
bool clean_complete = true; bool clean_complete = true;
int work_done = 0; int work_done = 0;
if (get_ecdev(q_vector->adapter))
return -EBUSY;
if (q_vector->tx.ring) if (q_vector->tx.ring)
clean_complete = igc_clean_tx_irq(q_vector, budget); clean_complete = igc_clean_tx_irq(q_vector, budget);
@ -4846,7 +4849,7 @@ void igc_up(struct igc_adapter *adapter)
igc_configure(adapter); igc_configure(adapter);
clear_bit(__IGC_DOWN, &adapter->state); clear_bit(__IGC_DOWN, &adapter->state);
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
for (i = 0; i < adapter->num_q_vectors; i++) for (i = 0; i < adapter->num_q_vectors; i++)
napi_enable(&adapter->q_vector[i]->napi); napi_enable(&adapter->q_vector[i]->napi);
} }
@ -4859,7 +4862,7 @@ void igc_up(struct igc_adapter *adapter)
rd32(IGC_ICR); rd32(IGC_ICR);
igc_irq_enable(adapter); igc_irq_enable(adapter);
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
netif_tx_start_all_queues(adapter->netdev); netif_tx_start_all_queues(adapter->netdev);
/* start the watchdog. */ /* start the watchdog. */
@ -5058,7 +5061,7 @@ void igc_down(struct igc_adapter *adapter)
} }
/* set trans_start so we don't get spurious watchdogs during reset */ /* set trans_start so we don't get spurious watchdogs during reset */
netif_trans_update(netdev); netif_trans_update(netdev);
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
netif_carrier_off(netdev); netif_carrier_off(netdev);
netif_tx_stop_all_queues(netdev); netif_tx_stop_all_queues(netdev);
} }
@ -5078,7 +5081,7 @@ void igc_down(struct igc_adapter *adapter)
adapter->flags &= ~IGC_FLAG_NEED_LINK_UPDATE; adapter->flags &= ~IGC_FLAG_NEED_LINK_UPDATE;
for (i = 0; i < adapter->num_q_vectors; i++) { for (i = 0; i < adapter->num_q_vectors; i++) {
if (!adapter->ecdev && adapter->q_vector[i]) { if (!get_ecdev(adapter) && adapter->q_vector[i]) {
napi_synchronize(&adapter->q_vector[i]->napi); napi_synchronize(&adapter->q_vector[i]->napi);
napi_disable(&adapter->q_vector[i]->napi); napi_disable(&adapter->q_vector[i]->napi);
} }
@ -5437,7 +5440,7 @@ static int igc_request_msix(struct igc_adapter *adapter)
unsigned int num_q_vectors = adapter->num_q_vectors; unsigned int num_q_vectors = adapter->num_q_vectors;
int i = 0, err = 0, vector = 0, free_vector = 0; int i = 0, err = 0, vector = 0, free_vector = 0;
struct net_device *netdev = adapter->netdev; struct net_device *netdev = adapter->netdev;
if (adapter->ecdev) { if (get_ecdev(adapter)) {
/* avoid requesting MSI-X. */ /* avoid requesting MSI-X. */
return 0; return 0;
} }
@ -5572,13 +5575,13 @@ static void igc_watchdog_task(struct work_struct *work)
u32 link; u32 link;
int i; int i;
if (adapter->ecdev) if (get_ecdev(adapter))
hw->mac.get_link_status = true; hw->mac.get_link_status = true;
link = igc_has_link(adapter); link = igc_has_link(adapter);
if (adapter->ecdev) { if (get_ecdev(adapter)) {
ecdev_set_link(adapter->ecdev, link); ecdev_set_link(get_ecdev(adapter), link);
return; return;
} }
@ -5825,7 +5828,7 @@ static irqreturn_t igc_intr(int irq, void *data)
static void igc_free_irq(struct igc_adapter *adapter) static void igc_free_irq(struct igc_adapter *adapter)
{ {
if (adapter->ecdev) { if (get_ecdev(adapter)) {
/* no IRQ to free in EtherCAT operation */ /* no IRQ to free in EtherCAT operation */
return; return;
} }
@ -5875,7 +5878,7 @@ static int igc_request_irq(struct igc_adapter *adapter)
igc_assign_vector(adapter->q_vector[0], 0); igc_assign_vector(adapter->q_vector[0], 0);
if (!adapter->ecdev && adapter->flags & IGC_FLAG_HAS_MSI) { if (!get_ecdev(adapter) && adapter->flags & IGC_FLAG_HAS_MSI) {
err = request_irq(pdev->irq, &igc_intr_msi, 0, err = request_irq(pdev->irq, &igc_intr_msi, 0,
netdev->name, adapter); netdev->name, adapter);
if (!err) if (!err)
@ -5886,7 +5889,7 @@ static int igc_request_irq(struct igc_adapter *adapter)
adapter->flags &= ~IGC_FLAG_HAS_MSI; adapter->flags &= ~IGC_FLAG_HAS_MSI;
} }
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
err = request_irq(pdev->irq, &igc_intr, IRQF_SHARED, err = request_irq(pdev->irq, &igc_intr, IRQF_SHARED,
netdev->name, adapter); netdev->name, adapter);
@ -5928,8 +5931,8 @@ static int __igc_open(struct net_device *netdev, bool resuming)
if (!resuming) if (!resuming)
pm_runtime_get_sync(&pdev->dev); pm_runtime_get_sync(&pdev->dev);
if (adapter->ecdev) { if (get_ecdev(adapter)) {
ecdev_set_link(adapter->ecdev, 0); ecdev_set_link(get_ecdev(adapter), 0);
} }
else { else {
netif_carrier_off(netdev); netif_carrier_off(netdev);
@ -5953,7 +5956,7 @@ static int __igc_open(struct net_device *netdev, bool resuming)
if (err) if (err)
goto err_req_irq; goto err_req_irq;
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
/* Notify the stack of the actual queue counts. */ /* Notify the stack of the actual queue counts. */
err = netif_set_real_num_tx_queues(netdev, adapter->num_tx_queues); err = netif_set_real_num_tx_queues(netdev, adapter->num_tx_queues);
if (err) if (err)
@ -5965,7 +5968,7 @@ static int __igc_open(struct net_device *netdev, bool resuming)
} }
clear_bit(__IGC_DOWN, &adapter->state); clear_bit(__IGC_DOWN, &adapter->state);
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
for (i = 0; i < adapter->num_q_vectors; i++) for (i = 0; i < adapter->num_q_vectors; i++)
napi_enable(&adapter->q_vector[i]->napi); napi_enable(&adapter->q_vector[i]->napi);
} }
@ -5977,11 +5980,11 @@ static int __igc_open(struct net_device *netdev, bool resuming)
if (!resuming) if (!resuming)
pm_runtime_put(&pdev->dev); pm_runtime_put(&pdev->dev);
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
netif_tx_start_all_queues(netdev); netif_tx_start_all_queues(netdev);
} }
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
/* start the watchdog. */ /* start the watchdog. */
hw->mac.get_link_status = true; hw->mac.get_link_status = true;
schedule_work(&adapter->watchdog_task); schedule_work(&adapter->watchdog_task);
@ -6913,12 +6916,13 @@ static int igc_probe(struct pci_dev *pdev,
*/ */
igc_get_hw_control(adapter); igc_get_hw_control(adapter);
adapter->ecdev = ecdev_offer(netdev, ec_poll, THIS_MODULE); adapter->ecdev_ = ecdev_offer(netdev, ec_poll, THIS_MODULE);
if (adapter->ecdev) { adapter->ecdev_initialized = true;
if (get_ecdev(adapter)) {
init_irq_work(&adapter->ec_watchdog_kicker, ec_kick_watchdog); init_irq_work(&adapter->ec_watchdog_kicker, ec_kick_watchdog);
err = ecdev_open(adapter->ecdev); err = ecdev_open(get_ecdev(adapter));
if (err) { if (err) {
ecdev_withdraw(adapter->ecdev); ecdev_withdraw(get_ecdev(adapter));
goto err_register; goto err_register;
} }
adapter->ec_watchdog_jiffies = jiffies; adapter->ec_watchdog_jiffies = jiffies;
@ -6980,10 +6984,10 @@ static void igc_remove(struct pci_dev *pdev)
struct net_device *netdev = pci_get_drvdata(pdev); struct net_device *netdev = pci_get_drvdata(pdev);
struct igc_adapter *adapter = netdev_priv(netdev); struct igc_adapter *adapter = netdev_priv(netdev);
if (adapter->ecdev) { if (get_ecdev(adapter)) {
ecdev_close(adapter->ecdev); ecdev_close(get_ecdev(adapter));
irq_work_sync(&adapter->ec_watchdog_kicker); irq_work_sync(&adapter->ec_watchdog_kicker);
ecdev_withdraw(adapter->ecdev); ecdev_withdraw(get_ecdev(adapter));
} }
pm_runtime_get_noresume(&pdev->dev); pm_runtime_get_noresume(&pdev->dev);
@ -7008,7 +7012,7 @@ static void igc_remove(struct pci_dev *pdev)
* would have already happened in close and is redundant. * would have already happened in close and is redundant.
*/ */
igc_release_hw_control(adapter); igc_release_hw_control(adapter);
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
unregister_netdev(netdev); unregister_netdev(netdev);
} }
@ -7031,8 +7035,8 @@ static int __igc_shutdown(struct pci_dev *pdev, bool *enable_wake,
u32 ctrl, rctl, status; u32 ctrl, rctl, status;
bool wake; bool wake;
if (adapter->ecdev) { if (get_ecdev(adapter)) {
ecdev_close(adapter->ecdev); ecdev_close(get_ecdev(adapter));
} else { } else {
rtnl_lock(); rtnl_lock();
netif_device_detach(netdev); netif_device_detach(netdev);
@ -7172,8 +7176,8 @@ static int __maybe_unused igc_resume(struct device *dev)
wr32(IGC_WUS, ~0); wr32(IGC_WUS, ~0);
if (adapter->ecdev) { if (get_ecdev(adapter)) {
ecdev_open(adapter->ecdev); ecdev_open(get_ecdev(adapter));
} else { } else {
rtnl_lock(); rtnl_lock();
if (!err && netif_running(netdev)) if (!err && netif_running(netdev))

View File

@ -211,7 +211,7 @@ static void igc_clean_tx_ring(struct igc_ring *tx_ring)
case IGC_TX_BUFFER_TYPE_SKB: case IGC_TX_BUFFER_TYPE_SKB:
{ {
struct igc_adapter *adapter = netdev_priv(tx_ring->netdev); struct igc_adapter *adapter = netdev_priv(tx_ring->netdev);
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
/* skb is reused in EtherCAT TX operation */ /* skb is reused in EtherCAT TX operation */
dev_kfree_skb_any(tx_buffer->skb); dev_kfree_skb_any(tx_buffer->skb);
} }
@ -1229,7 +1229,7 @@ static int __igc_maybe_stop_tx(struct igc_ring *tx_ring, const u16 size)
{ {
struct net_device *netdev = tx_ring->netdev; struct net_device *netdev = tx_ring->netdev;
struct igc_adapter *adapter = netdev_priv(netdev); struct igc_adapter *adapter = netdev_priv(netdev);
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
netif_stop_subqueue(netdev, tx_ring->queue_index); netif_stop_subqueue(netdev, tx_ring->queue_index);
} }
@ -1243,7 +1243,7 @@ static int __igc_maybe_stop_tx(struct igc_ring *tx_ring, const u16 size)
return -EBUSY; return -EBUSY;
/* A reprieve! */ /* A reprieve! */
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
netif_wake_subqueue(netdev, tx_ring->queue_index); netif_wake_subqueue(netdev, tx_ring->queue_index);
} }
@ -1452,7 +1452,7 @@ dma_error:
if (dma_unmap_len(tx_buffer, len)) if (dma_unmap_len(tx_buffer, len))
igc_unmap_tx_buffer(tx_ring->dev, tx_buffer); igc_unmap_tx_buffer(tx_ring->dev, tx_buffer);
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
dev_kfree_skb_any(tx_buffer->skb); dev_kfree_skb_any(tx_buffer->skb);
tx_buffer->skb = NULL; tx_buffer->skb = NULL;
} }
@ -1651,7 +1651,7 @@ done:
goto out_drop; goto out_drop;
} }
if (unlikely(!adapter->ecdev && if (unlikely(!get_ecdev(adapter) &&
test_bit(IGC_RING_FLAG_TX_HWTSTAMP, &tx_ring->flags) && test_bit(IGC_RING_FLAG_TX_HWTSTAMP, &tx_ring->flags) &&
(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP))) { (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP))) {
/* FIXME: add support for retrieving timestamps from /* FIXME: add support for retrieving timestamps from
@ -1692,7 +1692,7 @@ done:
return NETDEV_TX_OK; return NETDEV_TX_OK;
out_drop: out_drop:
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
dev_kfree_skb_any(first->skb); dev_kfree_skb_any(first->skb);
first->skb = NULL; first->skb = NULL;
} }
@ -2665,10 +2665,10 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget)
total_packets++; total_packets++;
total_bytes += size; total_bytes += size;
} }
else if (adapter->ecdev) { else if (get_ecdev(adapter)) {
unsigned char *va = page_address(rx_buffer->page) + rx_buffer->page_offset; unsigned char *va = page_address(rx_buffer->page) + rx_buffer->page_offset;
unsigned int size = le16_to_cpu(rx_desc->wb.upper.length); unsigned int size = le16_to_cpu(rx_desc->wb.upper.length);
ecdev_receive(adapter->ecdev, va, size); ecdev_receive(get_ecdev(adapter), va, size);
adapter->ec_watchdog_jiffies = jiffies; adapter->ec_watchdog_jiffies = jiffies;
igc_reuse_rx_page(rx_ring, rx_buffer); igc_reuse_rx_page(rx_ring, rx_buffer);
} }
@ -2697,7 +2697,7 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget)
continue; continue;
if (adapter->ecdev) { if (get_ecdev(adapter)) {
total_packets++; total_packets++;
continue; continue;
} }
@ -3027,7 +3027,7 @@ static bool igc_clean_tx_irq(struct igc_q_vector *q_vector, int napi_budget)
igc_unmap_tx_buffer(tx_ring->dev, tx_buffer); igc_unmap_tx_buffer(tx_ring->dev, tx_buffer);
break; break;
case IGC_TX_BUFFER_TYPE_SKB: case IGC_TX_BUFFER_TYPE_SKB:
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
napi_consume_skb(tx_buffer->skb, napi_budget); napi_consume_skb(tx_buffer->skb, napi_budget);
} }
igc_unmap_tx_buffer(tx_ring->dev, tx_buffer); igc_unmap_tx_buffer(tx_ring->dev, tx_buffer);
@ -3070,7 +3070,7 @@ static bool igc_clean_tx_irq(struct igc_q_vector *q_vector, int napi_budget)
budget--; budget--;
} while (likely(budget)); } while (likely(budget));
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
netdev_tx_completed_queue(txring_txq(tx_ring), netdev_tx_completed_queue(txring_txq(tx_ring),
total_packets, total_bytes); total_packets, total_bytes);
} }
@ -3088,7 +3088,7 @@ static bool igc_clean_tx_irq(struct igc_q_vector *q_vector, int napi_budget)
igc_xdp_xmit_zc(tx_ring); igc_xdp_xmit_zc(tx_ring);
} }
if (!adapter->ecdev && if (!get_ecdev(adapter) &&
test_bit(IGC_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags)) { test_bit(IGC_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags)) {
struct igc_hw *hw = &adapter->hw; struct igc_hw *hw = &adapter->hw;
@ -3133,7 +3133,7 @@ static bool igc_clean_tx_irq(struct igc_q_vector *q_vector, int napi_budget)
} }
#define TX_WAKE_THRESHOLD (DESC_NEEDED * 2) #define TX_WAKE_THRESHOLD (DESC_NEEDED * 2)
if (unlikely(!adapter->ecdev && total_packets && if (unlikely(!get_ecdev(adapter) && total_packets &&
netif_carrier_ok(tx_ring->netdev) && netif_carrier_ok(tx_ring->netdev) &&
igc_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD)) { igc_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD)) {
/* Make sure that anybody stopping the queue after this /* Make sure that anybody stopping the queue after this
@ -4103,7 +4103,7 @@ static void igc_configure_msix(struct igc_adapter *adapter)
*/ */
static void igc_irq_enable(struct igc_adapter *adapter) static void igc_irq_enable(struct igc_adapter *adapter)
{ {
if (adapter->ecdev) { if (get_ecdev(adapter)) {
/* skip enabling interrupts */ /* skip enabling interrupts */
return; return;
} }
@ -4146,7 +4146,7 @@ static void igc_irq_disable(struct igc_adapter *adapter)
wr32(IGC_IMC, ~0); wr32(IGC_IMC, ~0);
wrfl(); wrfl();
if (adapter->ecdev) { if (get_ecdev(adapter)) {
/* skip synchonizing IRQs */ /* skip synchonizing IRQs */
return; return;
} }
@ -4617,6 +4617,9 @@ static int igc_poll(struct napi_struct *napi, int budget)
bool clean_complete = true; bool clean_complete = true;
int work_done = 0; int work_done = 0;
if (get_ecdev(q_vector->adapter))
return -EBUSY;
if (q_vector->tx.ring) if (q_vector->tx.ring)
clean_complete = igc_clean_tx_irq(q_vector, budget); clean_complete = igc_clean_tx_irq(q_vector, budget);
@ -4910,7 +4913,7 @@ void igc_up(struct igc_adapter *adapter)
igc_configure(adapter); igc_configure(adapter);
clear_bit(__IGC_DOWN, &adapter->state); clear_bit(__IGC_DOWN, &adapter->state);
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
for (i = 0; i < adapter->num_q_vectors; i++) for (i = 0; i < adapter->num_q_vectors; i++)
napi_enable(&adapter->q_vector[i]->napi); napi_enable(&adapter->q_vector[i]->napi);
} }
@ -4923,7 +4926,7 @@ void igc_up(struct igc_adapter *adapter)
rd32(IGC_ICR); rd32(IGC_ICR);
igc_irq_enable(adapter); igc_irq_enable(adapter);
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
netif_tx_start_all_queues(adapter->netdev); netif_tx_start_all_queues(adapter->netdev);
/* start the watchdog. */ /* start the watchdog. */
@ -5122,7 +5125,7 @@ void igc_down(struct igc_adapter *adapter)
} }
/* set trans_start so we don't get spurious watchdogs during reset */ /* set trans_start so we don't get spurious watchdogs during reset */
netif_trans_update(netdev); netif_trans_update(netdev);
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
netif_carrier_off(netdev); netif_carrier_off(netdev);
netif_tx_stop_all_queues(netdev); netif_tx_stop_all_queues(netdev);
} }
@ -5142,7 +5145,7 @@ void igc_down(struct igc_adapter *adapter)
adapter->flags &= ~IGC_FLAG_NEED_LINK_UPDATE; adapter->flags &= ~IGC_FLAG_NEED_LINK_UPDATE;
for (i = 0; i < adapter->num_q_vectors; i++) { for (i = 0; i < adapter->num_q_vectors; i++) {
if (!adapter->ecdev && adapter->q_vector[i]) { if (!get_ecdev(adapter) && adapter->q_vector[i]) {
napi_synchronize(&adapter->q_vector[i]->napi); napi_synchronize(&adapter->q_vector[i]->napi);
napi_disable(&adapter->q_vector[i]->napi); napi_disable(&adapter->q_vector[i]->napi);
} }
@ -5502,7 +5505,7 @@ static int igc_request_msix(struct igc_adapter *adapter)
unsigned int num_q_vectors = adapter->num_q_vectors; unsigned int num_q_vectors = adapter->num_q_vectors;
int i = 0, err = 0, vector = 0, free_vector = 0; int i = 0, err = 0, vector = 0, free_vector = 0;
struct net_device *netdev = adapter->netdev; struct net_device *netdev = adapter->netdev;
if (adapter->ecdev) { if (get_ecdev(adapter)) {
/* avoid requesting MSI-X. */ /* avoid requesting MSI-X. */
return 0; return 0;
} }
@ -5637,13 +5640,13 @@ static void igc_watchdog_task(struct work_struct *work)
u32 link; u32 link;
int i; int i;
if (adapter->ecdev) if (get_ecdev(adapter))
hw->mac.get_link_status = true; hw->mac.get_link_status = true;
link = igc_has_link(adapter); link = igc_has_link(adapter);
if (adapter->ecdev) { if (get_ecdev(adapter)) {
ecdev_set_link(adapter->ecdev, link); ecdev_set_link(get_ecdev(adapter), link);
return; return;
} }
@ -5890,7 +5893,7 @@ static irqreturn_t igc_intr(int irq, void *data)
static void igc_free_irq(struct igc_adapter *adapter) static void igc_free_irq(struct igc_adapter *adapter)
{ {
if (adapter->ecdev) { if (get_ecdev(adapter)) {
/* no IRQ to free in EtherCAT operation */ /* no IRQ to free in EtherCAT operation */
return; return;
} }
@ -5940,7 +5943,7 @@ static int igc_request_irq(struct igc_adapter *adapter)
igc_assign_vector(adapter->q_vector[0], 0); igc_assign_vector(adapter->q_vector[0], 0);
if (!adapter->ecdev && adapter->flags & IGC_FLAG_HAS_MSI) { if (!get_ecdev(adapter) && adapter->flags & IGC_FLAG_HAS_MSI) {
err = request_irq(pdev->irq, &igc_intr_msi, 0, err = request_irq(pdev->irq, &igc_intr_msi, 0,
netdev->name, adapter); netdev->name, adapter);
if (!err) if (!err)
@ -5951,7 +5954,7 @@ static int igc_request_irq(struct igc_adapter *adapter)
adapter->flags &= ~IGC_FLAG_HAS_MSI; adapter->flags &= ~IGC_FLAG_HAS_MSI;
} }
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
err = request_irq(pdev->irq, &igc_intr, IRQF_SHARED, err = request_irq(pdev->irq, &igc_intr, IRQF_SHARED,
netdev->name, adapter); netdev->name, adapter);
@ -5993,8 +5996,8 @@ static int __igc_open(struct net_device *netdev, bool resuming)
if (!resuming) if (!resuming)
pm_runtime_get_sync(&pdev->dev); pm_runtime_get_sync(&pdev->dev);
if (adapter->ecdev) { if (get_ecdev(adapter)) {
ecdev_set_link(adapter->ecdev, 0); ecdev_set_link(get_ecdev(adapter), 0);
} }
else { else {
netif_carrier_off(netdev); netif_carrier_off(netdev);
@ -6018,7 +6021,7 @@ static int __igc_open(struct net_device *netdev, bool resuming)
if (err) if (err)
goto err_req_irq; goto err_req_irq;
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
/* Notify the stack of the actual queue counts. */ /* Notify the stack of the actual queue counts. */
err = netif_set_real_num_tx_queues(netdev, adapter->num_tx_queues); err = netif_set_real_num_tx_queues(netdev, adapter->num_tx_queues);
if (err) if (err)
@ -6030,7 +6033,7 @@ static int __igc_open(struct net_device *netdev, bool resuming)
} }
clear_bit(__IGC_DOWN, &adapter->state); clear_bit(__IGC_DOWN, &adapter->state);
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
for (i = 0; i < adapter->num_q_vectors; i++) for (i = 0; i < adapter->num_q_vectors; i++)
napi_enable(&adapter->q_vector[i]->napi); napi_enable(&adapter->q_vector[i]->napi);
} }
@ -6042,11 +6045,11 @@ static int __igc_open(struct net_device *netdev, bool resuming)
if (!resuming) if (!resuming)
pm_runtime_put(&pdev->dev); pm_runtime_put(&pdev->dev);
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
netif_tx_start_all_queues(netdev); netif_tx_start_all_queues(netdev);
} }
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
/* start the watchdog. */ /* start the watchdog. */
hw->mac.get_link_status = true; hw->mac.get_link_status = true;
schedule_work(&adapter->watchdog_task); schedule_work(&adapter->watchdog_task);
@ -7053,12 +7056,13 @@ static int igc_probe(struct pci_dev *pdev,
*/ */
igc_get_hw_control(adapter); igc_get_hw_control(adapter);
adapter->ecdev = ecdev_offer(netdev, ec_poll, THIS_MODULE); adapter->ecdev_ = ecdev_offer(netdev, ec_poll, THIS_MODULE);
if (adapter->ecdev) { adapter->ecdev_initialized = true;
if (get_ecdev(adapter)) {
init_irq_work(&adapter->ec_watchdog_kicker, ec_kick_watchdog); init_irq_work(&adapter->ec_watchdog_kicker, ec_kick_watchdog);
err = ecdev_open(adapter->ecdev); err = ecdev_open(get_ecdev(adapter));
if (err) { if (err) {
ecdev_withdraw(adapter->ecdev); ecdev_withdraw(get_ecdev(adapter));
goto err_register; goto err_register;
} }
adapter->ec_watchdog_jiffies = jiffies; adapter->ec_watchdog_jiffies = jiffies;
@ -7120,10 +7124,10 @@ static void igc_remove(struct pci_dev *pdev)
struct net_device *netdev = pci_get_drvdata(pdev); struct net_device *netdev = pci_get_drvdata(pdev);
struct igc_adapter *adapter = netdev_priv(netdev); struct igc_adapter *adapter = netdev_priv(netdev);
if (adapter->ecdev) { if (get_ecdev(adapter)) {
ecdev_close(adapter->ecdev); ecdev_close(get_ecdev(adapter));
irq_work_sync(&adapter->ec_watchdog_kicker); irq_work_sync(&adapter->ec_watchdog_kicker);
ecdev_withdraw(adapter->ecdev); ecdev_withdraw(get_ecdev(adapter));
} }
pm_runtime_get_noresume(&pdev->dev); pm_runtime_get_noresume(&pdev->dev);
@ -7148,7 +7152,7 @@ static void igc_remove(struct pci_dev *pdev)
* would have already happened in close and is redundant. * would have already happened in close and is redundant.
*/ */
igc_release_hw_control(adapter); igc_release_hw_control(adapter);
if (!adapter->ecdev) { if (!get_ecdev(adapter)) {
unregister_netdev(netdev); unregister_netdev(netdev);
} }
@ -7171,8 +7175,8 @@ static int __igc_shutdown(struct pci_dev *pdev, bool *enable_wake,
u32 ctrl, rctl, status; u32 ctrl, rctl, status;
bool wake; bool wake;
if (adapter->ecdev) { if (get_ecdev(adapter)) {
ecdev_close(adapter->ecdev); ecdev_close(get_ecdev(adapter));
} else { } else {
rtnl_lock(); rtnl_lock();
netif_device_detach(netdev); netif_device_detach(netdev);
@ -7312,8 +7316,8 @@ static int __maybe_unused igc_resume(struct device *dev)
wr32(IGC_WUS, ~0); wr32(IGC_WUS, ~0);
if (adapter->ecdev) { if (get_ecdev(adapter)) {
ecdev_open(adapter->ecdev); ecdev_open(get_ecdev(adapter));
} else { } else {
rtnl_lock(); rtnl_lock();
if (!err && netif_running(netdev)) if (!err && netif_running(netdev))