📄 e1000_mac.c
字号:
/* Get the SW semaphore */ while (i < timeout) { swsm = er32(SWSM); if (!(swsm & E1000_SWSM_SMBI)) break; udelay(50); i++; } if (i == timeout) { e_dbg("Driver can't access device - SMBI bit is set.\n"); ret_val = -E1000_ERR_NVM; goto out; } /* Get the FW semaphore. */ for (i = 0; i < timeout; i++) { swsm = er32(SWSM); ew32(SWSM, swsm | E1000_SWSM_SWESMBI); /* Semaphore acquired if bit latched */ if (er32(SWSM) & E1000_SWSM_SWESMBI) break; udelay(50); } if (i == timeout) { /* Release semaphores */ e1000e_put_hw_semaphore(hw); e_dbg("Driver can't access the NVM\n"); ret_val = -E1000_ERR_NVM; goto out; }out: return ret_val;}/** * e1000e_put_hw_semaphore - Release hardware semaphore * @hw: pointer to the HW structure * * Release hardware semaphore used to access the PHY or NVM **/void e1000e_put_hw_semaphore(struct e1000_hw *hw){ u32 swsm; swsm = er32(SWSM); swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI); ew32(SWSM, swsm);}/** * e1000e_get_auto_rd_done - Check for auto read completion * @hw: pointer to the HW structure * * Check EEPROM for Auto Read done bit. **/s32 e1000e_get_auto_rd_done(struct e1000_hw *hw){ s32 i = 0; s32 ret_val = E1000_SUCCESS; while (i < AUTO_READ_DONE_TIMEOUT) { if (er32(EECD) & E1000_EECD_AUTO_RD) break; msleep(1); i++; } if (i == AUTO_READ_DONE_TIMEOUT) { e_dbg("Auto read by HW from NVM has not completed.\n"); ret_val = -E1000_ERR_RESET; goto out; }out: return ret_val;}/** * e1000e_valid_led_default - Verify a valid default LED config * @hw: pointer to the HW structure * @data: pointer to the NVM (EEPROM) * * Read the EEPROM for the current default LED configuration. If the * LED configuration is not valid, set to a valid LED configuration. **/s32 e1000e_valid_led_default(struct e1000_hw *hw, u16 *data){ s32 ret_val; ret_val = e1000_read_nvm(hw, NVM_ID_LED_SETTINGS, 1, data); if (ret_val) { e_dbg("NVM Read Error\n"); goto out; } if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) *data = ID_LED_DEFAULT;out: return ret_val;}/** * e1000e_id_led_init - * @hw: pointer to the HW structure * **/s32 e1000e_id_led_init(struct e1000_hw *hw){ struct e1000_mac_info *mac = &hw->mac; s32 ret_val; const u32 ledctl_mask = 0x000000FF; const u32 ledctl_on = E1000_LEDCTL_MODE_LED_ON; const u32 ledctl_off = E1000_LEDCTL_MODE_LED_OFF; u16 data, i, temp; const u16 led_mask = 0x0F; ret_val = hw->nvm.ops.valid_led_default(hw, &data); if (ret_val) goto out; mac->ledctl_default = er32(LEDCTL); mac->ledctl_mode1 = mac->ledctl_default; mac->ledctl_mode2 = mac->ledctl_default; for (i = 0; i < 4; i++) { temp = (data >> (i << 2)) & led_mask; switch (temp) { case ID_LED_ON1_DEF2: case ID_LED_ON1_ON2: case ID_LED_ON1_OFF2: mac->ledctl_mode1 &= ~(ledctl_mask << (i << 3)); mac->ledctl_mode1 |= ledctl_on << (i << 3); break; case ID_LED_OFF1_DEF2: case ID_LED_OFF1_ON2: case ID_LED_OFF1_OFF2: mac->ledctl_mode1 &= ~(ledctl_mask << (i << 3)); mac->ledctl_mode1 |= ledctl_off << (i << 3); break; default: /* Do nothing */ break; } switch (temp) { case ID_LED_DEF1_ON2: case ID_LED_ON1_ON2: case ID_LED_OFF1_ON2: mac->ledctl_mode2 &= ~(ledctl_mask << (i << 3)); mac->ledctl_mode2 |= ledctl_on << (i << 3); break; case ID_LED_DEF1_OFF2: case ID_LED_ON1_OFF2: case ID_LED_OFF1_OFF2: mac->ledctl_mode2 &= ~(ledctl_mask << (i << 3)); mac->ledctl_mode2 |= ledctl_off << (i << 3); break; default: /* Do nothing */ break; } }out: return ret_val;}/** * e1000_setup_led_generic - Configures SW controllable LED * @hw: pointer to the HW structure * * This prepares the SW controllable LED for use and saves the current state * of the LED so it can be later restored. **/s32 e1000_setup_led_generic(struct e1000_hw *hw){ u32 ledctl; s32 ret_val = E1000_SUCCESS; if (hw->mac.ops.setup_led != e1000_setup_led_generic) { ret_val = -E1000_ERR_CONFIG; goto out; } if (hw->phy.media_type == e1000_media_type_fiber) { ledctl = er32(LEDCTL); hw->mac.ledctl_default = ledctl; /* Turn off LED0 */ ledctl &= ~(E1000_LEDCTL_LED0_IVRT | E1000_LEDCTL_LED0_BLINK | E1000_LEDCTL_LED0_MODE_MASK); ledctl |= (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED0_MODE_SHIFT); ew32(LEDCTL, ledctl); } else if (hw->phy.media_type == e1000_media_type_copper) { ew32(LEDCTL, hw->mac.ledctl_mode1); }out: return ret_val;}/** * e1000e_cleanup_led_generic - Set LED config to default operation * @hw: pointer to the HW structure * * Remove the current LED configuration and set the LED configuration * to the default value, saved from the EEPROM. **/s32 e1000e_cleanup_led_generic(struct e1000_hw *hw){ s32 ret_val = E1000_SUCCESS; if (hw->mac.ops.cleanup_led != e1000e_cleanup_led_generic) { ret_val = -E1000_ERR_CONFIG; goto out; } ew32(LEDCTL, hw->mac.ledctl_default);out: return ret_val;}/** * e1000e_blink_led - Blink LED * @hw: pointer to the HW structure * * Blink the LEDs which are set to be on. **/s32 e1000e_blink_led(struct e1000_hw *hw){ u32 ledctl_blink = 0; u32 i; if (hw->phy.media_type == e1000_media_type_fiber) { /* always blink LED0 for PCI-E fiber */ ledctl_blink = E1000_LEDCTL_LED0_BLINK | (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED0_MODE_SHIFT); } else { /* * set the blink bit for each LED that's "on" (0x0E) * in ledctl_mode2 */ ledctl_blink = hw->mac.ledctl_mode2; for (i = 0; i < 4; i++) if (((hw->mac.ledctl_mode2 >> (i * 8)) & 0xFF) == E1000_LEDCTL_MODE_LED_ON) ledctl_blink |= (E1000_LEDCTL_LED0_BLINK << (i * 8)); } ew32(LEDCTL, ledctl_blink); return E1000_SUCCESS;}/** * e1000e_led_on_generic - Turn LED on * @hw: pointer to the HW structure * * Turn LED on. **/s32 e1000e_led_on_generic(struct e1000_hw *hw){ u32 ctrl; switch (hw->phy.media_type) { case e1000_media_type_fiber: ctrl = er32(CTRL); ctrl &= ~E1000_CTRL_SWDPIN0; ctrl |= E1000_CTRL_SWDPIO0; ew32(CTRL, ctrl); break; case e1000_media_type_copper: ew32(LEDCTL, hw->mac.ledctl_mode2); break; default: break; } return E1000_SUCCESS;}/** * e1000e_led_off_generic - Turn LED off * @hw: pointer to the HW structure * * Turn LED off. **/s32 e1000e_led_off_generic(struct e1000_hw *hw){ u32 ctrl; switch (hw->phy.media_type) { case e1000_media_type_fiber: ctrl = er32(CTRL); ctrl |= E1000_CTRL_SWDPIN0; ctrl |= E1000_CTRL_SWDPIO0; ew32(CTRL, ctrl); break; case e1000_media_type_copper: ew32(LEDCTL, hw->mac.ledctl_mode1); break; default: break; } return E1000_SUCCESS;}/** * e1000e_set_pcie_no_snoop - Set PCI-express capabilities * @hw: pointer to the HW structure * @no_snoop: bitmap of snoop events * * Set the PCI-express register to snoop for events enabled in 'no_snoop'. **/void e1000e_set_pcie_no_snoop(struct e1000_hw *hw, u32 no_snoop){ u32 gcr; if (hw->bus.type != e1000_bus_type_pci_express) goto out; if (no_snoop) { gcr = er32(GCR); gcr &= ~(PCIE_NO_SNOOP_ALL); gcr |= no_snoop; ew32(GCR, gcr); }out: return;}/** * e1000e_disable_pcie_master - Disables PCI-express master access * @hw: pointer to the HW structure * * Returns 0 (E1000_SUCCESS) if successful, else returns -10 * (-E1000_ERR_MASTER_REQUESTS_PENDING) if master disable bit has not caused * the master requests to be disabled. * * Disables PCI-Express master access and verifies there are no pending * requests. **/s32 e1000e_disable_pcie_master(struct e1000_hw *hw){ u32 ctrl; s32 timeout = MASTER_DISABLE_TIMEOUT; s32 ret_val = E1000_SUCCESS; if (hw->bus.type != e1000_bus_type_pci_express) goto out; ctrl = er32(CTRL); ctrl |= E1000_CTRL_GIO_MASTER_DISABLE; ew32(CTRL, ctrl); while (timeout) { if (!(er32(STATUS) & E1000_STATUS_GIO_MASTER_ENABLE)) break; udelay(100); timeout--; } if (!timeout) { e_dbg("Master requests are pending.\n"); ret_val = -E1000_ERR_MASTER_REQUESTS_PENDING; goto out; }out: return ret_val;}/** * e1000e_reset_adaptive - Reset Adaptive Interframe Spacing * @hw: pointer to the HW structure * * Reset the Adaptive Interframe Spacing throttle to default values. **/void e1000e_reset_adaptive(struct e1000_hw *hw){ struct e1000_mac_info *mac = &hw->mac; if (!mac->adaptive_ifs) { e_dbg("Not in Adaptive IFS mode!\n"); goto out; } mac->current_ifs_val = 0; mac->ifs_min_val = IFS_MIN; mac->ifs_max_val = IFS_MAX; mac->ifs_step_size = IFS_STEP; mac->ifs_ratio = IFS_RATIO; mac->in_ifs_mode = false; ew32(AIT, 0);out: return;}/** * e1000e_update_adaptive - Update Adaptive Interframe Spacing * @hw: pointer to the HW structure * * Update the Adaptive Interframe Spacing Throttle value based on the * time between transmitted packets and time between collisions. **/void e1000e_update_adaptive(struct e1000_hw *hw){ struct e1000_mac_info *mac = &hw->mac; if (!mac->adaptive_ifs) { e_dbg("Not in Adaptive IFS mode!\n"); goto out; } if ((mac->collision_delta * mac->ifs_ratio) > mac->tx_packet_delta) { if (mac->tx_packet_delta > MIN_NUM_XMITS) { mac->in_ifs_mode = true; if (mac->current_ifs_val < mac->ifs_max_val) { if (!mac->current_ifs_val) mac->current_ifs_val = mac->ifs_min_val; else mac->current_ifs_val += mac->ifs_step_size; ew32(AIT, mac->current_ifs_val); } } } else { if (mac->in_ifs_mode && (mac->tx_packet_delta <= MIN_NUM_XMITS)) { mac->current_ifs_val = 0; mac->in_ifs_mode = false; ew32(AIT, 0); } }out: return;}/** * e1000_validate_mdi_setting_generic - Verify MDI/MDIx settings * @hw: pointer to the HW structure * * Verify that when not using auto-negotiation that MDI/MDIx is correctly * set, which is forced to MDI mode only. **/s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw){ s32 ret_val = E1000_SUCCESS; if (!hw->mac.autoneg && (hw->phy.mdix == 0 || hw->phy.mdix == 3)) { e_dbg("Invalid MDI setting detected\n"); hw->phy.mdix = 1; ret_val = -E1000_ERR_CONFIG; goto out; }out: return ret_val;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -