diff options
Diffstat (limited to 'drivers/net/ethernet/ti')
-rw-r--r-- | drivers/net/ethernet/ti/am65-cpsw-ethtool.c | 56 | ||||
-rw-r--r-- | drivers/net/ethernet/ti/am65-cpsw-nuss.c | 228 | ||||
-rw-r--r-- | drivers/net/ethernet/ti/am65-cpsw-nuss.h | 5 | ||||
-rw-r--r-- | drivers/net/ethernet/ti/am65-cpsw-switchdev.c | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/ti/cpsw_ethtool.c | 6 | ||||
-rw-r--r-- | drivers/net/ethernet/ti/cpsw_switchdev.c | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/ti/davinci_emac.c | 25 | ||||
-rw-r--r-- | drivers/net/ethernet/ti/netcp_core.c | 2 |
8 files changed, 152 insertions, 178 deletions
diff --git a/drivers/net/ethernet/ti/am65-cpsw-ethtool.c b/drivers/net/ethernet/ti/am65-cpsw-ethtool.c index d45b6bb86f0b..72acdf802258 100644 --- a/drivers/net/ethernet/ti/am65-cpsw-ethtool.c +++ b/drivers/net/ethernet/ti/am65-cpsw-ethtool.c @@ -6,7 +6,7 @@ */ #include <linux/net_tstamp.h> -#include <linux/phy.h> +#include <linux/phylink.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> @@ -471,9 +471,7 @@ static void am65_cpsw_get_pauseparam(struct net_device *ndev, { struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev); - pause->autoneg = AUTONEG_DISABLE; - pause->rx_pause = salve->rx_pause ? true : false; - pause->tx_pause = salve->tx_pause ? true : false; + phylink_ethtool_get_pauseparam(salve->phylink, pause); } static int am65_cpsw_set_pauseparam(struct net_device *ndev, @@ -481,18 +479,7 @@ static int am65_cpsw_set_pauseparam(struct net_device *ndev, { struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev); - if (!salve->phy) - return -EINVAL; - - if (!phy_validate_pause(salve->phy, pause)) - return -EINVAL; - - salve->rx_pause = pause->rx_pause ? true : false; - salve->tx_pause = pause->tx_pause ? true : false; - - phy_set_asym_pause(salve->phy, salve->rx_pause, salve->tx_pause); - - return 0; + return phylink_ethtool_set_pauseparam(salve->phylink, pause); } static void am65_cpsw_get_wol(struct net_device *ndev, @@ -500,11 +487,7 @@ static void am65_cpsw_get_wol(struct net_device *ndev, { struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev); - wol->supported = 0; - wol->wolopts = 0; - - if (salve->phy) - phy_ethtool_get_wol(salve->phy, wol); + phylink_ethtool_get_wol(salve->phylink, wol); } static int am65_cpsw_set_wol(struct net_device *ndev, @@ -512,10 +495,7 @@ static int am65_cpsw_set_wol(struct net_device *ndev, { struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev); - if (!salve->phy) - return -EOPNOTSUPP; - - return phy_ethtool_set_wol(salve->phy, wol); + return phylink_ethtool_set_wol(salve->phylink, wol); } static int am65_cpsw_get_link_ksettings(struct net_device *ndev, @@ -523,11 +503,7 @@ static int am65_cpsw_get_link_ksettings(struct net_device *ndev, { struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev); - if (!salve->phy) - return -EOPNOTSUPP; - - phy_ethtool_ksettings_get(salve->phy, ecmd); - return 0; + return phylink_ethtool_ksettings_get(salve->phylink, ecmd); } static int @@ -536,40 +512,28 @@ am65_cpsw_set_link_ksettings(struct net_device *ndev, { struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev); - if (!salve->phy || phy_is_pseudo_fixed_link(salve->phy)) - return -EOPNOTSUPP; - - return phy_ethtool_ksettings_set(salve->phy, ecmd); + return phylink_ethtool_ksettings_set(salve->phylink, ecmd); } static int am65_cpsw_get_eee(struct net_device *ndev, struct ethtool_eee *edata) { struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev); - if (!salve->phy || phy_is_pseudo_fixed_link(salve->phy)) - return -EOPNOTSUPP; - - return phy_ethtool_get_eee(salve->phy, edata); + return phylink_ethtool_get_eee(salve->phylink, edata); } static int am65_cpsw_set_eee(struct net_device *ndev, struct ethtool_eee *edata) { struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev); - if (!salve->phy || phy_is_pseudo_fixed_link(salve->phy)) - return -EOPNOTSUPP; - - return phy_ethtool_set_eee(salve->phy, edata); + return phylink_ethtool_set_eee(salve->phylink, edata); } static int am65_cpsw_nway_reset(struct net_device *ndev) { struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev); - if (!salve->phy || phy_is_pseudo_fixed_link(salve->phy)) - return -EOPNOTSUPP; - - return phy_restart_aneg(salve->phy); + return phylink_ethtool_nway_reset(salve->phylink); } static int am65_cpsw_get_regs_len(struct net_device *ndev) diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c index 8251d7eb001b..d2747e9db286 100644 --- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c +++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c @@ -18,7 +18,7 @@ #include <linux/of_mdio.h> #include <linux/of_net.h> #include <linux/of_device.h> -#include <linux/phy.h> +#include <linux/phylink.h> #include <linux/phy/phy.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> @@ -159,69 +159,6 @@ static void am65_cpsw_nuss_get_ver(struct am65_cpsw_common *common) common->pdata.quirks); } -void am65_cpsw_nuss_adjust_link(struct net_device *ndev) -{ - struct am65_cpsw_common *common = am65_ndev_to_common(ndev); - struct am65_cpsw_port *port = am65_ndev_to_port(ndev); - struct phy_device *phy = port->slave.phy; - u32 mac_control = 0; - - if (!phy) - return; - - if (phy->link) { - mac_control = CPSW_SL_CTL_GMII_EN; - - if (phy->speed == 1000) - mac_control |= CPSW_SL_CTL_GIG; - if (phy->speed == 10 && phy_interface_is_rgmii(phy)) - /* Can be used with in band mode only */ - mac_control |= CPSW_SL_CTL_EXT_EN; - if (phy->speed == 100 && phy->interface == PHY_INTERFACE_MODE_RMII) - mac_control |= CPSW_SL_CTL_IFCTL_A; - if (phy->duplex) - mac_control |= CPSW_SL_CTL_FULLDUPLEX; - - /* RGMII speed is 100M if !CPSW_SL_CTL_GIG*/ - - /* rx_pause/tx_pause */ - if (port->slave.rx_pause) - mac_control |= CPSW_SL_CTL_RX_FLOW_EN; - - if (port->slave.tx_pause) - mac_control |= CPSW_SL_CTL_TX_FLOW_EN; - - cpsw_sl_ctl_set(port->slave.mac_sl, mac_control); - - /* enable forwarding */ - cpsw_ale_control_set(common->ale, port->port_id, - ALE_PORT_STATE, ALE_PORT_STATE_FORWARD); - - am65_cpsw_qos_link_up(ndev, phy->speed); - netif_tx_wake_all_queues(ndev); - } else { - int tmo; - - /* disable forwarding */ - cpsw_ale_control_set(common->ale, port->port_id, - ALE_PORT_STATE, ALE_PORT_STATE_DISABLE); - - cpsw_sl_ctl_set(port->slave.mac_sl, CPSW_SL_CTL_CMD_IDLE); - - tmo = cpsw_sl_wait_for_idle(port->slave.mac_sl, 100); - dev_dbg(common->dev, "donw msc_sl %08x tmo %d\n", - cpsw_sl_reg_read(port->slave.mac_sl, CPSW_SL_MACSTATUS), - tmo); - - cpsw_sl_ctl_reset(port->slave.mac_sl); - - am65_cpsw_qos_link_down(ndev); - netif_tx_stop_all_queues(ndev); - } - - phy_print_status(phy); -} - static int am65_cpsw_nuss_ndo_slave_add_vid(struct net_device *ndev, __be16 proto, u16 vid) { @@ -589,15 +526,11 @@ static int am65_cpsw_nuss_ndo_slave_stop(struct net_device *ndev) struct am65_cpsw_port *port = am65_ndev_to_port(ndev); int ret; - if (port->slave.phy) - phy_stop(port->slave.phy); + phylink_stop(port->slave.phylink); netif_tx_stop_all_queues(ndev); - if (port->slave.phy) { - phy_disconnect(port->slave.phy); - port->slave.phy = NULL; - } + phylink_disconnect_phy(port->slave.phylink); ret = am65_cpsw_nuss_common_stop(common); if (ret) @@ -667,25 +600,14 @@ static int am65_cpsw_nuss_ndo_slave_open(struct net_device *ndev) if (ret) goto error_cleanup; - if (port->slave.phy_node) { - port->slave.phy = of_phy_connect(ndev, - port->slave.phy_node, - &am65_cpsw_nuss_adjust_link, - 0, port->slave.phy_if); - if (!port->slave.phy) { - dev_err(common->dev, "phy %pOF not found on slave %d\n", - port->slave.phy_node, - port->port_id); - ret = -ENODEV; - goto error_cleanup; - } - } + ret = phylink_of_phy_connect(port->slave.phylink, port->slave.phy_node, 0); + if (ret) + goto error_cleanup; /* restore vlan configurations */ vlan_for_each(ndev, cpsw_restore_vlans, port); - phy_attached_info(port->slave.phy); - phy_start(port->slave.phy); + phylink_start(port->slave.phylink); return 0; @@ -1431,10 +1353,7 @@ static int am65_cpsw_nuss_ndo_slave_ioctl(struct net_device *ndev, return am65_cpsw_nuss_hwtstamp_get(ndev, req); } - if (!port->slave.phy) - return -EOPNOTSUPP; - - return phy_mii_ioctl(port->slave.phy, req, cmd); + return phylink_mii_ioctl(port->slave.phylink, req, cmd); } static void am65_cpsw_nuss_ndo_get_stats(struct net_device *dev, @@ -1494,6 +1413,81 @@ static const struct net_device_ops am65_cpsw_nuss_netdev_ops = { .ndo_get_devlink_port = am65_cpsw_ndo_get_devlink_port, }; +static void am65_cpsw_nuss_mac_config(struct phylink_config *config, unsigned int mode, + const struct phylink_link_state *state) +{ + /* Currently not used */ +} + +static void am65_cpsw_nuss_mac_link_down(struct phylink_config *config, unsigned int mode, + phy_interface_t interface) +{ + struct am65_cpsw_slave_data *slave = container_of(config, struct am65_cpsw_slave_data, + phylink_config); + struct am65_cpsw_port *port = container_of(slave, struct am65_cpsw_port, slave); + struct am65_cpsw_common *common = port->common; + struct net_device *ndev = port->ndev; + int tmo; + + /* disable forwarding */ + cpsw_ale_control_set(common->ale, port->port_id, ALE_PORT_STATE, ALE_PORT_STATE_DISABLE); + + cpsw_sl_ctl_set(port->slave.mac_sl, CPSW_SL_CTL_CMD_IDLE); + + tmo = cpsw_sl_wait_for_idle(port->slave.mac_sl, 100); + dev_dbg(common->dev, "down msc_sl %08x tmo %d\n", + cpsw_sl_reg_read(port->slave.mac_sl, CPSW_SL_MACSTATUS), tmo); + + cpsw_sl_ctl_reset(port->slave.mac_sl); + + am65_cpsw_qos_link_down(ndev); + netif_tx_stop_all_queues(ndev); +} + +static void am65_cpsw_nuss_mac_link_up(struct phylink_config *config, struct phy_device *phy, + unsigned int mode, phy_interface_t interface, int speed, + int duplex, bool tx_pause, bool rx_pause) +{ + struct am65_cpsw_slave_data *slave = container_of(config, struct am65_cpsw_slave_data, + phylink_config); + struct am65_cpsw_port *port = container_of(slave, struct am65_cpsw_port, slave); + struct am65_cpsw_common *common = port->common; + u32 mac_control = CPSW_SL_CTL_GMII_EN; + struct net_device *ndev = port->ndev; + + if (speed == SPEED_1000) + mac_control |= CPSW_SL_CTL_GIG; + if (speed == SPEED_10 && interface == PHY_INTERFACE_MODE_RGMII) + /* Can be used with in band mode only */ + mac_control |= CPSW_SL_CTL_EXT_EN; + if (speed == SPEED_100 && interface == PHY_INTERFACE_MODE_RMII) + mac_control |= CPSW_SL_CTL_IFCTL_A; + if (duplex) + mac_control |= CPSW_SL_CTL_FULLDUPLEX; + + /* rx_pause/tx_pause */ + if (rx_pause) + mac_control |= CPSW_SL_CTL_RX_FLOW_EN; + + if (tx_pause) + mac_control |= CPSW_SL_CTL_TX_FLOW_EN; + + cpsw_sl_ctl_set(port->slave.mac_sl, mac_control); + + /* enable forwarding */ + cpsw_ale_control_set(common->ale, port->port_id, ALE_PORT_STATE, ALE_PORT_STATE_FORWARD); + + am65_cpsw_qos_link_up(ndev, speed); + netif_tx_wake_all_queues(ndev); +} + +static const struct phylink_mac_ops am65_cpsw_phylink_mac_ops = { + .validate = phylink_generic_validate, + .mac_config = am65_cpsw_nuss_mac_config, + .mac_link_down = am65_cpsw_nuss_mac_link_down, + .mac_link_up = am65_cpsw_nuss_mac_link_up, +}; + static void am65_cpsw_nuss_slave_disable_unused(struct am65_cpsw_port *port) { struct am65_cpsw_common *common = port->common; @@ -1890,27 +1884,7 @@ static int am65_cpsw_nuss_init_slave_ports(struct am65_cpsw_common *common) of_property_read_bool(port_np, "ti,mac-only"); /* get phy/link info */ - if (of_phy_is_fixed_link(port_np)) { - ret = of_phy_register_fixed_link(port_np); - if (ret) { - ret = dev_err_probe(dev, ret, - "failed to register fixed-link phy %pOF\n", - port_np); - goto of_node_put; - } - port->slave.phy_node = of_node_get(port_np); - } else { - port->slave.phy_node = - of_parse_phandle(port_np, "phy-handle", 0); - } - - if (!port->slave.phy_node) { - dev_err(dev, - "slave[%d] no phy found\n", port_id); - ret = -ENODEV; - goto of_node_put; - } - + port->slave.phy_node = port_np; ret = of_get_phy_mode(port_np, &port->slave.phy_if); if (ret) { dev_err(dev, "%pOF read phy-mode err %d\n", @@ -1952,12 +1926,25 @@ static void am65_cpsw_pcpu_stats_free(void *data) free_percpu(stats); } +static void am65_cpsw_nuss_phylink_cleanup(struct am65_cpsw_common *common) +{ + struct am65_cpsw_port *port; + int i; + + for (i = 0; i < common->port_num; i++) { + port = &common->ports[i]; + if (port->slave.phylink) + phylink_destroy(port->slave.phylink); + } +} + static int am65_cpsw_nuss_init_port_ndev(struct am65_cpsw_common *common, u32 port_idx) { struct am65_cpsw_ndev_priv *ndev_priv; struct device *dev = common->dev; struct am65_cpsw_port *port; + struct phylink *phylink; int ret; port = &common->ports[port_idx]; @@ -1995,6 +1982,20 @@ am65_cpsw_nuss_init_port_ndev(struct am65_cpsw_common *common, u32 port_idx) port->ndev->netdev_ops = &am65_cpsw_nuss_netdev_ops; port->ndev->ethtool_ops = &am65_cpsw_ethtool_ops_slave; + /* Configuring Phylink */ + port->slave.phylink_config.dev = &port->ndev->dev; + port->slave.phylink_config.type = PHYLINK_NETDEV; + port->slave.phylink_config.mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100 | MAC_1000FD; + + phy_interface_set_rgmii(port->slave.phylink_config.supported_interfaces); + + phylink = phylink_create(&port->slave.phylink_config, dev->fwnode, port->slave.phy_if, + &am65_cpsw_phylink_mac_ops); + if (IS_ERR(phylink)) + return PTR_ERR(phylink); + + port->slave.phylink = phylink; + /* Disable TX checksum offload by default due to HW bug */ if (common->pdata.quirks & AM65_CPSW_QUIRK_I2027_NO_TX_CSUM) port->ndev->features &= ~NETIF_F_HW_CSUM; @@ -2761,15 +2762,17 @@ static int am65_cpsw_nuss_probe(struct platform_device *pdev) ret = am65_cpsw_nuss_init_ndevs(common); if (ret) - goto err_of_clear; + goto err_free_phylink; ret = am65_cpsw_nuss_register_ndevs(common); if (ret) - goto err_of_clear; + goto err_free_phylink; pm_runtime_put(dev); return 0; +err_free_phylink: + am65_cpsw_nuss_phylink_cleanup(common); err_of_clear: of_platform_device_destroy(common->mdio_dev, NULL); err_pm_clear: @@ -2792,6 +2795,7 @@ static int am65_cpsw_nuss_remove(struct platform_device *pdev) return ret; } + am65_cpsw_nuss_phylink_cleanup(common); am65_cpsw_unregister_devlink(common); am65_cpsw_unregister_notifiers(common); diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.h b/drivers/net/ethernet/ti/am65-cpsw-nuss.h index 048ed10143c1..ac945631bf2f 100644 --- a/drivers/net/ethernet/ti/am65-cpsw-nuss.h +++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.h @@ -10,7 +10,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/netdevice.h> -#include <linux/phy.h> +#include <linux/phylink.h> #include <linux/platform_device.h> #include <linux/soc/ti/k3-ringacc.h> #include <net/devlink.h> @@ -30,13 +30,14 @@ struct am65_cpsw_slave_data { bool mac_only; struct cpsw_sl *mac_sl; struct device_node *phy_node; - struct phy_device *phy; phy_interface_t phy_if; struct phy *ifphy; bool rx_pause; bool tx_pause; u8 mac_addr[ETH_ALEN]; int port_vlan; + struct phylink *phylink; + struct phylink_config phylink_config; }; struct am65_cpsw_port { diff --git a/drivers/net/ethernet/ti/am65-cpsw-switchdev.c b/drivers/net/ethernet/ti/am65-cpsw-switchdev.c index 599708a3e81d..d4c56da98a6a 100644 --- a/drivers/net/ethernet/ti/am65-cpsw-switchdev.c +++ b/drivers/net/ethernet/ti/am65-cpsw-switchdev.c @@ -237,15 +237,11 @@ static int am65_cpsw_port_vlans_add(struct am65_cpsw_port *port, { bool untag = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; struct net_device *orig_dev = vlan->obj.orig_dev; - bool cpu_port = netif_is_bridge_master(orig_dev); bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID; netdev_dbg(port->ndev, "VID add: %s: vid:%u flags:%X\n", port->ndev->name, vlan->vid, vlan->flags); - if (cpu_port && !(vlan->flags & BRIDGE_VLAN_INFO_BRENTRY)) - return 0; - return am65_cpsw_port_vlan_add(port, untag, pvid, vlan->vid, orig_dev); } diff --git a/drivers/net/ethernet/ti/cpsw_ethtool.c b/drivers/net/ethernet/ti/cpsw_ethtool.c index aa42141be3c0..a557a477d039 100644 --- a/drivers/net/ethernet/ti/cpsw_ethtool.c +++ b/drivers/net/ethernet/ti/cpsw_ethtool.c @@ -364,11 +364,9 @@ int cpsw_ethtool_op_begin(struct net_device *ndev) struct cpsw_common *cpsw = priv->cpsw; int ret; - ret = pm_runtime_get_sync(cpsw->dev); - if (ret < 0) { + ret = pm_runtime_resume_and_get(cpsw->dev); + if (ret < 0) cpsw_err(priv, drv, "ethtool begin failed %d\n", ret); - pm_runtime_put_noidle(cpsw->dev); - } return ret; } diff --git a/drivers/net/ethernet/ti/cpsw_switchdev.c b/drivers/net/ethernet/ti/cpsw_switchdev.c index a7d97d429e06..ce85f7610273 100644 --- a/drivers/net/ethernet/ti/cpsw_switchdev.c +++ b/drivers/net/ethernet/ti/cpsw_switchdev.c @@ -252,15 +252,11 @@ static int cpsw_port_vlans_add(struct cpsw_priv *priv, { bool untag = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; struct net_device *orig_dev = vlan->obj.orig_dev; - bool cpu_port = netif_is_bridge_master(orig_dev); bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID; dev_dbg(priv->dev, "VID add: %s: vid:%u flags:%X\n", priv->ndev->name, vlan->vid, vlan->flags); - if (cpu_port && !(vlan->flags & BRIDGE_VLAN_INFO_BRENTRY)) - return 0; - return cpsw_port_vlan_add(priv, untag, pvid, vlan->vid, orig_dev); } diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c index 31df3267a01a..4b6aed78d392 100644 --- a/drivers/net/ethernet/ti/davinci_emac.c +++ b/drivers/net/ethernet/ti/davinci_emac.c @@ -1604,6 +1604,7 @@ static int emac_dev_stop(struct net_device *ndev) int irq_num; struct emac_priv *priv = netdev_priv(ndev); struct device *emac_dev = &ndev->dev; + int ret = 0; /* inform the upper layers. */ netif_stop_queue(ndev); @@ -1618,17 +1619,31 @@ static int emac_dev_stop(struct net_device *ndev) phy_disconnect(ndev->phydev); /* Free IRQ */ - while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, i))) { - for (irq_num = res->start; irq_num <= res->end; irq_num++) - free_irq(irq_num, priv->ndev); - i++; + if (dev_of_node(&priv->pdev->dev)) { + do { + ret = platform_get_irq_optional(priv->pdev, i); + if (ret < 0 && ret != -ENXIO) + break; + if (ret > 0) { + free_irq(ret, priv->ndev); + } else { + ret = 0; + break; + } + } while (++i); + } else { + while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, i))) { + for (irq_num = res->start; irq_num <= res->end; irq_num++) + free_irq(irq_num, priv->ndev); + i++; + } } if (netif_msg_drv(priv)) dev_notice(emac_dev, "DaVinci EMAC: %s stopped\n", ndev->name); pm_runtime_put(&priv->pdev->dev); - return 0; + return ret; } /** diff --git a/drivers/net/ethernet/ti/netcp_core.c b/drivers/net/ethernet/ti/netcp_core.c index b818e4579f6f..16507bff652a 100644 --- a/drivers/net/ethernet/ti/netcp_core.c +++ b/drivers/net/ethernet/ti/netcp_core.c @@ -2082,7 +2082,7 @@ static int netcp_create_interface(struct netcp_device *netcp_device, netcp->tx_pool_region_id = temp[1]; if (netcp->tx_pool_size < MAX_SKB_FRAGS) { - dev_err(dev, "tx-pool size too small, must be atleast(%ld)\n", + dev_err(dev, "tx-pool size too small, must be at least %ld\n", MAX_SKB_FRAGS); ret = -ENODEV; goto quit; |