|
@@ -223,9 +223,7 @@ static void s2io_vlan_rx_kill_vid(struct net_device *dev, unsigned long vid)
|
|
|
* the XAUI.
|
|
|
*/
|
|
|
|
|
|
-#define SWITCH_SIGN 0xA5A5A5A5A5A5A5A5ULL
|
|
|
#define END_SIGN 0x0
|
|
|
-
|
|
|
static const u64 herc_act_dtx_cfg[] = {
|
|
|
/* Set address */
|
|
|
0x8000051536750000ULL, 0x80000515367500E0ULL,
|
|
@@ -247,37 +245,19 @@ static const u64 herc_act_dtx_cfg[] = {
|
|
|
END_SIGN
|
|
|
};
|
|
|
|
|
|
-static const u64 xena_mdio_cfg[] = {
|
|
|
- /* Reset PMA PLL */
|
|
|
- 0xC001010000000000ULL, 0xC0010100000000E0ULL,
|
|
|
- 0xC0010100008000E4ULL,
|
|
|
- /* Remove Reset from PMA PLL */
|
|
|
- 0xC001010000000000ULL, 0xC0010100000000E0ULL,
|
|
|
- 0xC0010100000000E4ULL,
|
|
|
- END_SIGN
|
|
|
-};
|
|
|
-
|
|
|
static const u64 xena_dtx_cfg[] = {
|
|
|
+ /* Set address */
|
|
|
0x8000051500000000ULL, 0x80000515000000E0ULL,
|
|
|
- 0x80000515D93500E4ULL, 0x8001051500000000ULL,
|
|
|
- 0x80010515000000E0ULL, 0x80010515001E00E4ULL,
|
|
|
- 0x8002051500000000ULL, 0x80020515000000E0ULL,
|
|
|
- 0x80020515F21000E4ULL,
|
|
|
- /* Set PADLOOPBACKN */
|
|
|
- 0x8002051500000000ULL, 0x80020515000000E0ULL,
|
|
|
- 0x80020515B20000E4ULL, 0x8003051500000000ULL,
|
|
|
- 0x80030515000000E0ULL, 0x80030515B20000E4ULL,
|
|
|
- 0x8004051500000000ULL, 0x80040515000000E0ULL,
|
|
|
- 0x80040515B20000E4ULL, 0x8005051500000000ULL,
|
|
|
- 0x80050515000000E0ULL, 0x80050515B20000E4ULL,
|
|
|
- SWITCH_SIGN,
|
|
|
- /* Remove PADLOOPBACKN */
|
|
|
+ /* Write data */
|
|
|
+ 0x80000515D9350004ULL, 0x80000515D93500E4ULL,
|
|
|
+ /* Set address */
|
|
|
+ 0x8001051500000000ULL, 0x80010515000000E0ULL,
|
|
|
+ /* Write data */
|
|
|
+ 0x80010515001E0004ULL, 0x80010515001E00E4ULL,
|
|
|
+ /* Set address */
|
|
|
0x8002051500000000ULL, 0x80020515000000E0ULL,
|
|
|
- 0x80020515F20000E4ULL, 0x8003051500000000ULL,
|
|
|
- 0x80030515000000E0ULL, 0x80030515F20000E4ULL,
|
|
|
- 0x8004051500000000ULL, 0x80040515000000E0ULL,
|
|
|
- 0x80040515F20000E4ULL, 0x8005051500000000ULL,
|
|
|
- 0x80050515000000E0ULL, 0x80050515F20000E4ULL,
|
|
|
+ /* Write data */
|
|
|
+ 0x80020515F2100004ULL, 0x80020515F21000E4ULL,
|
|
|
END_SIGN
|
|
|
};
|
|
|
|
|
@@ -552,11 +532,6 @@ static int init_shared_mem(struct s2io_nic *nic)
|
|
|
rx_blocks->block_dma_addr +
|
|
|
(rxd_size[nic->rxd_mode] * l);
|
|
|
}
|
|
|
-
|
|
|
- mac_control->rings[i].rx_blocks[j].block_virt_addr =
|
|
|
- tmp_v_addr;
|
|
|
- mac_control->rings[i].rx_blocks[j].block_dma_addr =
|
|
|
- tmp_p_addr;
|
|
|
}
|
|
|
/* Interlinking all Rx Blocks */
|
|
|
for (j = 0; j < blk_cnt; j++) {
|
|
@@ -775,7 +750,21 @@ static int s2io_verify_pci_mode(nic_t *nic)
|
|
|
return mode;
|
|
|
}
|
|
|
|
|
|
+#define NEC_VENID 0x1033
|
|
|
+#define NEC_DEVID 0x0125
|
|
|
+static int s2io_on_nec_bridge(struct pci_dev *s2io_pdev)
|
|
|
+{
|
|
|
+ struct pci_dev *tdev = NULL;
|
|
|
+ while ((tdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, tdev)) != NULL) {
|
|
|
+ if ((tdev->vendor == NEC_VENID) && (tdev->device == NEC_DEVID)){
|
|
|
+ if (tdev->bus == s2io_pdev->bus->parent)
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
|
|
|
+int bus_speed[8] = {33, 133, 133, 200, 266, 133, 200, 266};
|
|
|
/**
|
|
|
* s2io_print_pci_mode -
|
|
|
*/
|
|
@@ -792,6 +781,14 @@ static int s2io_print_pci_mode(nic_t *nic)
|
|
|
if ( val64 & PCI_MODE_UNKNOWN_MODE)
|
|
|
return -1; /* Unknown PCI mode */
|
|
|
|
|
|
+ config->bus_speed = bus_speed[mode];
|
|
|
+
|
|
|
+ if (s2io_on_nec_bridge(nic->pdev)) {
|
|
|
+ DBG_PRINT(ERR_DBG, "%s: Device is on PCI-E bus\n",
|
|
|
+ nic->dev->name);
|
|
|
+ return mode;
|
|
|
+ }
|
|
|
+
|
|
|
if (val64 & PCI_MODE_32_BITS) {
|
|
|
DBG_PRINT(ERR_DBG, "%s: Device is on 32 bit ", nic->dev->name);
|
|
|
} else {
|
|
@@ -801,35 +798,27 @@ static int s2io_print_pci_mode(nic_t *nic)
|
|
|
switch(mode) {
|
|
|
case PCI_MODE_PCI_33:
|
|
|
DBG_PRINT(ERR_DBG, "33MHz PCI bus\n");
|
|
|
- config->bus_speed = 33;
|
|
|
break;
|
|
|
case PCI_MODE_PCI_66:
|
|
|
DBG_PRINT(ERR_DBG, "66MHz PCI bus\n");
|
|
|
- config->bus_speed = 133;
|
|
|
break;
|
|
|
case PCI_MODE_PCIX_M1_66:
|
|
|
DBG_PRINT(ERR_DBG, "66MHz PCIX(M1) bus\n");
|
|
|
- config->bus_speed = 133; /* Herc doubles the clock rate */
|
|
|
break;
|
|
|
case PCI_MODE_PCIX_M1_100:
|
|
|
DBG_PRINT(ERR_DBG, "100MHz PCIX(M1) bus\n");
|
|
|
- config->bus_speed = 200;
|
|
|
break;
|
|
|
case PCI_MODE_PCIX_M1_133:
|
|
|
DBG_PRINT(ERR_DBG, "133MHz PCIX(M1) bus\n");
|
|
|
- config->bus_speed = 266;
|
|
|
break;
|
|
|
case PCI_MODE_PCIX_M2_66:
|
|
|
DBG_PRINT(ERR_DBG, "133MHz PCIX(M2) bus\n");
|
|
|
- config->bus_speed = 133;
|
|
|
break;
|
|
|
case PCI_MODE_PCIX_M2_100:
|
|
|
DBG_PRINT(ERR_DBG, "200MHz PCIX(M2) bus\n");
|
|
|
- config->bus_speed = 200;
|
|
|
break;
|
|
|
case PCI_MODE_PCIX_M2_133:
|
|
|
DBG_PRINT(ERR_DBG, "266MHz PCIX(M2) bus\n");
|
|
|
- config->bus_speed = 266;
|
|
|
break;
|
|
|
default:
|
|
|
return -1; /* Unsupported bus speed */
|
|
@@ -857,7 +846,7 @@ static int init_nic(struct s2io_nic *nic)
|
|
|
int i, j;
|
|
|
mac_info_t *mac_control;
|
|
|
struct config_param *config;
|
|
|
- int mdio_cnt = 0, dtx_cnt = 0;
|
|
|
+ int dtx_cnt = 0;
|
|
|
unsigned long long mem_share;
|
|
|
int mem_size;
|
|
|
|
|
@@ -904,20 +893,6 @@ static int init_nic(struct s2io_nic *nic)
|
|
|
val64 = dev->mtu;
|
|
|
writeq(vBIT(val64, 2, 14), &bar0->rmac_max_pyld_len);
|
|
|
|
|
|
- /*
|
|
|
- * Configuring the XAUI Interface of Xena.
|
|
|
- * ***************************************
|
|
|
- * To Configure the Xena's XAUI, one has to write a series
|
|
|
- * of 64 bit values into two registers in a particular
|
|
|
- * sequence. Hence a macro 'SWITCH_SIGN' has been defined
|
|
|
- * which will be defined in the array of configuration values
|
|
|
- * (xena_dtx_cfg & xena_mdio_cfg) at appropriate places
|
|
|
- * to switch writing from one regsiter to another. We continue
|
|
|
- * writing these values until we encounter the 'END_SIGN' macro.
|
|
|
- * For example, After making a series of 21 writes into
|
|
|
- * dtx_control register the 'SWITCH_SIGN' appears and hence we
|
|
|
- * start writing into mdio_control until we encounter END_SIGN.
|
|
|
- */
|
|
|
if (nic->device_type & XFRAME_II_DEVICE) {
|
|
|
while (herc_act_dtx_cfg[dtx_cnt] != END_SIGN) {
|
|
|
SPECIAL_REG_WRITE(herc_act_dtx_cfg[dtx_cnt],
|
|
@@ -927,35 +902,11 @@ static int init_nic(struct s2io_nic *nic)
|
|
|
dtx_cnt++;
|
|
|
}
|
|
|
} else {
|
|
|
- while (1) {
|
|
|
- dtx_cfg:
|
|
|
- while (xena_dtx_cfg[dtx_cnt] != END_SIGN) {
|
|
|
- if (xena_dtx_cfg[dtx_cnt] == SWITCH_SIGN) {
|
|
|
- dtx_cnt++;
|
|
|
- goto mdio_cfg;
|
|
|
- }
|
|
|
- SPECIAL_REG_WRITE(xena_dtx_cfg[dtx_cnt],
|
|
|
- &bar0->dtx_control, UF);
|
|
|
- val64 = readq(&bar0->dtx_control);
|
|
|
- dtx_cnt++;
|
|
|
- }
|
|
|
- mdio_cfg:
|
|
|
- while (xena_mdio_cfg[mdio_cnt] != END_SIGN) {
|
|
|
- if (xena_mdio_cfg[mdio_cnt] == SWITCH_SIGN) {
|
|
|
- mdio_cnt++;
|
|
|
- goto dtx_cfg;
|
|
|
- }
|
|
|
- SPECIAL_REG_WRITE(xena_mdio_cfg[mdio_cnt],
|
|
|
- &bar0->mdio_control, UF);
|
|
|
- val64 = readq(&bar0->mdio_control);
|
|
|
- mdio_cnt++;
|
|
|
- }
|
|
|
- if ((xena_dtx_cfg[dtx_cnt] == END_SIGN) &&
|
|
|
- (xena_mdio_cfg[mdio_cnt] == END_SIGN)) {
|
|
|
- break;
|
|
|
- } else {
|
|
|
- goto dtx_cfg;
|
|
|
- }
|
|
|
+ while (xena_dtx_cfg[dtx_cnt] != END_SIGN) {
|
|
|
+ SPECIAL_REG_WRITE(xena_dtx_cfg[dtx_cnt],
|
|
|
+ &bar0->dtx_control, UF);
|
|
|
+ val64 = readq(&bar0->dtx_control);
|
|
|
+ dtx_cnt++;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1565,11 +1516,9 @@ static int init_nic(struct s2io_nic *nic)
|
|
|
val64 &= ~(BIT(13)|BIT(14)|BIT(15));
|
|
|
writeq(val64, &bar0->pic_control2);
|
|
|
}
|
|
|
-
|
|
|
- /* Setting Link stability period to 64 ms */
|
|
|
- if (nic->device_type == XFRAME_II_DEVICE) {
|
|
|
- val64 = MISC_LINK_STABILITY_PRD(3);
|
|
|
- writeq(val64, &bar0->misc_control);
|
|
|
+ if (strstr(nic->product_name, "CX4")) {
|
|
|
+ val64 = TMAC_AVG_IPG(0x17);
|
|
|
+ writeq(val64, &bar0->tmac_avg_ipg);
|
|
|
}
|
|
|
|
|
|
return SUCCESS;
|
|
@@ -2034,6 +1983,13 @@ static int start_nic(struct s2io_nic *nic)
|
|
|
val64 |= ADAPTER_EOI_TX_ON;
|
|
|
writeq(val64, &bar0->adapter_control);
|
|
|
|
|
|
+ if (s2io_link_fault_indication(nic) == MAC_RMAC_ERR_TIMER) {
|
|
|
+ /*
|
|
|
+ * Dont see link state interrupts initally on some switches,
|
|
|
+ * so directly scheduling the link state task here.
|
|
|
+ */
|
|
|
+ schedule_work(&nic->set_link_task);
|
|
|
+ }
|
|
|
/* SXE-002: Initialize link and activity LED */
|
|
|
subid = nic->pdev->subsystem_device;
|
|
|
if (((subid & 0xFF) >= 0x07) &&
|
|
@@ -2045,12 +2001,6 @@ static int start_nic(struct s2io_nic *nic)
|
|
|
writeq(val64, (void __iomem *)bar0 + 0x2700);
|
|
|
}
|
|
|
|
|
|
- /*
|
|
|
- * Don't see link state interrupts on certain switches, so
|
|
|
- * directly scheduling a link state task from here.
|
|
|
- */
|
|
|
- schedule_work(&nic->set_link_task);
|
|
|
-
|
|
|
return SUCCESS;
|
|
|
}
|
|
|
/**
|
|
@@ -2569,7 +2519,8 @@ static int s2io_poll(struct net_device *dev, int *budget)
|
|
|
}
|
|
|
}
|
|
|
/* Re enable the Rx interrupts. */
|
|
|
- en_dis_able_nic_intrs(nic, RX_TRAFFIC_INTR, ENABLE_INTRS);
|
|
|
+ writeq(0x0, &bar0->rx_traffic_mask);
|
|
|
+ val64 = readl(&bar0->rx_traffic_mask);
|
|
|
atomic_dec(&nic->isr_cnt);
|
|
|
return 0;
|
|
|
|
|
@@ -2881,23 +2832,26 @@ static void alarm_intr_handler(struct s2io_nic *nic)
|
|
|
* SUCCESS on success and FAILURE on failure.
|
|
|
*/
|
|
|
|
|
|
-static int wait_for_cmd_complete(nic_t * sp)
|
|
|
+static int wait_for_cmd_complete(void *addr, u64 busy_bit)
|
|
|
{
|
|
|
- XENA_dev_config_t __iomem *bar0 = sp->bar0;
|
|
|
int ret = FAILURE, cnt = 0;
|
|
|
u64 val64;
|
|
|
|
|
|
while (TRUE) {
|
|
|
- val64 = readq(&bar0->rmac_addr_cmd_mem);
|
|
|
- if (!(val64 & RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING)) {
|
|
|
+ val64 = readq(addr);
|
|
|
+ if (!(val64 & busy_bit)) {
|
|
|
ret = SUCCESS;
|
|
|
break;
|
|
|
}
|
|
|
- msleep(50);
|
|
|
+
|
|
|
+ if(in_interrupt())
|
|
|
+ mdelay(50);
|
|
|
+ else
|
|
|
+ msleep(50);
|
|
|
+
|
|
|
if (cnt++ > 10)
|
|
|
break;
|
|
|
}
|
|
|
-
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
@@ -2936,6 +2890,9 @@ static void s2io_reset(nic_t * sp)
|
|
|
* PCI write to sw_reset register is done by this time.
|
|
|
*/
|
|
|
msleep(250);
|
|
|
+ if (strstr(sp->product_name, "CX4")) {
|
|
|
+ msleep(750);
|
|
|
+ }
|
|
|
|
|
|
/* Restore the PCI state saved during initialization. */
|
|
|
pci_restore_state(sp->pdev);
|
|
@@ -3154,7 +3111,7 @@ static void restore_xmsi_data(nic_t *nic)
|
|
|
u64 val64;
|
|
|
int i;
|
|
|
|
|
|
- for (i=0; i< MAX_REQUESTED_MSI_X; i++) {
|
|
|
+ for (i=0; i< nic->avail_msix_vectors; i++) {
|
|
|
writeq(nic->msix_info[i].addr, &bar0->xmsi_address);
|
|
|
writeq(nic->msix_info[i].data, &bar0->xmsi_data);
|
|
|
val64 = (BIT(7) | BIT(15) | vBIT(i, 26, 6));
|
|
@@ -3173,7 +3130,7 @@ static void store_xmsi_data(nic_t *nic)
|
|
|
int i;
|
|
|
|
|
|
/* Store and display */
|
|
|
- for (i=0; i< MAX_REQUESTED_MSI_X; i++) {
|
|
|
+ for (i=0; i< nic->avail_msix_vectors; i++) {
|
|
|
val64 = (BIT(15) | vBIT(i, 26, 6));
|
|
|
writeq(val64, &bar0->xmsi_access);
|
|
|
if (wait_for_msix_trans(nic, i)) {
|
|
@@ -3301,15 +3258,24 @@ static int s2io_enable_msi_x(nic_t *nic)
|
|
|
writeq(tx_mat, &bar0->tx_mat0_n[7]);
|
|
|
}
|
|
|
|
|
|
+ nic->avail_msix_vectors = 0;
|
|
|
ret = pci_enable_msix(nic->pdev, nic->entries, MAX_REQUESTED_MSI_X);
|
|
|
+ /* We fail init if error or we get less vectors than min required */
|
|
|
+ if (ret >= (nic->config.tx_fifo_num + nic->config.rx_ring_num + 1)) {
|
|
|
+ nic->avail_msix_vectors = ret;
|
|
|
+ ret = pci_enable_msix(nic->pdev, nic->entries, ret);
|
|
|
+ }
|
|
|
if (ret) {
|
|
|
DBG_PRINT(ERR_DBG, "%s: Enabling MSIX failed\n", nic->dev->name);
|
|
|
kfree(nic->entries);
|
|
|
kfree(nic->s2io_entries);
|
|
|
nic->entries = NULL;
|
|
|
nic->s2io_entries = NULL;
|
|
|
+ nic->avail_msix_vectors = 0;
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
+ if (!nic->avail_msix_vectors)
|
|
|
+ nic->avail_msix_vectors = MAX_REQUESTED_MSI_X;
|
|
|
|
|
|
/*
|
|
|
* To enable MSI-X, MSI also needs to be enabled, due to a bug
|
|
@@ -3342,8 +3308,6 @@ static int s2io_open(struct net_device *dev)
|
|
|
{
|
|
|
nic_t *sp = dev->priv;
|
|
|
int err = 0;
|
|
|
- int i;
|
|
|
- u16 msi_control; /* Temp variable */
|
|
|
|
|
|
/*
|
|
|
* Make sure you have link off by default every time
|
|
@@ -3353,11 +3317,14 @@ static int s2io_open(struct net_device *dev)
|
|
|
sp->last_link_state = 0;
|
|
|
|
|
|
/* Initialize H/W and enable interrupts */
|
|
|
- if (s2io_card_up(sp)) {
|
|
|
+ err = s2io_card_up(sp);
|
|
|
+ if (err) {
|
|
|
DBG_PRINT(ERR_DBG, "%s: H/W initialization failed\n",
|
|
|
dev->name);
|
|
|
- err = -ENODEV;
|
|
|
- goto hw_init_failed;
|
|
|
+ if (err == -ENODEV)
|
|
|
+ goto hw_init_failed;
|
|
|
+ else
|
|
|
+ goto hw_enable_failed;
|
|
|
}
|
|
|
|
|
|
/* Store the values of the MSIX table in the nic_t structure */
|
|
@@ -3374,6 +3341,8 @@ failed\n", dev->name);
|
|
|
}
|
|
|
}
|
|
|
if (sp->intr_type == MSI_X) {
|
|
|
+ int i;
|
|
|
+
|
|
|
for (i=1; (sp->s2io_entries[i].in_use == MSIX_FLG); i++) {
|
|
|
if (sp->s2io_entries[i].type == MSIX_FIFO_TYPE) {
|
|
|
sprintf(sp->desc1, "%s:MSI-X-%d-TX",
|
|
@@ -3426,24 +3395,25 @@ setting_mac_address_failed:
|
|
|
isr_registration_failed:
|
|
|
del_timer_sync(&sp->alarm_timer);
|
|
|
if (sp->intr_type == MSI_X) {
|
|
|
- if (sp->device_type == XFRAME_II_DEVICE) {
|
|
|
- for (i=1; (sp->s2io_entries[i].in_use ==
|
|
|
+ int i;
|
|
|
+ u16 msi_control; /* Temp variable */
|
|
|
+ for (i=1; (sp->s2io_entries[i].in_use ==
|
|
|
MSIX_REGISTERED_SUCCESS); i++) {
|
|
|
- int vector = sp->entries[i].vector;
|
|
|
- void *arg = sp->s2io_entries[i].arg;
|
|
|
-
|
|
|
- free_irq(vector, arg);
|
|
|
- }
|
|
|
- pci_disable_msix(sp->pdev);
|
|
|
+ int vector = sp->entries[i].vector;
|
|
|
+ void *arg = sp->s2io_entries[i].arg;
|
|
|
|
|
|
- /* Temp */
|
|
|
- pci_read_config_word(sp->pdev, 0x42, &msi_control);
|
|
|
- msi_control &= 0xFFFE; /* Disable MSI */
|
|
|
- pci_write_config_word(sp->pdev, 0x42, msi_control);
|
|
|
+ free_irq(vector, arg);
|
|
|
}
|
|
|
+ pci_disable_msix(sp->pdev);
|
|
|
+
|
|
|
+ /* Temp */
|
|
|
+ pci_read_config_word(sp->pdev, 0x42, &msi_control);
|
|
|
+ msi_control &= 0xFFFE; /* Disable MSI */
|
|
|
+ pci_write_config_word(sp->pdev, 0x42, msi_control);
|
|
|
}
|
|
|
else if (sp->intr_type == MSI)
|
|
|
pci_disable_msi(sp->pdev);
|
|
|
+hw_enable_failed:
|
|
|
s2io_reset(sp);
|
|
|
hw_init_failed:
|
|
|
if (sp->intr_type == MSI_X) {
|
|
@@ -3471,35 +3441,12 @@ hw_init_failed:
|
|
|
static int s2io_close(struct net_device *dev)
|
|
|
{
|
|
|
nic_t *sp = dev->priv;
|
|
|
- int i;
|
|
|
- u16 msi_control;
|
|
|
|
|
|
flush_scheduled_work();
|
|
|
netif_stop_queue(dev);
|
|
|
/* Reset card, kill tasklet and free Tx and Rx buffers. */
|
|
|
- s2io_card_down(sp);
|
|
|
-
|
|
|
- if (sp->intr_type == MSI_X) {
|
|
|
- if (sp->device_type == XFRAME_II_DEVICE) {
|
|
|
- for (i=1; (sp->s2io_entries[i].in_use ==
|
|
|
- MSIX_REGISTERED_SUCCESS); i++) {
|
|
|
- int vector = sp->entries[i].vector;
|
|
|
- void *arg = sp->s2io_entries[i].arg;
|
|
|
-
|
|
|
- free_irq(vector, arg);
|
|
|
- }
|
|
|
- pci_read_config_word(sp->pdev, 0x42, &msi_control);
|
|
|
- msi_control &= 0xFFFE; /* Disable MSI */
|
|
|
- pci_write_config_word(sp->pdev, 0x42, msi_control);
|
|
|
+ s2io_card_down(sp, 1);
|
|
|
|
|
|
- pci_disable_msix(sp->pdev);
|
|
|
- }
|
|
|
- }
|
|
|
- else {
|
|
|
- free_irq(sp->pdev->irq, dev);
|
|
|
- if (sp->intr_type == MSI)
|
|
|
- pci_disable_msi(sp->pdev);
|
|
|
- }
|
|
|
sp->device_close_flag = TRUE; /* Device is shut down. */
|
|
|
return 0;
|
|
|
}
|
|
@@ -3825,41 +3772,56 @@ static void s2io_txpic_intr_handle(nic_t *sp)
|
|
|
val64 = readq(&bar0->gpio_int_reg);
|
|
|
if ((val64 & GPIO_INT_REG_LINK_DOWN) &&
|
|
|
(val64 & GPIO_INT_REG_LINK_UP)) {
|
|
|
+ /*
|
|
|
+ * This is unstable state so clear both up/down
|
|
|
+ * interrupt and adapter to re-evaluate the link state.
|
|
|
+ */
|
|
|
val64 |= GPIO_INT_REG_LINK_DOWN;
|
|
|
val64 |= GPIO_INT_REG_LINK_UP;
|
|
|
writeq(val64, &bar0->gpio_int_reg);
|
|
|
- goto masking;
|
|
|
- }
|
|
|
-
|
|
|
- if (((sp->last_link_state == LINK_UP) &&
|
|
|
- (val64 & GPIO_INT_REG_LINK_DOWN)) ||
|
|
|
- ((sp->last_link_state == LINK_DOWN) &&
|
|
|
- (val64 & GPIO_INT_REG_LINK_UP))) {
|
|
|
val64 = readq(&bar0->gpio_int_mask);
|
|
|
- val64 |= GPIO_INT_MASK_LINK_DOWN;
|
|
|
- val64 |= GPIO_INT_MASK_LINK_UP;
|
|
|
+ val64 &= ~(GPIO_INT_MASK_LINK_UP |
|
|
|
+ GPIO_INT_MASK_LINK_DOWN);
|
|
|
writeq(val64, &bar0->gpio_int_mask);
|
|
|
- s2io_set_link((unsigned long)sp);
|
|
|
}
|
|
|
-masking:
|
|
|
- if (sp->last_link_state == LINK_UP) {
|
|
|
- /*enable down interrupt */
|
|
|
- val64 = readq(&bar0->gpio_int_mask);
|
|
|
- /* unmasks link down intr */
|
|
|
- val64 &= ~GPIO_INT_MASK_LINK_DOWN;
|
|
|
- /* masks link up intr */
|
|
|
- val64 |= GPIO_INT_MASK_LINK_UP;
|
|
|
- writeq(val64, &bar0->gpio_int_mask);
|
|
|
- } else {
|
|
|
- /*enable UP Interrupt */
|
|
|
- val64 = readq(&bar0->gpio_int_mask);
|
|
|
- /* unmasks link up interrupt */
|
|
|
- val64 &= ~GPIO_INT_MASK_LINK_UP;
|
|
|
- /* masks link down interrupt */
|
|
|
- val64 |= GPIO_INT_MASK_LINK_DOWN;
|
|
|
- writeq(val64, &bar0->gpio_int_mask);
|
|
|
+ else if (val64 & GPIO_INT_REG_LINK_UP) {
|
|
|
+ val64 = readq(&bar0->adapter_status);
|
|
|
+ if (verify_xena_quiescence(sp, val64,
|
|
|
+ sp->device_enabled_once)) {
|
|
|
+ /* Enable Adapter */
|
|
|
+ val64 = readq(&bar0->adapter_control);
|
|
|
+ val64 |= ADAPTER_CNTL_EN;
|
|
|
+ writeq(val64, &bar0->adapter_control);
|
|
|
+ val64 |= ADAPTER_LED_ON;
|
|
|
+ writeq(val64, &bar0->adapter_control);
|
|
|
+ if (!sp->device_enabled_once)
|
|
|
+ sp->device_enabled_once = 1;
|
|
|
+
|
|
|
+ s2io_link(sp, LINK_UP);
|
|
|
+ /*
|
|
|
+ * unmask link down interrupt and mask link-up
|
|
|
+ * intr
|
|
|
+ */
|
|
|
+ val64 = readq(&bar0->gpio_int_mask);
|
|
|
+ val64 &= ~GPIO_INT_MASK_LINK_DOWN;
|
|
|
+ val64 |= GPIO_INT_MASK_LINK_UP;
|
|
|
+ writeq(val64, &bar0->gpio_int_mask);
|
|
|
+
|
|
|
+ }
|
|
|
+ }else if (val64 & GPIO_INT_REG_LINK_DOWN) {
|
|
|
+ val64 = readq(&bar0->adapter_status);
|
|
|
+ if (verify_xena_quiescence(sp, val64,
|
|
|
+ sp->device_enabled_once)) {
|
|
|
+ s2io_link(sp, LINK_DOWN);
|
|
|
+ /* Link is down so unmaks link up interrupt */
|
|
|
+ val64 = readq(&bar0->gpio_int_mask);
|
|
|
+ val64 &= ~GPIO_INT_MASK_LINK_UP;
|
|
|
+ val64 |= GPIO_INT_MASK_LINK_DOWN;
|
|
|
+ writeq(val64, &bar0->gpio_int_mask);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
+ val64 = readq(&bar0->gpio_int_mask);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -4080,7 +4042,8 @@ static void s2io_set_multicast(struct net_device *dev)
|
|
|
RMAC_ADDR_CMD_MEM_OFFSET(MAC_MC_ALL_MC_ADDR_OFFSET);
|
|
|
writeq(val64, &bar0->rmac_addr_cmd_mem);
|
|
|
/* Wait till command completes */
|
|
|
- wait_for_cmd_complete(sp);
|
|
|
+ wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
|
|
|
+ RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING);
|
|
|
|
|
|
sp->m_cast_flg = 1;
|
|
|
sp->all_multi_pos = MAC_MC_ALL_MC_ADDR_OFFSET;
|
|
@@ -4095,7 +4058,8 @@ static void s2io_set_multicast(struct net_device *dev)
|
|
|
RMAC_ADDR_CMD_MEM_OFFSET(sp->all_multi_pos);
|
|
|
writeq(val64, &bar0->rmac_addr_cmd_mem);
|
|
|
/* Wait till command completes */
|
|
|
- wait_for_cmd_complete(sp);
|
|
|
+ wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
|
|
|
+ RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING);
|
|
|
|
|
|
sp->m_cast_flg = 0;
|
|
|
sp->all_multi_pos = 0;
|
|
@@ -4160,7 +4124,8 @@ static void s2io_set_multicast(struct net_device *dev)
|
|
|
writeq(val64, &bar0->rmac_addr_cmd_mem);
|
|
|
|
|
|
/* Wait for command completes */
|
|
|
- if (wait_for_cmd_complete(sp)) {
|
|
|
+ if (wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
|
|
|
+ RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING)) {
|
|
|
DBG_PRINT(ERR_DBG, "%s: Adding ",
|
|
|
dev->name);
|
|
|
DBG_PRINT(ERR_DBG, "Multicasts failed\n");
|
|
@@ -4190,7 +4155,8 @@ static void s2io_set_multicast(struct net_device *dev)
|
|
|
writeq(val64, &bar0->rmac_addr_cmd_mem);
|
|
|
|
|
|
/* Wait for command completes */
|
|
|
- if (wait_for_cmd_complete(sp)) {
|
|
|
+ if (wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
|
|
|
+ RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING)) {
|
|
|
DBG_PRINT(ERR_DBG, "%s: Adding ",
|
|
|
dev->name);
|
|
|
DBG_PRINT(ERR_DBG, "Multicasts failed\n");
|
|
@@ -4235,7 +4201,8 @@ static int s2io_set_mac_addr(struct net_device *dev, u8 * addr)
|
|
|
RMAC_ADDR_CMD_MEM_OFFSET(0);
|
|
|
writeq(val64, &bar0->rmac_addr_cmd_mem);
|
|
|
/* Wait till command completes */
|
|
|
- if (wait_for_cmd_complete(sp)) {
|
|
|
+ if (wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
|
|
|
+ RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING)) {
|
|
|
DBG_PRINT(ERR_DBG, "%s: set_mac_addr failed\n", dev->name);
|
|
|
return FAILURE;
|
|
|
}
|
|
@@ -4632,7 +4599,6 @@ static int write_eeprom(nic_t * sp, int off, u64 data, int cnt)
|
|
|
}
|
|
|
return ret;
|
|
|
}
|
|
|
-
|
|
|
static void s2io_vpd_read(nic_t *nic)
|
|
|
{
|
|
|
u8 vpd_data[256],data;
|
|
@@ -4983,8 +4949,10 @@ static int s2io_link_test(nic_t * sp, uint64_t * data)
|
|
|
u64 val64;
|
|
|
|
|
|
val64 = readq(&bar0->adapter_status);
|
|
|
- if (val64 & ADAPTER_STATUS_RMAC_LOCAL_FAULT)
|
|
|
+ if(!(LINK_IS_UP(val64)))
|
|
|
*data = 1;
|
|
|
+ else
|
|
|
+ *data = 0;
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -5403,7 +5371,7 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu)
|
|
|
|
|
|
dev->mtu = new_mtu;
|
|
|
if (netif_running(dev)) {
|
|
|
- s2io_card_down(sp);
|
|
|
+ s2io_card_down(sp, 0);
|
|
|
netif_stop_queue(dev);
|
|
|
if (s2io_card_up(sp)) {
|
|
|
DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n",
|
|
@@ -5541,12 +5509,13 @@ static void s2io_set_link(unsigned long data)
|
|
|
clear_bit(0, &(nic->link_state));
|
|
|
}
|
|
|
|
|
|
-static void s2io_card_down(nic_t * sp)
|
|
|
+static void s2io_card_down(nic_t * sp, int flag)
|
|
|
{
|
|
|
int cnt = 0;
|
|
|
XENA_dev_config_t __iomem *bar0 = sp->bar0;
|
|
|
unsigned long flags;
|
|
|
register u64 val64 = 0;
|
|
|
+ struct net_device *dev = sp->dev;
|
|
|
|
|
|
del_timer_sync(&sp->alarm_timer);
|
|
|
/* If s2io_set_link task is executing, wait till it completes. */
|
|
@@ -5557,6 +5526,36 @@ static void s2io_card_down(nic_t * sp)
|
|
|
|
|
|
/* disable Tx and Rx traffic on the NIC */
|
|
|
stop_nic(sp);
|
|
|
+ if (flag) {
|
|
|
+ if (sp->intr_type == MSI_X) {
|
|
|
+ int i;
|
|
|
+ u16 msi_control;
|
|
|
+
|
|
|
+ for (i=1; (sp->s2io_entries[i].in_use ==
|
|
|
+ MSIX_REGISTERED_SUCCESS); i++) {
|
|
|
+ int vector = sp->entries[i].vector;
|
|
|
+ void *arg = sp->s2io_entries[i].arg;
|
|
|
+
|
|
|
+ free_irq(vector, arg);
|
|
|
+ }
|
|
|
+ pci_read_config_word(sp->pdev, 0x42, &msi_control);
|
|
|
+ msi_control &= 0xFFFE; /* Disable MSI */
|
|
|
+ pci_write_config_word(sp->pdev, 0x42, msi_control);
|
|
|
+ pci_disable_msix(sp->pdev);
|
|
|
+ } else {
|
|
|
+ free_irq(sp->pdev->irq, dev);
|
|
|
+ if (sp->intr_type == MSI)
|
|
|
+ pci_disable_msi(sp->pdev);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /* Waiting till all Interrupt handlers are complete */
|
|
|
+ cnt = 0;
|
|
|
+ do {
|
|
|
+ msleep(10);
|
|
|
+ if (!atomic_read(&sp->isr_cnt))
|
|
|
+ break;
|
|
|
+ cnt++;
|
|
|
+ } while(cnt < 5);
|
|
|
|
|
|
/* Kill tasklet. */
|
|
|
tasklet_kill(&sp->task);
|
|
@@ -5580,15 +5579,6 @@ static void s2io_card_down(nic_t * sp)
|
|
|
} while (1);
|
|
|
s2io_reset(sp);
|
|
|
|
|
|
- /* Waiting till all Interrupt handlers are complete */
|
|
|
- cnt = 0;
|
|
|
- do {
|
|
|
- msleep(10);
|
|
|
- if (!atomic_read(&sp->isr_cnt))
|
|
|
- break;
|
|
|
- cnt++;
|
|
|
- } while(cnt < 5);
|
|
|
-
|
|
|
spin_lock_irqsave(&sp->tx_lock, flags);
|
|
|
/* Free all Tx buffers */
|
|
|
free_tx_buffers(sp);
|
|
@@ -5689,7 +5679,7 @@ static void s2io_restart_nic(unsigned long data)
|
|
|
struct net_device *dev = (struct net_device *) data;
|
|
|
nic_t *sp = dev->priv;
|
|
|
|
|
|
- s2io_card_down(sp);
|
|
|
+ s2io_card_down(sp, 0);
|
|
|
if (s2io_card_up(sp)) {
|
|
|
DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n",
|
|
|
dev->name);
|
|
@@ -5751,6 +5741,7 @@ static int rx_osm_handler(ring_info_t *ring_data, RxD_t * rxdp)
|
|
|
lro_t *lro;
|
|
|
|
|
|
skb->dev = dev;
|
|
|
+
|
|
|
if (err) {
|
|
|
/*
|
|
|
* Drop the packet if bad transfer code. Exception being
|
|
@@ -5853,6 +5844,9 @@ static int rx_osm_handler(ring_info_t *ring_data, RxD_t * rxdp)
|
|
|
clear_lro_session(lro);
|
|
|
goto send_up;
|
|
|
case 0: /* sessions exceeded */
|
|
|
+ case -1: /* non-TCP or not
|
|
|
+ * L2 aggregatable
|
|
|
+ */
|
|
|
case 5: /*
|
|
|
* First pkt in session not
|
|
|
* L3/L4 aggregatable
|
|
@@ -6351,8 +6345,8 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
|
|
|
val64 = RMAC_ADDR_CMD_MEM_RD | RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
|
|
|
RMAC_ADDR_CMD_MEM_OFFSET(0 + MAC_MAC_ADDR_START_OFFSET);
|
|
|
writeq(val64, &bar0->rmac_addr_cmd_mem);
|
|
|
- wait_for_cmd_complete(sp);
|
|
|
-
|
|
|
+ wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
|
|
|
+ RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING);
|
|
|
tmp64 = readq(&bar0->rmac_addr_data0_mem);
|
|
|
mac_down = (u32) tmp64;
|
|
|
mac_up = (u32) (tmp64 >> 32);
|