📄 ixgbe_common.c
字号:
* ixgbe_add_mc_addr - Adds a multicast address. * @hw: pointer to hardware structure * @mc_addr: new multicast address * * Adds it to unused receive address register or to the multicast table. **/static void ixgbe_add_mc_addr(struct ixgbe_hw *hw, u8 *mc_addr){ u32 rar_entries = hw->mac.num_rx_addrs; hw_dbg(hw, " MC Addr =%.2X %.2X %.2X %.2X %.2X %.2X\n", mc_addr[0], mc_addr[1], mc_addr[2], mc_addr[3], mc_addr[4], mc_addr[5]); /* * Place this multicast address in the RAR if there is room, * else put it in the MTA */ if (hw->addr_ctrl.rar_used_count < rar_entries) { ixgbe_set_rar(hw, hw->addr_ctrl.rar_used_count, mc_addr, 0, IXGBE_RAH_AV); hw_dbg(hw, "Added a multicast address to RAR[%d]\n", hw->addr_ctrl.rar_used_count); hw->addr_ctrl.rar_used_count++; hw->addr_ctrl.mc_addr_in_rar_count++; } else { ixgbe_set_mta(hw, mc_addr); } hw_dbg(hw, "ixgbe_add_mc_addr Complete\n");}/** * ixgbe_update_mc_addr_list - Updates MAC list of multicast addresses * @hw: pointer to hardware structure * @mc_addr_list: the list of new multicast addresses * @mc_addr_count: number of addresses * @pad: number of bytes between addresses in the list * * The given list replaces any existing list. Clears the MC addrs from receive * address registers and the multicast table. Uses unsed receive address * registers for the first multicast addresses, and hashes the rest into the * multicast table. **/s32 ixgbe_update_mc_addr_list(struct ixgbe_hw *hw, u8 *mc_addr_list, u32 mc_addr_count, u32 pad){ u32 i; u32 rar_entries = hw->mac.num_rx_addrs; /* * Set the new number of MC addresses that we are being requested to * use. */ hw->addr_ctrl.num_mc_addrs = mc_addr_count; hw->addr_ctrl.rar_used_count -= hw->addr_ctrl.mc_addr_in_rar_count; hw->addr_ctrl.mc_addr_in_rar_count = 0; hw->addr_ctrl.mta_in_use = 0; /* Zero out the other receive addresses. */ hw_dbg(hw, "Clearing RAR[1-15]\n"); for (i = hw->addr_ctrl.rar_used_count; i < rar_entries; i++) { IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0); IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0); } /* Clear the MTA */ hw_dbg(hw, " Clearing MTA\n"); for (i = 0; i < IXGBE_MC_TBL_SIZE; i++) IXGBE_WRITE_REG(hw, IXGBE_MTA(i), 0); /* Add the new addresses */ for (i = 0; i < mc_addr_count; i++) { hw_dbg(hw, " Adding the multicast addresses:\n"); ixgbe_add_mc_addr(hw, mc_addr_list + (i * (IXGBE_ETH_LENGTH_OF_ADDRESS + pad))); } /* Enable mta */ if (hw->addr_ctrl.mta_in_use > 0) IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, IXGBE_MCSTCTRL_MFE | hw->mac.mc_filter_type); hw_dbg(hw, "ixgbe_update_mc_addr_list Complete\n"); return 0;}/** * ixgbe_clear_vfta - Clear VLAN filter table * @hw: pointer to hardware structure * * Clears the VLAN filer table, and the VMDq index associated with the filter **/static s32 ixgbe_clear_vfta(struct ixgbe_hw *hw){ u32 offset; u32 vlanbyte; for (offset = 0; offset < IXGBE_VLAN_FILTER_TBL_SIZE; offset++) IXGBE_WRITE_REG(hw, IXGBE_VFTA(offset), 0); for (vlanbyte = 0; vlanbyte < 4; vlanbyte++) for (offset = 0; offset < IXGBE_VLAN_FILTER_TBL_SIZE; offset++) IXGBE_WRITE_REG(hw, IXGBE_VFTAVIND(vlanbyte, offset), 0); return 0;}/** * ixgbe_set_vfta - Set VLAN filter table * @hw: pointer to hardware structure * @vlan: VLAN id to write to VLAN filter * @vind: VMDq output index that maps queue to VLAN id in VFTA * @vlan_on: boolean flag to turn on/off VLAN in VFTA * * Turn on/off specified VLAN in the VLAN filter table. **/s32 ixgbe_set_vfta(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on){ u32 VftaIndex; u32 BitOffset; u32 VftaReg; u32 VftaByte; /* Determine 32-bit word position in array */ VftaIndex = (vlan >> 5) & 0x7F; /* upper seven bits */ /* Determine the location of the (VMD) queue index */ VftaByte = ((vlan >> 3) & 0x03); /* bits (4:3) indicating byte array */ BitOffset = (vlan & 0x7) << 2; /* lower 3 bits indicate nibble */ /* Set the nibble for VMD queue index */ VftaReg = IXGBE_READ_REG(hw, IXGBE_VFTAVIND(VftaByte, VftaIndex)); VftaReg &= (~(0x0F << BitOffset)); VftaReg |= (vind << BitOffset); IXGBE_WRITE_REG(hw, IXGBE_VFTAVIND(VftaByte, VftaIndex), VftaReg); /* Determine the location of the bit for this VLAN id */ BitOffset = vlan & 0x1F; /* lower five bits */ VftaReg = IXGBE_READ_REG(hw, IXGBE_VFTA(VftaIndex)); if (vlan_on) /* Turn on this VLAN id */ VftaReg |= (1 << BitOffset); else /* Turn off this VLAN id */ VftaReg &= ~(1 << BitOffset); IXGBE_WRITE_REG(hw, IXGBE_VFTA(VftaIndex), VftaReg); return 0;}/** * ixgbe_setup_fc - Configure flow control settings * @hw: pointer to hardware structure * @packetbuf_num: packet buffer number (0-7) * * Configures the flow control settings based on SW configuration. * This function is used for 802.3x flow control configuration only. **/s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num){ u32 frctl_reg; u32 rmcs_reg; if (packetbuf_num < 0 || packetbuf_num > 7) hw_dbg(hw, "Invalid packet buffer number [%d], expected range" "is 0-7\n", packetbuf_num); frctl_reg = IXGBE_READ_REG(hw, IXGBE_FCTRL); frctl_reg &= ~(IXGBE_FCTRL_RFCE | IXGBE_FCTRL_RPFCE); rmcs_reg = IXGBE_READ_REG(hw, IXGBE_RMCS); rmcs_reg &= ~(IXGBE_RMCS_TFCE_PRIORITY | IXGBE_RMCS_TFCE_802_3X); /* * We want to save off the original Flow Control configuration just in * case we get disconnected and then reconnected into a different hub * or switch with different Flow Control capabilities. */ hw->fc.type = hw->fc.original_type; /* * The possible values of the "flow_control" parameter are: * 0: Flow control is completely disabled * 1: Rx flow control is enabled (we can receive pause frames but not * send pause frames). * 2: Tx flow control is enabled (we can send pause frames but we do not * support receiving pause frames) * 3: Both Rx and TX flow control (symmetric) are enabled. * other: Invalid. */ switch (hw->fc.type) { case ixgbe_fc_none: break; case ixgbe_fc_rx_pause: /* * RX Flow control is enabled, * and TX Flow control is disabled. */ frctl_reg |= IXGBE_FCTRL_RFCE; break; case ixgbe_fc_tx_pause: /* * TX Flow control is enabled, and RX Flow control is disabled, * by a software over-ride. */ rmcs_reg |= IXGBE_RMCS_TFCE_802_3X; break; case ixgbe_fc_full: /* * Flow control (both RX and TX) is enabled by a software * over-ride. */ frctl_reg |= IXGBE_FCTRL_RFCE; rmcs_reg |= IXGBE_RMCS_TFCE_802_3X; break; default: /* We should never get here. The value should be 0-3. */ hw_dbg(hw, "Flow control param set incorrectly\n"); break; } /* Enable 802.3x based flow control settings. */ IXGBE_WRITE_REG(hw, IXGBE_FCTRL, frctl_reg); IXGBE_WRITE_REG(hw, IXGBE_RMCS, rmcs_reg); /* * We need to set up the Receive Threshold high and low water * marks as well as (optionally) enabling the transmission of * XON frames. */ if (hw->fc.type & ixgbe_fc_tx_pause) { if (hw->fc.send_xon) { IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num), (hw->fc.low_water | IXGBE_FCRTL_XONE)); } else { IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num), hw->fc.low_water); } IXGBE_WRITE_REG(hw, IXGBE_FCRTH(packetbuf_num), (hw->fc.high_water)|IXGBE_FCRTH_FCEN); } IXGBE_WRITE_REG(hw, IXGBE_FCTTV(0), hw->fc.pause_time); IXGBE_WRITE_REG(hw, IXGBE_FCRTV, (hw->fc.pause_time >> 1)); return 0;}/** * ixgbe_disable_pcie_master - Disable PCI-express master access * @hw: pointer to hardware structure * * Disables PCI-Express master access and verifies there are no pending * requests. IXGBE_ERR_MASTER_REQUESTS_PENDING is returned if master disable * bit hasn't caused the master requests to be disabled, else 0 * is returned signifying master requests disabled. **/s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw){ u32 ctrl; s32 i; s32 status = IXGBE_ERR_MASTER_REQUESTS_PENDING; ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); ctrl |= IXGBE_CTRL_GIO_DIS; IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl); for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) { if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO)) { status = 0; break; } udelay(100); } return status;}/** * ixgbe_acquire_swfw_sync - Aquire SWFW semaphore * @hw: pointer to hardware structure * @mask: Mask to specify wich semaphore to acquire * * Aquires the SWFW semaphore throught the GSSR register for the specified * function (CSR, PHY0, PHY1, EEPROM, Flash) **/s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask){ u32 gssr; u32 swmask = mask; u32 fwmask = mask << 5; s32 timeout = 200; while (timeout) { if (ixgbe_get_eeprom_semaphore(hw)) return -IXGBE_ERR_SWFW_SYNC; gssr = IXGBE_READ_REG(hw, IXGBE_GSSR); if (!(gssr & (fwmask | swmask))) break; /* * Firmware currently using resource (fwmask) or other software * thread currently using resource (swmask) */ ixgbe_release_eeprom_semaphore(hw); msleep(5); timeout--; } if (!timeout) { hw_dbg(hw, "Driver can't access resource, GSSR timeout.\n"); return -IXGBE_ERR_SWFW_SYNC; } gssr |= swmask; IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr); ixgbe_release_eeprom_semaphore(hw); return 0;}/** * ixgbe_release_swfw_sync - Release SWFW semaphore * @hw: pointer to hardware structure * @mask: Mask to specify wich semaphore to release * * Releases the SWFW semaphore throught the GSSR register for the specified * function (CSR, PHY0, PHY1, EEPROM, Flash) **/void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask){ u32 gssr; u32 swmask = mask; ixgbe_get_eeprom_semaphore(hw); gssr = IXGBE_READ_REG(hw, IXGBE_GSSR); gssr &= ~swmask; IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr); ixgbe_release_eeprom_semaphore(hw);}/** * ixgbe_read_analog_reg8- Reads 8 bit 82598 Atlas analog register * @hw: pointer to hardware structure * @reg: analog register to read * @val: read value * * Performs write operation to analog register specified. **/s32 ixgbe_read_analog_reg8(struct ixgbe_hw *hw, u32 reg, u8 *val){ u32 atlas_ctl; IXGBE_WRITE_REG(hw, IXGBE_ATLASCTL, IXGBE_ATLASCTL_WRITE_CMD | (reg << 8)); IXGBE_WRITE_FLUSH(hw); udelay(10); atlas_ctl = IXGBE_READ_REG(hw, IXGBE_ATLASCTL); *val = (u8)atlas_ctl; return 0;}/** * ixgbe_write_analog_reg8- Writes 8 bit Atlas analog register * @hw: pointer to hardware structure * @reg: atlas register to write * @val: value to write * * Performs write operation to Atlas analog register specified. **/s32 ixgbe_write_analog_reg8(struct ixgbe_hw *hw, u32 reg, u8 val){ u32 atlas_ctl; atlas_ctl = (reg << 8) | val; IXGBE_WRITE_REG(hw, IXGBE_ATLASCTL, atlas_ctl); IXGBE_WRITE_FLUSH(hw); udelay(10); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -