From 0290bd291cc0e0488e35e66bf39efcd7d9d9122b Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 10 Dec 2019 09:23:51 -0500 Subject: netdev: pass the stuck queue to the timeout handler This allows incrementing the correct timeout statistic without any mess. Down the road, devices can learn to reset just the specific queue. The patch was generated with the following script: use strict; use warnings; our $^I = '.bak'; my @work = ( ["arch/m68k/emu/nfeth.c", "nfeth_tx_timeout"], ["arch/um/drivers/net_kern.c", "uml_net_tx_timeout"], ["arch/um/drivers/vector_kern.c", "vector_net_tx_timeout"], ["arch/xtensa/platforms/iss/network.c", "iss_net_tx_timeout"], ["drivers/char/pcmcia/synclink_cs.c", "hdlcdev_tx_timeout"], ["drivers/infiniband/ulp/ipoib/ipoib_main.c", "ipoib_timeout"], ["drivers/infiniband/ulp/ipoib/ipoib_main.c", "ipoib_timeout"], ["drivers/message/fusion/mptlan.c", "mpt_lan_tx_timeout"], ["drivers/misc/sgi-xp/xpnet.c", "xpnet_dev_tx_timeout"], ["drivers/net/appletalk/cops.c", "cops_timeout"], ["drivers/net/arcnet/arcdevice.h", "arcnet_timeout"], ["drivers/net/arcnet/arcnet.c", "arcnet_timeout"], ["drivers/net/arcnet/com20020.c", "arcnet_timeout"], ["drivers/net/ethernet/3com/3c509.c", "el3_tx_timeout"], ["drivers/net/ethernet/3com/3c515.c", "corkscrew_timeout"], ["drivers/net/ethernet/3com/3c574_cs.c", "el3_tx_timeout"], ["drivers/net/ethernet/3com/3c589_cs.c", "el3_tx_timeout"], ["drivers/net/ethernet/3com/3c59x.c", "vortex_tx_timeout"], ["drivers/net/ethernet/3com/3c59x.c", "vortex_tx_timeout"], ["drivers/net/ethernet/3com/typhoon.c", "typhoon_tx_timeout"], ["drivers/net/ethernet/8390/8390.h", "ei_tx_timeout"], ["drivers/net/ethernet/8390/8390.h", "eip_tx_timeout"], ["drivers/net/ethernet/8390/8390.c", "ei_tx_timeout"], ["drivers/net/ethernet/8390/8390p.c", "eip_tx_timeout"], ["drivers/net/ethernet/8390/ax88796.c", "ax_ei_tx_timeout"], ["drivers/net/ethernet/8390/axnet_cs.c", "axnet_tx_timeout"], ["drivers/net/ethernet/8390/etherh.c", "__ei_tx_timeout"], ["drivers/net/ethernet/8390/hydra.c", "__ei_tx_timeout"], ["drivers/net/ethernet/8390/mac8390.c", "__ei_tx_timeout"], ["drivers/net/ethernet/8390/mcf8390.c", "__ei_tx_timeout"], ["drivers/net/ethernet/8390/lib8390.c", "__ei_tx_timeout"], ["drivers/net/ethernet/8390/ne2k-pci.c", "ei_tx_timeout"], ["drivers/net/ethernet/8390/pcnet_cs.c", "ei_tx_timeout"], ["drivers/net/ethernet/8390/smc-ultra.c", "ei_tx_timeout"], ["drivers/net/ethernet/8390/wd.c", "ei_tx_timeout"], ["drivers/net/ethernet/8390/zorro8390.c", "__ei_tx_timeout"], ["drivers/net/ethernet/adaptec/starfire.c", "tx_timeout"], ["drivers/net/ethernet/agere/et131x.c", "et131x_tx_timeout"], ["drivers/net/ethernet/allwinner/sun4i-emac.c", "emac_timeout"], ["drivers/net/ethernet/alteon/acenic.c", "ace_watchdog"], ["drivers/net/ethernet/amazon/ena/ena_netdev.c", "ena_tx_timeout"], ["drivers/net/ethernet/amd/7990.h", "lance_tx_timeout"], ["drivers/net/ethernet/amd/7990.c", "lance_tx_timeout"], ["drivers/net/ethernet/amd/a2065.c", "lance_tx_timeout"], ["drivers/net/ethernet/amd/am79c961a.c", "am79c961_timeout"], ["drivers/net/ethernet/amd/amd8111e.c", "amd8111e_tx_timeout"], ["drivers/net/ethernet/amd/ariadne.c", "ariadne_tx_timeout"], ["drivers/net/ethernet/amd/atarilance.c", "lance_tx_timeout"], ["drivers/net/ethernet/amd/au1000_eth.c", "au1000_tx_timeout"], ["drivers/net/ethernet/amd/declance.c", "lance_tx_timeout"], ["drivers/net/ethernet/amd/lance.c", "lance_tx_timeout"], ["drivers/net/ethernet/amd/mvme147.c", "lance_tx_timeout"], ["drivers/net/ethernet/amd/ni65.c", "ni65_timeout"], ["drivers/net/ethernet/amd/nmclan_cs.c", "mace_tx_timeout"], ["drivers/net/ethernet/amd/pcnet32.c", "pcnet32_tx_timeout"], ["drivers/net/ethernet/amd/sunlance.c", "lance_tx_timeout"], ["drivers/net/ethernet/amd/xgbe/xgbe-drv.c", "xgbe_tx_timeout"], ["drivers/net/ethernet/apm/xgene-v2/main.c", "xge_timeout"], ["drivers/net/ethernet/apm/xgene/xgene_enet_main.c", "xgene_enet_timeout"], ["drivers/net/ethernet/apple/macmace.c", "mace_tx_timeout"], ["drivers/net/ethernet/atheros/ag71xx.c", "ag71xx_tx_timeout"], ["drivers/net/ethernet/atheros/alx/main.c", "alx_tx_timeout"], ["drivers/net/ethernet/atheros/atl1c/atl1c_main.c", "atl1c_tx_timeout"], ["drivers/net/ethernet/atheros/atl1e/atl1e_main.c", "atl1e_tx_timeout"], ["drivers/net/ethernet/atheros/atlx/atl.c", "atlx_tx_timeout"], ["drivers/net/ethernet/atheros/atlx/atl1.c", "atlx_tx_timeout"], ["drivers/net/ethernet/atheros/atlx/atl2.c", "atl2_tx_timeout"], ["drivers/net/ethernet/broadcom/b44.c", "b44_tx_timeout"], ["drivers/net/ethernet/broadcom/bcmsysport.c", "bcm_sysport_tx_timeout"], ["drivers/net/ethernet/broadcom/bnx2.c", "bnx2_tx_timeout"], ["drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h", "bnx2x_tx_timeout"], ["drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c", "bnx2x_tx_timeout"], ["drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c", "bnx2x_tx_timeout"], ["drivers/net/ethernet/broadcom/bnxt/bnxt.c", "bnxt_tx_timeout"], ["drivers/net/ethernet/broadcom/genet/bcmgenet.c", "bcmgenet_timeout"], ["drivers/net/ethernet/broadcom/sb1250-mac.c", "sbmac_tx_timeout"], ["drivers/net/ethernet/broadcom/tg3.c", "tg3_tx_timeout"], ["drivers/net/ethernet/calxeda/xgmac.c", "xgmac_tx_timeout"], ["drivers/net/ethernet/cavium/liquidio/lio_main.c", "liquidio_tx_timeout"], ["drivers/net/ethernet/cavium/liquidio/lio_vf_main.c", "liquidio_tx_timeout"], ["drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c", "lio_vf_rep_tx_timeout"], ["drivers/net/ethernet/cavium/thunder/nicvf_main.c", "nicvf_tx_timeout"], ["drivers/net/ethernet/cirrus/cs89x0.c", "net_timeout"], ["drivers/net/ethernet/cisco/enic/enic_main.c", "enic_tx_timeout"], ["drivers/net/ethernet/cisco/enic/enic_main.c", "enic_tx_timeout"], ["drivers/net/ethernet/cortina/gemini.c", "gmac_tx_timeout"], ["drivers/net/ethernet/davicom/dm9000.c", "dm9000_timeout"], ["drivers/net/ethernet/dec/tulip/de2104x.c", "de_tx_timeout"], ["drivers/net/ethernet/dec/tulip/tulip_core.c", "tulip_tx_timeout"], ["drivers/net/ethernet/dec/tulip/winbond-840.c", "tx_timeout"], ["drivers/net/ethernet/dlink/dl2k.c", "rio_tx_timeout"], ["drivers/net/ethernet/dlink/sundance.c", "tx_timeout"], ["drivers/net/ethernet/emulex/benet/be_main.c", "be_tx_timeout"], ["drivers/net/ethernet/ethoc.c", "ethoc_tx_timeout"], ["drivers/net/ethernet/faraday/ftgmac100.c", "ftgmac100_tx_timeout"], ["drivers/net/ethernet/fealnx.c", "fealnx_tx_timeout"], ["drivers/net/ethernet/freescale/dpaa/dpaa_eth.c", "dpaa_tx_timeout"], ["drivers/net/ethernet/freescale/fec_main.c", "fec_timeout"], ["drivers/net/ethernet/freescale/fec_mpc52xx.c", "mpc52xx_fec_tx_timeout"], ["drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c", "fs_timeout"], ["drivers/net/ethernet/freescale/gianfar.c", "gfar_timeout"], ["drivers/net/ethernet/freescale/ucc_geth.c", "ucc_geth_timeout"], ["drivers/net/ethernet/fujitsu/fmvj18x_cs.c", "fjn_tx_timeout"], ["drivers/net/ethernet/google/gve/gve_main.c", "gve_tx_timeout"], ["drivers/net/ethernet/hisilicon/hip04_eth.c", "hip04_timeout"], ["drivers/net/ethernet/hisilicon/hix5hd2_gmac.c", "hix5hd2_net_timeout"], ["drivers/net/ethernet/hisilicon/hns/hns_enet.c", "hns_nic_net_timeout"], ["drivers/net/ethernet/hisilicon/hns3/hns3_enet.c", "hns3_nic_net_timeout"], ["drivers/net/ethernet/huawei/hinic/hinic_main.c", "hinic_tx_timeout"], ["drivers/net/ethernet/i825xx/82596.c", "i596_tx_timeout"], ["drivers/net/ethernet/i825xx/ether1.c", "ether1_timeout"], ["drivers/net/ethernet/i825xx/lib82596.c", "i596_tx_timeout"], ["drivers/net/ethernet/i825xx/sun3_82586.c", "sun3_82586_timeout"], ["drivers/net/ethernet/ibm/ehea/ehea_main.c", "ehea_tx_watchdog"], ["drivers/net/ethernet/ibm/emac/core.c", "emac_tx_timeout"], ["drivers/net/ethernet/ibm/emac/core.c", "emac_tx_timeout"], ["drivers/net/ethernet/ibm/ibmvnic.c", "ibmvnic_tx_timeout"], ["drivers/net/ethernet/intel/e100.c", "e100_tx_timeout"], ["drivers/net/ethernet/intel/e1000/e1000_main.c", "e1000_tx_timeout"], ["drivers/net/ethernet/intel/e1000e/netdev.c", "e1000_tx_timeout"], ["drivers/net/ethernet/intel/fm10k/fm10k_netdev.c", "fm10k_tx_timeout"], ["drivers/net/ethernet/intel/i40e/i40e_main.c", "i40e_tx_timeout"], ["drivers/net/ethernet/intel/iavf/iavf_main.c", "iavf_tx_timeout"], ["drivers/net/ethernet/intel/ice/ice_main.c", "ice_tx_timeout"], ["drivers/net/ethernet/intel/ice/ice_main.c", "ice_tx_timeout"], ["drivers/net/ethernet/intel/igb/igb_main.c", "igb_tx_timeout"], ["drivers/net/ethernet/intel/igbvf/netdev.c", "igbvf_tx_timeout"], ["drivers/net/ethernet/intel/ixgb/ixgb_main.c", "ixgb_tx_timeout"], ["drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c", "adapter->netdev->netdev_ops->ndo_tx_timeout(adapter->netdev);"], ["drivers/net/ethernet/intel/ixgbe/ixgbe_main.c", "ixgbe_tx_timeout"], ["drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c", "ixgbevf_tx_timeout"], ["drivers/net/ethernet/jme.c", "jme_tx_timeout"], ["drivers/net/ethernet/korina.c", "korina_tx_timeout"], ["drivers/net/ethernet/lantiq_etop.c", "ltq_etop_tx_timeout"], ["drivers/net/ethernet/marvell/mv643xx_eth.c", "mv643xx_eth_tx_timeout"], ["drivers/net/ethernet/marvell/pxa168_eth.c", "pxa168_eth_tx_timeout"], ["drivers/net/ethernet/marvell/skge.c", "skge_tx_timeout"], ["drivers/net/ethernet/marvell/sky2.c", "sky2_tx_timeout"], ["drivers/net/ethernet/marvell/sky2.c", "sky2_tx_timeout"], ["drivers/net/ethernet/mediatek/mtk_eth_soc.c", "mtk_tx_timeout"], ["drivers/net/ethernet/mellanox/mlx4/en_netdev.c", "mlx4_en_tx_timeout"], ["drivers/net/ethernet/mellanox/mlx4/en_netdev.c", "mlx4_en_tx_timeout"], ["drivers/net/ethernet/mellanox/mlx5/core/en_main.c", "mlx5e_tx_timeout"], ["drivers/net/ethernet/micrel/ks8842.c", "ks8842_tx_timeout"], ["drivers/net/ethernet/micrel/ksz884x.c", "netdev_tx_timeout"], ["drivers/net/ethernet/microchip/enc28j60.c", "enc28j60_tx_timeout"], ["drivers/net/ethernet/microchip/encx24j600.c", "encx24j600_tx_timeout"], ["drivers/net/ethernet/natsemi/sonic.h", "sonic_tx_timeout"], ["drivers/net/ethernet/natsemi/sonic.c", "sonic_tx_timeout"], ["drivers/net/ethernet/natsemi/jazzsonic.c", "sonic_tx_timeout"], ["drivers/net/ethernet/natsemi/macsonic.c", "sonic_tx_timeout"], ["drivers/net/ethernet/natsemi/natsemi.c", "ns_tx_timeout"], ["drivers/net/ethernet/natsemi/ns83820.c", "ns83820_tx_timeout"], ["drivers/net/ethernet/natsemi/xtsonic.c", "sonic_tx_timeout"], ["drivers/net/ethernet/neterion/s2io.h", "s2io_tx_watchdog"], ["drivers/net/ethernet/neterion/s2io.c", "s2io_tx_watchdog"], ["drivers/net/ethernet/neterion/vxge/vxge-main.c", "vxge_tx_watchdog"], ["drivers/net/ethernet/netronome/nfp/nfp_net_common.c", "nfp_net_tx_timeout"], ["drivers/net/ethernet/nvidia/forcedeth.c", "nv_tx_timeout"], ["drivers/net/ethernet/nvidia/forcedeth.c", "nv_tx_timeout"], ["drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c", "pch_gbe_tx_timeout"], ["drivers/net/ethernet/packetengines/hamachi.c", "hamachi_tx_timeout"], ["drivers/net/ethernet/packetengines/yellowfin.c", "yellowfin_tx_timeout"], ["drivers/net/ethernet/pensando/ionic/ionic_lif.c", "ionic_tx_timeout"], ["drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c", "netxen_tx_timeout"], ["drivers/net/ethernet/qlogic/qla3xxx.c", "ql3xxx_tx_timeout"], ["drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c", "qlcnic_tx_timeout"], ["drivers/net/ethernet/qualcomm/emac/emac.c", "emac_tx_timeout"], ["drivers/net/ethernet/qualcomm/qca_spi.c", "qcaspi_netdev_tx_timeout"], ["drivers/net/ethernet/qualcomm/qca_uart.c", "qcauart_netdev_tx_timeout"], ["drivers/net/ethernet/rdc/r6040.c", "r6040_tx_timeout"], ["drivers/net/ethernet/realtek/8139cp.c", "cp_tx_timeout"], ["drivers/net/ethernet/realtek/8139too.c", "rtl8139_tx_timeout"], ["drivers/net/ethernet/realtek/atp.c", "tx_timeout"], ["drivers/net/ethernet/realtek/r8169_main.c", "rtl8169_tx_timeout"], ["drivers/net/ethernet/renesas/ravb_main.c", "ravb_tx_timeout"], ["drivers/net/ethernet/renesas/sh_eth.c", "sh_eth_tx_timeout"], ["drivers/net/ethernet/renesas/sh_eth.c", "sh_eth_tx_timeout"], ["drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c", "sxgbe_tx_timeout"], ["drivers/net/ethernet/seeq/ether3.c", "ether3_timeout"], ["drivers/net/ethernet/seeq/sgiseeq.c", "timeout"], ["drivers/net/ethernet/sfc/efx.c", "efx_watchdog"], ["drivers/net/ethernet/sfc/falcon/efx.c", "ef4_watchdog"], ["drivers/net/ethernet/sgi/ioc3-eth.c", "ioc3_timeout"], ["drivers/net/ethernet/sgi/meth.c", "meth_tx_timeout"], ["drivers/net/ethernet/silan/sc92031.c", "sc92031_tx_timeout"], ["drivers/net/ethernet/sis/sis190.c", "sis190_tx_timeout"], ["drivers/net/ethernet/sis/sis900.c", "sis900_tx_timeout"], ["drivers/net/ethernet/smsc/epic100.c", "epic_tx_timeout"], ["drivers/net/ethernet/smsc/smc911x.c", "smc911x_timeout"], ["drivers/net/ethernet/smsc/smc9194.c", "smc_timeout"], ["drivers/net/ethernet/smsc/smc91c92_cs.c", "smc_tx_timeout"], ["drivers/net/ethernet/smsc/smc91x.c", "smc_timeout"], ["drivers/net/ethernet/stmicro/stmmac/stmmac_main.c", "stmmac_tx_timeout"], ["drivers/net/ethernet/sun/cassini.c", "cas_tx_timeout"], ["drivers/net/ethernet/sun/ldmvsw.c", "sunvnet_tx_timeout_common"], ["drivers/net/ethernet/sun/niu.c", "niu_tx_timeout"], ["drivers/net/ethernet/sun/sunbmac.c", "bigmac_tx_timeout"], ["drivers/net/ethernet/sun/sungem.c", "gem_tx_timeout"], ["drivers/net/ethernet/sun/sunhme.c", "happy_meal_tx_timeout"], ["drivers/net/ethernet/sun/sunqe.c", "qe_tx_timeout"], ["drivers/net/ethernet/sun/sunvnet.c", "sunvnet_tx_timeout_common"], ["drivers/net/ethernet/sun/sunvnet_common.c", "sunvnet_tx_timeout_common"], ["drivers/net/ethernet/sun/sunvnet_common.h", "sunvnet_tx_timeout_common"], ["drivers/net/ethernet/synopsys/dwc-xlgmac-net.c", "xlgmac_tx_timeout"], ["drivers/net/ethernet/ti/cpmac.c", "cpmac_tx_timeout"], ["drivers/net/ethernet/ti/cpsw.c", "cpsw_ndo_tx_timeout"], ["drivers/net/ethernet/ti/cpsw_priv.c", "cpsw_ndo_tx_timeout"], ["drivers/net/ethernet/ti/cpsw_priv.h", "cpsw_ndo_tx_timeout"], ["drivers/net/ethernet/ti/davinci_emac.c", "emac_dev_tx_timeout"], ["drivers/net/ethernet/ti/netcp_core.c", "netcp_ndo_tx_timeout"], ["drivers/net/ethernet/ti/tlan.c", "tlan_tx_timeout"], ["drivers/net/ethernet/toshiba/ps3_gelic_net.h", "gelic_net_tx_timeout"], ["drivers/net/ethernet/toshiba/ps3_gelic_net.c", "gelic_net_tx_timeout"], ["drivers/net/ethernet/toshiba/ps3_gelic_wireless.c", "gelic_net_tx_timeout"], ["drivers/net/ethernet/toshiba/spider_net.c", "spider_net_tx_timeout"], ["drivers/net/ethernet/toshiba/tc35815.c", "tc35815_tx_timeout"], ["drivers/net/ethernet/via/via-rhine.c", "rhine_tx_timeout"], ["drivers/net/ethernet/wiznet/w5100.c", "w5100_tx_timeout"], ["drivers/net/ethernet/wiznet/w5300.c", "w5300_tx_timeout"], ["drivers/net/ethernet/xilinx/xilinx_emaclite.c", "xemaclite_tx_timeout"], ["drivers/net/ethernet/xircom/xirc2ps_cs.c", "xirc_tx_timeout"], ["drivers/net/fjes/fjes_main.c", "fjes_tx_retry"], ["drivers/net/slip/slip.c", "sl_tx_timeout"], ["include/linux/usb/usbnet.h", "usbnet_tx_timeout"], ["drivers/net/usb/aqc111.c", "usbnet_tx_timeout"], ["drivers/net/usb/asix_devices.c", "usbnet_tx_timeout"], ["drivers/net/usb/asix_devices.c", "usbnet_tx_timeout"], ["drivers/net/usb/asix_devices.c", "usbnet_tx_timeout"], ["drivers/net/usb/ax88172a.c", "usbnet_tx_timeout"], ["drivers/net/usb/ax88179_178a.c", "usbnet_tx_timeout"], ["drivers/net/usb/catc.c", "catc_tx_timeout"], ["drivers/net/usb/cdc_mbim.c", "usbnet_tx_timeout"], ["drivers/net/usb/cdc_ncm.c", "usbnet_tx_timeout"], ["drivers/net/usb/dm9601.c", "usbnet_tx_timeout"], ["drivers/net/usb/hso.c", "hso_net_tx_timeout"], ["drivers/net/usb/int51x1.c", "usbnet_tx_timeout"], ["drivers/net/usb/ipheth.c", "ipheth_tx_timeout"], ["drivers/net/usb/kaweth.c", "kaweth_tx_timeout"], ["drivers/net/usb/lan78xx.c", "lan78xx_tx_timeout"], ["drivers/net/usb/mcs7830.c", "usbnet_tx_timeout"], ["drivers/net/usb/pegasus.c", "pegasus_tx_timeout"], ["drivers/net/usb/qmi_wwan.c", "usbnet_tx_timeout"], ["drivers/net/usb/r8152.c", "rtl8152_tx_timeout"], ["drivers/net/usb/rndis_host.c", "usbnet_tx_timeout"], ["drivers/net/usb/rtl8150.c", "rtl8150_tx_timeout"], ["drivers/net/usb/sierra_net.c", "usbnet_tx_timeout"], ["drivers/net/usb/smsc75xx.c", "usbnet_tx_timeout"], ["drivers/net/usb/smsc95xx.c", "usbnet_tx_timeout"], ["drivers/net/usb/sr9700.c", "usbnet_tx_timeout"], ["drivers/net/usb/sr9800.c", "usbnet_tx_timeout"], ["drivers/net/usb/usbnet.c", "usbnet_tx_timeout"], ["drivers/net/vmxnet3/vmxnet3_drv.c", "vmxnet3_tx_timeout"], ["drivers/net/wan/cosa.c", "cosa_net_timeout"], ["drivers/net/wan/farsync.c", "fst_tx_timeout"], ["drivers/net/wan/fsl_ucc_hdlc.c", "uhdlc_tx_timeout"], ["drivers/net/wan/lmc/lmc_main.c", "lmc_driver_timeout"], ["drivers/net/wan/x25_asy.c", "x25_asy_timeout"], ["drivers/net/wimax/i2400m/netdev.c", "i2400m_tx_timeout"], ["drivers/net/wireless/intel/ipw2x00/ipw2100.c", "ipw2100_tx_timeout"], ["drivers/net/wireless/intersil/hostap/hostap_main.c", "prism2_tx_timeout"], ["drivers/net/wireless/intersil/hostap/hostap_main.c", "prism2_tx_timeout"], ["drivers/net/wireless/intersil/hostap/hostap_main.c", "prism2_tx_timeout"], ["drivers/net/wireless/intersil/orinoco/main.c", "orinoco_tx_timeout"], ["drivers/net/wireless/intersil/orinoco/orinoco_usb.c", "orinoco_tx_timeout"], ["drivers/net/wireless/intersil/orinoco/orinoco.h", "orinoco_tx_timeout"], ["drivers/net/wireless/intersil/prism54/islpci_dev.c", "islpci_eth_tx_timeout"], ["drivers/net/wireless/intersil/prism54/islpci_eth.c", "islpci_eth_tx_timeout"], ["drivers/net/wireless/intersil/prism54/islpci_eth.h", "islpci_eth_tx_timeout"], ["drivers/net/wireless/marvell/mwifiex/main.c", "mwifiex_tx_timeout"], ["drivers/net/wireless/quantenna/qtnfmac/core.c", "qtnf_netdev_tx_timeout"], ["drivers/net/wireless/quantenna/qtnfmac/core.h", "qtnf_netdev_tx_timeout"], ["drivers/net/wireless/rndis_wlan.c", "usbnet_tx_timeout"], ["drivers/net/wireless/wl3501_cs.c", "wl3501_tx_timeout"], ["drivers/net/wireless/zydas/zd1201.c", "zd1201_tx_timeout"], ["drivers/s390/net/qeth_core.h", "qeth_tx_timeout"], ["drivers/s390/net/qeth_core_main.c", "qeth_tx_timeout"], ["drivers/s390/net/qeth_l2_main.c", "qeth_tx_timeout"], ["drivers/s390/net/qeth_l2_main.c", "qeth_tx_timeout"], ["drivers/s390/net/qeth_l3_main.c", "qeth_tx_timeout"], ["drivers/s390/net/qeth_l3_main.c", "qeth_tx_timeout"], ["drivers/staging/ks7010/ks_wlan_net.c", "ks_wlan_tx_timeout"], ["drivers/staging/qlge/qlge_main.c", "qlge_tx_timeout"], ["drivers/staging/rtl8192e/rtl8192e/rtl_core.c", "_rtl92e_tx_timeout"], ["drivers/staging/rtl8192u/r8192U_core.c", "tx_timeout"], ["drivers/staging/unisys/visornic/visornic_main.c", "visornic_xmit_timeout"], ["drivers/staging/wlan-ng/p80211netdev.c", "p80211knetdev_tx_timeout"], ["drivers/tty/n_gsm.c", "gsm_mux_net_tx_timeout"], ["drivers/tty/synclink.c", "hdlcdev_tx_timeout"], ["drivers/tty/synclink_gt.c", "hdlcdev_tx_timeout"], ["drivers/tty/synclinkmp.c", "hdlcdev_tx_timeout"], ["net/atm/lec.c", "lec_tx_timeout"], ["net/bluetooth/bnep/netdev.c", "bnep_net_timeout"] ); for my $p (@work) { my @pair = @$p; my $file = $pair[0]; my $func = $pair[1]; print STDERR $file , ": ", $func,"\n"; our @ARGV = ($file); while () { if (m/($func\s*\(struct\s+net_device\s+\*[A-Za-z_]?[A-Za-z-0-9_]*)(\))/) { print STDERR "found $1+$2 in $file\n"; } if (s/($func\s*\(struct\s+net_device\s+\*[A-Za-z_]?[A-Za-z-0-9_]*)(\))/$1, unsigned int txqueue$2/) { print STDERR "$func found in $file\n"; } print; } } where the list of files and functions is simply from: git grep ndo_tx_timeout, with manual addition of headers in the rare cases where the function is from a header, then manually changing the few places which actually call ndo_tx_timeout. Signed-off-by: Michael S. Tsirkin Acked-by: Heiner Kallweit Acked-by: Jakub Kicinski Acked-by: Shannon Nelson Reviewed-by: Martin Habets changes from v9: fixup a forward declaration changes from v9: more leftovers from v3 change changes from v8: fix up a missing direct call to timeout rebased on net-next changes from v7: fixup leftovers from v3 change changes from v6: fix typo in rtl driver changes from v5: add missing files (allow any net device argument name) changes from v4: add a missing driver header changes from v3: change queue # to unsigned Changes from v2: added headers Changes from v1: Fix errors found by kbuild: generalize the pattern a bit, to pick up a couple of instances missed by the previous version. Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/s390/net/qeth_core_main.c') diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index b9a2349e4b90..ce7ff1abbef3 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -4325,7 +4325,7 @@ int qeth_set_access_ctrl_online(struct qeth_card *card, int fallback) return rc; } -void qeth_tx_timeout(struct net_device *dev) +void qeth_tx_timeout(struct net_device *dev, unsigned int txqueue) { struct qeth_card *card; -- cgit v1.2.3-70-g09d2 From 871602b1079234b2a9279062eaeadb3aad7bc863 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Wed, 18 Dec 2019 17:34:42 +0100 Subject: s390/qeth: only handle IRQs while device is online A qeth device that's offline should not be receiving any IRQs - all pending IOs have been terminated, and we avoid starting any new ones. So rather than immediately registering the IRQ handler when the device is probed, only register it while the device is online. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core_main.c | 68 ++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 37 deletions(-) (limited to 'drivers/s390/net/qeth_core_main.c') diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index ce7ff1abbef3..3d2374801308 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -972,8 +972,6 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm, /* while we hold the ccwdev lock, this stays valid: */ gdev = dev_get_drvdata(&cdev->dev); card = dev_get_drvdata(&gdev->dev); - if (!card) - return; QETH_CARD_TEXT(card, 5, "irq"); @@ -1198,31 +1196,6 @@ static void qeth_free_buffer_pool(struct qeth_card *card) } } -static void qeth_clean_channel(struct qeth_channel *channel) -{ - struct ccw_device *cdev = channel->ccwdev; - - QETH_DBF_TEXT(SETUP, 2, "freech"); - - spin_lock_irq(get_ccwdev_lock(cdev)); - cdev->handler = NULL; - spin_unlock_irq(get_ccwdev_lock(cdev)); -} - -static void qeth_setup_channel(struct qeth_channel *channel) -{ - struct ccw_device *cdev = channel->ccwdev; - - QETH_DBF_TEXT(SETUP, 2, "setupch"); - - channel->state = CH_STATE_DOWN; - atomic_set(&channel->irq_pending, 0); - - spin_lock_irq(get_ccwdev_lock(cdev)); - cdev->handler = qeth_irq; - spin_unlock_irq(get_ccwdev_lock(cdev)); -} - static int qeth_osa_set_output_queues(struct qeth_card *card, bool single) { unsigned int count = single ? 1 : card->dev->num_tx_queues; @@ -1395,9 +1368,6 @@ static struct qeth_card *qeth_alloc_card(struct ccwgroup_device *gdev) if (!card->read_cmd) goto out_read_cmd; - qeth_setup_channel(&card->read); - qeth_setup_channel(&card->write); - qeth_setup_channel(&card->data); card->qeth_service_level.seq_print = qeth_core_sl_print; register_service_level(&card->qeth_service_level); return card; @@ -1467,12 +1437,38 @@ int qeth_stop_channel(struct qeth_channel *channel) channel->active_cmd); channel->active_cmd = NULL; } + cdev->handler = NULL; spin_unlock_irq(get_ccwdev_lock(cdev)); return rc; } EXPORT_SYMBOL_GPL(qeth_stop_channel); +static int qeth_start_channel(struct qeth_channel *channel) +{ + struct ccw_device *cdev = channel->ccwdev; + int rc; + + channel->state = CH_STATE_DOWN; + atomic_set(&channel->irq_pending, 0); + + spin_lock_irq(get_ccwdev_lock(cdev)); + cdev->handler = qeth_irq; + spin_unlock_irq(get_ccwdev_lock(cdev)); + + rc = ccw_device_set_online(cdev); + if (rc) + goto err; + + return 0; + +err: + spin_lock_irq(get_ccwdev_lock(cdev)); + cdev->handler = NULL; + spin_unlock_irq(get_ccwdev_lock(cdev)); + return rc; +} + static int qeth_halt_channels(struct qeth_card *card) { int rc1 = 0, rc2 = 0, rc3 = 0; @@ -4706,7 +4702,7 @@ static void qeth_determine_capabilities(struct qeth_card *card) QETH_CARD_TEXT(card, 2, "detcapab"); if (!ddev->online) { ddev_offline = 1; - rc = ccw_device_set_online(ddev); + rc = qeth_start_channel(channel); if (rc) { QETH_CARD_TEXT_(card, 2, "3err%d", rc); goto out; @@ -4881,9 +4877,6 @@ out_free_nothing: static void qeth_core_free_card(struct qeth_card *card) { QETH_CARD_TEXT(card, 2, "freecrd"); - qeth_clean_channel(&card->read); - qeth_clean_channel(&card->write); - qeth_clean_channel(&card->data); qeth_put_cmd(card->read_cmd); destroy_workqueue(card->event_wq); unregister_service_level(&card->qeth_service_level); @@ -4946,13 +4939,14 @@ retry: qeth_stop_channel(&card->write); qeth_stop_channel(&card->read); qdio_free(CARD_DDEV(card)); - rc = ccw_device_set_online(CARD_RDEV(card)); + + rc = qeth_start_channel(&card->read); if (rc) goto retriable; - rc = ccw_device_set_online(CARD_WDEV(card)); + rc = qeth_start_channel(&card->write); if (rc) goto retriable; - rc = ccw_device_set_online(CARD_DDEV(card)); + rc = qeth_start_channel(&card->data); if (rc) goto retriable; retriable: -- cgit v1.2.3-70-g09d2 From 7359393f3c19c9351e81345ef29f4f47229a6416 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Wed, 18 Dec 2019 17:34:43 +0100 Subject: s390/qeth: wake up all waiters from qeth_irq() card->wait_q is shared by different users, for different wake-up conditions. qeth_irq() can potentially trigger multiple of these conditions: 1) A change to channel->irq_pending, which qeth_send_control_data() is waiting for. 2) A change to card->state, which qeth_clear_channel() and qeth_halt_channel() are waiting for. As qeth_irq() does only a single wake_up(), we might miss to wake up a second eligible waiter. Luckily all waiters are guarded with a timeout, so this situation should recover on its own eventually. To make things work robustly, add an additional wake_up() for changes to channel->state. And extract a helper that updates channel->irq_pending along with the needed wake_up(). Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core.h | 7 +++++++ drivers/s390/net/qeth_core_main.c | 27 +++++++++++---------------- 2 files changed, 18 insertions(+), 16 deletions(-) (limited to 'drivers/s390/net/qeth_core_main.c') diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index a23875a4fa2b..b54ef12840a2 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -862,6 +862,13 @@ static inline bool qeth_card_hw_is_reachable(struct qeth_card *card) return card->state == CARD_STATE_SOFTSETUP; } +static inline void qeth_unlock_channel(struct qeth_card *card, + struct qeth_channel *channel) +{ + atomic_set(&channel->irq_pending, 0); + wake_up(&card->wait_q); +} + struct qeth_trap_id { __u16 lparnr; char vmname[8]; diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 3d2374801308..38f3ed7567bc 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -520,11 +520,10 @@ static int __qeth_issue_next_read(struct qeth_card *card) } else { QETH_DBF_MESSAGE(2, "error %i on device %x when starting next read ccw!\n", rc, CARD_DEVID(card)); - atomic_set(&channel->irq_pending, 0); + qeth_unlock_channel(card, channel); qeth_put_cmd(iob); card->read_or_write_problem = 1; qeth_schedule_recovery(card); - wake_up(&card->wait_q); } return rc; } @@ -1001,24 +1000,25 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm, } channel->active_cmd = NULL; + qeth_unlock_channel(card, channel); rc = qeth_check_irb_error(card, cdev, irb); if (rc) { /* IO was terminated, free its resources. */ if (iob) qeth_cancel_cmd(iob, rc); - atomic_set(&channel->irq_pending, 0); - wake_up(&card->wait_q); return; } - atomic_set(&channel->irq_pending, 0); - - if (irb->scsw.cmd.fctl & (SCSW_FCTL_CLEAR_FUNC)) + if (irb->scsw.cmd.fctl & SCSW_FCTL_CLEAR_FUNC) { channel->state = CH_STATE_STOPPED; + wake_up(&card->wait_q); + } - if (irb->scsw.cmd.fctl & (SCSW_FCTL_HALT_FUNC)) + if (irb->scsw.cmd.fctl & SCSW_FCTL_HALT_FUNC) { channel->state = CH_STATE_HALTED; + wake_up(&card->wait_q); + } if (iob && (irb->scsw.cmd.fctl & (SCSW_FCTL_CLEAR_FUNC | SCSW_FCTL_HALT_FUNC))) { @@ -1052,7 +1052,7 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm, qeth_cancel_cmd(iob, rc); qeth_clear_ipacmd_list(card); qeth_schedule_recovery(card); - goto out; + return; } } @@ -1060,16 +1060,12 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm, /* sanity check: */ if (irb->scsw.cmd.count > iob->length) { qeth_cancel_cmd(iob, -EIO); - goto out; + return; } if (iob->callback) iob->callback(card, iob, iob->length - irb->scsw.cmd.count); } - -out: - wake_up(&card->wait_q); - return; } static void qeth_notify_skbs(struct qeth_qdio_out_q *q, @@ -1780,8 +1776,7 @@ static int qeth_send_control_data(struct qeth_card *card, QETH_CARD_TEXT_(card, 2, " err%d", rc); qeth_dequeue_cmd(card, iob); qeth_put_cmd(iob); - atomic_set(&channel->irq_pending, 0); - wake_up(&card->wait_q); + qeth_unlock_channel(card, channel); goto out; } -- cgit v1.2.3-70-g09d2 From 52f82bf16b6e754c2a9971420ccc8209ff52081c Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Wed, 18 Dec 2019 17:34:49 +0100 Subject: s390/qeth: consolidate helpers for capability checking Convert the old code to use struct qeth_ipa_caps, and while at it remove all unused helper macros. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core.h | 47 +++------------------------------------ drivers/s390/net/qeth_core_main.c | 28 +++++++++++------------ drivers/s390/net/qeth_core_mpc.h | 13 +++++++++-- 3 files changed, 27 insertions(+), 61 deletions(-) (limited to 'drivers/s390/net/qeth_core_main.c') diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index b54ef12840a2..6e16b19732f6 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -125,12 +125,6 @@ struct qeth_routing_info { enum qeth_routing_types type; }; -/* IPA stuff */ -struct qeth_ipa_info { - __u32 supported_funcs; - __u32 enabled_funcs; -}; - /* SETBRIDGEPORT stuff */ enum qeth_sbp_roles { QETH_SBP_ROLE_NONE = 0, @@ -169,41 +163,6 @@ struct qeth_vnicc_info { bool rx_bcast_enabled; }; -static inline int qeth_is_adp_supported(struct qeth_ipa_info *ipa, - enum qeth_ipa_setadp_cmd func) -{ - return (ipa->supported_funcs & func); -} - -static inline int qeth_is_ipa_supported(struct qeth_ipa_info *ipa, - enum qeth_ipa_funcs func) -{ - return (ipa->supported_funcs & func); -} - -static inline int qeth_is_ipa_enabled(struct qeth_ipa_info *ipa, - enum qeth_ipa_funcs func) -{ - return (ipa->supported_funcs & ipa->enabled_funcs & func); -} - -#define qeth_adp_supported(c, f) \ - qeth_is_adp_supported(&c->options.adp, f) -#define qeth_is_supported(c, f) \ - qeth_is_ipa_supported(&c->options.ipa4, f) -#define qeth_is_enabled(c, f) \ - qeth_is_ipa_enabled(&c->options.ipa4, f) -#define qeth_is_supported6(c, f) \ - qeth_is_ipa_supported(&c->options.ipa6, f) -#define qeth_is_enabled6(c, f) \ - qeth_is_ipa_enabled(&c->options.ipa6, f) -#define qeth_is_ipafunc_supported(c, prot, f) \ - ((prot == QETH_PROT_IPV6) ? \ - qeth_is_supported6(c, f) : qeth_is_supported(c, f)) -#define qeth_is_ipafunc_enabled(c, prot, f) \ - ((prot == QETH_PROT_IPV6) ? \ - qeth_is_enabled6(c, f) : qeth_is_enabled(c, f)) - #define QETH_IDX_FUNC_LEVEL_OSD 0x0101 #define QETH_IDX_FUNC_LEVEL_IQD 0x4108 @@ -735,11 +694,11 @@ enum qeth_discipline_id { }; struct qeth_card_options { + struct qeth_ipa_caps ipa4; + struct qeth_ipa_caps ipa6; struct qeth_routing_info route4; - struct qeth_ipa_info ipa4; - struct qeth_ipa_info adp; /*Adapter parameters*/ struct qeth_routing_info route6; - struct qeth_ipa_info ipa6; + struct qeth_ipa_caps adp; /* Adapter parameters */ struct qeth_sbp_info sbp; /* SETBRIDGEPORT options */ struct qeth_vnicc_info vnicc; /* VNICC options */ int fake_broadcast; diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 38f3ed7567bc..6b55271091cb 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -2862,7 +2862,7 @@ static int qeth_query_setadapterparms_cb(struct qeth_card *card, cmd->data.setadapterparms.data.query_cmds_supp.lan_type; QETH_CARD_TEXT_(card, 2, "lnk %d", card->info.link_type); } - card->options.adp.supported_funcs = + card->options.adp.supported = cmd->data.setadapterparms.data.query_cmds_supp.supported_cmds; return 0; } @@ -2918,8 +2918,8 @@ static int qeth_query_ipassists_cb(struct qeth_card *card, case IPA_RC_NOTSUPP: case IPA_RC_L2_UNSUPPORTED_CMD: QETH_CARD_TEXT(card, 2, "ipaunsup"); - card->options.ipa4.supported_funcs |= IPA_SETADAPTERPARMS; - card->options.ipa6.supported_funcs |= IPA_SETADAPTERPARMS; + card->options.ipa4.supported |= IPA_SETADAPTERPARMS; + card->options.ipa6.supported |= IPA_SETADAPTERPARMS; return -EOPNOTSUPP; default: QETH_DBF_MESSAGE(1, "IPA_CMD_QIPASSIST on device %x: Unhandled rc=%#x\n", @@ -2927,13 +2927,11 @@ static int qeth_query_ipassists_cb(struct qeth_card *card, return -EIO; } - if (cmd->hdr.prot_version == QETH_PROT_IPV4) { - card->options.ipa4.supported_funcs = cmd->hdr.ipa_supported; - card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled; - } else if (cmd->hdr.prot_version == QETH_PROT_IPV6) { - card->options.ipa6.supported_funcs = cmd->hdr.ipa_supported; - card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled; - } else + if (cmd->hdr.prot_version == QETH_PROT_IPV4) + card->options.ipa4 = cmd->hdr.assists; + else if (cmd->hdr.prot_version == QETH_PROT_IPV6) + card->options.ipa6 = cmd->hdr.assists; + else QETH_DBF_MESSAGE(1, "IPA_CMD_QIPASSIST on device %x: Flawed LIC detected\n", CARD_DEVID(card)); return 0; @@ -5002,9 +5000,9 @@ retriable: *carrier_ok = true; } - card->options.ipa4.supported_funcs = 0; - card->options.ipa6.supported_funcs = 0; - card->options.adp.supported_funcs = 0; + card->options.ipa4.supported = 0; + card->options.ipa6.supported = 0; + card->options.adp.supported = 0; card->options.sbp.supported_funcs = 0; card->info.diagass_support = 0; rc = qeth_query_ipassists(card, QETH_PROT_IPV4); @@ -5421,9 +5419,9 @@ int qeth_setassparms_cb(struct qeth_card *card, cmd->hdr.return_code = cmd->data.setassparms.hdr.return_code; if (cmd->hdr.prot_version == QETH_PROT_IPV4) - card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled; + card->options.ipa4.enabled = cmd->hdr.assists.enabled; if (cmd->hdr.prot_version == QETH_PROT_IPV6) - card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled; + card->options.ipa6.enabled = cmd->hdr.assists.enabled; return 0; } EXPORT_SYMBOL_GPL(qeth_setassparms_cb); diff --git a/drivers/s390/net/qeth_core_mpc.h b/drivers/s390/net/qeth_core_mpc.h index f13225b43781..f4dc37e28ac7 100644 --- a/drivers/s390/net/qeth_core_mpc.h +++ b/drivers/s390/net/qeth_core_mpc.h @@ -53,6 +53,16 @@ static inline bool qeth_ipa_caps_enabled(struct qeth_ipa_caps *caps, u32 mask) return (caps->enabled & mask) == mask; } +#define qeth_adp_supported(c, f) \ + qeth_ipa_caps_supported(&c->options.adp, f) +#define qeth_is_supported(c, f) \ + qeth_ipa_caps_supported(&c->options.ipa4, f) +#define qeth_is_supported6(c, f) \ + qeth_ipa_caps_supported(&c->options.ipa6, f) +#define qeth_is_ipafunc_supported(c, prot, f) \ + ((prot == QETH_PROT_IPV6) ? qeth_is_supported6(c, f) : \ + qeth_is_supported(c, f)) + enum qeth_card_types { QETH_CARD_TYPE_OSD = 1, QETH_CARD_TYPE_IQD = 5, @@ -766,8 +776,7 @@ struct qeth_ipacmd_hdr { __u8 prim_version_no; __u8 param_count; __u16 prot_version; - __u32 ipa_supported; - __u32 ipa_enabled; + struct qeth_ipa_caps assists; } __attribute__ ((packed)); /* The IPA command itself */ -- cgit v1.2.3-70-g09d2 From 334b49de120dd6deb28c31eedb7ca81351f7464e Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Wed, 18 Dec 2019 17:34:50 +0100 Subject: s390/qeth: make use of napi_schedule_irqoff() qeth_qdio_start_poll() is called from the qdio layer's IRQ handler, while IRQs are masked. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/s390/net/qeth_core_main.c') diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 6b55271091cb..78349355c582 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -3402,7 +3402,7 @@ static void qeth_qdio_start_poll(struct ccw_device *ccwdev, int queue, struct qeth_card *card = (struct qeth_card *)card_ptr; if (card->dev->flags & IFF_UP) - napi_schedule(&card->napi); + napi_schedule_irqoff(&card->napi); } int qeth_configure_cq(struct qeth_card *card, enum qeth_cq cq) -- cgit v1.2.3-70-g09d2 From c04b116a2866b3e3a6b909a576769ccde3d622ac Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Mon, 23 Dec 2019 15:22:25 +0100 Subject: s390/qeth: consolidate RX code To reduce the path length and levels of indirection, move the RX processing from the sub-drivers into the core. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core.h | 16 ---- drivers/s390/net/qeth_core_main.c | 180 ++++++++++++++++++++++++++++++++------ drivers/s390/net/qeth_l2_main.c | 40 --------- drivers/s390/net/qeth_l3_main.c | 91 ------------------- 4 files changed, 153 insertions(+), 174 deletions(-) (limited to 'drivers/s390/net/qeth_core_main.c') diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 6e16b19732f6..4ab3be814ea7 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -728,7 +728,6 @@ struct qeth_osn_info { struct qeth_discipline { const struct device_type *devtype; - int (*process_rx_buffer)(struct qeth_card *card, int budget, int *done); int (*recover)(void *ptr); int (*setup) (struct ccwgroup_device *); void (*remove) (struct ccwgroup_device *); @@ -923,18 +922,6 @@ static inline struct dst_entry *qeth_dst_check_rcu(struct sk_buff *skb, int ipv) return dst; } -static inline void qeth_rx_csum(struct qeth_card *card, struct sk_buff *skb, - u8 flags) -{ - if ((card->dev->features & NETIF_F_RXCSUM) && - (flags & QETH_HDR_EXT_CSUM_TRANSP_REQ)) { - skb->ip_summed = CHECKSUM_UNNECESSARY; - QETH_CARD_STAT_INC(card, rx_skb_csum); - } else { - skb->ip_summed = CHECKSUM_NONE; - } -} - static inline void qeth_tx_csum(struct sk_buff *skb, u8 *flags, int ipv) { *flags |= QETH_HDR_EXT_CSUM_TRANSP_REQ; @@ -1031,9 +1018,6 @@ struct qeth_cmd_buffer *qeth_get_diag_cmd(struct qeth_card *card, void qeth_notify_cmd(struct qeth_cmd_buffer *iob, int reason); void qeth_put_cmd(struct qeth_cmd_buffer *iob); -struct sk_buff *qeth_core_get_next_skb(struct qeth_card *, - struct qeth_qdio_buffer *, struct qdio_buffer_element **, int *, - struct qeth_hdr **); void qeth_schedule_recovery(struct qeth_card *); int qeth_poll(struct napi_struct *napi, int budget); void qeth_clear_ipacmd_list(struct qeth_card *); diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 41f37ce89a4f..8e2c0588525f 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -5046,6 +5046,114 @@ out: } EXPORT_SYMBOL_GPL(qeth_core_hardsetup_card); +#if IS_ENABLED(CONFIG_QETH_L3) +static void qeth_l3_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, + struct qeth_hdr *hdr) +{ + struct af_iucv_trans_hdr *iucv = (struct af_iucv_trans_hdr *) skb->data; + struct qeth_hdr_layer3 *l3_hdr = &hdr->hdr.l3; + struct net_device *dev = skb->dev; + + if (IS_IQD(card) && iucv->magic == ETH_P_AF_IUCV) { + dev_hard_header(skb, dev, ETH_P_AF_IUCV, dev->dev_addr, + "FAKELL", skb->len); + return; + } + + if (!(l3_hdr->flags & QETH_HDR_PASSTHRU)) { + u16 prot = (l3_hdr->flags & QETH_HDR_IPV6) ? ETH_P_IPV6 : + ETH_P_IP; + unsigned char tg_addr[ETH_ALEN]; + + skb_reset_network_header(skb); + switch (l3_hdr->flags & QETH_HDR_CAST_MASK) { + case QETH_CAST_MULTICAST: + if (prot == ETH_P_IP) + ip_eth_mc_map(ip_hdr(skb)->daddr, tg_addr); + else + ipv6_eth_mc_map(&ipv6_hdr(skb)->daddr, tg_addr); + QETH_CARD_STAT_INC(card, rx_multicast); + break; + case QETH_CAST_BROADCAST: + ether_addr_copy(tg_addr, dev->broadcast); + QETH_CARD_STAT_INC(card, rx_multicast); + break; + default: + if (card->options.sniffer) + skb->pkt_type = PACKET_OTHERHOST; + ether_addr_copy(tg_addr, dev->dev_addr); + } + + if (l3_hdr->ext_flags & QETH_HDR_EXT_SRC_MAC_ADDR) + dev_hard_header(skb, dev, prot, tg_addr, + &l3_hdr->next_hop.rx.src_mac, skb->len); + else + dev_hard_header(skb, dev, prot, tg_addr, "FAKELL", + skb->len); + } + + /* copy VLAN tag from hdr into skb */ + if (!card->options.sniffer && + (l3_hdr->ext_flags & (QETH_HDR_EXT_VLAN_FRAME | + QETH_HDR_EXT_INCLUDE_VLAN_TAG))) { + u16 tag = (l3_hdr->ext_flags & QETH_HDR_EXT_VLAN_FRAME) ? + l3_hdr->vlan_id : + l3_hdr->next_hop.rx.vlan_id; + + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), tag); + } +} +#endif + +static void qeth_receive_skb(struct qeth_card *card, struct sk_buff *skb, + struct qeth_hdr *hdr) +{ + bool is_cso; + + switch (hdr->hdr.l2.id) { + case QETH_HEADER_TYPE_OSN: + skb_push(skb, sizeof(*hdr)); + skb_copy_to_linear_data(skb, hdr, sizeof(*hdr)); + QETH_CARD_STAT_ADD(card, rx_bytes, skb->len); + QETH_CARD_STAT_INC(card, rx_packets); + + card->osn_info.data_cb(skb); + return; +#if IS_ENABLED(CONFIG_QETH_L3) + case QETH_HEADER_TYPE_LAYER3: + qeth_l3_rebuild_skb(card, skb, hdr); + is_cso = hdr->hdr.l3.ext_flags & QETH_HDR_EXT_CSUM_TRANSP_REQ; + break; +#endif + case QETH_HEADER_TYPE_LAYER2: + is_cso = hdr->hdr.l2.flags[1] & QETH_HDR_EXT_CSUM_TRANSP_REQ; + break; + default: + /* never happens */ + dev_kfree_skb_any(skb); + return; + } + + if (is_cso && (card->dev->features & NETIF_F_RXCSUM)) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + QETH_CARD_STAT_INC(card, rx_skb_csum); + } else { + skb->ip_summed = CHECKSUM_NONE; + } + + skb->protocol = eth_type_trans(skb, skb->dev); + + QETH_CARD_STAT_ADD(card, rx_bytes, skb->len); + QETH_CARD_STAT_INC(card, rx_packets); + if (skb_is_nonlinear(skb)) { + QETH_CARD_STAT_INC(card, rx_sg_skbs); + QETH_CARD_STAT_ADD(card, rx_sg_frags, + skb_shinfo(skb)->nr_frags); + } + + napi_gro_receive(&card->napi, skb); +} + static void qeth_create_skb_frag(struct sk_buff *skb, char *data, int data_len) { struct page *page = virt_to_page(data); @@ -5062,10 +5170,10 @@ static inline int qeth_is_last_sbale(struct qdio_buffer_element *sbale) return (sbale->eflags & SBAL_EFLAGS_LAST_ENTRY); } -struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card, - struct qeth_qdio_buffer *qethbuffer, - struct qdio_buffer_element **__element, int *__offset, - struct qeth_hdr **hdr) +static int qeth_extract_skb(struct qeth_card *card, + struct qeth_qdio_buffer *qethbuffer, + struct qdio_buffer_element **__element, + int *__offset) { struct qdio_buffer_element *element = *__element; struct qdio_buffer *buffer = qethbuffer->buffer; @@ -5073,6 +5181,7 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card, int offset = *__offset; bool use_rx_sg = false; unsigned int headroom; + struct qeth_hdr *hdr; struct sk_buff *skb; int skb_len = 0; @@ -5080,42 +5189,42 @@ next_packet: /* qeth_hdr must not cross element boundaries */ while (element->length < offset + sizeof(struct qeth_hdr)) { if (qeth_is_last_sbale(element)) - return NULL; + return -ENODATA; element++; offset = 0; } - *hdr = element->addr + offset; - offset += sizeof(struct qeth_hdr); + hdr = element->addr + offset; + offset += sizeof(*hdr); skb = NULL; - switch ((*hdr)->hdr.l2.id) { + switch (hdr->hdr.l2.id) { case QETH_HEADER_TYPE_LAYER2: - skb_len = (*hdr)->hdr.l2.pkt_length; + skb_len = hdr->hdr.l2.pkt_length; linear_len = ETH_HLEN; headroom = 0; break; case QETH_HEADER_TYPE_LAYER3: - skb_len = (*hdr)->hdr.l3.length; + skb_len = hdr->hdr.l3.length; if (!IS_LAYER3(card)) { QETH_CARD_STAT_INC(card, rx_dropped_notsupp); goto walk_packet; } - if ((*hdr)->hdr.l3.flags & QETH_HDR_PASSTHRU) { + if (hdr->hdr.l3.flags & QETH_HDR_PASSTHRU) { linear_len = ETH_HLEN; headroom = 0; break; } - if ((*hdr)->hdr.l3.flags & QETH_HDR_IPV6) + if (hdr->hdr.l3.flags & QETH_HDR_IPV6) linear_len = sizeof(struct ipv6hdr); else linear_len = sizeof(struct iphdr); headroom = ETH_HLEN; break; case QETH_HEADER_TYPE_OSN: - skb_len = (*hdr)->hdr.osn.pdu_length; + skb_len = hdr->hdr.osn.pdu_length; if (!IS_OSN(card)) { QETH_CARD_STAT_INC(card, rx_dropped_notsupp); goto walk_packet; @@ -5125,13 +5234,13 @@ next_packet: headroom = sizeof(struct qeth_hdr); break; default: - if ((*hdr)->hdr.l2.id & QETH_HEADER_MASK_INVAL) + if (hdr->hdr.l2.id & QETH_HEADER_MASK_INVAL) QETH_CARD_STAT_INC(card, rx_frame_errors); else QETH_CARD_STAT_INC(card, rx_dropped_notsupp); /* Can't determine packet length, drop the whole buffer. */ - return NULL; + return -EPROTONOSUPPORT; } if (skb_len < linear_len) { @@ -5195,7 +5304,7 @@ walk_packet: QETH_CARD_STAT_INC(card, rx_length_errors); } - return NULL; + return -EMSGSIZE; } element++; offset = 0; @@ -5208,22 +5317,40 @@ walk_packet: *__element = element; *__offset = offset; - if (use_rx_sg) { - QETH_CARD_STAT_INC(card, rx_sg_skbs); - QETH_CARD_STAT_ADD(card, rx_sg_frags, - skb_shinfo(skb)->nr_frags); + + qeth_receive_skb(card, skb, hdr); + return 0; +} + +static int qeth_extract_skbs(struct qeth_card *card, int budget, + struct qeth_qdio_buffer *buf, bool *done) +{ + int work_done = 0; + + WARN_ON_ONCE(!budget); + *done = false; + + while (budget) { + if (qeth_extract_skb(card, buf, &card->rx.b_element, + &card->rx.e_offset)) { + *done = true; + break; + } + + work_done++; + budget--; } - return skb; + + return work_done; } -EXPORT_SYMBOL_GPL(qeth_core_get_next_skb); int qeth_poll(struct napi_struct *napi, int budget) { struct qeth_card *card = container_of(napi, struct qeth_card, napi); int work_done = 0; struct qeth_qdio_buffer *buffer; - int done; int new_budget = budget; + bool done; while (1) { if (!card->rx.b_count) { @@ -5246,11 +5373,10 @@ int qeth_poll(struct napi_struct *napi, int budget) if (!(card->rx.qdio_err && qeth_check_qdio_errors(card, buffer->buffer, card->rx.qdio_err, "qinerr"))) - work_done += - card->discipline->process_rx_buffer( - card, new_budget, &done); + work_done += qeth_extract_skbs(card, new_budget, + buffer, &done); else - done = 1; + done = true; if (done) { QETH_CARD_STAT_INC(card, rx_bufs); diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 8c95e6019bac..69d147c4d2ca 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -298,45 +298,6 @@ static void qeth_l2_stop_card(struct qeth_card *card) card->info.promisc_mode = 0; } -static int qeth_l2_process_inbound_buffer(struct qeth_card *card, - int budget, int *done) -{ - int work_done = 0; - struct sk_buff *skb; - struct qeth_hdr *hdr; - unsigned int len; - - *done = 0; - WARN_ON_ONCE(!budget); - while (budget) { - skb = qeth_core_get_next_skb(card, - &card->qdio.in_q->bufs[card->rx.b_index], - &card->rx.b_element, &card->rx.e_offset, &hdr); - if (!skb) { - *done = 1; - break; - } - - if (hdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2) { - skb->protocol = eth_type_trans(skb, skb->dev); - qeth_rx_csum(card, skb, hdr->hdr.l2.flags[1]); - len = skb->len; - napi_gro_receive(&card->napi, skb); - } else { - skb_push(skb, sizeof(*hdr)); - skb_copy_to_linear_data(skb, hdr, sizeof(*hdr)); - len = skb->len; - card->osn_info.data_cb(skb); - } - - work_done++; - budget--; - QETH_CARD_STAT_INC(card, rx_packets); - QETH_CARD_STAT_ADD(card, rx_bytes, len); - } - return work_done; -} - static int qeth_l2_request_initial_mac(struct qeth_card *card) { int rc = 0; @@ -961,7 +922,6 @@ static int qeth_l2_control_event(struct qeth_card *card, struct qeth_discipline qeth_l2_discipline = { .devtype = &qeth_l2_devtype, - .process_rx_buffer = qeth_l2_process_inbound_buffer, .recover = qeth_l2_recover, .setup = qeth_l2_probe_device, .remove = qeth_l2_remove_device, diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 04d7777b7d16..8a1535ee1467 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -1164,96 +1164,6 @@ static int qeth_l3_vlan_rx_kill_vid(struct net_device *dev, return 0; } -static void qeth_l3_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, - struct qeth_hdr *hdr) -{ - struct af_iucv_trans_hdr *iucv = (struct af_iucv_trans_hdr *) skb->data; - struct net_device *dev = skb->dev; - - if (IS_IQD(card) && iucv->magic == ETH_P_AF_IUCV) { - dev_hard_header(skb, dev, ETH_P_AF_IUCV, dev->dev_addr, - "FAKELL", skb->len); - return; - } - - if (!(hdr->hdr.l3.flags & QETH_HDR_PASSTHRU)) { - u16 prot = (hdr->hdr.l3.flags & QETH_HDR_IPV6) ? ETH_P_IPV6 : - ETH_P_IP; - unsigned char tg_addr[ETH_ALEN]; - - skb_reset_network_header(skb); - switch (hdr->hdr.l3.flags & QETH_HDR_CAST_MASK) { - case QETH_CAST_MULTICAST: - if (prot == ETH_P_IP) - ip_eth_mc_map(ip_hdr(skb)->daddr, tg_addr); - else - ipv6_eth_mc_map(&ipv6_hdr(skb)->daddr, tg_addr); - QETH_CARD_STAT_INC(card, rx_multicast); - break; - case QETH_CAST_BROADCAST: - ether_addr_copy(tg_addr, card->dev->broadcast); - QETH_CARD_STAT_INC(card, rx_multicast); - break; - default: - if (card->options.sniffer) - skb->pkt_type = PACKET_OTHERHOST; - ether_addr_copy(tg_addr, card->dev->dev_addr); - } - - if (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_SRC_MAC_ADDR) - card->dev->header_ops->create(skb, card->dev, prot, - tg_addr, &hdr->hdr.l3.next_hop.rx.src_mac, - skb->len); - else - card->dev->header_ops->create(skb, card->dev, prot, - tg_addr, "FAKELL", skb->len); - } - - /* copy VLAN tag from hdr into skb */ - if (!card->options.sniffer && - (hdr->hdr.l3.ext_flags & (QETH_HDR_EXT_VLAN_FRAME | - QETH_HDR_EXT_INCLUDE_VLAN_TAG))) { - u16 tag = (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_VLAN_FRAME) ? - hdr->hdr.l3.vlan_id : - hdr->hdr.l3.next_hop.rx.vlan_id; - __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), tag); - } - - qeth_rx_csum(card, skb, hdr->hdr.l3.ext_flags); -} - -static int qeth_l3_process_inbound_buffer(struct qeth_card *card, - int budget, int *done) -{ - int work_done = 0; - struct sk_buff *skb; - struct qeth_hdr *hdr; - - *done = 0; - WARN_ON_ONCE(!budget); - while (budget) { - skb = qeth_core_get_next_skb(card, - &card->qdio.in_q->bufs[card->rx.b_index], - &card->rx.b_element, &card->rx.e_offset, &hdr); - if (!skb) { - *done = 1; - break; - } - - if (hdr->hdr.l3.id == QETH_HEADER_TYPE_LAYER3) - qeth_l3_rebuild_skb(card, skb, hdr); - - skb->protocol = eth_type_trans(skb, skb->dev); - QETH_CARD_STAT_INC(card, rx_packets); - QETH_CARD_STAT_ADD(card, rx_bytes, skb->len); - - napi_gro_receive(&card->napi, skb); - work_done++; - budget--; - } - return work_done; -} - static void qeth_l3_stop_card(struct qeth_card *card) { QETH_CARD_TEXT(card, 2, "stopcard"); @@ -2317,7 +2227,6 @@ static int qeth_l3_control_event(struct qeth_card *card, struct qeth_discipline qeth_l3_discipline = { .devtype = &qeth_l3_devtype, - .process_rx_buffer = qeth_l3_process_inbound_buffer, .recover = qeth_l3_recover, .setup = qeth_l3_probe_device, .remove = qeth_l3_remove_device, -- cgit v1.2.3-70-g09d2 From dcdcf8670dad7547cff59ef9ddd7312fc706464a Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Mon, 23 Dec 2019 15:22:26 +0100 Subject: s390/qeth: use napi_gro_frags() for SG skbs For non-linear packets, get the skb for attaching the page fragments from napi_get_frags() so that it can be recycled during GRO. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core_main.c | 67 +++++++++++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 17 deletions(-) (limited to 'drivers/s390/net/qeth_core_main.c') diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 8e2c0588525f..b32b50384c5c 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -5106,8 +5106,9 @@ static void qeth_l3_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, #endif static void qeth_receive_skb(struct qeth_card *card, struct sk_buff *skb, - struct qeth_hdr *hdr) + struct qeth_hdr *hdr, bool uses_frags) { + struct napi_struct *napi = &card->napi; bool is_cso; switch (hdr->hdr.l2.id) { @@ -5130,7 +5131,10 @@ static void qeth_receive_skb(struct qeth_card *card, struct sk_buff *skb, break; default: /* never happens */ - dev_kfree_skb_any(skb); + if (uses_frags) + napi_free_frags(napi); + else + dev_kfree_skb_any(skb); return; } @@ -5141,8 +5145,6 @@ static void qeth_receive_skb(struct qeth_card *card, struct sk_buff *skb, skb->ip_summed = CHECKSUM_NONE; } - skb->protocol = eth_type_trans(skb, skb->dev); - QETH_CARD_STAT_ADD(card, rx_bytes, skb->len); QETH_CARD_STAT_INC(card, rx_packets); if (skb_is_nonlinear(skb)) { @@ -5151,7 +5153,12 @@ static void qeth_receive_skb(struct qeth_card *card, struct sk_buff *skb, skb_shinfo(skb)->nr_frags); } - napi_gro_receive(&card->napi, skb); + if (uses_frags) { + napi_gro_frags(napi); + } else { + skb->protocol = eth_type_trans(skb, skb->dev); + napi_gro_receive(napi, skb); + } } static void qeth_create_skb_frag(struct sk_buff *skb, char *data, int data_len) @@ -5177,7 +5184,9 @@ static int qeth_extract_skb(struct qeth_card *card, { struct qdio_buffer_element *element = *__element; struct qdio_buffer *buffer = qethbuffer->buffer; + struct napi_struct *napi = &card->napi; unsigned int linear_len = 0; + bool uses_frags = false; int offset = *__offset; bool use_rx_sg = false; unsigned int headroom; @@ -5253,21 +5262,42 @@ next_packet: !atomic_read(&card->force_alloc_skb) && !IS_OSN(card)); - if (use_rx_sg && qethbuffer->rx_skb) { + if (use_rx_sg) { /* QETH_CQ_ENABLED only: */ - skb = qethbuffer->rx_skb; - qethbuffer->rx_skb = NULL; - } else { - if (!use_rx_sg) - linear_len = skb_len; - skb = napi_alloc_skb(&card->napi, linear_len + headroom); + if (qethbuffer->rx_skb) { + skb = qethbuffer->rx_skb; + qethbuffer->rx_skb = NULL; + goto use_skb; + } + + skb = napi_get_frags(napi); + if (!skb) { + /* -ENOMEM, no point in falling back further. */ + QETH_CARD_STAT_INC(card, rx_dropped_nomem); + goto walk_packet; + } + + if (skb_tailroom(skb) >= linear_len + headroom) { + uses_frags = true; + goto use_skb; + } + + netdev_info_once(card->dev, + "Insufficient linear space in NAPI frags skb, need %u but have %u\n", + linear_len + headroom, skb_tailroom(skb)); + /* Shouldn't happen. Don't optimize, fall back to linear skb. */ } - if (!skb) + linear_len = skb_len; + skb = napi_alloc_skb(napi, linear_len + headroom); + if (!skb) { QETH_CARD_STAT_INC(card, rx_dropped_nomem); - else if (headroom) - skb_reserve(skb, headroom); + goto walk_packet; + } +use_skb: + if (headroom) + skb_reserve(skb, headroom); walk_packet: while (skb_len) { int data_len = min(skb_len, (int)(element->length - offset)); @@ -5300,7 +5330,10 @@ walk_packet: QETH_CARD_TEXT(card, 4, "unexeob"); QETH_CARD_HEX(card, 2, buffer, sizeof(void *)); if (skb) { - dev_kfree_skb_any(skb); + if (uses_frags) + napi_free_frags(napi); + else + dev_kfree_skb_any(skb); QETH_CARD_STAT_INC(card, rx_length_errors); } @@ -5318,7 +5351,7 @@ walk_packet: *__element = element; *__offset = offset; - qeth_receive_skb(card, skb, hdr); + qeth_receive_skb(card, skb, hdr, uses_frags); return 0; } -- cgit v1.2.3-70-g09d2 From 8ca8559ff3cefd78e12b9658f21cc8bcc02407ec Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Mon, 23 Dec 2019 15:22:27 +0100 Subject: s390/qeth: remove QETH_RX_PULL_LEN Since commit f677fcb9aeb6 ("s390/qeth: ensure linear access to packet headers"), the CQ-specific skbs are allocated with a slightly bigger linear part than necessary. Shrink it down to the maximum that's needed by qeth_extract_skb(). Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core.h | 1 - drivers/s390/net/qeth_core_main.c | 6 ++++-- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/s390/net/qeth_core_main.c') diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 4ab3be814ea7..7c37e94fb28b 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -221,7 +221,6 @@ struct qeth_vnicc_info { /* large receive scatter gather copy break */ #define QETH_RX_SG_CB (PAGE_SIZE >> 1) -#define QETH_RX_PULL_LEN 256 struct qeth_hdr_layer3 { __u8 id; diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index b32b50384c5c..3be3d13f8d65 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -2627,7 +2627,8 @@ static int qeth_init_input_buffer(struct qeth_card *card, if ((card->options.cq == QETH_CQ_ENABLED) && (!buf->rx_skb)) { buf->rx_skb = netdev_alloc_skb(card->dev, - QETH_RX_PULL_LEN + ETH_HLEN); + ETH_HLEN + + sizeof(struct ipv6hdr)); if (!buf->rx_skb) return 1; } @@ -5264,7 +5265,8 @@ next_packet: if (use_rx_sg) { /* QETH_CQ_ENABLED only: */ - if (qethbuffer->rx_skb) { + if (qethbuffer->rx_skb && + skb_tailroom(qethbuffer->rx_skb) >= linear_len + headroom) { skb = qethbuffer->rx_skb; qethbuffer->rx_skb = NULL; goto use_skb; -- cgit v1.2.3-70-g09d2 From aa3ad3920301f2cf6d406209b14acde0c50f2323 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Sat, 25 Jan 2020 16:53:00 +0100 Subject: s390/qeth: consolidate QDIO queue setup Move some duplicated logic into a shared code path. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core.h | 1 - drivers/s390/net/qeth_core_main.c | 9 +++++++-- drivers/s390/net/qeth_l2_main.c | 8 +------- drivers/s390/net/qeth_l3_main.c | 8 +------- 4 files changed, 9 insertions(+), 17 deletions(-) (limited to 'drivers/s390/net/qeth_core_main.c') diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 7c37e94fb28b..09d8211fd542 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -994,7 +994,6 @@ int qeth_core_hardsetup_card(struct qeth_card *card, bool *carrier_ok); int qeth_stop_channel(struct qeth_channel *channel); void qeth_print_status_message(struct qeth_card *); -int qeth_init_qdio_queues(struct qeth_card *); int qeth_send_ipa_cmd(struct qeth_card *, struct qeth_cmd_buffer *, int (*reply_cb) (struct qeth_card *, struct qeth_reply *, unsigned long), diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index c19cc3978e1f..52e5f086444b 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -2665,7 +2665,7 @@ static unsigned int qeth_tx_select_bulk_max(struct qeth_card *card, return card->ssqd.mmwc ? card->ssqd.mmwc : 1; } -int qeth_init_qdio_queues(struct qeth_card *card) +static int qeth_init_qdio_queues(struct qeth_card *card) { unsigned int i; int rc; @@ -2713,7 +2713,6 @@ int qeth_init_qdio_queues(struct qeth_card *card) } return 0; } -EXPORT_SYMBOL_GPL(qeth_init_qdio_queues); static void qeth_ipa_finalize_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob) @@ -5026,6 +5025,12 @@ retriable: if (rc) goto out; + rc = qeth_init_qdio_queues(card); + if (rc) { + QETH_CARD_TEXT_(card, 2, "9err%d", rc); + goto out; + } + return 0; out: dev_warn(&card->gdev->dev, "The qeth device driver failed to recover " diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 7da306e267c9..5d9bb0597465 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -288,11 +288,11 @@ static void qeth_l2_stop_card(struct qeth_card *card) } if (card->state == CARD_STATE_HARDSETUP) { qeth_drain_output_queues(card); - qeth_clear_working_pool_list(card); card->state = CARD_STATE_DOWN; } qeth_qdio_clear_card(card, 0); + qeth_clear_working_pool_list(card); flush_workqueue(card->event_wq); card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED; card->info.promisc_mode = 0; @@ -787,12 +787,6 @@ static int qeth_l2_set_online(struct ccwgroup_device *gdev) /* softsetup */ QETH_CARD_TEXT(card, 2, "softsetp"); - rc = qeth_init_qdio_queues(card); - if (rc) { - QETH_CARD_TEXT_(card, 2, "6err%d", rc); - rc = -ENODEV; - goto out_remove; - } card->state = CARD_STATE_SOFTSETUP; qeth_set_allowed_threads(card, 0xffffffff, 0); diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 6c0bffd11138..ee1bdaaa26f6 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -1184,11 +1184,11 @@ static void qeth_l3_stop_card(struct qeth_card *card) } if (card->state == CARD_STATE_HARDSETUP) { qeth_drain_output_queues(card); - qeth_clear_working_pool_list(card); card->state = CARD_STATE_DOWN; } qeth_qdio_clear_card(card, 0); + qeth_clear_working_pool_list(card); flush_workqueue(card->event_wq); card->info.promisc_mode = 0; } @@ -2097,12 +2097,6 @@ static int qeth_l3_set_online(struct ccwgroup_device *gdev) QETH_CARD_TEXT_(card, 2, "5err%04x", rc); } - rc = qeth_init_qdio_queues(card); - if (rc) { - QETH_CARD_TEXT_(card, 2, "6err%d", rc); - rc = -ENODEV; - goto out_remove; - } card->state = CARD_STATE_SOFTSETUP; qeth_set_allowed_threads(card, 0xffffffff, 0); -- cgit v1.2.3-70-g09d2 From 91003f354e6bbe8d225b4d54127d80c694d201d9 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Sat, 25 Jan 2020 16:53:01 +0100 Subject: s390/qeth: consolidate online/offline code Large parts of the online/offline code are identical now, and cleaning up the remaining stuff is easier with a shared core. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core.h | 9 ++-- drivers/s390/net/qeth_core_main.c | 110 +++++++++++++++++++++++++++++++++----- drivers/s390/net/qeth_l2_main.c | 85 ++--------------------------- drivers/s390/net/qeth_l3_main.c | 87 ++---------------------------- 4 files changed, 107 insertions(+), 184 deletions(-) (limited to 'drivers/s390/net/qeth_core_main.c') diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 09d8211fd542..d052a265da1c 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -727,11 +727,10 @@ struct qeth_osn_info { struct qeth_discipline { const struct device_type *devtype; - int (*recover)(void *ptr); int (*setup) (struct ccwgroup_device *); void (*remove) (struct ccwgroup_device *); - int (*set_online) (struct ccwgroup_device *); - int (*set_offline) (struct ccwgroup_device *); + int (*set_online)(struct qeth_card *card); + void (*set_offline)(struct qeth_card *card); int (*do_ioctl)(struct net_device *dev, struct ifreq *rq, int cmd); int (*control_event_handler)(struct qeth_card *card, struct qeth_ipa_cmd *cmd); @@ -987,11 +986,9 @@ struct net_device *qeth_clone_netdev(struct net_device *orig); struct qeth_card *qeth_get_card_by_busid(char *bus_id); void qeth_set_allowed_threads(struct qeth_card *, unsigned long , int); int qeth_threads_running(struct qeth_card *, unsigned long); -int qeth_do_run_thread(struct qeth_card *, unsigned long); -void qeth_clear_thread_start_bit(struct qeth_card *, unsigned long); -void qeth_clear_thread_running_bit(struct qeth_card *, unsigned long); int qeth_core_hardsetup_card(struct qeth_card *card, bool *carrier_ok); int qeth_stop_channel(struct qeth_channel *channel); +int qeth_set_offline(struct qeth_card *card, bool resetting); void qeth_print_status_message(struct qeth_card *); int qeth_send_ipa_cmd(struct qeth_card *, struct qeth_cmd_buffer *, diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 52e5f086444b..d66a7433908c 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -823,7 +823,8 @@ static int qeth_set_thread_start_bit(struct qeth_card *card, return 0; } -void qeth_clear_thread_start_bit(struct qeth_card *card, unsigned long thread) +static void qeth_clear_thread_start_bit(struct qeth_card *card, + unsigned long thread) { unsigned long flags; @@ -832,9 +833,9 @@ void qeth_clear_thread_start_bit(struct qeth_card *card, unsigned long thread) spin_unlock_irqrestore(&card->thread_mask_lock, flags); wake_up(&card->wait_q); } -EXPORT_SYMBOL_GPL(qeth_clear_thread_start_bit); -void qeth_clear_thread_running_bit(struct qeth_card *card, unsigned long thread) +static void qeth_clear_thread_running_bit(struct qeth_card *card, + unsigned long thread) { unsigned long flags; @@ -843,7 +844,6 @@ void qeth_clear_thread_running_bit(struct qeth_card *card, unsigned long thread) spin_unlock_irqrestore(&card->thread_mask_lock, flags); wake_up_all(&card->wait_q); } -EXPORT_SYMBOL_GPL(qeth_clear_thread_running_bit); static int __qeth_do_run_thread(struct qeth_card *card, unsigned long thread) { @@ -864,7 +864,7 @@ static int __qeth_do_run_thread(struct qeth_card *card, unsigned long thread) return rc; } -int qeth_do_run_thread(struct qeth_card *card, unsigned long thread) +static int qeth_do_run_thread(struct qeth_card *card, unsigned long thread) { int rc = 0; @@ -872,7 +872,6 @@ int qeth_do_run_thread(struct qeth_card *card, unsigned long thread) (rc = __qeth_do_run_thread(card, thread)) >= 0); return rc; } -EXPORT_SYMBOL_GPL(qeth_do_run_thread); void qeth_schedule_recovery(struct qeth_card *card) { @@ -880,7 +879,6 @@ void qeth_schedule_recovery(struct qeth_card *card) if (qeth_set_thread_start_bit(card, QETH_RECOVER_THREAD) == 0) schedule_work(&card->kernel_thread_starter); } -EXPORT_SYMBOL_GPL(qeth_schedule_recovery); static int qeth_get_problem(struct qeth_card *card, struct ccw_device *cdev, struct irb *irb) @@ -1287,6 +1285,7 @@ static int qeth_do_start_thread(struct qeth_card *card, unsigned long thread) return rc; } +static int qeth_do_reset(void *data); static void qeth_start_kernel_thread(struct work_struct *work) { struct task_struct *ts; @@ -1298,8 +1297,7 @@ static void qeth_start_kernel_thread(struct work_struct *work) card->write.state != CH_STATE_UP) return; if (qeth_do_start_thread(card, QETH_RECOVER_THREAD)) { - ts = kthread_run(card->discipline->recover, (void *)card, - "qeth_recover"); + ts = kthread_run(qeth_do_reset, card, "qeth_recover"); if (IS_ERR(ts)) { qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD); qeth_clear_thread_running_bit(card, @@ -3095,7 +3093,6 @@ int qeth_hw_trap(struct qeth_card *card, enum qeth_diags_trap_action action) } return qeth_send_ipa_cmd(card, iob, qeth_hw_trap_cb, NULL); } -EXPORT_SYMBOL_GPL(qeth_hw_trap); static int qeth_check_qdio_errors(struct qeth_card *card, struct qdio_buffer *buf, @@ -5041,6 +5038,89 @@ out: } EXPORT_SYMBOL_GPL(qeth_core_hardsetup_card); +static int qeth_set_online(struct qeth_card *card) +{ + int rc; + + mutex_lock(&card->discipline_mutex); + mutex_lock(&card->conf_mutex); + QETH_CARD_TEXT(card, 2, "setonlin"); + + rc = card->discipline->set_online(card); + + mutex_unlock(&card->conf_mutex); + mutex_unlock(&card->discipline_mutex); + + return rc; +} + +int qeth_set_offline(struct qeth_card *card, bool resetting) +{ + int rc, rc2, rc3; + + mutex_lock(&card->discipline_mutex); + mutex_lock(&card->conf_mutex); + QETH_CARD_TEXT(card, 3, "setoffl"); + + if ((!resetting && card->info.hwtrap) || card->info.hwtrap == 2) { + qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); + card->info.hwtrap = 1; + } + + rtnl_lock(); + card->info.open_when_online = card->dev->flags & IFF_UP; + dev_close(card->dev); + netif_device_detach(card->dev); + netif_carrier_off(card->dev); + rtnl_unlock(); + + card->discipline->set_offline(card); + + rc = qeth_stop_channel(&card->data); + rc2 = qeth_stop_channel(&card->write); + rc3 = qeth_stop_channel(&card->read); + if (!rc) + rc = (rc2) ? rc2 : rc3; + if (rc) + QETH_CARD_TEXT_(card, 2, "1err%d", rc); + qdio_free(CARD_DDEV(card)); + + /* let user_space know that device is offline */ + kobject_uevent(&card->gdev->dev.kobj, KOBJ_CHANGE); + + mutex_unlock(&card->conf_mutex); + mutex_unlock(&card->discipline_mutex); + return 0; +} +EXPORT_SYMBOL_GPL(qeth_set_offline); + +static int qeth_do_reset(void *data) +{ + struct qeth_card *card = data; + int rc; + + QETH_CARD_TEXT(card, 2, "recover1"); + if (!qeth_do_run_thread(card, QETH_RECOVER_THREAD)) + return 0; + QETH_CARD_TEXT(card, 2, "recover2"); + dev_warn(&card->gdev->dev, + "A recovery process has been started for the device\n"); + + qeth_set_offline(card, true); + rc = qeth_set_online(card); + if (!rc) { + dev_info(&card->gdev->dev, + "Device successfully recovered!\n"); + } else { + ccwgroup_set_offline(card->gdev); + dev_warn(&card->gdev->dev, + "The qeth device driver failed to recover an error on the device\n"); + } + qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD); + qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD); + return 0; +} + #if IS_ENABLED(CONFIG_QETH_L3) static void qeth_l3_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, struct qeth_hdr *hdr) @@ -5977,7 +6057,8 @@ static int qeth_core_set_online(struct ccwgroup_device *gdev) goto err; } } - rc = card->discipline->set_online(gdev); + + rc = qeth_set_online(card); err: return rc; } @@ -5985,7 +6066,8 @@ err: static int qeth_core_set_offline(struct ccwgroup_device *gdev) { struct qeth_card *card = dev_get_drvdata(&gdev->dev); - return card->discipline->set_offline(gdev); + + return qeth_set_offline(card, false); } static void qeth_core_shutdown(struct ccwgroup_device *gdev) @@ -6008,7 +6090,7 @@ static int qeth_suspend(struct ccwgroup_device *gdev) if (gdev->state == CCWGROUP_OFFLINE) return 0; - card->discipline->set_offline(gdev); + qeth_set_offline(card, false); return 0; } @@ -6017,7 +6099,7 @@ static int qeth_resume(struct ccwgroup_device *gdev) struct qeth_card *card = dev_get_drvdata(&gdev->dev); int rc; - rc = card->discipline->set_online(gdev); + rc = qeth_set_online(card); qeth_set_allowed_threads(card, 0xffffffff, 0); if (rc) diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 5d9bb0597465..c36b6c1fc33f 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -24,7 +24,6 @@ #include "qeth_core.h" #include "qeth_l2.h" -static int qeth_l2_set_offline(struct ccwgroup_device *); static void qeth_bridgeport_query_support(struct qeth_card *card); static void qeth_bridge_state_change(struct qeth_card *card, struct qeth_ipa_cmd *cmd); @@ -610,7 +609,7 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev) wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0); if (cgdev->state == CCWGROUP_ONLINE) - qeth_l2_set_offline(cgdev); + qeth_set_offline(card, false); cancel_work_sync(&card->close_dev_work); if (qeth_netdev_is_registered(card->dev)) @@ -746,17 +745,13 @@ static void qeth_l2_setup_bridgeport_attrs(struct qeth_card *card) } } -static int qeth_l2_set_online(struct ccwgroup_device *gdev) +static int qeth_l2_set_online(struct qeth_card *card) { - struct qeth_card *card = dev_get_drvdata(&gdev->dev); + struct ccwgroup_device *gdev = card->gdev; struct net_device *dev = card->dev; int rc = 0; bool carrier_ok; - mutex_lock(&card->discipline_mutex); - mutex_lock(&card->conf_mutex); - QETH_CARD_TEXT(card, 2, "setonlin"); - rc = qeth_core_hardsetup_card(card, &carrier_ok); if (rc) { QETH_CARD_TEXT_(card, 2, "2err%04x", rc); @@ -813,8 +808,6 @@ static int qeth_l2_set_online(struct ccwgroup_device *gdev) } /* let user_space know that device is online */ kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE); - mutex_unlock(&card->conf_mutex); - mutex_unlock(&card->discipline_mutex); return 0; out_remove: @@ -823,81 +816,12 @@ out_remove: qeth_stop_channel(&card->write); qeth_stop_channel(&card->read); qdio_free(CARD_DDEV(card)); - - mutex_unlock(&card->conf_mutex); - mutex_unlock(&card->discipline_mutex); return rc; } -static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev, - int recovery_mode) +static void qeth_l2_set_offline(struct qeth_card *card) { - struct qeth_card *card = dev_get_drvdata(&cgdev->dev); - int rc = 0, rc2 = 0, rc3 = 0; - - mutex_lock(&card->discipline_mutex); - mutex_lock(&card->conf_mutex); - QETH_CARD_TEXT(card, 3, "setoffl"); - - if ((!recovery_mode && card->info.hwtrap) || card->info.hwtrap == 2) { - qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); - card->info.hwtrap = 1; - } - - rtnl_lock(); - card->info.open_when_online = card->dev->flags & IFF_UP; - dev_close(card->dev); - netif_device_detach(card->dev); - netif_carrier_off(card->dev); - rtnl_unlock(); - qeth_l2_stop_card(card); - rc = qeth_stop_channel(&card->data); - rc2 = qeth_stop_channel(&card->write); - rc3 = qeth_stop_channel(&card->read); - if (!rc) - rc = (rc2) ? rc2 : rc3; - if (rc) - QETH_CARD_TEXT_(card, 2, "1err%d", rc); - qdio_free(CARD_DDEV(card)); - - /* let user_space know that device is offline */ - kobject_uevent(&cgdev->dev.kobj, KOBJ_CHANGE); - mutex_unlock(&card->conf_mutex); - mutex_unlock(&card->discipline_mutex); - return 0; -} - -static int qeth_l2_set_offline(struct ccwgroup_device *cgdev) -{ - return __qeth_l2_set_offline(cgdev, 0); -} - -static int qeth_l2_recover(void *ptr) -{ - struct qeth_card *card; - int rc = 0; - - card = (struct qeth_card *) ptr; - QETH_CARD_TEXT(card, 2, "recover1"); - if (!qeth_do_run_thread(card, QETH_RECOVER_THREAD)) - return 0; - QETH_CARD_TEXT(card, 2, "recover2"); - dev_warn(&card->gdev->dev, - "A recovery process has been started for the device\n"); - __qeth_l2_set_offline(card->gdev, 1); - rc = qeth_l2_set_online(card->gdev); - if (!rc) - dev_info(&card->gdev->dev, - "Device successfully recovered!\n"); - else { - ccwgroup_set_offline(card->gdev); - dev_warn(&card->gdev->dev, "The qeth device driver " - "failed to recover an error on the device\n"); - } - qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD); - qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD); - return 0; } static int __init qeth_l2_init(void) @@ -934,7 +858,6 @@ static int qeth_l2_control_event(struct qeth_card *card, struct qeth_discipline qeth_l2_discipline = { .devtype = &qeth_l2_devtype, - .recover = qeth_l2_recover, .setup = qeth_l2_probe_device, .remove = qeth_l2_remove_device, .set_online = qeth_l2_set_online, diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index ee1bdaaa26f6..eb2d9c427b10 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -37,8 +37,6 @@ #include "qeth_l3.h" - -static int qeth_l3_set_offline(struct ccwgroup_device *); static int qeth_l3_register_addr_entry(struct qeth_card *, struct qeth_ipaddr *); static int qeth_l3_deregister_addr_entry(struct qeth_card *, @@ -2044,7 +2042,7 @@ static void qeth_l3_remove_device(struct ccwgroup_device *cgdev) wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0); if (cgdev->state == CCWGROUP_ONLINE) - qeth_l3_set_offline(cgdev); + qeth_set_offline(card, false); cancel_work_sync(&card->close_dev_work); if (qeth_netdev_is_registered(card->dev)) @@ -2056,17 +2054,13 @@ static void qeth_l3_remove_device(struct ccwgroup_device *cgdev) qeth_l3_clear_ipato_list(card); } -static int qeth_l3_set_online(struct ccwgroup_device *gdev) +static int qeth_l3_set_online(struct qeth_card *card) { - struct qeth_card *card = dev_get_drvdata(&gdev->dev); + struct ccwgroup_device *gdev = card->gdev; struct net_device *dev = card->dev; int rc = 0; bool carrier_ok; - mutex_lock(&card->discipline_mutex); - mutex_lock(&card->conf_mutex); - QETH_CARD_TEXT(card, 2, "setonlin"); - rc = qeth_core_hardsetup_card(card, &carrier_ok); if (rc) { QETH_CARD_TEXT_(card, 2, "2err%04x", rc); @@ -2125,8 +2119,6 @@ static int qeth_l3_set_online(struct ccwgroup_device *gdev) qeth_trace_features(card); /* let user_space know that device is online */ kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE); - mutex_unlock(&card->conf_mutex); - mutex_unlock(&card->discipline_mutex); return 0; out_remove: qeth_l3_stop_card(card); @@ -2134,82 +2126,12 @@ out_remove: qeth_stop_channel(&card->write); qeth_stop_channel(&card->read); qdio_free(CARD_DDEV(card)); - - mutex_unlock(&card->conf_mutex); - mutex_unlock(&card->discipline_mutex); return rc; } -static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev, - int recovery_mode) +static void qeth_l3_set_offline(struct qeth_card *card) { - struct qeth_card *card = dev_get_drvdata(&cgdev->dev); - int rc = 0, rc2 = 0, rc3 = 0; - - mutex_lock(&card->discipline_mutex); - mutex_lock(&card->conf_mutex); - QETH_CARD_TEXT(card, 3, "setoffl"); - - if ((!recovery_mode && card->info.hwtrap) || card->info.hwtrap == 2) { - qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); - card->info.hwtrap = 1; - } - - rtnl_lock(); - card->info.open_when_online = card->dev->flags & IFF_UP; - dev_close(card->dev); - netif_device_detach(card->dev); - netif_carrier_off(card->dev); - rtnl_unlock(); - qeth_l3_stop_card(card); - rc = qeth_stop_channel(&card->data); - rc2 = qeth_stop_channel(&card->write); - rc3 = qeth_stop_channel(&card->read); - if (!rc) - rc = (rc2) ? rc2 : rc3; - if (rc) - QETH_CARD_TEXT_(card, 2, "1err%d", rc); - qdio_free(CARD_DDEV(card)); - - /* let user_space know that device is offline */ - kobject_uevent(&cgdev->dev.kobj, KOBJ_CHANGE); - mutex_unlock(&card->conf_mutex); - mutex_unlock(&card->discipline_mutex); - return 0; -} - -static int qeth_l3_set_offline(struct ccwgroup_device *cgdev) -{ - return __qeth_l3_set_offline(cgdev, 0); -} - -static int qeth_l3_recover(void *ptr) -{ - struct qeth_card *card; - int rc = 0; - - card = (struct qeth_card *) ptr; - QETH_CARD_TEXT(card, 2, "recover1"); - QETH_CARD_HEX(card, 2, &card, sizeof(void *)); - if (!qeth_do_run_thread(card, QETH_RECOVER_THREAD)) - return 0; - QETH_CARD_TEXT(card, 2, "recover2"); - dev_warn(&card->gdev->dev, - "A recovery process has been started for the device\n"); - __qeth_l3_set_offline(card->gdev, 1); - rc = qeth_l3_set_online(card->gdev); - if (!rc) - dev_info(&card->gdev->dev, - "Device successfully recovered!\n"); - else { - ccwgroup_set_offline(card->gdev); - dev_warn(&card->gdev->dev, "The qeth device driver " - "failed to recover an error on the device\n"); - } - qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD); - qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD); - return 0; } /* Returns zero if the command is successfully "consumed" */ @@ -2221,7 +2143,6 @@ static int qeth_l3_control_event(struct qeth_card *card, struct qeth_discipline qeth_l3_discipline = { .devtype = &qeth_l3_devtype, - .recover = qeth_l3_recover, .setup = qeth_l3_probe_device, .remove = qeth_l3_remove_device, .set_online = qeth_l3_set_online, -- cgit v1.2.3-70-g09d2 From 7f92316c5393b583c5217bb2cfc789d6820ec393 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Sat, 25 Jan 2020 16:53:02 +0100 Subject: s390/qeth: make cmd/reply matching more flexible When data is received on the READ channel, the matching logic for cmds that are waiting for a reply is currently hard-coded into the channel's main IO callback. Move this into a per-cmd callback, so that we can apply custom matching logic for each individual cmd. This also allows us to remove the coarse-grained check for unexpected non-IPA replies, since they will no longer match against _all_ pending cmds. Note that IDX cmds use _no_ matcher, since their reply is synchronously received as part of the cmd's IO. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core.h | 14 +++++++++++++- drivers/s390/net/qeth_core_main.c | 34 ++++++++++++++++++++++++---------- drivers/s390/net/qeth_l2_main.c | 3 ++- 3 files changed, 39 insertions(+), 12 deletions(-) (limited to 'drivers/s390/net/qeth_core_main.c') diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index d052a265da1c..950d01551373 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -608,6 +608,8 @@ struct qeth_cmd_buffer { long timeout; unsigned char *data; void (*finalize)(struct qeth_card *card, struct qeth_cmd_buffer *iob); + bool (*match)(struct qeth_cmd_buffer *iob, + struct qeth_cmd_buffer *reply); void (*callback)(struct qeth_card *card, struct qeth_cmd_buffer *iob, unsigned int data_length); int rc; @@ -618,6 +620,14 @@ static inline void qeth_get_cmd(struct qeth_cmd_buffer *iob) refcount_inc(&iob->ref_count); } +static inline struct qeth_ipa_cmd *__ipa_reply(struct qeth_cmd_buffer *iob) +{ + if (!IS_IPA(iob->data)) + return NULL; + + return (struct qeth_ipa_cmd *) PDU_ENCAPSULATION(iob->data); +} + static inline struct qeth_ipa_cmd *__ipa_cmd(struct qeth_cmd_buffer *iob) { return (struct qeth_ipa_cmd *)(iob->data + IPA_PDU_HEADER_SIZE); @@ -1023,7 +1033,9 @@ void qeth_setadp_promisc_mode(struct qeth_card *card, bool enable); int qeth_setadpparms_change_macaddr(struct qeth_card *); void qeth_tx_timeout(struct net_device *, unsigned int txqueue); void qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob, - u16 cmd_length); + u16 cmd_length, + bool (*match)(struct qeth_cmd_buffer *iob, + struct qeth_cmd_buffer *reply)); int qeth_query_switch_attributes(struct qeth_card *card, struct qeth_switch_info *sw_info); int qeth_query_card_info(struct qeth_card *card, diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index d66a7433908c..0f5f36e63823 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -748,8 +748,8 @@ static void qeth_issue_next_read_cb(struct qeth_card *card, goto out; } - if (IS_IPA(iob->data)) { - cmd = (struct qeth_ipa_cmd *) PDU_ENCAPSULATION(iob->data); + cmd = __ipa_reply(iob); + if (cmd) { cmd = qeth_check_ipa_data(card, cmd); if (!cmd) goto out; @@ -758,17 +758,12 @@ static void qeth_issue_next_read_cb(struct qeth_card *card, card->osn_info.assist_cb(card->dev, cmd); goto out; } - } else { - /* non-IPA commands should only flow during initialization */ - if (card->state != CARD_STATE_DOWN) - goto out; } /* match against pending cmd requests */ spin_lock_irqsave(&card->lock, flags); list_for_each_entry(tmp, &card->cmd_waiter_list, list) { - if (!IS_IPA(tmp->data) || - __ipa_cmd(tmp)->hdr.seqno == cmd->hdr.seqno) { + if (tmp->match && tmp->match(tmp, iob)) { request = tmp; /* take the object outside the lock */ qeth_get_cmd(request); @@ -1688,6 +1683,13 @@ static void qeth_mpc_finalize_cmd(struct qeth_card *card, iob->callback = qeth_release_buffer_cb; } +static bool qeth_mpc_match_reply(struct qeth_cmd_buffer *iob, + struct qeth_cmd_buffer *reply) +{ + /* MPC cmds are issued strictly in sequence. */ + return !IS_IPA(reply->data); +} + static struct qeth_cmd_buffer *qeth_mpc_alloc_cmd(struct qeth_card *card, void *data, unsigned int data_length) @@ -1702,6 +1704,7 @@ static struct qeth_cmd_buffer *qeth_mpc_alloc_cmd(struct qeth_card *card, qeth_setup_ccw(__ccw_from_cmd(iob), CCW_CMD_WRITE, 0, data_length, iob->data); iob->finalize = qeth_mpc_finalize_cmd; + iob->match = qeth_mpc_match_reply; return iob; } @@ -2722,7 +2725,9 @@ static void qeth_ipa_finalize_cmd(struct qeth_card *card, } void qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob, - u16 cmd_length) + u16 cmd_length, + bool (*match)(struct qeth_cmd_buffer *iob, + struct qeth_cmd_buffer *reply)) { u8 prot_type = qeth_mpc_select_prot_type(card); u16 total_length = iob->length; @@ -2730,6 +2735,7 @@ void qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob, qeth_setup_ccw(__ccw_from_cmd(iob), CCW_CMD_WRITE, 0, total_length, iob->data); iob->finalize = qeth_ipa_finalize_cmd; + iob->match = match; memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE); memcpy(QETH_IPA_PDU_LEN_TOTAL(iob->data), &total_length, 2); @@ -2742,6 +2748,14 @@ void qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob, } EXPORT_SYMBOL_GPL(qeth_prepare_ipa_cmd); +static bool qeth_ipa_match_reply(struct qeth_cmd_buffer *iob, + struct qeth_cmd_buffer *reply) +{ + struct qeth_ipa_cmd *ipa_reply = __ipa_reply(reply); + + return ipa_reply && (__ipa_cmd(iob)->hdr.seqno == ipa_reply->hdr.seqno); +} + struct qeth_cmd_buffer *qeth_ipa_alloc_cmd(struct qeth_card *card, enum qeth_ipa_cmds cmd_code, enum qeth_prot_versions prot, @@ -2757,7 +2771,7 @@ struct qeth_cmd_buffer *qeth_ipa_alloc_cmd(struct qeth_card *card, if (!iob) return NULL; - qeth_prepare_ipa_cmd(card, iob, data_length); + qeth_prepare_ipa_cmd(card, iob, data_length, qeth_ipa_match_reply); hdr = &__ipa_cmd(iob)->hdr; hdr->command = cmd_code; diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index c36b6c1fc33f..d5ffd40937d3 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -896,7 +896,8 @@ int qeth_osn_assist(struct net_device *dev, void *data, int data_len) if (!iob) return -ENOMEM; - qeth_prepare_ipa_cmd(card, iob, (u16) data_len); + qeth_prepare_ipa_cmd(card, iob, (u16) data_len, NULL); + memcpy(__ipa_cmd(iob), data, data_len); iob->callback = qeth_osn_assist_cb; return qeth_send_ipa_cmd(card, iob, NULL, NULL); -- cgit v1.2.3-70-g09d2 From 17d9723e69d44491d04289213006fea1647bd0a6 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Sat, 25 Jan 2020 16:53:03 +0100 Subject: s390/qeth: remove HARDSETUP state qeth_l?_stop_card() is _never_ called while in HARDSETUP state, and there's no other usage of the card state that relies on the DOWN -> HARDSETUP -> SOFTSETUP transition. As related cleanup, remove the check in qeth_realloc_buffer_pool() as it is already done by the callers. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core.h | 1 - drivers/s390/net/qeth_core_main.c | 3 --- drivers/s390/net/qeth_core_sys.c | 2 -- drivers/s390/net/qeth_l2_main.c | 4 ---- drivers/s390/net/qeth_l3_main.c | 14 +++----------- 5 files changed, 3 insertions(+), 21 deletions(-) (limited to 'drivers/s390/net/qeth_core_main.c') diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 950d01551373..9575a627a1e1 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -558,7 +558,6 @@ enum qeth_channel_states { */ enum qeth_card_states { CARD_STATE_DOWN, - CARD_STATE_HARDSETUP, CARD_STATE_SOFTSETUP, }; diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 0f5f36e63823..9639938581f5 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -247,9 +247,6 @@ int qeth_realloc_buffer_pool(struct qeth_card *card, int bufcnt) { QETH_CARD_TEXT(card, 2, "realcbp"); - if (card->state != CARD_STATE_DOWN) - return -EPERM; - /* TODO: steel/add buffers from/to a running card's buffer pool (?) */ qeth_clear_working_pool_list(card); qeth_free_buffer_pool(card); diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c index 7bd86027f559..2bd9993aa60b 100644 --- a/drivers/s390/net/qeth_core_sys.c +++ b/drivers/s390/net/qeth_core_sys.c @@ -24,8 +24,6 @@ static ssize_t qeth_dev_state_show(struct device *dev, switch (card->state) { case CARD_STATE_DOWN: return sprintf(buf, "DOWN\n"); - case CARD_STATE_HARDSETUP: - return sprintf(buf, "HARDSETUP\n"); case CARD_STATE_SOFTSETUP: if (card->dev->flags & IFF_UP) return sprintf(buf, "UP (LAN %s)\n", diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index d5ffd40937d3..692bd2623401 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -283,9 +283,6 @@ static void qeth_l2_stop_card(struct qeth_card *card) if (card->state == CARD_STATE_SOFTSETUP) { qeth_clear_ipacmd_list(card); - card->state = CARD_STATE_HARDSETUP; - } - if (card->state == CARD_STATE_HARDSETUP) { qeth_drain_output_queues(card); card->state = CARD_STATE_DOWN; } @@ -776,7 +773,6 @@ static int qeth_l2_set_online(struct qeth_card *card) qeth_trace_features(card); qeth_l2_trace_features(card); - card->state = CARD_STATE_HARDSETUP; qeth_print_status_message(card); /* softsetup */ diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index eb2d9c427b10..317d56647a4a 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -901,7 +901,7 @@ out: return rc; } -static int qeth_l3_start_ipassists(struct qeth_card *card) +static void qeth_l3_start_ipassists(struct qeth_card *card) { QETH_CARD_TEXT(card, 3, "strtipas"); @@ -911,7 +911,6 @@ static int qeth_l3_start_ipassists(struct qeth_card *card) qeth_l3_start_ipa_multicast(card); /* go on*/ qeth_l3_start_ipa_ipv6(card); /* go on*/ qeth_l3_start_ipa_broadcast(card); /* go on*/ - return 0; } static int qeth_l3_iqd_read_initial_mac_cb(struct qeth_card *card, @@ -1178,9 +1177,6 @@ static void qeth_l3_stop_card(struct qeth_card *card) if (card->state == CARD_STATE_SOFTSETUP) { qeth_l3_clear_ip_htable(card, 1); qeth_clear_ipacmd_list(card); - card->state = CARD_STATE_HARDSETUP; - } - if (card->state == CARD_STATE_HARDSETUP) { qeth_drain_output_queues(card); card->state = CARD_STATE_DOWN; } @@ -2068,7 +2064,6 @@ static int qeth_l3_set_online(struct qeth_card *card) goto out_remove; } - card->state = CARD_STATE_HARDSETUP; qeth_print_status_message(card); /* softsetup */ @@ -2078,11 +2073,8 @@ static int qeth_l3_set_online(struct qeth_card *card) if (rc) QETH_CARD_TEXT_(card, 2, "2err%04x", rc); if (!card->options.sniffer) { - rc = qeth_l3_start_ipassists(card); - if (rc) { - QETH_CARD_TEXT_(card, 2, "3err%d", rc); - goto out_remove; - } + qeth_l3_start_ipassists(card); + rc = qeth_l3_setrouting_v4(card); if (rc) QETH_CARD_TEXT_(card, 2, "4err%04x", rc); -- cgit v1.2.3-70-g09d2