+ tw32_f(MAC_MODE, tp->mac_mode);
+ udelay(40);
+
+ tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
+
+ tp->link_config.active_speed = current_speed;
+ tp->link_config.active_duplex = current_duplex;
+
+ if (current_link_up != netif_carrier_ok(tp->dev)) {
+ if (current_link_up)
+ netif_carrier_on(tp->dev);
+ else {
+ netif_carrier_off(tp->dev);
+ tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT;
+ }
+ tg3_link_report(tp);
+ }
+ return err;
+}
+
+static void tg3_serdes_parallel_detect(struct tg3 *tp)
+{
+ if (tp->tg3_flags2 & TG3_FLG2_PHY_JUST_INITTED) {
+ /* Give autoneg time to complete. */
+ tp->tg3_flags2 &= ~TG3_FLG2_PHY_JUST_INITTED;
+ return;
+ }
+ if (!netif_carrier_ok(tp->dev) &&
+ (tp->link_config.autoneg == AUTONEG_ENABLE)) {
+ u32 bmcr;
+
+ tg3_readphy(tp, MII_BMCR, &bmcr);
+ if (bmcr & BMCR_ANENABLE) {
+ u32 phy1, phy2;
+
+ /* Select shadow register 0x1f */
+ tg3_writephy(tp, 0x1c, 0x7c00);
+ tg3_readphy(tp, 0x1c, &phy1);
+
+ /* Select expansion interrupt status register */
+ tg3_writephy(tp, 0x17, 0x0f01);
+ tg3_readphy(tp, 0x15, &phy2);
+ tg3_readphy(tp, 0x15, &phy2);
+
+ if ((phy1 & 0x10) && !(phy2 & 0x20)) {
+ /* We have signal detect and not receiving
+ * config code words, link is up by parallel
+ * detection.
+ */
+
+ bmcr &= ~BMCR_ANENABLE;
+ bmcr |= BMCR_SPEED1000 | BMCR_FULLDPLX;
+ tg3_writephy(tp, MII_BMCR, bmcr);
+ tp->tg3_flags2 |= TG3_FLG2_PARALLEL_DETECT;
+ }
+ }
+ }
+ else if (netif_carrier_ok(tp->dev) &&
+ (tp->link_config.autoneg == AUTONEG_ENABLE) &&
+ (tp->tg3_flags2 & TG3_FLG2_PARALLEL_DETECT)) {
+ u32 phy2;
+
+ /* Select expansion interrupt status register */
+ tg3_writephy(tp, 0x17, 0x0f01);
+ tg3_readphy(tp, 0x15, &phy2);
+ if (phy2 & 0x20) {
+ u32 bmcr;
+
+ /* Config code words received, turn on autoneg. */
+ tg3_readphy(tp, MII_BMCR, &bmcr);
+ tg3_writephy(tp, MII_BMCR, bmcr | BMCR_ANENABLE);
+
+ tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT;
+
+ }
+ }
+}
+
+static int tg3_setup_phy(struct tg3 *tp, int force_reset)
+{
+ int err;
+
+ if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
+ err = tg3_setup_fiber_phy(tp, force_reset);
+ } else if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) {
+ err = tg3_setup_fiber_mii_phy(tp, force_reset);
+ } else {
+ err = tg3_setup_copper_phy(tp, force_reset);
+ }
+
+ if (tp->link_config.active_speed == SPEED_1000 &&
+ tp->link_config.active_duplex == DUPLEX_HALF)
+ tw32(MAC_TX_LENGTHS,
+ ((2 << TX_LENGTHS_IPG_CRS_SHIFT) |
+ (6 << TX_LENGTHS_IPG_SHIFT) |
+ (0xff << TX_LENGTHS_SLOT_TIME_SHIFT)));
+ else
+ tw32(MAC_TX_LENGTHS,
+ ((2 << TX_LENGTHS_IPG_CRS_SHIFT) |
+ (6 << TX_LENGTHS_IPG_SHIFT) |
+ (32 << TX_LENGTHS_SLOT_TIME_SHIFT)));
+
+ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
+ if (netif_carrier_ok(tp->dev)) {
+ tw32(HOSTCC_STAT_COAL_TICKS,
+ tp->coal.stats_block_coalesce_usecs);
+ } else {
+ tw32(HOSTCC_STAT_COAL_TICKS, 0);
+ }
+ }
+
+ return err;
+}
+
+/* Tigon3 never reports partial packet sends. So we do not
+ * need special logic to handle SKBs that have not had all
+ * of their frags sent yet, like SunGEM does.
+ */
+static void tg3_tx(struct tg3 *tp)
+{
+ u32 hw_idx = tp->hw_status->idx[0].tx_consumer;
+ u32 sw_idx = tp->tx_cons;
+
+ while (sw_idx != hw_idx) {
+ struct tx_ring_info *ri = &tp->tx_buffers[sw_idx];
+ struct sk_buff *skb = ri->skb;
+ int i;
+
+ BUG_ON(skb == NULL);
+ pci_unmap_single(tp->pdev,
+ pci_unmap_addr(ri, mapping),
+ skb_headlen(skb),
+ PCI_DMA_TODEVICE);
+
+ ri->skb = NULL;
+
+ sw_idx = NEXT_TX(sw_idx);
+
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+ BUG_ON(sw_idx == hw_idx);
+
+ ri = &tp->tx_buffers[sw_idx];
+ BUG_ON(ri->skb != NULL);
+
+ pci_unmap_page(tp->pdev,
+ pci_unmap_addr(ri, mapping),
+ skb_shinfo(skb)->frags[i].size,
+ PCI_DMA_TODEVICE);
+
+ sw_idx = NEXT_TX(sw_idx);
+ }
+
+ dev_kfree_skb(skb);
+ }
+
+ tp->tx_cons = sw_idx;
+
+ if (unlikely(netif_queue_stopped(tp->dev))) {
+ spin_lock(&tp->tx_lock);
+ if (netif_queue_stopped(tp->dev) &&
+ (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH))
+ netif_wake_queue(tp->dev);
+ spin_unlock(&tp->tx_lock);
+ }
+}