[PATCH v4 0/8] staging: qlge: Re-writing the debugging features
This patch set aims to avoid dumping registers, data structures and coredump to dmesg and also to reduce the code size of the qlge driver. As pointed out by Benjamin [1], > At 2000 lines, qlge_dbg.c alone is larger than some entire ethernet > drivers. Most of what it does is dump kernel data structures or pci > memory mapped registers to dmesg. There are better facilities for that. > My thinking is not simply to delete qlge_dbg.c but to replace it, making > sure that most of the same information is still available. For data > structures, crash or drgn can be used; possibly with a script for the > latter which formats the data. For pci registers, they should be > included in the ethtool register dump and a patch added to ethtool to > pretty print them. That's what other drivers like e1000e do. For the > "coredump", devlink health can be used. So the debugging features are re-written following Benjamin's advice, - dump kernel data structures in drgn - use devlink to do coredump which also includes device status and general registers For the usage examples of supported devlink commands, please check the last patch. The tests have been done successfully following Shung-Hsi's steps[2] on a machine from Red Hat, - build the kernel and this driver with KASAN, UBSAN, DEBUG_ATOMIC_SLEEP, PROVE_LOCKING and DEBUG_KMEMLEAK enabled - load and unload the driver - devlink health dump [1] https://lkml.org/lkml/2020/6/30/19 [2] https://lore.kernel.org/netdev/20200816025717.GA28176@f3/T/ v3 -> v4 - remove unnecessary memeset in qlge_init_device [Shung-Hsi Yu] - Call qlge_soft_reset_mpi_risc after getting coredump - only allow force_coredump for NIC function that owns the firmware v2 -> v3 - Fix newly introduced resource leak [Dan Carpenter] - Fix bugs after using struct qlge_adapter as the private data struct of devlink - Add qlge_ prefix for structures not having a prefix and fix a left-over ql_adapter [Benjamin Poirier] v1 -> v2 - Call devlink_free when register_netdev fails [Willem de Bruijn] - "scripts/checkpatch.pl --strict" for changes [Dan Carpente] - Declares variables in "Reverse Christmas Tree" [Dan Carpente] - Use the sizeof() directly [Dan Carpente] - Add SPDX-License-Identifier to qlge_devlink.{c,h} - Rename ql_* to qlge_* [Benjamin Poirier] - Update drivers/staging/qlge/TODO [Benjamin Poirier] - struct qlge_adapter is now used as the private data struct of devlink instead of net_device [Benjamin Poirier] RFC -> v1 - select NET_DEVLINK in Kconfig [Benjamin Poirier] - Don't do a coredump when the interface is down [Shung-Hsi Yu] - Remove stray newlines [Benjamin Poirier] - force_coredump for devlink - Remove mpi_core_to_log which will output the coredump to the kernel ring buffer - Put drgn script under Documentation [Benjamin Poirier] - Rename qlge_health.* to qlge_devlink.* Coiby Xu (8): staging: qlge: use qlge_* prefix to avoid namespace clashes with other qlogic drivers staging: qlge: Initialize devlink health dump framework staging: qlge: re-write qlge_init_device staging: qlge: coredump via devlink health reporter staging: qlge: support force_coredump option for devlink health dump staging: qlge: remove mpi_core_to_log which sends coredump to the kernel ring buffer staging: qlge: clean up debugging code in the QL_ALL_DUMP ifdef land staging: qlge: add documentation for debugging qlge .../networking/device_drivers/index.rst |1 + .../device_drivers/qlogic/index.rst | 18 + .../networking/device_drivers/qlogic/qlge.rst | 118 ++ MAINTAINERS |6 + drivers/staging/qlge/Kconfig |1 + drivers/staging/qlge/Makefile |2 +- drivers/staging/qlge/TODO | 10 - drivers/staging/qlge/qlge.h | 244 +-- drivers/staging/qlge/qlge_dbg.c | 1650 + drivers/staging/qlge/qlge_devlink.c | 164 ++ drivers/staging/qlge/qlge_devlink.h |9 + drivers/staging/qlge/qlge_ethtool.c | 233 ++- drivers/staging/qlge/qlge_main.c | 1376 +++--- drivers/staging/qlge/qlge_mpi.c | 356 ++-- 14 files changed, 1873 insertions(+), 2315 deletions(-) create mode 100644 Documentation/networking/device_drivers/qlogic/index.rst create mode 100644 Documentation/networking/device_drivers/qlogic/qlge.rst create mode 100644 drivers/staging/qlge/qlge_devlink.c create mode 100644 drivers/staging/qlge/qlge_devlink.h -- 2.29.2 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH v4 2/8] staging: qlge: Initialize devlink health dump framework
Initialize devlink health dump framework for the qlge driver so the coredump could be done via devlink. struct qlge_adapter is now used as the private data structure of struct devlink so it could exist independently of struct net_device and devlink reload could be supported in the future. The private data of PCIe driver now points to qlge_adapter. Since devlink_alloc will zero out struct qlge_adapter, memset in qlge_init_device is not necessary. Signed-off-by: Coiby Xu --- drivers/staging/qlge/Kconfig| 1 + drivers/staging/qlge/Makefile | 2 +- drivers/staging/qlge/qlge.h | 13 +++ drivers/staging/qlge/qlge_devlink.c | 31 +++ drivers/staging/qlge/qlge_devlink.h | 9 ++ drivers/staging/qlge/qlge_ethtool.c | 36 drivers/staging/qlge/qlge_main.c| 125 +--- 7 files changed, 151 insertions(+), 66 deletions(-) create mode 100644 drivers/staging/qlge/qlge_devlink.c create mode 100644 drivers/staging/qlge/qlge_devlink.h diff --git a/drivers/staging/qlge/Kconfig b/drivers/staging/qlge/Kconfig index a3cb25a3ab80..6d831ed67965 100644 --- a/drivers/staging/qlge/Kconfig +++ b/drivers/staging/qlge/Kconfig @@ -3,6 +3,7 @@ config QLGE tristate "QLogic QLGE 10Gb Ethernet Driver Support" depends on ETHERNET && PCI + select NET_DEVLINK help This driver supports QLogic ISP8XXX 10Gb Ethernet cards. diff --git a/drivers/staging/qlge/Makefile b/drivers/staging/qlge/Makefile index 1dc2568e820c..07c1898a512e 100644 --- a/drivers/staging/qlge/Makefile +++ b/drivers/staging/qlge/Makefile @@ -5,4 +5,4 @@ obj-$(CONFIG_QLGE) += qlge.o -qlge-objs := qlge_main.o qlge_dbg.o qlge_mpi.o qlge_ethtool.o +qlge-objs := qlge_main.o qlge_dbg.o qlge_mpi.o qlge_ethtool.o qlge_devlink.o diff --git a/drivers/staging/qlge/qlge.h b/drivers/staging/qlge/qlge.h index 1ac85f2f770f..41f69751d34d 100644 --- a/drivers/staging/qlge/qlge.h +++ b/drivers/staging/qlge/qlge.h @@ -2060,6 +2060,18 @@ struct nic_operations { int (*port_initialize)(struct qlge_adapter *qdev); }; +struct qlge_netdev_priv { + struct qlge_adapter *qdev; + struct net_device *ndev; +}; + +static inline +struct qlge_adapter *netdev_to_qdev(struct net_device *ndev) +{ + struct qlge_netdev_priv *ndev_priv = netdev_priv(ndev); + + return ndev_priv->qdev; +} /* * The main Adapter structure definition. * This structure has all fields relevant to the hardware. @@ -2077,6 +2089,7 @@ struct qlge_adapter { struct pci_dev *pdev; struct net_device *ndev;/* Parent NET device */ + struct devlink_health_reporter *reporter; /* Hardware information */ u32 chip_rev_id; u32 fw_rev_id; diff --git a/drivers/staging/qlge/qlge_devlink.c b/drivers/staging/qlge/qlge_devlink.c new file mode 100644 index ..d9c71f45211f --- /dev/null +++ b/drivers/staging/qlge/qlge_devlink.c @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#include "qlge.h" +#include "qlge_devlink.h" + +static int +qlge_reporter_coredump(struct devlink_health_reporter *reporter, + struct devlink_fmsg *fmsg, void *priv_ctx, + struct netlink_ext_ack *extack) +{ + return 0; +} + +static const struct devlink_health_reporter_ops qlge_reporter_ops = { + .name = "dummy", + .dump = qlge_reporter_coredump, +}; + +void qlge_health_create_reporters(struct qlge_adapter *priv) +{ + struct devlink_health_reporter *reporter; + struct devlink *devlink; + + devlink = priv_to_devlink(priv); + priv->reporter = + devlink_health_reporter_create(devlink, &qlge_reporter_ops, + 0, priv); + if (IS_ERR(priv->reporter)) + netdev_warn(priv->ndev, + "Failed to create reporter, err = %ld\n", + PTR_ERR(reporter)); +} diff --git a/drivers/staging/qlge/qlge_devlink.h b/drivers/staging/qlge/qlge_devlink.h new file mode 100644 index ..19078e1ac694 --- /dev/null +++ b/drivers/staging/qlge/qlge_devlink.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#ifndef QLGE_DEVLINK_H +#define QLGE_DEVLINK_H + +#include + +void qlge_health_create_reporters(struct qlge_adapter *priv); + +#endif /* QLGE_DEVLINK_H */ diff --git a/drivers/staging/qlge/qlge_ethtool.c b/drivers/staging/qlge/qlge_ethtool.c index 3e577e1bc27c..24b079523d5c 100644 --- a/drivers/staging/qlge/qlge_ethtool.c +++ b/drivers/staging/qlge/qlge_ethtool.c @@ -366,7 +366,7 @@ static void qlge_get_ethtool_stats(struct net_device *ndev, struct ethtool_stats *stats, u64 *data) { - struct qlge_adapter *qdev = netdev_priv(ndev); + struct qlge_adapter *qdev = netdev_to_qdev(ndev); int index, length; length = QLGE_STATS_LEN; @@ -383,7 +383,7 @@ qlge_get_ethtool_stats(struct net_device *ndev, st
[PATCH v4 3/8] staging: qlge: re-write qlge_init_device
Stop calling ql_release_all in qlge_init_device and free things one step at a time. struct qlge_adapter *qdev is now a private structure of struct devlink and memset is not necessary. Link: https://lore.kernel.org/patchwork/patch/1321092/#1516928 Suggested-by: Dan Carpenter Signed-off-by: Coiby Xu --- drivers/staging/qlge/qlge_main.c | 32 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/drivers/staging/qlge/qlge_main.c b/drivers/staging/qlge/qlge_main.c index bb9fc590d97b..2ec688d3d946 100644 --- a/drivers/staging/qlge/qlge_main.c +++ b/drivers/staging/qlge/qlge_main.c @@ -4394,13 +4394,13 @@ static int qlge_init_device(struct pci_dev *pdev, struct qlge_adapter *qdev, err = pcie_set_readrq(pdev, 4096); if (err) { dev_err(&pdev->dev, "Set readrq failed.\n"); - goto err_out1; + goto err_disable_pci; } err = pci_request_regions(pdev, DRV_NAME); if (err) { dev_err(&pdev->dev, "PCI region request failed.\n"); - return err; + goto err_disable_pci; } pci_set_master(pdev); @@ -4416,7 +4416,7 @@ static int qlge_init_device(struct pci_dev *pdev, struct qlge_adapter *qdev, if (err) { dev_err(&pdev->dev, "No usable DMA configuration.\n"); - goto err_out2; + goto err_release_pci; } /* Set PCIe reset type for EEH to fundamental. */ @@ -4427,7 +4427,7 @@ static int qlge_init_device(struct pci_dev *pdev, struct qlge_adapter *qdev, if (!qdev->reg_base) { dev_err(&pdev->dev, "Register mapping failed.\n"); err = -ENOMEM; - goto err_out2; + goto err_release_pci; } qdev->doorbell_area_size = pci_resource_len(pdev, 3); @@ -4436,14 +4436,14 @@ static int qlge_init_device(struct pci_dev *pdev, struct qlge_adapter *qdev, if (!qdev->doorbell_area) { dev_err(&pdev->dev, "Doorbell register mapping failed.\n"); err = -ENOMEM; - goto err_out2; + goto err_iounmap_base; } err = qlge_get_board_info(qdev); if (err) { dev_err(&pdev->dev, "Register access failed.\n"); err = -EIO; - goto err_out2; + goto err_iounmap_doorbell; } qdev->msg_enable = netif_msg_init(debug, default_msg); spin_lock_init(&qdev->stats_lock); @@ -4453,7 +4453,7 @@ static int qlge_init_device(struct pci_dev *pdev, struct qlge_adapter *qdev, vmalloc(sizeof(struct qlge_mpi_coredump)); if (!qdev->mpi_coredump) { err = -ENOMEM; - goto err_out2; + goto err_iounmap_doorbell; } if (qlge_force_coredump) set_bit(QL_FRC_COREDUMP, &qdev->flags); @@ -4462,7 +4462,7 @@ static int qlge_init_device(struct pci_dev *pdev, struct qlge_adapter *qdev, err = qdev->nic_ops->get_flash(qdev); if (err) { dev_err(&pdev->dev, "Invalid FLASH.\n"); - goto err_out2; + goto err_free_mpi_coredump; } /* Keep local copy of current mac address. */ @@ -4485,7 +4485,7 @@ static int qlge_init_device(struct pci_dev *pdev, struct qlge_adapter *qdev, ndev->name); if (!qdev->workqueue) { err = -ENOMEM; - goto err_out2; + goto err_free_mpi_coredump; } INIT_DELAYED_WORK(&qdev->asic_reset_work, qlge_asic_reset_work); @@ -4503,10 +4503,18 @@ static int qlge_init_device(struct pci_dev *pdev, struct qlge_adapter *qdev, DRV_NAME, DRV_VERSION); } return 0; -err_out2: - qlge_release_all(pdev); -err_out1: + +err_free_mpi_coredump: + vfree(qdev->mpi_coredump); +err_iounmap_doorbell: + iounmap(qdev->doorbell_area); +err_iounmap_base: + iounmap(qdev->reg_base); +err_release_pci: + pci_release_regions(pdev); +err_disable_pci: pci_disable_device(pdev); + return err; } -- 2.29.2 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH v4 4/8] staging: qlge: coredump via devlink health reporter
$ devlink health dump show DEVICE reporter coredump -p -j { "Core Registers": { "segment": 1, "values": [ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ] }, "Test Logic Regs": { "segment": 2, "values": [ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ] }, "RMII Registers": { "segment": 3, "values": [ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ] }, ... "Sem Registers": { "segment": 50, "values": [ 0,0,0,0 ] } } Signed-off-by: Coiby Xu --- drivers/staging/qlge/qlge_devlink.c | 132 ++-- 1 file changed, 126 insertions(+), 6 deletions(-) diff --git a/drivers/staging/qlge/qlge_devlink.c b/drivers/staging/qlge/qlge_devlink.c index d9c71f45211f..bf7d75ed5eae 100644 --- a/drivers/staging/qlge/qlge_devlink.c +++ b/drivers/staging/qlge/qlge_devlink.c @@ -2,16 +2,136 @@ #include "qlge.h" #include "qlge_devlink.h" -static int -qlge_reporter_coredump(struct devlink_health_reporter *reporter, - struct devlink_fmsg *fmsg, void *priv_ctx, - struct netlink_ext_ack *extack) +static int qlge_fill_seg_(struct devlink_fmsg *fmsg, + struct mpi_coredump_segment_header *seg_header, + u32 *reg_data) { - return 0; + int regs_num = (seg_header->seg_size + - sizeof(struct mpi_coredump_segment_header)) / sizeof(u32); + int err; + int i; + + err = devlink_fmsg_pair_nest_start(fmsg, seg_header->description); + if (err) + return err; + err = devlink_fmsg_obj_nest_start(fmsg); + if (err) + return err; + err = devlink_fmsg_u32_pair_put(fmsg, "segment", seg_header->seg_num); + if (err) + return err; + err = devlink_fmsg_arr_pair_nest_start(fmsg, "values"); + if (err) + return err; + for (i = 0; i < regs_num; i++) { + err = devlink_fmsg_u32_put(fmsg, *reg_data); + if (err) + return err; + reg_data++; + } + err = devlink_fmsg_obj_nest_end(fmsg); + if (err) + return err; + err = devlink_fmsg_arr_pair_nest_end(fmsg); + if (err) + return err; + err = devlink_fmsg_pair_nest_end(fmsg); + return err; +} + +#define FILL_SEG(seg_hdr, seg_regs)\ + do {\ + err = qlge_fill_seg_(fmsg, &dump->seg_hdr, dump->seg_regs); \ + if (err) { \ + kvfree(dump); \ + return err; \ + } \ + } while (0) + +static int qlge_reporter_coredump(struct devlink_health_reporter *reporter, + struct devlink_fmsg *fmsg, void *priv_ctx, + struct netlink_ext_ack *extack) +{ + int err = 0; + + struct qlge_adapter *qdev = devlink_health_reporter_priv(reporter); + struct qlge_mpi_coredump *dump; + + if (!netif_running(qdev->ndev)) + return 0; + + dump = kvmalloc(sizeof(*dump), GFP_KERNEL); + if (!dump) + return -ENOMEM; + + err = qlge_core_dump(qdev, dump); + if (err) { + kvfree(dump); + return err; + } + + qlge_soft_reset_mpi_risc(qdev); + + FILL_SEG(core_regs_seg_hdr, mpi_core_regs); + FILL_SEG(test_logic_regs_seg_hdr, test_logic_regs); + FILL_SEG(rmii_regs_seg_hdr, rmii_regs); + FILL_SEG(fcmac1_regs_seg_hdr, fcmac1_regs); + FILL_SEG(fcmac2_regs_seg_hdr, fcmac2_regs); + FILL_SEG(fc1_mbx_regs_seg_hdr, fc1_mbx_regs); + FILL_SEG(ide_regs_seg_hdr, ide_regs); + FILL_SEG(nic1_mbx_regs_seg_hdr, nic1_mbx_regs); + FILL_SEG(smbus_regs_seg_hdr, smbus_regs); + FILL_SEG(fc2_mbx_regs_seg_hdr, fc2_mbx_regs); + FILL_SEG(nic2_mbx_regs_seg_hdr, nic2_mbx_regs); + FILL_SEG(i2c_regs_seg_hdr, i2c_regs); + FILL_SEG(memc_regs_seg_hdr, memc_regs); + FILL_SEG(pbus_regs_seg_hdr, pbus_regs); + FILL_SEG(mde_regs_seg_hdr, mde_regs); + FILL_SEG(nic_regs_seg_hdr, nic_regs); + FILL_SEG(nic2_regs_seg_hdr, nic2_regs); + FILL_SEG(xgmac1_seg_hdr, xgmac1); +
[PATCH v4 7/8] staging: qlge: clean up debugging code in the QL_ALL_DUMP ifdef land
The debugging code in the following ifdef land - QL_ALL_DUMP - QL_REG_DUMP - QL_DEV_DUMP - QL_CB_DUMP - QL_IB_DUMP - QL_OB_DUMP becomes unnecessary because, - Device status and general registers can be obtained by ethtool. - Coredump can be done via devlink health reporter. - Structure related to the hardware (struct ql_adapter) can be obtained by crash or drgn. Link: https://lkml.org/lkml/2020/6/30/19 Suggested-by: Benjamin Poirier Signed-off-by: Coiby Xu --- drivers/staging/qlge/TODO | 4 - drivers/staging/qlge/qlge.h | 82 drivers/staging/qlge/qlge_dbg.c | 688 drivers/staging/qlge/qlge_ethtool.c | 2 - drivers/staging/qlge/qlge_main.c| 7 +- 5 files changed, 1 insertion(+), 782 deletions(-) diff --git a/drivers/staging/qlge/TODO b/drivers/staging/qlge/TODO index e68c95f47754..c76394b9451b 100644 --- a/drivers/staging/qlge/TODO +++ b/drivers/staging/qlge/TODO @@ -14,10 +14,6 @@ queues" is confusing. * struct rx_ring is used for rx and tx completions, with some members relevant to one case only -* there is an inordinate amount of disparate debugging code, most of which is - of questionable value. In particular, qlge_dbg.c has hundreds of lines of - code bitrotting away in ifdef land (doesn't compile since commit - 18c49b91777c ("qlge: do vlan cleanup", v3.1-rc1), 8 years ago). * the flow control implementation in firmware is buggy (sends a flood of pause frames, resets the link, device and driver buffer queues become desynchronized), disable it by default diff --git a/drivers/staging/qlge/qlge.h b/drivers/staging/qlge/qlge.h index aa5721862140..55e0ad759250 100644 --- a/drivers/staging/qlge/qlge.h +++ b/drivers/staging/qlge/qlge.h @@ -2289,86 +2289,4 @@ void qlge_check_lb_frame(struct qlge_adapter *qdev, struct sk_buff *skb); int qlge_own_firmware(struct qlge_adapter *qdev); int qlge_clean_lb_rx_ring(struct rx_ring *rx_ring, int budget); -/* #define QL_ALL_DUMP */ -/* #define QL_REG_DUMP */ -/* #define QL_DEV_DUMP */ -/* #define QL_CB_DUMP */ -/* #define QL_IB_DUMP */ -/* #define QL_OB_DUMP */ - -#ifdef QL_REG_DUMP -void qlge_dump_xgmac_control_regs(struct qlge_adapter *qdev); -void qlge_dump_routing_entries(struct qlge_adapter *qdev); -void qlge_dump_regs(struct qlge_adapter *qdev); -#define QL_DUMP_REGS(qdev) qlge_dump_regs(qdev) -#define QL_DUMP_ROUTE(qdev) qlge_dump_routing_entries(qdev) -#define QL_DUMP_XGMAC_CONTROL_REGS(qdev) qlge_dump_xgmac_control_regs(qdev) -#else -#define QL_DUMP_REGS(qdev) -#define QL_DUMP_ROUTE(qdev) -#define QL_DUMP_XGMAC_CONTROL_REGS(qdev) -#endif - -#ifdef QL_STAT_DUMP -void qlge_dump_stat(struct qlge_adapter *qdev); -#define QL_DUMP_STAT(qdev) qlge_dump_stat(qdev) -#else -#define QL_DUMP_STAT(qdev) -#endif - -#ifdef QL_DEV_DUMP -void qlge_dump_qdev(struct qlge_adapter *qdev); -#define QL_DUMP_QDEV(qdev) qlge_dump_qdev(qdev) -#else -#define QL_DUMP_QDEV(qdev) -#endif - -#ifdef QL_CB_DUMP -void qlge_dump_wqicb(struct wqicb *wqicb); -void qlge_dump_tx_ring(struct tx_ring *tx_ring); -void qlge_dump_ricb(struct ricb *ricb); -void qlge_dump_cqicb(struct cqicb *cqicb); -void qlge_dump_rx_ring(struct rx_ring *rx_ring); -void qlge_dump_hw_cb(struct qlge_adapter *qdev, int size, u32 bit, u16 q_id); -#define QL_DUMP_RICB(ricb) qlge_dump_ricb(ricb) -#define QL_DUMP_WQICB(wqicb) qlge_dump_wqicb(wqicb) -#define QL_DUMP_TX_RING(tx_ring) qlge_dump_tx_ring(tx_ring) -#define QL_DUMP_CQICB(cqicb) qlge_dump_cqicb(cqicb) -#define QL_DUMP_RX_RING(rx_ring) qlge_dump_rx_ring(rx_ring) -#define QL_DUMP_HW_CB(qdev, size, bit, q_id) \ - qlge_dump_hw_cb(qdev, size, bit, q_id) -#else -#define QL_DUMP_RICB(ricb) -#define QL_DUMP_WQICB(wqicb) -#define QL_DUMP_TX_RING(tx_ring) -#define QL_DUMP_CQICB(cqicb) -#define QL_DUMP_RX_RING(rx_ring) -#define QL_DUMP_HW_CB(qdev, size, bit, q_id) -#endif - -#ifdef QL_OB_DUMP -void qlge_dump_tx_desc(struct qlge_adapter *qdev, struct tx_buf_desc *tbd); -void qlge_dump_ob_mac_iocb(struct qlge_adapter *qdev, struct qlge_ob_mac_iocb_req *ob_mac_iocb); -void qlge_dump_ob_mac_rsp(struct qlge_adapter *qdev, struct qlge_ob_mac_iocb_rsp *ob_mac_rsp); -#define QL_DUMP_OB_MAC_IOCB(qdev, ob_mac_iocb) qlge_dump_ob_mac_iocb(qdev, ob_mac_iocb) -#define QL_DUMP_OB_MAC_RSP(qdev, ob_mac_rsp) qlge_dump_ob_mac_rsp(qdev, ob_mac_rsp) -#else -#define QL_DUMP_OB_MAC_IOCB(qdev, ob_mac_iocb) -#define QL_DUMP_OB_MAC_RSP(qdev, ob_mac_rsp) -#endif - -#ifdef QL_IB_DUMP -void qlge_dump_ib_mac_rsp(struct qlge_adapter *qdev, struct qlge_ib_mac_iocb_rsp *ib_mac_rsp); -#define QL_DUMP_IB_MAC_RSP(qdev, ib_mac_rsp) qlge_dump_ib_mac_rsp(qdev, ib_mac_rsp) -#else -#define QL_DUMP_IB_MAC_RSP(qdev, ib_mac_rsp) -#endif - -#ifdef QL_ALL_DUMP -void qlge_dump_all(struct qlge_adapter *qdev); -#define QL_DUMP_ALL(qdev) qlge_dump_all(qdev) -#else -#define QL_DUMP_ALL(qdev) -#endif - #endif /* _QLGE_H_ */ diff --git a/drivers/staging/qlge/qlge_dbg.c b/drivers/staging/qlge/qlge_dbg.c index
[PATCH v4 8/8] staging: qlge: add documentation for debugging qlge
Instructions and examples on kernel data structures dumping and coredump. Signed-off-by: Coiby Xu --- .../networking/device_drivers/index.rst | 1 + .../device_drivers/qlogic/index.rst | 18 +++ .../networking/device_drivers/qlogic/qlge.rst | 118 ++ MAINTAINERS | 6 + 4 files changed, 143 insertions(+) create mode 100644 Documentation/networking/device_drivers/qlogic/index.rst create mode 100644 Documentation/networking/device_drivers/qlogic/qlge.rst diff --git a/Documentation/networking/device_drivers/index.rst b/Documentation/networking/device_drivers/index.rst index a3113ffd7a16..d8279de7bf25 100644 --- a/Documentation/networking/device_drivers/index.rst +++ b/Documentation/networking/device_drivers/index.rst @@ -15,6 +15,7 @@ Contents: ethernet/index fddi/index hamradio/index + qlogic/index wan/index wifi/index diff --git a/Documentation/networking/device_drivers/qlogic/index.rst b/Documentation/networking/device_drivers/qlogic/index.rst new file mode 100644 index ..ad05b04286e4 --- /dev/null +++ b/Documentation/networking/device_drivers/qlogic/index.rst @@ -0,0 +1,18 @@ +.. SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) + +QLogic QLGE Device Drivers +=== + +Contents: + +.. toctree:: + :maxdepth: 2 + + qlge + +.. only:: subproject and html + + Indices + === + + * :ref:`genindex` diff --git a/Documentation/networking/device_drivers/qlogic/qlge.rst b/Documentation/networking/device_drivers/qlogic/qlge.rst new file mode 100644 index ..0b888253d152 --- /dev/null +++ b/Documentation/networking/device_drivers/qlogic/qlge.rst @@ -0,0 +1,118 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=== +QLogic QLGE 10Gb Ethernet device driver +=== + +This driver use drgn and devlink for debugging. + +Dump kernel data structures in drgn +--- + +To dump kernel data structures, the following Python script can be used +in drgn: + +.. code-block:: python + + def align(x, a): + """the alignment a should be a power of 2 + """ + mask = a - 1 + return (x+ mask) & ~mask + + def struct_size(struct_type): + struct_str = "struct {}".format(struct_type) + return sizeof(Object(prog, struct_str, address=0x0)) + + def netdev_priv(netdevice): + NETDEV_ALIGN = 32 + return netdevice.value_() + align(struct_size("net_device"), NETDEV_ALIGN) + + name = 'xxx' + qlge_device = None + netdevices = prog['init_net'].dev_base_head.address_of_() + for netdevice in list_for_each_entry("struct net_device", netdevices, "dev_list"): + if netdevice.name.string_().decode('ascii') == name: + print(netdevice.name) + + ql_adapter = Object(prog, "struct ql_adapter", address=netdev_priv(qlge_device)) + +The struct ql_adapter will be printed in drgn as follows, + +>>> ql_adapter +(struct ql_adapter){ +.ricb = (struct ricb){ +.base_cq = (u8)0, +.flags = (u8)120, +.mask = (__le16)26637, +.hash_cq_id = (u8 [1024]){ 172, 142, 255, 255 }, +.ipv6_hash_key = (__le32 [10]){}, +.ipv4_hash_key = (__le32 [4]){}, +}, +.flags = (unsigned long)0, +.wol = (u32)0, +.nic_stats = (struct nic_stats){ +.tx_pkts = (u64)0, +.tx_bytes = (u64)0, +.tx_mcast_pkts = (u64)0, +.tx_bcast_pkts = (u64)0, +.tx_ucast_pkts = (u64)0, +.tx_ctl_pkts = (u64)0, +.tx_pause_pkts = (u64)0, +... +}, +.active_vlans = (unsigned long [64]){ +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52780853100545, 18446744073709551615, +18446619461681283072, 0, 42949673024, 2147483647, +}, +.rx_ring = (struct rx_ring [17]){ +{ +.cqicb = (struct cqicb){ +.msix_vect = (u8)0, +.reserved1 = (u8)0, +.reserved2 = (u8)0, +.flags = (u8)0, +.len = (__le16)0, +.rid = (__le16)0, +... +}, +.cq_base = (void *)0x0, +.cq_base_dma = (dma_addr_t)0, +} +
[PATCH v4 5/8] staging: qlge: support force_coredump option for devlink health dump
With force_coredump module parameter set, devlink health dump will reset the MPI RISC first which takes 5 secs to be finished. Note that only NIC function that owns the firmware can do the force_dumping. Otherwise devlink will receive an EPERM error. Signed-off-by: Coiby Xu --- drivers/staging/qlge/qlge_devlink.c | 13 + 1 file changed, 13 insertions(+) diff --git a/drivers/staging/qlge/qlge_devlink.c b/drivers/staging/qlge/qlge_devlink.c index bf7d75ed5eae..c6ef5163e241 100644 --- a/drivers/staging/qlge/qlge_devlink.c +++ b/drivers/staging/qlge/qlge_devlink.c @@ -56,10 +56,23 @@ static int qlge_reporter_coredump(struct devlink_health_reporter *reporter, struct qlge_adapter *qdev = devlink_health_reporter_priv(reporter); struct qlge_mpi_coredump *dump; + wait_queue_head_t wait; if (!netif_running(qdev->ndev)) return 0; + if (test_bit(QL_FRC_COREDUMP, &qdev->flags)) { + if (qlge_own_firmware(qdev)) { + qlge_queue_fw_error(qdev); + init_waitqueue_head(&wait); + wait_event_timeout(wait, 0, 5 * HZ); + } else { + netif_err(qdev, ifup, qdev->ndev, + "Force Coredump failed because this NIC function doesn't own the firmware\n"); + return -EPERM; + } + } + dump = kvmalloc(sizeof(*dump), GFP_KERNEL); if (!dump) return -ENOMEM; -- 2.29.2 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH v4 6/8] staging: qlge: remove mpi_core_to_log which sends coredump to the kernel ring buffer
devlink health could be used to get coredump. No need to send so much data to the kernel ring buffer. Signed-off-by: Coiby Xu --- drivers/staging/qlge/TODO | 2 -- drivers/staging/qlge/qlge.h | 3 --- drivers/staging/qlge/qlge_dbg.c | 11 --- drivers/staging/qlge/qlge_ethtool.c | 1 - drivers/staging/qlge/qlge_main.c| 2 -- drivers/staging/qlge/qlge_mpi.c | 6 -- 6 files changed, 25 deletions(-) diff --git a/drivers/staging/qlge/TODO b/drivers/staging/qlge/TODO index 5ac55664c3e2..e68c95f47754 100644 --- a/drivers/staging/qlge/TODO +++ b/drivers/staging/qlge/TODO @@ -18,8 +18,6 @@ of questionable value. In particular, qlge_dbg.c has hundreds of lines of code bitrotting away in ifdef land (doesn't compile since commit 18c49b91777c ("qlge: do vlan cleanup", v3.1-rc1), 8 years ago). -* triggering an ethtool regdump will hexdump a 176k struct to dmesg depending - on some module parameters. * the flow control implementation in firmware is buggy (sends a flood of pause frames, resets the link, device and driver buffer queues become desynchronized), disable it by default diff --git a/drivers/staging/qlge/qlge.h b/drivers/staging/qlge/qlge.h index 41f69751d34d..aa5721862140 100644 --- a/drivers/staging/qlge/qlge.h +++ b/drivers/staging/qlge/qlge.h @@ -2153,7 +2153,6 @@ struct qlge_adapter { u32 port_init; u32 link_status; struct qlge_mpi_coredump *mpi_coredump; - u32 core_is_dumped; u32 link_config; u32 led_config; u32 max_frame_size; @@ -2166,7 +2165,6 @@ struct qlge_adapter { struct delayed_work mpi_work; struct delayed_work mpi_port_cfg_work; struct delayed_work mpi_idc_work; - struct delayed_work mpi_core_to_log; struct completion ide_completion; const struct nic_operations *nic_ops; u16 device_id; @@ -2257,7 +2255,6 @@ int qlge_write_cfg(struct qlge_adapter *qdev, void *ptr, int size, u32 bit, void qlge_queue_fw_error(struct qlge_adapter *qdev); void qlge_mpi_work(struct work_struct *work); void qlge_mpi_reset_work(struct work_struct *work); -void qlge_mpi_core_to_log(struct work_struct *work); int qlge_wait_reg_rdy(struct qlge_adapter *qdev, u32 reg, u32 bit, u32 ebit); void qlge_queue_asic_error(struct qlge_adapter *qdev); void qlge_set_ethtool_ops(struct net_device *ndev); diff --git a/drivers/staging/qlge/qlge_dbg.c b/drivers/staging/qlge/qlge_dbg.c index b0d4ea071f32..5c64d6de3b30 100644 --- a/drivers/staging/qlge/qlge_dbg.c +++ b/drivers/staging/qlge/qlge_dbg.c @@ -1313,17 +1313,6 @@ void qlge_get_dump(struct qlge_adapter *qdev, void *buff) } } -/* Coredump to messages log file using separate worker thread */ -void qlge_mpi_core_to_log(struct work_struct *work) -{ - struct qlge_adapter *qdev = - container_of(work, struct qlge_adapter, mpi_core_to_log.work); - - print_hex_dump(KERN_DEBUG, "Core is dumping to log file!\n", - DUMP_PREFIX_OFFSET, 32, 4, qdev->mpi_coredump, - sizeof(*qdev->mpi_coredump), false); -} - #ifdef QL_REG_DUMP static void qlge_dump_intr_states(struct qlge_adapter *qdev) { diff --git a/drivers/staging/qlge/qlge_ethtool.c b/drivers/staging/qlge/qlge_ethtool.c index 24b079523d5c..3e911f147dfc 100644 --- a/drivers/staging/qlge/qlge_ethtool.c +++ b/drivers/staging/qlge/qlge_ethtool.c @@ -617,7 +617,6 @@ static void qlge_get_regs(struct net_device *ndev, struct qlge_adapter *qdev = netdev_to_qdev(ndev); qlge_get_dump(qdev, p); - qdev->core_is_dumped = 0; if (!test_bit(QL_FRC_COREDUMP, &qdev->flags)) regs->len = sizeof(struct qlge_mpi_coredump); else diff --git a/drivers/staging/qlge/qlge_main.c b/drivers/staging/qlge/qlge_main.c index 2ec688d3d946..747dbb54dde4 100644 --- a/drivers/staging/qlge/qlge_main.c +++ b/drivers/staging/qlge/qlge_main.c @@ -3800,7 +3800,6 @@ static void qlge_cancel_all_work_sync(struct qlge_adapter *qdev) cancel_delayed_work_sync(&qdev->mpi_reset_work); cancel_delayed_work_sync(&qdev->mpi_work); cancel_delayed_work_sync(&qdev->mpi_idc_work); - cancel_delayed_work_sync(&qdev->mpi_core_to_log); cancel_delayed_work_sync(&qdev->mpi_port_cfg_work); } @@ -4493,7 +4492,6 @@ static int qlge_init_device(struct pci_dev *pdev, struct qlge_adapter *qdev, INIT_DELAYED_WORK(&qdev->mpi_work, qlge_mpi_work); INIT_DELAYED_WORK(&qdev->mpi_port_cfg_work, qlge_mpi_port_cfg_work); INIT_DELAYED_WORK(&qdev->mpi_idc_work, qlge_mpi_idc_work); - INIT_DELAYED_WORK(&qdev->mpi_core_to_log, qlge_mpi_core_to_log); init_completion(&qdev->ide_completion); mutex_init(&qdev->mpi_mutex); diff --git a/drivers/staging/qlge/qlge_mpi.c b/drivers/staging/qlge/qlge_mpi.c index 2b77995ec76c..2630ebf50341 100644 --- a/drivers/staging/qlge/qlge_mpi.c +++ b/drivers/staging/qlge/qlge_mpi.c @@ -1269,11 +12
[driver-core:driver-core-linus] BUILD SUCCESS e020ff611ba9be54e959e6b548038f8a020da1c9
tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git driver-core-linus branch HEAD: e020ff611ba9be54e959e6b548038f8a020da1c9 driver core: Fix device link device name collision elapsed time: 3298m configs tested: 100 configs skipped: 2 The following configs have been built successfully. More configs may be tested in the coming days. gcc tested configs: arm defconfig arm64allyesconfig arm64 defconfig arm allyesconfig arm allmodconfig powerpcamigaone_defconfig mipsmalta_qemu_32r6_defconfig mipsmaltaup_defconfig powerpc tqm8560_defconfig powerpc mpc8315_rdb_defconfig arm efm32_defconfig armshmobile_defconfig arm s3c6400_defconfig mips mtx1_defconfig powerpc tqm8555_defconfig powerpc mpc885_ads_defconfig powerpc holly_defconfig powerpc storcenter_defconfig powerpc taishan_defconfig powerpc tqm8541_defconfig powerpc mgcoge_defconfig powerpc rainier_defconfig arm exynos_defconfig shshmin_defconfig arm cm_x300_defconfig mips ip27_defconfig m68k amcore_defconfig powerpc sequoia_defconfig mips ath25_defconfig arm orion5x_defconfig sh se7712_defconfig mipsbcm47xx_defconfig armspear3xx_defconfig sh ap325rxa_defconfig archsdk_defconfig ia64 allmodconfig ia64defconfig ia64 allyesconfig m68k allmodconfig m68kdefconfig m68k allyesconfig nios2 defconfig arc allyesconfig nds32 allnoconfig c6x allyesconfig nds32 defconfig nios2allyesconfig cskydefconfig alpha defconfig alphaallyesconfig xtensa allyesconfig h8300allyesconfig arc defconfig sh allmodconfig parisc defconfig s390 allyesconfig parisc allyesconfig s390defconfig i386 allyesconfig sparcallyesconfig sparc defconfig i386 tinyconfig i386defconfig mips allyesconfig mips allmodconfig powerpc allyesconfig powerpc allmodconfig powerpc allnoconfig x86_64 randconfig-a002-20210121 x86_64 randconfig-a003-20210121 x86_64 randconfig-a001-20210121 x86_64 randconfig-a005-20210121 x86_64 randconfig-a006-20210121 x86_64 randconfig-a004-20210121 i386 randconfig-a001-20210121 i386 randconfig-a002-20210121 i386 randconfig-a004-20210121 i386 randconfig-a006-20210121 i386 randconfig-a005-20210121 i386 randconfig-a003-20210121 i386 randconfig-a013-20210121 i386 randconfig-a011-20210121 i386 randconfig-a012-20210121 i386 randconfig-a014-20210121 i386 randconfig-a015-20210121 i386 randconfig-a016-20210121 riscvnommu_k210_defconfig riscvallyesconfig riscvnommu_virt_defconfig riscv allnoconfig riscv defconfig riscv rv32_defconfig riscvallmodconfig x86_64 allyesconfig x86_64 defconfig x86_64 rhel x86_64rhel-7.6-kselftests x86_64 rhel-8.3 x86_64 rhel-8.3-kbuiltin x86_64 kexec --- 0