staticconstchar ice_gstrings_test[][ETH_GSTRING_LEN] = { "Register test (offline)", "EEPROM test (offline)", "Interrupt test (offline)", "Loopback test (offline)", "Link test (on/offline)",
};
/* Display NVM version (from which the firmware version can be * determined) which contains more pertinent information.
*/
snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), "%x.%02x 0x%x %d.%d.%d", nvm->major, nvm->minor,
nvm->eetrack, orom->major, orom->build, orom->patch);
/** * ice_ethtool_get_maxspeed - Get the max speed for given lport * @hw: pointer to the HW struct * @lport: logical port for which max speed is requested * @max_speed: return max speed for input lport * * Return: 0 on success, negative on failure.
*/ staticint ice_ethtool_get_maxspeed(struct ice_hw *hw, u8 lport, u8 *max_speed)
{ struct ice_aqc_get_port_options_elem options[ICE_AQC_PORT_OPT_MAX] = {}; bool active_valid = false, pending_valid = true;
u8 option_count = ICE_AQC_PORT_OPT_MAX;
u8 active_idx = 0, pending_idx = 0; int status;
status = ice_aq_get_port_options(hw, options, &option_count, lport, true, &active_idx, &active_valid,
&pending_idx, &pending_valid); if (status) return -EIO; if (!active_valid) return -EINVAL;
/** * ice_is_serdes_muxed - returns whether serdes is muxed in hardware * @hw: pointer to the HW struct * * Return: true when serdes is muxed, false when serdes is not muxed.
*/ staticbool ice_is_serdes_muxed(struct ice_hw *hw)
{
u32 reg_value = rd32(hw, GLGEN_SWITCH_MODE_CONFIG);
/** * ice_active_vfs - check if there are any active VFs * @pf: board private structure * * Returns true if an active VF is found, otherwise returns false
*/ staticbool ice_active_vfs(struct ice_pf *pf)
{ bool active = false; struct ice_vf *vf; unsignedint bkt;
rcu_read_lock();
ice_for_each_vf_rcu(pf, bkt, vf) { if (test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
active = true; break;
}
}
rcu_read_unlock();
return active;
}
/** * ice_link_test - perform a link test on a given net_device * @netdev: network interface device structure * * This function performs one of the self-tests required by ethtool. * Returns 0 on success, non-zero on failure.
*/ static u64 ice_link_test(struct net_device *netdev)
{ struct ice_netdev_priv *np = netdev_priv(netdev); bool link_up = false; int status;
netdev_info(netdev, "link test\n");
status = ice_get_link_status(np->vsi->port_info, &link_up); if (status) {
netdev_err(netdev, "link query error, status = %d\n",
status); return 1;
}
if (!link_up) return 2;
return 0;
}
/** * ice_eeprom_test - perform an EEPROM test on a given net_device * @netdev: network interface device structure * * This function performs one of the self-tests required by ethtool. * Returns 0 on success, non-zero on failure.
*/ static u64 ice_eeprom_test(struct net_device *netdev)
{ struct ice_netdev_priv *np = netdev_priv(netdev); struct ice_pf *pf = np->vsi->back;
/* bail on failure (non-zero return) */ if (ice_reg_pattern_test(hw, reg, mask)) return 1;
}
}
return 0;
}
/** * ice_lbtest_prepare_rings - configure Tx/Rx test rings * @vsi: pointer to the VSI structure * * Function configures rings of a VSI for loopback test without * enabling interrupts or informing the kernel about new queues. * * Returns 0 on success, negative on failure.
*/ staticint ice_lbtest_prepare_rings(struct ice_vsi *vsi)
{ int status;
status = ice_vsi_setup_tx_rings(vsi); if (status) goto err_setup_tx_ring;
status = ice_vsi_setup_rx_rings(vsi); if (status) goto err_setup_rx_ring;
status = ice_vsi_cfg_lan(vsi); if (status) goto err_setup_rx_ring;
status = ice_vsi_start_all_rx_rings(vsi); if (status) goto err_start_rx_ring;
/** * ice_lbtest_disable_rings - disable Tx/Rx test rings after loopback test * @vsi: pointer to the VSI structure * * Function stops and frees VSI rings after a loopback test. * Returns 0 on success, negative on failure.
*/ staticint ice_lbtest_disable_rings(struct ice_vsi *vsi)
{ int status;
status = ice_vsi_stop_lan_tx_rings(vsi, ICE_NO_RESET, 0); if (status)
netdev_err(vsi->netdev, "Failed to stop Tx rings, VSI %d error %d\n",
vsi->vsi_num, status);
status = ice_vsi_stop_all_rx_rings(vsi); if (status)
netdev_err(vsi->netdev, "Failed to stop Rx rings, VSI %d error %d\n",
vsi->vsi_num, status);
/** * ice_lbtest_create_frame - create test packet * @pf: pointer to the PF structure * @ret_data: allocated frame buffer * @size: size of the packet data * * Function allocates a frame with a test pattern on specific offsets. * Returns 0 on success, non-zero on failure.
*/ staticint ice_lbtest_create_frame(struct ice_pf *pf, u8 **ret_data, u16 size)
{
u8 *data;
if (!pf) return -EINVAL;
data = kzalloc(size, GFP_KERNEL); if (!data) return -ENOMEM;
/* Since the ethernet test frame should always be at least * 64 bytes long, fill some octets in the payload with test data.
*/
memset(data, 0xFF, size);
data[32] = 0xDE;
data[42] = 0xAD;
data[44] = 0xBE;
data[46] = 0xEF;
*ret_data = data;
return 0;
}
/** * ice_lbtest_check_frame - verify received loopback frame * @frame: pointer to the raw packet data * * Function verifies received test frame with a pattern. * Returns true if frame matches the pattern, false otherwise.
*/ staticbool ice_lbtest_check_frame(u8 *frame)
{ /* Validate bytes of a frame under offsets chosen earlier */ if (frame[32] == 0xDE &&
frame[42] == 0xAD &&
frame[44] == 0xBE &&
frame[46] == 0xEF &&
frame[48] == 0xFF) returntrue;
returnfalse;
}
/** * ice_diag_send - send test frames to the test ring * @tx_ring: pointer to the transmit ring * @data: pointer to the raw packet data * @size: size of the packet to send * * Function sends loopback packets on a test Tx ring.
*/ staticint ice_diag_send(struct ice_tx_ring *tx_ring, u8 *data, u16 size)
{ struct ice_tx_desc *tx_desc; struct ice_tx_buf *tx_buf;
dma_addr_t dma;
u64 td_cmd;
/* Wait until the packets get transmitted to the receive queue. */
usleep_range(1000, 2000);
dma_unmap_single(tx_ring->dev, dma, size, DMA_TO_DEVICE);
return 0;
}
#define ICE_LB_FRAME_SIZE 64 /** * ice_lbtest_receive_frames - receive and verify test frames * @rx_ring: pointer to the receive ring * * Function receives loopback packets and verify their correctness. * Returns number of received valid frames.
*/ staticint ice_lbtest_receive_frames(struct ice_rx_ring *rx_ring)
{ struct ice_rx_buf *rx_buf; int valid_frames, i;
u8 *received_buf;
valid_frames = 0;
for (i = 0; i < rx_ring->count; i++) { union ice_32b_rx_flex_desc *rx_desc;
rx_desc = ICE_RX_DESC(rx_ring, i);
if (!(rx_desc->wb.status_error0 &
(cpu_to_le16(BIT(ICE_RX_FLEX_DESC_STATUS0_DD_S)) |
cpu_to_le16(BIT(ICE_RX_FLEX_DESC_STATUS0_EOF_S))))) continue;
if (ice_lbtest_prepare_rings(test_vsi)) {
ret = 2; goto lbtest_vsi_close;
}
if (ice_alloc_rx_bufs(rx_ring, rx_ring->count)) {
ret = 3; goto lbtest_rings_dis;
}
/* Enable MAC loopback in firmware */ if (ice_aq_set_mac_loopback(&pf->hw, true, NULL)) {
ret = 4; goto lbtest_mac_dis;
}
/* Test VSI needs to receive broadcast packets */
eth_broadcast_addr(broadcast); if (ice_fltr_add_mac(test_vsi, broadcast, ICE_FWD_TO_VSI)) {
ret = 5; goto lbtest_mac_dis;
}
if (ice_lbtest_create_frame(pf, &tx_frame, ICE_LB_FRAME_SIZE)) {
ret = 7; goto remove_mac_filters;
}
num_frames = min_t(int, tx_ring->count, 32); for (i = 0; i < num_frames; i++) { if (ice_diag_send(tx_ring, tx_frame, ICE_LB_FRAME_SIZE)) {
ret = 8; goto remove_mac_filters;
}
}
valid_frames = ice_lbtest_receive_frames(rx_ring); if (!valid_frames)
ret = 9; elseif (valid_frames != num_frames)
ret = 10;
remove_mac_filters: if (ice_fltr_remove_mac(test_vsi, broadcast, ICE_FWD_TO_VSI))
netdev_err(netdev, "Could not remove MAC filter for the test VSI\n");
lbtest_mac_dis: /* Disable MAC loopback after the test is completed. */ if (ice_aq_set_mac_loopback(&pf->hw, false, NULL))
netdev_err(netdev, "Could not disable MAC loopback\n");
lbtest_rings_dis: if (ice_lbtest_disable_rings(test_vsi))
netdev_err(netdev, "Could not disable test rings\n");
lbtest_vsi_close:
test_vsi->netdev = NULL; if (ice_vsi_release(test_vsi))
netdev_err(netdev, "Failed to remove the test VSI\n");
return ret;
}
/** * ice_intr_test - perform an interrupt test on a given net_device * @netdev: network interface device structure * * This function performs one of the self-tests required by ethtool. * Returns 0 on success, non-zero on failure.
*/ static u64 ice_intr_test(struct net_device *netdev)
{ struct ice_netdev_priv *np = netdev_priv(netdev); struct ice_pf *pf = np->vsi->back;
u16 swic_old = pf->sw_int_count;
/** * ice_self_test - handler function for performing a self-test by ethtool * @netdev: network interface device structure * @eth_test: ethtool_test structure * @data: required by ethtool.self_test * * This function is called after invoking 'ethtool -t devname' command where * devname is the name of the network device on which ethtool should operate. * It performs a set of self-tests to check if a device works properly.
*/ staticvoid
ice_self_test(struct net_device *netdev, struct ethtool_test *eth_test,
u64 *data)
{ struct ice_netdev_priv *np = netdev_priv(netdev); bool if_running = netif_running(netdev); struct ice_pf *pf = np->vsi->back; struct device *dev;
dev = ice_pf_to_dev(pf);
if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
netdev_info(netdev, "offline testing starting\n");
set_bit(ICE_TESTING, pf->state);
if (ice_active_vfs(pf)) {
dev_warn(dev, "Please take active VFs and Netqueues offline and restart the adapter before running NIC diagnostics\n");
data[ICE_ETH_TEST_REG] = 1;
data[ICE_ETH_TEST_EEPROM] = 1;
data[ICE_ETH_TEST_INTR] = 1;
data[ICE_ETH_TEST_LOOP] = 1;
data[ICE_ETH_TEST_LINK] = 1;
eth_test->flags |= ETH_TEST_FL_FAILED;
clear_bit(ICE_TESTING, pf->state); goto skip_ol_tests;
} /* If the device is online then take it offline */ if (if_running) /* indicate we're in test mode */
ice_stop(netdev);
if (status) {
dev_err(dev, "Could not open device %s, err %d\n",
pf->int_name, status);
}
}
} else { /* Online tests */
netdev_info(netdev, "online testing starting\n");
data[ICE_ETH_TEST_LINK] = ice_link_test(netdev); if (data[ICE_ETH_TEST_LINK])
eth_test->flags |= ETH_TEST_FL_FAILED;
/* Offline only tests, not run in online; pass by default */
data[ICE_ETH_TEST_REG] = 0;
data[ICE_ETH_TEST_EEPROM] = 0;
data[ICE_ETH_TEST_INTR] = 0;
data[ICE_ETH_TEST_LOOP] = 0;
}
/* Changing the FEC parameters is not supported if not the PF VSI */ if (vsi->type != ICE_VSI_PF) {
netdev_info(netdev, "Changing FEC parameters only supported for PF VSI\n"); return -EOPNOTSUPP;
}
/* Proceed only if requesting different FEC mode */ if (pi->phy.curr_user_fec_req == req_fec) return 0;
/* Copy the current user PHY configuration. The current user PHY * configuration is initialized during probe from PHY capabilities * software mode, and updated on set PHY configuration.
*/
memcpy(&config, &pi->phy.curr_user_phy_cfg, sizeof(config));
if (!pi) return -EOPNOTSUPP;
link_info = &pi->phy.link_info;
/* Set FEC mode based on negotiated link info */ switch (link_info->fec_info) { case ICE_AQ_LINK_25G_KR_FEC_EN:
fecparam->active_fec = ETHTOOL_FEC_BASER; break; case ICE_AQ_LINK_25G_RS_528_FEC_EN: case ICE_AQ_LINK_25G_RS_544_FEC_EN:
fecparam->active_fec = ETHTOOL_FEC_RS; break; default:
fecparam->active_fec = ETHTOOL_FEC_OFF; break;
}
caps = kzalloc(sizeof(*caps), GFP_KERNEL); if (!caps) return -ENOMEM;
/* If VSI state is up, then restart autoneg with link up */ if (!test_bit(ICE_DOWN, vsi->back->state))
err = ice_set_link(vsi, true); else
err = ice_set_link(vsi, false);
return err;
}
/** * ice_get_priv_flags - report device private flags * @netdev: network interface device structure * * The get string set count and the string set should be matched for each * flag returned. Add new strings for each flag to the ice_gstrings_priv_flags * array. * * Returns a u32 bitmap of flags.
*/ static u32 ice_get_priv_flags(struct net_device *netdev)
{ struct ice_netdev_priv *np = netdev_priv(netdev); struct ice_vsi *vsi = np->vsi; struct ice_pf *pf = vsi->back;
u32 i, ret_flags = 0;
for (i = 0; i < ICE_PRIV_FLAG_ARRAY_SIZE; i++) { conststruct ice_priv_flag *priv_flag;
priv_flag = &ice_gstrings_priv_flags[i];
if (test_bit(priv_flag->bitno, pf->flags))
ret_flags |= BIT(i);
}
return ret_flags;
}
/** * ice_set_priv_flags - set private flags * @netdev: network interface device structure * @flags: bit flags to be set
*/ staticint ice_set_priv_flags(struct net_device *netdev, u32 flags)
{ struct ice_netdev_priv *np = netdev_priv(netdev);
DECLARE_BITMAP(change_flags, ICE_PF_FLAGS_NBITS);
DECLARE_BITMAP(orig_flags, ICE_PF_FLAGS_NBITS); struct ice_vsi *vsi = np->vsi; struct ice_pf *pf = vsi->back; struct device *dev; int ret = 0;
u32 i;
if (flags > BIT(ICE_PRIV_FLAG_ARRAY_SIZE)) return -EINVAL;
dev = ice_pf_to_dev(pf);
set_bit(ICE_FLAG_ETHTOOL_CTXT, pf->flags);
bitmap_copy(orig_flags, pf->flags, ICE_PF_FLAGS_NBITS); for (i = 0; i < ICE_PRIV_FLAG_ARRAY_SIZE; i++) { conststruct ice_priv_flag *priv_flag;
priv_flag = &ice_gstrings_priv_flags[i];
if (flags & BIT(i))
set_bit(priv_flag->bitno, pf->flags); else
clear_bit(priv_flag->bitno, pf->flags);
}
/* Do not allow change to link-down-on-close when Total Port Shutdown * is enabled.
*/ if (test_bit(ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA, change_flags) &&
test_bit(ICE_FLAG_TOTAL_PORT_SHUTDOWN_ENA, pf->flags)) {
dev_err(dev, "Setting link-down-on-close not supported on this port\n");
set_bit(ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA, pf->flags);
ret = -EINVAL; goto ethtool_exit;
}
if (test_bit(ICE_FLAG_FW_LLDP_AGENT, change_flags)) { if (!test_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags)) { int status;
/* Disable FW LLDP engine */
status = ice_cfg_lldp_mib_change(&pf->hw, false);
/* If unregistering for LLDP events fails, this is * not an error state, as there shouldn't be any * events to respond to.
*/ if (status)
dev_info(dev, "Failed to unreg for LLDP events\n");
/* The AQ call to stop the FW LLDP agent will generate * an error if the agent is already stopped.
*/
status = ice_aq_stop_lldp(&pf->hw, true, true, NULL); if (status)
dev_warn(dev, "Fail to stop LLDP agent\n"); /* Use case for having the FW LLDP agent stopped * will likely not need DCB, so failure to init is * not a concern of ethtool
*/
status = ice_init_pf_dcb(pf, true); if (status)
dev_warn(dev, "Fail to init DCB\n");
if (ice_get_pfc_mode(pf) == ICE_QOS_MODE_DSCP) {
clear_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags);
dev_err(dev, "QoS in L3 DSCP mode, FW Agent not allowed to start\n");
ret = -EOPNOTSUPP; goto ethtool_exit;
}
/* Remove rule to direct LLDP packets to default VSI. * The FW LLDP engine will now be consuming them.
*/
ice_cfg_sw_rx_lldp(vsi->back, false);
/* AQ command to start FW LLDP agent will return an * error if the agent is already started
*/
status = ice_aq_start_lldp(&pf->hw, true, NULL); if (status)
dev_warn(dev, "Fail to start LLDP Agent\n");
/* AQ command to start FW DCBX agent will fail if * the agent is already started
*/
status = ice_aq_start_stop_dcbx(&pf->hw, true,
&dcbx_agent_status,
NULL); if (status)
dev_dbg(dev, "Failed to start FW DCBX\n");
/* Failure to configure MIB change or init DCB is not * relevant to ethtool. Print notification that * registration/init failed but do not return error * state to ethtool
*/
status = ice_init_pf_dcb(pf, true); if (status)
dev_dbg(dev, "Fail to init DCB\n");
/* Register for MIB change events */
status = ice_cfg_lldp_mib_change(&pf->hw, true); if (status)
dev_dbg(dev, "Fail to enable MIB change events\n");
ice_nway_reset(netdev);
}
} if (test_bit(ICE_FLAG_LEGACY_RX, change_flags)) { /* down and up VSI so that changes of Rx cfg are reflected. */
ice_down_up(vsi);
} /* don't allow modification of this flag when a single VF is in * promiscuous mode because it's not supported
*/ if (test_bit(ICE_FLAG_VF_TRUE_PROMISC_ENA, change_flags) &&
ice_is_any_vf_in_unicast_promisc(pf)) {
dev_err(dev, "Changing vf-true-promisc-support flag while VF(s) are in promiscuous mode not supported\n"); /* toggle bit back to previous state */
change_bit(ICE_FLAG_VF_TRUE_PROMISC_ENA, pf->flags);
ret = -EAGAIN;
}
if (test_bit(ICE_FLAG_VF_VLAN_PRUNING, change_flags) &&
ice_has_vfs(pf)) {
dev_err(dev, "vf-vlan-pruning: VLAN pruning cannot be changed while VFs are active.\n"); /* toggle bit back to previous state */
change_bit(ICE_FLAG_VF_VLAN_PRUNING, pf->flags);
ret = -EOPNOTSUPP;
}
ethtool_exit:
clear_bit(ICE_FLAG_ETHTOOL_CTXT, pf->flags); return ret;
}
staticint ice_get_sset_count(struct net_device *netdev, int sset)
{ switch (sset) { case ETH_SS_STATS: /* The number (and order) of strings reported *must* remain * constant for a given netdevice. This function must not * report a different number based on run time parameters * (such as the number of queues in use, or the setting of * a private ethtool flag). This is due to the nature of the * ethtool stats API. * * Userspace programs such as ethtool must make 3 separate * ioctl requests, one for size, one for the strings, and * finally one for the stats. Since these cross into * userspace, changes to the number or size could result in * undefined memory access or incorrect string<->value * correlations for statistics. * * Even if it appears to be safe, changes to the size or * order of strings will suffer from race conditions and are * not safe.
*/ return ICE_ALL_STATS_LEN(netdev); case ETH_SS_TEST: return ICE_TEST_LEN; case ETH_SS_PRIV_FLAGS: return ICE_PRIV_FLAG_ARRAY_SIZE; default: return -EOPNOTSUPP;
}
}
/** * ice_mask_min_supported_speeds * @hw: pointer to the HW structure * @phy_types_high: PHY type high * @phy_types_low: PHY type low to apply minimum supported speeds mask * * Apply minimum supported speeds mask to PHY type low. These are the speeds * for ethtool supported link mode.
*/ staticvoid
ice_mask_min_supported_speeds(struct ice_hw *hw,
u64 phy_types_high, u64 *phy_types_low)
{ /* if QSFP connection with 100G speed, minimum supported speed is 25G */ if ((*phy_types_low & ICE_PHY_TYPE_LOW_MASK_100G) ||
(phy_types_high & ICE_PHY_TYPE_HIGH_MASK_100G) ||
(phy_types_high & ICE_PHY_TYPE_HIGH_MASK_200G))
*phy_types_low &= ~ICE_PHY_TYPE_LOW_MASK_MIN_25G; elseif (!ice_is_100m_speed_supported(hw))
*phy_types_low &= ~ICE_PHY_TYPE_LOW_MASK_MIN_1G;
}
/** * ice_linkmode_set_bit - set link mode bit * @phy_to_ethtool: PHY type to ethtool link mode struct to set * @ks: ethtool link ksettings struct to fill out * @req_speeds: speed requested by user * @advert_phy_type: advertised PHY type * @phy_type: PHY type
*/ staticvoid
ice_linkmode_set_bit(conststruct ice_phy_type_to_ethtool *phy_to_ethtool, struct ethtool_link_ksettings *ks, u32 req_speeds,
u64 advert_phy_type, u32 phy_type)
{
linkmode_set_bit(phy_to_ethtool->link_mode, ks->link_modes.supported);
/* Check if lenient mode is supported and enabled, or in strict mode. * * In lenient mode the Supported link modes are the PHY types without * media. The Advertising link mode is either 1. the user requested * speed, 2. the override PHY mask, or 3. the PHY types with media. * * In strict mode Supported link mode are the PHY type with media, * and Advertising link modes are the media PHY type or the speed * requested by user.
*/ if (test_bit(ICE_FLAG_LINK_LENIENT_MODE_ENA, pf->flags)) {
phy_types_low = le64_to_cpu(pf->nvm_phy_type_lo);
phy_types_high = le64_to_cpu(pf->nvm_phy_type_hi);
ice_mask_min_supported_speeds(&pf->hw, phy_types_high,
&phy_types_low); /* determine advertised modes based on link override only * if it's supported and if the FW doesn't abstract the * driver from having to account for link overrides
*/ if (ice_fw_supports_link_override(&pf->hw) &&
!ice_fw_supports_report_dflt_cfg(&pf->hw)) { struct ice_link_default_override_tlv *ldo;
ldo = &pf->link_dflt_override; /* If override enabled and PHY mask set, then * Advertising link mode is the intersection of the PHY * types without media and the override PHY mask.
*/ if (ldo->options & ICE_LINK_OVERRIDE_EN &&
(ldo->phy_type_low || ldo->phy_type_high)) {
advert_phy_type_lo =
le64_to_cpu(pf->nvm_phy_type_lo) &
ldo->phy_type_low;
advert_phy_type_hi =
le64_to_cpu(pf->nvm_phy_type_hi) &
ldo->phy_type_high;
}
}
} else { /* strict mode */
phy_types_low = vsi->port_info->phy.phy_type_low;
phy_types_high = vsi->port_info->phy.phy_type_high;
}
/* If Advertising link mode PHY type is not using override PHY type, * then use PHY type with media.
*/ if (!advert_phy_type_lo && !advert_phy_type_hi) {
advert_phy_type_lo = vsi->port_info->phy.phy_type_low;
advert_phy_type_hi = vsi->port_info->phy.phy_type_high;
}
for (i = 0; i < ARRAY_SIZE(phy_type_low_lkup); i++) { if (phy_types_low & BIT_ULL(i))
ice_linkmode_set_bit(&phy_type_low_lkup[i], ks,
req_speeds, advert_phy_type_lo,
i);
}
for (i = 0; i < ARRAY_SIZE(phy_type_high_lkup); i++) { if (phy_types_high & BIT_ULL(i))
ice_linkmode_set_bit(&phy_type_high_lkup[i], ks,
req_speeds, advert_phy_type_hi,
i);
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.