in ethernet/neterion/s2io.c [1187:1816]
static int init_nic(struct s2io_nic *nic)
{
struct XENA_dev_config __iomem *bar0 = nic->bar0;
struct net_device *dev = nic->dev;
register u64 val64 = 0;
void __iomem *add;
u32 time;
int i, j;
int dtx_cnt = 0;
unsigned long long mem_share;
int mem_size;
struct config_param *config = &nic->config;
struct mac_info *mac_control = &nic->mac_control;
/* 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;
}
/* Enable Receiving broadcasts */
add = &bar0->mac_cfg;
val64 = readq(&bar0->mac_cfg);
val64 |= MAC_RMAC_BCAST_ENABLE;
writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key);
writel((u32)val64, add);
writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key);
writel((u32) (val64 >> 32), (add + 4));
/* Read registers in all blocks */
val64 = readq(&bar0->mac_int_mask);
val64 = readq(&bar0->mc_int_mask);
val64 = readq(&bar0->xgxs_int_mask);
/* Set MTU */
val64 = dev->mtu;
writeq(vBIT(val64, 2, 14), &bar0->rmac_max_pyld_len);
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],
&bar0->dtx_control, UF);
if (dtx_cnt & 0x1)
msleep(1); /* Necessary!! */
dtx_cnt++;
}
} else {
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++;
}
}
/* Tx DMA Initialization */
val64 = 0;
writeq(val64, &bar0->tx_fifo_partition_0);
writeq(val64, &bar0->tx_fifo_partition_1);
writeq(val64, &bar0->tx_fifo_partition_2);
writeq(val64, &bar0->tx_fifo_partition_3);
for (i = 0, j = 0; i < config->tx_fifo_num; i++) {
struct tx_fifo_config *tx_cfg = &config->tx_cfg[i];
val64 |= vBIT(tx_cfg->fifo_len - 1, ((j * 32) + 19), 13) |
vBIT(tx_cfg->fifo_priority, ((j * 32) + 5), 3);
if (i == (config->tx_fifo_num - 1)) {
if (i % 2 == 0)
i++;
}
switch (i) {
case 1:
writeq(val64, &bar0->tx_fifo_partition_0);
val64 = 0;
j = 0;
break;
case 3:
writeq(val64, &bar0->tx_fifo_partition_1);
val64 = 0;
j = 0;
break;
case 5:
writeq(val64, &bar0->tx_fifo_partition_2);
val64 = 0;
j = 0;
break;
case 7:
writeq(val64, &bar0->tx_fifo_partition_3);
val64 = 0;
j = 0;
break;
default:
j++;
break;
}
}
/*
* Disable 4 PCCs for Xena1, 2 and 3 as per H/W bug
* SXE-008 TRANSMIT DMA ARBITRATION ISSUE.
*/
if ((nic->device_type == XFRAME_I_DEVICE) && (nic->pdev->revision < 4))
writeq(PCC_ENABLE_FOUR, &bar0->pcc_enable);
val64 = readq(&bar0->tx_fifo_partition_0);
DBG_PRINT(INIT_DBG, "Fifo partition at: 0x%p is: 0x%llx\n",
&bar0->tx_fifo_partition_0, (unsigned long long)val64);
/*
* Initialization of Tx_PA_CONFIG register to ignore packet
* integrity checking.
*/
val64 = readq(&bar0->tx_pa_cfg);
val64 |= TX_PA_CFG_IGNORE_FRM_ERR |
TX_PA_CFG_IGNORE_SNAP_OUI |
TX_PA_CFG_IGNORE_LLC_CTRL |
TX_PA_CFG_IGNORE_L2_ERR;
writeq(val64, &bar0->tx_pa_cfg);
/* Rx DMA initialization. */
val64 = 0;
for (i = 0; i < config->rx_ring_num; i++) {
struct rx_ring_config *rx_cfg = &config->rx_cfg[i];
val64 |= vBIT(rx_cfg->ring_priority, (5 + (i * 8)), 3);
}
writeq(val64, &bar0->rx_queue_priority);
/*
* Allocating equal share of memory to all the
* configured Rings.
*/
val64 = 0;
if (nic->device_type & XFRAME_II_DEVICE)
mem_size = 32;
else
mem_size = 64;
for (i = 0; i < config->rx_ring_num; i++) {
switch (i) {
case 0:
mem_share = (mem_size / config->rx_ring_num +
mem_size % config->rx_ring_num);
val64 |= RX_QUEUE_CFG_Q0_SZ(mem_share);
continue;
case 1:
mem_share = (mem_size / config->rx_ring_num);
val64 |= RX_QUEUE_CFG_Q1_SZ(mem_share);
continue;
case 2:
mem_share = (mem_size / config->rx_ring_num);
val64 |= RX_QUEUE_CFG_Q2_SZ(mem_share);
continue;
case 3:
mem_share = (mem_size / config->rx_ring_num);
val64 |= RX_QUEUE_CFG_Q3_SZ(mem_share);
continue;
case 4:
mem_share = (mem_size / config->rx_ring_num);
val64 |= RX_QUEUE_CFG_Q4_SZ(mem_share);
continue;
case 5:
mem_share = (mem_size / config->rx_ring_num);
val64 |= RX_QUEUE_CFG_Q5_SZ(mem_share);
continue;
case 6:
mem_share = (mem_size / config->rx_ring_num);
val64 |= RX_QUEUE_CFG_Q6_SZ(mem_share);
continue;
case 7:
mem_share = (mem_size / config->rx_ring_num);
val64 |= RX_QUEUE_CFG_Q7_SZ(mem_share);
continue;
}
}
writeq(val64, &bar0->rx_queue_cfg);
/*
* Filling Tx round robin registers
* as per the number of FIFOs for equal scheduling priority
*/
switch (config->tx_fifo_num) {
case 1:
val64 = 0x0;
writeq(val64, &bar0->tx_w_round_robin_0);
writeq(val64, &bar0->tx_w_round_robin_1);
writeq(val64, &bar0->tx_w_round_robin_2);
writeq(val64, &bar0->tx_w_round_robin_3);
writeq(val64, &bar0->tx_w_round_robin_4);
break;
case 2:
val64 = 0x0001000100010001ULL;
writeq(val64, &bar0->tx_w_round_robin_0);
writeq(val64, &bar0->tx_w_round_robin_1);
writeq(val64, &bar0->tx_w_round_robin_2);
writeq(val64, &bar0->tx_w_round_robin_3);
val64 = 0x0001000100000000ULL;
writeq(val64, &bar0->tx_w_round_robin_4);
break;
case 3:
val64 = 0x0001020001020001ULL;
writeq(val64, &bar0->tx_w_round_robin_0);
val64 = 0x0200010200010200ULL;
writeq(val64, &bar0->tx_w_round_robin_1);
val64 = 0x0102000102000102ULL;
writeq(val64, &bar0->tx_w_round_robin_2);
val64 = 0x0001020001020001ULL;
writeq(val64, &bar0->tx_w_round_robin_3);
val64 = 0x0200010200000000ULL;
writeq(val64, &bar0->tx_w_round_robin_4);
break;
case 4:
val64 = 0x0001020300010203ULL;
writeq(val64, &bar0->tx_w_round_robin_0);
writeq(val64, &bar0->tx_w_round_robin_1);
writeq(val64, &bar0->tx_w_round_robin_2);
writeq(val64, &bar0->tx_w_round_robin_3);
val64 = 0x0001020300000000ULL;
writeq(val64, &bar0->tx_w_round_robin_4);
break;
case 5:
val64 = 0x0001020304000102ULL;
writeq(val64, &bar0->tx_w_round_robin_0);
val64 = 0x0304000102030400ULL;
writeq(val64, &bar0->tx_w_round_robin_1);
val64 = 0x0102030400010203ULL;
writeq(val64, &bar0->tx_w_round_robin_2);
val64 = 0x0400010203040001ULL;
writeq(val64, &bar0->tx_w_round_robin_3);
val64 = 0x0203040000000000ULL;
writeq(val64, &bar0->tx_w_round_robin_4);
break;
case 6:
val64 = 0x0001020304050001ULL;
writeq(val64, &bar0->tx_w_round_robin_0);
val64 = 0x0203040500010203ULL;
writeq(val64, &bar0->tx_w_round_robin_1);
val64 = 0x0405000102030405ULL;
writeq(val64, &bar0->tx_w_round_robin_2);
val64 = 0x0001020304050001ULL;
writeq(val64, &bar0->tx_w_round_robin_3);
val64 = 0x0203040500000000ULL;
writeq(val64, &bar0->tx_w_round_robin_4);
break;
case 7:
val64 = 0x0001020304050600ULL;
writeq(val64, &bar0->tx_w_round_robin_0);
val64 = 0x0102030405060001ULL;
writeq(val64, &bar0->tx_w_round_robin_1);
val64 = 0x0203040506000102ULL;
writeq(val64, &bar0->tx_w_round_robin_2);
val64 = 0x0304050600010203ULL;
writeq(val64, &bar0->tx_w_round_robin_3);
val64 = 0x0405060000000000ULL;
writeq(val64, &bar0->tx_w_round_robin_4);
break;
case 8:
val64 = 0x0001020304050607ULL;
writeq(val64, &bar0->tx_w_round_robin_0);
writeq(val64, &bar0->tx_w_round_robin_1);
writeq(val64, &bar0->tx_w_round_robin_2);
writeq(val64, &bar0->tx_w_round_robin_3);
val64 = 0x0001020300000000ULL;
writeq(val64, &bar0->tx_w_round_robin_4);
break;
}
/* Enable all configured Tx FIFO partitions */
val64 = readq(&bar0->tx_fifo_partition_0);
val64 |= (TX_FIFO_PARTITION_EN);
writeq(val64, &bar0->tx_fifo_partition_0);
/* 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);
val64 = 0x8080808080808080ULL;
writeq(val64, &bar0->rts_qos_steering);
break;
case 2:
val64 = 0x0001000100010001ULL;
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);
val64 = 0x0001000100000000ULL;
writeq(val64, &bar0->rx_w_round_robin_4);
val64 = 0x8080808040404040ULL;
writeq(val64, &bar0->rts_qos_steering);
break;
case 3:
val64 = 0x0001020001020001ULL;
writeq(val64, &bar0->rx_w_round_robin_0);
val64 = 0x0200010200010200ULL;
writeq(val64, &bar0->rx_w_round_robin_1);
val64 = 0x0102000102000102ULL;
writeq(val64, &bar0->rx_w_round_robin_2);
val64 = 0x0001020001020001ULL;
writeq(val64, &bar0->rx_w_round_robin_3);
val64 = 0x0200010200000000ULL;
writeq(val64, &bar0->rx_w_round_robin_4);
val64 = 0x8080804040402020ULL;
writeq(val64, &bar0->rts_qos_steering);
break;
case 4:
val64 = 0x0001020300010203ULL;
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);
val64 = 0x0001020300000000ULL;
writeq(val64, &bar0->rx_w_round_robin_4);
val64 = 0x8080404020201010ULL;
writeq(val64, &bar0->rts_qos_steering);
break;
case 5:
val64 = 0x0001020304000102ULL;
writeq(val64, &bar0->rx_w_round_robin_0);
val64 = 0x0304000102030400ULL;
writeq(val64, &bar0->rx_w_round_robin_1);
val64 = 0x0102030400010203ULL;
writeq(val64, &bar0->rx_w_round_robin_2);
val64 = 0x0400010203040001ULL;
writeq(val64, &bar0->rx_w_round_robin_3);
val64 = 0x0203040000000000ULL;
writeq(val64, &bar0->rx_w_round_robin_4);
val64 = 0x8080404020201008ULL;
writeq(val64, &bar0->rts_qos_steering);
break;
case 6:
val64 = 0x0001020304050001ULL;
writeq(val64, &bar0->rx_w_round_robin_0);
val64 = 0x0203040500010203ULL;
writeq(val64, &bar0->rx_w_round_robin_1);
val64 = 0x0405000102030405ULL;
writeq(val64, &bar0->rx_w_round_robin_2);
val64 = 0x0001020304050001ULL;
writeq(val64, &bar0->rx_w_round_robin_3);
val64 = 0x0203040500000000ULL;
writeq(val64, &bar0->rx_w_round_robin_4);
val64 = 0x8080404020100804ULL;
writeq(val64, &bar0->rts_qos_steering);
break;
case 7:
val64 = 0x0001020304050600ULL;
writeq(val64, &bar0->rx_w_round_robin_0);
val64 = 0x0102030405060001ULL;
writeq(val64, &bar0->rx_w_round_robin_1);
val64 = 0x0203040506000102ULL;
writeq(val64, &bar0->rx_w_round_robin_2);
val64 = 0x0304050600010203ULL;
writeq(val64, &bar0->rx_w_round_robin_3);
val64 = 0x0405060000000000ULL;
writeq(val64, &bar0->rx_w_round_robin_4);
val64 = 0x8080402010080402ULL;
writeq(val64, &bar0->rts_qos_steering);
break;
case 8:
val64 = 0x0001020304050607ULL;
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);
val64 = 0x0001020300000000ULL;
writeq(val64, &bar0->rx_w_round_robin_4);
val64 = 0x8040201008040201ULL;
writeq(val64, &bar0->rts_qos_steering);
break;
}
/* 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);
if (nic->device_type == XFRAME_II_DEVICE) {
val64 = STAT_BC(0x320);
writeq(val64, &bar0->stat_byte_cnt);
}
/*
* 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.
*/
/* Initialize TTI */
if (SUCCESS != init_tti(nic, nic->last_link_state, true))
return -ENODEV;
/* RTI Initialization */
if (nic->device_type == XFRAME_II_DEVICE) {
/*
* Programmed to generate Apprx 500 Intrs per
* second
*/
int count = (nic->config.bus_speed * 125)/4;
val64 = RTI_DATA1_MEM_RX_TIMER_VAL(count);
} else
val64 = RTI_DATA1_MEM_RX_TIMER_VAL(0xFFF);
val64 |= RTI_DATA1_MEM_RX_URNG_A(0xA) |
RTI_DATA1_MEM_RX_URNG_B(0x10) |
RTI_DATA1_MEM_RX_URNG_C(0x30) |
RTI_DATA1_MEM_RX_TIMER_AC_EN;
writeq(val64, &bar0->rti_data1_mem);
val64 = RTI_DATA2_MEM_RX_UFC_A(0x1) |
RTI_DATA2_MEM_RX_UFC_B(0x2) ;
if (nic->config.intr_type == MSI_X)
val64 |= (RTI_DATA2_MEM_RX_UFC_C(0x20) |
RTI_DATA2_MEM_RX_UFC_D(0x40));
else
val64 |= (RTI_DATA2_MEM_RX_UFC_C(0x40) |
RTI_DATA2_MEM_RX_UFC_D(0x80));
writeq(val64, &bar0->rti_data2_mem);
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;
if (time > 10) {
DBG_PRINT(ERR_DBG, "%s: RTI init failed\n",
dev->name);
return -ENODEV;
}
time++;
msleep(50);
}
}
/*
* 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);
/* Disable RMAC PAD STRIPPING */
add = &bar0->mac_cfg;
val64 = readq(&bar0->mac_cfg);
val64 &= ~(MAC_CFG_RMAC_STRIP_PAD);
writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key);
writel((u32) (val64), add);
writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key);
writel((u32) (val64 >> 32), (add + 4));
val64 = readq(&bar0->mac_cfg);
/* Enable FCS stripping by adapter */
add = &bar0->mac_cfg;
val64 = readq(&bar0->mac_cfg);
val64 |= MAC_CFG_RMAC_STRIP_FCS;
if (nic->device_type == XFRAME_II_DEVICE)
writeq(val64, &bar0->mac_cfg);
else {
writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key);
writel((u32) (val64), add);
writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key);
writel((u32) (val64 >> 32), (add + 4));
}
/*
* 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);
if (nic->config.bus_speed == 266) {
writeq(TXREQTO_VAL(0x7f) | TXREQTO_EN, &bar0->txreqtimeout);
writeq(0x0, &bar0->read_retry_delay);
writeq(0x0, &bar0->write_retry_delay);
}
/*
* 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);
}
return SUCCESS;
}