Commit 19a60522 authored by Sivakumar Subramani's avatar Sivakumar Subramani Committed by Jeff Garzik

S2IO: Fixes for reset and link handling.

1. Fix for reset and link handling.
2. Allow for promiscuos mode and multicast state be maintained through
   ifconfig up and down.
3. Support to print adapter serial number.
Signed-off-by: default avatarSivakumar Subramani <sivakumar.subramani@neterion.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent db874e65
...@@ -300,6 +300,7 @@ typedef struct _XENA_dev_config { ...@@ -300,6 +300,7 @@ typedef struct _XENA_dev_config {
u64 gpio_control; u64 gpio_control;
#define GPIO_CTRL_GPIO_0 BIT(8) #define GPIO_CTRL_GPIO_0 BIT(8)
u64 misc_control; u64 misc_control;
#define FAULT_BEHAVIOUR BIT(0)
#define EXT_REQ_EN BIT(1) #define EXT_REQ_EN BIT(1)
#define MISC_LINK_STABILITY_PRD(val) vBIT(val,29,3) #define MISC_LINK_STABILITY_PRD(val) vBIT(val,29,3)
......
...@@ -1415,7 +1415,7 @@ static int init_nic(struct s2io_nic *nic) ...@@ -1415,7 +1415,7 @@ static int init_nic(struct s2io_nic *nic)
val64 = TTI_DATA2_MEM_TX_UFC_A(0x10) | val64 = TTI_DATA2_MEM_TX_UFC_A(0x10) |
TTI_DATA2_MEM_TX_UFC_B(0x20) | TTI_DATA2_MEM_TX_UFC_B(0x20) |
TTI_DATA2_MEM_TX_UFC_C(0x70) | TTI_DATA2_MEM_TX_UFC_D(0x80); TTI_DATA2_MEM_TX_UFC_C(0x40) | TTI_DATA2_MEM_TX_UFC_D(0x80);
writeq(val64, &bar0->tti_data2_mem); writeq(val64, &bar0->tti_data2_mem);
val64 = TTI_CMD_MEM_WE | TTI_CMD_MEM_STROBE_NEW_CMD; val64 = TTI_CMD_MEM_WE | TTI_CMD_MEM_STROBE_NEW_CMD;
...@@ -1611,7 +1611,8 @@ static int init_nic(struct s2io_nic *nic) ...@@ -1611,7 +1611,8 @@ static int init_nic(struct s2io_nic *nic)
* that does not start on an ADB to reduce disconnects. * that does not start on an ADB to reduce disconnects.
*/ */
if (nic->device_type == XFRAME_II_DEVICE) { if (nic->device_type == XFRAME_II_DEVICE) {
val64 = EXT_REQ_EN | MISC_LINK_STABILITY_PRD(3); val64 = FAULT_BEHAVIOUR | EXT_REQ_EN |
MISC_LINK_STABILITY_PRD(3);
writeq(val64, &bar0->misc_control); writeq(val64, &bar0->misc_control);
val64 = readq(&bar0->pic_control2); val64 = readq(&bar0->pic_control2);
val64 &= ~(BIT(13)|BIT(14)|BIT(15)); val64 &= ~(BIT(13)|BIT(14)|BIT(15));
...@@ -1878,41 +1879,36 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag) ...@@ -1878,41 +1879,36 @@ 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, int rev_id, int herc) /**
* verify_pcc_quiescent- Checks for PCC quiescent state
* Return: 1 If PCC is quiescence
* 0 If PCC is not quiescence
*/
static int verify_pcc_quiescent(nic_t *sp, int flag)
{ {
int ret = 0; int ret = 0, herc;
XENA_dev_config_t __iomem *bar0 = sp->bar0;
u64 val64 = readq(&bar0->adapter_status);
herc = (sp->device_type == XFRAME_II_DEVICE);
if (flag == FALSE) { if (flag == FALSE) {
if ((!herc && (rev_id >= 4)) || herc) { if ((!herc && (get_xena_rev_id(sp->pdev) >= 4)) || herc) {
if (!(val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) && if (!(val64 & ADAPTER_STATUS_RMAC_PCC_IDLE))
((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ==
ADAPTER_STATUS_RC_PRC_QUIESCENT)) {
ret = 1; ret = 1;
} } else {
}else { if (!(val64 & ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE))
if (!(val64 & ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE) &&
((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ==
ADAPTER_STATUS_RC_PRC_QUIESCENT)) {
ret = 1; ret = 1;
}
} }
} else { } else {
if ((!herc && (rev_id >= 4)) || herc) { if ((!herc && (get_xena_rev_id(sp->pdev) >= 4)) || herc) {
if (((val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) == if (((val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) ==
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; ret = 1;
}
} else { } else {
if (((val64 & ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE) == if (((val64 & ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE) ==
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; ret = 1;
}
} }
} }
...@@ -1920,9 +1916,6 @@ static int check_prc_pcc_state(u64 val64, int flag, int rev_id, int herc) ...@@ -1920,9 +1916,6 @@ static int check_prc_pcc_state(u64 val64, int flag, int rev_id, int herc)
} }
/** /**
* verify_xena_quiescence - Checks whether the H/W is ready * verify_xena_quiescence - Checks whether the H/W is ready
* @val64 : Value read from adapter status register.
* @flag : indicates if the adapter enable bit was ever written once
* before.
* Description: Returns whether the H/W is ready to go or not. Depending * Description: Returns whether the H/W is ready to go or not. Depending
* on whether adapter enable bit was written or not the comparison * on whether adapter enable bit was written or not the comparison
* differs and the calling function passes the input argument flag to * differs and the calling function passes the input argument flag to
...@@ -1931,24 +1924,63 @@ static int check_prc_pcc_state(u64 val64, int flag, int rev_id, int herc) ...@@ -1931,24 +1924,63 @@ static int check_prc_pcc_state(u64 val64, int flag, int rev_id, int herc)
* 0 If Xena is not quiescence * 0 If Xena is not quiescence
*/ */
static int verify_xena_quiescence(nic_t *sp, u64 val64, int flag) static int verify_xena_quiescence(nic_t *sp)
{ {
int ret = 0, herc; int mode;
u64 tmp64 = ~((u64) val64); XENA_dev_config_t __iomem *bar0 = sp->bar0;
int rev_id = get_xena_rev_id(sp->pdev); u64 val64 = readq(&bar0->adapter_status);
mode = s2io_verify_pci_mode(sp);
herc = (sp->device_type == XFRAME_II_DEVICE); if (!(val64 & ADAPTER_STATUS_TDMA_READY)) {
if (! DBG_PRINT(ERR_DBG, "%s", "TDMA is not ready!");
(tmp64 & return 0;
(ADAPTER_STATUS_TDMA_READY | ADAPTER_STATUS_RDMA_READY | }
ADAPTER_STATUS_PFC_READY | ADAPTER_STATUS_TMAC_BUF_EMPTY | if (!(val64 & ADAPTER_STATUS_RDMA_READY)) {
ADAPTER_STATUS_PIC_QUIESCENT | ADAPTER_STATUS_MC_DRAM_READY | DBG_PRINT(ERR_DBG, "%s", "RDMA is not ready!");
ADAPTER_STATUS_MC_QUEUES_READY | ADAPTER_STATUS_M_PLL_LOCK | return 0;
ADAPTER_STATUS_P_PLL_LOCK))) { }
ret = check_prc_pcc_state(val64, flag, rev_id, herc); if (!(val64 & ADAPTER_STATUS_PFC_READY)) {
DBG_PRINT(ERR_DBG, "%s", "PFC is not ready!");
return 0;
}
if (!(val64 & ADAPTER_STATUS_TMAC_BUF_EMPTY)) {
DBG_PRINT(ERR_DBG, "%s", "TMAC BUF is not empty!");
return 0;
}
if (!(val64 & ADAPTER_STATUS_PIC_QUIESCENT)) {
DBG_PRINT(ERR_DBG, "%s", "PIC is not QUIESCENT!");
return 0;
}
if (!(val64 & ADAPTER_STATUS_MC_DRAM_READY)) {
DBG_PRINT(ERR_DBG, "%s", "MC_DRAM is not ready!");
return 0;
}
if (!(val64 & ADAPTER_STATUS_MC_QUEUES_READY)) {
DBG_PRINT(ERR_DBG, "%s", "MC_QUEUES is not ready!");
return 0;
}
if (!(val64 & ADAPTER_STATUS_M_PLL_LOCK)) {
DBG_PRINT(ERR_DBG, "%s", "M_PLL is not locked!");
return 0;
} }
return ret; /*
* In PCI 33 mode, the P_PLL is not used, and therefore,
* the the P_PLL_LOCK bit in the adapter_status register will
* not be asserted.
*/
if (!(val64 & ADAPTER_STATUS_P_PLL_LOCK) &&
sp->device_type == XFRAME_II_DEVICE && mode !=
PCI_MODE_PCI_33) {
DBG_PRINT(ERR_DBG, "%s", "P_PLL is not locked!");
return 0;
}
if (!((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ==
ADAPTER_STATUS_RC_PRC_QUIESCENT)) {
DBG_PRINT(ERR_DBG, "%s", "RC_PRC is not QUIESCENT!");
return 0;
}
return 1;
} }
/** /**
...@@ -2053,7 +2085,7 @@ static int start_nic(struct s2io_nic *nic) ...@@ -2053,7 +2085,7 @@ static int start_nic(struct s2io_nic *nic)
* it. * it.
*/ */
val64 = readq(&bar0->adapter_status); val64 = readq(&bar0->adapter_status);
if (!verify_xena_quiescence(nic, val64, nic->device_enabled_once)) { if (!verify_xena_quiescence(nic)) {
DBG_PRINT(ERR_DBG, "%s: device is not ready, ", dev->name); DBG_PRINT(ERR_DBG, "%s: device is not ready, ", dev->name);
DBG_PRINT(ERR_DBG, "Adapter status reads: 0x%llx\n", DBG_PRINT(ERR_DBG, "Adapter status reads: 0x%llx\n",
(unsigned long long) val64); (unsigned long long) val64);
...@@ -2577,7 +2609,6 @@ static int s2io_poll(struct net_device *dev, int *budget) ...@@ -2577,7 +2609,6 @@ static int s2io_poll(struct net_device *dev, int *budget)
mac_info_t *mac_control; mac_info_t *mac_control;
struct config_param *config; struct config_param *config;
XENA_dev_config_t __iomem *bar0 = nic->bar0; XENA_dev_config_t __iomem *bar0 = nic->bar0;
u64 val64 = 0xFFFFFFFFFFFFFFFFULL;
int i; int i;
atomic_inc(&nic->isr_cnt); atomic_inc(&nic->isr_cnt);
...@@ -2589,8 +2620,8 @@ static int s2io_poll(struct net_device *dev, int *budget) ...@@ -2589,8 +2620,8 @@ static int s2io_poll(struct net_device *dev, int *budget)
nic->pkts_to_process = dev->quota; nic->pkts_to_process = dev->quota;
org_pkts_to_process = nic->pkts_to_process; org_pkts_to_process = nic->pkts_to_process;
writeq(val64, &bar0->rx_traffic_int); writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_int);
val64 = readl(&bar0->rx_traffic_int); readl(&bar0->rx_traffic_int);
for (i = 0; i < config->rx_ring_num; i++) { for (i = 0; i < config->rx_ring_num; i++) {
rx_intr_handler(&mac_control->rings[i]); rx_intr_handler(&mac_control->rings[i]);
...@@ -2616,7 +2647,7 @@ static int s2io_poll(struct net_device *dev, int *budget) ...@@ -2616,7 +2647,7 @@ static int s2io_poll(struct net_device *dev, int *budget)
} }
/* Re enable the Rx interrupts. */ /* Re enable the Rx interrupts. */
writeq(0x0, &bar0->rx_traffic_mask); writeq(0x0, &bar0->rx_traffic_mask);
val64 = readl(&bar0->rx_traffic_mask); readl(&bar0->rx_traffic_mask);
atomic_dec(&nic->isr_cnt); atomic_dec(&nic->isr_cnt);
return 0; return 0;
...@@ -2851,11 +2882,10 @@ static void tx_intr_handler(fifo_info_t *fifo_data) ...@@ -2851,11 +2882,10 @@ static void tx_intr_handler(fifo_info_t *fifo_data)
} }
if ((err >> 48) == 0xA) { if ((err >> 48) == 0xA) {
DBG_PRINT(TX_DBG, "TxD returned due \ DBG_PRINT(TX_DBG, "TxD returned due \
to loss of link\n"); to loss of link\n");
} }
else { else {
DBG_PRINT(ERR_DBG, "***TxD error \ DBG_PRINT(ERR_DBG, "***TxD error %llx\n", err);
%llx\n", err);
} }
} }
...@@ -3294,6 +3324,25 @@ static int wait_for_cmd_complete(void __iomem *addr, u64 busy_bit) ...@@ -3294,6 +3324,25 @@ static int wait_for_cmd_complete(void __iomem *addr, u64 busy_bit)
} }
return ret; return ret;
} }
/*
* check_pci_device_id - Checks if the device id is supported
* @id : device id
* Description: Function to check if the pci device id is supported by driver.
* Return value: Actual device id if supported else PCI_ANY_ID
*/
static u16 check_pci_device_id(u16 id)
{
switch (id) {
case PCI_DEVICE_ID_HERC_WIN:
case PCI_DEVICE_ID_HERC_UNI:
return XFRAME_II_DEVICE;
case PCI_DEVICE_ID_S2IO_UNI:
case PCI_DEVICE_ID_S2IO_WIN:
return XFRAME_I_DEVICE;
default:
return PCI_ANY_ID;
}
}
/** /**
* s2io_reset - Resets the card. * s2io_reset - Resets the card.
...@@ -3310,37 +3359,52 @@ static void s2io_reset(nic_t * sp) ...@@ -3310,37 +3359,52 @@ static void s2io_reset(nic_t * sp)
XENA_dev_config_t __iomem *bar0 = sp->bar0; XENA_dev_config_t __iomem *bar0 = sp->bar0;
u64 val64; u64 val64;
u16 subid, pci_cmd; u16 subid, pci_cmd;
int i;
u16 val16;
DBG_PRINT(INIT_DBG,"%s - Resetting XFrame card %s\n",
__FUNCTION__, sp->dev->name);
/* Back up the PCI-X CMD reg, dont want to lose MMRBC, OST settings */ /* Back up the PCI-X CMD reg, dont want to lose MMRBC, OST settings */
pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER, &(pci_cmd)); pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER, &(pci_cmd));
if (sp->device_type == XFRAME_II_DEVICE) {
int ret;
ret = pci_set_power_state(sp->pdev, 3);
if (!ret)
ret = pci_set_power_state(sp->pdev, 0);
else {
DBG_PRINT(ERR_DBG,"%s PME based SW_Reset failed!\n",
__FUNCTION__);
goto old_way;
}
msleep(20);
goto new_way;
}
old_way:
val64 = SW_RESET_ALL; val64 = SW_RESET_ALL;
writeq(val64, &bar0->sw_reset); writeq(val64, &bar0->sw_reset);
new_way:
/*
* At this stage, if the PCI write is indeed completed, the
* card is reset and so is the PCI Config space of the device.
* So a read cannot be issued at this stage on any of the
* registers to ensure the write into "sw_reset" register
* has gone through.
* Question: Is there any system call that will explicitly force
* all the write commands still pending on the bus to be pushed
* through?
* As of now I'am just giving a 250ms delay and hoping that the
* PCI write to sw_reset register is done by this time.
*/
msleep(250);
if (strstr(sp->product_name, "CX4")) { if (strstr(sp->product_name, "CX4")) {
msleep(750); msleep(750);
} }
msleep(250);
for (i = 0; i < S2IO_MAX_PCI_CONFIG_SPACE_REINIT; i++) {
/* Restore the PCI state saved during initialization. */ /* Restore the PCI state saved during initialization. */
pci_restore_state(sp->pdev); pci_restore_state(sp->pdev);
pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER, pci_read_config_word(sp->pdev, 0x2, &val16);
pci_cmd); if (check_pci_device_id(val16) != (u16)PCI_ANY_ID)
s2io_init_pci(sp); break;
msleep(200);
}
msleep(250); if (check_pci_device_id(val16) == (u16)PCI_ANY_ID) {
DBG_PRINT(ERR_DBG,"%s SW_Reset failed!\n", __FUNCTION__);
}
pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER, pci_cmd);
s2io_init_pci(sp);
/* Set swapper to enable I/O register access */ /* Set swapper to enable I/O register access */
s2io_set_swapper(sp); s2io_set_swapper(sp);
...@@ -4104,39 +4168,33 @@ static void s2io_txpic_intr_handle(nic_t *sp) ...@@ -4104,39 +4168,33 @@ static void s2io_txpic_intr_handle(nic_t *sp)
} }
else if (val64 & GPIO_INT_REG_LINK_UP) { else if (val64 & GPIO_INT_REG_LINK_UP) {
val64 = readq(&bar0->adapter_status); val64 = readq(&bar0->adapter_status);
if (verify_xena_quiescence(sp, val64,
sp->device_enabled_once)) {
/* Enable Adapter */ /* Enable Adapter */
val64 = readq(&bar0->adapter_control); val64 = readq(&bar0->adapter_control);
val64 |= ADAPTER_CNTL_EN; val64 |= ADAPTER_CNTL_EN;
writeq(val64, &bar0->adapter_control); writeq(val64, &bar0->adapter_control);
val64 |= ADAPTER_LED_ON; val64 |= ADAPTER_LED_ON;
writeq(val64, &bar0->adapter_control); writeq(val64, &bar0->adapter_control);
if (!sp->device_enabled_once) if (!sp->device_enabled_once)
sp->device_enabled_once = 1; sp->device_enabled_once = 1;
s2io_link(sp, LINK_UP); s2io_link(sp, LINK_UP);
/* /*
* unmask link down interrupt and mask link-up * unmask link down interrupt and mask link-up
* intr * intr
*/ */
val64 = readq(&bar0->gpio_int_mask); val64 = readq(&bar0->gpio_int_mask);
val64 &= ~GPIO_INT_MASK_LINK_DOWN; val64 &= ~GPIO_INT_MASK_LINK_DOWN;
val64 |= GPIO_INT_MASK_LINK_UP; val64 |= GPIO_INT_MASK_LINK_UP;
writeq(val64, &bar0->gpio_int_mask); writeq(val64, &bar0->gpio_int_mask);
}
}else if (val64 & GPIO_INT_REG_LINK_DOWN) { }else if (val64 & GPIO_INT_REG_LINK_DOWN) {
val64 = readq(&bar0->adapter_status); val64 = readq(&bar0->adapter_status);
if (verify_xena_quiescence(sp, val64, s2io_link(sp, LINK_DOWN);
sp->device_enabled_once)) { /* Link is down so unmaks link up interrupt */
s2io_link(sp, LINK_DOWN); val64 = readq(&bar0->gpio_int_mask);
/* Link is down so unmaks link up interrupt */ val64 &= ~GPIO_INT_MASK_LINK_UP;
val64 = readq(&bar0->gpio_int_mask); val64 |= GPIO_INT_MASK_LINK_DOWN;
val64 &= ~GPIO_INT_MASK_LINK_UP; writeq(val64, &bar0->gpio_int_mask);
val64 |= GPIO_INT_MASK_LINK_DOWN;
writeq(val64, &bar0->gpio_int_mask);
}
} }
} }
val64 = readq(&bar0->gpio_int_mask); val64 = readq(&bar0->gpio_int_mask);
...@@ -4161,7 +4219,7 @@ static irqreturn_t s2io_isr(int irq, void *dev_id) ...@@ -4161,7 +4219,7 @@ static irqreturn_t s2io_isr(int irq, void *dev_id)
nic_t *sp = dev->priv; nic_t *sp = dev->priv;
XENA_dev_config_t __iomem *bar0 = sp->bar0; XENA_dev_config_t __iomem *bar0 = sp->bar0;
int i; int i;
u64 reason = 0, val64, org_mask; u64 reason = 0;
mac_info_t *mac_control; mac_info_t *mac_control;
struct config_param *config; struct config_param *config;
...@@ -4180,22 +4238,24 @@ static irqreturn_t s2io_isr(int irq, void *dev_id) ...@@ -4180,22 +4238,24 @@ static irqreturn_t s2io_isr(int irq, void *dev_id)
reason = readq(&bar0->general_int_status); reason = readq(&bar0->general_int_status);
if (!reason) { if (!reason) {
/* The interrupt was not raised by Xena. */ /* The interrupt was not raised by us. */
atomic_dec(&sp->isr_cnt);
return IRQ_NONE;
}
else if (unlikely(reason == S2IO_MINUS_ONE) ) {
/* Disable device and get out */
atomic_dec(&sp->isr_cnt); atomic_dec(&sp->isr_cnt);
return IRQ_NONE; return IRQ_NONE;
} }
val64 = 0xFFFFFFFFFFFFFFFFULL;
/* Store current mask before masking all interrupts */
org_mask = readq(&bar0->general_int_mask);
writeq(val64, &bar0->general_int_mask);
if (napi) { if (napi) {
if (reason & GEN_INTR_RXTRAFFIC) { if (reason & GEN_INTR_RXTRAFFIC) {
if (netif_rx_schedule_prep(dev)) { if ( likely ( netif_rx_schedule_prep(dev)) ) {
writeq(val64, &bar0->rx_traffic_mask);
__netif_rx_schedule(dev); __netif_rx_schedule(dev);
writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_mask);
} }
else
writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_int);
} }
} else { } else {
/* /*
...@@ -4205,7 +4265,9 @@ static irqreturn_t s2io_isr(int irq, void *dev_id) ...@@ -4205,7 +4265,9 @@ static irqreturn_t s2io_isr(int irq, void *dev_id)
* will ensure that the actual interrupt causing bit get's * will ensure that the actual interrupt causing bit get's
* cleared and hence a read can be avoided. * cleared and hence a read can be avoided.
*/ */
writeq(val64, &bar0->rx_traffic_int); if (reason & GEN_INTR_RXTRAFFIC)
writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_int);
for (i = 0; i < config->rx_ring_num; i++) { for (i = 0; i < config->rx_ring_num; i++) {
rx_intr_handler(&mac_control->rings[i]); rx_intr_handler(&mac_control->rings[i]);
} }
...@@ -4216,7 +4278,8 @@ static irqreturn_t s2io_isr(int irq, void *dev_id) ...@@ -4216,7 +4278,8 @@ static irqreturn_t s2io_isr(int irq, void *dev_id)
* will ensure that the actual interrupt causing bit get's * will ensure that the actual interrupt causing bit get's
* cleared and hence a read can be avoided. * cleared and hence a read can be avoided.
*/ */
writeq(val64, &bar0->tx_traffic_int); if (reason & GEN_INTR_TXTRAFFIC)
writeq(S2IO_MINUS_ONE, &bar0->tx_traffic_int);
for (i = 0; i < config->tx_fifo_num; i++) for (i = 0; i < config->tx_fifo_num; i++)
tx_intr_handler(&mac_control->fifos[i]); tx_intr_handler(&mac_control->fifos[i]);
...@@ -4912,6 +4975,7 @@ static void s2io_vpd_read(nic_t *nic) ...@@ -4912,6 +4975,7 @@ static void s2io_vpd_read(nic_t *nic)
strcpy(nic->product_name, "Xframe I 10GbE network adapter"); strcpy(nic->product_name, "Xframe I 10GbE network adapter");
vpd_addr = 0x50; vpd_addr = 0x50;
} }
strcpy(nic->serial_num, "NOT AVAILABLE");
vpd_data = kmalloc(256, GFP_KERNEL); vpd_data = kmalloc(256, GFP_KERNEL);
if (!vpd_data) if (!vpd_data)
...@@ -4935,7 +4999,22 @@ static void s2io_vpd_read(nic_t *nic) ...@@ -4935,7 +4999,22 @@ static void s2io_vpd_read(nic_t *nic)
pci_read_config_dword(nic->pdev, (vpd_addr + 4), pci_read_config_dword(nic->pdev, (vpd_addr + 4),
(u32 *)&vpd_data[i]); (u32 *)&vpd_data[i]);
} }
if ((!fail) && (vpd_data[1] < VPD_PRODUCT_NAME_LEN)) {
if(!fail) {
/* read serial number of adapter */
for (cnt = 0; cnt < 256; cnt++) {
if ((vpd_data[cnt] == 'S') &&
(vpd_data[cnt+1] == 'N') &&
(vpd_data[cnt+2] < VPD_STRING_LEN)) {
memset(nic->serial_num, 0, VPD_STRING_LEN);
memcpy(nic->serial_num, &vpd_data[cnt + 3],
vpd_data[cnt+2]);
break;
}
}
}
if ((!fail) && (vpd_data[1] < VPD_STRING_LEN)) {
memset(nic->product_name, 0, vpd_data[1]); memset(nic->product_name, 0, vpd_data[1]);
memcpy(nic->product_name, &vpd_data[3], vpd_data[1]); memcpy(nic->product_name, &vpd_data[3], vpd_data[1]);
} }
...@@ -5890,50 +5969,45 @@ static void s2io_set_link(struct work_struct *work) ...@@ -5890,50 +5969,45 @@ static void s2io_set_link(struct work_struct *work)
} }
val64 = readq(&bar0->adapter_status); val64 = readq(&bar0->adapter_status);
if (verify_xena_quiescence(nic, val64, nic->device_enabled_once)) { if (LINK_IS_UP(val64)) {
if (LINK_IS_UP(val64)) { if (!(readq(&bar0->adapter_control) & ADAPTER_CNTL_EN)) {
val64 = readq(&bar0->adapter_control); if (verify_xena_quiescence(nic)) {
val64 |= ADAPTER_CNTL_EN; val64 = readq(&bar0->adapter_control);
writeq(val64, &bar0->adapter_control); val64 |= ADAPTER_CNTL_EN;
if (CARDS_WITH_FAULTY_LINK_INDICATORS(nic->device_type,
subid)) {
val64 = readq(&bar0->gpio_control);
val64 |= GPIO_CTRL_GPIO_0;
writeq(val64, &bar0->gpio_control);
val64 = readq(&bar0->gpio_control);
} else {
val64 |= ADAPTER_LED_ON;
writeq(val64, &bar0->adapter_control); writeq(val64, &bar0->adapter_control);
} if (CARDS_WITH_FAULTY_LINK_INDICATORS(
if (s2io_link_fault_indication(nic) == nic->device_type, subid)) {
MAC_RMAC_ERR_TIMER) { val64 = readq(&bar0->gpio_control);
val64 = readq(&bar0->adapter_status); val64 |= GPIO_CTRL_GPIO_0;
if (!LINK_IS_UP(val64)) { writeq(val64, &bar0->gpio_control);
DBG_PRINT(ERR_DBG, "%s:", dev->name); val64 = readq(&bar0->gpio_control);
DBG_PRINT(ERR_DBG, " Link down"); } else {
DBG_PRINT(ERR_DBG, "after "); val64 |= ADAPTER_LED_ON;
DBG_PRINT(ERR_DBG, "enabling "); writeq(val64, &bar0->adapter_control);
DBG_PRINT(ERR_DBG, "device \n");
} }
}
if (nic->device_enabled_once == FALSE) {
nic->device_enabled_once = TRUE; nic->device_enabled_once = TRUE;
} else {
DBG_PRINT(ERR_DBG, "%s: Error: ", dev->name);
DBG_PRINT(ERR_DBG, "device is not Quiescent\n");
netif_stop_queue(dev);
} }
}
val64 = readq(&bar0->adapter_status);
if (!LINK_IS_UP(val64)) {
DBG_PRINT(ERR_DBG, "%s:", dev->name);
DBG_PRINT(ERR_DBG, " Link down after enabling ");
DBG_PRINT(ERR_DBG, "device \n");
} else
s2io_link(nic, LINK_UP); s2io_link(nic, LINK_UP);
} else { } else {
if (CARDS_WITH_FAULTY_LINK_INDICATORS(nic->device_type, if (CARDS_WITH_FAULTY_LINK_INDICATORS(nic->device_type,
subid)) { subid)) {
val64 = readq(&bar0->gpio_control); val64 = readq(&bar0->gpio_control);
val64 &= ~GPIO_CTRL_GPIO_0; val64 &= ~GPIO_CTRL_GPIO_0;
writeq(val64, &bar0->gpio_control); writeq(val64, &bar0->gpio_control);
val64 = readq(&bar0->gpio_control); val64 = readq(&bar0->gpio_control);
}
s2io_link(nic, LINK_DOWN);
} }
} else { /* NIC is not Quiescent. */ s2io_link(nic, LINK_DOWN);
DBG_PRINT(ERR_DBG, "%s: Error: ", dev->name);
DBG_PRINT(ERR_DBG, "device is not Quiescent\n");
netif_stop_queue(dev);
} }
clear_bit(0, &(nic->link_state)); clear_bit(0, &(nic->link_state));
} }
...@@ -5982,7 +6056,7 @@ static int set_rxd_buffer_pointer(nic_t *sp, RxD_t *rxdp, buffAdd_t *ba, ...@@ -5982,7 +6056,7 @@ static int set_rxd_buffer_pointer(nic_t *sp, RxD_t *rxdp, buffAdd_t *ba,
*skb = dev_alloc_skb(size); *skb = dev_alloc_skb(size);
if (!(*skb)) { if (!(*skb)) {
DBG_PRINT(ERR_DBG, "%s: dev_alloc_skb failed\n", DBG_PRINT(ERR_DBG, "%s: dev_alloc_skb failed\n",
dev->name); dev->name);
return -ENOMEM; return -ENOMEM;
} }
((RxD3_t*)rxdp)->Buffer2_ptr = *temp2 = ((RxD3_t*)rxdp)->Buffer2_ptr = *temp2 =
...@@ -6252,7 +6326,8 @@ static void s2io_card_down(nic_t * sp) ...@@ -6252,7 +6326,8 @@ static void s2io_card_down(nic_t * sp)
rxd_owner_bit_reset(sp); rxd_owner_bit_reset(sp);
val64 = readq(&bar0->adapter_status); val64 = readq(&bar0->adapter_status);
if (verify_xena_quiescence(sp, val64, sp->device_enabled_once)) { if (verify_xena_quiescence(sp)) {
if(verify_pcc_quiescent(sp, sp->device_enabled_once))
break; break;
} }
...@@ -6315,6 +6390,13 @@ static int s2io_card_up(nic_t * sp) ...@@ -6315,6 +6390,13 @@ static int s2io_card_up(nic_t * sp)
DBG_PRINT(INFO_DBG, "Buf in ring:%d is %d:\n", i, DBG_PRINT(INFO_DBG, "Buf in ring:%d is %d:\n", i,
atomic_read(&sp->rx_bufs_left[i])); atomic_read(&sp->rx_bufs_left[i]));
} }
/* Maintain the state prior to the open */
if (sp->promisc_flg)
sp->promisc_flg = 0;
if (sp->m_cast_flg) {
sp->m_cast_flg = 0;
sp->all_multi_pos= 0;
}
/* Setting its receive mode */ /* Setting its receive mode */
s2io_set_multicast(dev); s2io_set_multicast(dev);
...@@ -6914,7 +6996,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) ...@@ -6914,7 +6996,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
sp->bar0 = ioremap(pci_resource_start(pdev, 0), sp->bar0 = ioremap(pci_resource_start(pdev, 0),
pci_resource_len(pdev, 0)); pci_resource_len(pdev, 0));
if (!sp->bar0) { if (!sp->bar0) {
DBG_PRINT(ERR_DBG, "%s: S2IO: cannot remap io mem1\n", DBG_PRINT(ERR_DBG, "%s: Neterion: cannot remap io mem1\n",
dev->name); dev->name);
ret = -ENOMEM; ret = -ENOMEM;
goto bar0_remap_failed; goto bar0_remap_failed;
...@@ -6923,7 +7005,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) ...@@ -6923,7 +7005,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
sp->bar1 = ioremap(pci_resource_start(pdev, 2), sp->bar1 = ioremap(pci_resource_start(pdev, 2),
pci_resource_len(pdev, 2)); pci_resource_len(pdev, 2));
if (!sp->bar1) { if (!sp->bar1) {
DBG_PRINT(ERR_DBG, "%s: S2IO: cannot remap io mem2\n", DBG_PRINT(ERR_DBG, "%s: Neterion: cannot remap io mem2\n",
dev->name); dev->name);
ret = -ENOMEM; ret = -ENOMEM;
goto bar1_remap_failed; goto bar1_remap_failed;
...@@ -7081,13 +7163,14 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) ...@@ -7081,13 +7163,14 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
DBG_PRINT(ERR_DBG, "%s: Driver version %s\n", dev->name, DBG_PRINT(ERR_DBG, "%s: Driver version %s\n", dev->name,
s2io_driver_version); s2io_driver_version);
DBG_PRINT(ERR_DBG, "%s: MAC ADDR: " DBG_PRINT(ERR_DBG, "%s: MAC ADDR: "
"%02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, "%02x:%02x:%02x:%02x:%02x:%02x", dev->name,
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],
sp->def_mac_addr[0].mac_addr[2], sp->def_mac_addr[0].mac_addr[2],
sp->def_mac_addr[0].mac_addr[3], sp->def_mac_addr[0].mac_addr[3],
sp->def_mac_addr[0].mac_addr[4], sp->def_mac_addr[0].mac_addr[4],
sp->def_mac_addr[0].mac_addr[5]); sp->def_mac_addr[0].mac_addr[5]);
DBG_PRINT(ERR_DBG, "SERIAL NUMBER: %s\n", sp->serial_num);
if (sp->device_type & XFRAME_II_DEVICE) { if (sp->device_type & XFRAME_II_DEVICE) {
mode = s2io_print_pci_mode(sp); mode = s2io_print_pci_mode(sp);
if (mode < 0) { if (mode < 0) {
...@@ -7200,7 +7283,6 @@ static void __devexit s2io_rem_nic(struct pci_dev *pdev) ...@@ -7200,7 +7283,6 @@ static void __devexit s2io_rem_nic(struct pci_dev *pdev)
free_shared_mem(sp); free_shared_mem(sp);
iounmap(sp->bar0); iounmap(sp->bar0);
iounmap(sp->bar1); iounmap(sp->bar1);
pci_disable_device(pdev);
if (sp->intr_type != MSI_X) if (sp->intr_type != MSI_X)
pci_release_regions(pdev); pci_release_regions(pdev);
else { else {
...@@ -7211,6 +7293,7 @@ static void __devexit s2io_rem_nic(struct pci_dev *pdev) ...@@ -7211,6 +7293,7 @@ static void __devexit s2io_rem_nic(struct pci_dev *pdev)
} }
pci_set_drvdata(pdev, NULL); pci_set_drvdata(pdev, NULL);
free_netdev(dev); free_netdev(dev);
pci_disable_device(pdev);
} }
/** /**
......
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
#undef SUCCESS #undef SUCCESS
#define SUCCESS 0 #define SUCCESS 0
#define FAILURE -1 #define FAILURE -1
#define S2IO_MINUS_ONE 0xFFFFFFFFFFFFFFFFULL
#define S2IO_MAX_PCI_CONFIG_SPACE_REINIT 100
#define CHECKBIT(value, nbit) (value & (1 << nbit)) #define CHECKBIT(value, nbit) (value & (1 << nbit))
...@@ -537,9 +539,9 @@ typedef struct _RxD_block { ...@@ -537,9 +539,9 @@ typedef struct _RxD_block {
#define SIZE_OF_BLOCK 4096 #define SIZE_OF_BLOCK 4096
#define RXD_MODE_1 0 #define RXD_MODE_1 0 /* One Buffer mode */
#define RXD_MODE_3A 1 #define RXD_MODE_3A 1 /* Three Buffer mode */
#define RXD_MODE_3B 2 #define RXD_MODE_3B 2 /* Two Buffer mode */
/* Structure to hold virtual addresses of Buf0 and Buf1 in /* Structure to hold virtual addresses of Buf0 and Buf1 in
* 2buf mode. */ * 2buf mode. */
...@@ -849,8 +851,9 @@ struct s2io_nic { ...@@ -849,8 +851,9 @@ struct s2io_nic {
spinlock_t rx_lock; spinlock_t rx_lock;
atomic_t isr_cnt; atomic_t isr_cnt;
u64 *ufo_in_band_v; u64 *ufo_in_band_v;
#define VPD_PRODUCT_NAME_LEN 50 #define VPD_STRING_LEN 80
u8 product_name[VPD_PRODUCT_NAME_LEN]; u8 product_name[VPD_STRING_LEN];
u8 serial_num[VPD_STRING_LEN];
}; };
#define RESET_ERROR 1; #define RESET_ERROR 1;
...@@ -974,11 +977,13 @@ static void tx_intr_handler(fifo_info_t *fifo_data); ...@@ -974,11 +977,13 @@ static void tx_intr_handler(fifo_info_t *fifo_data);
static void alarm_intr_handler(struct s2io_nic *sp); static void alarm_intr_handler(struct s2io_nic *sp);
static int s2io_starter(void); static int s2io_starter(void);
static void s2io_closer(void);
static void s2io_tx_watchdog(struct net_device *dev); static void s2io_tx_watchdog(struct net_device *dev);
static void s2io_tasklet(unsigned long dev_addr); static void s2io_tasklet(unsigned long dev_addr);
static void s2io_set_multicast(struct net_device *dev); static void s2io_set_multicast(struct net_device *dev);
static int rx_osm_handler(ring_info_t *ring_data, RxD_t * rxdp); static int rx_osm_handler(ring_info_t *ring_data, RxD_t * rxdp);
static void s2io_link(nic_t * sp, int link); static void s2io_link(nic_t * sp, int link);
static void s2io_reset(nic_t * sp);
static int s2io_poll(struct net_device *dev, int *budget); static int s2io_poll(struct net_device *dev, int *budget);
static void s2io_init_pci(nic_t * sp); static void s2io_init_pci(nic_t * sp);
static int s2io_set_mac_addr(struct net_device *dev, u8 * addr); static int s2io_set_mac_addr(struct net_device *dev, u8 * addr);
...@@ -990,13 +995,17 @@ s2io_msix_ring_handle(int irq, void *dev_id); ...@@ -990,13 +995,17 @@ s2io_msix_ring_handle(int irq, void *dev_id);
static irqreturn_t static irqreturn_t
s2io_msix_fifo_handle(int irq, void *dev_id); s2io_msix_fifo_handle(int irq, void *dev_id);
static irqreturn_t s2io_isr(int irq, void *dev_id); static irqreturn_t s2io_isr(int irq, void *dev_id);
static int verify_xena_quiescence(nic_t *sp, u64 val64, int flag); static int verify_xena_quiescence(nic_t *sp);
static const struct ethtool_ops netdev_ethtool_ops; static const struct ethtool_ops netdev_ethtool_ops;
static void s2io_set_link(struct work_struct *work); static void s2io_set_link(struct work_struct *work);
static int s2io_set_swapper(nic_t * sp); static int s2io_set_swapper(nic_t * sp);
static void s2io_card_down(nic_t *nic); static void s2io_card_down(nic_t *nic);
static int s2io_card_up(nic_t *nic); static int s2io_card_up(nic_t *nic);
static int get_xena_rev_id(struct pci_dev *pdev); static int get_xena_rev_id(struct pci_dev *pdev);
static int wait_for_cmd_complete(void *addr, u64 busy_bit);
static int s2io_add_isr(nic_t * sp);
static void s2io_rem_isr(nic_t * sp);
static void restore_xmsi_data(nic_t *nic); static void restore_xmsi_data(nic_t *nic);
static int s2io_club_tcp_session(u8 *buffer, u8 **tcp, u32 *tcp_len, lro_t **lro, RxD_t *rxdp, nic_t *sp); static int s2io_club_tcp_session(u8 *buffer, u8 **tcp, u32 *tcp_len, lro_t **lro, RxD_t *rxdp, nic_t *sp);
......
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