📄 s2io.c
字号:
for (i = 0; i < config->rx_ring_num; i++) { blk_cnt = mac_control->rings[i].block_count; for (j = 0; j < blk_cnt; j++) { tmp_v_addr = mac_control->rings[i].rx_blocks[j]. block_virt_addr; tmp_p_addr = mac_control->rings[i].rx_blocks[j]. block_dma_addr; if (tmp_v_addr == NULL) break; pci_free_consistent(nic->pdev, size, tmp_v_addr, tmp_p_addr); nic->mac_control.stats_info->sw_stat.mem_freed += size; kfree(mac_control->rings[i].rx_blocks[j].rxds); nic->mac_control.stats_info->sw_stat.mem_freed += ( sizeof(struct rxd_info)* rxd_count[nic->rxd_mode]); } } if (nic->rxd_mode == RXD_MODE_3B) { /* Freeing buffer storage addresses in 2BUFF mode. */ for (i = 0; i < config->rx_ring_num; i++) { blk_cnt = config->rx_cfg[i].num_rxd / (rxd_count[nic->rxd_mode] + 1); for (j = 0; j < blk_cnt; j++) { int k = 0; if (!mac_control->rings[i].ba[j]) continue; while (k != rxd_count[nic->rxd_mode]) { struct buffAdd *ba = &mac_control->rings[i].ba[j][k]; kfree(ba->ba_0_org); nic->mac_control.stats_info->sw_stat.\ mem_freed += (BUF0_LEN + ALIGN_SIZE); kfree(ba->ba_1_org); nic->mac_control.stats_info->sw_stat.\ mem_freed += (BUF1_LEN + ALIGN_SIZE); k++; } kfree(mac_control->rings[i].ba[j]); nic->mac_control.stats_info->sw_stat.mem_freed += (sizeof(struct buffAdd) * (rxd_count[nic->rxd_mode] + 1)); } kfree(mac_control->rings[i].ba); nic->mac_control.stats_info->sw_stat.mem_freed += (sizeof(struct buffAdd *) * blk_cnt); } } if (mac_control->stats_mem) { pci_free_consistent(nic->pdev, mac_control->stats_mem_sz, mac_control->stats_mem, mac_control->stats_mem_phy); nic->mac_control.stats_info->sw_stat.mem_freed += mac_control->stats_mem_sz; } if (nic->ufo_in_band_v) { kfree(nic->ufo_in_band_v); nic->mac_control.stats_info->sw_stat.mem_freed += (ufo_size * sizeof(u64)); }}/** * s2io_verify_pci_mode - */static int s2io_verify_pci_mode(struct s2io_nic *nic){ struct XENA_dev_config __iomem *bar0 = nic->bar0; register u64 val64 = 0; int mode; val64 = readq(&bar0->pci_mode); mode = (u8)GET_PCI_MODE(val64); if ( val64 & PCI_MODE_UNKNOWN_MODE) return -1; /* Unknown PCI mode */ return mode;}#define NEC_VENID 0x1033#define NEC_DEVID 0x0125static int s2io_on_nec_bridge(struct pci_dev *s2io_pdev){ struct pci_dev *tdev = NULL; while ((tdev = pci_get_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) pci_dev_put(tdev); return 1; } } return 0;}static int bus_speed[8] = {33, 133, 133, 200, 266, 133, 200, 266};/** * s2io_print_pci_mode - */static int s2io_print_pci_mode(struct s2io_nic *nic){ struct XENA_dev_config __iomem *bar0 = nic->bar0; register u64 val64 = 0; int mode; struct config_param *config = &nic->config; val64 = readq(&bar0->pci_mode); mode = (u8)GET_PCI_MODE(val64); 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 { DBG_PRINT(ERR_DBG, "%s: Device is on 64 bit ", nic->dev->name); } switch(mode) { case PCI_MODE_PCI_33: DBG_PRINT(ERR_DBG, "33MHz PCI bus\n"); break; case PCI_MODE_PCI_66: DBG_PRINT(ERR_DBG, "66MHz PCI bus\n"); break; case PCI_MODE_PCIX_M1_66: DBG_PRINT(ERR_DBG, "66MHz PCIX(M1) bus\n"); break; case PCI_MODE_PCIX_M1_100: DBG_PRINT(ERR_DBG, "100MHz PCIX(M1) bus\n"); break; case PCI_MODE_PCIX_M1_133: DBG_PRINT(ERR_DBG, "133MHz PCIX(M1) bus\n"); break; case PCI_MODE_PCIX_M2_66: DBG_PRINT(ERR_DBG, "133MHz PCIX(M2) bus\n"); break; case PCI_MODE_PCIX_M2_100: DBG_PRINT(ERR_DBG, "200MHz PCIX(M2) bus\n"); break; case PCI_MODE_PCIX_M2_133: DBG_PRINT(ERR_DBG, "266MHz PCIX(M2) bus\n"); break; default: return -1; /* Unsupported bus speed */ } return mode;}/** * init_nic - Initialization of hardware * @nic: device peivate 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). */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; struct mac_info *mac_control; struct config_param *config; int dtx_cnt = 0; unsigned long long mem_share; int mem_size; mac_control = &nic->mac_control; config = &nic->config; /* 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++) { val64 |= vBIT(config->tx_cfg[i].fifo_len - 1, ((i * 32) + 19), 13) | vBIT(config->tx_cfg[i].fifo_priority, ((i * 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; break; case 3: writeq(val64, &bar0->tx_fifo_partition_1); val64 = 0; break; case 5: writeq(val64, &bar0->tx_fifo_partition_2); val64 = 0; break; case 7: writeq(val64, &bar0->tx_fifo_partition_3); 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 intialization. */ val64 = 0; for (i = 0; i < config->rx_ring_num; i++) { val64 |= vBIT(config->rx_cfg[i].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 */ switch (config->tx_fifo_num) { case 1: val64 = 0x0000000000000000ULL; 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 = 0x0000010000010000ULL; writeq(val64, &bar0->tx_w_round_robin_0); val64 = 0x0100000100000100ULL; writeq(val64, &bar0->tx_w_round_robin_1); val64 = 0x0001000001000001ULL; writeq(val64, &bar0->tx_w_round_robin_2); val64 = 0x0000010000010000ULL; writeq(val64, &bar0->tx_w_round_robin_3); val64 = 0x0100000000000000ULL; writeq(val64, &bar0->tx_w_round_robin_4); break; case 3: val64 = 0x0001000102000001ULL; writeq(val64, &bar0->tx_w_round_robin_0); val64 = 0x0001020000010001ULL; writeq(val64, &bar0->tx_w_round_robin_1); val64 = 0x0200000100010200ULL; writeq(val64, &bar0->tx_w_round_robin_2); val64 = 0x0001000102000001ULL; writeq(val64, &bar0->tx_w_round_robin_3); val64 = 0x0001020000000000ULL; writeq(val64, &bar0->tx_w_round_robin_4); break; case 4: val64 = 0x0001020300010200ULL; writeq(val64, &bar0->tx_w_round_robin_0); val64 = 0x0100000102030001ULL; writeq(val64, &bar0->tx_w_round_robin_1); val64 = 0x0200010000010203ULL; writeq(val64, &bar0->tx_w_round_robin_2); val64 = 0x0001020001000001ULL; writeq(val64, &bar0->tx_w_round_robin_3); val64 = 0x0203000100000000ULL; writeq(val64, &bar0->tx_w_round_robin_4); break; case 5: val64 = 0x0001000203000102ULL; writeq(val64, &bar0->tx_w_round_robin_0); val64 = 0x0001020001030004ULL; writeq(val64, &bar0->tx_w_round_robin_1); val64 = 0x0001000203000102ULL; writeq(val64, &bar0->tx_w_round_robin_2); val64 = 0x0001020001030004ULL; writeq(val64, &bar0->tx_w_round_robin_3); val64 = 0x0001000000000000ULL; writeq(val64, &bar0->tx_w_round_robin_4); break; case 6: val64 = 0x0001020304000102ULL; writeq(val64, &bar0->tx_w_round_robin_0); val64 = 0x0304050001020001ULL; writeq(val64, &bar0->tx_w_round_robin_1); val64 = 0x0203000100000102ULL; writeq(val64, &bar0->tx_w_round_robin_2); val64 = 0x0304000102030405ULL; writeq(val64, &bar0->tx_w_round_robin_3); val64 = 0x0001000200000000ULL; writeq(val64, &bar0->tx_w_round_robin_4); break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -