diff options
Diffstat (limited to 'drivers/net')
| -rw-r--r-- | drivers/net/ethernet/broadcom/genet/bcmgenet.c | 24 | ||||
| -rw-r--r-- | drivers/net/ethernet/broadcom/genet/bcmgenet.h | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/broadcom/genet/bcmmii.c | 6 | ||||
| -rw-r--r-- | drivers/net/ethernet/cadence/macb.h | 25 | ||||
| -rw-r--r-- | drivers/net/ethernet/cadence/macb_main.c | 140 | ||||
| -rw-r--r-- | drivers/net/phy/bcm-phy-ptp.c | 12 | ||||
| -rw-r--r-- | drivers/net/phy/broadcom.c | 764 | ||||
| -rw-r--r-- | drivers/net/phy/microchip.c | 27 | ||||
| -rw-r--r-- | drivers/net/usb/lan78xx.c | 37 | ||||
| -rw-r--r-- | drivers/net/usb/smsc95xx.c | 41 |
10 files changed, 699 insertions, 379 deletions
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index 98971ae4f87d..0d89590d0022 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -65,6 +65,12 @@ /* Forward declarations */ static void bcmgenet_set_rx_mode(struct net_device *dev); +static bool skip_umac_reset = false; +module_param(skip_umac_reset, bool, 0444); +MODULE_PARM_DESC(skip_umac_reset, "Skip UMAC reset step"); +static bool eee = true; +module_param(eee, bool, 0444); +MODULE_PARM_DESC(eee, "Enable EEE (default Y)"); static inline void bcmgenet_writel(u32 value, void __iomem *offset) { @@ -2566,6 +2572,11 @@ static void reset_umac(struct bcmgenet_priv *priv) bcmgenet_rbuf_ctrl_set(priv, 0); udelay(10); + if (skip_umac_reset) { + pr_warn("Skipping UMAC reset\n"); + return; + } + /* issue soft reset and disable MAC while updating its registers */ spin_lock_bh(&priv->reg_lock); bcmgenet_umac_writel(priv, CMD_SW_RESET, UMAC_CMD); @@ -2728,7 +2739,7 @@ static void bcmgenet_init_tx_ring(struct bcmgenet_priv *priv, bcmgenet_tdma_ring_writel(priv, index, 0, TDMA_PROD_INDEX); bcmgenet_tdma_ring_writel(priv, index, 0, TDMA_CONS_INDEX); - bcmgenet_tdma_ring_writel(priv, index, 1, DMA_MBUF_DONE_THRESH); + bcmgenet_tdma_ring_writel(priv, index, 10, DMA_MBUF_DONE_THRESH); /* Disable rate control for now */ bcmgenet_tdma_ring_writel(priv, index, flow_period_val, TDMA_FLOW_PERIOD); @@ -3363,6 +3374,17 @@ static int bcmgenet_open(struct net_device *dev) bcmgenet_phy_pause_set(dev, priv->rx_pause, priv->tx_pause); + if (!eee) { + struct ethtool_keee eee_data; + + ret = bcmgenet_get_eee(dev, &eee_data); + if (ret == 0) { + eee_data.eee_enabled = 0; + bcmgenet_set_eee(dev, &eee_data); + netdev_warn(dev, "EEE disabled\n"); + } + } + bcmgenet_netif_start(dev); netif_tx_start_all_queues(dev); diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h index 5ec3979779ec..3527e8e23a66 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h @@ -34,7 +34,7 @@ #define ENET_PAD 8 #define ENET_MAX_MTU_SIZE (ETH_DATA_LEN + ETH_HLEN + VLAN_HLEN + \ ENET_BRCM_TAG_LEN + ETH_FCS_LEN + ENET_PAD) -#define DMA_MAX_BURST_LENGTH 0x10 +#define DMA_MAX_BURST_LENGTH 0x08 /* misc. configuration */ #define MAX_NUM_OF_FS_RULES 16 diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c index 573e8b279e52..f2fd1e5a4015 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmmii.c +++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c @@ -309,14 +309,14 @@ int bcmgenet_mii_probe(struct net_device *dev) struct device_node *dn = kdev->of_node; phy_interface_t phy_iface = priv->phy_interface; struct phy_device *phydev; - u32 phy_flags = PHY_BRCM_AUTO_PWRDWN_ENABLE | - PHY_BRCM_DIS_TXCRXC_NOENRGY | - PHY_BRCM_IDDQ_SUSPEND; + u32 phy_flags = 0; int ret; /* Communicate the integrated PHY revision */ if (priv->internal_phy) phy_flags = priv->gphy_rev; + else + phy_flags = PHY_BRCM_AUTO_PWRDWN_ENABLE; /* This is an ugly quirk but we have not been correctly interpreting * the phy_interface values and we have done that across different diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h index 0830c48973aa..2c814a2d06b7 100644 --- a/drivers/net/ethernet/cadence/macb.h +++ b/drivers/net/ethernet/cadence/macb.h @@ -86,6 +86,8 @@ #define GEM_PBUFRXCUT 0x0044 /* RX Partial Store and Forward */ #define GEM_JML 0x0048 /* Jumbo Max Length */ #define GEM_HS_MAC_CONFIG 0x0050 /* GEM high speed config */ +#define GEM_AMP 0x0054 /* AXI Max Pipeline */ +#define GEM_INTMOD 0x005c /* Interrupt moderation */ #define GEM_HRB 0x0080 /* Hash Bottom */ #define GEM_HRT 0x0084 /* Hash Top */ #define GEM_SA1B 0x0088 /* Specific1 Bottom */ @@ -360,6 +362,21 @@ #define GEM_ADDR64_OFFSET 30 /* Address bus width - 64b or 32b */ #define GEM_ADDR64_SIZE 1 +/* Bitfields in AMP */ +#define GEM_AR2R_MAX_PIPE_OFFSET 0 /* Maximum number of outstanding AXI read requests */ +#define GEM_AR2R_MAX_PIPE_SIZE 8 +#define GEM_AW2W_MAX_PIPE_OFFSET 8 /* Maximum number of outstanding AXI write requests */ +#define GEM_AW2W_MAX_PIPE_SIZE 8 +#define GEM_AW2B_FILL_OFFSET 16 /* Select wether the max AW2W transactions operates between: */ +#define GEM_AW2B_FILL_AW2W 0 /* 0: the AW to W AXI channel */ +#define GEM_AW2B_FILL_AW2B 1 /* 1: AW to B channel */ +#define GEM_AW2B_FILL_SIZE 1 + +/* Bitfields in INTMOD */ +#define GEM_RX_MODERATION_OFFSET 0 /* RX interrupt moderation */ +#define GEM_RX_MODERATION_SIZE 8 +#define GEM_TX_MODERATION_OFFSET 16 /* TX interrupt moderation */ +#define GEM_TX_MODERATION_SIZE 8 /* Bitfields in PBUFRXCUT */ #define GEM_ENCUTTHRU_OFFSET 31 /* Enable RX partial store and forward */ @@ -843,6 +860,7 @@ }) #define MACB_READ_NSR(bp) macb_readl(bp, NSR) +#define MACB_READ_TSR(bp) macb_readl(bp, TSR) /* struct macb_dma_desc - Hardware DMA descriptor * @addr: DMA address of data buffer @@ -1260,6 +1278,7 @@ struct macb_queue { dma_addr_t tx_ring_dma; struct work_struct tx_error_task; bool txubr_pending; + bool tx_pending; struct napi_struct napi_tx; dma_addr_t rx_ring_dma; @@ -1327,9 +1346,15 @@ struct macb { u32 caps; unsigned int dma_burst_length; + u8 aw2w_max_pipe; + u8 ar2r_max_pipe; + bool use_aw2b_fill; phy_interface_t phy_interface; + struct gpio_desc *phy_reset_gpio; + int phy_reset_ms; + /* AT91RM9200 transmit queue (1 on wire + 1 queued) */ struct macb_tx_skb rm9200_txq[2]; unsigned int max_tx_length; diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index ca2386b83473..db4c08e1514a 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -21,6 +21,7 @@ #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/dma-mapping.h> +#include <linux/gpio/consumer.h> #include <linux/platform_device.h> #include <linux/phylink.h> #include <linux/of.h> @@ -39,6 +40,9 @@ #include <net/pkt_sched.h> #include "macb.h" +static unsigned int txdelay = 35; +module_param(txdelay, uint, 0644); + /* This structure is only used for MACB on SiFive FU540 devices */ struct sifive_fu540_macb_mgmt { void __iomem *reg; @@ -328,7 +332,7 @@ static int macb_mdio_wait_for_idle(struct macb *bp) u32 val; return readx_poll_timeout(MACB_READ_NSR, bp, val, val & MACB_BIT(IDLE), - 1, MACB_MDIO_TIMEOUT); + 100, MACB_MDIO_TIMEOUT); } static int macb_mdio_read_c22(struct mii_bus *bus, int mii_id, int regnum) @@ -487,6 +491,19 @@ mdio_pm_exit: return status; } +static int macb_mdio_reset(struct mii_bus *bus) +{ + struct macb *bp = bus->priv; + + if (bp->phy_reset_gpio) { + gpiod_set_value_cansleep(bp->phy_reset_gpio, 1); + msleep(bp->phy_reset_ms); + gpiod_set_value_cansleep(bp->phy_reset_gpio, 0); + } + + return 0; +} + static void macb_init_buffers(struct macb *bp) { struct macb_queue *queue; @@ -953,6 +970,7 @@ static int macb_mii_init(struct macb *bp) bp->mii_bus->write = &macb_mdio_write_c22; bp->mii_bus->read_c45 = &macb_mdio_read_c45; bp->mii_bus->write_c45 = &macb_mdio_write_c45; + bp->mii_bus->reset = &macb_mdio_reset; snprintf(bp->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x", bp->pdev->name, bp->pdev->id); bp->mii_bus->priv = bp; @@ -1629,6 +1647,11 @@ static int macb_rx(struct macb_queue *queue, struct napi_struct *napi, macb_init_rx_ring(queue); queue_writel(queue, RBQP, queue->rx_ring_dma); +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT + if (bp->hw_dma_cap & HW_DMA_CAP_64B) + macb_writel(bp, RBQPH, + upper_32_bits(queue->rx_ring_dma)); +#endif macb_writel(bp, NCR, ctrl | MACB_BIT(RE)); @@ -1931,8 +1954,9 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) queue_writel(queue, ISR, MACB_BIT(TCOMP) | MACB_BIT(TXUBR)); - if (status & MACB_BIT(TXUBR)) { + if (status & MACB_BIT(TXUBR) || queue->tx_pending) { queue->txubr_pending = true; + queue->tx_pending = 0; wmb(); // ensure softirq can see update } @@ -2390,6 +2414,11 @@ static netdev_tx_t macb_start_xmit(struct sk_buff *skb, struct net_device *dev) skb->len); spin_lock(&bp->lock); + + /* TSTART write might get dropped, so make the IRQ retrigger a buffer read */ + if (macb_readl(bp, TSR) & MACB_BIT(TGO)) + queue->tx_pending = 1; + macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART)); spin_unlock(&bp->lock); @@ -2813,6 +2842,37 @@ static void macb_configure_dma(struct macb *bp) } } +static void gem_init_axi(struct macb *bp) +{ + u32 amp; + + /* AXI pipeline setup - don't touch values unless specified in device + * tree. Some hardware could have reset values > 1. + */ + amp = gem_readl(bp, AMP); + + if (bp->use_aw2b_fill) + amp = GEM_BFINS(AW2B_FILL, bp->use_aw2b_fill, amp); + if (bp->aw2w_max_pipe) + amp = GEM_BFINS(AW2W_MAX_PIPE, bp->aw2w_max_pipe, amp); + if (bp->ar2r_max_pipe) + amp = GEM_BFINS(AR2R_MAX_PIPE, bp->ar2r_max_pipe, amp); + + gem_writel(bp, AMP, amp); +} + +static void gem_init_intmod(struct macb *bp) +{ + unsigned int throttle; + u32 intmod = 0; + + /* Use sensible interrupt moderation thresholds (50us rx and tx) */ + throttle = (1000 * 50) / 800; + intmod = GEM_BFINS(TX_MODERATION, throttle, intmod); + intmod = GEM_BFINS(RX_MODERATION, throttle, intmod); + gem_writel(bp, INTMOD, intmod); +} + static void macb_init_hw(struct macb *bp) { u32 config; @@ -2841,6 +2901,11 @@ static void macb_init_hw(struct macb *bp) if (bp->caps & MACB_CAPS_JUMBO) bp->rx_frm_len_mask = MACB_RX_JFRMLEN_MASK; + if (macb_is_gem(bp)) { + gem_init_axi(bp); + gem_init_intmod(bp); + } + macb_configure_dma(bp); /* Enable RX partial store and forward and set watermark */ @@ -3201,6 +3266,52 @@ static void gem_get_ethtool_strings(struct net_device *dev, u32 sset, u8 *p) } } +static int gem_set_coalesce(struct net_device *dev, + struct ethtool_coalesce *ec, + struct kernel_ethtool_coalesce *kernel_coal, + struct netlink_ext_ack *extack) +{ + struct macb *bp = netdev_priv(dev); + unsigned int tx_throttle; + unsigned int rx_throttle; + u32 intmod = 0; + + /* GEM has simple IRQ throttling support. RX and TX interrupts + * are separately moderated on 800ns quantums, with no support + * for frame coalescing. + */ + + /* Max is 255 * 0.8us = 204us. Zero implies no moderation. */ + if (ec->rx_coalesce_usecs > 204 || ec->tx_coalesce_usecs > 204) + return -EINVAL; + + tx_throttle = (1000 * ec->tx_coalesce_usecs) / 800; + rx_throttle = (1000 * ec->rx_coalesce_usecs) / 800; + + intmod = GEM_BFINS(TX_MODERATION, tx_throttle, intmod); + intmod = GEM_BFINS(RX_MODERATION, rx_throttle, intmod); + + gem_writel(bp, INTMOD, intmod); + + return 0; +} + +static int gem_get_coalesce(struct net_device *dev, + struct ethtool_coalesce *ec, + struct kernel_ethtool_coalesce *kernel_coal, + struct netlink_ext_ack *extack) +{ + struct macb *bp = netdev_priv(dev); + u32 intmod; + + intmod = gem_readl(bp, INTMOD); + + ec->tx_coalesce_usecs = (GEM_BFEXT(TX_MODERATION, intmod) * 800) / 1000; + ec->rx_coalesce_usecs = (GEM_BFEXT(RX_MODERATION, intmod) * 800) / 1000; + + return 0; +} + static void macb_get_stats(struct net_device *dev, struct rtnl_link_stats64 *nstat) { @@ -3954,6 +4065,8 @@ static const struct ethtool_ops macb_ethtool_ops = { }; static const struct ethtool_ops gem_ethtool_ops = { + .supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS | + ETHTOOL_COALESCE_TX_USECS, .get_regs_len = macb_get_regs_len, .get_regs = macb_get_regs, .get_wol = macb_get_wol, @@ -3967,6 +4080,8 @@ static const struct ethtool_ops gem_ethtool_ops = { .get_eth_mac_stats = gem_get_eth_mac_stats, .get_eth_phy_stats = gem_get_eth_phy_stats, .get_rmon_stats = gem_get_rmon_stats, + .get_coalesce = gem_get_coalesce, + .set_coalesce = gem_set_coalesce, .get_link_ksettings = macb_get_link_ksettings, .set_link_ksettings = macb_set_link_ksettings, .get_ringparam = macb_get_ringparam, @@ -5533,6 +5648,11 @@ static int macb_probe(struct platform_device *pdev) } } } + + device_property_read_u8(&pdev->dev, "cdns,aw2w-max-pipe", &bp->aw2w_max_pipe); + device_property_read_u8(&pdev->dev, "cdns,ar2r-max-pipe", &bp->ar2r_max_pipe); + bp->use_aw2b_fill = device_property_read_bool(&pdev->dev, "cdns,use-aw2b-fill"); + spin_lock_init(&bp->lock); spin_lock_init(&bp->stats_lock); @@ -5593,6 +5713,21 @@ static int macb_probe(struct platform_device *pdev) else bp->phy_interface = interface; + /* optional PHY reset-related properties */ + bp->phy_reset_gpio = devm_gpiod_get_optional(&pdev->dev, "phy-reset", + GPIOD_OUT_LOW); + if (IS_ERR(bp->phy_reset_gpio)) { + dev_err(&pdev->dev, "Failed to obtain phy-reset gpio\n"); + err = PTR_ERR(bp->phy_reset_gpio); + goto err_out_free_netdev; + } + + bp->phy_reset_ms = 10; + of_property_read_u32(np, "phy-reset-duration", &bp->phy_reset_ms); + /* A sane reset duration should not be longer than 1s */ + if (bp->phy_reset_ms > 1000) + bp->phy_reset_ms = 1000; + /* IP specific init */ err = init(pdev); if (err) @@ -5932,6 +6067,7 @@ static const struct dev_pm_ops macb_pm_ops = { static struct platform_driver macb_driver = { .probe = macb_probe, .remove = macb_remove, + .shutdown = macb_shutdown, .driver = { .name = "macb", .of_match_table = of_match_ptr(macb_dt_ids), diff --git a/drivers/net/phy/bcm-phy-ptp.c b/drivers/net/phy/bcm-phy-ptp.c index d3501f8487d9..fcb004fcba3d 100644 --- a/drivers/net/phy/bcm-phy-ptp.c +++ b/drivers/net/phy/bcm-phy-ptp.c @@ -912,6 +912,18 @@ struct bcm_ptp_private *bcm_ptp_probe(struct phy_device *phydev) switch (BRCM_PHY_MODEL(phydev)) { case PHY_ID_BCM54210E: break; +#ifdef PHY_ID_BCM54213PE + case PHY_ID_BCM54213PE: + switch (phydev->mdio.addr) { + case 0: // CM4 - this is a BCM54210PE which supports PTP + break; + case 1: // 4B - this is a BCM54213PE which doesn't + return NULL; + default: // Unknown - assume it's BCM54210PE + break; + } + break; +#endif default: return NULL; } diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c index cb306f9e80cc..ddd055da6684 100644 --- a/drivers/net/phy/broadcom.c +++ b/drivers/net/phy/broadcom.c @@ -31,34 +31,30 @@ MODULE_AUTHOR("Maciej W. Rozycki"); MODULE_LICENSE("GPL"); struct bcm54xx_phy_priv { - u64 *stats; + u64 *stats; struct bcm_ptp_private *ptp; - int wake_irq; - bool wake_irq_enabled; - bool brr_mode; + int wake_irq; + bool wake_irq_enabled; + bool brr_mode; }; /* Link modes for BCM58411 PHY */ -static const int bcm54811_linkmodes[] = { - ETHTOOL_LINK_MODE_100baseT1_Full_BIT, - ETHTOOL_LINK_MODE_10baseT1BRR_Full_BIT, - ETHTOOL_LINK_MODE_1000baseT_Full_BIT, - ETHTOOL_LINK_MODE_1000baseX_Full_BIT, - ETHTOOL_LINK_MODE_1000baseT_Half_BIT, - ETHTOOL_LINK_MODE_100baseT_Full_BIT, - ETHTOOL_LINK_MODE_100baseT_Half_BIT, - ETHTOOL_LINK_MODE_10baseT_Full_BIT, - ETHTOOL_LINK_MODE_10baseT_Half_BIT -}; +static const int bcm54811_linkmodes[] = { ETHTOOL_LINK_MODE_100baseT1_Full_BIT, + ETHTOOL_LINK_MODE_10baseT1BRR_Full_BIT, + ETHTOOL_LINK_MODE_1000baseT_Full_BIT, + ETHTOOL_LINK_MODE_1000baseX_Full_BIT, + ETHTOOL_LINK_MODE_1000baseT_Half_BIT, + ETHTOOL_LINK_MODE_100baseT_Full_BIT, + ETHTOOL_LINK_MODE_100baseT_Half_BIT, + ETHTOOL_LINK_MODE_10baseT_Full_BIT, + ETHTOOL_LINK_MODE_10baseT_Half_BIT }; /* Long-Distance Signaling (BroadR-Reach mode aneg) relevant linkmode bits */ -static const int lds_br_bits[] = { - ETHTOOL_LINK_MODE_Autoneg_BIT, - ETHTOOL_LINK_MODE_Pause_BIT, - ETHTOOL_LINK_MODE_Asym_Pause_BIT, - ETHTOOL_LINK_MODE_10baseT1BRR_Full_BIT, - ETHTOOL_LINK_MODE_100baseT1_Full_BIT -}; +static const int lds_br_bits[] = { ETHTOOL_LINK_MODE_Autoneg_BIT, + ETHTOOL_LINK_MODE_Pause_BIT, + ETHTOOL_LINK_MODE_Asym_Pause_BIT, + ETHTOOL_LINK_MODE_10baseT1BRR_Full_BIT, + ETHTOOL_LINK_MODE_100baseT1_Full_BIT }; static bool bcm54xx_phy_can_wakeup(struct phy_device *phydev) { @@ -84,8 +80,7 @@ static int bcm54xx_config_clock_delay(struct phy_device *phydev) /* Enable RGMII RXC-RXD skew */ val |= MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN; } - rc = bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC, - val); + rc = bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC, val); if (rc < 0) return rc; @@ -123,6 +118,11 @@ static int bcm54210e_config_init(struct phy_device *phydev) return 0; } +static int bcm54213pe_config_init(struct phy_device *phydev) +{ + return bcm54210e_config_init(phydev); +} + static int bcm54612e_config_init(struct phy_device *phydev) { int reg; @@ -159,8 +159,7 @@ static int bcm54616s_config_init(struct phy_device *phydev) return val; val &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_EN; val |= MII_BCM54XX_AUXCTL_MISC_WREN; - rc = bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC, - val); + rc = bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC, val); if (rc < 0) return rc; @@ -181,8 +180,8 @@ static int bcm54616s_config_init(struct phy_device *phydev) /* Select proper interface mode */ val &= ~BCM54XX_SHD_INTF_SEL_MASK; val |= phydev->interface == PHY_INTERFACE_MODE_SGMII ? - BCM54XX_SHD_INTF_SEL_SGMII : - BCM54XX_SHD_INTF_SEL_GBIC; + BCM54XX_SHD_INTF_SEL_SGMII : + BCM54XX_SHD_INTF_SEL_GBIC; rc = bcm_phy_write_shadow(phydev, BCM54XX_SHD_MODE, val); if (rc < 0) return rc; @@ -209,7 +208,7 @@ static int bcm50610_a0_workaround(struct phy_device *phydev) err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_AADJ1CH0, MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN | - MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF); + MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF); if (err < 0) return err; @@ -239,10 +238,9 @@ static int bcm54xx_phydsp_config(struct phy_device *phydev) int err, err2; /* Enable the SMDSP clock */ - err = bcm54xx_auxctl_write(phydev, - MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL, + err = bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL, MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA | - MII_BCM54XX_AUXCTL_ACTL_TX_6DB); + MII_BCM54XX_AUXCTL_ACTL_TX_6DB); if (err < 0) return err; @@ -274,8 +272,7 @@ static int bcm54xx_phydsp_config(struct phy_device *phydev) error: /* Disable the SMDSP clock */ - err2 = bcm54xx_auxctl_write(phydev, - MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL, + err2 = bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL, MII_BCM54XX_AUXCTL_ACTL_TX_6DB); /* Return the first error reported. */ @@ -293,6 +290,7 @@ static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev) phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM50610) || phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM50610M) || phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM54210E) || + phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM54213PE) || phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM54810) || phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM54811))) return; @@ -328,8 +326,10 @@ static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev) val |= BCM54XX_SHD_SCR3_DLLAPD_DIS; if (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY) { - if (phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM54210E) || - phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM54810) || + if (phy_id_compare_model(phydev->drv->phy_id, + PHY_ID_BCM54210E) || + phy_id_compare_model(phydev->drv->phy_id, + PHY_ID_BCM54810) || phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM54811)) val |= BCM54XX_SHD_SCR3_RXCTXC_DIS; else @@ -386,8 +386,8 @@ static int bcm5481x_set_brrmode(struct phy_device *phydev, bool on) else reg &= ~BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN; - err = bcm_phy_write_exp(phydev, - BCM54810_EXP_BROADREACH_LRE_MISC_CTL, reg); + err = bcm_phy_write_exp(phydev, BCM54810_EXP_BROADREACH_LRE_MISC_CTL, + reg); if (err) return err; @@ -444,11 +444,10 @@ static int bcm54811_config_init(struct phy_device *phydev) /* Also writing Reserved bits 6:5 because the documentation requires * them to be written to 0b11 */ - err = bcm54xx_auxctl_write(phydev, - MII_BCM54XX_AUXCTL_SHDWSEL_MISC, - MII_BCM54XX_AUXCTL_MISC_WREN | - aux_rgmii_en | - MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RSVD); + err = bcm54xx_auxctl_write( + phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC, + MII_BCM54XX_AUXCTL_MISC_WREN | aux_rgmii_en | + MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RSVD); if (err < 0) return err; @@ -458,6 +457,9 @@ static int bcm54811_config_init(struct phy_device *phydev) static int bcm54xx_config_init(struct phy_device *phydev) { int reg, err, val; + u32 led_modes[] = { BCM_LED_MULTICOLOR_LINK_ACT, + BCM_LED_MULTICOLOR_LINK }; + struct device_node *np = phydev->mdio.dev.of_node; reg = phy_read(phydev, MII_BCM54XX_ECR); if (reg < 0) @@ -470,8 +472,7 @@ static int bcm54xx_config_init(struct phy_device *phydev) return err; /* Unmask events we are interested in. */ - reg = ~(MII_BCM54XX_INT_DUPLEX | - MII_BCM54XX_INT_SPEED | + reg = ~(MII_BCM54XX_INT_DUPLEX | MII_BCM54XX_INT_SPEED | MII_BCM54XX_INT_LINK); err = phy_write(phydev, MII_BCM54XX_IMR, reg); if (err < 0) @@ -482,6 +483,9 @@ static int bcm54xx_config_init(struct phy_device *phydev) (phydev->dev_flags & PHY_BRCM_CLEAR_RGMII_MODE)) bcm_phy_write_shadow(phydev, BCM54XX_SHD_RGMII_MODE, 0); + if (of_property_read_bool(np, "brcm,powerdown-enable")) + phydev->dev_flags |= PHY_BRCM_AUTO_PWRDWN_ENABLE; + bcm54xx_adjust_rxrefclk(phydev); switch (phydev->drv->phy_id & PHY_ID_MATCH_MODEL_MASK) { @@ -495,6 +499,9 @@ static int bcm54xx_config_init(struct phy_device *phydev) case PHY_ID_BCM54612E: err = bcm54612e_config_init(phydev); break; + case PHY_ID_BCM54213PE: + err = bcm54213pe_config_init(phydev); + break; case PHY_ID_BCM54616S: err = bcm54616s_config_init(phydev); break; @@ -503,9 +510,8 @@ static int bcm54xx_config_init(struct phy_device *phydev) val = bcm_phy_read_exp(phydev, BCM54810_EXP_BROADREACH_LRE_MISC_CTL); val &= ~BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN; - err = bcm_phy_write_exp(phydev, - BCM54810_EXP_BROADREACH_LRE_MISC_CTL, - val); + err = bcm_phy_write_exp( + phydev, BCM54810_EXP_BROADREACH_LRE_MISC_CTL, val); break; case PHY_ID_BCM54811: err = bcm54811_config_init(phydev); @@ -516,22 +522,27 @@ static int bcm54xx_config_init(struct phy_device *phydev) bcm54xx_phydsp_config(phydev); + of_property_read_u32_array(np, "led-modes", led_modes, 2); + /* For non-SFP setups, encode link speed into LED1 and LED3 pair * (green/amber). - * Also flash these two LEDs on activity. This means configuring - * them for MULTICOLOR and encoding link/activity into them. * Don't do this for devices on an SFP module, since some of these * use the LED outputs to control the SFP LOS signal, and changing * these settings will cause LOS to malfunction. */ if (!phy_on_sfp(phydev)) { val = BCM54XX_SHD_LEDS1_LED1(BCM_LED_SRC_MULTICOLOR1) | - BCM54XX_SHD_LEDS1_LED3(BCM_LED_SRC_MULTICOLOR1); + BCM54XX_SHD_LEDS1_LED3(BCM_LED_SRC_MULTICOLOR1); bcm_phy_write_shadow(phydev, BCM54XX_SHD_LEDS1, val); + /* BCM54210PE controls two extra LEDs with the next register. + * Make them shadow the first pair of LEDs - useful on CM4 which + * uses LED3 for ETH_LEDY instead of LED1. + */ + bcm_phy_write_shadow(phydev, BCM54XX_SHD_LEDS1 + 1, val); val = BCM_LED_MULTICOLOR_IN_PHASE | - BCM54XX_SHD_LEDS1_LED1(BCM_LED_MULTICOLOR_LINK_ACT) | - BCM54XX_SHD_LEDS1_LED3(BCM_LED_MULTICOLOR_LINK_ACT); + BCM54XX_SHD_LEDS1_LED1(led_modes[0]) | + BCM54XX_SHD_LEDS1_LED3(led_modes[1]); bcm_phy_write_exp(phydev, BCM_EXP_MULTICOLOR, val); } @@ -664,7 +675,6 @@ static int bcm54810_write_mmd(struct phy_device *phydev, int devnum, u16 regnum, return -EOPNOTSUPP; } - /** * bcm5481x_read_abilities - read PHY abilities from LRESR or Clause 22 * (BMSR) registers, based on whether the PHY is in BroadR-Reach or IEEE mode @@ -715,14 +725,11 @@ static int bcm5481x_read_abilities(struct phy_device *phydev) aneg = val & LRESR_LDSABILITY; linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, - phydev->supported, - aneg); + phydev->supported, aneg); linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT1_Full_BIT, - phydev->supported, - val & LRESR_100_1PAIR); + phydev->supported, val & LRESR_100_1PAIR); linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT1BRR_Full_BIT, - phydev->supported, - val & LRESR_10_1PAIR); + phydev->supported, val & LRESR_10_1PAIR); return 0; } @@ -738,9 +745,8 @@ static int bcm5481x_config_delay_swap(struct phy_device *phydev) if (of_property_read_bool(np, "enet-phy-lane-swap")) { /* Lane Swap - Undocumented register...magic! */ - int ret = bcm_phy_write_exp(phydev, - MII_BCM54XX_EXP_SEL_ER + 0x9, - 0x11B); + int ret = bcm_phy_write_exp( + phydev, MII_BCM54XX_EXP_SEL_ER + 0x9, 0x11B); if (ret < 0) return ret; } @@ -905,13 +911,10 @@ static int brcm_fet_config_init(struct phy_device *phydev) /* Unmask events we are interested in and mask interrupts globally. */ if (phydev->drv->phy_id == PHY_ID_BCM5221) - reg = MII_BRCM_FET_IR_ENABLE | - MII_BRCM_FET_IR_MASK; + reg = MII_BRCM_FET_IR_ENABLE | MII_BRCM_FET_IR_MASK; else - reg = MII_BRCM_FET_IR_DUPLEX_EN | - MII_BRCM_FET_IR_SPEED_EN | - MII_BRCM_FET_IR_LINK_EN | - MII_BRCM_FET_IR_ENABLE | + reg = MII_BRCM_FET_IR_DUPLEX_EN | MII_BRCM_FET_IR_SPEED_EN | + MII_BRCM_FET_IR_LINK_EN | MII_BRCM_FET_IR_ENABLE | MII_BRCM_FET_IR_MASK; err = phy_write(phydev, MII_BRCM_FET_INTREG, reg); @@ -1095,9 +1098,9 @@ static int bcm5221_config_aneg(struct phy_device *phydev) return 0; } - return phy_modify(phydev, BCM5221_AEGSR, BCM5221_AEGSR_MDIX_MAN_SWAP | - BCM5221_AEGSR_MDIX_DIS, - val); + return phy_modify(phydev, BCM5221_AEGSR, + BCM5221_AEGSR_MDIX_MAN_SWAP | BCM5221_AEGSR_MDIX_DIS, + val); } static int bcm5221_read_status(struct phy_device *phydev) @@ -1316,8 +1319,7 @@ static int lre_read_lpa(struct phy_device *phydev) phydev->lp_advertising, lrelpa & LRELPA_PAUSE_ASYM); linkmode_mod_bit(ETHTOOL_LINK_MODE_Pause_BIT, - phydev->lp_advertising, - lrelpa & LRELPA_PAUSE); + phydev->lp_advertising, lrelpa & LRELPA_PAUSE); linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT1_Full_BIT, phydev->lp_advertising, lrelpa & LRELPA_100_1PAIR); @@ -1416,8 +1418,7 @@ static int bcm54811_lre_read_status(struct phy_device *phydev) return err; /* why bother the PHY if nothing can have changed */ - if (phydev->autoneg == - AUTONEG_ENABLE && old_link && phydev->link) + if (phydev->autoneg == AUTONEG_ENABLE && old_link && phydev->link) return 0; phydev->speed = SPEED_UNKNOWN; @@ -1447,304 +1448,339 @@ static int bcm54811_read_status(struct phy_device *phydev) struct bcm54xx_phy_priv *priv = phydev->priv; if (priv->brr_mode) - return bcm54811_lre_read_status(phydev); + return bcm54811_lre_read_status(phydev); return genphy_read_status(phydev); } static struct phy_driver broadcom_drivers[] = { -{ - PHY_ID_MATCH_MODEL(PHY_ID_BCM5411), - .name = "Broadcom BCM5411", - /* PHY_GBIT_FEATURES */ - .get_sset_count = bcm_phy_get_sset_count, - .get_strings = bcm_phy_get_strings, - .get_stats = bcm54xx_get_stats, - .probe = bcm54xx_phy_probe, - .config_init = bcm54xx_config_init, - .config_intr = bcm_phy_config_intr, - .handle_interrupt = bcm_phy_handle_interrupt, - .link_change_notify = bcm54xx_link_change_notify, -}, { - PHY_ID_MATCH_MODEL(PHY_ID_BCM5421), - .name = "Broadcom BCM5421", - /* PHY_GBIT_FEATURES */ - .get_sset_count = bcm_phy_get_sset_count, - .get_strings = bcm_phy_get_strings, - .get_stats = bcm54xx_get_stats, - .probe = bcm54xx_phy_probe, - .config_init = bcm54xx_config_init, - .config_intr = bcm_phy_config_intr, - .handle_interrupt = bcm_phy_handle_interrupt, - .link_change_notify = bcm54xx_link_change_notify, -}, { - PHY_ID_MATCH_MODEL(PHY_ID_BCM54210E), - .name = "Broadcom BCM54210E", - /* PHY_GBIT_FEATURES */ - .flags = PHY_ALWAYS_CALL_SUSPEND, - .get_sset_count = bcm_phy_get_sset_count, - .get_strings = bcm_phy_get_strings, - .get_stats = bcm54xx_get_stats, - .probe = bcm54xx_phy_probe, - .config_init = bcm54xx_config_init, - .config_intr = bcm_phy_config_intr, - .handle_interrupt = bcm_phy_handle_interrupt, - .link_change_notify = bcm54xx_link_change_notify, - .suspend = bcm54xx_suspend, - .resume = bcm54xx_resume, - .get_wol = bcm54xx_phy_get_wol, - .set_wol = bcm54xx_phy_set_wol, - .led_brightness_set = bcm_phy_led_brightness_set, -}, { - PHY_ID_MATCH_MODEL(PHY_ID_BCM5461), - .name = "Broadcom BCM5461", - /* PHY_GBIT_FEATURES */ - .get_sset_count = bcm_phy_get_sset_count, - .get_strings = bcm_phy_get_strings, - .get_stats = bcm54xx_get_stats, - .probe = bcm54xx_phy_probe, - .config_init = bcm54xx_config_init, - .config_intr = bcm_phy_config_intr, - .handle_interrupt = bcm_phy_handle_interrupt, - .link_change_notify = bcm54xx_link_change_notify, - .led_brightness_set = bcm_phy_led_brightness_set, -}, { - PHY_ID_MATCH_MODEL(PHY_ID_BCM54612E), - .name = "Broadcom BCM54612E", - /* PHY_GBIT_FEATURES */ - .get_sset_count = bcm_phy_get_sset_count, - .get_strings = bcm_phy_get_strings, - .get_stats = bcm54xx_get_stats, - .probe = bcm54xx_phy_probe, - .config_init = bcm54xx_config_init, - .config_intr = bcm_phy_config_intr, - .handle_interrupt = bcm_phy_handle_interrupt, - .link_change_notify = bcm54xx_link_change_notify, - .led_brightness_set = bcm_phy_led_brightness_set, - .suspend = bcm54xx_suspend, - .resume = bcm54xx_resume, -}, { - PHY_ID_MATCH_MODEL(PHY_ID_BCM54616S), - .name = "Broadcom BCM54616S", - /* PHY_GBIT_FEATURES */ - .soft_reset = genphy_soft_reset, - .config_init = bcm54xx_config_init, - .config_aneg = bcm54616s_config_aneg, - .config_intr = bcm_phy_config_intr, - .handle_interrupt = bcm_phy_handle_interrupt, - .read_status = bcm54616s_read_status, - .probe = bcm54616s_probe, - .link_change_notify = bcm54xx_link_change_notify, - .led_brightness_set = bcm_phy_led_brightness_set, -}, { - PHY_ID_MATCH_MODEL(PHY_ID_BCM5464), - .name = "Broadcom BCM5464", - /* PHY_GBIT_FEATURES */ - .get_sset_count = bcm_phy_get_sset_count, - .get_strings = bcm_phy_get_strings, - .get_stats = bcm54xx_get_stats, - .probe = bcm54xx_phy_probe, - .config_init = bcm54xx_config_init, - .config_intr = bcm_phy_config_intr, - .handle_interrupt = bcm_phy_handle_interrupt, - .suspend = genphy_suspend, - .resume = genphy_resume, - .link_change_notify = bcm54xx_link_change_notify, - .led_brightness_set = bcm_phy_led_brightness_set, -}, { - PHY_ID_MATCH_MODEL(PHY_ID_BCM5481), - .name = "Broadcom BCM5481", - /* PHY_GBIT_FEATURES */ - .get_sset_count = bcm_phy_get_sset_count, - .get_strings = bcm_phy_get_strings, - .get_stats = bcm54xx_get_stats, - .probe = bcm54xx_phy_probe, - .config_init = bcm54xx_config_init, - .config_aneg = bcm5481_config_aneg, - .config_intr = bcm_phy_config_intr, - .handle_interrupt = bcm_phy_handle_interrupt, - .link_change_notify = bcm54xx_link_change_notify, - .led_brightness_set = bcm_phy_led_brightness_set, -}, { - PHY_ID_MATCH_MODEL(PHY_ID_BCM54810), - .name = "Broadcom BCM54810", - /* PHY_GBIT_FEATURES */ - .get_sset_count = bcm_phy_get_sset_count, - .get_strings = bcm_phy_get_strings, - .get_stats = bcm54xx_get_stats, - .probe = bcm54xx_phy_probe, - .read_mmd = bcm54810_read_mmd, - .write_mmd = bcm54810_write_mmd, - .config_init = bcm54xx_config_init, - .config_aneg = bcm5481_config_aneg, - .config_intr = bcm_phy_config_intr, - .handle_interrupt = bcm_phy_handle_interrupt, - .suspend = bcm54xx_suspend, - .resume = bcm54xx_resume, - .link_change_notify = bcm54xx_link_change_notify, - .led_brightness_set = bcm_phy_led_brightness_set, -}, { - PHY_ID_MATCH_MODEL(PHY_ID_BCM54811), - .name = "Broadcom BCM54811", - /* PHY_GBIT_FEATURES */ - .get_sset_count = bcm_phy_get_sset_count, - .get_strings = bcm_phy_get_strings, - .get_stats = bcm54xx_get_stats, - .probe = bcm54xx_phy_probe, - .config_init = bcm54xx_config_init, - .config_aneg = bcm54811_config_aneg, - .config_intr = bcm_phy_config_intr, - .handle_interrupt = bcm_phy_handle_interrupt, - .read_status = bcm54811_read_status, - .get_features = bcm5481x_read_abilities, - .suspend = bcm54xx_suspend, - .resume = bcm54xx_resume, - .link_change_notify = bcm54xx_link_change_notify, - .led_brightness_set = bcm_phy_led_brightness_set, -}, { - PHY_ID_MATCH_MODEL(PHY_ID_BCM5482), - .name = "Broadcom BCM5482", - /* PHY_GBIT_FEATURES */ - .get_sset_count = bcm_phy_get_sset_count, - .get_strings = bcm_phy_get_strings, - .get_stats = bcm54xx_get_stats, - .probe = bcm54xx_phy_probe, - .config_init = bcm54xx_config_init, - .config_intr = bcm_phy_config_intr, - .handle_interrupt = bcm_phy_handle_interrupt, - .link_change_notify = bcm54xx_link_change_notify, - .led_brightness_set = bcm_phy_led_brightness_set, -}, { - PHY_ID_MATCH_MODEL(PHY_ID_BCM50610), - .name = "Broadcom BCM50610", - /* PHY_GBIT_FEATURES */ - .get_sset_count = bcm_phy_get_sset_count, - .get_strings = bcm_phy_get_strings, - .get_stats = bcm54xx_get_stats, - .probe = bcm54xx_phy_probe, - .config_init = bcm54xx_config_init, - .config_intr = bcm_phy_config_intr, - .handle_interrupt = bcm_phy_handle_interrupt, - .link_change_notify = bcm54xx_link_change_notify, - .suspend = bcm54xx_suspend, - .resume = bcm54xx_resume, - .led_brightness_set = bcm_phy_led_brightness_set, -}, { - PHY_ID_MATCH_MODEL(PHY_ID_BCM50610M), - .name = "Broadcom BCM50610M", - /* PHY_GBIT_FEATURES */ - .get_sset_count = bcm_phy_get_sset_count, - .get_strings = bcm_phy_get_strings, - .get_stats = bcm54xx_get_stats, - .probe = bcm54xx_phy_probe, - .config_init = bcm54xx_config_init, - .config_intr = bcm_phy_config_intr, - .handle_interrupt = bcm_phy_handle_interrupt, - .link_change_notify = bcm54xx_link_change_notify, - .suspend = bcm54xx_suspend, - .resume = bcm54xx_resume, - .led_brightness_set = bcm_phy_led_brightness_set, -}, { - PHY_ID_MATCH_MODEL(PHY_ID_BCM57780), - .name = "Broadcom BCM57780", - /* PHY_GBIT_FEATURES */ - .get_sset_count = bcm_phy_get_sset_count, - .get_strings = bcm_phy_get_strings, - .get_stats = bcm54xx_get_stats, - .probe = bcm54xx_phy_probe, - .config_init = bcm54xx_config_init, - .config_intr = bcm_phy_config_intr, - .handle_interrupt = bcm_phy_handle_interrupt, - .link_change_notify = bcm54xx_link_change_notify, - .led_brightness_set = bcm_phy_led_brightness_set, -}, { - PHY_ID_MATCH_MODEL(PHY_ID_BCMAC131), - .name = "Broadcom BCMAC131", - /* PHY_BASIC_FEATURES */ - .config_init = brcm_fet_config_init, - .config_intr = brcm_fet_config_intr, - .handle_interrupt = brcm_fet_handle_interrupt, - .suspend = brcm_fet_suspend, - .resume = brcm_fet_config_init, -}, { - PHY_ID_MATCH_MODEL(PHY_ID_BCM5241), - .name = "Broadcom BCM5241", - /* PHY_BASIC_FEATURES */ - .config_init = brcm_fet_config_init, - .config_intr = brcm_fet_config_intr, - .handle_interrupt = brcm_fet_handle_interrupt, - .suspend = brcm_fet_suspend, - .resume = brcm_fet_config_init, -}, { - PHY_ID_MATCH_MODEL(PHY_ID_BCM5221), - .name = "Broadcom BCM5221", - /* PHY_BASIC_FEATURES */ - .config_init = brcm_fet_config_init, - .config_intr = brcm_fet_config_intr, - .handle_interrupt = brcm_fet_handle_interrupt, - .suspend = brcm_fet_suspend, - .resume = brcm_fet_config_init, - .config_aneg = bcm5221_config_aneg, - .read_status = bcm5221_read_status, -}, { - PHY_ID_MATCH_MODEL(PHY_ID_BCM5395), - .name = "Broadcom BCM5395", - .flags = PHY_IS_INTERNAL, - /* PHY_GBIT_FEATURES */ - .get_sset_count = bcm_phy_get_sset_count, - .get_strings = bcm_phy_get_strings, - .get_stats = bcm54xx_get_stats, - .probe = bcm54xx_phy_probe, - .link_change_notify = bcm54xx_link_change_notify, - .led_brightness_set = bcm_phy_led_brightness_set, -}, { - PHY_ID_MATCH_MODEL(PHY_ID_BCM53125), - .name = "Broadcom BCM53125", - .flags = PHY_IS_INTERNAL, - /* PHY_GBIT_FEATURES */ - .get_sset_count = bcm_phy_get_sset_count, - .get_strings = bcm_phy_get_strings, - .get_stats = bcm54xx_get_stats, - .probe = bcm54xx_phy_probe, - .config_init = bcm54xx_config_init, - .config_intr = bcm_phy_config_intr, - .handle_interrupt = bcm_phy_handle_interrupt, - .link_change_notify = bcm54xx_link_change_notify, - .led_brightness_set = bcm_phy_led_brightness_set, -}, { - PHY_ID_MATCH_MODEL(PHY_ID_BCM53128), - .name = "Broadcom BCM53128", - .flags = PHY_IS_INTERNAL, - /* PHY_GBIT_FEATURES */ - .get_sset_count = bcm_phy_get_sset_count, - .get_strings = bcm_phy_get_strings, - .get_stats = bcm54xx_get_stats, - .probe = bcm54xx_phy_probe, - .config_init = bcm54xx_config_init, - .config_intr = bcm_phy_config_intr, - .handle_interrupt = bcm_phy_handle_interrupt, - .link_change_notify = bcm54xx_link_change_notify, - .led_brightness_set = bcm_phy_led_brightness_set, -}, { - PHY_ID_MATCH_MODEL(PHY_ID_BCM89610), - .name = "Broadcom BCM89610", - /* PHY_GBIT_FEATURES */ - .get_sset_count = bcm_phy_get_sset_count, - .get_strings = bcm_phy_get_strings, - .get_stats = bcm54xx_get_stats, - .probe = bcm54xx_phy_probe, - .config_init = bcm54xx_config_init, - .config_intr = bcm_phy_config_intr, - .handle_interrupt = bcm_phy_handle_interrupt, - .link_change_notify = bcm54xx_link_change_notify, -} }; + { + PHY_ID_MATCH_MODEL(PHY_ID_BCM5411), + .name = "Broadcom BCM5411", + /* PHY_GBIT_FEATURES */ + .get_sset_count = bcm_phy_get_sset_count, + .get_strings = bcm_phy_get_strings, + .get_stats = bcm54xx_get_stats, + .probe = bcm54xx_phy_probe, + .config_init = bcm54xx_config_init, + .config_intr = bcm_phy_config_intr, + .handle_interrupt = bcm_phy_handle_interrupt, + .link_change_notify = bcm54xx_link_change_notify, + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_BCM5421), + .name = "Broadcom BCM5421", + /* PHY_GBIT_FEATURES */ + .get_sset_count = bcm_phy_get_sset_count, + .get_strings = bcm_phy_get_strings, + .get_stats = bcm54xx_get_stats, + .probe = bcm54xx_phy_probe, + .config_init = bcm54xx_config_init, + .config_intr = bcm_phy_config_intr, + .handle_interrupt = bcm_phy_handle_interrupt, + .link_change_notify = bcm54xx_link_change_notify, + }, + { + PHY_ID_MATCH_EXACT(PHY_ID_BCM54210E), + .name = "Broadcom BCM54210E", + /* PHY_GBIT_FEATURES */ + .flags = PHY_ALWAYS_CALL_SUSPEND, + .get_sset_count = bcm_phy_get_sset_count, + .get_strings = bcm_phy_get_strings, + .get_stats = bcm54xx_get_stats, + .probe = bcm54xx_phy_probe, + .config_init = bcm54xx_config_init, + .config_intr = bcm_phy_config_intr, + .handle_interrupt = bcm_phy_handle_interrupt, + .link_change_notify = bcm54xx_link_change_notify, + .suspend = bcm54xx_suspend, + .resume = bcm54xx_resume, + .get_wol = bcm54xx_phy_get_wol, + .set_wol = bcm54xx_phy_set_wol, + .led_brightness_set = bcm_phy_led_brightness_set, + }, + { + PHY_ID_MATCH_EXACT(PHY_ID_BCM54213PE), + .name = "Broadcom BCM54213PE", + /* PHY_GBIT_FEATURES */ + .get_sset_count = bcm_phy_get_sset_count, + .get_strings = bcm_phy_get_strings, + .get_stats = bcm54xx_get_stats, + .probe = bcm54xx_phy_probe, + .config_init = bcm54xx_config_init, + .config_intr = bcm_phy_config_intr, + .suspend = bcm54xx_suspend, + .resume = bcm54xx_resume, + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_BCM5461), + .name = "Broadcom BCM5461", + /* PHY_GBIT_FEATURES */ + .get_sset_count = bcm_phy_get_sset_count, + .get_strings = bcm_phy_get_strings, + .get_stats = bcm54xx_get_stats, + .probe = bcm54xx_phy_probe, + .config_init = bcm54xx_config_init, + .config_intr = bcm_phy_config_intr, + .handle_interrupt = bcm_phy_handle_interrupt, + .link_change_notify = bcm54xx_link_change_notify, + .led_brightness_set = bcm_phy_led_brightness_set, + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_BCM54612E), + .name = "Broadcom BCM54612E", + /* PHY_GBIT_FEATURES */ + .get_sset_count = bcm_phy_get_sset_count, + .get_strings = bcm_phy_get_strings, + .get_stats = bcm54xx_get_stats, + .probe = bcm54xx_phy_probe, + .config_init = bcm54xx_config_init, + .config_intr = bcm_phy_config_intr, + .handle_interrupt = bcm_phy_handle_interrupt, + .link_change_notify = bcm54xx_link_change_notify, + .led_brightness_set = bcm_phy_led_brightness_set, + .suspend = bcm54xx_suspend, + .resume = bcm54xx_resume, + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_BCM54616S), + .name = "Broadcom BCM54616S", + /* PHY_GBIT_FEATURES */ + .soft_reset = genphy_soft_reset, + .config_init = bcm54xx_config_init, + .config_aneg = bcm54616s_config_aneg, + .config_intr = bcm_phy_config_intr, + .handle_interrupt = bcm_phy_handle_interrupt, + .read_status = bcm54616s_read_status, + .probe = bcm54616s_probe, + .link_change_notify = bcm54xx_link_change_notify, + .led_brightness_set = bcm_phy_led_brightness_set, + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_BCM5464), + .name = "Broadcom BCM5464", + /* PHY_GBIT_FEATURES */ + .get_sset_count = bcm_phy_get_sset_count, + .get_strings = bcm_phy_get_strings, + .get_stats = bcm54xx_get_stats, + .probe = bcm54xx_phy_probe, + .config_init = bcm54xx_config_init, + .config_intr = bcm_phy_config_intr, + .handle_interrupt = bcm_phy_handle_interrupt, + .suspend = genphy_suspend, + .resume = genphy_resume, + .link_change_notify = bcm54xx_link_change_notify, + .led_brightness_set = bcm_phy_led_brightness_set, + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_BCM5481), + .name = "Broadcom BCM5481", + /* PHY_GBIT_FEATURES */ + .get_sset_count = bcm_phy_get_sset_count, + .get_strings = bcm_phy_get_strings, + .get_stats = bcm54xx_get_stats, + .probe = bcm54xx_phy_probe, + .config_init = bcm54xx_config_init, + .config_aneg = bcm5481_config_aneg, + .config_intr = bcm_phy_config_intr, + .handle_interrupt = bcm_phy_handle_interrupt, + .link_change_notify = bcm54xx_link_change_notify, + .led_brightness_set = bcm_phy_led_brightness_set, + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_BCM54810), + .name = "Broadcom BCM54810", + /* PHY_GBIT_FEATURES */ + .get_sset_count = bcm_phy_get_sset_count, + .get_strings = bcm_phy_get_strings, + .get_stats = bcm54xx_get_stats, + .probe = bcm54xx_phy_probe, + .read_mmd = bcm54810_read_mmd, + .write_mmd = bcm54810_write_mmd, + .config_init = bcm54xx_config_init, + .config_aneg = bcm5481_config_aneg, + .config_intr = bcm_phy_config_intr, + .handle_interrupt = bcm_phy_handle_interrupt, + .suspend = bcm54xx_suspend, + .resume = bcm54xx_resume, + .link_change_notify = bcm54xx_link_change_notify, + .led_brightness_set = bcm_phy_led_brightness_set, + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_BCM54811), + .name = "Broadcom BCM54811", + /* PHY_GBIT_FEATURES */ + .get_sset_count = bcm_phy_get_sset_count, + .get_strings = bcm_phy_get_strings, + .get_stats = bcm54xx_get_stats, + .probe = bcm54xx_phy_probe, + .config_init = bcm54xx_config_init, + .config_aneg = bcm54811_config_aneg, + .config_intr = bcm_phy_config_intr, + .handle_interrupt = bcm_phy_handle_interrupt, + .read_status = bcm54811_read_status, + .get_features = bcm5481x_read_abilities, + .suspend = bcm54xx_suspend, + .resume = bcm54xx_resume, + .link_change_notify = bcm54xx_link_change_notify, + .led_brightness_set = bcm_phy_led_brightness_set, + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_BCM5482), + .name = "Broadcom BCM5482", + /* PHY_GBIT_FEATURES */ + .get_sset_count = bcm_phy_get_sset_count, + .get_strings = bcm_phy_get_strings, + .get_stats = bcm54xx_get_stats, + .probe = bcm54xx_phy_probe, + .config_init = bcm54xx_config_init, + .config_intr = bcm_phy_config_intr, + .handle_interrupt = bcm_phy_handle_interrupt, + .link_change_notify = bcm54xx_link_change_notify, + .led_brightness_set = bcm_phy_led_brightness_set, + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_BCM50610), + .name = "Broadcom BCM50610", + /* PHY_GBIT_FEATURES */ + .get_sset_count = bcm_phy_get_sset_count, + .get_strings = bcm_phy_get_strings, + .get_stats = bcm54xx_get_stats, + .probe = bcm54xx_phy_probe, + .config_init = bcm54xx_config_init, + .config_intr = bcm_phy_config_intr, + .handle_interrupt = bcm_phy_handle_interrupt, + .link_change_notify = bcm54xx_link_change_notify, + .suspend = bcm54xx_suspend, + .resume = bcm54xx_resume, + .led_brightness_set = bcm_phy_led_brightness_set, + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_BCM50610M), + .name = "Broadcom BCM50610M", + /* PHY_GBIT_FEATURES */ + .get_sset_count = bcm_phy_get_sset_count, + .get_strings = bcm_phy_get_strings, + .get_stats = bcm54xx_get_stats, + .probe = bcm54xx_phy_probe, + .config_init = bcm54xx_config_init, + .config_intr = bcm_phy_config_intr, + .handle_interrupt = bcm_phy_handle_interrupt, + .link_change_notify = bcm54xx_link_change_notify, + .suspend = bcm54xx_suspend, + .resume = bcm54xx_resume, + .led_brightness_set = bcm_phy_led_brightness_set, + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_BCM57780), + .name = "Broadcom BCM57780", + /* PHY_GBIT_FEATURES */ + .get_sset_count = bcm_phy_get_sset_count, + .get_strings = bcm_phy_get_strings, + .get_stats = bcm54xx_get_stats, + .probe = bcm54xx_phy_probe, + .config_init = bcm54xx_config_init, + .config_intr = bcm_phy_config_intr, + .handle_interrupt = bcm_phy_handle_interrupt, + .link_change_notify = bcm54xx_link_change_notify, + .led_brightness_set = bcm_phy_led_brightness_set, + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_BCMAC131), + .name = "Broadcom BCMAC131", + /* PHY_BASIC_FEATURES */ + .config_init = brcm_fet_config_init, + .config_intr = brcm_fet_config_intr, + .handle_interrupt = brcm_fet_handle_interrupt, + .suspend = brcm_fet_suspend, + .resume = brcm_fet_config_init, + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_BCM5241), + .name = "Broadcom BCM5241", + /* PHY_BASIC_FEATURES */ + .config_init = brcm_fet_config_init, + .config_intr = brcm_fet_config_intr, + .handle_interrupt = brcm_fet_handle_interrupt, + .suspend = brcm_fet_suspend, + .resume = brcm_fet_config_init, + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_BCM5221), + .name = "Broadcom BCM5221", + /* PHY_BASIC_FEATURES */ + .config_init = brcm_fet_config_init, + .config_intr = brcm_fet_config_intr, + .handle_interrupt = brcm_fet_handle_interrupt, + .suspend = brcm_fet_suspend, + .resume = brcm_fet_config_init, + .config_aneg = bcm5221_config_aneg, + .read_status = bcm5221_read_status, + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_BCM5395), + .name = "Broadcom BCM5395", + .flags = PHY_IS_INTERNAL, + /* PHY_GBIT_FEATURES */ + .get_sset_count = bcm_phy_get_sset_count, + .get_strings = bcm_phy_get_strings, + .get_stats = bcm54xx_get_stats, + .probe = bcm54xx_phy_probe, + .link_change_notify = bcm54xx_link_change_notify, + .led_brightness_set = bcm_phy_led_brightness_set, + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_BCM53125), + .name = "Broadcom BCM53125", + .flags = PHY_IS_INTERNAL, + /* PHY_GBIT_FEATURES */ + .get_sset_count = bcm_phy_get_sset_count, + .get_strings = bcm_phy_get_strings, + .get_stats = bcm54xx_get_stats, + .probe = bcm54xx_phy_probe, + .config_init = bcm54xx_config_init, + .config_intr = bcm_phy_config_intr, + .handle_interrupt = bcm_phy_handle_interrupt, + .link_change_notify = bcm54xx_link_change_notify, + .led_brightness_set = bcm_phy_led_brightness_set, + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_BCM53128), + .name = "Broadcom BCM53128", + .flags = PHY_IS_INTERNAL, + /* PHY_GBIT_FEATURES */ + .get_sset_count = bcm_phy_get_sset_count, + .get_strings = bcm_phy_get_strings, + .get_stats = bcm54xx_get_stats, + .probe = bcm54xx_phy_probe, + .config_init = bcm54xx_config_init, + .config_intr = bcm_phy_config_intr, + .handle_interrupt = bcm_phy_handle_interrupt, + .link_change_notify = bcm54xx_link_change_notify, + .led_brightness_set = bcm_phy_led_brightness_set, + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_BCM89610), + .name = "Broadcom BCM89610", + /* PHY_GBIT_FEATURES */ + .get_sset_count = bcm_phy_get_sset_count, + .get_strings = bcm_phy_get_strings, + .get_stats = bcm54xx_get_stats, + .probe = bcm54xx_phy_probe, + .config_init = bcm54xx_config_init, + .config_intr = bcm_phy_config_intr, + .handle_interrupt = bcm_phy_handle_interrupt, + .link_change_notify = bcm54xx_link_change_notify, + } +}; module_phy_driver(broadcom_drivers); static const struct mdio_device_id __maybe_unused broadcom_tbl[] = { { PHY_ID_MATCH_MODEL(PHY_ID_BCM5411) }, { PHY_ID_MATCH_MODEL(PHY_ID_BCM5421) }, - { PHY_ID_MATCH_MODEL(PHY_ID_BCM54210E) }, + { PHY_ID_MATCH_EXACT(PHY_ID_BCM54210E) }, + { PHY_ID_MATCH_EXACT(PHY_ID_BCM54213PE) }, { PHY_ID_MATCH_MODEL(PHY_ID_BCM5461) }, { PHY_ID_MATCH_MODEL(PHY_ID_BCM54612E) }, { PHY_ID_MATCH_MODEL(PHY_ID_BCM54616S) }, @@ -1763,7 +1799,7 @@ static const struct mdio_device_id __maybe_unused broadcom_tbl[] = { { PHY_ID_MATCH_MODEL(PHY_ID_BCM53125) }, { PHY_ID_MATCH_MODEL(PHY_ID_BCM53128) }, { PHY_ID_MATCH_MODEL(PHY_ID_BCM89610) }, - { } + {} }; MODULE_DEVICE_TABLE(mdio, broadcom_tbl); diff --git a/drivers/net/phy/microchip.c b/drivers/net/phy/microchip.c index dc8634e7bcbe..53f6f7c89237 100644 --- a/drivers/net/phy/microchip.c +++ b/drivers/net/phy/microchip.c @@ -198,6 +198,7 @@ static int lan88xx_probe(struct phy_device *phydev) struct device *dev = &phydev->mdio.dev; struct lan88xx_priv *priv; u32 led_modes[4]; + u32 downshift_after = 0; int len; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); @@ -227,6 +228,32 @@ static int lan88xx_probe(struct phy_device *phydev) return -EINVAL; } + if (!of_property_read_u32(dev->of_node, + "microchip,downshift-after", + &downshift_after)) { + u32 mask = LAN78XX_PHY_CTRL3_DOWNSHIFT_CTRL_MASK; + u32 val= LAN78XX_PHY_CTRL3_AUTO_DOWNSHIFT; + + switch (downshift_after) { + case 2: val |= LAN78XX_PHY_CTRL3_DOWNSHIFT_CTRL_2; + break; + case 3: val |= LAN78XX_PHY_CTRL3_DOWNSHIFT_CTRL_3; + break; + case 4: val |= LAN78XX_PHY_CTRL3_DOWNSHIFT_CTRL_4; + break; + case 5: val |= LAN78XX_PHY_CTRL3_DOWNSHIFT_CTRL_5; + break; + case 0: // Disable completely + mask = LAN78XX_PHY_CTRL3_AUTO_DOWNSHIFT; + val = 0; + break; + default: + return -EINVAL; + } + (void)phy_modify_paged(phydev, 1, LAN78XX_PHY_CTRL3, + mask, val); + } + /* these values can be used to identify internal PHY */ priv->chip_id = phy_read_mmd(phydev, 3, LAN88XX_MMD3_CHIP_ID); priv->chip_rev = phy_read_mmd(phydev, 3, LAN88XX_MMD3_CHIP_REV); diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index 00397a807393..bb28ea01449a 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -596,6 +596,20 @@ static int lan78xx_alloc_tx_resources(struct lan78xx_net *dev) dev->n_tx_urbs, dev->tx_urb_size, dev); } +/* TSO seems to be having some issue with Selective Acknowledge (SACK) that + * results in lost data never being retransmitted. + * Disable it by default now, but adds a module parameter to enable it for + * debug purposes (the full cause is not currently understood). + */ +static bool enable_tso; +module_param(enable_tso, bool, 0644); +MODULE_PARM_DESC(enable_tso, "Enables TCP segmentation offload"); + +#define INT_URB_MICROFRAMES_PER_MS 8 +static int int_urb_interval_ms = 8; +module_param(int_urb_interval_ms, int, 0); +MODULE_PARM_DESC(int_urb_interval_ms, "Override usb interrupt urb interval"); + static int lan78xx_read_reg(struct lan78xx_net *dev, u32 index, u32 *data) { u32 *buf; @@ -1918,6 +1932,7 @@ static const struct ethtool_ops lan78xx_ethtool_ops = { .set_link_ksettings = lan78xx_set_link_ksettings, .get_regs_len = lan78xx_get_regs_len, .get_regs = lan78xx_get_regs, + .get_ts_info = ethtool_op_get_ts_info, }; static int lan78xx_init_mac_address(struct lan78xx_net *dev) @@ -3294,6 +3309,10 @@ static int lan78xx_reset(struct lan78xx_net *dev) buf |= HW_CFG_CLK125_EN_; buf |= HW_CFG_REFCLK25_EN_; + /* If no valid EEPROM and no valid OTP, enable the LEDs by default */ + if (!has_eeprom && !has_otp) + buf |= HW_CFG_LED0_EN_ | HW_CFG_LED1_EN_; + ret = lan78xx_write_reg(dev, HW_CFG, buf); if (ret < 0) return ret; @@ -3756,8 +3775,14 @@ static int lan78xx_bind(struct lan78xx_net *dev, struct usb_interface *intf) if (DEFAULT_RX_CSUM_ENABLE) dev->net->features |= NETIF_F_RXCSUM; - if (DEFAULT_TSO_CSUM_ENABLE) - dev->net->features |= NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_SG; + if (DEFAULT_TSO_CSUM_ENABLE) { + dev->net->features |= NETIF_F_SG; + /* Use module parameter to control TCP segmentation offload as + * it appears to cause issues. + */ + if (enable_tso) + dev->net->features |= NETIF_F_TSO | NETIF_F_TSO6; + } if (DEFAULT_VLAN_RX_OFFLOAD) dev->net->features |= NETIF_F_HW_VLAN_CTAG_RX; @@ -4720,7 +4745,13 @@ static int lan78xx_probe(struct usb_interface *intf, if (ret < 0) goto out4; - period = ep_intr->desc.bInterval; + if (int_urb_interval_ms <= 0) + period = ep_intr->desc.bInterval; + else + period = int_urb_interval_ms * INT_URB_MICROFRAMES_PER_MS; + + netif_notice(dev, probe, netdev, "int urb period %d\n", period); + maxp = usb_maxpacket(dev->udev, dev->pipe_intr); dev->urb_intr = usb_alloc_urb(0, GFP_KERNEL); diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index de733e0488bf..b83a9840e3c6 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -82,6 +82,14 @@ static bool turbo_mode = true; module_param(turbo_mode, bool, 0644); MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction"); +static int packetsize = 2560; +module_param(packetsize, int, 0644); +MODULE_PARM_DESC(packetsize, "Override the RX URB packet size"); + +static char *macaddr = ":"; +module_param(macaddr, charp, 0); +MODULE_PARM_DESC(macaddr, "MAC address"); + static int __must_check smsc95xx_read_reg(struct usbnet *dev, u32 index, u32 *data) { @@ -862,6 +870,21 @@ static int smsc95xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) return phy_mii_ioctl(netdev->phydev, rq, cmd); } +/* Check the macaddr module parameter for a MAC address */ +static int smsc95xx_macaddr_param(struct usbnet *dev, struct net_device *nd) +{ + u8 mtbl[ETH_ALEN]; + + if (mac_pton(macaddr, mtbl)) { + netif_dbg(dev, ifup, dev->net, + "Overriding MAC address with: %pM\n", mtbl); + dev_addr_mod(nd, 0, mtbl, ETH_ALEN); + return 0; + } else { + return -EINVAL; + } +} + static void smsc95xx_init_mac_address(struct usbnet *dev) { u8 addr[ETH_ALEN]; @@ -885,6 +908,14 @@ static void smsc95xx_init_mac_address(struct usbnet *dev) } } + /* Check module parameters */ + if (smsc95xx_macaddr_param(dev, dev->net) == 0) { + if (is_valid_ether_addr(dev->net->dev_addr)) { + netif_dbg(dev, ifup, dev->net, "MAC address read from module parameter\n"); + return; + } + } + /* no useful static MAC address found. generate a random one */ eth_hw_addr_random(dev->net); netif_dbg(dev, ifup, dev->net, "MAC address set to eth_random_addr\n"); @@ -993,13 +1024,13 @@ static int smsc95xx_reset(struct usbnet *dev) if (!turbo_mode) { burst_cap = 0; - dev->rx_urb_size = MAX_SINGLE_PACKET_SIZE; + dev->rx_urb_size = packetsize ? packetsize : MAX_SINGLE_PACKET_SIZE; } else if (dev->udev->speed == USB_SPEED_HIGH) { - burst_cap = DEFAULT_HS_BURST_CAP_SIZE / HS_USB_PKT_SIZE; - dev->rx_urb_size = DEFAULT_HS_BURST_CAP_SIZE; + dev->rx_urb_size = packetsize ? packetsize : DEFAULT_HS_BURST_CAP_SIZE; + burst_cap = dev->rx_urb_size / HS_USB_PKT_SIZE; } else { - burst_cap = DEFAULT_FS_BURST_CAP_SIZE / FS_USB_PKT_SIZE; - dev->rx_urb_size = DEFAULT_FS_BURST_CAP_SIZE; + dev->rx_urb_size = packetsize ? packetsize : DEFAULT_FS_BURST_CAP_SIZE; + burst_cap = dev->rx_urb_size / FS_USB_PKT_SIZE; } netif_dbg(dev, ifup, dev->net, "rx_urb_size=%ld\n", |
