drivers/net/ethernet/intel/igc/igc_mac.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/intel/igc/igc_mac.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/intel/igc/igc_mac.c
Extension
.c
Size
24762 bytes
Lines
872
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (hw->fc.requested_mode == igc_fc_full) {
			hw->fc.current_mode = igc_fc_full;
			hw_dbg("Flow Control = FULL.\n");
		} else {
			hw->fc.current_mode = igc_fc_rx_pause;
			hw_dbg("Flow Control = RX PAUSE frames only.\n");
		}
	}

	/* For receiving PAUSE frames ONLY.
	 *
	 *   LOCAL DEVICE  |   LINK PARTNER
	 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
	 *-------|---------|-------|---------|--------------------
	 *   0   |    1    |   1   |    1    | igc_fc_tx_pause
	 */
	else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) &&
		 (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
		 (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
		 (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
		hw->fc.current_mode = igc_fc_tx_pause;
		hw_dbg("Flow Control = TX PAUSE frames only.\n");
	}
	/* For transmitting PAUSE frames ONLY.
	 *
	 *   LOCAL DEVICE  |   LINK PARTNER
	 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
	 *-------|---------|-------|---------|--------------------
	 *   1   |    1    |   0   |    1    | igc_fc_rx_pause
	 */
	else if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
		 (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
		 !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
		 (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
		hw->fc.current_mode = igc_fc_rx_pause;
		hw_dbg("Flow Control = RX PAUSE frames only.\n");
	}
	/* Per the IEEE spec, at this point flow control should be
	 * disabled.  However, we want to consider that we could
	 * be connected to a legacy switch that doesn't advertise
	 * desired flow control, but can be forced on the link
	 * partner.  So if we advertised no flow control, that is
	 * what we will resolve to.  If we advertised some kind of
	 * receive capability (Rx Pause Only or Full Flow Control)
	 * and the link partner advertised none, we will configure
	 * ourselves to enable Rx Flow Control only.  We can do
	 * this safely for two reasons:  If the link partner really
	 * didn't want flow control enabled, and we enable Rx, no
	 * harm done since we won't be receiving any PAUSE frames
	 * anyway.  If the intent on the link partner was to have
	 * flow control enabled, then by us enabling RX only, we
	 * can at least receive pause frames and process them.
	 * This is a good idea because in most cases, since we are
	 * predominantly a server NIC, more times than not we will
	 * be asked to delay transmission of packets than asking
	 * our link partner to pause transmission of frames.
	 */
	else if ((hw->fc.requested_mode == igc_fc_none) ||
		 (hw->fc.requested_mode == igc_fc_tx_pause) ||
		 (hw->fc.strict_ieee)) {
		hw->fc.current_mode = igc_fc_none;
		hw_dbg("Flow Control = NONE.\n");
	} else {
		hw->fc.current_mode = igc_fc_rx_pause;
		hw_dbg("Flow Control = RX PAUSE frames only.\n");
	}

	/* Now we need to do one last check...  If we auto-
	 * negotiated to HALF DUPLEX, flow control should not be
	 * enabled per IEEE 802.3 spec.
	 */
	ret_val = hw->mac.ops.get_speed_and_duplex(hw, &speed, &duplex);
	if (ret_val) {
		hw_dbg("Error getting link speed and duplex\n");
		goto out;
	}

	if (duplex == HALF_DUPLEX)
		hw->fc.current_mode = igc_fc_none;

	/* Now we call a subroutine to actually force the MAC
	 * controller to use the correct flow control settings.
	 */
	ret_val = igc_force_mac_fc(hw);
	if (ret_val) {
		hw_dbg("Error forcing flow control settings\n");
		goto out;
	}

out:

Annotation

Implementation Notes