|
@@ -68,6 +68,16 @@
|
|
|
static char s2io_driver_name[] = "Neterion";
|
|
|
static char s2io_driver_version[] = "Version 1.7.7";
|
|
|
|
|
|
+static inline int RXD_IS_UP2DT(RxD_t *rxdp)
|
|
|
+{
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ ret = ((!(rxdp->Control_1 & RXD_OWN_XENA)) &&
|
|
|
+ (GET_RXD_MARKER(rxdp->Control_2) != THE_RXD_MARK));
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Cards with following subsystem_id have a link state indication
|
|
|
* problem, 600B, 600C, 600D, 640B, 640C and 640D.
|
|
@@ -230,6 +240,7 @@ static unsigned int rx_ring_sz[MAX_RX_RINGS] =
|
|
|
static unsigned int Stats_refresh_time = 4;
|
|
|
static unsigned int rts_frm_len[MAX_RX_RINGS] =
|
|
|
{[0 ...(MAX_RX_RINGS - 1)] = 0 };
|
|
|
+static unsigned int use_continuous_tx_intrs = 1;
|
|
|
static unsigned int rmac_pause_time = 65535;
|
|
|
static unsigned int mc_pause_threshold_q0q3 = 187;
|
|
|
static unsigned int mc_pause_threshold_q4q7 = 187;
|
|
@@ -638,7 +649,7 @@ static int init_nic(struct s2io_nic *nic)
|
|
|
mac_control = &nic->mac_control;
|
|
|
config = &nic->config;
|
|
|
|
|
|
- /* to set the swapper control on the card */
|
|
|
+ /* to set the swapper controle on the card */
|
|
|
if(s2io_set_swapper(nic)) {
|
|
|
DBG_PRINT(ERR_DBG,"ERROR: Setting Swapper failed\n");
|
|
|
return -1;
|
|
@@ -756,6 +767,13 @@ static int init_nic(struct s2io_nic *nic)
|
|
|
val64 |= BIT(0); /* To enable the FIFO partition. */
|
|
|
writeq(val64, &bar0->tx_fifo_partition_0);
|
|
|
|
|
|
+ /*
|
|
|
+ * Disable 4 PCCs for Xena1, 2 and 3 as per H/W bug
|
|
|
+ * SXE-008 TRANSMIT DMA ARBITRATION ISSUE.
|
|
|
+ */
|
|
|
+ if (get_xena_rev_id(nic->pdev) < 4)
|
|
|
+ writeq(PCC_ENABLE_FOUR, &bar0->pcc_enable);
|
|
|
+
|
|
|
val64 = readq(&bar0->tx_fifo_partition_0);
|
|
|
DBG_PRINT(INIT_DBG, "Fifo partition at: 0x%p is: 0x%llx\n",
|
|
|
&bar0->tx_fifo_partition_0, (unsigned long long) val64);
|
|
@@ -823,37 +841,250 @@ static int init_nic(struct s2io_nic *nic)
|
|
|
}
|
|
|
writeq(val64, &bar0->rx_queue_cfg);
|
|
|
|
|
|
- /* Initializing the Tx round robin registers to 0
|
|
|
- * filling tx and rx round robin registers as per
|
|
|
- * the number of FIFOs and Rings is still TODO
|
|
|
- */
|
|
|
- writeq(0, &bar0->tx_w_round_robin_0);
|
|
|
- writeq(0, &bar0->tx_w_round_robin_1);
|
|
|
- writeq(0, &bar0->tx_w_round_robin_2);
|
|
|
- writeq(0, &bar0->tx_w_round_robin_3);
|
|
|
- writeq(0, &bar0->tx_w_round_robin_4);
|
|
|
-
|
|
|
/*
|
|
|
- * TODO
|
|
|
- * Disable Rx steering. Hard coding all packets to be steered to
|
|
|
- * Queue 0 for now.
|
|
|
+ * Filling Tx round robin registers
|
|
|
+ * as per the number of FIFOs
|
|
|
*/
|
|
|
- val64 = 0x8080808080808080ULL;
|
|
|
- writeq(val64, &bar0->rts_qos_steering);
|
|
|
+ switch (config->tx_fifo_num) {
|
|
|
+ case 1:
|
|
|
+ val64 = 0x0000000000000000ULL;
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_0);
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_1);
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_2);
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_3);
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_4);
|
|
|
+ break;
|
|
|
+ case 2:
|
|
|
+ val64 = 0x0000010000010000ULL;
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_0);
|
|
|
+ val64 = 0x0100000100000100ULL;
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_1);
|
|
|
+ val64 = 0x0001000001000001ULL;
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_2);
|
|
|
+ val64 = 0x0000010000010000ULL;
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_3);
|
|
|
+ val64 = 0x0100000000000000ULL;
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_4);
|
|
|
+ break;
|
|
|
+ case 3:
|
|
|
+ val64 = 0x0001000102000001ULL;
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_0);
|
|
|
+ val64 = 0x0001020000010001ULL;
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_1);
|
|
|
+ val64 = 0x0200000100010200ULL;
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_2);
|
|
|
+ val64 = 0x0001000102000001ULL;
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_3);
|
|
|
+ val64 = 0x0001020000000000ULL;
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_4);
|
|
|
+ break;
|
|
|
+ case 4:
|
|
|
+ val64 = 0x0001020300010200ULL;
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_0);
|
|
|
+ val64 = 0x0100000102030001ULL;
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_1);
|
|
|
+ val64 = 0x0200010000010203ULL;
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_2);
|
|
|
+ val64 = 0x0001020001000001ULL;
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_3);
|
|
|
+ val64 = 0x0203000100000000ULL;
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_4);
|
|
|
+ break;
|
|
|
+ case 5:
|
|
|
+ val64 = 0x0001000203000102ULL;
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_0);
|
|
|
+ val64 = 0x0001020001030004ULL;
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_1);
|
|
|
+ val64 = 0x0001000203000102ULL;
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_2);
|
|
|
+ val64 = 0x0001020001030004ULL;
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_3);
|
|
|
+ val64 = 0x0001000000000000ULL;
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_4);
|
|
|
+ break;
|
|
|
+ case 6:
|
|
|
+ val64 = 0x0001020304000102ULL;
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_0);
|
|
|
+ val64 = 0x0304050001020001ULL;
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_1);
|
|
|
+ val64 = 0x0203000100000102ULL;
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_2);
|
|
|
+ val64 = 0x0304000102030405ULL;
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_3);
|
|
|
+ val64 = 0x0001000200000000ULL;
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_4);
|
|
|
+ break;
|
|
|
+ case 7:
|
|
|
+ val64 = 0x0001020001020300ULL;
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_0);
|
|
|
+ val64 = 0x0102030400010203ULL;
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_1);
|
|
|
+ val64 = 0x0405060001020001ULL;
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_2);
|
|
|
+ val64 = 0x0304050000010200ULL;
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_3);
|
|
|
+ val64 = 0x0102030000000000ULL;
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_4);
|
|
|
+ break;
|
|
|
+ case 8:
|
|
|
+ val64 = 0x0001020300040105ULL;
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_0);
|
|
|
+ val64 = 0x0200030106000204ULL;
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_1);
|
|
|
+ val64 = 0x0103000502010007ULL;
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_2);
|
|
|
+ val64 = 0x0304010002060500ULL;
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_3);
|
|
|
+ val64 = 0x0103020400000000ULL;
|
|
|
+ writeq(val64, &bar0->tx_w_round_robin_4);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Filling the Rx round robin registers as per the
|
|
|
+ * number of Rings and steering based on QoS.
|
|
|
+ */
|
|
|
+ switch (config->rx_ring_num) {
|
|
|
+ case 1:
|
|
|
+ val64 = 0x8080808080808080ULL;
|
|
|
+ writeq(val64, &bar0->rts_qos_steering);
|
|
|
+ break;
|
|
|
+ case 2:
|
|
|
+ val64 = 0x0000010000010000ULL;
|
|
|
+ writeq(val64, &bar0->rx_w_round_robin_0);
|
|
|
+ val64 = 0x0100000100000100ULL;
|
|
|
+ writeq(val64, &bar0->rx_w_round_robin_1);
|
|
|
+ val64 = 0x0001000001000001ULL;
|
|
|
+ writeq(val64, &bar0->rx_w_round_robin_2);
|
|
|
+ val64 = 0x0000010000010000ULL;
|
|
|
+ writeq(val64, &bar0->rx_w_round_robin_3);
|
|
|
+ val64 = 0x0100000000000000ULL;
|
|
|
+ writeq(val64, &bar0->rx_w_round_robin_4);
|
|
|
+
|
|
|
+ val64 = 0x8080808040404040ULL;
|
|
|
+ writeq(val64, &bar0->rts_qos_steering);
|
|
|
+ break;
|
|
|
+ case 3:
|
|
|
+ val64 = 0x0001000102000001ULL;
|
|
|
+ writeq(val64, &bar0->rx_w_round_robin_0);
|
|
|
+ val64 = 0x0001020000010001ULL;
|
|
|
+ writeq(val64, &bar0->rx_w_round_robin_1);
|
|
|
+ val64 = 0x0200000100010200ULL;
|
|
|
+ writeq(val64, &bar0->rx_w_round_robin_2);
|
|
|
+ val64 = 0x0001000102000001ULL;
|
|
|
+ writeq(val64, &bar0->rx_w_round_robin_3);
|
|
|
+ val64 = 0x0001020000000000ULL;
|
|
|
+ writeq(val64, &bar0->rx_w_round_robin_4);
|
|
|
+
|
|
|
+ val64 = 0x8080804040402020ULL;
|
|
|
+ writeq(val64, &bar0->rts_qos_steering);
|
|
|
+ break;
|
|
|
+ case 4:
|
|
|
+ val64 = 0x0001020300010200ULL;
|
|
|
+ writeq(val64, &bar0->rx_w_round_robin_0);
|
|
|
+ val64 = 0x0100000102030001ULL;
|
|
|
+ writeq(val64, &bar0->rx_w_round_robin_1);
|
|
|
+ val64 = 0x0200010000010203ULL;
|
|
|
+ writeq(val64, &bar0->rx_w_round_robin_2);
|
|
|
+ val64 = 0x0001020001000001ULL;
|
|
|
+ writeq(val64, &bar0->rx_w_round_robin_3);
|
|
|
+ val64 = 0x0203000100000000ULL;
|
|
|
+ writeq(val64, &bar0->rx_w_round_robin_4);
|
|
|
+
|
|
|
+ val64 = 0x8080404020201010ULL;
|
|
|
+ writeq(val64, &bar0->rts_qos_steering);
|
|
|
+ break;
|
|
|
+ case 5:
|
|
|
+ val64 = 0x0001000203000102ULL;
|
|
|
+ writeq(val64, &bar0->rx_w_round_robin_0);
|
|
|
+ val64 = 0x0001020001030004ULL;
|
|
|
+ writeq(val64, &bar0->rx_w_round_robin_1);
|
|
|
+ val64 = 0x0001000203000102ULL;
|
|
|
+ writeq(val64, &bar0->rx_w_round_robin_2);
|
|
|
+ val64 = 0x0001020001030004ULL;
|
|
|
+ writeq(val64, &bar0->rx_w_round_robin_3);
|
|
|
+ val64 = 0x0001000000000000ULL;
|
|
|
+ writeq(val64, &bar0->rx_w_round_robin_4);
|
|
|
+
|
|
|
+ val64 = 0x8080404020201008ULL;
|
|
|
+ writeq(val64, &bar0->rts_qos_steering);
|
|
|
+ break;
|
|
|
+ case 6:
|
|
|
+ val64 = 0x0001020304000102ULL;
|
|
|
+ writeq(val64, &bar0->rx_w_round_robin_0);
|
|
|
+ val64 = 0x0304050001020001ULL;
|
|
|
+ writeq(val64, &bar0->rx_w_round_robin_1);
|
|
|
+ val64 = 0x0203000100000102ULL;
|
|
|
+ writeq(val64, &bar0->rx_w_round_robin_2);
|
|
|
+ val64 = 0x0304000102030405ULL;
|
|
|
+ writeq(val64, &bar0->rx_w_round_robin_3);
|
|
|
+ val64 = 0x0001000200000000ULL;
|
|
|
+ writeq(val64, &bar0->rx_w_round_robin_4);
|
|
|
+
|
|
|
+ val64 = 0x8080404020100804ULL;
|
|
|
+ writeq(val64, &bar0->rts_qos_steering);
|
|
|
+ break;
|
|
|
+ case 7:
|
|
|
+ val64 = 0x0001020001020300ULL;
|
|
|
+ writeq(val64, &bar0->rx_w_round_robin_0);
|
|
|
+ val64 = 0x0102030400010203ULL;
|
|
|
+ writeq(val64, &bar0->rx_w_round_robin_1);
|
|
|
+ val64 = 0x0405060001020001ULL;
|
|
|
+ writeq(val64, &bar0->rx_w_round_robin_2);
|
|
|
+ val64 = 0x0304050000010200ULL;
|
|
|
+ writeq(val64, &bar0->rx_w_round_robin_3);
|
|
|
+ val64 = 0x0102030000000000ULL;
|
|
|
+ writeq(val64, &bar0->rx_w_round_robin_4);
|
|
|
+
|
|
|
+ val64 = 0x8080402010080402ULL;
|
|
|
+ writeq(val64, &bar0->rts_qos_steering);
|
|
|
+ break;
|
|
|
+ case 8:
|
|
|
+ val64 = 0x0001020300040105ULL;
|
|
|
+ writeq(val64, &bar0->rx_w_round_robin_0);
|
|
|
+ val64 = 0x0200030106000204ULL;
|
|
|
+ writeq(val64, &bar0->rx_w_round_robin_1);
|
|
|
+ val64 = 0x0103000502010007ULL;
|
|
|
+ writeq(val64, &bar0->rx_w_round_robin_2);
|
|
|
+ val64 = 0x0304010002060500ULL;
|
|
|
+ writeq(val64, &bar0->rx_w_round_robin_3);
|
|
|
+ val64 = 0x0103020400000000ULL;
|
|
|
+ writeq(val64, &bar0->rx_w_round_robin_4);
|
|
|
+
|
|
|
+ val64 = 0x8040201008040201ULL;
|
|
|
+ writeq(val64, &bar0->rts_qos_steering);
|
|
|
+ break;
|
|
|
+ }
|
|
|
|
|
|
/* UDP Fix */
|
|
|
val64 = 0;
|
|
|
for (i = 0; i < 8; i++)
|
|
|
writeq(val64, &bar0->rts_frm_len_n[i]);
|
|
|
|
|
|
- /* Set the default rts frame length for ring0 */
|
|
|
- writeq(MAC_RTS_FRM_LEN_SET(dev->mtu+22),
|
|
|
- &bar0->rts_frm_len_n[0]);
|
|
|
+ /* Set the default rts frame length for the rings configured */
|
|
|
+ val64 = MAC_RTS_FRM_LEN_SET(dev->mtu+22);
|
|
|
+ for (i = 0 ; i < config->rx_ring_num ; i++)
|
|
|
+ writeq(val64, &bar0->rts_frm_len_n[i]);
|
|
|
+
|
|
|
+ /* Set the frame length for the configured rings
|
|
|
+ * desired by the user
|
|
|
+ */
|
|
|
+ for (i = 0; i < config->rx_ring_num; i++) {
|
|
|
+ /* If rts_frm_len[i] == 0 then it is assumed that user not
|
|
|
+ * specified frame length steering.
|
|
|
+ * If the user provides the frame length then program
|
|
|
+ * the rts_frm_len register for those values or else
|
|
|
+ * leave it as it is.
|
|
|
+ */
|
|
|
+ if (rts_frm_len[i] != 0) {
|
|
|
+ writeq(MAC_RTS_FRM_LEN_SET(rts_frm_len[i]),
|
|
|
+ &bar0->rts_frm_len_n[i]);
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
/* Program statistics memory */
|
|
|
writeq(mac_control->stats_mem_phy, &bar0->stat_addr);
|
|
|
val64 = SET_UPDT_PERIOD(Stats_refresh_time) |
|
|
|
- STAT_CFG_STAT_RO | STAT_CFG_STAT_EN;
|
|
|
+ STAT_CFG_STAT_RO | STAT_CFG_STAT_EN;
|
|
|
writeq(val64, &bar0->stat_cfg);
|
|
|
|
|
|
/*
|
|
@@ -877,13 +1108,14 @@ static int init_nic(struct s2io_nic *nic)
|
|
|
val64 = TTI_DATA1_MEM_TX_TIMER_VAL(0x2078) |
|
|
|
TTI_DATA1_MEM_TX_URNG_A(0xA) |
|
|
|
TTI_DATA1_MEM_TX_URNG_B(0x10) |
|
|
|
- TTI_DATA1_MEM_TX_URNG_C(0x30) | TTI_DATA1_MEM_TX_TIMER_AC_EN |
|
|
|
- TTI_DATA1_MEM_TX_TIMER_CI_EN;
|
|
|
+ TTI_DATA1_MEM_TX_URNG_C(0x30) | TTI_DATA1_MEM_TX_TIMER_AC_EN;
|
|
|
+ if (use_continuous_tx_intrs)
|
|
|
+ val64 |= TTI_DATA1_MEM_TX_TIMER_CI_EN;
|
|
|
writeq(val64, &bar0->tti_data1_mem);
|
|
|
|
|
|
val64 = TTI_DATA2_MEM_TX_UFC_A(0x10) |
|
|
|
TTI_DATA2_MEM_TX_UFC_B(0x20) |
|
|
|
- TTI_DATA2_MEM_TX_UFC_C(0x40) | TTI_DATA2_MEM_TX_UFC_D(0x80);
|
|
|
+ TTI_DATA2_MEM_TX_UFC_C(0x70) | TTI_DATA2_MEM_TX_UFC_D(0x80);
|
|
|
writeq(val64, &bar0->tti_data2_mem);
|
|
|
|
|
|
val64 = TTI_CMD_MEM_WE | TTI_CMD_MEM_STROBE_NEW_CMD;
|
|
@@ -927,10 +1159,11 @@ static int init_nic(struct s2io_nic *nic)
|
|
|
writeq(val64, &bar0->rti_command_mem);
|
|
|
|
|
|
/*
|
|
|
- * Once the operation completes, the Strobe bit of the command
|
|
|
- * register will be reset. We poll for this particular condition
|
|
|
- * We wait for a maximum of 500ms for the operation to complete,
|
|
|
- * if it's not complete by then we return error.
|
|
|
+ * Once the operation completes, the Strobe bit of the
|
|
|
+ * command register will be reset. We poll for this
|
|
|
+ * particular condition. We wait for a maximum of 500ms
|
|
|
+ * for the operation to complete, if it's not complete
|
|
|
+ * by then we return error.
|
|
|
*/
|
|
|
time = 0;
|
|
|
while (TRUE) {
|
|
@@ -1185,10 +1418,10 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
|
|
|
temp64 &= ~((u64) val64);
|
|
|
writeq(temp64, &bar0->general_int_mask);
|
|
|
/*
|
|
|
- * All MC block error interrupts are disabled for now.
|
|
|
- * TODO
|
|
|
+ * Enable all MC Intrs.
|
|
|
*/
|
|
|
- writeq(DISABLE_ALL_INTRS, &bar0->mc_int_mask);
|
|
|
+ writeq(0x0, &bar0->mc_int_mask);
|
|
|
+ writeq(0x0, &bar0->mc_err_mask);
|
|
|
} else if (flag == DISABLE_INTRS) {
|
|
|
/*
|
|
|
* Disable MC Intrs in the general intr mask register
|
|
@@ -1247,23 +1480,41 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static int check_prc_pcc_state(u64 val64, int flag)
|
|
|
+static int check_prc_pcc_state(u64 val64, int flag, int rev_id)
|
|
|
{
|
|
|
int ret = 0;
|
|
|
|
|
|
if (flag == FALSE) {
|
|
|
- if (!(val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) &&
|
|
|
- ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ==
|
|
|
- ADAPTER_STATUS_RC_PRC_QUIESCENT)) {
|
|
|
- ret = 1;
|
|
|
+ if (rev_id >= 4) {
|
|
|
+ if (!(val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) &&
|
|
|
+ ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ==
|
|
|
+ ADAPTER_STATUS_RC_PRC_QUIESCENT)) {
|
|
|
+ ret = 1;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (!(val64 & ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE) &&
|
|
|
+ ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ==
|
|
|
+ ADAPTER_STATUS_RC_PRC_QUIESCENT)) {
|
|
|
+ ret = 1;
|
|
|
+ }
|
|
|
}
|
|
|
} else {
|
|
|
- if (((val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) ==
|
|
|
- ADAPTER_STATUS_RMAC_PCC_IDLE) &&
|
|
|
- (!(val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ||
|
|
|
- ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ==
|
|
|
- ADAPTER_STATUS_RC_PRC_QUIESCENT))) {
|
|
|
- ret = 1;
|
|
|
+ if (rev_id >= 4) {
|
|
|
+ if (((val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) ==
|
|
|
+ ADAPTER_STATUS_RMAC_PCC_IDLE) &&
|
|
|
+ (!(val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ||
|
|
|
+ ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ==
|
|
|
+ ADAPTER_STATUS_RC_PRC_QUIESCENT))) {
|
|
|
+ ret = 1;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (((val64 & ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE) ==
|
|
|
+ ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE) &&
|
|
|
+ (!(val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ||
|
|
|
+ ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ==
|
|
|
+ ADAPTER_STATUS_RC_PRC_QUIESCENT))) {
|
|
|
+ ret = 1;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1286,6 +1537,7 @@ static int verify_xena_quiescence(nic_t *sp, u64 val64, int flag)
|
|
|
{
|
|
|
int ret = 0;
|
|
|
u64 tmp64 = ~((u64) val64);
|
|
|
+ int rev_id = get_xena_rev_id(sp->pdev);
|
|
|
|
|
|
if (!
|
|
|
(tmp64 &
|
|
@@ -1294,7 +1546,7 @@ static int verify_xena_quiescence(nic_t *sp, u64 val64, int flag)
|
|
|
ADAPTER_STATUS_PIC_QUIESCENT | ADAPTER_STATUS_MC_DRAM_READY |
|
|
|
ADAPTER_STATUS_MC_QUEUES_READY | ADAPTER_STATUS_M_PLL_LOCK |
|
|
|
ADAPTER_STATUS_P_PLL_LOCK))) {
|
|
|
- ret = check_prc_pcc_state(val64, flag);
|
|
|
+ ret = check_prc_pcc_state(val64, flag, rev_id);
|
|
|
}
|
|
|
|
|
|
return ret;
|
|
@@ -1407,7 +1659,7 @@ static int start_nic(struct s2io_nic *nic)
|
|
|
|
|
|
/* Enable select interrupts */
|
|
|
interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR | TX_MAC_INTR |
|
|
|
- RX_MAC_INTR;
|
|
|
+ RX_MAC_INTR | MC_INTR;
|
|
|
en_dis_able_nic_intrs(nic, interruptible, ENABLE_INTRS);
|
|
|
|
|
|
/*
|
|
@@ -1439,21 +1691,6 @@ static int start_nic(struct s2io_nic *nic)
|
|
|
*/
|
|
|
schedule_work(&nic->set_link_task);
|
|
|
|
|
|
- /*
|
|
|
- * Here we are performing soft reset on XGXS to
|
|
|
- * force link down. Since link is already up, we will get
|
|
|
- * link state change interrupt after this reset
|
|
|
- */
|
|
|
- SPECIAL_REG_WRITE(0x80010515001E0000ULL, &bar0->dtx_control, UF);
|
|
|
- val64 = readq(&bar0->dtx_control);
|
|
|
- udelay(50);
|
|
|
- SPECIAL_REG_WRITE(0x80010515001E00E0ULL, &bar0->dtx_control, UF);
|
|
|
- val64 = readq(&bar0->dtx_control);
|
|
|
- udelay(50);
|
|
|
- SPECIAL_REG_WRITE(0x80070515001F00E4ULL, &bar0->dtx_control, UF);
|
|
|
- val64 = readq(&bar0->dtx_control);
|
|
|
- udelay(50);
|
|
|
-
|
|
|
return SUCCESS;
|
|
|
}
|
|
|
|
|
@@ -1524,7 +1761,7 @@ static void stop_nic(struct s2io_nic *nic)
|
|
|
|
|
|
/* Disable all interrupts */
|
|
|
interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR | TX_MAC_INTR |
|
|
|
- RX_MAC_INTR;
|
|
|
+ RX_MAC_INTR | MC_INTR;
|
|
|
en_dis_able_nic_intrs(nic, interruptible, DISABLE_INTRS);
|
|
|
|
|
|
/* Disable PRCs */
|
|
@@ -1737,6 +1974,7 @@ int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
|
|
|
off++;
|
|
|
mac_control->rings[ring_no].rx_curr_put_info.offset = off;
|
|
|
#endif
|
|
|
+ rxdp->Control_2 |= SET_RXD_MARKER;
|
|
|
|
|
|
atomic_inc(&nic->rx_bufs_left[ring_no]);
|
|
|
alloc_tab++;
|
|
@@ -1965,11 +2203,8 @@ static void rx_intr_handler(ring_info_t *ring_data)
|
|
|
put_offset = (put_block * (MAX_RXDS_PER_BLOCK + 1)) +
|
|
|
put_info.offset;
|
|
|
#endif
|
|
|
- while ((!(rxdp->Control_1 & RXD_OWN_XENA)) &&
|
|
|
-#ifdef CONFIG_2BUFF_MODE
|
|
|
- (!rxdp->Control_2 & BIT(0)) &&
|
|
|
-#endif
|
|
|
- (((get_offset + 1) % ring_bufs) != put_offset)) {
|
|
|
+ while (RXD_IS_UP2DT(rxdp) &&
|
|
|
+ (((get_offset + 1) % ring_bufs) != put_offset)) {
|
|
|
skb = (struct sk_buff *) ((unsigned long)rxdp->Host_Control);
|
|
|
if (skb == NULL) {
|
|
|
DBG_PRINT(ERR_DBG, "%s: The skb is ",
|
|
@@ -2153,6 +2388,21 @@ static void alarm_intr_handler(struct s2io_nic *nic)
|
|
|
schedule_work(&nic->set_link_task);
|
|
|
}
|
|
|
|
|
|
+ /* Handling Ecc errors */
|
|
|
+ val64 = readq(&bar0->mc_err_reg);
|
|
|
+ writeq(val64, &bar0->mc_err_reg);
|
|
|
+ if (val64 & (MC_ERR_REG_ECC_ALL_SNG | MC_ERR_REG_ECC_ALL_DBL)) {
|
|
|
+ if (val64 & MC_ERR_REG_ECC_ALL_DBL) {
|
|
|
+ DBG_PRINT(ERR_DBG, "%s: Device indicates ",
|
|
|
+ dev->name);
|
|
|
+ DBG_PRINT(ERR_DBG, "double ECC error!!\n");
|
|
|
+ netif_stop_queue(dev);
|
|
|
+ schedule_work(&nic->rst_timer_task);
|
|
|
+ } else {
|
|
|
+ /* Device can recover from Single ECC errors */
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/* In case of a serious error, the device will be Reset. */
|
|
|
val64 = readq(&bar0->serr_source);
|
|
|
if (val64 & SERR_SOURCE_ANY) {
|
|
@@ -2226,7 +2476,7 @@ void s2io_reset(nic_t * sp)
|
|
|
{
|
|
|
XENA_dev_config_t __iomem *bar0 = sp->bar0;
|
|
|
u64 val64;
|
|
|
- u16 subid;
|
|
|
+ u16 subid, pci_cmd;
|
|
|
|
|
|
val64 = SW_RESET_ALL;
|
|
|
writeq(val64, &bar0->sw_reset);
|
|
@@ -2255,6 +2505,18 @@ void s2io_reset(nic_t * sp)
|
|
|
/* Set swapper to enable I/O register access */
|
|
|
s2io_set_swapper(sp);
|
|
|
|
|
|
+ /* Clear certain PCI/PCI-X fields after reset */
|
|
|
+ pci_read_config_word(sp->pdev, PCI_COMMAND, &pci_cmd);
|
|
|
+ pci_cmd &= 0x7FFF; /* Clear parity err detect bit */
|
|
|
+ pci_write_config_word(sp->pdev, PCI_COMMAND, pci_cmd);
|
|
|
+
|
|
|
+ val64 = readq(&bar0->txpic_int_reg);
|
|
|
+ val64 &= ~BIT(62); /* Clearing PCI_STATUS error reflected here */
|
|
|
+ writeq(val64, &bar0->txpic_int_reg);
|
|
|
+
|
|
|
+ /* Clearing PCIX Ecc status register */
|
|
|
+ pci_write_config_dword(sp->pdev, 0x68, 0);
|
|
|
+
|
|
|
/* Reset device statistics maintained by OS */
|
|
|
memset(&sp->stats, 0, sizeof (struct net_device_stats));
|
|
|
|
|
@@ -2797,6 +3059,8 @@ static void s2io_set_multicast(struct net_device *dev)
|
|
|
/* Disable all Multicast addresses */
|
|
|
writeq(RMAC_ADDR_DATA0_MEM_ADDR(dis_addr),
|
|
|
&bar0->rmac_addr_data0_mem);
|
|
|
+ writeq(RMAC_ADDR_DATA1_MEM_MASK(0x0),
|
|
|
+ &bar0->rmac_addr_data1_mem);
|
|
|
val64 = RMAC_ADDR_CMD_MEM_WE |
|
|
|
RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
|
|
|
RMAC_ADDR_CMD_MEM_OFFSET(sp->all_multi_pos);
|
|
@@ -4369,21 +4633,6 @@ static void s2io_init_pci(nic_t * sp)
|
|
|
(pci_cmd | PCI_COMMAND_PARITY));
|
|
|
pci_read_config_word(sp->pdev, PCI_COMMAND, &pci_cmd);
|
|
|
|
|
|
- /* Set MMRB count to 1024 in PCI-X Command register. */
|
|
|
- pcix_cmd &= 0xFFF3;
|
|
|
- pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
|
|
|
- (pcix_cmd | (0x1 << 2))); /* MMRBC 1K */
|
|
|
- pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
|
|
|
- &(pcix_cmd));
|
|
|
-
|
|
|
- /* Setting Maximum outstanding splits based on system type. */
|
|
|
- pcix_cmd &= 0xFF8F;
|
|
|
- pcix_cmd |= XENA_MAX_OUTSTANDING_SPLITS(0x1); /* 2 splits. */
|
|
|
- pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
|
|
|
- pcix_cmd);
|
|
|
- pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
|
|
|
- &(pcix_cmd));
|
|
|
-
|
|
|
/* Forcibly disabling relaxed ordering capability of the card. */
|
|
|
pcix_cmd &= 0xfffd;
|
|
|
pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
|
|
@@ -4400,6 +4649,7 @@ module_param_array(tx_fifo_len, uint, NULL, 0);
|
|
|
module_param_array(rx_ring_sz, uint, NULL, 0);
|
|
|
module_param(Stats_refresh_time, int, 0);
|
|
|
module_param_array(rts_frm_len, uint, NULL, 0);
|
|
|
+module_param(use_continuous_tx_intrs, int, 1);
|
|
|
module_param(rmac_pause_time, int, 0);
|
|
|
module_param(mc_pause_threshold_q0q3, int, 0);
|
|
|
module_param(mc_pause_threshold_q4q7, int, 0);
|