static struct pci_driver s2io_driver = {
.name = "S2IO",
.id_table = s2io_tbl,
.probe = s2io_init_nic,
.remove = s2io_rem_nic,
.err_handler = &s2io_err_handler,
};
##############################################################
/**
* s2io_init_nic - Initialization of the adapter .
* @pdev : structure containing the PCI related information of the device.
* @pre: List of PCI devices supported by the driver listed in s2io_tbl.
* Description:
* The function initializes an adapter identified by the pci_dec structure.
* All OS related initialization including memory and device structure and
* initlaization of the device private variable is done. Also the swapper
* control register is initialized to enable read and write into the I/O
* registers of the device.
* Return value:
* returns 0 on success and negative on failure.
*/
static int
s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
{
struct s2io_nic *sp;
struct net_device *dev;
int i, j, ret;
int dma_flag = false;
u32 mac_up, mac_down;
u64 val64 = 0, tmp64 = 0;
struct XENA_dev_config __iomem *bar0 = NULL;
u16 subid;
struct config_param *config;
struct mac_info *mac_control;
int mode;
u8 dev_intr_type = intr_type;
u8 dev_multiq = 0;
ret = s2io_verify_parm(pdev, &dev_intr_type, &dev_multiq);
if (ret)
return ret;
ret = pci_enable_device(pdev);
if (ret) {
DBG_PRINT(ERR_DBG,
"%s: pci_enable_device failed\n", __func__);
return ret;
}
if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
DBG_PRINT(INIT_DBG, "%s: Using 64bit DMA\n", __func__);
dma_flag = true;
if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) {
DBG_PRINT(ERR_DBG,
"Unable to obtain 64bit DMA "
"for consistent allocations\n");
pci_disable_device(pdev);
return -ENOMEM;
}
} else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
DBG_PRINT(INIT_DBG, "%s: Using 32bit DMA\n", __func__);
} else {
pci_disable_device(pdev);
return -ENOMEM;
}
ret = pci_request_regions(pdev, s2io_driver_name);
if (ret) {
DBG_PRINT(ERR_DBG, "%s: Request Regions failed - %x\n",
__func__, ret);
pci_disable_device(pdev);
return -ENODEV;
}
if (dev_multiq)
dev = alloc_etherdev_mq(sizeof(struct s2io_nic), tx_fifo_num);
else
dev = alloc_etherdev(sizeof(struct s2io_nic));
if (dev == NULL) {
pci_disable_device(pdev);
pci_release_regions(pdev);
return -ENODEV;
}
pci_set_master(pdev);
pci_set_drvdata(pdev, dev);
SET_NETDEV_DEV(dev, &pdev->dev);
/* Private member variable initialized to s2io NIC structure */
sp = netdev_priv(dev);
sp->dev = dev;
sp->pdev = pdev;
sp->high_dma_flag = dma_flag;
sp->device_enabled_once = false;
if (rx_ring_mode == 1)
sp->rxd_mode = RXD_MODE_1;
if (rx_ring_mode == 2)
sp->rxd_mode = RXD_MODE_3B;
sp->config.intr_type = dev_intr_type;
if ((pdev->device == PCI_DEVICE_ID_HERC_WIN) ||
(pdev->device == PCI_DEVICE_ID_HERC_UNI))
sp->device_type = XFRAME_II_DEVICE;
else
sp->device_type = XFRAME_I_DEVICE;
/* Initialize some PCI/PCI-X fields of the NIC. */
s2io_init_pci(sp);
/*
* Setting the device configuration parameters.
* Most of these parameters can be specified by the user during
* module insertion as they are module loadable parameters. If
* these parameters are not not specified during load time, they
* are initialized with default values.
*/
config = &sp->config;
mac_control = &sp->mac_control;
config->napi = napi;
config->tx_steering_type = tx_steering_type;
/* Tx side parameters. */
if (config->tx_steering_type == TX_PRIORITY_STEERING)
config->tx_fifo_num = MAX_TX_FIFOS;
else
config->tx_fifo_num = tx_fifo_num;
/* Initialize the fifos used for tx steering */
if (config->tx_fifo_num < 5) {
if (config->tx_fifo_num == 1)
sp->total_tcp_fifos = 1;
else
sp->total_tcp_fifos = config->tx_fifo_num - 1;
sp->udp_fifo_idx = config->tx_fifo_num - 1;
sp->total_udp_fifos = 1;
sp->other_fifo_idx = sp->total_tcp_fifos - 1;
} else {
sp->total_tcp_fifos = (tx_fifo_num - FIFO_UDP_MAX_NUM -
FIFO_OTHER_MAX_NUM);
sp->udp_fifo_idx = sp->total_tcp_fifos;
sp->total_udp_fifos = FIFO_UDP_MAX_NUM;
sp->other_fifo_idx = sp->udp_fifo_idx + FIFO_UDP_MAX_NUM;
}
config->multiq = dev_multiq;
for (i = 0; i < config->tx_fifo_num; i++) {
struct tx_fifo_config *tx_cfg = &config->tx_cfg[i];
tx_cfg->fifo_len = tx_fifo_len[i];
tx_cfg->fifo_priority = i;
}
/* mapping the QoS priority to the configured fifos */
for (i = 0; i < MAX_TX_FIFOS; i++)
config->fifo_mapping[i] = fifo_map[config->tx_fifo_num - 1][i];
/* map the hashing selector table to the configured fifos */
for (i = 0; i < config->tx_fifo_num; i++)
sp->fifo_selector[i] = fifo_selector[i];
config->tx_intr_type = TXD_INT_TYPE_UTILZ;
for (i = 0; i < config->tx_fifo_num; i++) {
struct tx_fifo_config *tx_cfg = &config->tx_cfg[i];
tx_cfg->f_no_snoop = (NO_SNOOP_TXD | NO_SNOOP_TXD_BUFFER);
if (tx_cfg->fifo_len < 65) {
config->tx_intr_type = TXD_INT_TYPE_PER_LIST;
break;
}
}
/* + 2 because one Txd for skb->data and one Txd for UFO */
config->max_txds = MAX_SKB_FRAGS + 2;
/* Rx side parameters. */
config->rx_ring_num = rx_ring_num;
for (i = 0; i < config->rx_ring_num; i++) {
struct rx_ring_config *rx_cfg = &config->rx_cfg[i];
struct ring_info *ring = &mac_control->rings[i];
rx_cfg->num_rxd = rx_ring_sz[i] * (rxd_count[sp->rxd_mode] + 1);
rx_cfg->ring_priority = i;
ring->rx_bufs_left = 0;
ring->rxd_mode = sp->rxd_mode;
ring->rxd_count = rxd_count[sp->rxd_mode];
ring->pdev = sp->pdev;
ring->dev = sp->dev;
}
for (i = 0; i < rx_ring_num; i++) {
struct rx_ring_config *rx_cfg = &config->rx_cfg[i];
rx_cfg->ring_org = RING_ORG_BUFF1;
rx_cfg->f_no_snoop = (NO_SNOOP_RXD | NO_SNOOP_RXD_BUFFER);
}
/* Setting Mac Control parameters */
mac_control->rmac_pause_time = rmac_pause_time;
mac_control->mc_pause_threshold_q0q3 = mc_pause_threshold_q0q3;
mac_control->mc_pause_threshold_q4q7 = mc_pause_threshold_q4q7;
/* 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", dev->name);
ret = -ENOMEM;
goto mem_alloc_failed;
}
sp->bar0 = pci_ioremap_bar(pdev, 0);
if (!sp->bar0) {
DBG_PRINT(ERR_DBG, "%s: Neterion: cannot remap io mem1\n",
dev->name);
ret = -ENOMEM;
goto bar0_remap_failed;
}
sp->bar1 = pci_ioremap_bar(pdev, 2);
if (!sp->bar1) {
DBG_PRINT(ERR_DBG, "%s: Neterion: cannot remap io mem2\n",
dev->name);
ret = -ENOMEM;
goto bar1_remap_failed;
}
/* Initializing the BAR1 address as the start of the FIFO pointer. */
for (j = 0; j < MAX_TX_FIFOS; j++) {
mac_control->tx_FIFO_start[j] = sp->bar1 + (j * 0x00020000);
}
/* Driver entry points */
dev->netdev_ops = &s2io_netdev_ops;
dev->ethtool_ops = &netdev_ethtool_ops;
dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM |
NETIF_F_TSO | NETIF_F_TSO6 |
NETIF_F_RXCSUM | NETIF_F_LRO;
dev->features |= dev->hw_features |
NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
if (sp->device_type & XFRAME_II_DEVICE) {
dev->hw_features |= NETIF_F_UFO;
if (ufo)
dev->features |= NETIF_F_UFO;
}
if (sp->high_dma_flag == true)
dev->features |= NETIF_F_HIGHDMA;
dev->watchdog_timeo = WATCH_DOG_TIMEOUT;
INIT_WORK(&sp->rst_timer_task, s2io_restart_nic);
INIT_WORK(&sp->set_link_task, s2io_set_link);
pci_save_state(sp->pdev);
/* Setting swapper control on the NIC, for proper reset operation */
if (s2io_set_swapper(sp)) {
DBG_PRINT(ERR_DBG, "%s: swapper settings are wrong\n",
dev->name);
ret = -EAGAIN;
goto set_swap_failed;
}
/* Verify if the Herc works on the slot its placed into */
if (sp->device_type & XFRAME_II_DEVICE) {
mode = s2io_verify_pci_mode(sp);
if (mode < 0) {
DBG_PRINT(ERR_DBG, "%s: Unsupported PCI bus mode\n",
__func__);
ret = -EBADSLT;
goto set_swap_failed;
}
}
if (sp->config.intr_type == MSI_X) {
sp->num_entries = config->rx_ring_num + 1;
ret = s2io_enable_msi_x(sp);
if (!ret) {
ret = s2io_test_msi(sp);
/* rollback MSI-X, will re-enable during add_isr() */
remove_msix_isr(sp);
}
if (ret) {
DBG_PRINT(ERR_DBG,
"MSI-X requested but failed to enable\n");
sp->config.intr_type = INTA;
}
}
if (config->intr_type == MSI_X) {
for (i = 0; i < config->rx_ring_num ; i++) {
struct ring_info *ring = &mac_control->rings[i];
netif_napi_add(dev, &ring->napi, s2io_poll_msix, 64);
}
} else {
netif_napi_add(dev, &sp->napi, s2io_poll_inta, 64);
}
/* Not needed for Herc */
if (sp->device_type & XFRAME_I_DEVICE) {
/*
* Fix for all "FFs" MAC address problems observed on
* Alpha platforms
*/
fix_mac_address(sp);
s2io_reset(sp);
}
/*
* MAC address initialization.
* For now only one mac address will be read and used.
*/
bar0 = sp->bar0;
val64 = RMAC_ADDR_CMD_MEM_RD | RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
RMAC_ADDR_CMD_MEM_OFFSET(0 + S2IO_MAC_ADDR_START_OFFSET);
writeq(val64, &bar0->rmac_addr_cmd_mem);
wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING,
S2IO_BIT_RESET);
tmp64 = readq(&bar0->rmac_addr_data0_mem);
mac_down = (u32)tmp64;
mac_up = (u32) (tmp64 >> 32);
sp->def_mac_addr[0].mac_addr[3] = (u8) (mac_up);
sp->def_mac_addr[0].mac_addr[2] = (u8) (mac_up >> 8);
sp->def_mac_addr[0].mac_addr[1] = (u8) (mac_up >> 16);
sp->def_mac_addr[0].mac_addr[0] = (u8) (mac_up >> 24);
sp->def_mac_addr[0].mac_addr[5] = (u8) (mac_down >> 16);
sp->def_mac_addr[0].mac_addr[4] = (u8) (mac_down >> 24);
/* Set the factory defined MAC address initially */
dev->addr_len = ETH_ALEN;
memcpy(dev->dev_addr, sp->def_mac_addr, ETH_ALEN);
/* initialize number of multicast & unicast MAC entries variables */
if (sp->device_type == XFRAME_I_DEVICE) {
config->max_mc_addr = S2IO_XENA_MAX_MC_ADDRESSES;
config->max_mac_addr = S2IO_XENA_MAX_MAC_ADDRESSES;
config->mc_start_offset = S2IO_XENA_MC_ADDR_START_OFFSET;
} else if (sp->device_type == XFRAME_II_DEVICE) {
config->max_mc_addr = S2IO_HERC_MAX_MC_ADDRESSES;
config->max_mac_addr = S2IO_HERC_MAX_MAC_ADDRESSES;
config->mc_start_offset = S2IO_HERC_MC_ADDR_START_OFFSET;
}
/* store mac addresses from CAM to s2io_nic structure */
do_s2io_store_unicast_mc(sp);
/* Configure MSIX vector for number of rings configured plus one */
if ((sp->device_type == XFRAME_II_DEVICE) &&
(config->intr_type == MSI_X))
sp->num_entries = config->rx_ring_num + 1;
/* Store the values of the MSIX table in the s2io_nic structure */
store_xmsi_data(sp);
/* reset Nic and bring it to known state */
s2io_reset(sp);
/*
* Initialize link state flags
* and the card state parameter
*/
sp->state = 0;
/* Initialize spinlocks */
for (i = 0; i < sp->config.tx_fifo_num; i++) {
struct fifo_info *fifo = &mac_control->fifos[i];
spin_lock_init(&fifo->tx_lock);
}
/*
* SXE-002: Configure link and activity LED to init state
* on driver load.
*/
subid = sp->pdev->subsystem_device;
if ((subid & 0xFF) >= 0x07) {
val64 = readq(&bar0->gpio_control);
val64 |= 0x0000800000000000ULL;
writeq(val64, &bar0->gpio_control);
val64 = 0x0411040400000000ULL;
writeq(val64, (void __iomem *)bar0 + 0x2700);
val64 = readq(&bar0->gpio_control);
}
sp->rx_csum = 1; /* Rx chksum verify enabled by default */
if (register_netdev(dev)) {
DBG_PRINT(ERR_DBG, "Device registration failed\n");
ret = -ENODEV;
goto register_failed;
}
s2io_vpd_read(sp);
DBG_PRINT(ERR_DBG, "Copyright(c) 2002-2010 Exar Corp.\n");
DBG_PRINT(ERR_DBG, "%s: Neterion %s (rev %d)\n", dev->name,
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 Address: %pM\n", dev->name, 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 (mode < 0) {
ret = -EBADSLT;
unregister_netdev(dev);
goto set_swap_failed;
}
}
switch (sp->rxd_mode) {
case RXD_MODE_1:
DBG_PRINT(ERR_DBG, "%s: 1-Buffer receive mode enabled\n",
dev->name);
break;
case RXD_MODE_3B:
DBG_PRINT(ERR_DBG, "%s: 2-Buffer receive mode enabled\n",
dev->name);
break;
}
switch (sp->config.napi) {
case 0:
DBG_PRINT(ERR_DBG, "%s: NAPI disabled\n", dev->name);
break;
case 1:
DBG_PRINT(ERR_DBG, "%s: NAPI enabled\n", dev->name);
break;
}
DBG_PRINT(ERR_DBG, "%s: Using %d Tx fifo(s)\n", dev->name,
sp->config.tx_fifo_num);
DBG_PRINT(ERR_DBG, "%s: Using %d Rx ring(s)\n", dev->name,
sp->config.rx_ring_num);
switch (sp->config.intr_type) {
case INTA:
DBG_PRINT(ERR_DBG, "%s: Interrupt type INTA\n", dev->name);
break;
case MSI_X:
DBG_PRINT(ERR_DBG, "%s: Interrupt type MSI-X\n", dev->name);
break;
}
if (sp->config.multiq) {
for (i = 0; i < sp->config.tx_fifo_num; i++) {
struct fifo_info *fifo = &mac_control->fifos[i];
fifo->multiq = config->multiq;
}
DBG_PRINT(ERR_DBG, "%s: Multiqueue support enabled\n",
dev->name);
} else
DBG_PRINT(ERR_DBG, "%s: Multiqueue support disabled\n",
dev->name);
switch (sp->config.tx_steering_type) {
case NO_STEERING:
DBG_PRINT(ERR_DBG, "%s: No steering enabled for transmit\n",
dev->name);
break;
case TX_PRIORITY_STEERING:
DBG_PRINT(ERR_DBG,
"%s: Priority steering enabled for transmit\n",
dev->name);
break;
case TX_DEFAULT_STEERING:
DBG_PRINT(ERR_DBG,
"%s: Default steering enabled for transmit\n",
dev->name);
}
DBG_PRINT(ERR_DBG, "%s: Large receive offload enabled\n",
dev->name);
if (ufo)
DBG_PRINT(ERR_DBG,
"%s: UDP Fragmentation Offload(UFO) enabled\n",
dev->name);
/* Initialize device name */
snprintf(sp->name, sizeof(sp->name), "%s Neterion %s", dev->name,
sp->product_name);
if (vlan_tag_strip)
sp->vlan_strip_flag = 1;
else
sp->vlan_strip_flag = 0;
/*
* Make Link state as off at this point, when the Link change
* interrupt comes the state will be automatically changed to
* the right state.
*/
netif_carrier_off(dev);
return 0;
register_failed:
set_swap_failed:
iounmap(sp->bar1);
bar1_remap_failed:
iounmap(sp->bar0);
bar0_remap_failed:
mem_alloc_failed:
free_shared_mem(sp);
pci_disable_device(pdev);
pci_release_regions(pdev);
free_netdev(dev);
return ret;
}
##########################################################################
static const struct net_device_ops s2io_netdev_ops = {
.ndo_open = s2io_open,
.ndo_stop = s2io_close,
.ndo_get_stats = s2io_get_stats,
.ndo_start_xmit = s2io_xmit,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_rx_mode = s2io_set_multicast,
.ndo_do_ioctl = s2io_ioctl,
.ndo_set_mac_address = s2io_set_mac_addr,
.ndo_change_mtu = s2io_change_mtu,
.ndo_set_features = s2io_set_features,
.ndo_tx_timeout = s2io_tx_watchdog,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = s2io_netpoll,
#endif
};