[PATCH] S2io: Hardware fixes

Hi,
Below patch addresses few h/w specific issues.
1. Check for additional ownership bit on Rx path before
   starting Rx processing.
2. Enable only 4 PCCs(Per Context Controller) for Xframe I
   revisions less than 4.
3. Program Rx and Tx round robin registers depending on
   no. of rings/FIFOs.
4. Tx continous interrupts is now a loadable parameter.
5. Reset the card if we get double-bit ECC errors.
6. A soft reset of XGXS being done to force a link state change has been
   eliminated.
7. After a reset, clear "parity error detected" bit,
   PCI-X ECC status register, and PCI_STATUS bit in
   tx_pic_int register.
8. The error in the disabling allmulticast implementation has been
   rectified.
9. Leave the PCI-X parameters MMRBC, OST etc. at their
   BIOS/system defaults.

Signed-off-by: Ravinandan Arakali <ravinandan.arakali@neterion.com>
Signed-off-by: Raghavendra Koushik <raghavendra.koushik@neterion.com>
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
This commit is contained in:
raghavendra.koushik@neterion.com 2005-08-03 12:27:09 -07:00 committed by Jeff Garzik
parent 20346722ec
commit 5e25b9ddb6
3 changed files with 341 additions and 80 deletions

View File

@ -62,6 +62,7 @@ typedef struct _XENA_dev_config {
#define ADAPTER_STATUS_RMAC_REMOTE_FAULT BIT(6)
#define ADAPTER_STATUS_RMAC_LOCAL_FAULT BIT(7)
#define ADAPTER_STATUS_RMAC_PCC_IDLE vBIT(0xFF,8,8)
#define ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE vBIT(0x0F,8,8)
#define ADAPTER_STATUS_RC_PRC_QUIESCENT vBIT(0xFF,16,8)
#define ADAPTER_STATUS_MC_DRAM_READY BIT(24)
#define ADAPTER_STATUS_MC_QUEUES_READY BIT(25)
@ -245,6 +246,7 @@ typedef struct _XENA_dev_config {
#define STAT_TRSF_PER(n) TBD
#define PER_SEC 0x208d5
#define SET_UPDT_PERIOD(n) vBIT((PER_SEC*n),32,32)
#define SET_UPDT_CLICKS(val) vBIT(val, 32, 32)
u64 stat_addr;
@ -289,6 +291,7 @@ typedef struct _XENA_dev_config {
u64 pcc_err_reg;
#define PCC_FB_ECC_DB_ERR vBIT(0xFF, 16, 8)
#define PCC_ENABLE_FOUR vBIT(0x0F,0,8)
u64 pcc_err_mask;
u64 pcc_err_alarm;
@ -690,6 +693,10 @@ typedef struct _XENA_dev_config {
#define MC_ERR_REG_MIRI_CRI_ERR_0 BIT(22)
#define MC_ERR_REG_MIRI_CRI_ERR_1 BIT(23)
#define MC_ERR_REG_SM_ERR BIT(31)
#define MC_ERR_REG_ECC_ALL_SNG (BIT(6) | \
BIT(7) | BIT(17) | BIT(19))
#define MC_ERR_REG_ECC_ALL_DBL (BIT(14) | \
BIT(15) | BIT(18) | BIT(20))
u64 mc_err_mask;
u64 mc_err_alarm;

View File

@ -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);

View File

@ -372,6 +372,10 @@ typedef struct _RxD_t {
#define RXD_GET_L4_CKSUM(val) ((u16)(val) & 0xFFFF)
u64 Control_2;
#define THE_RXD_MARK 0x3
#define SET_RXD_MARKER vBIT(THE_RXD_MARK, 0, 2)
#define GET_RXD_MARKER(ctrl) ((ctrl & SET_RXD_MARKER) >> 62)
#ifndef CONFIG_2BUFF_MODE
#define MASK_BUFFER0_SIZE vBIT(0x3FFF,2,14)
#define SET_BUFFER0_SIZE(val) vBIT(val,2,14)