Commit 258f5f90 authored by Karol Kolacinski's avatar Karol Kolacinski Committed by Tony Nguyen
Browse files

ice: Add correct PHY lane assignment



Driver always naively assumes, that for PTP purposes, PHY lane to
configure is corresponding to PF ID.

This is not true for some port configurations, e.g.:
- 2x50G per quad, where lanes used are 0 and 2 on each quad, but PF IDs
  are 0 and 1
- 100G per quad on 2 quads, where lanes used are 0 and 4, but PF IDs are
  0 and 1

Use correct PHY lane assignment by getting and parsing port options.
This is read from the NVM by the FW and provided to the driver with
the indication of active port split.

Remove ice_is_muxed_topo(), which is no longer needed.

Fixes: 4409ea17 ("ice: Adjust PTP init for 2x50G E825C devices")
Reviewed-by: default avatarPrzemek Kitszel <przemyslaw.kitszel@intel.com>
Reviewed-by: default avatarArkadiusz Kubalewski <Arkadiusz.kubalewski@intel.com>
Signed-off-by: default avatarKarol Kolacinski <karol.kolacinski@intel.com>
Signed-off-by: default avatarGrzegorz Nitka <grzegorz.nitka@intel.com>
Tested-by: Pucha Himasekhar Reddy <himasekharx.reddy.pucha@intel.com> (A Contingent worker at Intel)
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent 2e60560f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1665,6 +1665,7 @@ struct ice_aqc_get_port_options_elem {
#define ICE_AQC_PORT_OPT_MAX_LANE_25G	5
#define ICE_AQC_PORT_OPT_MAX_LANE_50G	6
#define ICE_AQC_PORT_OPT_MAX_LANE_100G	7
#define ICE_AQC_PORT_OPT_MAX_LANE_200G	8

	u8 global_scid[2];
	u8 phy_scid[2];
+51 −0
Original line number Diff line number Diff line
@@ -4095,6 +4095,57 @@ ice_aq_set_port_option(struct ice_hw *hw, u8 lport, u8 lport_valid,
	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
}

/**
 * ice_get_phy_lane_number - Get PHY lane number for current adapter
 * @hw: pointer to the hw struct
 *
 * Return: PHY lane number on success, negative error code otherwise.
 */
int ice_get_phy_lane_number(struct ice_hw *hw)
{
	struct ice_aqc_get_port_options_elem *options;
	unsigned int lport = 0;
	unsigned int lane;
	int err;

	options = kcalloc(ICE_AQC_PORT_OPT_MAX, sizeof(*options), GFP_KERNEL);
	if (!options)
		return -ENOMEM;

	for (lane = 0; lane < ICE_MAX_PORT_PER_PCI_DEV; lane++) {
		u8 options_count = ICE_AQC_PORT_OPT_MAX;
		u8 speed, active_idx, pending_idx;
		bool active_valid, pending_valid;

		err = ice_aq_get_port_options(hw, options, &options_count, lane,
					      true, &active_idx, &active_valid,
					      &pending_idx, &pending_valid);
		if (err)
			goto err;

		if (!active_valid)
			continue;

		speed = options[active_idx].max_lane_speed;
		/* If we don't get speed for this lane, it's unoccupied */
		if (speed > ICE_AQC_PORT_OPT_MAX_LANE_200G)
			continue;

		if (hw->pf_id == lport) {
			kfree(options);
			return lane;
		}

		lport++;
	}

	/* PHY lane not found */
	err = -ENXIO;
err:
	kfree(options);
	return err;
}

/**
 * ice_aq_sff_eeprom
 * @hw: pointer to the HW struct
+1 −0
Original line number Diff line number Diff line
@@ -193,6 +193,7 @@ ice_aq_get_port_options(struct ice_hw *hw,
int
ice_aq_set_port_option(struct ice_hw *hw, u8 lport, u8 lport_valid,
		       u8 new_option);
int ice_get_phy_lane_number(struct ice_hw *hw);
int
ice_aq_sff_eeprom(struct ice_hw *hw, u16 lport, u8 bus_addr,
		  u16 mem_addr, u8 page, u8 set_page, u8 *data, u8 length,
+3 −3
Original line number Diff line number Diff line
@@ -1144,7 +1144,7 @@ ice_link_event(struct ice_pf *pf, struct ice_port_info *pi, bool link_up,
	if (link_up == old_link && link_speed == old_link_speed)
		return 0;

	ice_ptp_link_change(pf, pf->hw.pf_id, link_up);
	ice_ptp_link_change(pf, link_up);

	if (ice_is_dcb_active(pf)) {
		if (test_bit(ICE_FLAG_DCB_ENA, pf->flags))
@@ -6790,7 +6790,7 @@ static int ice_up_complete(struct ice_vsi *vsi)
		ice_print_link_msg(vsi, true);
		netif_tx_start_all_queues(vsi->netdev);
		netif_carrier_on(vsi->netdev);
		ice_ptp_link_change(pf, pf->hw.pf_id, true);
		ice_ptp_link_change(pf, true);
	}

	/* Perform an initial read of the statistics registers now to
@@ -7260,7 +7260,7 @@ int ice_down(struct ice_vsi *vsi)

	if (vsi->netdev) {
		vlan_err = ice_vsi_del_vlan_zero(vsi);
		ice_ptp_link_change(vsi->back, vsi->back->hw.pf_id, false);
		ice_ptp_link_change(vsi->back, false);
		netif_carrier_off(vsi->netdev);
		netif_tx_disable(vsi->netdev);
	}
+9 −14
Original line number Diff line number Diff line
@@ -1388,10 +1388,9 @@ ice_ptp_port_phy_restart(struct ice_ptp_port *ptp_port)
/**
 * ice_ptp_link_change - Reconfigure PTP after link status change
 * @pf: Board private structure
 * @port: Port for which the PHY start is set
 * @linkup: Link is up or down
 */
void ice_ptp_link_change(struct ice_pf *pf, u8 port, bool linkup)
void ice_ptp_link_change(struct ice_pf *pf, bool linkup)
{
	struct ice_ptp_port *ptp_port;
	struct ice_hw *hw = &pf->hw;
@@ -1399,14 +1398,7 @@ void ice_ptp_link_change(struct ice_pf *pf, u8 port, bool linkup)
	if (pf->ptp.state != ICE_PTP_READY)
		return;

	if (WARN_ON_ONCE(port >= hw->ptp.num_lports))
		return;

	ptp_port = &pf->ptp.port;
	if (ice_is_e825c(hw) && hw->ptp.is_2x50g_muxed_topo)
		port *= 2;
	if (WARN_ON_ONCE(ptp_port->port_num != port))
		return;

	/* Update cached link status for this port immediately */
	ptp_port->link_up = linkup;
@@ -3164,10 +3156,17 @@ void ice_ptp_init(struct ice_pf *pf)
{
	struct ice_ptp *ptp = &pf->ptp;
	struct ice_hw *hw = &pf->hw;
	int err;
	int lane_num, err;

	ptp->state = ICE_PTP_INITIALIZING;

	lane_num = ice_get_phy_lane_number(hw);
	if (lane_num < 0) {
		err = lane_num;
		goto err_exit;
	}

	ptp->port.port_num = (u8)lane_num;
	ice_ptp_init_hw(hw);

	ice_ptp_init_tx_interrupt_mode(pf);
@@ -3188,10 +3187,6 @@ void ice_ptp_init(struct ice_pf *pf)
	if (err)
		goto err_exit;

	ptp->port.port_num = hw->pf_id;
	if (ice_is_e825c(hw) && hw->ptp.is_2x50g_muxed_topo)
		ptp->port.port_num = hw->pf_id * 2;

	err = ice_ptp_init_port(pf, &ptp->port);
	if (err)
		goto err_exit;
Loading