X-Git-Url: https://bbs.cooldavid.org/git/?p=jme.git;a=blobdiff_plain;f=jme.c;h=5b441b75e138fd1f432f72d186311943fb908e8f;hp=d446fdb89f683ce1d0ec8d65dd4e30d6dfbd1e01;hb=a452eef142039455edcfbbd790d18377f4720e83;hpb=e4610a83adbbae6dae4ca88a7285a83d58e8e0cb diff --git a/jme.c b/jme.c index d446fdb..5b441b7 100644 --- a/jme.c +++ b/jme.c @@ -160,6 +160,67 @@ jme_setup_wakeup_frame(struct jme_adapter *jme, } } +static inline void +jme_mac_rxclk_off(struct jme_adapter *jme) +{ + jme->reg_gpreg1 |= GPREG1_RXCLKOFF; + jwrite32f(jme, JME_GPREG1, jme->reg_gpreg1); +} + +static inline void +jme_mac_rxclk_on(struct jme_adapter *jme) +{ + jme->reg_gpreg1 &= ~GPREG1_RXCLKOFF; + jwrite32f(jme, JME_GPREG1, jme->reg_gpreg1); +} + +static inline void +jme_mac_txclk_off(struct jme_adapter *jme) +{ + jme->reg_ghc &= ~(GHC_TO_CLK_SRC | GHC_TXMAC_CLK_SRC); + jwrite32f(jme, JME_GHC, jme->reg_ghc); +} + +static inline void +jme_mac_txclk_on(struct jme_adapter *jme) +{ + u32 speed = jme->reg_ghc & GHC_SPEED; + if (speed == GHC_SPEED_1000M) + jme->reg_ghc |= GHC_TO_CLK_GPHY | GHC_TXMAC_CLK_GPHY; + else + jme->reg_ghc |= GHC_TO_CLK_PCIE | GHC_TXMAC_CLK_PCIE; + jwrite32f(jme, JME_GHC, jme->reg_ghc); +} + +static inline void +jme_reset_ghc_speed(struct jme_adapter *jme) +{ + jme->reg_ghc &= ~(GHC_SPEED | GHC_DPX); + jwrite32f(jme, JME_GHC, jme->reg_ghc); +} + +static inline void +jme_reset_250A2_workaround(struct jme_adapter *jme) +{ + jme->reg_gpreg1 &= ~(GPREG1_HALFMODEPATCH | + GPREG1_RSSPATCH); + jwrite32(jme, JME_GPREG1, jme->reg_gpreg1); +} + +static inline void +jme_assert_ghc_reset(struct jme_adapter *jme) +{ + jme->reg_ghc |= GHC_SWRST; + jwrite32f(jme, JME_GHC, jme->reg_ghc); +} + +static inline void +jme_clear_ghc_reset(struct jme_adapter *jme) +{ + jme->reg_ghc &= ~GHC_SWRST; + jwrite32f(jme, JME_GHC, jme->reg_ghc); +} + static inline void jme_reset_mac_processor(struct jme_adapter *jme) { @@ -168,9 +229,24 @@ jme_reset_mac_processor(struct jme_adapter *jme) u32 gpreg0; int i; - jwrite32(jme, JME_GHC, jme->reg_ghc | GHC_SWRST); - udelay(2); - jwrite32(jme, JME_GHC, jme->reg_ghc); + jme_reset_ghc_speed(jme); + jme_reset_250A2_workaround(jme); + + jme_mac_rxclk_on(jme); + jme_mac_txclk_on(jme); + udelay(1); + jme_assert_ghc_reset(jme); + udelay(1); + jme_mac_rxclk_off(jme); + jme_mac_txclk_off(jme); + udelay(1); + jme_clear_ghc_reset(jme); + udelay(1); + jme_mac_rxclk_on(jme); + jme_mac_txclk_on(jme); + udelay(1); + jme_mac_rxclk_off(jme); + jme_mac_txclk_off(jme); jwrite32(jme, JME_RXDBA_LO, 0x00000000); jwrite32(jme, JME_RXDBA_HI, 0x00000000); @@ -190,14 +266,6 @@ jme_reset_mac_processor(struct jme_adapter *jme) else gpreg0 = GPREG0_DEFAULT; jwrite32(jme, JME_GPREG0, gpreg0); - jwrite32(jme, JME_GPREG1, GPREG1_DEFAULT); -} - -static inline void -jme_reset_ghc_speed(struct jme_adapter *jme) -{ - jme->reg_ghc &= ~(GHC_SPEED_1000M | GHC_DPX); - jwrite32(jme, JME_GHC, jme->reg_ghc); } static inline void @@ -336,13 +404,13 @@ jme_linkstat_from_phy(struct jme_adapter *jme) } static inline void -jme_set_phyfifoa(struct jme_adapter *jme) +jme_set_phyfifo_5level(struct jme_adapter *jme) { jme_mdio_write(jme->dev, jme->mii_if.phy_id, 27, 0x0004); } static inline void -jme_set_phyfifob(struct jme_adapter *jme) +jme_set_phyfifo_8level(struct jme_adapter *jme) { jme_mdio_write(jme->dev, jme->mii_if.phy_id, 27, 0x0000); } @@ -351,7 +419,7 @@ static int jme_check_link(struct net_device *netdev, int testonly) { struct jme_adapter *jme = netdev_priv(netdev); - u32 phylink, ghc, cnt = JME_SPDRSV_TIMEOUT, bmcr, gpreg1; + u32 phylink, cnt = JME_SPDRSV_TIMEOUT, bmcr; char linkmsg[64]; int rc = 0; @@ -414,23 +482,21 @@ jme_check_link(struct net_device *netdev, int testonly) jme->phylink = phylink; - ghc = jme->reg_ghc & ~(GHC_SPEED | GHC_DPX | - GHC_TO_CLK_PCIE | GHC_TXMAC_CLK_PCIE | - GHC_TO_CLK_GPHY | GHC_TXMAC_CLK_GPHY); + /* + * The speed/duplex setting of jme->reg_ghc already cleared + * by jme_reset_mac_processor() + */ switch (phylink & PHY_LINK_SPEED_MASK) { case PHY_LINK_SPEED_10M: - ghc |= GHC_SPEED_10M | - GHC_TO_CLK_PCIE | GHC_TXMAC_CLK_PCIE; + jme->reg_ghc |= GHC_SPEED_10M; strcat(linkmsg, "10 Mbps, "); break; case PHY_LINK_SPEED_100M: - ghc |= GHC_SPEED_100M | - GHC_TO_CLK_PCIE | GHC_TXMAC_CLK_PCIE; + jme->reg_ghc |= GHC_SPEED_100M; strcat(linkmsg, "100 Mbps, "); break; case PHY_LINK_SPEED_1000M: - ghc |= GHC_SPEED_1000M | - GHC_TO_CLK_GPHY | GHC_TXMAC_CLK_GPHY; + jme->reg_ghc |= GHC_SPEED_1000M; strcat(linkmsg, "1000 Mbps, "); break; default: @@ -439,42 +505,40 @@ jme_check_link(struct net_device *netdev, int testonly) if (phylink & PHY_LINK_DUPLEX) { jwrite32(jme, JME_TXMCS, TXMCS_DEFAULT); - ghc |= GHC_DPX; + jwrite32(jme, JME_TXTRHD, TXTRHD_FULLDUPLEX); + jme->reg_ghc |= GHC_DPX; } else { jwrite32(jme, JME_TXMCS, TXMCS_DEFAULT | TXMCS_BACKOFF | TXMCS_CARRIERSENSE | TXMCS_COLLISION); - jwrite32(jme, JME_TXTRHD, TXTRHD_TXPEN | - ((0x2000 << TXTRHD_TXP_SHIFT) & TXTRHD_TXP) | - TXTRHD_TXREN | - ((8 << TXTRHD_TXRL_SHIFT) & TXTRHD_TXRL)); + jwrite32(jme, JME_TXTRHD, TXTRHD_HALFDUPLEX); } - gpreg1 = GPREG1_DEFAULT; + jwrite32(jme, JME_GHC, jme->reg_ghc); + if (is_buggy250(jme->pdev->device, jme->chiprev)) { + jme->reg_gpreg1 &= ~(GPREG1_HALFMODEPATCH | + GPREG1_RSSPATCH); if (!(phylink & PHY_LINK_DUPLEX)) - gpreg1 |= GPREG1_HALFMODEPATCH; + jme->reg_gpreg1 |= GPREG1_HALFMODEPATCH; switch (phylink & PHY_LINK_SPEED_MASK) { case PHY_LINK_SPEED_10M: - jme_set_phyfifoa(jme); - gpreg1 |= GPREG1_RSSPATCH; + jme_set_phyfifo_8level(jme); + jme->reg_gpreg1 |= GPREG1_RSSPATCH; break; case PHY_LINK_SPEED_100M: - jme_set_phyfifob(jme); - gpreg1 |= GPREG1_RSSPATCH; + jme_set_phyfifo_5level(jme); + jme->reg_gpreg1 |= GPREG1_RSSPATCH; break; case PHY_LINK_SPEED_1000M: - jme_set_phyfifoa(jme); + jme_set_phyfifo_8level(jme); break; default: break; } } - - jwrite32(jme, JME_GPREG1, gpreg1); - jwrite32(jme, JME_GHC, ghc); - jme->reg_ghc = ghc; + jwrite32(jme, JME_GPREG1, jme->reg_gpreg1); strcat(linkmsg, (phylink & PHY_LINK_DUPLEX) ? "Full-Duplex, " : @@ -613,10 +677,14 @@ jme_enable_tx_engine(struct jme_adapter *jme) * Enable TX Engine */ wmb(); - jwrite32(jme, JME_TXCS, jme->reg_txcs | + jwrite32f(jme, JME_TXCS, jme->reg_txcs | TXCS_SELECT_QUEUE0 | TXCS_ENABLE); + /* + * Start clock for TX MAC Processor + */ + jme_mac_txclk_on(jme); } static inline void @@ -651,6 +719,11 @@ jme_disable_tx_engine(struct jme_adapter *jme) if (!i) pr_err("Disable TX engine timeout\n"); + + /* + * Stop clock for TX MAC Processor + */ + jme_mac_txclk_off(jme); } static void @@ -825,16 +898,22 @@ jme_enable_rx_engine(struct jme_adapter *jme) /* * Setup Unicast Filter */ + jme_set_unicastaddr(jme->dev); jme_set_multi(jme->dev); /* * Enable RX Engine */ wmb(); - jwrite32(jme, JME_RXCS, jme->reg_rxcs | + jwrite32f(jme, JME_RXCS, jme->reg_rxcs | RXCS_QUEUESEL_Q0 | RXCS_ENABLE | RXCS_QST); + + /* + * Start clock for RX MAC Processor + */ + jme_mac_rxclk_on(jme); } static inline void @@ -871,10 +950,40 @@ jme_disable_rx_engine(struct jme_adapter *jme) if (!i) pr_err("Disable RX engine timeout\n"); + /* + * Stop clock for RX MAC Processor + */ + jme_mac_rxclk_off(jme); +} + +static u16 +jme_udpsum(struct sk_buff *skb) +{ + u16 csum = 0xFFFFu; + + if (skb->len < (ETH_HLEN + sizeof(struct iphdr))) + return csum; + if (skb->protocol != htons(ETH_P_IP)) + return csum; + skb_set_network_header(skb, ETH_HLEN); + if ((ip_hdr(skb)->protocol != IPPROTO_UDP) || + (skb->len < (ETH_HLEN + + (ip_hdr(skb)->ihl << 2) + + sizeof(struct udphdr)))) { + skb_reset_network_header(skb); + return csum; + } + skb_set_transport_header(skb, + ETH_HLEN + (ip_hdr(skb)->ihl << 2)); + csum = udp_hdr(skb)->check; + skb_reset_transport_header(skb); + skb_reset_network_header(skb); + + return csum; } static int -jme_rxsum_ok(struct jme_adapter *jme, u16 flags) +jme_rxsum_ok(struct jme_adapter *jme, u16 flags, struct sk_buff *skb) { if (!(flags & (RXWBFLAG_TCPON | RXWBFLAG_UDPON | RXWBFLAG_IPV4))) return false; @@ -887,7 +996,7 @@ jme_rxsum_ok(struct jme_adapter *jme, u16 flags) } if (unlikely((flags & (RXWBFLAG_MF | RXWBFLAG_UDPON | RXWBFLAG_UDPCS)) - == RXWBFLAG_UDPON)) { + == RXWBFLAG_UDPON) && jme_udpsum(skb)) { if (flags & RXWBFLAG_IPV4) netif_err(jme, rx_err, jme->dev, "UDP Checksum error\n"); return false; @@ -935,7 +1044,7 @@ jme_alloc_and_feed_skb(struct jme_adapter *jme, int idx) skb_put(skb, framesize); skb->protocol = eth_type_trans(skb, jme->dev); - if (jme_rxsum_ok(jme, le16_to_cpu(rxdesc->descwb.flags))) + if (jme_rxsum_ok(jme, le16_to_cpu(rxdesc->descwb.flags), skb)) skb->ip_summed = CHECKSUM_UNNECESSARY; else skb_checksum_none_assert(skb); @@ -1207,7 +1316,6 @@ jme_link_change_tasklet(unsigned long arg) tasklet_disable(&jme->rxempty_task); if (netif_carrier_ok(netdev)) { - jme_reset_ghc_speed(jme); jme_disable_rx_engine(jme); jme_disable_tx_engine(jme); jme_reset_mac_processor(jme); @@ -1737,7 +1845,6 @@ jme_close(struct net_device *netdev) tasklet_disable(&jme->rxclean_task); tasklet_disable(&jme->rxempty_task); - jme_reset_ghc_speed(jme); jme_disable_rx_engine(jme); jme_disable_tx_engine(jme); jme_reset_mac_processor(jme); @@ -2034,27 +2141,34 @@ jme_start_xmit(struct sk_buff *skb, struct net_device *netdev) return NETDEV_TX_OK; } +static void +jme_set_unicastaddr(struct net_device *netdev) +{ + struct jme_adapter *jme = netdev_priv(netdev); + u32 val; + + val = (netdev->dev_addr[3] & 0xff) << 24 | + (netdev->dev_addr[2] & 0xff) << 16 | + (netdev->dev_addr[1] & 0xff) << 8 | + (netdev->dev_addr[0] & 0xff); + jwrite32(jme, JME_RXUMA_LO, val); + val = (netdev->dev_addr[5] & 0xff) << 8 | + (netdev->dev_addr[4] & 0xff); + jwrite32(jme, JME_RXUMA_HI, val); +} + static int jme_set_macaddr(struct net_device *netdev, void *p) { struct jme_adapter *jme = netdev_priv(netdev); struct sockaddr *addr = p; - u32 val; if (netif_running(netdev)) return -EBUSY; spin_lock_bh(&jme->macaddr_lock); memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - - val = (addr->sa_data[3] & 0xff) << 24 | - (addr->sa_data[2] & 0xff) << 16 | - (addr->sa_data[1] & 0xff) << 8 | - (addr->sa_data[0] & 0xff); - jwrite32(jme, JME_RXUMA_LO, val); - val = (addr->sa_data[5] & 0xff) << 8 | - (addr->sa_data[4] & 0xff); - jwrite32(jme, JME_RXUMA_HI, val); + jme_set_unicastaddr(netdev); spin_unlock_bh(&jme->macaddr_lock); return 0; @@ -2923,6 +3037,7 @@ jme_init_one(struct pci_dev *pdev, jme->reg_rxmcs = RXMCS_DEFAULT; jme->reg_txpfc = 0; jme->reg_pmcs = PMCS_MFEN; + jme->reg_gpreg1 = GPREG1_DEFAULT; set_bit(JME_FLAG_TXCSUM, &jme->flags); set_bit(JME_FLAG_TSO, &jme->flags); @@ -2979,7 +3094,7 @@ jme_init_one(struct pci_dev *pdev, jme->mii_if.mdio_write = jme_mdio_write; jme_clear_pm(jme); - jme_set_phyfifoa(jme); + jme_set_phyfifo_5level(jme); pci_read_config_byte(pdev, PCI_REVISION_ID, &jme->pcirev); if (!jme->fpgaver) jme_phy_init(jme); @@ -3078,7 +3193,6 @@ jme_suspend(struct pci_dev *pdev, pm_message_t state) jme_polling_mode(jme); jme_stop_pcc_timer(jme); - jme_reset_ghc_speed(jme); jme_disable_rx_engine(jme); jme_disable_tx_engine(jme); jme_reset_mac_processor(jme);