From cf54188d74ef27b453d6ea7c8f43ac326caa142f Mon Sep 17 00:00:00 2001 From: Bjarne von Horn Date: Wed, 3 Apr 2024 11:13:39 +0200 Subject: [PATCH] WARN_ONCE on querying ecdev before ecdev_offer for e100 --- devices/Kbuild.in | 5 ++ devices/e100-6.1-ethercat.c | 108 ++++++++++++++++++++---------------- 2 files changed, 64 insertions(+), 49 deletions(-) diff --git a/devices/Kbuild.in b/devices/Kbuild.in index acd9a684..a46b0410 100644 --- a/devices/Kbuild.in +++ b/devices/Kbuild.in @@ -26,6 +26,11 @@ src := @abs_srcdir@ ccflags-y := -I@abs_top_builddir@ +ifeq (@ENABLE_DRIVER_RESOURCE_VERIFYING@,1) + ccflags-y += -DEC_ENABLE_DRIVER_RESOURCE_VERIFYING +endif + + REV := $(shell if test -s $(src)/../revision; then \ cat $(src)/../revision; \ else \ diff --git a/devices/e100-6.1-ethercat.c b/devices/e100-6.1-ethercat.c index 7bf75bc0..a8c88dd1 100644 --- a/devices/e100-6.1-ethercat.c +++ b/devices/e100-6.1-ethercat.c @@ -646,10 +646,19 @@ struct nic { __le16 eeprom[256]; spinlock_t mdio_lock; const struct firmware *fw; - ec_device_t *ecdev; + ec_device_t *ecdev_; unsigned long ec_watchdog_jiffies; + bool ecdev_initialized; }; +static inline ec_device_t *get_ecdev(struct nic *adapter) +{ +#ifdef EC_ENABLE_DRIVER_RESOURCE_VERIFYING + WARN_ON(!adapter->ecdev_initialized); +#endif + return adapter->ecdev_; +} + static inline void e100_write_flush(struct nic *nic) { /* Flush previous PCI writes through intermediate bridges @@ -661,7 +670,7 @@ static void e100_enable_irq(struct nic *nic) { unsigned long flags; - if (nic->ecdev) + if (get_ecdev(nic)) return; spin_lock_irqsave(&nic->cmd_lock, flags); @@ -674,11 +683,11 @@ static void e100_disable_irq(struct nic *nic) { unsigned long flags = 0; - if (!nic->ecdev) + if (!nic->ecdev_) spin_lock_irqsave(&nic->cmd_lock, flags); iowrite8(irq_mask_all, &nic->csr->scb.cmd_hi); e100_write_flush(nic); - if (!nic->ecdev) + if (!nic->ecdev_) spin_unlock_irqrestore(&nic->cmd_lock, flags); } @@ -868,7 +877,7 @@ static int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr) unsigned int i; int err = 0; - if (!nic->ecdev) + if (!get_ecdev(nic)) spin_lock_irqsave(&nic->cmd_lock, flags); /* Previous command is accepted when SCB clears */ @@ -889,7 +898,7 @@ static int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr) iowrite8(cmd, &nic->csr->scb.cmd_lo); err_unlock: - if (!nic->ecdev) + if (!get_ecdev(nic)) spin_unlock_irqrestore(&nic->cmd_lock, flags); return err; @@ -902,7 +911,7 @@ static int e100_exec_cb(struct nic *nic, struct sk_buff *skb, unsigned long flags; int err; - if (!nic->ecdev) { + if (!get_ecdev(nic)) { spin_lock_irqsave(&nic->cb_lock, flags); } @@ -950,7 +959,7 @@ static int e100_exec_cb(struct nic *nic, struct sk_buff *skb, } err_unlock: - if (!nic->ecdev) { + if (!get_ecdev(nic)) { spin_unlock_irqrestore(&nic->cb_lock, flags); } @@ -984,7 +993,7 @@ static u16 mdio_ctrl_hw(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data) * manipulation of the MDI control registers is a multi-step * procedure it should be done under lock. */ - if (!nic->ecdev) + if (!nic->ecdev_) /* exemption of initialization check */ spin_lock_irqsave(&nic->mdio_lock, flags); for (i = 100; i; --i) { if (ioread32(&nic->csr->mdi_ctrl) & mdi_ready) @@ -993,7 +1002,7 @@ static u16 mdio_ctrl_hw(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data) } if (unlikely(!i)) { netdev_err(nic->netdev, "e100.mdio_ctrl won't go Ready\n"); - if (!nic->ecdev) + if (!get_ecdev(nic)) spin_unlock_irqrestore(&nic->mdio_lock, flags); return 0; /* No way to indicate timeout error */ } @@ -1004,7 +1013,7 @@ static u16 mdio_ctrl_hw(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data) if ((data_out = ioread32(&nic->csr->mdi_ctrl)) & mdi_ready) break; } - if (!nic->ecdev) + if (!nic->ecdev_) spin_unlock_irqrestore(&nic->mdio_lock, flags); netif_printk(nic, hw, KERN_DEBUG, nic->netdev, "%s:addr=%d, reg=%d, data_in=0x%04X, data_out=0x%04X\n", @@ -1182,7 +1191,7 @@ static int e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) config->multicast_all = 0x1; /* 1=accept, 0=no */ /* disable WoL when up */ - if (nic->ecdev || + if (get_ecdev(nic) || (netif_running(nic->netdev) || !(nic->flags & wol_magic))) config->magic_packet_disable = 0x1; /* 1=off, 0=on */ @@ -1748,8 +1757,8 @@ static void e100_watchdog_impl(struct nic *nic) struct ethtool_cmd cmd = { .cmd = ETHTOOL_GSET }; u32 speed; - if (nic->ecdev) { - ecdev_set_link(nic->ecdev, mii_link_ok(&nic->mii) ? 1 : 0); + if (get_ecdev(nic)) { + ecdev_set_link(get_ecdev(nic), mii_link_ok(&nic->mii) ? 1 : 0); return; } @@ -1862,14 +1871,14 @@ static netdev_tx_t e100_xmit_frame(struct sk_buff *skb, /* We queued the skb, but now we're out of space. */ netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev, "No space for CB\n"); - if (!nic->ecdev) + if (!get_ecdev(nic)) netif_stop_queue(netdev); break; case -ENOMEM: /* This is a hard error - log it. */ netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev, "Out of Tx resources, returning skb\n"); - if (!nic->ecdev) + if (!get_ecdev(nic)) netif_stop_queue(netdev); return NETDEV_TX_BUSY; } @@ -1883,7 +1892,7 @@ static int e100_tx_clean(struct nic *nic) struct cb *cb; int tx_cleaned = 0; - if (!nic->ecdev) + if (!get_ecdev(nic)) spin_lock(&nic->cb_lock); /* Clean CBs marked complete */ @@ -1904,7 +1913,7 @@ static int e100_tx_clean(struct nic *nic) le32_to_cpu(cb->u.tcb.tbd.buf_addr), le16_to_cpu(cb->u.tcb.tbd.size), DMA_TO_DEVICE); - if (!nic->ecdev) + if (!get_ecdev(nic)) dev_kfree_skb_any(cb->skb); cb->skb = NULL; tx_cleaned = 1; @@ -1913,7 +1922,7 @@ static int e100_tx_clean(struct nic *nic) nic->cbs_avail++; } - if (!nic->ecdev) { + if (!get_ecdev(nic)) { spin_unlock(&nic->cb_lock); /* Recover from running out of Tx resources in xmit_frame */ @@ -1934,7 +1943,7 @@ static void e100_clean_cbs(struct nic *nic) le32_to_cpu(cb->u.tcb.tbd.buf_addr), le16_to_cpu(cb->u.tcb.tbd.size), DMA_TO_DEVICE); - if (!nic->ecdev) + if (!get_ecdev(nic)) dev_kfree_skb(cb->skb); } nic->cb_to_clean = nic->cb_to_clean->next; @@ -2089,7 +2098,7 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx, nic->ru_running = RU_SUSPENDED; } - if (!nic->ecdev) { + if (!get_ecdev(nic)) { /* Pull off the RFD and put the actual data (minus eth hdr) */ skb_reserve(skb, sizeof(struct rfd)); skb_put(skb, actual_size); @@ -2107,27 +2116,27 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx, } if (unlikely(!(rfd_status & cb_ok))) { - if (!nic->ecdev) { + if (!get_ecdev(nic)) { /* Don't indicate if hardware indicates errors */ dev_kfree_skb_any(skb); } } else if (actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN + fcs_pad) { /* Don't indicate oversized frames */ nic->rx_over_length_errors++; - if (!nic->ecdev) { + if (!get_ecdev(nic)) { dev_kfree_skb_any(skb); } } else { process_skb: dev->stats.rx_packets++; dev->stats.rx_bytes += (actual_size - fcs_pad); - if (nic->ecdev) { - ecdev_receive(nic->ecdev, + if (get_ecdev(nic)) { + ecdev_receive(get_ecdev(nic), skb->data + sizeof(struct rfd), actual_size - fcs_pad); // No need to detect link status as // long as frames are received: Reset watchdog. - if (ecdev_get_link(nic->ecdev)) { + if (ecdev_get_link(get_ecdev(nic))) { nic->ec_watchdog_jiffies = jiffies; } } else { @@ -2137,7 +2146,7 @@ process_skb: (*work_done)++; } - if (nic->ecdev) { + if (get_ecdev(nic)) { // make receive frame descriptior usable again memcpy(skb->data, &nic->blank_rfd, sizeof(struct rfd)); rx->dma_addr = dma_map_single(&nic->pdev->dev, skb->data, @@ -2191,7 +2200,7 @@ static void e100_rx_clean(struct nic *nic, unsigned int *work_done, old_before_last_rx = nic->rx_to_use->prev->prev; old_before_last_rfd = (struct rfd *)old_before_last_rx->skb->data; - if (!nic->ecdev) { + if (!get_ecdev(nic)) { /* Alloc new skbs to refill list */ for(rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) { if(unlikely(e100_rx_alloc_skb(nic, rx))) @@ -2288,7 +2297,7 @@ static int e100_rx_alloc_list(struct nic *nic) } } - if (!nic->ecdev) { + if (!get_ecdev(nic)) { /* Set the el-bit on the buffer that is before the last buffer. * This lets us update the next pointer on the last buffer without * worrying about hardware touching it. @@ -2330,7 +2339,7 @@ static irqreturn_t e100_intr(int irq, void *dev_id) if (stat_ack & stat_ack_rnr) nic->ru_running = RU_SUSPENDED; - if (!nic->ecdev && likely(napi_schedule_prep(&nic->napi))) { + if (!get_ecdev(nic) && likely(napi_schedule_prep(&nic->napi))) { e100_disable_irq(nic); __napi_schedule(&nic->napi); } @@ -2418,13 +2427,13 @@ static int e100_up(struct nic *nic) goto err_clean_cbs; e100_set_multicast_list(nic->netdev); e100_start_receiver(nic, NULL); - if (!nic->ecdev) { + if (!get_ecdev(nic)) { mod_timer(&nic->watchdog, jiffies); } if ((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED, nic->netdev->name, nic->netdev))) goto err_no_irq; - if (!nic->ecdev) { + if (!get_ecdev(nic)) { netif_wake_queue(nic->netdev); napi_enable(&nic->napi); /* enable ints _after_ enabling poll, preventing a race between @@ -2434,7 +2443,7 @@ static int e100_up(struct nic *nic) return 0; err_no_irq: - if (!nic->ecdev) + if (!get_ecdev(nic)) del_timer_sync(&nic->watchdog); err_clean_cbs: e100_clean_cbs(nic); @@ -2445,14 +2454,14 @@ err_rx_clean_list: static void e100_down(struct nic *nic) { - if (!nic->ecdev) { + if (!get_ecdev(nic)) { /* wait here for poll to complete */ napi_disable(&nic->napi); netif_stop_queue(nic->netdev); } e100_hw_reset(nic); free_irq(nic->pdev->irq, nic->netdev); - if (!nic->ecdev) { + if (!get_ecdev(nic)) { del_timer_sync(&nic->watchdog); netif_carrier_off(nic->netdev); } @@ -2929,7 +2938,7 @@ static int e100_open(struct net_device *netdev) struct nic *nic = netdev_priv(netdev); int err = 0; - if (!nic->ecdev) + if (!get_ecdev(nic)) netif_carrier_off(netdev); if ((err = e100_up(nic))) netif_err(nic, ifup, nic->netdev, "Cannot open interface, aborting\n"); @@ -3089,9 +3098,10 @@ static int e100_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pci_pme_active(pdev, false); // offer device to EtherCAT master module - nic->ecdev = ecdev_offer(netdev, e100_ec_poll, THIS_MODULE); + nic->ecdev_ = ecdev_offer(netdev, e100_ec_poll, THIS_MODULE); + nic->ecdev_initialized = true; - if (!nic->ecdev) { + if (!get_ecdev(nic)) { strcpy(netdev->name, "eth%d"); if ((err = register_netdev(netdev))) { netif_err(nic, probe, nic->netdev, @@ -3115,10 +3125,10 @@ static int e100_probe(struct pci_dev *pdev, const struct pci_device_id *ent) (unsigned long long)pci_resource_start(pdev, use_io ? 1 : 0), pdev->irq, netdev->dev_addr); - if (nic->ecdev) { - err = ecdev_open(nic->ecdev); + if (get_ecdev(nic)) { + err = ecdev_open(get_ecdev(nic)); if (err) { - ecdev_withdraw(nic->ecdev); + ecdev_withdraw(get_ecdev(nic)); goto err_out_free; } } @@ -3146,9 +3156,9 @@ static void e100_remove(struct pci_dev *pdev) if (netdev) { struct nic *nic = netdev_priv(netdev); - if (nic->ecdev) { - ecdev_close(nic->ecdev); - ecdev_withdraw(nic->ecdev); + if (get_ecdev(nic)) { + ecdev_close(get_ecdev(nic)); + ecdev_withdraw(get_ecdev(nic)); } else { unregister_netdev(netdev); } @@ -3263,7 +3273,7 @@ static pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel struct net_device *netdev = pci_get_drvdata(pdev); struct nic *nic = netdev_priv(netdev); - if (nic->ecdev) + if (get_ecdev(nic)) return -EBUSY; netif_device_detach(netdev); @@ -3290,7 +3300,7 @@ static pci_ers_result_t e100_io_slot_reset(struct pci_dev *pdev) struct net_device *netdev = pci_get_drvdata(pdev); struct nic *nic = netdev_priv(netdev); - if (nic->ecdev) + if (get_ecdev(nic)) return -EBUSY; if (pci_enable_device(pdev)) { @@ -3323,11 +3333,11 @@ static void e100_io_resume(struct pci_dev *pdev) /* ack any pending wake events, disable PME */ pci_enable_wake(pdev, PCI_D0, 0); - if (!nic->ecdev) + if (!get_ecdev(nic)) netif_device_attach(netdev); - if (nic->ecdev || netif_running(netdev)) { + if (get_ecdev(nic) || netif_running(netdev)) { e100_open(netdev); - if (!nic->ecdev) + if (!get_ecdev(nic)) mod_timer(&nic->watchdog, jiffies); } }