📄 s2io.c
字号:
TXDMA_LSO_INT | TXDMA_TPA_INT | TXDMA_SM_INT, flag, &bar0->txdma_int_mask); do_s2io_write_bits(PFC_ECC_DB_ERR | PFC_SM_ERR_ALARM | PFC_MISC_0_ERR | PFC_MISC_1_ERR | PFC_PCIX_ERR | PFC_ECC_SG_ERR, flag, &bar0->pfc_err_mask); do_s2io_write_bits(TDA_Fn_ECC_DB_ERR | TDA_SM0_ERR_ALARM | TDA_SM1_ERR_ALARM | TDA_Fn_ECC_SG_ERR | TDA_PCIX_ERR, flag, &bar0->tda_err_mask); do_s2io_write_bits(PCC_FB_ECC_DB_ERR | PCC_TXB_ECC_DB_ERR | PCC_SM_ERR_ALARM | PCC_WR_ERR_ALARM | PCC_N_SERR | PCC_6_COF_OV_ERR | PCC_7_COF_OV_ERR | PCC_6_LSO_OV_ERR | PCC_7_LSO_OV_ERR | PCC_FB_ECC_SG_ERR | PCC_TXB_ECC_SG_ERR, flag, &bar0->pcc_err_mask); do_s2io_write_bits(TTI_SM_ERR_ALARM | TTI_ECC_SG_ERR | TTI_ECC_DB_ERR, flag, &bar0->tti_err_mask); do_s2io_write_bits(LSO6_ABORT | LSO7_ABORT | LSO6_SM_ERR_ALARM | LSO7_SM_ERR_ALARM | LSO6_SEND_OFLOW | LSO7_SEND_OFLOW, flag, &bar0->lso_err_mask); do_s2io_write_bits(TPA_SM_ERR_ALARM | TPA_TX_FRM_DROP, flag, &bar0->tpa_err_mask); do_s2io_write_bits(SM_SM_ERR_ALARM, flag, &bar0->sm_err_mask); } if (mask & TX_MAC_INTR) { gen_int_mask |= TXMAC_INT_M; do_s2io_write_bits(MAC_INT_STATUS_TMAC_INT, flag, &bar0->mac_int_mask); do_s2io_write_bits(TMAC_TX_BUF_OVRN | TMAC_TX_SM_ERR | TMAC_ECC_SG_ERR | TMAC_ECC_DB_ERR | TMAC_DESC_ECC_SG_ERR | TMAC_DESC_ECC_DB_ERR, flag, &bar0->mac_tmac_err_mask); } if (mask & TX_XGXS_INTR) { gen_int_mask |= TXXGXS_INT_M; do_s2io_write_bits(XGXS_INT_STATUS_TXGXS, flag, &bar0->xgxs_int_mask); do_s2io_write_bits(TXGXS_ESTORE_UFLOW | TXGXS_TX_SM_ERR | TXGXS_ECC_SG_ERR | TXGXS_ECC_DB_ERR, flag, &bar0->xgxs_txgxs_err_mask); } if (mask & RX_DMA_INTR) { gen_int_mask |= RXDMA_INT_M; do_s2io_write_bits(RXDMA_INT_RC_INT_M | RXDMA_INT_RPA_INT_M | RXDMA_INT_RDA_INT_M | RXDMA_INT_RTI_INT_M, flag, &bar0->rxdma_int_mask); do_s2io_write_bits(RC_PRCn_ECC_DB_ERR | RC_FTC_ECC_DB_ERR | RC_PRCn_SM_ERR_ALARM | RC_FTC_SM_ERR_ALARM | RC_PRCn_ECC_SG_ERR | RC_FTC_ECC_SG_ERR | RC_RDA_FAIL_WR_Rn, flag, &bar0->rc_err_mask); do_s2io_write_bits(PRC_PCI_AB_RD_Rn | PRC_PCI_AB_WR_Rn | PRC_PCI_AB_F_WR_Rn | PRC_PCI_DP_RD_Rn | PRC_PCI_DP_WR_Rn | PRC_PCI_DP_F_WR_Rn, flag, &bar0->prc_pcix_err_mask); do_s2io_write_bits(RPA_SM_ERR_ALARM | RPA_CREDIT_ERR | RPA_ECC_SG_ERR | RPA_ECC_DB_ERR, flag, &bar0->rpa_err_mask); do_s2io_write_bits(RDA_RXDn_ECC_DB_ERR | RDA_FRM_ECC_DB_N_AERR | RDA_SM1_ERR_ALARM | RDA_SM0_ERR_ALARM | RDA_RXD_ECC_DB_SERR | RDA_RXDn_ECC_SG_ERR | RDA_FRM_ECC_SG_ERR | RDA_MISC_ERR|RDA_PCIX_ERR, flag, &bar0->rda_err_mask); do_s2io_write_bits(RTI_SM_ERR_ALARM | RTI_ECC_SG_ERR | RTI_ECC_DB_ERR, flag, &bar0->rti_err_mask); } if (mask & RX_MAC_INTR) { gen_int_mask |= RXMAC_INT_M; do_s2io_write_bits(MAC_INT_STATUS_RMAC_INT, flag, &bar0->mac_int_mask); do_s2io_write_bits(RMAC_RX_BUFF_OVRN | RMAC_RX_SM_ERR | RMAC_UNUSED_INT | RMAC_SINGLE_ECC_ERR | RMAC_DOUBLE_ECC_ERR | RMAC_LINK_STATE_CHANGE_INT, flag, &bar0->mac_rmac_err_mask); } if (mask & RX_XGXS_INTR) { gen_int_mask |= RXXGXS_INT_M; do_s2io_write_bits(XGXS_INT_STATUS_RXGXS, flag, &bar0->xgxs_int_mask); do_s2io_write_bits(RXGXS_ESTORE_OFLOW | RXGXS_RX_SM_ERR, flag, &bar0->xgxs_rxgxs_err_mask); } if (mask & MC_INTR) { gen_int_mask |= MC_INT_M; do_s2io_write_bits(MC_INT_MASK_MC_INT, flag, &bar0->mc_int_mask); do_s2io_write_bits(MC_ERR_REG_SM_ERR | MC_ERR_REG_ECC_ALL_SNG | MC_ERR_REG_ECC_ALL_DBL | PLL_LOCK_N, flag, &bar0->mc_err_mask); } nic->general_int_mask = gen_int_mask; /* 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. */static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag){ struct XENA_dev_config __iomem *bar0 = nic->bar0; register u64 temp64 = 0, intr_mask = 0; intr_mask = nic->general_int_mask; /* Top level interrupt classification */ /* PIC Interrupts */ if (mask & TX_PIC_INTR) { /* Enable PIC Intrs in the general intr mask register */ intr_mask |= TXPIC_INT_M; if (flag == ENABLE_INTRS) { /* * If Hercules adapter enable GPIO otherwise * disable all PCIX, Flash, MDIO, IIC and GPIO * interrupts for now. * TODO */ if (s2io_link_fault_indication(nic) == LINK_UP_DOWN_INTERRUPT ) { do_s2io_write_bits(PIC_INT_GPIO, flag, &bar0->pic_int_mask); do_s2io_write_bits(GPIO_INT_MASK_LINK_UP, flag, &bar0->gpio_int_mask); } else writeq(DISABLE_ALL_INTRS, &bar0->pic_int_mask); } else if (flag == DISABLE_INTRS) { /* * Disable PIC Intrs in the general * intr mask register */ writeq(DISABLE_ALL_INTRS, &bar0->pic_int_mask); } } /* Tx traffic interrupts */ if (mask & TX_TRAFFIC_INTR) { intr_mask |= TXTRAFFIC_INT_M; if (flag == ENABLE_INTRS) { /* * Enable all the Tx side interrupts * writing 0 Enables all 64 TX interrupt levels */ writeq(0x0, &bar0->tx_traffic_mask); } else if (flag == DISABLE_INTRS) { /* * Disable Tx Traffic Intrs in the general intr mask * register. */ writeq(DISABLE_ALL_INTRS, &bar0->tx_traffic_mask); } } /* Rx traffic interrupts */ if (mask & RX_TRAFFIC_INTR) { intr_mask |= RXTRAFFIC_INT_M; if (flag == ENABLE_INTRS) { /* writing 0 Enables all 8 RX interrupt levels */ writeq(0x0, &bar0->rx_traffic_mask); } else if (flag == DISABLE_INTRS) { /* * Disable Rx Traffic Intrs in the general intr mask * register. */ writeq(DISABLE_ALL_INTRS, &bar0->rx_traffic_mask); } } temp64 = readq(&bar0->general_int_mask); if (flag == ENABLE_INTRS) temp64 &= ~((u64) intr_mask); else temp64 = DISABLE_ALL_INTRS; writeq(temp64, &bar0->general_int_mask); nic->general_int_mask = readq(&bar0->general_int_mask);}/** * verify_pcc_quiescent- Checks for PCC quiescent state * Return: 1 If PCC is quiescence * 0 If PCC is not quiescence */static int 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 * 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 */static int verify_xena_quiescence(struct s2io_nic *sp){ int mode; struct XENA_dev_config __iomem *bar0 = sp->bar0; u64 val64 = readq(&bar0->adapter_status); mode = s2io_verify_pci_mode(sp); if (!(val64 & ADAPTER_STATUS_TDMA_READY)) { DBG_PRINT(ERR_DBG, "%s", "TDMA is not ready!"); return 0; } if (!(val64 & ADAPTER_STATUS_RDMA_READY)) { DBG_PRINT(ERR_DBG, "%s", "RDMA is not ready!"); return 0; } if (!(val64 & ADAPTER_STATUS_PFC_READY)) { DBG_PRINT(ERR_DBG, "%s", "PFC is not ready!"); return 0; } if (!(val64 & ADAPTER_STATUS_TMAC_BUF_EMPTY)) { DBG_PRINT(ERR_DBG, "%s", "TMAC BUF is not empty!"); return 0; } if (!(val64 & ADAPTER_STATUS_PIC_QUIESCENT)) { DBG_PRINT(ERR_DBG, "%s", "PIC is not QUIESCENT!"); return 0; } if (!(val64 & ADAPTER_STATUS_MC_DRAM_READY)) { DBG_PRINT(ERR_DBG, "%s", "MC_DRAM is not ready!"); return 0; } if (!(val64 & ADAPTER_STATUS_MC_QUEUES_READY)) { DBG_PRINT(ERR_DBG, "%s", "MC_QUEUES is not ready!"); return 0; } if (!(val64 & ADAPTER_STATUS_M_PLL_LOCK)) { DBG_PRINT(ERR_DBG, "%s", "M_PLL is not locked!"); return 0; } /* * In PCI 33 mode, the P_PLL is not used, and therefore, * the 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, "%s", "P_PLL is not locked!"); return 0; } if (!((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) == ADAPTER_STATUS_RC_PRC_QUIESCENT)) { DBG_PRINT(ERR_DBG, "%s", "RC_PRC is not QUIESCENT!"); 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 * */static void fix_mac_address(struct s2io_nic * sp){ struct XENA_dev_config __iomem *bar0 = sp->bar0; u64 val64; int i = 0; while (fix_mac[i] != END_SIGN) { writeq(fix_mac[i++], &bar0->gpio_control); udelay(10); val64 = readq(&bar0->gpio_control); }}/** * 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. */static int start_nic(struct s2io_nic *nic){ struct XENA_dev_config __iomem *bar0 = nic->bar0; struct net_device *dev = nic->dev; register u64 val64 = 0; u16 subid, i; struct mac_info *mac_control; struct config_param *config; mac_control = &nic->mac_control; config = &nic->config; /* PRC Initialization and configuration */ for (i = 0; i < config->rx_ring_num; i++) { writeq((u64) mac_control->rings[i].rx_blocks[0].block_dma_addr, &bar0->prc_rxd0_n[i]); val64 = readq(&bar0->prc_ctrl_n[i]); if (nic->rxd_mode == RXD_MODE_1) val64 |= PRC_CTRL_RC_ENABLED; else val64 |= PRC_CTRL_RC_ENABLED | PRC_CTRL_RING_MODE_3; if (nic->device_type == XFRAME_II_DEVICE) val64 |= PRC_CTRL_GROUP_READS; val64 &= ~PRC_CTRL_RXD_BACKOFF_INTERVAL(0xFFFFFF); val64 |= PRC_CTRL_RXD_BACKOFF_INTERVAL(0x1000); writeq(val64, &bar0->prc_ctrl_n[i]); } if (nic->rxd_mode == RXD_MODE_3B) { /* Enabling 2 buffer mode by writing into Rx_pa_cfg reg. */ val64 = readq(&bar0->rx_pa_cfg); val64 |= RX_PA_CFG_IGNORE_L2_ERR; writeq(val64, &bar0->rx_pa_cfg); } if (vlan_tag_strip == 0) { val64 = readq(&bar0->rx_pa_cfg); val64 &= ~RX_PA_CFG_STRIP_VLAN_TAG; writeq(val64, &bar0->rx_pa_cfg); vlan_strip_flag = 0; } /* * 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); msleep(100); /* Delay by around 100 ms. */ /* Enabling ECC Protection. */ val64 = readq(&bar0->adapter_control); val64 &= ~ADAPTER_ECC_EN; writeq(val64, &bar0->adapter_control); /* * Verify if the device is ready to be enabled, if so enable * it. */ val64 = readq(&bar0->adapter_status); if (!verify_xena_quiescence(nic)) { DBG_PRINT(ERR_DBG, "%s: device is not ready, ", dev->name); DBG_PRINT(ERR_DBG, "Adapter status reads: 0x%llx\n", (unsigned long long) val64); return FAILURE; } /* * With some switches, link might be already up at this point. * Because of this weird behavior, when we enable laser, * we may not get link. We need to handle this. We cannot * figure out which switch is misbehaving. So we are forced to * make a global change. */ /* Enabling Laser. */ val64 = readq(&bar0->adapter_control); val64 |= ADAPTER_EOI_TX_ON; writeq(val64, &bar0->adapter_control); if (s2io_link_fault_indication(nic) == MAC_RMAC_ERR_TIMER) { /* * Dont see link state interrupts initally on some switches, * so directly scheduling the link state task here. */ schedule_work(&nic->set_link_task); } /* SXE-002: Initialize link and activity LED */ subid = nic->pdev->subsystem_device; if (((subid & 0xFF) >= 0x07) && (nic->device_type == XFRAME_I_DEVICE)) { val64 = readq(&bar0->gpio_control); val64 |= 0x0000800000000000ULL; writeq(val64, &bar0->gpio_control); val64 = 0x0411040400000000ULL; writeq(val64, (void __iomem *)bar0 + 0x2700); } return SUCCESS;}/** * s2io_txdl_getskb - Get the skb from txdl, unmap
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -