#include "s2io.h"
#include "s2io-regs.h"
-#define DRV_VERSION "2.0.26.1"
+#define DRV_VERSION "2.0.26.2"
/* S2io Driver name & version. */
static char s2io_driver_name[] = "Neterion";
return 0;
}
+static inline int is_s2io_card_up(const struct s2io_nic * sp)
+{
+ return test_bit(__S2IO_STATE_CARD_UP, &sp->state);
+}
+
/* Ethtool related variables and Macros. */
static char s2io_gstrings[][ETH_GSTRING_LEN] = {
"Register test\t(offline)",
val64 = RTI_DATA2_MEM_RX_UFC_A(0x1) |
RTI_DATA2_MEM_RX_UFC_B(0x2) ;
- if (nic->intr_type == MSI_X)
+ if (nic->config.intr_type == MSI_X)
val64 |= (RTI_DATA2_MEM_RX_UFC_C(0x20) | \
RTI_DATA2_MEM_RX_UFC_D(0x40));
else
static int s2io_link_fault_indication(struct s2io_nic *nic)
{
- if (nic->intr_type != INTA)
+ if (nic->config.intr_type != INTA)
return MAC_RMAC_ERR_TIMER;
if (nic->device_type == XFRAME_II_DEVICE)
return LINK_UP_DOWN_INTERRUPT;
struct XENA_dev_config __iomem *bar0 = nic->bar0;
int i;
- atomic_inc(&nic->isr_cnt);
+ if (!is_s2io_card_up(nic))
+ return 0;
+
mac_control = &nic->mac_control;
config = &nic->config;
/* Re enable the Rx interrupts. */
writeq(0x0, &bar0->rx_traffic_mask);
readl(&bar0->rx_traffic_mask);
- atomic_dec(&nic->isr_cnt);
return pkt_cnt;
no_rx:
break;
}
}
- atomic_dec(&nic->isr_cnt);
return pkt_cnt;
}
disable_irq(dev->irq);
- atomic_inc(&nic->isr_cnt);
mac_control = &nic->mac_control;
config = &nic->config;
break;
}
}
- atomic_dec(&nic->isr_cnt);
enable_irq(dev->irq);
return;
}
struct RxD3* rxdp3;
spin_lock(&nic->rx_lock);
- if (atomic_read(&nic->card_state) == CARD_DOWN) {
- DBG_PRINT(INTR_DBG, "%s: %s going down for reset\n",
- __FUNCTION__, dev->name);
- spin_unlock(&nic->rx_lock);
- return;
- }
get_info = ring_data->rx_curr_get_info;
get_block = get_info.block_index;
SWAPPER_CTRL_RXF_W_FE |
SWAPPER_CTRL_XMSI_FE |
SWAPPER_CTRL_STATS_FE | SWAPPER_CTRL_STATS_SE);
- if (sp->intr_type == INTA)
+ if (sp->config.intr_type == INTA)
val64 |= SWAPPER_CTRL_XMSI_SE;
writeq(val64, &bar0->swapper_ctrl);
#else
SWAPPER_CTRL_RXF_W_FE |
SWAPPER_CTRL_XMSI_FE |
SWAPPER_CTRL_STATS_FE | SWAPPER_CTRL_STATS_SE);
- if (sp->intr_type == INTA)
+ if (sp->config.intr_type == INTA)
val64 |= SWAPPER_CTRL_XMSI_SE;
writeq(val64, &bar0->swapper_ctrl);
#endif
napi_enable(&sp->napi);
- if (sp->intr_type == MSI_X) {
+ if (sp->config.intr_type == MSI_X) {
int ret = s2io_enable_msi_x(sp);
if (!ret) {
DBG_PRINT(ERR_DBG,
"%s: MSI-X requested but failed to enable\n",
dev->name);
- sp->intr_type = INTA;
+ sp->config.intr_type = INTA;
}
}
/* NAPI doesn't work well with MSI(X) */
- if (sp->intr_type != INTA) {
+ if (sp->config.intr_type != INTA) {
if(sp->config.napi)
sp->config.napi = 0;
}
hw_init_failed:
napi_disable(&sp->napi);
- if (sp->intr_type == MSI_X) {
+ if (sp->config.intr_type == MSI_X) {
if (sp->entries) {
kfree(sp->entries);
sp->mac_control.stats_info->sw_stat.mem_freed
}
spin_lock_irqsave(&sp->tx_lock, flags);
- if (atomic_read(&sp->card_state) == CARD_DOWN) {
+ if (!is_s2io_card_up(sp)) {
DBG_PRINT(TX_DBG, "%s: Card going down for reset\n",
dev->name);
spin_unlock_irqrestore(&sp->tx_lock, flags);
struct ring_info *ring = (struct ring_info *)dev_id;
struct s2io_nic *sp = ring->nic;
- atomic_inc(&sp->isr_cnt);
+ if (!is_s2io_card_up(sp))
+ return IRQ_HANDLED;
rx_intr_handler(ring);
s2io_chk_rx_buffers(sp, ring->ring_no);
- atomic_dec(&sp->isr_cnt);
return IRQ_HANDLED;
}
struct fifo_info *fifo = (struct fifo_info *)dev_id;
struct s2io_nic *sp = fifo->nic;
- atomic_inc(&sp->isr_cnt);
+ if (!is_s2io_card_up(sp))
+ return IRQ_HANDLED;
+
tx_intr_handler(fifo);
- atomic_dec(&sp->isr_cnt);
return IRQ_HANDLED;
}
static void s2io_txpic_intr_handle(struct s2io_nic *sp)
struct swStat *sw_stat = &sp->mac_control.stats_info->sw_stat;
struct xpakStat *stats = &sp->mac_control.stats_info->xpak_stat;
- if (unlikely(atomic_read(&sp->card_state) == CARD_DOWN))
+ if (!is_s2io_card_up(sp))
return;
if (pci_channel_offline(sp->pdev))
if (pci_channel_offline(sp->pdev))
return IRQ_NONE;
- atomic_inc(&sp->isr_cnt);
+ if (!is_s2io_card_up(sp))
+ return IRQ_NONE;
+
mac_control = &sp->mac_control;
config = &sp->config;
* 1. Rx of packet.
* 2. Tx complete.
* 3. Link down.
- * 4. Error in any functional blocks of the NIC.
*/
reason = readq(&bar0->general_int_status);
- if (!reason) {
- /* 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);
- return IRQ_NONE;
+ if (unlikely(reason == S2IO_MINUS_ONE) ) {
+ /* Nothing much can be done. Get out */
+ return IRQ_HANDLED;
}
- if (napi) {
- if (reason & GEN_INTR_RXTRAFFIC) {
- if (likely (netif_rx_schedule_prep(dev, &sp->napi))) {
- __netif_rx_schedule(dev, &sp->napi);
- writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_mask);
+ if (reason & (GEN_INTR_RXTRAFFIC |
+ GEN_INTR_TXTRAFFIC | GEN_INTR_TXPIC))
+ {
+ writeq(S2IO_MINUS_ONE, &bar0->general_int_mask);
+
+ if (config->napi) {
+ if (reason & GEN_INTR_RXTRAFFIC) {
+ if (likely(netif_rx_schedule_prep(dev,
+ &sp->napi))) {
+ __netif_rx_schedule(dev, &sp->napi);
+ writeq(S2IO_MINUS_ONE,
+ &bar0->rx_traffic_mask);
+ } else
+ writeq(S2IO_MINUS_ONE,
+ &bar0->rx_traffic_int);
}
- else
+ } else {
+ /*
+ * rx_traffic_int reg is an R1 register, writing all 1's
+ * will ensure that the actual interrupt causing bit
+ * get's cleared and hence a read can be avoided.
+ */
+ if (reason & GEN_INTR_RXTRAFFIC)
writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_int);
+
+ for (i = 0; i < config->rx_ring_num; i++)
+ rx_intr_handler(&mac_control->rings[i]);
}
- } else {
+
/*
- * Rx handler is called by default, without checking for the
- * cause of interrupt.
- * rx_traffic_int reg is an R1 register, writing all 1's
+ * tx_traffic_int reg is an R1 register, writing all 1's
* will ensure that the actual interrupt causing bit get's
* cleared and hence a read can be avoided.
*/
- if (reason & GEN_INTR_RXTRAFFIC)
- writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_int);
+ if (reason & GEN_INTR_TXTRAFFIC)
+ writeq(S2IO_MINUS_ONE, &bar0->tx_traffic_int);
- for (i = 0; i < config->rx_ring_num; i++) {
- rx_intr_handler(&mac_control->rings[i]);
- }
- }
+ for (i = 0; i < config->tx_fifo_num; i++)
+ tx_intr_handler(&mac_control->fifos[i]);
- /*
- * tx_traffic_int reg is an R1 register, writing all 1's
- * will ensure that the actual interrupt causing bit get's
- * cleared and hence a read can be avoided.
- */
- if (reason & GEN_INTR_TXTRAFFIC)
- writeq(S2IO_MINUS_ONE, &bar0->tx_traffic_int);
+ if (reason & GEN_INTR_TXPIC)
+ s2io_txpic_intr_handle(sp);
- for (i = 0; i < config->tx_fifo_num; i++)
- tx_intr_handler(&mac_control->fifos[i]);
+ /*
+ * Reallocate the buffers from the interrupt handler itself.
+ */
+ if (!config->napi) {
+ for (i = 0; i < config->rx_ring_num; i++)
+ s2io_chk_rx_buffers(sp, i);
+ }
+ writeq(sp->general_int_mask, &bar0->general_int_mask);
+ readl(&bar0->general_int_status);
- if (reason & GEN_INTR_TXPIC)
- s2io_txpic_intr_handle(sp);
- /*
- * If the Rx buffer count is below the panic threshold then
- * reallocate the buffers from the interrupt handler itself,
- * else schedule a tasklet to reallocate the buffers.
- */
- if (!napi) {
- for (i = 0; i < config->rx_ring_num; i++)
- s2io_chk_rx_buffers(sp, i);
- }
+ return IRQ_HANDLED;
- writeq(0, &bar0->general_int_mask);
- readl(&bar0->general_int_status);
+ }
+ else if (!reason) {
+ /* The interrupt was not raised by us */
+ return IRQ_NONE;
+ }
- atomic_dec(&sp->isr_cnt);
return IRQ_HANDLED;
}
u64 val64;
int cnt = 0;
- if (atomic_read(&sp->card_state) == CARD_UP) {
+ if (is_s2io_card_up(sp)) {
/* Apprx 30us on a 133 MHz bus */
val64 = SET_UPDT_CLICKS(10) |
STAT_CFG_ONE_SHOT_EN | STAT_CFG_STAT_EN;
.set_pauseparam = s2io_ethtool_setpause_data,
.get_rx_csum = s2io_ethtool_get_rx_csum,
.set_rx_csum = s2io_ethtool_set_rx_csum,
- .get_tx_csum = ethtool_op_get_tx_csum,
.set_tx_csum = s2io_ethtool_op_set_tx_csum,
- .get_sg = ethtool_op_get_sg,
.set_sg = ethtool_op_set_sg,
.get_tso = s2io_ethtool_op_get_tso,
.set_tso = s2io_ethtool_op_set_tso,
- .get_ufo = ethtool_op_get_ufo,
.set_ufo = ethtool_op_set_ufo,
.self_test_count = s2io_ethtool_self_test_count,
.self_test = s2io_ethtool_test,
if (!netif_running(dev))
goto out_unlock;
- if (test_and_set_bit(0, &(nic->link_state))) {
+ if (test_and_set_bit(__S2IO_STATE_LINK_TASK, &(nic->state))) {
/* The card is being reset, no point doing anything */
goto out_unlock;
}
writeq(val64, &bar0->adapter_control);
s2io_link(nic, LINK_DOWN);
}
- clear_bit(0, &(nic->link_state));
+ clear_bit(__S2IO_STATE_LINK_TASK, &(nic->state));
out_unlock:
rtnl_unlock();
struct net_device *dev = sp->dev;
int err = 0;
- if (sp->intr_type == MSI_X)
+ if (sp->config.intr_type == MSI_X)
ret = s2io_enable_msi_x(sp);
if (ret) {
DBG_PRINT(ERR_DBG, "%s: Defaulting to INTA\n", dev->name);
- sp->intr_type = INTA;
+ sp->config.intr_type = INTA;
}
/* Store the values of the MSIX table in the struct s2io_nic structure */
store_xmsi_data(sp);
/* After proper initialization of H/W, register ISR */
- if (sp->intr_type == MSI_X) {
+ if (sp->config.intr_type == MSI_X) {
int i, msix_tx_cnt=0,msix_rx_cnt=0;
for (i=1; (sp->s2io_entries[i].in_use == MSIX_FLG); i++) {
printk("MSI-X-TX %d entries enabled\n",msix_tx_cnt);
printk("MSI-X-RX %d entries enabled\n",msix_rx_cnt);
}
- if (sp->intr_type == INTA) {
+ if (sp->config.intr_type == INTA) {
err = request_irq((int) sp->pdev->irq, s2io_isr, IRQF_SHARED,
sp->name, dev);
if (err) {
}
static void s2io_rem_isr(struct s2io_nic * sp)
{
- int cnt = 0;
struct net_device *dev = sp->dev;
struct swStat *stats = &sp->mac_control.stats_info->sw_stat;
- if (sp->intr_type == MSI_X) {
+ if (sp->config.intr_type == MSI_X) {
int i;
u16 msi_control;
int vector = sp->entries[i].vector;
void *arg = sp->s2io_entries[i].arg;
+ synchronize_irq(vector);
free_irq(vector, arg);
}
pci_disable_msix(sp->pdev);
} else {
+ synchronize_irq(sp->pdev->irq);
free_irq(sp->pdev->irq, dev);
}
- /* Waiting till all Interrupt handlers are complete */
- cnt = 0;
- do {
- msleep(10);
- if (!atomic_read(&sp->isr_cnt))
- break;
- cnt++;
- } while(cnt < 5);
}
static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
del_timer_sync(&sp->alarm_timer);
/* If s2io_set_link task is executing, wait till it completes. */
- while (test_and_set_bit(0, &(sp->link_state))) {
+ while (test_and_set_bit(__S2IO_STATE_LINK_TASK, &(sp->state))) {
msleep(50);
}
- atomic_set(&sp->card_state, CARD_DOWN);
+ clear_bit(__S2IO_STATE_CARD_UP, &sp->state);
/* disable Tx and Rx traffic on the NIC */
if (do_io)
free_rx_buffers(sp);
spin_unlock_irqrestore(&sp->rx_lock, flags);
- clear_bit(0, &(sp->link_state));
+ clear_bit(__S2IO_STATE_LINK_TASK, &(sp->state));
}
static void s2io_card_down(struct s2io_nic * sp)
/* Add interrupt service routine */
if (s2io_add_isr(sp) != 0) {
- if (sp->intr_type == MSI_X)
+ if (sp->config.intr_type == MSI_X)
s2io_rem_isr(sp);
s2io_reset(sp);
free_rx_buffers(sp);
/* Enable select interrupts */
en_dis_err_alarms(sp, ENA_ALL_INTRS, ENABLE_INTRS);
- if (sp->intr_type != INTA)
+ if (sp->config.intr_type != INTA)
en_dis_able_nic_intrs(sp, ENA_ALL_INTRS, DISABLE_INTRS);
else {
interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR;
en_dis_able_nic_intrs(sp, interruptible, ENABLE_INTRS);
}
-
- atomic_set(&sp->card_state, CARD_UP);
+ set_bit(__S2IO_STATE_CARD_UP, &sp->state);
return 0;
}
if (*dev_intr_type != INTA)
napi = 0;
-#ifndef CONFIG_PCI_MSI
- if (*dev_intr_type != INTA) {
- DBG_PRINT(ERR_DBG, "s2io: This kernel does not support"
- "MSI/MSI-X. Defaulting to INTA\n");
- *dev_intr_type = INTA;
- }
-#else
if ((*dev_intr_type != INTA) && (*dev_intr_type != MSI_X)) {
DBG_PRINT(ERR_DBG, "s2io: Wrong intr_type requested. "
"Defaulting to INTA\n");
*dev_intr_type = INTA;
}
-#endif
+
if ((*dev_intr_type == MSI_X) &&
((pdev->device != PCI_DEVICE_ID_HERC_WIN) &&
(pdev->device != PCI_DEVICE_ID_HERC_UNI))) {
struct config_param *config;
int mode;
u8 dev_intr_type = intr_type;
+ DECLARE_MAC_BUF(mac);
if ((ret = s2io_verify_parm(pdev, &dev_intr_type)))
return ret;
pci_set_master(pdev);
pci_set_drvdata(pdev, dev);
- SET_MODULE_OWNER(dev);
SET_NETDEV_DEV(dev, &pdev->dev);
/* Private member variable initialized to s2io NIC structure */
if (rx_ring_mode == 2)
sp->rxd_mode = RXD_MODE_3B;
- sp->intr_type = dev_intr_type;
+ sp->config.intr_type = dev_intr_type;
if ((pdev->device == PCI_DEVICE_ID_HERC_WIN) ||
(pdev->device == PCI_DEVICE_ID_HERC_UNI))
mac_control = &sp->mac_control;
config = &sp->config;
+ config->napi = napi;
+
/* Tx side parameters. */
config->tx_fifo_num = tx_fifo_num;
for (i = 0; i < MAX_TX_FIFOS; i++) {
for (i = 0; i < config->rx_ring_num; i++)
atomic_set(&sp->rx_bufs_left[i], 0);
- /* Initialize the number of ISRs currently running */
- atomic_set(&sp->isr_cnt, 0);
-
/* initialize the shared memory used by the NIC and the host */
if (init_shared_mem(sp)) {
DBG_PRINT(ERR_DBG, "%s: Memory allocation failed\n",
* Initialize the tasklet status and link state flags
* and the card state parameter
*/
- atomic_set(&(sp->card_state), 0);
sp->tasklet_status = 0;
- sp->link_state = 0;
+ sp->state = 0;
/* Initialize spinlocks */
spin_lock_init(&sp->tx_lock);
sp->product_name, pdev->revision);
DBG_PRINT(ERR_DBG, "%s: Driver version %s\n", dev->name,
s2io_driver_version);
- DBG_PRINT(ERR_DBG, "%s: MAC ADDR: "
- "%02x:%02x:%02x:%02x:%02x:%02x", dev->name,
- sp->def_mac_addr[0].mac_addr[0],
- sp->def_mac_addr[0].mac_addr[1],
- sp->def_mac_addr[0].mac_addr[2],
- sp->def_mac_addr[0].mac_addr[3],
- sp->def_mac_addr[0].mac_addr[4],
- sp->def_mac_addr[0].mac_addr[5]);
+ DBG_PRINT(ERR_DBG, "%s: MAC ADDR: %s\n",
+ dev->name, print_mac(mac, dev->dev_addr));
DBG_PRINT(ERR_DBG, "SERIAL NUMBER: %s\n", sp->serial_num);
if (sp->device_type & XFRAME_II_DEVICE) {
mode = s2io_print_pci_mode(sp);
if (napi)
DBG_PRINT(ERR_DBG, "%s: NAPI enabled\n", dev->name);
- switch(sp->intr_type) {
+ switch(sp->config.intr_type) {
case INTA:
DBG_PRINT(ERR_DBG, "%s: Interrupt type INTA\n", dev->name);
break;