Commit 776bd20f authored by ravinandan.arakali@neterion.com's avatar ravinandan.arakali@neterion.com Committed by Jeff Garzik

[PATCH] S2io: Hardware and miscellaneous fixes

Hi,
This patch contains the following hardware related fixes and other
miscellaneous bug fixes.

1. Updated the definition of single and double-bit ECC errors
2. Earlier we were allocating Transmit descriptors equal to
   MAX_SKB_FRAGS. This was causing a boundary condition failure.
   Need to allocate MAX_SKB_FRAGS+1 descriptors.
3. On some platforms(like PPC), pci_alloc_consistent() can return
   a zero DMA address. Since the NIC cannot handle zero-addresses,
   a workaround has been provided. Basically, we don't use such
   that page. We reallocate.
4. If list_info allocation failed during driver load, check for
   it during driver exit and return instead of trying to dereference
   NULL pointer.
5. Increase the debug level of few non-critical debug messages.
6. Reset the card on critical ECC double errors only in case of
   XframeI since XframeII can recover from such errors.
7. Print copyright message on driver load.
8. Bumped up the driver version no. to 2.0.8.1
Signed-off-by: default avatarRavinandan Arakali <ravinandan.arakali@neterion.com>
Signed-off-by: default avatarJeff Garzik <jgarzik@pobox.com>
parent 4706df3d
/************************************************************************ /************************************************************************
* regs.h: A Linux PCI-X Ethernet driver for S2IO 10GbE Server NIC * regs.h: A Linux PCI-X Ethernet driver for Neterion 10GbE Server NIC
* Copyright(c) 2002-2005 Neterion Inc. * Copyright(c) 2002-2005 Neterion Inc.
* This software may be used and distributed according to the terms of * This software may be used and distributed according to the terms of
...@@ -713,13 +713,16 @@ typedef struct _XENA_dev_config { ...@@ -713,13 +713,16 @@ typedef struct _XENA_dev_config {
u64 mc_err_reg; u64 mc_err_reg;
#define MC_ERR_REG_ECC_DB_ERR_L BIT(14) #define MC_ERR_REG_ECC_DB_ERR_L BIT(14)
#define MC_ERR_REG_ECC_DB_ERR_U BIT(15) #define MC_ERR_REG_ECC_DB_ERR_U BIT(15)
#define MC_ERR_REG_MIRI_ECC_DB_ERR_0 BIT(18)
#define MC_ERR_REG_MIRI_ECC_DB_ERR_1 BIT(20)
#define MC_ERR_REG_MIRI_CRI_ERR_0 BIT(22) #define MC_ERR_REG_MIRI_CRI_ERR_0 BIT(22)
#define MC_ERR_REG_MIRI_CRI_ERR_1 BIT(23) #define MC_ERR_REG_MIRI_CRI_ERR_1 BIT(23)
#define MC_ERR_REG_SM_ERR BIT(31) #define MC_ERR_REG_SM_ERR BIT(31)
#define MC_ERR_REG_ECC_ALL_SNG (BIT(6) | \ #define MC_ERR_REG_ECC_ALL_SNG (BIT(2) | BIT(3) | BIT(4) | BIT(5) |\
BIT(7) | BIT(17) | BIT(19)) BIT(6) | BIT(7) | BIT(17) | BIT(19))
#define MC_ERR_REG_ECC_ALL_DBL (BIT(14) | \ #define MC_ERR_REG_ECC_ALL_DBL (BIT(10) | BIT(11) | BIT(12) |\
BIT(15) | BIT(18) | BIT(20)) BIT(13) | BIT(14) | BIT(15) |\
BIT(18) | BIT(20))
u64 mc_err_mask; u64 mc_err_mask;
u64 mc_err_alarm; u64 mc_err_alarm;
......
/************************************************************************ /************************************************************************
* s2io.c: A Linux PCI-X Ethernet driver for S2IO 10GbE Server NIC * s2io.c: A Linux PCI-X Ethernet driver for Neterion 10GbE Server NIC
* Copyright(c) 2002-2005 Neterion Inc. * Copyright(c) 2002-2005 Neterion Inc.
* This software may be used and distributed according to the terms of * This software may be used and distributed according to the terms of
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
* explaination of all the variables. * explaination of all the variables.
* rx_ring_num : This can be used to program the number of receive rings used * rx_ring_num : This can be used to program the number of receive rings used
* in the driver. * in the driver.
* rx_ring_len: This defines the number of descriptors each ring can have. This * rx_ring_sz: This defines the number of descriptors each ring can have. This
* is also an array of size 8. * is also an array of size 8.
* tx_fifo_num: This defines the number of Tx FIFOs thats used int the driver. * tx_fifo_num: This defines the number of Tx FIFOs thats used int the driver.
* tx_fifo_len: This too is an array of 8. Each element defines the number of * tx_fifo_len: This too is an array of 8. Each element defines the number of
...@@ -67,7 +67,7 @@ ...@@ -67,7 +67,7 @@
/* S2io Driver name & version. */ /* S2io Driver name & version. */
static char s2io_driver_name[] = "Neterion"; static char s2io_driver_name[] = "Neterion";
static char s2io_driver_version[] = "Version 2.0.3.1"; static char s2io_driver_version[] = "Version 2.0.8.1";
static inline int RXD_IS_UP2DT(RxD_t *rxdp) static inline int RXD_IS_UP2DT(RxD_t *rxdp)
{ {
...@@ -404,7 +404,7 @@ static int init_shared_mem(struct s2io_nic *nic) ...@@ -404,7 +404,7 @@ static int init_shared_mem(struct s2io_nic *nic)
config->tx_cfg[i].fifo_len - 1; config->tx_cfg[i].fifo_len - 1;
mac_control->fifos[i].fifo_no = i; mac_control->fifos[i].fifo_no = i;
mac_control->fifos[i].nic = nic; mac_control->fifos[i].nic = nic;
mac_control->fifos[i].max_txds = MAX_SKB_FRAGS; mac_control->fifos[i].max_txds = MAX_SKB_FRAGS + 1;
for (j = 0; j < page_num; j++) { for (j = 0; j < page_num; j++) {
int k = 0; int k = 0;
...@@ -418,6 +418,26 @@ static int init_shared_mem(struct s2io_nic *nic) ...@@ -418,6 +418,26 @@ static int init_shared_mem(struct s2io_nic *nic)
DBG_PRINT(ERR_DBG, "failed for TxDL\n"); DBG_PRINT(ERR_DBG, "failed for TxDL\n");
return -ENOMEM; return -ENOMEM;
} }
/* If we got a zero DMA address(can happen on
* certain platforms like PPC), reallocate.
* Store virtual address of page we don't want,
* to be freed later.
*/
if (!tmp_p) {
mac_control->zerodma_virt_addr = tmp_v;
DBG_PRINT(INIT_DBG,
"%s: Zero DMA address for TxDL. ", dev->name);
DBG_PRINT(INIT_DBG,
"Virtual address %llx\n", (u64)tmp_v);
tmp_v = pci_alloc_consistent(nic->pdev,
PAGE_SIZE, &tmp_p);
if (!tmp_v) {
DBG_PRINT(ERR_DBG,
"pci_alloc_consistent ");
DBG_PRINT(ERR_DBG, "failed for TxDL\n");
return -ENOMEM;
}
}
while (k < lst_per_page) { while (k < lst_per_page) {
int l = (j * lst_per_page) + k; int l = (j * lst_per_page) + k;
if (l == config->tx_cfg[i].fifo_len) if (l == config->tx_cfg[i].fifo_len)
...@@ -600,7 +620,7 @@ static void free_shared_mem(struct s2io_nic *nic) ...@@ -600,7 +620,7 @@ static void free_shared_mem(struct s2io_nic *nic)
mac_info_t *mac_control; mac_info_t *mac_control;
struct config_param *config; struct config_param *config;
int lst_size, lst_per_page; int lst_size, lst_per_page;
struct net_device *dev = nic->dev;
if (!nic) if (!nic)
return; return;
...@@ -616,9 +636,10 @@ static void free_shared_mem(struct s2io_nic *nic) ...@@ -616,9 +636,10 @@ static void free_shared_mem(struct s2io_nic *nic)
lst_per_page); lst_per_page);
for (j = 0; j < page_num; j++) { for (j = 0; j < page_num; j++) {
int mem_blks = (j * lst_per_page); int mem_blks = (j * lst_per_page);
if ((!mac_control->fifos[i].list_info) || if (!mac_control->fifos[i].list_info)
(!mac_control->fifos[i].list_info[mem_blks]. return;
list_virt_addr)) if (!mac_control->fifos[i].list_info[mem_blks].
list_virt_addr)
break; break;
pci_free_consistent(nic->pdev, PAGE_SIZE, pci_free_consistent(nic->pdev, PAGE_SIZE,
mac_control->fifos[i]. mac_control->fifos[i].
...@@ -628,6 +649,18 @@ static void free_shared_mem(struct s2io_nic *nic) ...@@ -628,6 +649,18 @@ static void free_shared_mem(struct s2io_nic *nic)
list_info[mem_blks]. list_info[mem_blks].
list_phy_addr); list_phy_addr);
} }
/* If we got a zero DMA address during allocation,
* free the page now
*/
if (mac_control->zerodma_virt_addr) {
pci_free_consistent(nic->pdev, PAGE_SIZE,
mac_control->zerodma_virt_addr,
(dma_addr_t)0);
DBG_PRINT(INIT_DBG,
"%s: Freeing TxDL with zero DMA addr. ", dev->name);
DBG_PRINT(INIT_DBG, "Virtual address %llx\n",
(u64)(mac_control->zerodma_virt_addr));
}
kfree(mac_control->fifos[i].list_info); kfree(mac_control->fifos[i].list_info);
} }
...@@ -2479,9 +2512,10 @@ static void rx_intr_handler(ring_info_t *ring_data) ...@@ -2479,9 +2512,10 @@ static void rx_intr_handler(ring_info_t *ring_data)
#endif #endif
spin_lock(&nic->rx_lock); spin_lock(&nic->rx_lock);
if (atomic_read(&nic->card_state) == CARD_DOWN) { if (atomic_read(&nic->card_state) == CARD_DOWN) {
DBG_PRINT(ERR_DBG, "%s: %s going down for reset\n", DBG_PRINT(INTR_DBG, "%s: %s going down for reset\n",
__FUNCTION__, dev->name); __FUNCTION__, dev->name);
spin_unlock(&nic->rx_lock); spin_unlock(&nic->rx_lock);
return;
} }
get_info = ring_data->rx_curr_get_info; get_info = ring_data->rx_curr_get_info;
...@@ -2596,8 +2630,14 @@ static void tx_intr_handler(fifo_info_t *fifo_data) ...@@ -2596,8 +2630,14 @@ static void tx_intr_handler(fifo_info_t *fifo_data)
if (txdlp->Control_1 & TXD_T_CODE) { if (txdlp->Control_1 & TXD_T_CODE) {
unsigned long long err; unsigned long long err;
err = txdlp->Control_1 & TXD_T_CODE; err = txdlp->Control_1 & TXD_T_CODE;
DBG_PRINT(ERR_DBG, "***TxD error %llx\n", if ((err >> 48) == 0xA) {
err); DBG_PRINT(TX_DBG, "TxD returned due \
to loss of link\n");
}
else {
DBG_PRINT(ERR_DBG, "***TxD error \
%llx\n", err);
}
} }
skb = (struct sk_buff *) ((unsigned long) skb = (struct sk_buff *) ((unsigned long)
...@@ -2689,13 +2729,17 @@ static void alarm_intr_handler(struct s2io_nic *nic) ...@@ -2689,13 +2729,17 @@ static void alarm_intr_handler(struct s2io_nic *nic)
if (val64 & MC_ERR_REG_ECC_ALL_DBL) { if (val64 & MC_ERR_REG_ECC_ALL_DBL) {
nic->mac_control.stats_info->sw_stat. nic->mac_control.stats_info->sw_stat.
double_ecc_errs++; double_ecc_errs++;
DBG_PRINT(ERR_DBG, "%s: Device indicates ", DBG_PRINT(INIT_DBG, "%s: Device indicates ",
dev->name); dev->name);
DBG_PRINT(ERR_DBG, "double ECC error!!\n"); DBG_PRINT(INIT_DBG, "double ECC error!!\n");
if (nic->device_type != XFRAME_II_DEVICE) { if (nic->device_type != XFRAME_II_DEVICE) {
/* Reset XframeI only if critical error */
if (val64 & (MC_ERR_REG_MIRI_ECC_DB_ERR_0 |
MC_ERR_REG_MIRI_ECC_DB_ERR_1)) {
netif_stop_queue(dev); netif_stop_queue(dev);
schedule_work(&nic->rst_timer_task); schedule_work(&nic->rst_timer_task);
} }
}
} else { } else {
nic->mac_control.stats_info->sw_stat. nic->mac_control.stats_info->sw_stat.
single_ecc_errs++; single_ecc_errs++;
...@@ -2706,7 +2750,8 @@ static void alarm_intr_handler(struct s2io_nic *nic) ...@@ -2706,7 +2750,8 @@ static void alarm_intr_handler(struct s2io_nic *nic)
val64 = readq(&bar0->serr_source); val64 = readq(&bar0->serr_source);
if (val64 & SERR_SOURCE_ANY) { if (val64 & SERR_SOURCE_ANY) {
DBG_PRINT(ERR_DBG, "%s: Device indicates ", dev->name); DBG_PRINT(ERR_DBG, "%s: Device indicates ", dev->name);
DBG_PRINT(ERR_DBG, "serious error!!\n"); DBG_PRINT(ERR_DBG, "serious error %llx!!\n",
(unsigned long long)val64);
netif_stop_queue(dev); netif_stop_queue(dev);
schedule_work(&nic->rst_timer_task); schedule_work(&nic->rst_timer_task);
} }
...@@ -3130,7 +3175,7 @@ int s2io_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -3130,7 +3175,7 @@ int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
queue_len = mac_control->fifos[queue].tx_curr_put_info.fifo_len + 1; queue_len = mac_control->fifos[queue].tx_curr_put_info.fifo_len + 1;
/* Avoid "put" pointer going beyond "get" pointer */ /* Avoid "put" pointer going beyond "get" pointer */
if (txdp->Host_Control || (((put_off + 1) % queue_len) == get_off)) { if (txdp->Host_Control || (((put_off + 1) % queue_len) == get_off)) {
DBG_PRINT(ERR_DBG, "Error in xmit, No free TXDs.\n"); DBG_PRINT(TX_DBG, "Error in xmit, No free TXDs.\n");
netif_stop_queue(dev); netif_stop_queue(dev);
dev_kfree_skb(skb); dev_kfree_skb(skb);
spin_unlock_irqrestore(&sp->tx_lock, flags); spin_unlock_irqrestore(&sp->tx_lock, flags);
...@@ -3528,7 +3573,7 @@ static void s2io_set_multicast(struct net_device *dev) ...@@ -3528,7 +3573,7 @@ static void s2io_set_multicast(struct net_device *dev)
val64 = readq(&bar0->mac_cfg); val64 = readq(&bar0->mac_cfg);
sp->promisc_flg = 1; sp->promisc_flg = 1;
DBG_PRINT(ERR_DBG, "%s: entered promiscuous mode\n", DBG_PRINT(INFO_DBG, "%s: entered promiscuous mode\n",
dev->name); dev->name);
} else if (!(dev->flags & IFF_PROMISC) && (sp->promisc_flg)) { } else if (!(dev->flags & IFF_PROMISC) && (sp->promisc_flg)) {
/* Remove the NIC from promiscuous mode */ /* Remove the NIC from promiscuous mode */
...@@ -3543,7 +3588,7 @@ static void s2io_set_multicast(struct net_device *dev) ...@@ -3543,7 +3588,7 @@ static void s2io_set_multicast(struct net_device *dev)
val64 = readq(&bar0->mac_cfg); val64 = readq(&bar0->mac_cfg);
sp->promisc_flg = 0; sp->promisc_flg = 0;
DBG_PRINT(ERR_DBG, "%s: left promiscuous mode\n", DBG_PRINT(INFO_DBG, "%s: left promiscuous mode\n",
dev->name); dev->name);
} }
...@@ -5325,7 +5370,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) ...@@ -5325,7 +5370,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
break; break;
} }
} }
config->max_txds = MAX_SKB_FRAGS; config->max_txds = MAX_SKB_FRAGS + 1;
/* Rx side parameters. */ /* Rx side parameters. */
if (rx_ring_sz[0] == 0) if (rx_ring_sz[0] == 0)
...@@ -5525,9 +5570,14 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) ...@@ -5525,9 +5570,14 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
if (sp->device_type & XFRAME_II_DEVICE) { if (sp->device_type & XFRAME_II_DEVICE) {
DBG_PRINT(ERR_DBG, "%s: Neterion Xframe II 10GbE adapter ", DBG_PRINT(ERR_DBG, "%s: Neterion Xframe II 10GbE adapter ",
dev->name); dev->name);
DBG_PRINT(ERR_DBG, "(rev %d), Driver %s\n", DBG_PRINT(ERR_DBG, "(rev %d), %s",
get_xena_rev_id(sp->pdev), get_xena_rev_id(sp->pdev),
s2io_driver_version); s2io_driver_version);
#ifdef CONFIG_2BUFF_MODE
DBG_PRINT(ERR_DBG, ", Buffer mode %d",2);
#endif
DBG_PRINT(ERR_DBG, "\nCopyright(c) 2002-2005 Neterion Inc.\n");
DBG_PRINT(ERR_DBG, "MAC ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n", DBG_PRINT(ERR_DBG, "MAC ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n",
sp->def_mac_addr[0].mac_addr[0], sp->def_mac_addr[0].mac_addr[0],
sp->def_mac_addr[0].mac_addr[1], sp->def_mac_addr[0].mac_addr[1],
...@@ -5544,9 +5594,13 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) ...@@ -5544,9 +5594,13 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
} else { } else {
DBG_PRINT(ERR_DBG, "%s: Neterion Xframe I 10GbE adapter ", DBG_PRINT(ERR_DBG, "%s: Neterion Xframe I 10GbE adapter ",
dev->name); dev->name);
DBG_PRINT(ERR_DBG, "(rev %d), Driver %s\n", DBG_PRINT(ERR_DBG, "(rev %d), %s",
get_xena_rev_id(sp->pdev), get_xena_rev_id(sp->pdev),
s2io_driver_version); s2io_driver_version);
#ifdef CONFIG_2BUFF_MODE
DBG_PRINT(ERR_DBG, ", Buffer mode %d",2);
#endif
DBG_PRINT(ERR_DBG, "\nCopyright(c) 2002-2005 Neterion Inc.\n");
DBG_PRINT(ERR_DBG, "MAC ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n", DBG_PRINT(ERR_DBG, "MAC ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n",
sp->def_mac_addr[0].mac_addr[0], sp->def_mac_addr[0].mac_addr[0],
sp->def_mac_addr[0].mac_addr[1], sp->def_mac_addr[0].mac_addr[1],
......
/************************************************************************ /************************************************************************
* s2io.h: A Linux PCI-X Ethernet driver for S2IO 10GbE Server NIC * s2io.h: A Linux PCI-X Ethernet driver for Neterion 10GbE Server NIC
* Copyright(c) 2002-2005 Neterion Inc. * Copyright(c) 2002-2005 Neterion Inc.
* This software may be used and distributed according to the terms of * This software may be used and distributed according to the terms of
...@@ -622,6 +622,9 @@ typedef struct mac_info { ...@@ -622,6 +622,9 @@ typedef struct mac_info {
/* Fifo specific structure */ /* Fifo specific structure */
fifo_info_t fifos[MAX_TX_FIFOS]; fifo_info_t fifos[MAX_TX_FIFOS];
/* Save virtual address of TxD page with zero DMA addr(if any) */
void *zerodma_virt_addr;
/* rx side stuff */ /* rx side stuff */
/* Ring specific structure */ /* Ring specific structure */
ring_info_t rings[MAX_RX_RINGS]; ring_info_t rings[MAX_RX_RINGS];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment