diff options
Diffstat (limited to 'drivers')
39 files changed, 385 insertions, 462 deletions
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig index 620766eb6bc1..2e31db55d927 100644 --- a/drivers/net/can/Kconfig +++ b/drivers/net/can/Kconfig @@ -169,6 +169,7 @@ config CAN_KVASER_PCIEFD Kvaser Mini PCI Express 1xCAN v3 Kvaser Mini PCI Express 2xCAN v3 Kvaser M.2 PCIe 4xCAN + Kvaser PCIe 8xCAN config CAN_SLCAN tristate "Serial / USB serial CAN Adaptors (slcan)" diff --git a/drivers/net/can/kvaser_pciefd.c b/drivers/net/can/kvaser_pciefd.c index 416f10480b40..f81b598147b3 100644 --- a/drivers/net/can/kvaser_pciefd.c +++ b/drivers/net/can/kvaser_pciefd.c @@ -27,7 +27,7 @@ MODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices"); #define KVASER_PCIEFD_BEC_POLL_FREQ (jiffies + msecs_to_jiffies(200)) #define KVASER_PCIEFD_MAX_ERR_REP 256U #define KVASER_PCIEFD_CAN_TX_MAX_COUNT 17U -#define KVASER_PCIEFD_MAX_CAN_CHANNELS 4UL +#define KVASER_PCIEFD_MAX_CAN_CHANNELS 8UL #define KVASER_PCIEFD_DMA_COUNT 2U #define KVASER_PCIEFD_DMA_SIZE (4U * 1024U) @@ -49,6 +49,7 @@ MODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices"); /* Xilinx based devices */ #define KVASER_PCIEFD_M2_4CAN_DEVICE_ID 0x0017 +#define KVASER_PCIEFD_8CAN_DEVICE_ID 0x0019 /* Altera SerDes Enable 64-bit DMA address translation */ #define KVASER_PCIEFD_ALTERA_DMA_64BIT BIT(0) @@ -497,6 +498,10 @@ static struct pci_device_id kvaser_pciefd_id_table[] = { .driver_data = (kernel_ulong_t)&kvaser_pciefd_xilinx_driver_data, }, { + PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_8CAN_DEVICE_ID), + .driver_data = (kernel_ulong_t)&kvaser_pciefd_xilinx_driver_data, + }, + { 0, }, }; diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c index eebf967f4711..1d9057dc44f2 100644 --- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c +++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c @@ -837,7 +837,7 @@ static int __mcp251xfd_get_berr_counter(const struct net_device *ndev, return err; if (trec & MCP251XFD_REG_TREC_TXBO) - bec->txerr = 256; + bec->txerr = CAN_BUS_OFF_THRESHOLD; else bec->txerr = FIELD_GET(MCP251XFD_REG_TREC_TEC_MASK, trec); bec->rxerr = FIELD_GET(MCP251XFD_REG_TREC_REC_MASK, trec); diff --git a/drivers/net/can/usb/Kconfig b/drivers/net/can/usb/Kconfig index d1450722cb3c..bd58c636d465 100644 --- a/drivers/net/can/usb/Kconfig +++ b/drivers/net/can/usb/Kconfig @@ -100,6 +100,7 @@ config CAN_KVASER_USB - Scania VCI2 (if you have the Kvaser logo on top) - Kvaser BlackBird v2 - Kvaser Leaf Pro HS v2 + - Kvaser Leaf v3 - Kvaser Hybrid CAN/LIN - Kvaser Hybrid 2xCAN/LIN - Kvaser Hybrid Pro CAN/LIN diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index 95b0fdb602c8..65c962f76898 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -385,7 +385,7 @@ static struct gs_tx_context *gs_get_tx_context(struct gs_can *dev, static int gs_cmd_reset(struct gs_can *dev) { struct gs_device_mode dm = { - .mode = GS_CAN_MODE_RESET, + .mode = cpu_to_le32(GS_CAN_MODE_RESET), }; return usb_control_msg_send(dev->udev, 0, GS_USB_BREQ_MODE, diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c index 71ef4db5c09f..8faf8a462c05 100644 --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c @@ -88,6 +88,7 @@ #define USB_USBCAN_PRO_4HS_PRODUCT_ID 0x0114 #define USB_HYBRID_CANLIN_PRODUCT_ID 0x0115 #define USB_HYBRID_PRO_CANLIN_PRODUCT_ID 0x0116 +#define USB_LEAF_V3_PRODUCT_ID 0x0117 static const struct kvaser_usb_driver_info kvaser_usb_driver_info_hydra = { .quirks = KVASER_USB_QUIRK_HAS_HARDWARE_TIMESTAMP, @@ -235,6 +236,8 @@ static const struct usb_device_id kvaser_usb_table[] = { .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra }, { USB_DEVICE(KVASER_VENDOR_ID, USB_HYBRID_PRO_CANLIN_PRODUCT_ID), .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra }, + { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_V3_PRODUCT_ID), + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra }, { } }; MODULE_DEVICE_TABLE(usb, kvaser_usb_table); diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c index 03d966fa67b2..1ae11b180d54 100644 --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c @@ -966,18 +966,10 @@ mt753x_trap_frames(struct mt7530_priv *priv) MT753X_R0E_PORT_FW(MT753X_BPDU_CPU_ONLY)); } -static int +static void mt753x_cpu_port_enable(struct dsa_switch *ds, int port) { struct mt7530_priv *priv = ds->priv; - int ret; - - /* Setup max capability of CPU port at first */ - if (priv->info->cpu_port_config) { - ret = priv->info->cpu_port_config(ds, port); - if (ret) - return ret; - } /* Enable Mediatek header mode on the cpu port */ mt7530_write(priv, MT7530_PVC_P(port), @@ -1003,8 +995,6 @@ mt753x_cpu_port_enable(struct dsa_switch *ds, int port) /* Set to fallback mode for independent VLAN learning */ mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK, MT7530_PORT_FALLBACK_MODE); - - return 0; } static int @@ -1028,7 +1018,6 @@ mt7530_port_enable(struct dsa_switch *ds, int port, priv->ports[port].enable = true; mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK, priv->ports[port].pm); - mt7530_clear(priv, MT7530_PMCR_P(port), PMCR_LINK_SETTINGS_MASK); mutex_unlock(&priv->reg_mutex); @@ -1048,7 +1037,6 @@ mt7530_port_disable(struct dsa_switch *ds, int port) priv->ports[port].enable = false; mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK, PCR_MATRIX_CLR); - mt7530_clear(priv, MT7530_PMCR_P(port), PMCR_LINK_SETTINGS_MASK); mutex_unlock(&priv->reg_mutex); } @@ -2055,7 +2043,7 @@ mt7530_setup_irq(struct mt7530_priv *priv) } /* This register must be set for MT7530 to properly fire interrupts */ - if (priv->id != ID_MT7531) + if (priv->id == ID_MT7530 || priv->id == ID_MT7621) mt7530_set(priv, MT7530_TOP_SIG_CTRL, TOP_SIG_CTRL_NORMAL); ret = request_threaded_irq(priv->irq, NULL, mt7530_irq_thread_fn, @@ -2261,14 +2249,18 @@ mt7530_setup(struct dsa_switch *ds) val |= MHWTRAP_MANUAL; mt7530_write(priv, MT7530_MHWTRAP, val); - priv->p6_interface = PHY_INTERFACE_MODE_NA; - mt753x_trap_frames(priv); /* Enable and reset MIB counters */ mt7530_mib_reset(ds); for (i = 0; i < MT7530_NUM_PORTS; i++) { + /* Clear link settings and enable force mode to force link down + * on all ports until they're enabled later. + */ + mt7530_rmw(priv, MT7530_PMCR_P(i), PMCR_LINK_SETTINGS_MASK | + PMCR_FORCE_MODE, PMCR_FORCE_MODE); + /* Disable forwarding by default on all ports */ mt7530_rmw(priv, MT7530_PCR_P(i), PCR_MATRIX_MASK, PCR_MATRIX_CLR); @@ -2277,9 +2269,7 @@ mt7530_setup(struct dsa_switch *ds) mt7530_set(priv, MT7530_PSC_P(i), SA_DIS); if (dsa_is_cpu_port(ds, i)) { - ret = mt753x_cpu_port_enable(ds, i); - if (ret) - return ret; + mt753x_cpu_port_enable(ds, i); } else { mt7530_port_disable(ds, i); @@ -2373,6 +2363,12 @@ mt7531_setup_common(struct dsa_switch *ds) UNU_FFP_MASK); for (i = 0; i < MT7530_NUM_PORTS; i++) { + /* Clear link settings and enable force mode to force link down + * on all ports until they're enabled later. + */ + mt7530_rmw(priv, MT7530_PMCR_P(i), PMCR_LINK_SETTINGS_MASK | + MT7531_FORCE_MODE, MT7531_FORCE_MODE); + /* Disable forwarding by default on all ports */ mt7530_rmw(priv, MT7530_PCR_P(i), PCR_MATRIX_MASK, PCR_MATRIX_CLR); @@ -2383,9 +2379,7 @@ mt7531_setup_common(struct dsa_switch *ds) mt7530_set(priv, MT7531_DBG_CNT(i), MT7531_DIS_CLR); if (dsa_is_cpu_port(ds, i)) { - ret = mt753x_cpu_port_enable(ds, i); - if (ret) - return ret; + mt753x_cpu_port_enable(ds, i); } else { mt7530_port_disable(ds, i); @@ -2451,14 +2445,12 @@ mt7531_setup(struct dsa_switch *ds) val = mt7530_read(priv, MT7531_TOP_SIG_SR); priv->p5_sgmii = !!(val & PAD_DUAL_SGMII_EN); - /* all MACs must be forced link-down before sw reset */ + /* Force link down on all ports before internal reset */ for (i = 0; i < MT7530_NUM_PORTS; i++) mt7530_write(priv, MT7530_PMCR_P(i), MT7531_FORCE_LNK); /* Reset the switch through internal reset */ - mt7530_write(priv, MT7530_SYS_CTRL, - SYS_CTRL_PHY_RST | SYS_CTRL_SW_RST | - SYS_CTRL_REG_RST); + mt7530_write(priv, MT7530_SYS_CTRL, SYS_CTRL_SW_RST | SYS_CTRL_REG_RST); if (!priv->p5_sgmii) { mt7531_pll_setup(priv); @@ -2476,10 +2468,6 @@ mt7531_setup(struct dsa_switch *ds) mt7530_rmw(priv, MT7531_GPIO_MODE0, MT7531_GPIO0_MASK, MT7531_GPIO0_INTERRUPT); - /* Let phylink decide the interface later. */ - priv->p5_interface = PHY_INTERFACE_MODE_NA; - priv->p6_interface = PHY_INTERFACE_MODE_NA; - /* Enable PHY core PLL, since phy_device has not yet been created * provided for phy_[read,write]_mmd_indirect is called, we provide * our own mt7531_ind_mmd_phy_[read,write] to complete this @@ -2589,7 +2577,7 @@ static void mt7988_mac_port_get_caps(struct dsa_switch *ds, int port, } } -static int +static void mt7530_mac_config(struct dsa_switch *ds, int port, unsigned int mode, phy_interface_t interface) { @@ -2599,22 +2587,14 @@ mt7530_mac_config(struct dsa_switch *ds, int port, unsigned int mode, mt7530_setup_port5(priv->ds, interface); else if (port == 6) mt7530_setup_port6(priv->ds, interface); - - return 0; } -static int mt7531_rgmii_setup(struct mt7530_priv *priv, u32 port, - phy_interface_t interface, - struct phy_device *phydev) +static void mt7531_rgmii_setup(struct mt7530_priv *priv, u32 port, + phy_interface_t interface, + struct phy_device *phydev) { u32 val; - if (priv->p5_sgmii) { - dev_err(priv->dev, "RGMII mode is not available for port %d\n", - port); - return -EINVAL; - } - val = mt7530_read(priv, MT7531_CLKGEN_CTRL); val |= GP_CLK_EN; val &= ~GP_MODE_MASK; @@ -2642,31 +2622,14 @@ static int mt7531_rgmii_setup(struct mt7530_priv *priv, u32 port, case PHY_INTERFACE_MODE_RGMII_ID: break; default: - return -EINVAL; + break; } } - mt7530_write(priv, MT7531_CLKGEN_CTRL, val); - - return 0; -} -static bool mt753x_is_mac_port(u32 port) -{ - return (port == 5 || port == 6); -} - -static int -mt7988_mac_config(struct dsa_switch *ds, int port, unsigned int mode, - phy_interface_t interface) -{ - if (dsa_is_cpu_port(ds, port) && - interface == PHY_INTERFACE_MODE_INTERNAL) - return 0; - - return -EINVAL; + mt7530_write(priv, MT7531_CLKGEN_CTRL, val); } -static int +static void mt7531_mac_config(struct dsa_switch *ds, int port, unsigned int mode, phy_interface_t interface) { @@ -2674,39 +2637,11 @@ mt7531_mac_config(struct dsa_switch *ds, int port, unsigned int mode, struct phy_device *phydev; struct dsa_port *dp; - if (!mt753x_is_mac_port(port)) { - dev_err(priv->dev, "port %d is not a MAC port\n", port); - return -EINVAL; - } - - switch (interface) { - case PHY_INTERFACE_MODE_RGMII: - case PHY_INTERFACE_MODE_RGMII_ID: - case PHY_INTERFACE_MODE_RGMII_RXID: - case PHY_INTERFACE_MODE_RGMII_TXID: + if (phy_interface_mode_is_rgmii(interface)) { dp = dsa_to_port(ds, port); phydev = dp->user->phydev; - return mt7531_rgmii_setup(priv, port, interface, phydev); - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_NA: - case PHY_INTERFACE_MODE_1000BASEX: - case PHY_INTERFACE_MODE_2500BASEX: - /* handled in SGMII PCS driver */ - return 0; - default: - return -EINVAL; + mt7531_rgmii_setup(priv, port, interface, phydev); } - - return -EINVAL; -} - -static int -mt753x_mac_config(struct dsa_switch *ds, int port, unsigned int mode, - const struct phylink_link_state *state) -{ - struct mt7530_priv *priv = ds->priv; - - return priv->info->mac_port_config(ds, port, mode, state->interface); } static struct phylink_pcs * @@ -2732,52 +2667,13 @@ mt753x_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode, const struct phylink_link_state *state) { struct mt7530_priv *priv = ds->priv; - u32 mcr_cur, mcr_new; - - switch (port) { - case 0 ... 4: - if (state->interface != PHY_INTERFACE_MODE_GMII && - state->interface != PHY_INTERFACE_MODE_INTERNAL) - goto unsupported; - break; - case 5: - if (priv->p5_interface == state->interface) - break; - if (mt753x_mac_config(ds, port, mode, state) < 0) - goto unsupported; - - if (priv->p5_intf_sel != P5_DISABLED) - priv->p5_interface = state->interface; - break; - case 6: - if (priv->p6_interface == state->interface) - break; - - if (mt753x_mac_config(ds, port, mode, state) < 0) - goto unsupported; - - priv->p6_interface = state->interface; - break; - default: -unsupported: - dev_err(ds->dev, "%s: unsupported %s port: %i\n", - __func__, phy_modes(state->interface), port); - return; - } - - mcr_cur = mt7530_read(priv, MT7530_PMCR_P(port)); - mcr_new = mcr_cur; - mcr_new &= ~PMCR_LINK_SETTINGS_MASK; - mcr_new |= PMCR_IFG_XMIT(1) | PMCR_MAC_MODE | PMCR_BACKOFF_EN | - PMCR_BACKPR_EN | PMCR_FORCE_MODE_ID(priv->id); + if ((port == 5 || port == 6) && priv->info->mac_port_config) + priv->info->mac_port_config(ds, port, mode, state->interface); /* Are we connected to external phy */ if (port == 5 && dsa_is_user_port(ds, 5)) - mcr_new |= PMCR_EXT_PHY; - - if (mcr_new != mcr_cur) - mt7530_write(priv, MT7530_PMCR_P(port), mcr_new); + mt7530_set(priv, MT7530_PMCR_P(port), PMCR_EXT_PHY); } static void mt753x_phylink_mac_link_down(struct dsa_switch *ds, int port, @@ -2801,17 +2697,10 @@ static void mt753x_phylink_mac_link_up(struct dsa_switch *ds, int port, mcr = PMCR_RX_EN | PMCR_TX_EN | PMCR_FORCE_LNK; - /* MT753x MAC works in 1G full duplex mode for all up-clocked - * variants. - */ - if (interface == PHY_INTERFACE_MODE_TRGMII || - (phy_interface_mode_is_8023z(interface))) { - speed = SPEED_1000; - duplex = DUPLEX_FULL; - } - switch (speed) { case SPEED_1000: + case SPEED_2500: + case SPEED_10000: mcr |= PMCR_FORCE_SPEED_1000; break; case SPEED_100: @@ -2829,6 +2718,7 @@ static void mt753x_phylink_mac_link_up(struct dsa_switch *ds, int port, if (mode == MLO_AN_PHY && phydev && phy_init_eee(phydev, false) >= 0) { switch (speed) { case SPEED_1000: + case SPEED_2500: mcr |= PMCR_FORCE_EEE1G; break; case SPEED_100: @@ -2840,63 +2730,6 @@ static void mt753x_phylink_mac_link_up(struct dsa_switch *ds, int port, mt7530_set(priv, MT7530_PMCR_P(port), mcr); } -static int -mt7531_cpu_port_config(struct dsa_switch *ds, int port) -{ - struct mt7530_priv *priv = ds->priv; - phy_interface_t interface; - int speed; - int ret; - - switch (port) { - case 5: - if (!priv->p5_sgmii) - interface = PHY_INTERFACE_MODE_RGMII; - else - interface = PHY_INTERFACE_MODE_2500BASEX; - - priv->p5_interface = interface; - break; - case 6: - interface = PHY_INTERFACE_MODE_2500BASEX; - - priv->p6_interface = interface; - break; - default: - return -EINVAL; - } - - if (interface == PHY_INTERFACE_MODE_2500BASEX) - speed = SPEED_2500; - else - speed = SPEED_1000; - - ret = mt7531_mac_config(ds, port, MLO_AN_FIXED, interface); - if (ret) - return ret; - mt7530_write(priv, MT7530_PMCR_P(port), - PMCR_CPU_PORT_SETTING(priv->id)); - mt753x_phylink_mac_link_up(ds, port, MLO_AN_FIXED, interface, NULL, - speed, DUPLEX_FULL, true, true); - - return 0; -} - -static int -mt7988_cpu_port_config(struct dsa_switch *ds, int port) -{ - struct mt7530_priv *priv = ds->priv; - - mt7530_write(priv, MT7530_PMCR_P(port), - PMCR_CPU_PORT_SETTING(priv->id)); - - mt753x_phylink_mac_link_up(ds, port, MLO_AN_FIXED, - PHY_INTERFACE_MODE_INTERNAL, NULL, - SPEED_10000, DUPLEX_FULL, true, true); - - return 0; -} - static void mt753x_phylink_get_caps(struct dsa_switch *ds, int port, struct phylink_config *config) { @@ -2979,17 +2812,9 @@ static int mt753x_setup(struct dsa_switch *ds) { struct mt7530_priv *priv = ds->priv; - int i, ret; - - /* Initialise the PCS devices */ - for (i = 0; i < priv->ds->num_ports; i++) { - priv->pcs[i].pcs.ops = priv->info->pcs_ops; - priv->pcs[i].pcs.neg_mode = true; - priv->pcs[i].priv = priv; - priv->pcs[i].port = i; - } + int ret = priv->info->sw_setup(ds); + int i; - ret = priv->info->sw_setup(ds); if (ret) return ret; @@ -3001,6 +2826,14 @@ mt753x_setup(struct dsa_switch *ds) if (ret && priv->irq) mt7530_free_irq_common(priv); + /* Initialise the PCS devices */ + for (i = 0; i < priv->ds->num_ports; i++) { + priv->pcs[i].pcs.ops = priv->info->pcs_ops; + priv->pcs[i].pcs.neg_mode = true; + priv->pcs[i].priv = priv; + priv->pcs[i].port = i; + } + if (priv->create_sgmii) { ret = priv->create_sgmii(priv); if (ret && priv->irq) @@ -3155,7 +2988,6 @@ const struct mt753x_info mt753x_table[] = { .phy_write_c22 = mt7531_ind_c22_phy_write, .phy_read_c45 = mt7531_ind_c45_phy_read, .phy_write_c45 = mt7531_ind_c45_phy_write, - .cpu_port_config = mt7531_cpu_port_config, .mac_port_get_caps = mt7531_mac_port_get_caps, .mac_port_config = mt7531_mac_config, }, @@ -3167,9 +2999,7 @@ const struct mt753x_info mt753x_table[] = { .phy_write_c22 = mt7531_ind_c22_phy_write, .phy_read_c45 = mt7531_ind_c45_phy_read, .phy_write_c45 = mt7531_ind_c45_phy_write, - .cpu_port_config = mt7988_cpu_port_config, .mac_port_get_caps = mt7988_mac_port_get_caps, - .mac_port_config = mt7988_mac_config, }, }; EXPORT_SYMBOL_GPL(mt753x_table); @@ -3197,8 +3027,7 @@ mt7530_probe_common(struct mt7530_priv *priv) * properly. */ if (!priv->info->sw_setup || !priv->info->phy_read_c22 || - !priv->info->phy_write_c22 || !priv->info->mac_port_get_caps || - !priv->info->mac_port_config) + !priv->info->phy_write_c22 || !priv->info->mac_port_get_caps) return -EINVAL; priv->id = priv->info->id; diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h index 26a6d2160c08..a71166e0a7fc 100644 --- a/drivers/net/dsa/mt7530.h +++ b/drivers/net/dsa/mt7530.h @@ -304,20 +304,11 @@ enum mt7530_vlan_port_acc_frm { MT7531_FORCE_DPX | \ MT7531_FORCE_RX_FC | \ MT7531_FORCE_TX_FC) -#define PMCR_FORCE_MODE_ID(id) ((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \ - MT7531_FORCE_MODE : PMCR_FORCE_MODE) #define PMCR_LINK_SETTINGS_MASK (PMCR_TX_EN | PMCR_FORCE_SPEED_1000 | \ PMCR_RX_EN | PMCR_FORCE_SPEED_100 | \ PMCR_TX_FC_EN | PMCR_RX_FC_EN | \ PMCR_FORCE_FDX | PMCR_FORCE_LNK | \ PMCR_FORCE_EEE1G | PMCR_FORCE_EEE100) -#define PMCR_CPU_PORT_SETTING(id) (PMCR_FORCE_MODE_ID((id)) | \ - PMCR_IFG_XMIT(1) | PMCR_MAC_MODE | \ - PMCR_BACKOFF_EN | PMCR_BACKPR_EN | \ - PMCR_TX_EN | PMCR_RX_EN | \ - PMCR_TX_FC_EN | PMCR_RX_FC_EN | \ - PMCR_FORCE_SPEED_1000 | \ - PMCR_FORCE_FDX | PMCR_FORCE_LNK) #define MT7530_PMEEECR_P(x) (0x3004 + (x) * 0x100) #define WAKEUP_TIME_1000(x) (((x) & 0xFF) << 24) @@ -724,15 +715,14 @@ struct mt753x_info { int regnum); int (*phy_write_c45)(struct mt7530_priv *priv, int port, int devad, int regnum, u16 val); - int (*cpu_port_config)(struct dsa_switch *ds, int port); void (*mac_port_get_caps)(struct dsa_switch *ds, int port, struct phylink_config *config); void (*mac_port_validate)(struct dsa_switch *ds, int port, phy_interface_t interface, unsigned long *supported); - int (*mac_port_config)(struct dsa_switch *ds, int port, - unsigned int mode, - phy_interface_t interface); + void (*mac_port_config)(struct dsa_switch *ds, int port, + unsigned int mode, + phy_interface_t interface); }; /* struct mt7530_priv - This is the main data structure for holding the state @@ -750,7 +740,6 @@ struct mt753x_info { * @ports: Holding the state among ports * @reg_mutex: The lock for protecting among process accessing * registers - * @p6_interface Holding the current port 6 interface * @p5_intf_sel: Holding the current port 5 interface select * @p5_sgmii: Flag for distinguishing if port 5 of the MT7531 switch * has got SGMII @@ -772,8 +761,6 @@ struct mt7530_priv { const struct mt753x_info *info; unsigned int id; bool mcm; - phy_interface_t p6_interface; - phy_interface_t p5_interface; enum p5_interface_select p5_intf_sel; bool p5_sgmii; u8 mirror_rx; diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 207f1f66c117..d7693fdf640d 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -2017,6 +2017,37 @@ static int fec_get_mac(struct net_device *ndev) /* * Phy section */ + +/* LPI Sleep Ts count base on tx clk (clk_ref). + * The lpi sleep cnt value = X us / (cycle_ns). + */ +static int fec_enet_us_to_tx_cycle(struct net_device *ndev, int us) +{ + struct fec_enet_private *fep = netdev_priv(ndev); + + return us * (fep->clk_ref_rate / 1000) / 1000; +} + +static int fec_enet_eee_mode_set(struct net_device *ndev, bool enable) +{ + struct fec_enet_private *fep = netdev_priv(ndev); + struct ethtool_keee *p = &fep->eee; + unsigned int sleep_cycle, wake_cycle; + + if (enable) { + sleep_cycle = fec_enet_us_to_tx_cycle(ndev, p->tx_lpi_timer); + wake_cycle = sleep_cycle; + } else { + sleep_cycle = 0; + wake_cycle = 0; + } + + writel(sleep_cycle, fep->hwp + FEC_LPI_SLEEP); + writel(wake_cycle, fep->hwp + FEC_LPI_WAKE); + + return 0; +} + static void fec_enet_adjust_link(struct net_device *ndev) { struct fec_enet_private *fep = netdev_priv(ndev); @@ -2056,6 +2087,8 @@ static void fec_enet_adjust_link(struct net_device *ndev) netif_tx_unlock_bh(ndev); napi_enable(&fep->napi); } + if (fep->quirks & FEC_QUIRK_HAS_EEE) + fec_enet_eee_mode_set(ndev, phy_dev->enable_tx_lpi); } else { if (fep->link) { netif_stop_queue(ndev); @@ -2415,6 +2448,9 @@ static int fec_enet_mii_probe(struct net_device *ndev) else phy_set_max_speed(phy_dev, 100); + if (fep->quirks & FEC_QUIRK_HAS_EEE) + phy_support_eee(phy_dev); + fep->link = 0; fep->full_duplex = 0; @@ -3121,43 +3157,6 @@ static int fec_enet_set_coalesce(struct net_device *ndev, return 0; } -/* LPI Sleep Ts count base on tx clk (clk_ref). - * The lpi sleep cnt value = X us / (cycle_ns). - */ -static int fec_enet_us_to_tx_cycle(struct net_device *ndev, int us) -{ - struct fec_enet_private *fep = netdev_priv(ndev); - - return us * (fep->clk_ref_rate / 1000) / 1000; -} - -static int fec_enet_eee_mode_set(struct net_device *ndev, bool enable) -{ - struct fec_enet_private *fep = netdev_priv(ndev); - struct ethtool_keee *p = &fep->eee; - unsigned int sleep_cycle, wake_cycle; - int ret = 0; - - if (enable) { - ret = phy_init_eee(ndev->phydev, false); - if (ret) - return ret; - - sleep_cycle = fec_enet_us_to_tx_cycle(ndev, p->tx_lpi_timer); - wake_cycle = sleep_cycle; - } else { - sleep_cycle = 0; - wake_cycle = 0; - } - - p->tx_lpi_enabled = enable; - - writel(sleep_cycle, fep->hwp + FEC_LPI_SLEEP); - writel(wake_cycle, fep->hwp + FEC_LPI_WAKE); - - return 0; -} - static int fec_enet_get_eee(struct net_device *ndev, struct ethtool_keee *edata) { @@ -3171,7 +3170,6 @@ fec_enet_get_eee(struct net_device *ndev, struct ethtool_keee *edata) return -ENETDOWN; edata->tx_lpi_timer = p->tx_lpi_timer; - edata->tx_lpi_enabled = p->tx_lpi_enabled; return phy_ethtool_get_eee(ndev->phydev, edata); } @@ -3181,7 +3179,6 @@ fec_enet_set_eee(struct net_device *ndev, struct ethtool_keee *edata) { struct fec_enet_private *fep = netdev_priv(ndev); struct ethtool_keee *p = &fep->eee; - int ret = 0; if (!(fep->quirks & FEC_QUIRK_HAS_EEE)) return -EOPNOTSUPP; @@ -3191,15 +3188,6 @@ fec_enet_set_eee(struct net_device *ndev, struct ethtool_keee *edata) p->tx_lpi_timer = edata->tx_lpi_timer; - if (!edata->eee_enabled || !edata->tx_lpi_enabled || - !edata->tx_lpi_timer) - ret = fec_enet_eee_mode_set(ndev, false); - else - ret = fec_enet_eee_mode_set(ndev, true); - - if (ret) - return ret; - return phy_ethtool_set_eee(ndev->phydev, edata); } diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c index 7b89b66adb53..166bd827a6d7 100644 --- a/drivers/net/ethernet/google/gve/gve_main.c +++ b/drivers/net/ethernet/google/gve/gve_main.c @@ -1276,17 +1276,10 @@ static void gve_unreg_xdp_info(struct gve_priv *priv) static void gve_drain_page_cache(struct gve_priv *priv) { - struct page_frag_cache *nc; int i; - for (i = 0; i < priv->rx_cfg.num_queues; i++) { - nc = &priv->rx[i].page_cache; - if (nc->va) { - __page_frag_cache_drain(virt_to_page(nc->va), - nc->pagecnt_bias); - nc->va = NULL; - } - } + for (i = 0; i < priv->rx_cfg.num_queues; i++) + page_frag_cache_drain(&priv->rx[i].page_cache); } static void gve_qpls_get_curr_alloc_cfg(struct gve_priv *priv, diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.c b/drivers/net/ethernet/hisilicon/hns/hnae.c index 8a1027ad340d..d4293f76d69d 100644 --- a/drivers/net/ethernet/hisilicon/hns/hnae.c +++ b/drivers/net/ethernet/hisilicon/hns/hnae.c @@ -12,7 +12,9 @@ #define cls_to_ae_dev(dev) container_of(dev, struct hnae_ae_dev, cls_dev) -static struct class *hnae_class; +static const struct class hnae_class = { + .name = "hnae", +}; static void hnae_list_add(spinlock_t *lock, struct list_head *node, struct list_head *head) @@ -111,7 +113,7 @@ static struct hnae_ae_dev *find_ae(const struct fwnode_handle *fwnode) WARN_ON(!fwnode); - dev = class_find_device(hnae_class, NULL, fwnode, __ae_match); + dev = class_find_device(&hnae_class, NULL, fwnode, __ae_match); return dev ? cls_to_ae_dev(dev) : NULL; } @@ -415,7 +417,7 @@ int hnae_ae_register(struct hnae_ae_dev *hdev, struct module *owner) hdev->owner = owner; hdev->id = (int)atomic_inc_return(&id); hdev->cls_dev.parent = hdev->dev; - hdev->cls_dev.class = hnae_class; + hdev->cls_dev.class = &hnae_class; hdev->cls_dev.release = hnae_release; (void)dev_set_name(&hdev->cls_dev, "hnae%d", hdev->id); ret = device_register(&hdev->cls_dev); @@ -448,13 +450,12 @@ EXPORT_SYMBOL(hnae_ae_unregister); static int __init hnae_init(void) { - hnae_class = class_create("hnae"); - return PTR_ERR_OR_ZERO(hnae_class); + return class_register(&hnae_class); } static void __exit hnae_exit(void) { - class_destroy(hnae_class); + class_unregister(&hnae_class); } subsys_initcall(hnae_init); diff --git a/drivers/net/ethernet/intel/Kconfig b/drivers/net/ethernet/intel/Kconfig index 767358b60507..639fbb12bd35 100644 --- a/drivers/net/ethernet/intel/Kconfig +++ b/drivers/net/ethernet/intel/Kconfig @@ -372,6 +372,7 @@ config IGC config IGC_LEDS def_bool LEDS_TRIGGER_NETDEV depends on IGC && LEDS_CLASS + depends on LEDS_CLASS=y || IGC=m help Optional support for controlling the NIC LED's with the netdev LED trigger. diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c index 01f0f12035ca..3fcb8daaa243 100644 --- a/drivers/net/ethernet/intel/e100.c +++ b/drivers/net/ethernet/intel/e100.c @@ -171,8 +171,8 @@ static int debug = 3; static int eeprom_bad_csum_allow = 0; static int use_io = 0; module_param(debug, int, 0); -module_param(eeprom_bad_csum_allow, int, 0); -module_param(use_io, int, 0); +module_param(eeprom_bad_csum_allow, int, 0444); +module_param(use_io, int, 0444); MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); MODULE_PARM_DESC(eeprom_bad_csum_allow, "Allow bad eeprom checksums"); MODULE_PARM_DESC(use_io, "Force use of i/o access mode"); diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index af5d9d97a0d6..cc8c531ec3df 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -6688,14 +6688,14 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool runtime) if (adapter->hw.phy.type == e1000_phy_igp_3) { e1000e_igp3_phy_powerdown_workaround_ich8lan(&adapter->hw); } else if (hw->mac.type >= e1000_pch_lpt) { - if (wufc && !(wufc & (E1000_WUFC_EX | E1000_WUFC_MC | E1000_WUFC_BC))) + if (wufc && !(wufc & (E1000_WUFC_EX | E1000_WUFC_MC | E1000_WUFC_BC))) { /* ULP does not support wake from unicast, multicast * or broadcast. */ retval = e1000_enable_ulp_lpt_lp(hw, !runtime); - - if (retval) - return retval; + if (retval) + return retval; + } } /* Ensure that the appropriate bits are set in LPI_CTRL diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index b35556550503..518298bbdadc 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -202,7 +202,7 @@ static struct notifier_block dca_notifier = { #endif #ifdef CONFIG_PCI_IOV static unsigned int max_vfs; -module_param(max_vfs, uint, 0); +module_param(max_vfs, uint, 0444); MODULE_PARM_DESC(max_vfs, "Maximum number of virtual functions to allocate per physical function"); #endif /* CONFIG_PCI_IOV */ diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c index e0c300fe5cee..cdaf087b4e85 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c @@ -334,7 +334,9 @@ static int ixgbe_get_link_capabilities_82599(struct ixgbe_hw *hw, hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 || hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1 || hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 || - hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1) { + hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1 || + hw->phy.sfp_type == ixgbe_sfp_type_1g_bx_core0 || + hw->phy.sfp_type == ixgbe_sfp_type_1g_bx_core1) { *speed = IXGBE_LINK_SPEED_1GB_FULL; *autoneg = true; return 0; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c index 633bac1543dd..6e6e6f1847b6 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c @@ -349,6 +349,8 @@ static int ixgbe_get_link_ksettings(struct net_device *netdev, case ixgbe_sfp_type_1g_sx_core1: case ixgbe_sfp_type_1g_lx_core0: case ixgbe_sfp_type_1g_lx_core1: + case ixgbe_sfp_type_1g_bx_core0: + case ixgbe_sfp_type_1g_bx_core1: ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE); ethtool_link_ksettings_add_link_mode(cmd, advertising, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 1e93edc967ed..595098a4c488 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -153,7 +153,7 @@ MODULE_PARM_DESC(max_vfs, #endif /* CONFIG_PCI_IOV */ static bool allow_unsupported_sfp; -module_param(allow_unsupported_sfp, bool, 0); +module_param(allow_unsupported_sfp, bool, 0444); MODULE_PARM_DESC(allow_unsupported_sfp, "Allow unsupported and untested SFP+ modules on 82599-based adapters"); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c index 75e9453331ed..07eaa3c3f4d3 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c @@ -1532,6 +1532,7 @@ int ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) enum ixgbe_sfp_type stored_sfp_type = hw->phy.sfp_type; struct ixgbe_adapter *adapter = hw->back; u8 oui_bytes[3] = {0, 0, 0}; + u8 bitrate_nominal = 0; u8 comp_codes_10g = 0; u8 comp_codes_1g = 0; u16 enforce_sfp = 0; @@ -1576,7 +1577,12 @@ int ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_CABLE_TECHNOLOGY, &cable_tech); + if (status) + goto err_read_i2c_eeprom; + status = hw->phy.ops.read_i2c_eeprom(hw, + IXGBE_SFF_BITRATE_NOMINAL, + &bitrate_nominal); if (status) goto err_read_i2c_eeprom; @@ -1659,6 +1665,18 @@ int ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) else hw->phy.sfp_type = ixgbe_sfp_type_1g_lx_core1; + /* Support only Ethernet 1000BASE-BX10, checking the Bit Rate + * Nominal Value as per SFF-8472 by convention 1.25 Gb/s should + * be rounded up to 0Dh (13 in units of 100 MBd) for 1000BASE-BX + */ + } else if ((comp_codes_1g & IXGBE_SFF_BASEBX10_CAPABLE) && + (bitrate_nominal == 0xD)) { + if (hw->bus.lan_id == 0) + hw->phy.sfp_type = + ixgbe_sfp_type_1g_bx_core0; + else + hw->phy.sfp_type = + ixgbe_sfp_type_1g_bx_core1; } else { hw->phy.sfp_type = ixgbe_sfp_type_unknown; } @@ -1747,7 +1765,9 @@ int ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 || hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1 || hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 || - hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1)) { + hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1 || + hw->phy.sfp_type == ixgbe_sfp_type_1g_bx_core0 || + hw->phy.sfp_type == ixgbe_sfp_type_1g_bx_core1)) { hw->phy.type = ixgbe_phy_sfp_unsupported; return -EOPNOTSUPP; } @@ -1763,7 +1783,9 @@ int ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 || hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1 || hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 || - hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1)) { + hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1 || + hw->phy.sfp_type == ixgbe_sfp_type_1g_bx_core0 || + hw->phy.sfp_type == ixgbe_sfp_type_1g_bx_core1)) { /* Make sure we're a supported PHY type */ if (hw->phy.type == ixgbe_phy_sfp_intel) return 0; @@ -1999,12 +2021,14 @@ int ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw, if (sfp_type == ixgbe_sfp_type_da_act_lmt_core0 || sfp_type == ixgbe_sfp_type_1g_lx_core0 || sfp_type == ixgbe_sfp_type_1g_cu_core0 || - sfp_type == ixgbe_sfp_type_1g_sx_core0) + sfp_type == ixgbe_sfp_type_1g_sx_core0 || + sfp_type == ixgbe_sfp_type_1g_bx_core0) sfp_type = ixgbe_sfp_type_srlr_core0; else if (sfp_type == ixgbe_sfp_type_da_act_lmt_core1 || sfp_type == ixgbe_sfp_type_1g_lx_core1 || sfp_type == ixgbe_sfp_type_1g_cu_core1 || - sfp_type == ixgbe_sfp_type_1g_sx_core1) + sfp_type == ixgbe_sfp_type_1g_sx_core1 || + sfp_type == ixgbe_sfp_type_1g_bx_core1) sfp_type = ixgbe_sfp_type_srlr_core1; /* Read offset to PHY init contents */ diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h index beedcb7bec0d..14aa2ca51f70 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h @@ -17,6 +17,7 @@ #define IXGBE_SFF_1GBE_COMP_CODES 0x6 #define IXGBE_SFF_10GBE_COMP_CODES 0x3 #define IXGBE_SFF_CABLE_TECHNOLOGY 0x8 +#define IXGBE_SFF_BITRATE_NOMINAL 0xC #define IXGBE_SFF_CABLE_SPEC_COMP 0x3C #define IXGBE_SFF_SFF_8472_SWAP 0x5C #define IXGBE_SFF_SFF_8472_COMP 0x5E @@ -39,6 +40,7 @@ #define IXGBE_SFF_1GBASESX_CAPABLE 0x1 #define IXGBE_SFF_1GBASELX_CAPABLE 0x2 #define IXGBE_SFF_1GBASET_CAPABLE 0x8 +#define IXGBE_SFF_BASEBX10_CAPABLE 0x64 #define IXGBE_SFF_10GBASESR_CAPABLE 0x10 #define IXGBE_SFF_10GBASELR_CAPABLE 0x20 #define IXGBE_SFF_SOFT_RS_SELECT_MASK 0x8 diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index d44c58130be2..ed440dd0c4f9 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -3210,6 +3210,9 @@ enum ixgbe_sfp_type { ixgbe_sfp_type_1g_sx_core1 = 12, ixgbe_sfp_type_1g_lx_core0 = 13, ixgbe_sfp_type_1g_lx_core1 = 14, + ixgbe_sfp_type_1g_bx_core0 = 15, + ixgbe_sfp_type_1g_bx_core1 = 16, + ixgbe_sfp_type_not_present = 0xFFFE, ixgbe_sfp_type_unknown = 0xFFFF }; diff --git a/drivers/net/ethernet/mediatek/mtk_wed_wo.c b/drivers/net/ethernet/mediatek/mtk_wed_wo.c index d58b07e7e123..7063c78bd35f 100644 --- a/drivers/net/ethernet/mediatek/mtk_wed_wo.c +++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.c @@ -286,7 +286,6 @@ mtk_wed_wo_queue_free(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q) static void mtk_wed_wo_queue_tx_clean(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q) { - struct page *page; int i; for (i = 0; i < q->n_desc; i++) { @@ -301,19 +300,12 @@ mtk_wed_wo_queue_tx_clean(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q) entry->buf = NULL; } - if (!q->cache.va) - return; - - page = virt_to_page(q->cache.va); - __page_frag_cache_drain(page, q->cache.pagecnt_bias); - memset(&q->cache, 0, sizeof(q->cache)); + page_frag_cache_drain(&q->cache); } static void mtk_wed_wo_queue_rx_clean(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q) { - struct page *page; - for (;;) { void *buf = mtk_wed_wo_dequeue(wo, q, NULL, true); @@ -323,12 +315,7 @@ mtk_wed_wo_queue_rx_clean(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q) skb_free_frag(buf); } - if (!q->cache.va) - return; - - page = virt_to_page(q->cache.va); - __page_frag_cache_drain(page, q->cache.pagecnt_bias); - memset(&q->cache, 0, sizeof(q->cache)); + page_frag_cache_drain(&q->cache); } static void diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c index e67a21294158..bd4624d14ca0 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c @@ -81,6 +81,7 @@ static void txgbe_up_complete(struct wx *wx) { struct net_device *netdev = wx->netdev; + txgbe_reinit_gpio_intr(wx); wx_control_hw(wx, true); wx_configure_vectors(wx); diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c index bae0a8ee7014..93295916b1d2 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c @@ -475,8 +475,10 @@ irqreturn_t txgbe_gpio_irq_handler(int irq, void *data) gc = txgbe->gpio; for_each_set_bit(hwirq, &gpioirq, gc->ngpio) { int gpio = irq_find_mapping(gc->irq.domain, hwirq); + struct irq_data *d = irq_get_irq_data(gpio); u32 irq_type = irq_get_trigger_type(gpio); + txgbe_gpio_irq_ack(d); handle_nested_irq(gpio); if ((irq_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) { @@ -489,6 +491,33 @@ irqreturn_t txgbe_gpio_irq_handler(int irq, void *data) return IRQ_HANDLED; } +void txgbe_reinit_gpio_intr(struct wx *wx) +{ + struct txgbe *txgbe = wx->priv; + irq_hw_number_t hwirq; + unsigned long gpioirq; + struct gpio_chip *gc; + unsigned long flags; + + /* for gpio interrupt pending before irq enable */ + gpioirq = rd32(wx, WX_GPIO_INTSTATUS); + + gc = txgbe->gpio; + for_each_set_bit(hwirq, &gpioirq, gc->ngpio) { + int gpio = irq_find_mapping(gc->irq.domain, hwirq); + struct irq_data *d = irq_get_irq_data(gpio); + u32 irq_type = irq_get_trigger_type(gpio); + + txgbe_gpio_irq_ack(d); + + if ((irq_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) { + raw_spin_lock_irqsave(&wx->gpio_lock, flags); + txgbe_toggle_trigger(gc, hwirq); + raw_spin_unlock_irqrestore(&wx->gpio_lock, flags); + } + } +} + static int txgbe_gpio_init(struct txgbe *txgbe) { struct gpio_irq_chip *girq; diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.h index 9855d44076cb..8a026d804fe2 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.h +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.h @@ -5,6 +5,7 @@ #define _TXGBE_PHY_H_ irqreturn_t txgbe_gpio_irq_handler(int irq, void *data); +void txgbe_reinit_gpio_intr(struct wx *wx); irqreturn_t txgbe_link_irq_handler(int irq, void *data); int txgbe_init_phy(struct txgbe *txgbe); void txgbe_remove_phy(struct txgbe *txgbe); diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index 6f3f9b446b1d..e25e0a31126c 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -508,7 +508,7 @@ static struct sk_buff *geneve_gro_receive(struct sock *sk, gh_len = geneve_hlen(gh); hlen = off_gnv + gh_len; - if (skb_gro_header_hard(skb, hlen)) { + if (!skb_gro_may_pull(skb, hlen)) { gh = skb_gro_header_slow(skb, hlen, off_gnv); if (unlikely(!gh)) goto out; diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index 9b6973581989..8b8634600c51 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c @@ -114,6 +114,13 @@ #define LAN8814_INTR_CTRL_REG_POLARITY BIT(1) #define LAN8814_INTR_CTRL_REG_INTR_ENABLE BIT(0) +#define LAN8814_EEE_STATE 0x38 +#define LAN8814_EEE_STATE_MASK2P5P BIT(10) + +#define LAN8814_PD_CONTROLS 0x9d +#define LAN8814_PD_CONTROLS_PD_MEAS_TIME_MASK GENMASK(3, 0) +#define LAN8814_PD_CONTROLS_PD_MEAS_TIME_VAL 0xb + /* Represents 1ppm adjustment in 2^32 format with * each nsec contains 4 clock cycles. * The value is calculated as following: (1/1000000)/((2^-32)/4) @@ -3288,6 +3295,33 @@ static int lan8814_release_coma_mode(struct phy_device *phydev) return 0; } +static void lan8814_clear_2psp_bit(struct phy_device *phydev) +{ + u16 val; + + /* It was noticed that when traffic is passing through the PHY and the + * cable is removed then the LED was still one even though there is no + * link + */ + val = lanphy_read_page_reg(phydev, 2, LAN8814_EEE_STATE); + val &= ~LAN8814_EEE_STATE_MASK2P5P; + lanphy_write_page_reg(phydev, 2, LAN8814_EEE_STATE, val); +} + +static void lan8814_update_meas_time(struct phy_device *phydev) +{ + u16 val; + + /* By setting the measure time to a value of 0xb this will allow cables + * longer than 100m to be used. This configuration can be used + * regardless of the mode of operation of the PHY + */ + val = lanphy_read_page_reg(phydev, 1, LAN8814_PD_CONTROLS); + val &= ~LAN8814_PD_CONTROLS_PD_MEAS_TIME_MASK; + val |= LAN8814_PD_CONTROLS_PD_MEAS_TIME_VAL; + lanphy_write_page_reg(phydev, 1, LAN8814_PD_CONTROLS, val); +} + static int lan8814_probe(struct phy_device *phydev) { const struct kszphy_type *type = phydev->drv->driver_data; @@ -3324,6 +3358,10 @@ static int lan8814_probe(struct phy_device *phydev) lan8814_ptp_init(phydev); + /* Errata workarounds */ + lan8814_clear_2psp_bit(phydev); + lan8814_update_meas_time(phydev); + return 0; } diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c index 3e95b8a15f44..5695935fdce9 100644 --- a/drivers/net/phy/phy-c45.c +++ b/drivers/net/phy/phy-c45.c @@ -1550,6 +1550,8 @@ EXPORT_SYMBOL(genphy_c45_ethtool_get_eee); * advertised, but the previously advertised link modes are * retained. This allows EEE to be enabled/disabled in a * non-destructive way. + * Returns either error code, 0 if there was no change, or positive + * value if there was a change which triggered auto-neg. */ int genphy_c45_ethtool_set_eee(struct phy_device *phydev, struct ethtool_keee *data) @@ -1576,8 +1578,16 @@ int genphy_c45_ethtool_set_eee(struct phy_device *phydev, phydev->eee_enabled = data->eee_enabled; ret = genphy_c45_an_config_eee_aneg(phydev); - if (ret > 0) - return phy_restart_aneg(phydev); + if (ret > 0) { + ret = phy_restart_aneg(phydev); + if (ret < 0) + return ret; + + /* explicitly return 1, otherwise (ret > 0) value will be + * overwritten by phy_restart_aneg(). + */ + return 1; + } return ret; } diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 14224e06d69f..c3a0a5ee5f11 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -983,9 +983,17 @@ static int phy_check_link_status(struct phy_device *phydev) if (phydev->link && phydev->state != PHY_RUNNING) { phy_check_downshift(phydev); phydev->state = PHY_RUNNING; + err = genphy_c45_eee_is_active(phydev, + NULL, NULL, NULL); + if (err < 0) + phydev->enable_tx_lpi = false; + else + phydev->enable_tx_lpi = (err & phydev->eee_cfg.tx_lpi_enabled); + phy_link_up(phydev); } else if (!phydev->link && phydev->state != PHY_NOLINK) { phydev->state = PHY_NOLINK; + phydev->enable_tx_lpi = false; phy_link_down(phydev); } @@ -1633,8 +1641,8 @@ EXPORT_SYMBOL(phy_get_eee_err); * @phydev: target phy_device struct * @data: ethtool_keee data * - * Description: it reportes the Supported/Advertisement/LP Advertisement - * capabilities. + * Description: reports the Supported/Advertisement/LP Advertisement + * capabilities, etc. */ int phy_ethtool_get_eee(struct phy_device *phydev, struct ethtool_keee *data) { @@ -1645,6 +1653,7 @@ int phy_ethtool_get_eee(struct phy_device *phydev, struct ethtool_keee *data) mutex_lock(&phydev->lock); ret = genphy_c45_ethtool_get_eee(phydev, data); + eeecfg_to_eee(data, &phydev->eee_cfg); mutex_unlock(&phydev->lock); return ret; @@ -1652,6 +1661,36 @@ int phy_ethtool_get_eee(struct phy_device *phydev, struct ethtool_keee *data) EXPORT_SYMBOL(phy_ethtool_get_eee); /** + * phy_ethtool_set_eee_noneg - Adjusts MAC LPI configuration without PHY + * renegotiation + * @phydev: pointer to the target PHY device structure + * @data: pointer to the ethtool_keee structure containing the new EEE settings + * + * This function updates the Energy Efficient Ethernet (EEE) configuration + * for cases where only the MAC's Low Power Idle (LPI) configuration changes, + * without triggering PHY renegotiation. It ensures that the MAC is properly + * informed of the new LPI settings by cycling the link down and up, which + * is necessary for the MAC to adopt the new configuration. This adjustment + * is done only if there is a change in the tx_lpi_enabled or tx_lpi_timer + * configuration. + */ +static void phy_ethtool_set_eee_noneg(struct phy_device *phydev, + struct ethtool_keee *data) +{ + if (phydev->eee_cfg.tx_lpi_enabled != data->tx_lpi_enabled || + phydev->eee_cfg.tx_lpi_timer != data->tx_lpi_timer) { + eee_to_eeecfg(&phydev->eee_cfg, data); + phydev->enable_tx_lpi = eeecfg_mac_can_tx_lpi(&phydev->eee_cfg); + if (phydev->link) { + phydev->link = false; + phy_link_down(phydev); + phydev->link = true; + phy_link_up(phydev); + } + } +} + +/** * phy_ethtool_set_eee - set EEE supported and status * @phydev: target phy_device struct * @data: ethtool_keee data @@ -1667,9 +1706,14 @@ int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_keee *data) mutex_lock(&phydev->lock); ret = genphy_c45_ethtool_set_eee(phydev, data); + if (ret >= 0) { + if (ret == 0) + phy_ethtool_set_eee_noneg(phydev, data); + eee_to_eeecfg(&phydev->eee_cfg, data); + } mutex_unlock(&phydev->lock); - return ret; + return ret < 0 ? ret : 0; } EXPORT_SYMBOL(phy_ethtool_set_eee); diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 2eefee970851..72452e6a478c 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -2911,6 +2911,34 @@ void phy_advertise_eee_all(struct phy_device *phydev) EXPORT_SYMBOL_GPL(phy_advertise_eee_all); /** + * phy_support_eee - Set initial EEE policy configuration + * @phydev: Target phy_device struct + * + * This function configures the initial policy for Energy Efficient Ethernet + * (EEE) on the specified PHY device, influencing that EEE capabilities are + * advertised before the link is established. It should be called during PHY + * registration by the MAC driver and/or the PHY driver (for SmartEEE PHYs) + * if MAC supports LPI or PHY is capable to compensate missing LPI functionality + * of the MAC. + * + * The function sets default EEE policy parameters, including preparing the PHY + * to advertise EEE capabilities based on hardware support. + * + * It also sets the expected configuration for Low Power Idle (LPI) in the MAC + * driver. If the PHY framework determines that both local and remote + * advertisements support EEE, and the negotiated link mode is compatible with + * EEE, it will set enable_tx_lpi = true. The MAC driver is expected to act on + * this setting by enabling the LPI timer if enable_tx_lpi is set. + */ +void phy_support_eee(struct phy_device *phydev) +{ + linkmode_copy(phydev->advertising_eee, phydev->supported_eee); + phydev->eee_cfg.tx_lpi_enabled = true; + phydev->eee_cfg.eee_enabled = true; +} +EXPORT_SYMBOL(phy_support_eee); + +/** * phy_support_sym_pause - Enable support of symmetrical pause * @phydev: target phy_device struct * diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index db1d11ae817b..fe380fe196e7 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -295,7 +295,9 @@ static void ppp_setup(struct net_device *dev); static const struct net_device_ops ppp_netdev_ops; -static struct class *ppp_class; +static const struct class ppp_class = { + .name = "ppp", +}; /* per net-namespace data */ static inline struct ppp_net *ppp_pernet(struct net *net) @@ -1394,11 +1396,9 @@ static int __init ppp_init(void) goto out_net; } - ppp_class = class_create("ppp"); - if (IS_ERR(ppp_class)) { - err = PTR_ERR(ppp_class); + err = class_register(&ppp_class); + if (err) goto out_chrdev; - } err = rtnl_link_register(&ppp_link_ops); if (err) { @@ -1407,12 +1407,12 @@ static int __init ppp_init(void) } /* not a big deal if we fail here :-) */ - device_create(ppp_class, NULL, MKDEV(PPP_MAJOR, 0), NULL, "ppp"); + device_create(&ppp_class, NULL, MKDEV(PPP_MAJOR, 0), NULL, "ppp"); return 0; out_class: - class_destroy(ppp_class); + class_unregister(&ppp_class); out_chrdev: unregister_chrdev(PPP_MAJOR, "ppp"); out_net: @@ -3549,8 +3549,8 @@ static void __exit ppp_cleanup(void) pr_err("PPP: removing module but units remain!\n"); rtnl_link_unregister(&ppp_link_ops); unregister_chrdev(PPP_MAJOR, "ppp"); - device_destroy(ppp_class, MKDEV(PPP_MAJOR, 0)); - class_destroy(ppp_class); + device_destroy(&ppp_class, MKDEV(PPP_MAJOR, 0)); + class_unregister(&ppp_class); unregister_pernet_device(&ppp_net_ops); } diff --git a/drivers/net/tun.c b/drivers/net/tun.c index be37235af55d..8d258e263f54 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -977,20 +977,15 @@ static int tun_net_init(struct net_device *dev) struct ifreq *ifr = tun->ifr; int err; - dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); - if (!dev->tstats) - return -ENOMEM; - spin_lock_init(&tun->lock); err = security_tun_dev_alloc_security(&tun->security); - if (err < 0) { - free_percpu(dev->tstats); + if (err < 0) return err; - } tun_flow_init(tun); + dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS; dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | TUN_USER_FEATURES | NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX; @@ -1008,7 +1003,6 @@ static int tun_net_init(struct net_device *dev) if (err < 0) { tun_flow_uninit(tun); security_tun_dev_free_security(tun->security); - free_percpu(dev->tstats); return err; } return 0; @@ -1344,7 +1338,6 @@ static const struct net_device_ops tap_netdev_ops = { .ndo_select_queue = tun_select_queue, .ndo_features_check = passthru_features_check, .ndo_set_rx_headroom = tun_set_headroom, - .ndo_get_stats64 = dev_get_tstats64, .ndo_bpf = tun_xdp, .ndo_xdp_xmit = tun_xdp_xmit, .ndo_change_carrier = tun_net_change_carrier, @@ -2317,7 +2310,6 @@ static void tun_free_netdev(struct net_device *dev) BUG_ON(!(list_empty(&tun->disabled))); - free_percpu(dev->tstats); tun_flow_uninit(tun); security_tun_dev_free_security(tun->security); __tun_set_ebpf(tun, &tun->steering_prog, NULL); diff --git a/drivers/net/wan/framer/framer-core.c b/drivers/net/wan/framer/framer-core.c index 33b358b99f70..f547c22e26ac 100644 --- a/drivers/net/wan/framer/framer-core.c +++ b/drivers/net/wan/framer/framer-core.c @@ -18,7 +18,12 @@ #include <linux/regulator/consumer.h> #include <linux/slab.h> -static struct class *framer_class; +static void framer_release(struct device *dev); +static const struct class framer_class = { + .name = "framer", + .dev_release = framer_release, +}; + static DEFINE_MUTEX(framer_provider_mutex); static LIST_HEAD(framer_provider_list); static DEFINE_IDA(framer_ida); @@ -627,7 +632,7 @@ struct framer *framer_create(struct device *dev, struct device_node *node, INIT_DELAYED_WORK(&framer->polling_work, framer_polling_work); BLOCKING_INIT_NOTIFIER_HEAD(&framer->notifier_list); - framer->dev.class = framer_class; + framer->dev.class = &framer_class; framer->dev.parent = dev; framer->dev.of_node = node ? node : dev->of_node; framer->id = id; @@ -741,7 +746,7 @@ struct framer *framer_provider_simple_of_xlate(struct device *dev, struct class_dev_iter iter; struct framer *framer; - class_dev_iter_init(&iter, framer_class, NULL, NULL); + class_dev_iter_init(&iter, &framer_class, NULL, NULL); while ((dev = class_dev_iter_next(&iter))) { framer = dev_to_framer(dev); if (args->np != framer->dev.of_node) @@ -870,14 +875,6 @@ static void framer_release(struct device *dev) static int __init framer_core_init(void) { - framer_class = class_create("framer"); - if (IS_ERR(framer_class)) { - pr_err("failed to create framer class (%pe)\n", framer_class); - return PTR_ERR(framer_class); - } - - framer_class->dev_release = framer_release; - - return 0; + return class_register(&framer_class); } device_initcall(framer_core_init); diff --git a/drivers/net/wwan/wwan_core.c b/drivers/net/wwan/wwan_core.c index b0030f3ed0f0..17431f1b1a0c 100644 --- a/drivers/net/wwan/wwan_core.c +++ b/drivers/net/wwan/wwan_core.c @@ -26,7 +26,9 @@ static DEFINE_MUTEX(wwan_register_lock); /* WWAN device create|remove lock */ static DEFINE_IDA(minors); /* minors for WWAN port chardevs */ static DEFINE_IDA(wwan_dev_ids); /* for unique WWAN device IDs */ -static struct class *wwan_class; +static const struct class wwan_class = { + .name = "wwan", +}; static int wwan_major; static struct dentry *wwan_debugfs_dir; @@ -130,7 +132,7 @@ static struct wwan_device *wwan_dev_get_by_parent(struct device *parent) { struct device *dev; - dev = class_find_device(wwan_class, NULL, parent, wwan_dev_parent_match); + dev = class_find_device(&wwan_class, NULL, parent, wwan_dev_parent_match); if (!dev) return ERR_PTR(-ENODEV); @@ -147,7 +149,7 @@ static struct wwan_device *wwan_dev_get_by_name(const char *name) { struct device *dev; - dev = class_find_device(wwan_class, NULL, name, wwan_dev_name_match); + dev = class_find_device(&wwan_class, NULL, name, wwan_dev_name_match); if (!dev) return ERR_PTR(-ENODEV); @@ -183,7 +185,7 @@ static struct wwan_device *wwan_dev_get_by_debugfs(struct dentry *dir) { struct device *dev; - dev = class_find_device(wwan_class, NULL, dir, wwan_dev_debugfs_match); + dev = class_find_device(&wwan_class, NULL, dir, wwan_dev_debugfs_match); if (!dev) return ERR_PTR(-ENODEV); @@ -239,7 +241,7 @@ static struct wwan_device *wwan_create_dev(struct device *parent) } wwandev->dev.parent = parent; - wwandev->dev.class = wwan_class; + wwandev->dev.class = &wwan_class; wwandev->dev.type = &wwan_dev_type; wwandev->id = id; dev_set_name(&wwandev->dev, "wwan%d", wwandev->id); @@ -265,7 +267,7 @@ done_unlock: static int is_wwan_child(struct device *dev, void *data) { - return dev->class == wwan_class; + return dev->class == &wwan_class; } static void wwan_remove_dev(struct wwan_device *wwandev) @@ -375,7 +377,7 @@ static struct wwan_port *wwan_port_get_by_minor(unsigned int minor) { struct device *dev; - dev = class_find_device(wwan_class, NULL, &minor, wwan_port_minor_match); + dev = class_find_device(&wwan_class, NULL, &minor, wwan_port_minor_match); if (!dev) return ERR_PTR(-ENODEV); @@ -405,7 +407,7 @@ static int __wwan_port_dev_assign_name(struct wwan_port *port, const char *fmt) return -ENOMEM; /* Collect ids of same name format ports */ - class_dev_iter_init(&iter, wwan_class, NULL, &wwan_port_dev_type); + class_dev_iter_init(&iter, &wwan_class, NULL, &wwan_port_dev_type); while ((dev = class_dev_iter_next(&iter))) { if (dev->parent != &wwandev->dev) continue; @@ -477,7 +479,7 @@ struct wwan_port *wwan_create_port(struct device *parent, mutex_init(&port->data_lock); port->dev.parent = &wwandev->dev; - port->dev.class = wwan_class; + port->dev.class = &wwan_class; port->dev.type = &wwan_port_dev_type; port->dev.devt = MKDEV(wwan_major, minor); dev_set_drvdata(&port->dev, drvdata); @@ -1212,11 +1214,9 @@ static int __init wwan_init(void) if (err) return err; - wwan_class = class_create("wwan"); - if (IS_ERR(wwan_class)) { - err = PTR_ERR(wwan_class); + err = class_register(&wwan_class); + if (err) goto unregister; - } /* chrdev used for wwan ports */ wwan_major = __register_chrdev(0, 0, WWAN_MAX_MINORS, "wwan_port", @@ -1233,7 +1233,7 @@ static int __init wwan_init(void) return 0; destroy: - class_destroy(wwan_class); + class_unregister(&wwan_class); unregister: rtnl_link_unregister(&wwan_rtnl_link_ops); return err; @@ -1244,7 +1244,7 @@ static void __exit wwan_exit(void) debugfs_remove_recursive(wwan_debugfs_dir); __unregister_chrdev(wwan_major, 0, WWAN_MAX_MINORS, "wwan_port"); rtnl_link_unregister(&wwan_rtnl_link_ops); - class_destroy(wwan_class); + class_unregister(&wwan_class); } module_init(wwan_init); diff --git a/drivers/net/wwan/wwan_hwsim.c b/drivers/net/wwan/wwan_hwsim.c index ff3dd24ddb33..b02befd1b6fb 100644 --- a/drivers/net/wwan/wwan_hwsim.c +++ b/drivers/net/wwan/wwan_hwsim.c @@ -25,7 +25,9 @@ static int wwan_hwsim_devsnum = 2; module_param_named(devices, wwan_hwsim_devsnum, int, 0444); MODULE_PARM_DESC(devices, "Number of simulated devices"); -static struct class *wwan_hwsim_class; +static const struct class wwan_hwsim_class = { + .name = "wwan_hwsim", +}; static struct dentry *wwan_hwsim_debugfs_topdir; static struct dentry *wwan_hwsim_debugfs_devcreate; @@ -277,7 +279,7 @@ static struct wwan_hwsim_dev *wwan_hwsim_dev_new(void) spin_unlock(&wwan_hwsim_devs_lock); dev->dev.release = wwan_hwsim_dev_release; - dev->dev.class = wwan_hwsim_class; + dev->dev.class = &wwan_hwsim_class; dev_set_name(&dev->dev, "hwsim%u", dev->id); spin_lock_init(&dev->ports_lock); @@ -511,11 +513,9 @@ static int __init wwan_hwsim_init(void) if (!wwan_wq) return -ENOMEM; - wwan_hwsim_class = class_create("wwan_hwsim"); - if (IS_ERR(wwan_hwsim_class)) { - err = PTR_ERR(wwan_hwsim_class); + err = class_register(&wwan_hwsim_class); + if (err) goto err_wq_destroy; - } wwan_hwsim_debugfs_topdir = debugfs_create_dir("wwan_hwsim", NULL); wwan_hwsim_debugfs_devcreate = @@ -534,7 +534,7 @@ err_clean_devs: wwan_hwsim_free_devs(); flush_workqueue(wwan_wq); /* Wait deletion works completion */ debugfs_remove(wwan_hwsim_debugfs_topdir); - class_destroy(wwan_hwsim_class); + class_unregister(&wwan_hwsim_class); err_wq_destroy: destroy_workqueue(wwan_wq); @@ -547,7 +547,7 @@ static void __exit wwan_hwsim_exit(void) wwan_hwsim_free_devs(); flush_workqueue(wwan_wq); /* Wait deletion works completion */ debugfs_remove(wwan_hwsim_debugfs_topdir); - class_destroy(wwan_hwsim_class); + class_unregister(&wwan_hwsim_class); destroy_workqueue(wwan_wq); } diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c index a6d596e05602..3692b56cb58d 100644 --- a/drivers/nvme/host/tcp.c +++ b/drivers/nvme/host/tcp.c @@ -1344,7 +1344,6 @@ static int nvme_tcp_alloc_async_req(struct nvme_tcp_ctrl *ctrl) static void nvme_tcp_free_queue(struct nvme_ctrl *nctrl, int qid) { - struct page *page; struct nvme_tcp_ctrl *ctrl = to_tcp_ctrl(nctrl); struct nvme_tcp_queue *queue = &ctrl->queues[qid]; unsigned int noreclaim_flag; @@ -1355,11 +1354,7 @@ static void nvme_tcp_free_queue(struct nvme_ctrl *nctrl, int qid) if (queue->hdr_digest || queue->data_digest) nvme_tcp_free_crypto(queue); - if (queue->pf_cache.va) { - page = virt_to_head_page(queue->pf_cache.va); - __page_frag_cache_drain(page, queue->pf_cache.pagecnt_bias); - queue->pf_cache.va = NULL; - } + page_frag_cache_drain(&queue->pf_cache); noreclaim_flag = memalloc_noreclaim_save(); /* ->sock will be released by fput() */ diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c index c8655fc5aa5b..2aa5762e9f50 100644 --- a/drivers/nvme/target/tcp.c +++ b/drivers/nvme/target/tcp.c @@ -1591,7 +1591,6 @@ static void nvmet_tcp_free_cmd_data_in_buffers(struct nvmet_tcp_queue *queue) static void nvmet_tcp_release_queue_work(struct work_struct *w) { - struct page *page; struct nvmet_tcp_queue *queue = container_of(w, struct nvmet_tcp_queue, release_work); @@ -1615,8 +1614,7 @@ static void nvmet_tcp_release_queue_work(struct work_struct *w) if (queue->hdr_digest || queue->data_digest) nvmet_tcp_free_crypto(queue); ida_free(&nvmet_tcp_queue_ida, queue->idx); - page = virt_to_head_page(queue->pf_cache.va); - __page_frag_cache_drain(page, queue->pf_cache.pagecnt_bias); + page_frag_cache_drain(&queue->pf_cache); kfree(queue); } diff --git a/drivers/ptp/ptp_fc3.c b/drivers/ptp/ptp_fc3.c index 0e2286ba088a..6ef982862e27 100644 --- a/drivers/ptp/ptp_fc3.c +++ b/drivers/ptp/ptp_fc3.c @@ -996,13 +996,11 @@ static int idtfc3_probe(struct platform_device *pdev) return 0; } -static int idtfc3_remove(struct platform_device *pdev) +static void idtfc3_remove(struct platform_device *pdev) { struct idtfc3 *idtfc3 = platform_get_drvdata(pdev); ptp_clock_unregister(idtfc3->ptp_clock); - - return 0; } static struct platform_driver idtfc3_driver = { @@ -1010,7 +1008,7 @@ static struct platform_driver idtfc3_driver = { .name = "rc38xxx-phc", }, .probe = idtfc3_probe, - .remove = idtfc3_remove, + .remove_new = idtfc3_remove, }; module_platform_driver(idtfc3_driver); diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index f2ed7167c848..4b2fcb228a0a 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -141,10 +141,8 @@ struct vhost_net { unsigned tx_zcopy_err; /* Flush in progress. Protected by tx vq lock. */ bool tx_flush; - /* Private page frag */ - struct page_frag page_frag; - /* Refcount bias of page frag */ - int refcnt_bias; + /* Private page frag cache */ + struct page_frag_cache pf_cache; }; static unsigned vhost_net_zcopy_mask __read_mostly; @@ -655,41 +653,6 @@ static bool tx_can_batch(struct vhost_virtqueue *vq, size_t total_len) !vhost_vq_avail_empty(vq->dev, vq); } -static bool vhost_net_page_frag_refill(struct vhost_net *net, unsigned int sz, - struct page_frag *pfrag, gfp_t gfp) -{ - if (pfrag->page) { - if (pfrag->offset + sz <= pfrag->size) - return true; - __page_frag_cache_drain(pfrag->page, net->refcnt_bias); - } - - pfrag->offset = 0; - net->refcnt_bias = 0; - if (SKB_FRAG_PAGE_ORDER) { - /* Avoid direct reclaim but allow kswapd to wake */ - pfrag->page = alloc_pages((gfp & ~__GFP_DIRECT_RECLAIM) | - __GFP_COMP | __GFP_NOWARN | - __GFP_NORETRY, - SKB_FRAG_PAGE_ORDER); - if (likely(pfrag->page)) { - pfrag->size = PAGE_SIZE << SKB_FRAG_PAGE_ORDER; - goto done; - } - } - pfrag->page = alloc_page(gfp); - if (likely(pfrag->page)) { - pfrag->size = PAGE_SIZE; - goto done; - } - return false; - -done: - net->refcnt_bias = USHRT_MAX; - page_ref_add(pfrag->page, USHRT_MAX - 1); - return true; -} - #define VHOST_NET_RX_PAD (NET_IP_ALIGN + NET_SKB_PAD) static int vhost_net_build_xdp(struct vhost_net_virtqueue *nvq, @@ -699,7 +662,6 @@ static int vhost_net_build_xdp(struct vhost_net_virtqueue *nvq, struct vhost_net *net = container_of(vq->dev, struct vhost_net, dev); struct socket *sock = vhost_vq_get_backend(vq); - struct page_frag *alloc_frag = &net->page_frag; struct virtio_net_hdr *gso; struct xdp_buff *xdp = &nvq->xdp[nvq->batched_xdp]; struct tun_xdp_hdr *hdr; @@ -710,6 +672,7 @@ static int vhost_net_build_xdp(struct vhost_net_virtqueue *nvq, int sock_hlen = nvq->sock_hlen; void *buf; int copied; + int ret; if (unlikely(len < nvq->sock_hlen)) return -EFAULT; @@ -719,18 +682,17 @@ static int vhost_net_build_xdp(struct vhost_net_virtqueue *nvq, return -ENOSPC; buflen += SKB_DATA_ALIGN(len + pad); - alloc_frag->offset = ALIGN((u64)alloc_frag->offset, SMP_CACHE_BYTES); - if (unlikely(!vhost_net_page_frag_refill(net, buflen, - alloc_frag, GFP_KERNEL))) + buf = page_frag_alloc_align(&net->pf_cache, buflen, GFP_KERNEL, + SMP_CACHE_BYTES); + if (unlikely(!buf)) return -ENOMEM; - buf = (char *)page_address(alloc_frag->page) + alloc_frag->offset; - copied = copy_page_from_iter(alloc_frag->page, - alloc_frag->offset + - offsetof(struct tun_xdp_hdr, gso), - sock_hlen, from); - if (copied != sock_hlen) - return -EFAULT; + copied = copy_from_iter(buf + offsetof(struct tun_xdp_hdr, gso), + sock_hlen, from); + if (copied != sock_hlen) { + ret = -EFAULT; + goto err; + } hdr = buf; gso = &hdr->gso; @@ -743,27 +705,30 @@ static int vhost_net_build_xdp(struct vhost_net_virtqueue *nvq, vhost16_to_cpu(vq, gso->csum_start) + vhost16_to_cpu(vq, gso->csum_offset) + 2); - if (vhost16_to_cpu(vq, gso->hdr_len) > len) - return -EINVAL; + if (vhost16_to_cpu(vq, gso->hdr_len) > len) { + ret = -EINVAL; + goto err; + } } len -= sock_hlen; - copied = copy_page_from_iter(alloc_frag->page, - alloc_frag->offset + pad, - len, from); - if (copied != len) - return -EFAULT; + copied = copy_from_iter(buf + pad, len, from); + if (copied != len) { + ret = -EFAULT; + goto err; + } xdp_init_buff(xdp, buflen, NULL); xdp_prepare_buff(xdp, buf, pad, len, true); hdr->buflen = buflen; - --net->refcnt_bias; - alloc_frag->offset += buflen; - ++nvq->batched_xdp; return 0; + +err: + page_frag_free(buf); + return ret; } static void handle_tx_copy(struct vhost_net *net, struct socket *sock) @@ -1353,8 +1318,7 @@ static int vhost_net_open(struct inode *inode, struct file *f) vqs[VHOST_NET_VQ_RX]); f->private_data = n; - n->page_frag.page = NULL; - n->refcnt_bias = 0; + n->pf_cache.va = NULL; return 0; } @@ -1422,8 +1386,7 @@ static int vhost_net_release(struct inode *inode, struct file *f) kfree(n->vqs[VHOST_NET_VQ_RX].rxq.queue); kfree(n->vqs[VHOST_NET_VQ_TX].xdp); kfree(n->dev.vqs); - if (n->page_frag.page) - __page_frag_cache_drain(n->page_frag.page, n->refcnt_bias); + page_frag_cache_drain(&n->pf_cache); kvfree(n); return 0; } |