diff options
Diffstat (limited to 'drivers/net/ethernet/realtek/r8169_main.c')
| -rw-r--r-- | drivers/net/ethernet/realtek/r8169_main.c | 238 | 
1 files changed, 116 insertions, 122 deletions
diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index 45147a1016be..4b19803a7dd0 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -30,6 +30,7 @@  #include <linux/ipv6.h>  #include <asm/unaligned.h>  #include <net/ip6_checksum.h> +#include <net/netdev_queues.h>  #include "r8169.h"  #include "r8169_firmware.h" @@ -68,6 +69,8 @@  #define NUM_RX_DESC	256	/* Number of Rx descriptor registers */  #define R8169_TX_RING_BYTES	(NUM_TX_DESC * sizeof(struct TxDesc))  #define R8169_RX_RING_BYTES	(NUM_RX_DESC * sizeof(struct RxDesc)) +#define R8169_TX_STOP_THRS	(MAX_SKB_FRAGS + 1) +#define R8169_TX_START_THRS	(2 * R8169_TX_STOP_THRS)  #define OCP_STD_PHY_BASE	0xa400 @@ -613,8 +616,13 @@ struct rtl8169_private {  		struct work_struct work;  	} wk; +	raw_spinlock_t config25_lock; +	raw_spinlock_t mac_ocp_lock; + +	raw_spinlock_t cfg9346_usage_lock; +	int cfg9346_usage_count; +  	unsigned supports_gmii:1; -	unsigned aspm_manageable:1;  	dma_addr_t counters_phys_addr;  	struct rtl8169_counters *counters;  	struct rtl8169_tc_offsets tc_offset; @@ -661,12 +669,22 @@ static inline struct device *tp_to_dev(struct rtl8169_private *tp)  static void rtl_lock_config_regs(struct rtl8169_private *tp)  { -	RTL_W8(tp, Cfg9346, Cfg9346_Lock); +	unsigned long flags; + +	raw_spin_lock_irqsave(&tp->cfg9346_usage_lock, flags); +	if (!--tp->cfg9346_usage_count) +		RTL_W8(tp, Cfg9346, Cfg9346_Lock); +	raw_spin_unlock_irqrestore(&tp->cfg9346_usage_lock, flags);  }  static void rtl_unlock_config_regs(struct rtl8169_private *tp)  { -	RTL_W8(tp, Cfg9346, Cfg9346_Unlock); +	unsigned long flags; + +	raw_spin_lock_irqsave(&tp->cfg9346_usage_lock, flags); +	if (!tp->cfg9346_usage_count++) +		RTL_W8(tp, Cfg9346, Cfg9346_Unlock); +	raw_spin_unlock_irqrestore(&tp->cfg9346_usage_lock, flags);  }  static void rtl_pci_commit(struct rtl8169_private *tp) @@ -675,6 +693,28 @@ static void rtl_pci_commit(struct rtl8169_private *tp)  	RTL_R8(tp, ChipCmd);  } +static void rtl_mod_config2(struct rtl8169_private *tp, u8 clear, u8 set) +{ +	unsigned long flags; +	u8 val; + +	raw_spin_lock_irqsave(&tp->config25_lock, flags); +	val = RTL_R8(tp, Config2); +	RTL_W8(tp, Config2, (val & ~clear) | set); +	raw_spin_unlock_irqrestore(&tp->config25_lock, flags); +} + +static void rtl_mod_config5(struct rtl8169_private *tp, u8 clear, u8 set) +{ +	unsigned long flags; +	u8 val; + +	raw_spin_lock_irqsave(&tp->config25_lock, flags); +	val = RTL_R8(tp, Config5); +	RTL_W8(tp, Config5, (val & ~clear) | set); +	raw_spin_unlock_irqrestore(&tp->config25_lock, flags); +} +  static bool rtl_is_8125(struct rtl8169_private *tp)  {  	return tp->mac_version >= RTL_GIGA_MAC_VER_61; @@ -847,7 +887,7 @@ static int r8168_phy_ocp_read(struct rtl8169_private *tp, u32 reg)  		(RTL_R32(tp, GPHY_OCP) & 0xffff) : -ETIMEDOUT;  } -static void r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data) +static void __r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)  {  	if (rtl_ocp_reg_failure(reg))  		return; @@ -855,7 +895,16 @@ static void r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)  	RTL_W32(tp, OCPDR, OCPAR_FLAG | (reg << 15) | data);  } -static u16 r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg) +static void r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data) +{ +	unsigned long flags; + +	raw_spin_lock_irqsave(&tp->mac_ocp_lock, flags); +	__r8168_mac_ocp_write(tp, reg, data); +	raw_spin_unlock_irqrestore(&tp->mac_ocp_lock, flags); +} + +static u16 __r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg)  {  	if (rtl_ocp_reg_failure(reg))  		return 0; @@ -865,12 +914,28 @@ static u16 r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg)  	return RTL_R32(tp, OCPDR);  } +static u16 r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg) +{ +	unsigned long flags; +	u16 val; + +	raw_spin_lock_irqsave(&tp->mac_ocp_lock, flags); +	val = __r8168_mac_ocp_read(tp, reg); +	raw_spin_unlock_irqrestore(&tp->mac_ocp_lock, flags); + +	return val; +} +  static void r8168_mac_ocp_modify(struct rtl8169_private *tp, u32 reg, u16 mask,  				 u16 set)  { -	u16 data = r8168_mac_ocp_read(tp, reg); +	unsigned long flags; +	u16 data; -	r8168_mac_ocp_write(tp, reg, (data & ~mask) | set); +	raw_spin_lock_irqsave(&tp->mac_ocp_lock, flags); +	data = __r8168_mac_ocp_read(tp, reg); +	__r8168_mac_ocp_write(tp, reg, (data & ~mask) | set); +	raw_spin_unlock_irqrestore(&tp->mac_ocp_lock, flags);  }  /* Work around a hw issue with RTL8168g PHY, the quirk disables @@ -1336,6 +1401,7 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)  		{ WAKE_MAGIC, Config3, MagicPacket }  	};  	unsigned int i, tmp = ARRAY_SIZE(cfg); +	unsigned long flags;  	u8 options;  	rtl_unlock_config_regs(tp); @@ -1354,12 +1420,14 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)  			r8168_mac_ocp_modify(tp, 0xc0b6, BIT(0), 0);  	} +	raw_spin_lock_irqsave(&tp->config25_lock, flags);  	for (i = 0; i < tmp; i++) {  		options = RTL_R8(tp, cfg[i].reg) & ~cfg[i].mask;  		if (wolopts & cfg[i].opt)  			options |= cfg[i].mask;  		RTL_W8(tp, cfg[i].reg, options);  	} +	raw_spin_unlock_irqrestore(&tp->config25_lock, flags);  	switch (tp->mac_version) {  	case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06: @@ -1371,10 +1439,10 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)  	case RTL_GIGA_MAC_VER_34:  	case RTL_GIGA_MAC_VER_37:  	case RTL_GIGA_MAC_VER_39 ... RTL_GIGA_MAC_VER_63: -		options = RTL_R8(tp, Config2) & ~PME_SIGNAL;  		if (wolopts) -			options |= PME_SIGNAL; -		RTL_W8(tp, Config2, options); +			rtl_mod_config2(tp, 0, PME_SIGNAL); +		else +			rtl_mod_config2(tp, PME_SIGNAL, 0);  		break;  	default:  		break; @@ -2675,10 +2743,12 @@ static void rtl_disable_exit_l1(struct rtl8169_private *tp)  static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)  { -	/* Don't enable ASPM in the chip if OS can't control ASPM */ -	if (enable && tp->aspm_manageable) { -		RTL_W8(tp, Config5, RTL_R8(tp, Config5) | ASPM_en); -		RTL_W8(tp, Config2, RTL_R8(tp, Config2) | ClkReqEn); +	if (tp->mac_version < RTL_GIGA_MAC_VER_32) +		return; + +	if (enable) { +		rtl_mod_config5(tp, 0, ASPM_en); +		rtl_mod_config2(tp, 0, ClkReqEn);  		switch (tp->mac_version) {  		case RTL_GIGA_MAC_VER_46 ... RTL_GIGA_MAC_VER_48: @@ -2701,11 +2771,9 @@ static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)  			break;  		} -		RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~ClkReqEn); -		RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~ASPM_en); +		rtl_mod_config2(tp, ClkReqEn, 0); +		rtl_mod_config5(tp, ASPM_en, 0);  	} - -	udelay(10);  }  static void rtl_set_fifo_size(struct rtl8169_private *tp, u16 rx_stat, @@ -2863,7 +2931,7 @@ static void rtl_hw_start_8168e_1(struct rtl8169_private *tp)  	RTL_W32(tp, MISC, RTL_R32(tp, MISC) | TXPLA_RST);  	RTL_W32(tp, MISC, RTL_R32(tp, MISC) & ~TXPLA_RST); -	RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~Spi_en); +	rtl_mod_config5(tp, Spi_en, 0);  }  static void rtl_hw_start_8168e_2(struct rtl8169_private *tp) @@ -2896,9 +2964,7 @@ static void rtl_hw_start_8168e_2(struct rtl8169_private *tp)  	RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) | PFM_EN);  	RTL_W32(tp, MISC, RTL_R32(tp, MISC) | PWM_EN); -	RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~Spi_en); - -	rtl_hw_aspm_clkreq_enable(tp, true); +	rtl_mod_config5(tp, Spi_en, 0);  }  static void rtl_hw_start_8168f(struct rtl8169_private *tp) @@ -2919,7 +2985,7 @@ static void rtl_hw_start_8168f(struct rtl8169_private *tp)  	RTL_W8(tp, MCU, RTL_R8(tp, MCU) & ~NOW_IS_OOB);  	RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) | PFM_EN);  	RTL_W32(tp, MISC, RTL_R32(tp, MISC) | PWM_EN); -	RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~Spi_en); +	rtl_mod_config5(tp, Spi_en, 0);  	rtl8168_config_eee_mac(tp);  } @@ -2989,11 +3055,7 @@ static void rtl_hw_start_8168g_1(struct rtl8169_private *tp)  	};  	rtl_hw_start_8168g(tp); - -	/* disable aspm and clock request before access ephy */ -	rtl_hw_aspm_clkreq_enable(tp, false);  	rtl_ephy_init(tp, e_info_8168g_1); -	rtl_hw_aspm_clkreq_enable(tp, true);  }  static void rtl_hw_start_8168g_2(struct rtl8169_private *tp) @@ -3011,9 +3073,6 @@ static void rtl_hw_start_8168g_2(struct rtl8169_private *tp)  	};  	rtl_hw_start_8168g(tp); - -	/* disable aspm and clock request before access ephy */ -	rtl_hw_aspm_clkreq_enable(tp, false);  	rtl_ephy_init(tp, e_info_8168g_2);  } @@ -3034,8 +3093,6 @@ static void rtl_hw_start_8411_2(struct rtl8169_private *tp)  	rtl_hw_start_8168g(tp); -	/* disable aspm and clock request before access ephy */ -	rtl_hw_aspm_clkreq_enable(tp, false);  	rtl_ephy_init(tp, e_info_8411_2);  	/* The following Realtek-provided magic fixes an issue with the RX unit @@ -3173,8 +3230,6 @@ static void rtl_hw_start_8411_2(struct rtl8169_private *tp)  	r8168_mac_ocp_write(tp, 0xFC32, 0x0C25);  	r8168_mac_ocp_write(tp, 0xFC34, 0x00A9);  	r8168_mac_ocp_write(tp, 0xFC36, 0x012D); - -	rtl_hw_aspm_clkreq_enable(tp, true);  }  static void rtl_hw_start_8168h_1(struct rtl8169_private *tp) @@ -3189,8 +3244,6 @@ static void rtl_hw_start_8168h_1(struct rtl8169_private *tp)  	};  	int rg_saw_cnt; -	/* disable aspm and clock request before access ephy */ -	rtl_hw_aspm_clkreq_enable(tp, false);  	rtl_ephy_init(tp, e_info_8168h_1);  	rtl_set_fifo_size(tp, 0x08, 0x10, 0x02, 0x06); @@ -3238,8 +3291,6 @@ static void rtl_hw_start_8168h_1(struct rtl8169_private *tp)  	r8168_mac_ocp_write(tp, 0xe63e, 0x0000);  	r8168_mac_ocp_write(tp, 0xc094, 0x0000);  	r8168_mac_ocp_write(tp, 0xc09e, 0x0000); - -	rtl_hw_aspm_clkreq_enable(tp, true);  }  static void rtl_hw_start_8168ep(struct rtl8169_private *tp) @@ -3278,8 +3329,6 @@ static void rtl_hw_start_8168ep_3(struct rtl8169_private *tp)  		{ 0x1e, 0x0000,	0x2000 },  	}; -	/* disable aspm and clock request before access ephy */ -	rtl_hw_aspm_clkreq_enable(tp, false);  	rtl_ephy_init(tp, e_info_8168ep_3);  	rtl_hw_start_8168ep(tp); @@ -3290,8 +3339,6 @@ static void rtl_hw_start_8168ep_3(struct rtl8169_private *tp)  	r8168_mac_ocp_modify(tp, 0xd3e2, 0x0fff, 0x0271);  	r8168_mac_ocp_modify(tp, 0xd3e4, 0x00ff, 0x0000);  	r8168_mac_ocp_modify(tp, 0xe860, 0x0000, 0x0080); - -	rtl_hw_aspm_clkreq_enable(tp, true);  }  static void rtl_hw_start_8117(struct rtl8169_private *tp) @@ -3303,9 +3350,6 @@ static void rtl_hw_start_8117(struct rtl8169_private *tp)  	int rg_saw_cnt;  	rtl8168ep_stop_cmac(tp); - -	/* disable aspm and clock request before access ephy */ -	rtl_hw_aspm_clkreq_enable(tp, false);  	rtl_ephy_init(tp, e_info_8117);  	rtl_set_fifo_size(tp, 0x08, 0x10, 0x02, 0x06); @@ -3355,8 +3399,6 @@ static void rtl_hw_start_8117(struct rtl8169_private *tp)  	/* firmware is for MAC only */  	r8169_apply_firmware(tp); - -	rtl_hw_aspm_clkreq_enable(tp, true);  }  static void rtl_hw_start_8102e_1(struct rtl8169_private *tp) @@ -3479,8 +3521,6 @@ static void rtl_hw_start_8402(struct rtl8169_private *tp)  static void rtl_hw_start_8106(struct rtl8169_private *tp)  { -	rtl_hw_aspm_clkreq_enable(tp, false); -  	/* Force LAN exit from ASPM if Rx/Tx are not idle */  	RTL_W32(tp, FuncEvent, RTL_R32(tp, FuncEvent) | 0x002800); @@ -3497,7 +3537,6 @@ static void rtl_hw_start_8106(struct rtl8169_private *tp)  	rtl_eri_write(tp, 0x1b0, ERIAR_MASK_0011, 0x0000);  	rtl_pcie_state_l2l3_disable(tp); -	rtl_hw_aspm_clkreq_enable(tp, true);  }  DECLARE_RTL_COND(rtl_mac_ocp_e00e_cond) @@ -3585,13 +3624,8 @@ static void rtl_hw_start_8125a_2(struct rtl8169_private *tp)  	};  	rtl_set_def_aspm_entry_latency(tp); - -	/* disable aspm and clock request before access ephy */ -	rtl_hw_aspm_clkreq_enable(tp, false);  	rtl_ephy_init(tp, e_info_8125a_2); -  	rtl_hw_start_8125_common(tp); -	rtl_hw_aspm_clkreq_enable(tp, true);  }  static void rtl_hw_start_8125b(struct rtl8169_private *tp) @@ -3606,12 +3640,8 @@ static void rtl_hw_start_8125b(struct rtl8169_private *tp)  	};  	rtl_set_def_aspm_entry_latency(tp); -	rtl_hw_aspm_clkreq_enable(tp, false); -  	rtl_ephy_init(tp, e_info_8125b);  	rtl_hw_start_8125_common(tp); - -	rtl_hw_aspm_clkreq_enable(tp, true);  }  static void rtl_hw_config(struct rtl8169_private *tp) @@ -3707,7 +3737,8 @@ static void rtl_hw_start_8169(struct rtl8169_private *tp)  static void rtl_hw_start(struct  rtl8169_private *tp)  {  	rtl_unlock_config_regs(tp); - +	/* disable aspm and clock request before ephy access */ +	rtl_hw_aspm_clkreq_enable(tp, false);  	RTL_W16(tp, CPlusCmd, tp->cp_cmd);  	if (tp->mac_version <= RTL_GIGA_MAC_VER_06) @@ -3718,6 +3749,7 @@ static void rtl_hw_start(struct  rtl8169_private *tp)  		rtl_hw_start_8168(tp);  	rtl_enable_exit_l1(tp); +	rtl_hw_aspm_clkreq_enable(tp, true);  	rtl_set_rx_max_size(tp);  	rtl_set_rx_tx_desc_registers(tp);  	rtl_lock_config_regs(tp); @@ -4133,13 +4165,9 @@ static bool rtl8169_tso_csum_v2(struct rtl8169_private *tp,  	return true;  } -static bool rtl_tx_slots_avail(struct rtl8169_private *tp) +static unsigned int rtl_tx_slots_avail(struct rtl8169_private *tp)  { -	unsigned int slots_avail = READ_ONCE(tp->dirty_tx) + NUM_TX_DESC -					- READ_ONCE(tp->cur_tx); - -	/* A skbuff with nr_frags needs nr_frags+1 entries in the tx queue */ -	return slots_avail > MAX_SKB_FRAGS; +	return READ_ONCE(tp->dirty_tx) + NUM_TX_DESC - READ_ONCE(tp->cur_tx);  }  /* Versions RTL8102e and from RTL8168c onwards support csum_v2 */ @@ -4216,27 +4244,10 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,  	WRITE_ONCE(tp->cur_tx, tp->cur_tx + frags + 1); -	stop_queue = !rtl_tx_slots_avail(tp); -	if (unlikely(stop_queue)) { -		/* Avoid wrongly optimistic queue wake-up: rtl_tx thread must -		 * not miss a ring update when it notices a stopped queue. -		 */ -		smp_wmb(); -		netif_stop_queue(dev); -		/* Sync with rtl_tx: -		 * - publish queue status and cur_tx ring index (write barrier) -		 * - refresh dirty_tx ring index (read barrier). -		 * May the current thread have a pessimistic view of the ring -		 * status and forget to wake up queue, a racing rtl_tx thread -		 * can't. -		 */ -		smp_mb__after_atomic(); -		if (rtl_tx_slots_avail(tp)) -			netif_start_queue(dev); -		door_bell = true; -	} - -	if (door_bell) +	stop_queue = !netif_subqueue_maybe_stop(dev, 0, rtl_tx_slots_avail(tp), +						R8169_TX_STOP_THRS, +						R8169_TX_START_THRS); +	if (door_bell || stop_queue)  		rtl8169_doorbell(tp);  	return NETDEV_TX_OK; @@ -4360,19 +4371,12 @@ static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp,  	}  	if (tp->dirty_tx != dirty_tx) { -		netdev_completed_queue(dev, pkts_compl, bytes_compl);  		dev_sw_netstats_tx_add(dev, pkts_compl, bytes_compl); +		WRITE_ONCE(tp->dirty_tx, dirty_tx); -		/* Sync with rtl8169_start_xmit: -		 * - publish dirty_tx ring index (write barrier) -		 * - refresh cur_tx ring index and queue status (read barrier) -		 * May the current thread miss the stopped queue condition, -		 * a racing xmit thread can only have a right view of the -		 * ring status. -		 */ -		smp_store_mb(tp->dirty_tx, dirty_tx); -		if (netif_queue_stopped(dev) && rtl_tx_slots_avail(tp)) -			netif_wake_queue(dev); +		netif_subqueue_completed_wake(dev, 0, pkts_compl, bytes_compl, +					      rtl_tx_slots_avail(tp), +					      R8169_TX_START_THRS);  		/*  		 * 8168 hack: TxPoll requests are lost when the Tx packets are  		 * too close. Let's kick an extra TxPoll request when a burst @@ -4510,6 +4514,10 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)  	}  	if (napi_schedule_prep(&tp->napi)) { +		rtl_unlock_config_regs(tp); +		rtl_hw_aspm_clkreq_enable(tp, false); +		rtl_lock_config_regs(tp); +  		rtl_irq_disable(tp);  		__napi_schedule(&tp->napi);  	} @@ -4569,9 +4577,14 @@ static int rtl8169_poll(struct napi_struct *napi, int budget)  	work_done = rtl_rx(dev, tp, budget); -	if (work_done < budget && napi_complete_done(napi, work_done)) +	if (work_done < budget && napi_complete_done(napi, work_done)) {  		rtl_irq_enable(tp); +		rtl_unlock_config_regs(tp); +		rtl_hw_aspm_clkreq_enable(tp, true); +		rtl_lock_config_regs(tp); +	} +  	return work_done;  } @@ -5145,16 +5158,6 @@ done:  	rtl_rar_set(tp, mac_addr);  } -/* register is set if system vendor successfully tested ASPM 1.2 */ -static bool rtl_aspm_is_safe(struct rtl8169_private *tp) -{ -	if (tp->mac_version >= RTL_GIGA_MAC_VER_61 && -	    r8168_mac_ocp_read(tp, 0xc0b2) & 0xf) -		return true; - -	return false; -} -  static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  {  	struct rtl8169_private *tp; @@ -5176,6 +5179,10 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  	tp->eee_adv = -1;  	tp->ocp_base = OCP_STD_PHY_BASE; +	raw_spin_lock_init(&tp->cfg9346_usage_lock); +	raw_spin_lock_init(&tp->config25_lock); +	raw_spin_lock_init(&tp->mac_ocp_lock); +  	dev->tstats = devm_netdev_alloc_pcpu_stats(&pdev->dev,  						   struct pcpu_sw_netstats);  	if (!dev->tstats) @@ -5222,19 +5229,6 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  	tp->mac_version = chipset; -	/* Disable ASPM L1 as that cause random device stop working -	 * problems as well as full system hangs for some PCIe devices users. -	 * Chips from RTL8168h partially have issues with L1.2, but seem -	 * to work fine with L1 and L1.1. -	 */ -	if (rtl_aspm_is_safe(tp)) -		rc = 0; -	else if (tp->mac_version >= RTL_GIGA_MAC_VER_46) -		rc = pci_disable_link_state(pdev, PCIE_LINK_STATE_L1_2); -	else -		rc = pci_disable_link_state(pdev, PCIE_LINK_STATE_L1); -	tp->aspm_manageable = !rc; -  	tp->dash_type = rtl_check_dash(tp);  	tp->cp_cmd = RTL_R16(tp, CPlusCmd) & CPCMD_MASK;  |