/************************************************************************ * s2io.c: A Linux PCI-X Ethernet driver for Neterion 10GbE Server NIC * Copyright(c) 2002-2010 Exar Corp. * * This software may be used and distributed according to the terms of * the GNU General Public License (GPL), incorporated herein by reference. * Drivers based on or derived from this code fall under the GPL and must * retain the authorship, copyright and license notice. This file is not * a complete program and may only be used when the entire operating * system is licensed under the GPL. * See the file COPYING in this distribution for more information. * * Credits: * Jeff Garzik : For pointing out the improper error condition * check in the s2io_xmit routine and also some * issues in the Tx watch dog function. Also for * patiently answering all those innumerable * questions regaring the 2.6 porting issues. * Stephen Hemminger : Providing proper 2.6 porting mechanism for some * macros available only in 2.6 Kernel. * Francois Romieu : For pointing out all code part that were * deprecated and also styling related comments. * Grant Grundler : For helping me get rid of some Architecture * dependent code. * Christopher Hellwig : Some more 2.6 specific issues in the driver. * * The module loadable parameters that are supported by the driver and a brief * explanation of all the variables. * * rx_ring_num : This can be used to program the number of receive rings used * in the driver. * rx_ring_sz: This defines the number of receive blocks each ring can have. * This is also an array of size 8. * rx_ring_mode: This defines the operation mode of all 8 rings. The valid * values are 1, 2. * 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 descriptors that can be associated with each corresponding FIFO. * intr_type: This defines the type of interrupt. The values can be 0(INTA), * 2(MSI_X). Default value is '2(MSI_X)' * lro_max_pkts: This parameter defines maximum number of packets can be * aggregated as a single large packet * napi: This parameter used to enable/disable NAPI (polling Rx) * Possible values '1' for enable and '0' for disable. Default is '1' * vlan_tag_strip: This can be used to enable or disable vlan stripping. * Possible values '1' for enable , '0' for disable. * Default is '2' - which means disable in promisc mode * and enable in non-promiscuous mode. * multiq: This parameter used to enable/disable MULTIQUEUE support. * Possible values '1' for enable and '0' for disable. Default is '0'
************************************************************************/
/* Module Loadable parameters. */
S2IO_PARM_INT(tx_fifo_num, FIFO_DEFAULT_NUM);
S2IO_PARM_INT(rx_ring_num, 1);
S2IO_PARM_INT(multiq, 0);
S2IO_PARM_INT(rx_ring_mode, 1);
S2IO_PARM_INT(use_continuous_tx_intrs, 1);
S2IO_PARM_INT(rmac_pause_time, 0x100);
S2IO_PARM_INT(mc_pause_threshold_q0q3, 187);
S2IO_PARM_INT(mc_pause_threshold_q4q7, 187);
S2IO_PARM_INT(shared_splits, 0);
S2IO_PARM_INT(tmac_util_period, 5);
S2IO_PARM_INT(rmac_util_period, 5);
S2IO_PARM_INT(l3l4hdr_size, 128); /* 0 is no steering, 1 is Priority steering, 2 is Default steering */
S2IO_PARM_INT(tx_steering_type, TX_DEFAULT_STEERING); /* Frequency of Rx desc syncs expressed as power of 2 */
S2IO_PARM_INT(rxsync_frequency, 3); /* Interrupt type. Values can be 0(INTA), 2(MSI_X) */
S2IO_PARM_INT(intr_type, 2); /* Large receive offload feature */
/* Max pkts to be aggregated by LRO at one time. If not specified, * aggregation happens until we hit max IP pkt size(64K)
*/
S2IO_PARM_INT(lro_max_pkts, 0xFFFF);
S2IO_PARM_INT(indicate_max_pkts, 0);
/* A simplifier macro used both by init and free shared_mem Fns(). */ #define TXD_MEM_PAGE_CNT(len, per_each) DIV_ROUND_UP(len, per_each)
/* netqueue manipulation helper functions */ staticinlinevoid s2io_stop_all_tx_queue(struct s2io_nic *sp)
{ if (!sp->config.multiq) { int i;
for (i = 0; i < sp->config.tx_fifo_num; i++)
sp->mac_control.fifos[i].queue_state = FIFO_QUEUE_STOP;
}
netif_tx_stop_all_queues(sp->dev);
}
staticinlinevoid s2io_stop_tx_queue(struct s2io_nic *sp, int fifo_no)
{ if (!sp->config.multiq)
sp->mac_control.fifos[fifo_no].queue_state =
FIFO_QUEUE_STOP;
netif_tx_stop_all_queues(sp->dev);
}
staticinlinevoid s2io_start_all_tx_queue(struct s2io_nic *sp)
{ if (!sp->config.multiq) { int i;
for (i = 0; i < sp->config.tx_fifo_num; i++)
sp->mac_control.fifos[i].queue_state = FIFO_QUEUE_START;
}
netif_tx_start_all_queues(sp->dev);
}
staticinlinevoid s2io_wake_all_tx_queue(struct s2io_nic *sp)
{ if (!sp->config.multiq) { int i;
for (i = 0; i < sp->config.tx_fifo_num; i++)
sp->mac_control.fifos[i].queue_state = FIFO_QUEUE_START;
}
netif_tx_wake_all_queues(sp->dev);
}
staticinlinevoid s2io_wake_tx_queue( struct fifo_info *fifo, int cnt, u8 multiq)
{
if (multiq) { if (cnt && __netif_subqueue_stopped(fifo->dev, fifo->fifo_no))
netif_wake_subqueue(fifo->dev, fifo->fifo_no);
} elseif (cnt && (fifo->queue_state == FIFO_QUEUE_STOP)) { if (netif_queue_stopped(fifo->dev)) {
fifo->queue_state = FIFO_QUEUE_START;
netif_wake_queue(fifo->dev);
}
}
}
/** * init_shared_mem - Allocation and Initialization of Memory * @nic: Device private variable. * Description: The function allocates all the memory areas shared * between the NIC and the driver. This includes Tx descriptors, * Rx descriptors and the statistics block.
*/
/* Allocation and initialization of TXDLs in FIFOs */
size = 0; for (i = 0; i < config->tx_fifo_num; i++) { struct tx_fifo_config *tx_cfg = &config->tx_cfg[i];
size += tx_cfg->fifo_len;
} if (size > MAX_AVAILABLE_TXDS) {
DBG_PRINT(ERR_DBG, "Too many TxDs requested: %d, max supported: %d\n",
size, MAX_AVAILABLE_TXDS); return -EINVAL;
}
size = 0; for (i = 0; i < config->tx_fifo_num; i++) { struct tx_fifo_config *tx_cfg = &config->tx_cfg[i];
size = tx_cfg->fifo_len; /* * Legal values are from 2 to 8192
*/ if (size < 2) {
DBG_PRINT(ERR_DBG, "Fifo %d: Invalid length (%d) - " "Valid lengths are 2 through 8192\n",
i, size); return -EINVAL;
}
}
blk_cnt = rx_cfg->num_rxd / (rxd_count[nic->rxd_mode] + 1); /* Allocating all the Rx blocks */ for (j = 0; j < blk_cnt; j++) { struct rx_block_info *rx_blocks; int l;
rx_blocks = &ring->rx_blocks[j];
size = SIZE_OF_BLOCK; /* size is always page size */
tmp_v_addr = dma_alloc_coherent(&nic->pdev->dev, size,
&tmp_p_addr, GFP_KERNEL); if (tmp_v_addr == NULL) { /* * In case of failure, free_shared_mem() * is called, which should free any * memory that was alloced till the * failure happened.
*/
rx_blocks->block_virt_addr = tmp_v_addr; return -ENOMEM;
}
mem_allocated += size;
/* Allocation and initialization of Statistics block */
size = sizeof(struct stat_block);
mac_control->stats_mem =
dma_alloc_coherent(&nic->pdev->dev, size,
&mac_control->stats_mem_phy, GFP_KERNEL);
if (!mac_control->stats_mem) { /* * In case of failure, free_shared_mem() is called, which * should free any memory that was alloced till the * failure happened.
*/ return -ENOMEM;
}
mem_allocated += size;
mac_control->stats_mem_sz = size;
/** * free_shared_mem - Free the allocated Memory * @nic: Device private variable. * Description: This function is to free all memory locations allocated by * the init_shared_mem() function and return it to the kernel.
*/
staticvoid free_shared_mem(struct s2io_nic *nic)
{ int i, j, blk_cnt, size; void *tmp_v_addr;
dma_addr_t tmp_p_addr; int lst_size, lst_per_page; struct net_device *dev; int page_num = 0; struct config_param *config; struct mac_info *mac_control; struct stat_block *stats; struct swStat *swstats;
if (s2io_on_nec_bridge(nic->pdev)) {
DBG_PRINT(ERR_DBG, "%s: Device is on PCI-E bus\n",
nic->dev->name); return mode;
}
switch (mode) { case PCI_MODE_PCI_33:
pcimode = "33MHz PCI bus"; break; case PCI_MODE_PCI_66:
pcimode = "66MHz PCI bus"; break; case PCI_MODE_PCIX_M1_66:
pcimode = "66MHz PCIX(M1) bus"; break; case PCI_MODE_PCIX_M1_100:
pcimode = "100MHz PCIX(M1) bus"; break; case PCI_MODE_PCIX_M1_133:
pcimode = "133MHz PCIX(M1) bus"; break; case PCI_MODE_PCIX_M2_66:
pcimode = "133MHz PCIX(M2) bus"; break; case PCI_MODE_PCIX_M2_100:
pcimode = "200MHz PCIX(M2) bus"; break; case PCI_MODE_PCIX_M2_133:
pcimode = "266MHz PCIX(M2) bus"; break; default:
pcimode = "unsupported bus!";
mode = -1;
}
DBG_PRINT(ERR_DBG, "%s: Device is on %d bit %s\n",
nic->dev->name, val64 & PCI_MODE_32_BITS ? 32 : 64, pcimode);
return mode;
}
/** * init_tti - Initialization transmit traffic interrupt scheme * @nic: device private variable * @link: link status (UP/DOWN) used to enable/disable continuous * transmit interrupts * @may_sleep: parameter indicates if sleeping when waiting for * command complete * Description: The function configures transmit traffic interrupts * Return Value: SUCCESS on success and * '-1' on failure
*/
for (i = 0; i < config->tx_fifo_num; i++) { /* * TTI Initialization. Default Tx timer gets us about * 250 interrupts per sec. Continuous interrupts are enabled * by default.
*/ if (nic->device_type == XFRAME_II_DEVICE) { int count = (nic->config.bus_speed * 125)/2;
val64 = TTI_DATA1_MEM_TX_TIMER_VAL(count);
} else
val64 = TTI_DATA1_MEM_TX_TIMER_VAL(0x2078);
val64 |= TTI_DATA1_MEM_TX_URNG_A(0xA) |
TTI_DATA1_MEM_TX_URNG_B(0x10) |
TTI_DATA1_MEM_TX_URNG_C(0x30) |
TTI_DATA1_MEM_TX_TIMER_AC_EN; if (i == 0) if (use_continuous_tx_intrs && (link == LINK_UP))
val64 |= TTI_DATA1_MEM_TX_TIMER_CI_EN;
writeq(val64, &bar0->tti_data1_mem);
if (wait_for_cmd_complete(&bar0->tti_command_mem,
TTI_CMD_MEM_STROBE_NEW_CMD,
S2IO_BIT_RESET, may_sleep) != SUCCESS) return FAILURE;
}
return SUCCESS;
}
/** * init_nic - Initialization of hardware * @nic: device private variable * Description: The function sequentially configures every block * of the H/W from their reset values. * Return Value: SUCCESS on success and * '-1' on failure (endian settings incorrect).
*/
/* to set the swapper controle on the card */ if (s2io_set_swapper(nic)) {
DBG_PRINT(ERR_DBG, "ERROR: Setting Swapper failed\n"); return -EIO;
}
/* * Herc requires EOI to be removed from reset before XGXS, so..
*/ if (nic->device_type & XFRAME_II_DEVICE) {
val64 = 0xA500000000ULL;
writeq(val64, &bar0->sw_reset);
msleep(500);
val64 = readq(&bar0->sw_reset);
}
/* Remove XGXS from reset state */
val64 = 0;
writeq(val64, &bar0->sw_reset);
msleep(500);
val64 = readq(&bar0->sw_reset);
/* Ensure that it's safe to access registers by checking * RIC_RUNNING bit is reset. Check is valid only for XframeII.
*/ if (nic->device_type == XFRAME_II_DEVICE) { for (i = 0; i < 50; i++) {
val64 = readq(&bar0->adapter_status); if (!(val64 & ADAPTER_STATUS_RIC_RUNNING)) break;
msleep(10);
} if (i == 50) return -ENODEV;
}
/* Filling the Rx round robin registers as per the * number of Rings and steering based on QoS with * equal priority.
*/ switch (config->rx_ring_num) { case 1:
val64 = 0x0;
writeq(val64, &bar0->rx_w_round_robin_0);
writeq(val64, &bar0->rx_w_round_robin_1);
writeq(val64, &bar0->rx_w_round_robin_2);
writeq(val64, &bar0->rx_w_round_robin_3);
writeq(val64, &bar0->rx_w_round_robin_4);
/* UDP Fix */
val64 = 0; for (i = 0; i < 8; i++)
writeq(val64, &bar0->rts_frm_len_n[i]);
/* Set the default rts frame length for the rings configured */
val64 = MAC_RTS_FRM_LEN_SET(dev->mtu+22); for (i = 0 ; i < config->rx_ring_num ; i++)
writeq(val64, &bar0->rts_frm_len_n[i]);
/* Set the frame length for the configured rings * desired by the user
*/ for (i = 0; i < config->rx_ring_num; i++) { /* If rts_frm_len[i] == 0 then it is assumed that user not * specified frame length steering. * If the user provides the frame length then program * the rts_frm_len register for those values or else * leave it as it is.
*/ if (rts_frm_len[i] != 0) {
writeq(MAC_RTS_FRM_LEN_SET(rts_frm_len[i]),
&bar0->rts_frm_len_n[i]);
}
}
/* Disable differentiated services steering logic */ for (i = 0; i < 64; i++) { if (rts_ds_steer(nic, i, 0) == FAILURE) {
DBG_PRINT(ERR_DBG, "%s: rts_ds_steer failed on codepoint %d\n",
dev->name, i); return -ENODEV;
}
}
/* Program statistics memory */
writeq(mac_control->stats_mem_phy, &bar0->stat_addr);
/* * Initializing the sampling rate for the device to calculate the * bandwidth utilization.
*/
val64 = MAC_TX_LINK_UTIL_VAL(tmac_util_period) |
MAC_RX_LINK_UTIL_VAL(rmac_util_period);
writeq(val64, &bar0->mac_link_util);
/* * Initializing the Transmit and Receive Traffic Interrupt * Scheme.
*/
for (i = 0; i < config->rx_ring_num; i++) {
val64 = RTI_CMD_MEM_WE |
RTI_CMD_MEM_STROBE_NEW_CMD |
RTI_CMD_MEM_OFFSET(i);
writeq(val64, &bar0->rti_command_mem);
/* * Once the operation completes, the Strobe bit of the * command register will be reset. We poll for this * particular condition. We wait for a maximum of 500ms * for the operation to complete, if it's not complete * by then we return error.
*/
time = 0; while (true) {
val64 = readq(&bar0->rti_command_mem); if (!(val64 & RTI_CMD_MEM_STROBE_NEW_CMD)) break;
/* * Initializing proper values as Pause threshold into all * the 8 Queues on Rx side.
*/
writeq(0xffbbffbbffbbffbbULL, &bar0->mc_pause_thresh_q0q3);
writeq(0xffbbffbbffbbffbbULL, &bar0->mc_pause_thresh_q4q7);
/* * Set the time value to be inserted in the pause frame * generated by xena.
*/
val64 = readq(&bar0->rmac_pause_cfg);
val64 &= ~(RMAC_PAUSE_HG_PTIME(0xffff));
val64 |= RMAC_PAUSE_HG_PTIME(nic->mac_control.rmac_pause_time);
writeq(val64, &bar0->rmac_pause_cfg);
/* * Set the Threshold Limit for Generating the pause frame * If the amount of data in any Queue exceeds ratio of * (mac_control.mc_pause_threshold_q0q3 or q4q7)/256 * pause frame is generated
*/
val64 = 0; for (i = 0; i < 4; i++) {
val64 |= (((u64)0xFF00 |
nic->mac_control.mc_pause_threshold_q0q3)
<< (i * 2 * 8));
}
writeq(val64, &bar0->mc_pause_thresh_q0q3);
val64 = 0; for (i = 0; i < 4; i++) {
val64 |= (((u64)0xFF00 |
nic->mac_control.mc_pause_threshold_q4q7)
<< (i * 2 * 8));
}
writeq(val64, &bar0->mc_pause_thresh_q4q7);
/* * TxDMA will stop Read request if the number of read split has * exceeded the limit pointed by shared_splits
*/
val64 = readq(&bar0->pic_control);
val64 |= PIC_CNTL_SHARED_SPLITS(shared_splits);
writeq(val64, &bar0->pic_control);
/* * Programming the Herc to split every write transaction * that does not start on an ADB to reduce disconnects.
*/ if (nic->device_type == XFRAME_II_DEVICE) {
val64 = FAULT_BEHAVIOUR | EXT_REQ_EN |
MISC_LINK_STABILITY_PRD(3);
writeq(val64, &bar0->misc_control);
val64 = readq(&bar0->pic_control2);
val64 &= ~(s2BIT(13)|s2BIT(14)|s2BIT(15));
writeq(val64, &bar0->pic_control2);
} if (strstr(nic->product_name, "CX4")) {
val64 = TMAC_AVG_IPG(0x17);
writeq(val64, &bar0->tmac_avg_ipg);
}
/* Remove this line when alarm interrupts are enabled */
nic->general_int_mask = 0;
}
/** * en_dis_able_nic_intrs - Enable or Disable the interrupts * @nic: device private variable, * @mask: A mask indicating which Intr block must be modified and, * @flag: A flag indicating whether to enable or disable the Intrs. * Description: This function will either disable or enable the interrupts * depending on the flag argument. The mask argument can be used to * enable/disable any Intr block. * Return Value: NONE.
*/
/** * verify_pcc_quiescent- Checks for PCC quiescent state * @sp : private member of the device structure, which is a pointer to the * s2io_nic structure. * @flag: boolean controlling function path * Return: 1 If PCC is quiescence * 0 If PCC is not quiescence
*/ staticint verify_pcc_quiescent(struct s2io_nic *sp, int flag)
{ int ret = 0, herc; struct XENA_dev_config __iomem *bar0 = sp->bar0;
u64 val64 = readq(&bar0->adapter_status);
herc = (sp->device_type == XFRAME_II_DEVICE);
if (flag == false) { if ((!herc && (sp->pdev->revision >= 4)) || herc) { if (!(val64 & ADAPTER_STATUS_RMAC_PCC_IDLE))
ret = 1;
} else { if (!(val64 & ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE))
ret = 1;
}
} else { if ((!herc && (sp->pdev->revision >= 4)) || herc) { if (((val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) ==
ADAPTER_STATUS_RMAC_PCC_IDLE))
ret = 1;
} else { if (((val64 & ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE) ==
ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE))
ret = 1;
}
}
return ret;
} /** * verify_xena_quiescence - Checks whether the H/W is ready * @sp : private member of the device structure, which is a pointer to the * s2io_nic structure. * Description: Returns whether the H/W is ready to go or not. Depending * on whether adapter enable bit was written or not the comparison * differs and the calling function passes the input argument flag to * indicate this. * Return: 1 If xena is quiescence * 0 If Xena is not quiescence
*/
if (!(val64 & ADAPTER_STATUS_TDMA_READY)) {
DBG_PRINT(ERR_DBG, "TDMA is not ready!\n"); return 0;
} if (!(val64 & ADAPTER_STATUS_RDMA_READY)) {
DBG_PRINT(ERR_DBG, "RDMA is not ready!\n"); return 0;
} if (!(val64 & ADAPTER_STATUS_PFC_READY)) {
DBG_PRINT(ERR_DBG, "PFC is not ready!\n"); return 0;
} if (!(val64 & ADAPTER_STATUS_TMAC_BUF_EMPTY)) {
DBG_PRINT(ERR_DBG, "TMAC BUF is not empty!\n"); return 0;
} if (!(val64 & ADAPTER_STATUS_PIC_QUIESCENT)) {
DBG_PRINT(ERR_DBG, "PIC is not QUIESCENT!\n"); return 0;
} if (!(val64 & ADAPTER_STATUS_MC_DRAM_READY)) {
DBG_PRINT(ERR_DBG, "MC_DRAM is not ready!\n"); return 0;
} if (!(val64 & ADAPTER_STATUS_MC_QUEUES_READY)) {
DBG_PRINT(ERR_DBG, "MC_QUEUES is not ready!\n"); return 0;
} if (!(val64 & ADAPTER_STATUS_M_PLL_LOCK)) {
DBG_PRINT(ERR_DBG, "M_PLL is not locked!\n"); return 0;
}
/* * In PCI 33 mode, the P_PLL is not used, and therefore, * 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, "P_PLL is not locked!\n"); return 0;
} if (!((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ==
ADAPTER_STATUS_RC_PRC_QUIESCENT)) {
DBG_PRINT(ERR_DBG, "RC_PRC is not QUIESCENT!\n"); return 0;
} return 1;
}
/** * fix_mac_address - Fix for Mac addr problem on Alpha platforms * @sp: Pointer to device specifc structure * Description : * New procedure to clear mac address reading problems on Alpha platforms *
*/
staticvoid fix_mac_address(struct s2io_nic *sp)
{ struct XENA_dev_config __iomem *bar0 = sp->bar0; int i = 0;
/** * start_nic - Turns the device on * @nic : device private variable. * Description: * This function actually turns the device on. Before this function is * called,all Registers are configured from their reset states * and shared memory is allocated but the NIC is still quiescent. On * calling this function, the device interrupts are cleared and the NIC is * literally switched on by writing into the adapter control register. * Return Value: * SUCCESS on success and -1 on failure.
*/
/* * Enabling MC-RLDRAM. After enabling the device, we timeout * for around 100ms, which is approximately the time required * for the device to be ready for operation.
*/
val64 = readq(&bar0->mc_rldram_mrs);
val64 |= MC_RLDRAM_QUEUE_SIZE_ENABLE | MC_RLDRAM_MRS_ENABLE;
SPECIAL_REG_WRITE(val64, &bar0->mc_rldram_mrs, UF);
val64 = readq(&bar0->mc_rldram_mrs);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.