Commit b0801256 authored by Jiawen Wu's avatar Jiawen Wu Committed by David S. Miller
Browse files

net: txgbe: Reset hardware



Reset and initialize the hardware by configuring the MAC layer.

Signed-off-by: default avatarJiawen Wu <jiawenwu@trustnetic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a34b3e6e
Loading
Loading
Loading
Loading
+160 −0
Original line number Diff line number Diff line
@@ -7,6 +7,21 @@
#include "wx_type.h"
#include "wx_hw.h"

static void wx_intr_disable(struct wx_hw *wxhw, u64 qmask)
{
	u32 mask;

	mask = (qmask & 0xFFFFFFFF);
	if (mask)
		wr32(wxhw, WX_PX_IMS(0), mask);

	if (wxhw->mac.type == wx_mac_sp) {
		mask = (qmask >> 32);
		if (mask)
			wr32(wxhw, WX_PX_IMS(1), mask);
	}
}

/* cmd_addr is used for some special command:
 * 1. to be sector address, when implemented erase sector command
 * 2. to be flash address when implemented read, write flash address
@@ -56,6 +71,151 @@ int wx_check_flash_load(struct wx_hw *hw, u32 check_bit)
}
EXPORT_SYMBOL(wx_check_flash_load);

static void wx_disable_rx(struct wx_hw *wxhw)
{
	u32 pfdtxgswc;
	u32 rxctrl;

	rxctrl = rd32(wxhw, WX_RDB_PB_CTL);
	if (rxctrl & WX_RDB_PB_CTL_RXEN) {
		pfdtxgswc = rd32(wxhw, WX_PSR_CTL);
		if (pfdtxgswc & WX_PSR_CTL_SW_EN) {
			pfdtxgswc &= ~WX_PSR_CTL_SW_EN;
			wr32(wxhw, WX_PSR_CTL, pfdtxgswc);
			wxhw->mac.set_lben = true;
		} else {
			wxhw->mac.set_lben = false;
		}
		rxctrl &= ~WX_RDB_PB_CTL_RXEN;
		wr32(wxhw, WX_RDB_PB_CTL, rxctrl);

		if (!(((wxhw->subsystem_device_id & WX_NCSI_MASK) == WX_NCSI_SUP) ||
		      ((wxhw->subsystem_device_id & WX_WOL_MASK) == WX_WOL_SUP))) {
			/* disable mac receiver */
			wr32m(wxhw, WX_MAC_RX_CFG,
			      WX_MAC_RX_CFG_RE, 0);
		}
	}
}

/**
 *  wx_disable_pcie_master - Disable PCI-express master access
 *  @wxhw: pointer to hardware structure
 *
 *  Disables PCI-Express master access and verifies there are no pending
 *  requests.
 **/
static int wx_disable_pcie_master(struct wx_hw *wxhw)
{
	int status = 0;
	u32 val;

	/* Always set this bit to ensure any future transactions are blocked */
	pci_clear_master(wxhw->pdev);

	/* Exit if master requests are blocked */
	if (!(rd32(wxhw, WX_PX_TRANSACTION_PENDING)))
		return 0;

	/* Poll for master request bit to clear */
	status = read_poll_timeout(rd32, val, !val, 100, WX_PCI_MASTER_DISABLE_TIMEOUT,
				   false, wxhw, WX_PX_TRANSACTION_PENDING);
	if (status < 0)
		wx_err(wxhw, "PCIe transaction pending bit did not clear.\n");

	return status;
}

/**
 *  wx_stop_adapter - Generic stop Tx/Rx units
 *  @wxhw: pointer to hardware structure
 *
 *  Sets the adapter_stopped flag within wx_hw struct. Clears interrupts,
 *  disables transmit and receive units. The adapter_stopped flag is used by
 *  the shared code and drivers to determine if the adapter is in a stopped
 *  state and should not touch the hardware.
 **/
int wx_stop_adapter(struct wx_hw *wxhw)
{
	u16 i;

	/* Set the adapter_stopped flag so other driver functions stop touching
	 * the hardware
	 */
	wxhw->adapter_stopped = true;

	/* Disable the receive unit */
	wx_disable_rx(wxhw);

	/* Set interrupt mask to stop interrupts from being generated */
	wx_intr_disable(wxhw, WX_INTR_ALL);

	/* Clear any pending interrupts, flush previous writes */
	wr32(wxhw, WX_PX_MISC_IC, 0xffffffff);
	wr32(wxhw, WX_BME_CTL, 0x3);

	/* Disable the transmit unit.  Each queue must be disabled. */
	for (i = 0; i < wxhw->mac.max_tx_queues; i++) {
		wr32m(wxhw, WX_PX_TR_CFG(i),
		      WX_PX_TR_CFG_SWFLSH | WX_PX_TR_CFG_ENABLE,
		      WX_PX_TR_CFG_SWFLSH);
	}

	/* Disable the receive unit by stopping each queue */
	for (i = 0; i < wxhw->mac.max_rx_queues; i++) {
		wr32m(wxhw, WX_PX_RR_CFG(i),
		      WX_PX_RR_CFG_RR_EN, 0);
	}

	/* flush all queues disables */
	WX_WRITE_FLUSH(wxhw);

	/* Prevent the PCI-E bus from hanging by disabling PCI-E master
	 * access and verify no pending requests
	 */
	return wx_disable_pcie_master(wxhw);
}
EXPORT_SYMBOL(wx_stop_adapter);

void wx_reset_misc(struct wx_hw *wxhw)
{
	int i;

	/* receive packets that size > 2048 */
	wr32m(wxhw, WX_MAC_RX_CFG, WX_MAC_RX_CFG_JE, WX_MAC_RX_CFG_JE);

	/* clear counters on read */
	wr32m(wxhw, WX_MMC_CONTROL,
	      WX_MMC_CONTROL_RSTONRD, WX_MMC_CONTROL_RSTONRD);

	wr32m(wxhw, WX_MAC_RX_FLOW_CTRL,
	      WX_MAC_RX_FLOW_CTRL_RFE, WX_MAC_RX_FLOW_CTRL_RFE);

	wr32(wxhw, WX_MAC_PKT_FLT, WX_MAC_PKT_FLT_PR);

	wr32m(wxhw, WX_MIS_RST_ST,
	      WX_MIS_RST_ST_RST_INIT, 0x1E00);

	/* errata 4: initialize mng flex tbl and wakeup flex tbl*/
	wr32(wxhw, WX_PSR_MNG_FLEX_SEL, 0);
	for (i = 0; i < 16; i++) {
		wr32(wxhw, WX_PSR_MNG_FLEX_DW_L(i), 0);
		wr32(wxhw, WX_PSR_MNG_FLEX_DW_H(i), 0);
		wr32(wxhw, WX_PSR_MNG_FLEX_MSK(i), 0);
	}
	wr32(wxhw, WX_PSR_LAN_FLEX_SEL, 0);
	for (i = 0; i < 16; i++) {
		wr32(wxhw, WX_PSR_LAN_FLEX_DW_L(i), 0);
		wr32(wxhw, WX_PSR_LAN_FLEX_DW_H(i), 0);
		wr32(wxhw, WX_PSR_LAN_FLEX_MSK(i), 0);
	}

	/* set pause frame dst mac addr */
	wr32(wxhw, WX_RDB_PFCMACDAL, 0xC2000001);
	wr32(wxhw, WX_RDB_PFCMACDAH, 0x0180);
}
EXPORT_SYMBOL(wx_reset_misc);

int wx_sw_init(struct wx_hw *wxhw)
{
	struct pci_dev *pdev = wxhw->pdev;
+2 −0
Original line number Diff line number Diff line
@@ -5,6 +5,8 @@
#define _WX_HW_H_

int wx_check_flash_load(struct wx_hw *hw, u32 check_bit);
int wx_stop_adapter(struct wx_hw *wxhw);
void wx_reset_misc(struct wx_hw *wxhw);
int wx_sw_init(struct wx_hw *wxhw);

#endif /* _WX_HW_H_ */
+146 −0
Original line number Diff line number Diff line
@@ -9,6 +9,20 @@
#define PCI_VENDOR_ID_WANGXUN                   0x8088
#endif

#define WX_NCSI_SUP                             0x8000
#define WX_NCSI_MASK                            0x8000
#define WX_WOL_SUP                              0x4000
#define WX_WOL_MASK                             0x4000

/**************** Global Registers ****************************/
/* chip control Registers */
#define WX_MIS_PWR                   0x10000
#define WX_MIS_RST                   0x1000C
#define WX_MIS_RST_LAN_RST(_i)       BIT((_i) + 1)
#define WX_MIS_RST_ST                0x10030
#define WX_MIS_RST_ST_RST_INI_SHIFT  8
#define WX_MIS_RST_ST_RST_INIT       (0xFF << WX_MIS_RST_ST_RST_INI_SHIFT)

/* FMGR Registers */
#define WX_SPI_CMD                   0x10104
#define WX_SPI_CMD_READ_DWORD        0x1
@@ -25,16 +39,120 @@
#define WX_SPI_STATUS_FLASH_BYPASS   BIT(31)
#define WX_SPI_ILDR_STATUS           0x10120

/* Sensors for PVT(Process Voltage Temperature) */
#define WX_TS_EN                     0x10304
#define WX_TS_EN_ENA                 BIT(0)
#define WX_TS_ALARM_THRE             0x1030C
#define WX_TS_DALARM_THRE            0x10310
#define WX_TS_INT_EN                 0x10314
#define WX_TS_INT_EN_DALARM_INT_EN   BIT(1)
#define WX_TS_INT_EN_ALARM_INT_EN    BIT(0)
#define WX_TS_ALARM_ST               0x10318
#define WX_TS_ALARM_ST_DALARM        BIT(1)
#define WX_TS_ALARM_ST_ALARM         BIT(0)

/***************************** RDB registers *********************************/
/* receive packet buffer */
#define WX_RDB_PB_CTL                0x19000
#define WX_RDB_PB_CTL_RXEN           BIT(31) /* Enable Receiver */
#define WX_RDB_PB_CTL_DISABLED       BIT(0)
/* statistic */
#define WX_RDB_PFCMACDAL             0x19210
#define WX_RDB_PFCMACDAH             0x19214

/******************************* PSR Registers *******************************/
/* psr control */
#define WX_PSR_CTL                   0x15000
/* Header split receive */
#define WX_PSR_CTL_SW_EN             BIT(18)
#define WX_PSR_CTL_RSC_ACK           BIT(17)
#define WX_PSR_CTL_RSC_DIS           BIT(16)
#define WX_PSR_CTL_PCSD              BIT(13)
#define WX_PSR_CTL_IPPCSE            BIT(12)
#define WX_PSR_CTL_BAM               BIT(10)
#define WX_PSR_CTL_UPE               BIT(9)
#define WX_PSR_CTL_MPE               BIT(8)
#define WX_PSR_CTL_MFE               BIT(7)
#define WX_PSR_CTL_MO_SHIFT          5
#define WX_PSR_CTL_MO                (0x3 << WX_PSR_CTL_MO_SHIFT)
#define WX_PSR_CTL_TPE               BIT(4)

/* Management */
#define WX_PSR_MNG_FLEX_SEL          0x1582C
#define WX_PSR_MNG_FLEX_DW_L(_i)     (0x15A00 + ((_i) * 16))
#define WX_PSR_MNG_FLEX_DW_H(_i)     (0x15A04 + ((_i) * 16))
#define WX_PSR_MNG_FLEX_MSK(_i)      (0x15A08 + ((_i) * 16))
#define WX_PSR_LAN_FLEX_SEL          0x15B8C
#define WX_PSR_LAN_FLEX_DW_L(_i)     (0x15C00 + ((_i) * 16))
#define WX_PSR_LAN_FLEX_DW_H(_i)     (0x15C04 + ((_i) * 16))
#define WX_PSR_LAN_FLEX_MSK(_i)      (0x15C08 + ((_i) * 16))

/************************************* ETH MAC *****************************/
#define WX_MAC_RX_CFG                0x11004
#define WX_MAC_RX_CFG_RE             BIT(0)
#define WX_MAC_RX_CFG_JE             BIT(8)
#define WX_MAC_PKT_FLT               0x11008
#define WX_MAC_PKT_FLT_PR            BIT(0) /* promiscuous mode */
#define WX_MAC_RX_FLOW_CTRL          0x11090
#define WX_MAC_RX_FLOW_CTRL_RFE      BIT(0) /* receive fc enable */
#define WX_MMC_CONTROL               0x11800
#define WX_MMC_CONTROL_RSTONRD       BIT(2) /* reset on read */

/********************************* BAR registers ***************************/
/* Interrupt Registers */
#define WX_BME_CTL                   0x12020
#define WX_PX_MISC_IC                0x100
#define WX_PX_IMS(_i)                (0x140 + (_i) * 4)
#define WX_PX_TRANSACTION_PENDING    0x168

/* transmit DMA Registers */
#define WX_PX_TR_CFG(_i)             (0x03010 + ((_i) * 0x40))
/* Transmit Config masks */
#define WX_PX_TR_CFG_ENABLE          BIT(0) /* Ena specific Tx Queue */
#define WX_PX_TR_CFG_TR_SIZE_SHIFT   1 /* tx desc number per ring */
#define WX_PX_TR_CFG_SWFLSH          BIT(26) /* Tx Desc. wr-bk flushing */
#define WX_PX_TR_CFG_WTHRESH_SHIFT   16 /* shift to WTHRESH bits */
#define WX_PX_TR_CFG_THRE_SHIFT      8

/* Receive DMA Registers */
#define WX_PX_RR_CFG(_i)             (0x01010 + ((_i) * 0x40))
/* PX_RR_CFG bit definitions */
#define WX_PX_RR_CFG_RR_EN           BIT(0)

/* Number of 80 microseconds we wait for PCI Express master disable */
#define WX_PCI_MASTER_DISABLE_TIMEOUT        80000

/* Bus parameters */
struct wx_bus_info {
	u8 func;
	u16 device;
};

struct wx_thermal_sensor_data {
	s16 temp;
	s16 alarm_thresh;
	s16 dalarm_thresh;
};

enum wx_mac_type {
	wx_mac_unknown = 0,
	wx_mac_sp,
	wx_mac_em
};

struct wx_mac_info {
	enum wx_mac_type type;
	bool set_lben;
	u32 max_tx_queues;
	u32 max_rx_queues;
	struct wx_thermal_sensor_data sensor;
};

struct wx_hw {
	u8 __iomem *hw_addr;
	struct pci_dev *pdev;
	struct wx_bus_info bus;
	struct wx_mac_info mac;
	u16 device_id;
	u16 vendor_id;
	u16 subsystem_device_id;
@@ -42,12 +160,40 @@ struct wx_hw {
	u8 revision_id;
	u16 oem_ssid;
	u16 oem_svid;
	bool adapter_stopped;
};

#define WX_INTR_ALL (~0ULL)

/* register operations */
#define wr32(a, reg, value)	writel((value), ((a)->hw_addr + (reg)))
#define rd32(a, reg)		readl((a)->hw_addr + (reg))

static inline u32
rd32m(struct wx_hw *wxhw, u32 reg, u32 mask)
{
	u32 val;

	val = rd32(wxhw, reg);
	return val & mask;
}

static inline void
wr32m(struct wx_hw *wxhw, u32 reg, u32 mask, u32 field)
{
	u32 val;

	val = rd32(wxhw, reg);
	val = ((val & ~mask) | (field & mask));

	wr32(wxhw, reg, val);
}

/* On some domestic CPU platforms, sometimes IO is not synchronized with
 * flushing memory, here use readl() to flush PCI read and write.
 */
#define WX_WRITE_FLUSH(H) rd32(H, WX_MIS_PWR)

#define wx_err(wxhw, fmt, arg...) \
	dev_err(&(wxhw)->pdev->dev, fmt, ##arg)

+2 −1
Original line number Diff line number Diff line
@@ -6,4 +6,5 @@

obj-$(CONFIG_TXGBE) += txgbe.o

txgbe-objs := txgbe_main.o
txgbe-objs := txgbe_main.o \
              txgbe_hw.o
+3 −2
Original line number Diff line number Diff line
@@ -4,13 +4,14 @@
#ifndef _TXGBE_H_
#define _TXGBE_H_

#include "txgbe_type.h"

#define TXGBE_MAX_FDIR_INDICES          63

#define TXGBE_MAX_RX_QUEUES   (TXGBE_MAX_FDIR_INDICES + 1)
#define TXGBE_MAX_TX_QUEUES   (TXGBE_MAX_FDIR_INDICES + 1)

#define TXGBE_SP_MAX_TX_QUEUES  128
#define TXGBE_SP_MAX_RX_QUEUES  128

/* board specific private data structure */
struct txgbe_adapter {
	u8 __iomem *io_addr;    /* Mainly for iounmap use */
Loading