Ejemplo n.º 1
0
static int
qlcnic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
{
	u32 config = 0;
	u32 ret = 0;
	struct qlcnic_adapter *adapter = netdev_priv(dev);

	if (adapter->ahw->port_type != QLCNIC_GBE)
		return -EOPNOTSUPP;

	/* read which mode */
	if (ecmd->duplex)
		config |= 0x1;

	if (ecmd->autoneg)
		config |= 0x2;

	switch (ethtool_cmd_speed(ecmd)) {
	case SPEED_10:
		config |= (0 << 8);
		break;
	case SPEED_100:
		config |= (1 << 8);
		break;
	case SPEED_1000:
		config |= (10 << 8);
		break;
	default:
		return -EIO;
	}

	ret = qlcnic_fw_cmd_set_port(adapter, config);

	if (ret == QLCNIC_RCODE_NOT_SUPPORTED)
		return -EOPNOTSUPP;
	else if (ret)
		return -EIO;

	adapter->link_speed = ethtool_cmd_speed(ecmd);
	adapter->link_duplex = ecmd->duplex;
	adapter->link_autoneg = ecmd->autoneg;

	if (!netif_running(dev))
		return 0;

	dev->netdev_ops->ndo_stop(dev);
	return dev->netdev_ops->ndo_open(dev);
}
static int qlcnic_set_port_config(struct qlcnic_adapter *adapter,
				  struct ethtool_cmd *ecmd)
{
	u32 ret = 0, config = 0;
	/* read which mode */
	if (ecmd->duplex)
		config |= 0x1;

	if (ecmd->autoneg)
		config |= 0x2;

	switch (ethtool_cmd_speed(ecmd)) {
	case SPEED_10:
		config |= (0 << 8);
		break;
	case SPEED_100:
		config |= (1 << 8);
		break;
	case SPEED_1000:
		config |= (10 << 8);
		break;
	default:
		return -EIO;
	}

	ret = qlcnic_fw_cmd_set_port(adapter, config);

	if (ret == QLCNIC_RCODE_NOT_SUPPORTED)
		return -EOPNOTSUPP;
	else if (ret)
		return -EIO;
	return ret;
}
static int qlcnic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
{
	u32 ret = 0;
	struct qlcnic_adapter *adapter = netdev_priv(dev);

	if (adapter->ahw->port_type != QLCNIC_GBE)
		return -EOPNOTSUPP;

	if (qlcnic_83xx_check(adapter))
		ret = qlcnic_83xx_set_settings(adapter, ecmd);
	else
		ret = qlcnic_set_port_config(adapter, ecmd);

	if (!ret)
		return ret;

	adapter->ahw->link_speed = ethtool_cmd_speed(ecmd);
	adapter->ahw->link_duplex = ecmd->duplex;
	adapter->ahw->link_autoneg = ecmd->autoneg;

	if (!netif_running(dev))
		return 0;

	dev->netdev_ops->ndo_stop(dev);
	return dev->netdev_ops->ndo_open(dev);
}
Ejemplo n.º 4
0
u32 ethtool_bitrate(const char *ifname)
{
	int ret, sock, bitrate;
	struct ifreq ifr;
	struct ethtool_cmd ecmd;

	sock = af_socket(AF_INET);

	memset(&ecmd, 0, sizeof(ecmd));

	memset(&ifr, 0, sizeof(ifr));
	strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);

	ecmd.cmd = ETHTOOL_GSET;
	ifr.ifr_data = (char *) &ecmd;

	ret = ioctl(sock, SIOCETHTOOL, &ifr);
	if (ret) {
		bitrate = 0;
		goto out;
	}

	bitrate = ethtool_cmd_speed(&ecmd);
	if (bitrate == SPEED_UNKNOWN)
		bitrate = 0;
out:
	close(sock);

	return bitrate;
}
Ejemplo n.º 5
0
static int xgbe_set_settings(struct net_device *netdev,
			     struct ethtool_cmd *cmd)
{
	struct xgbe_prv_data *pdata = netdev_priv(netdev);
	struct phy_device *phydev = pdata->phydev;
	u32 speed;
	int ret;

	DBGPR("-->xgbe_set_settings\n");

	if (!pdata->phydev)
		return -ENODEV;

	speed = ethtool_cmd_speed(cmd);

	if (cmd->phy_address != phydev->addr)
		return -EINVAL;

	if ((cmd->autoneg != AUTONEG_ENABLE) &&
	    (cmd->autoneg != AUTONEG_DISABLE))
		return -EINVAL;

	if (cmd->autoneg == AUTONEG_DISABLE) {
		switch (speed) {
		case SPEED_10000:
		case SPEED_2500:
		case SPEED_1000:
			break;
		default:
			return -EINVAL;
		}

		if (cmd->duplex != DUPLEX_FULL)
			return -EINVAL;
	}

	cmd->advertising &= phydev->supported;
	if ((cmd->autoneg == AUTONEG_ENABLE) && !cmd->advertising)
		return -EINVAL;

	ret = 0;
	phydev->autoneg = cmd->autoneg;
	phydev->speed = speed;
	phydev->duplex = cmd->duplex;
	phydev->advertising = cmd->advertising;

	if (cmd->autoneg == AUTONEG_ENABLE)
		phydev->advertising |= ADVERTISED_Autoneg;
	else
		phydev->advertising &= ~ADVERTISED_Autoneg;

	if (netif_running(netdev))
		ret = phy_start_aneg(phydev);

	DBGPR("<--xgbe_set_settings\n");

	return ret;
}
Ejemplo n.º 6
0
static int qede_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
	struct qede_dev *edev = netdev_priv(dev);
	struct qed_link_output current_link;
	struct qed_link_params params;
	u32 speed;

	if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) {
		DP_INFO(edev,
			"Link settings are not allowed to be changed\n");
		return -EOPNOTSUPP;
	}

	memset(&current_link, 0, sizeof(current_link));
	memset(&params, 0, sizeof(params));
	edev->ops->common->get_link(edev->cdev, &current_link);

	speed = ethtool_cmd_speed(cmd);
	params.override_flags |= QED_LINK_OVERRIDE_SPEED_ADV_SPEEDS;
	params.override_flags |= QED_LINK_OVERRIDE_SPEED_AUTONEG;
	if (cmd->autoneg == AUTONEG_ENABLE) {
		params.autoneg = true;
		params.forced_speed = 0;
		params.adv_speeds = cmd->advertising;
	} else { /* forced speed */
		params.override_flags |= QED_LINK_OVERRIDE_SPEED_FORCED_SPEED;
		params.autoneg = false;
		params.forced_speed = speed;
		switch (speed) {
		case SPEED_10000:
			if (!(current_link.supported_caps &
			    SUPPORTED_10000baseKR_Full)) {
				DP_INFO(edev, "10G speed not supported\n");
				return -EINVAL;
			}
			params.adv_speeds = SUPPORTED_10000baseKR_Full;
			break;
		case SPEED_40000:
			if (!(current_link.supported_caps &
			    SUPPORTED_40000baseLR4_Full)) {
				DP_INFO(edev, "40G speed not supported\n");
				return -EINVAL;
			}
			params.adv_speeds = SUPPORTED_40000baseLR4_Full;
			break;
		default:
			DP_INFO(edev, "Unsupported speed %u\n", speed);
			return -EINVAL;
		}
	}

	params.link_up = true;
	edev->ops->common->set_link(edev->cdev, &params);

	return 0;
}
Ejemplo n.º 7
0
/**
 * vxge_ethtool_sset - Sets different link parameters.
 * @dev: device pointer.
 * @info: pointer to the structure with parameters given by ethtool to set
 * link information.
 *
 * The function sets different link parameters provided by the user onto
 * the NIC.
 * Return value:
 * 0 on success.
 */
static int vxge_ethtool_sset(struct net_device *dev, struct ethtool_cmd *info)
{
	/* We currently only support 10Gb/FULL */
	if ((info->autoneg == AUTONEG_ENABLE) ||
	    (ethtool_cmd_speed(info) != SPEED_10000) ||
	    (info->duplex != DUPLEX_FULL))
		return -EINVAL;

	return 0;
}
Ejemplo n.º 8
0
static int efx_mcdi_phy_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
{
	struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
	u32 caps;
	int rc;

	if (ecmd->autoneg) {
		caps = (ethtool_to_mcdi_cap(ecmd->advertising) |
			 1 << MC_CMD_PHY_CAP_AN_LBN);
	} else if (ecmd->duplex) {
		switch (ethtool_cmd_speed(ecmd)) {
		case 10:    caps = 1 << MC_CMD_PHY_CAP_10FDX_LBN;    break;
		case 100:   caps = 1 << MC_CMD_PHY_CAP_100FDX_LBN;   break;
		case 1000:  caps = 1 << MC_CMD_PHY_CAP_1000FDX_LBN;  break;
		case 10000: caps = 1 << MC_CMD_PHY_CAP_10000FDX_LBN; break;
		case 40000: caps = 1 << MC_CMD_PHY_CAP_40000FDX_LBN; break;
		default:    return -EINVAL;
		}
	} else {
		switch (ethtool_cmd_speed(ecmd)) {
		case 10:    caps = 1 << MC_CMD_PHY_CAP_10HDX_LBN;    break;
		case 100:   caps = 1 << MC_CMD_PHY_CAP_100HDX_LBN;   break;
		case 1000:  caps = 1 << MC_CMD_PHY_CAP_1000HDX_LBN;  break;
		default:    return -EINVAL;
		}
	}

	rc = efx_mcdi_set_link(efx, caps, efx_get_mcdi_phy_flags(efx),
			       efx->loopback_mode, 0);
	if (rc)
		return rc;

	if (ecmd->autoneg) {
		efx_link_set_advertising(
			efx, ecmd->advertising | ADVERTISED_Autoneg);
		phy_cfg->forced_cap = 0;
	} else {
		efx_link_set_advertising(efx, 0);
		phy_cfg->forced_cap = caps;
	}
	return 0;
}
Ejemplo n.º 9
0
static int
bnad_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
{
	/* 10G full duplex setting supported only */
	if (cmd->autoneg == AUTONEG_ENABLE)
		return -EOPNOTSUPP; else {
		if ((ethtool_cmd_speed(cmd) == SPEED_10000)
		    && (cmd->duplex == DUPLEX_FULL))
			return 0;
	}

	return -EOPNOTSUPP;
}
Ejemplo n.º 10
0
static int atl1c_set_settings(struct net_device *netdev,
			      struct ethtool_cmd *ecmd)
{
	struct atl1c_adapter *adapter = netdev_priv(netdev);
	struct atl1c_hw *hw = &adapter->hw;
	u16  autoneg_advertised;

	while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
		msleep(1);

	if (ecmd->autoneg == AUTONEG_ENABLE) {
		autoneg_advertised = ADVERTISED_Autoneg;
	} else {
		u32 speed = ethtool_cmd_speed(ecmd);
		if (speed == SPEED_1000) {
			if (ecmd->duplex != DUPLEX_FULL) {
				if (netif_msg_link(adapter))
					dev_warn(&adapter->pdev->dev,
						"1000M half is invalid\n");
				clear_bit(__AT_RESETTING, &adapter->flags);
				return -EINVAL;
			}
			autoneg_advertised = ADVERTISED_1000baseT_Full;
		} else if (speed == SPEED_100) {
			if (ecmd->duplex == DUPLEX_FULL)
				autoneg_advertised = ADVERTISED_100baseT_Full;
			else
				autoneg_advertised = ADVERTISED_100baseT_Half;
		} else {
			if (ecmd->duplex == DUPLEX_FULL)
				autoneg_advertised = ADVERTISED_10baseT_Full;
			else
				autoneg_advertised = ADVERTISED_10baseT_Half;
		}
	}

	if (hw->autoneg_advertised != autoneg_advertised) {
		hw->autoneg_advertised = autoneg_advertised;
		if (atl1c_restart_autoneg(hw) != 0) {
			if (netif_msg_link(adapter))
				dev_warn(&adapter->pdev->dev,
					"ethtool speed/duplex setting failed\n");
			clear_bit(__AT_RESETTING, &adapter->flags);
			return -EINVAL;
		}
	}
	clear_bit(__AT_RESETTING, &adapter->flags);
	return 0;
}
Ejemplo n.º 11
0
static int netvsc_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
	struct net_device_context *ndc = netdev_priv(dev);
	u32 speed;

	speed = ethtool_cmd_speed(cmd);
	if (!ethtool_validate_speed(speed) ||
	    !ethtool_validate_duplex(cmd->duplex) ||
	    !netvsc_validate_ethtool_ss_cmd(cmd))
		return -EINVAL;

	ndc->speed = speed;
	ndc->duplex = cmd->duplex;

	return 0;
}
Ejemplo n.º 12
0
static int efx_ethtool_set_settings(struct net_device *net_dev,
				    struct ethtool_cmd *ecmd)
#endif
{
	struct efx_nic *efx = netdev_priv(net_dev);
	int rc;

#ifdef EFX_NOT_UPSTREAM
	/* Older versions of ethtool have the following short-comings:
	 *  - They don't understand 10G.
	 *  - They have no "advertising" field to allow someone to
	 *    control the speeds supported by a non-autoneg PHY.
	 * Support these versions by allowing the user to use "autoneg on"
	 * to revert the advertised capabilities to the default set, even
	 * on a PHY that doesn't support autoneg.
	 *
	 * The user can override this behaviour when using "ethtool advertise"
	 * on ethtool-6 by including ADVERTISED_Autoneg = 0x40.
	 */
	if (ecmd->advertising != efx->link_advertising
	    && ecmd->autoneg && !(ecmd->advertising & ADVERTISED_Autoneg)) {
		if (ecmd->advertising ==
		    (ADVERTISED_100baseT_Full | ADVERTISED_100baseT_Half |
		     ADVERTISED_10baseT_Full | ADVERTISED_10baseT_Half |
		     ADVERTISED_1000baseT_Full | ADVERTISED_1000baseT_Half))
			ecmd->advertising = ecmd->supported;
		if (ecmd->autoneg && !(ecmd->supported & SUPPORTED_Autoneg))
			ecmd->autoneg = 0;
	}
#endif

	/* GMAC does not support 1000Mbps HD */
	if ((ethtool_cmd_speed(ecmd) == SPEED_1000) &&
	    (ecmd->duplex != DUPLEX_FULL)) {
		netif_dbg(efx, drv, efx->net_dev,
			  "rejecting unsupported 1000Mbps HD setting\n");
		return -EINVAL;
	}

	mutex_lock(&efx->mac_lock);
	rc = efx->phy_op->set_settings(efx, ecmd);
	mutex_unlock(&efx->mac_lock);
	return rc;
}
Ejemplo n.º 13
0
/*
 * Obtain an appropriate bandwidth for the interface if_name. On Linux, we
 * get this via an ioctl(). Elsewhere or in the error case, we return the
 * speed as 0.
 */
unsigned int
opal_ethtool_get_speed (const char *if_name)
{
    unsigned int speed = 0;

#if defined(HAVE_DECL_SIOCETHTOOL) && defined(HAVE_STRUCT_IFREQ) && defined(HAVE_STRUCT_ETHTOOL_CMD)
    int sockfd;
    struct ifreq ifr;
    struct ethtool_cmd edata = {
        .cmd = ETHTOOL_GSET,
    };

    sockfd = socket(PF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        goto out;
    }

    memset(&ifr, 0, sizeof(struct ifreq));
    strncpy(ifr.ifr_name, if_name, IF_NAMESIZE);
    /* strncpy does not null terminate when the string is truncated */
    ifr.ifr_name[IF_NAMESIZE-1] = '\0';
    ifr.ifr_data = (char *)&edata;

    if (ioctl(sockfd, SIOCETHTOOL, &ifr) < 0) {
        goto out;
    }

#if HAVE_DECL_ETHTOOL_CMD_SPEED
    speed = ethtool_cmd_speed(&edata);
#elif defined(HAVE_STRUCT_ETHTOOL_CMD_SPEED_HI)
    speed = (edata.speed_hi << 16) | edata.speed;
#else
    speed = edata.speed;
#endif
    if (UINT_MAX == speed) {
        speed = 0;
    }

out:
    close(sockfd);
#endif

    return speed;
}
Ejemplo n.º 14
0
static int set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
	unsigned int cap;
	struct port_info *p = netdev_priv(dev);
	struct link_config *lc = &p->link_cfg;
	u32 speed = ethtool_cmd_speed(cmd);

	if (cmd->duplex != DUPLEX_FULL)     /* only full-duplex supported */
		return -EINVAL;

	if (!(lc->supported & FW_PORT_CAP_ANEG)) {
		/* PHY offers a single speed.  See if that's what's
		 * being requested.
		 */
		if (cmd->autoneg == AUTONEG_DISABLE &&
		    (lc->supported & speed_to_caps(speed)))
			return 0;
		return -EINVAL;
	}

	if (cmd->autoneg == AUTONEG_DISABLE) {
		cap = speed_to_caps(speed);

		if (!(lc->supported & cap) ||
		    (speed == 1000) ||
		    (speed == 10000) ||
		    (speed == 40000))
			return -EINVAL;
		lc->requested_speed = cap;
		lc->advertising = 0;
	} else {
		cap = to_fw_linkcaps(cmd->advertising);
		if (!(lc->supported & cap))
			return -EINVAL;
		lc->requested_speed = 0;
		lc->advertising = cap | FW_PORT_CAP_ANEG;
	}
	lc->autoneg = cmd->autoneg;

	if (netif_running(dev))
		return t4_link_l1cfg(p->adapter, p->adapter->pf, p->tx_chan,
				     lc);
	return 0;
}
Ejemplo n.º 15
0
/* This must be called with rtnl_lock held. */
static int efx_ethtool_set_settings(struct net_device *net_dev,
				    struct ethtool_cmd *ecmd)
{
	struct efx_nic *efx = netdev_priv(net_dev);
	int rc;

	/* GMAC does not support 1000Mbps HD */
	if ((ethtool_cmd_speed(ecmd) == SPEED_1000) &&
	    (ecmd->duplex != DUPLEX_FULL)) {
		netif_dbg(efx, drv, efx->net_dev,
			  "rejecting unsupported 1000Mbps HD setting\n");
		return -EINVAL;
	}

	mutex_lock(&efx->mac_lock);
	rc = efx->phy_op->set_settings(efx, ecmd);
	mutex_unlock(&efx->mac_lock);
	return rc;
}
Ejemplo n.º 16
0
/**
 * DPDK callback to retrieve physical link information (unlocked version).
 *
 * @param dev
 *   Pointer to Ethernet device structure.
 * @param wait_to_complete
 *   Wait for request completion (ignored).
 */
static int
mlx5_link_update_unlocked(struct rte_eth_dev *dev, int wait_to_complete)
{
	struct priv *priv = mlx5_get_priv(dev);
	struct ethtool_cmd edata = {
		.cmd = ETHTOOL_GSET
	};
	struct ifreq ifr;
	struct rte_eth_link dev_link;
	int link_speed = 0;

	(void)wait_to_complete;
	if (priv_ifreq(priv, SIOCGIFFLAGS, &ifr)) {
		WARN("ioctl(SIOCGIFFLAGS) failed: %s", strerror(errno));
		return -1;
	}
	memset(&dev_link, 0, sizeof(dev_link));
	dev_link.link_status = ((ifr.ifr_flags & IFF_UP) &&
				(ifr.ifr_flags & IFF_RUNNING));
	ifr.ifr_data = &edata;
	if (priv_ifreq(priv, SIOCETHTOOL, &ifr)) {
		WARN("ioctl(SIOCETHTOOL, ETHTOOL_GSET) failed: %s",
		     strerror(errno));
		return -1;
	}
	link_speed = ethtool_cmd_speed(&edata);
	if (link_speed == -1)
		dev_link.link_speed = 0;
	else
		dev_link.link_speed = link_speed;
	dev_link.link_duplex = ((edata.duplex == DUPLEX_HALF) ?
				ETH_LINK_HALF_DUPLEX : ETH_LINK_FULL_DUPLEX);
	dev_link.link_autoneg = !(dev->data->dev_conf.link_speeds &
			ETH_LINK_SPEED_FIXED);
	if (memcmp(&dev_link, &dev->data->dev_link, sizeof(dev_link))) {
		/* Link status changed. */
		dev->data->dev_link = dev_link;
		return 0;
	}
	/* Link status is still the same. */
	return -1;
}
Ejemplo n.º 17
0
static int
ixgb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
{
	struct ixgb_adapter *adapter = netdev_priv(netdev);
	u32 speed = ethtool_cmd_speed(ecmd);

	if (ecmd->autoneg == AUTONEG_ENABLE ||
	    (speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL))
		return -EINVAL;

	if (netif_running(adapter->netdev)) {
		ixgb_down(adapter, true);
		ixgb_reset(adapter);
		ixgb_up(adapter);
		ixgb_set_speed_duplex(netdev);
	} else
		ixgb_reset(adapter);

	return 0;
}
Ejemplo n.º 18
0
/**
 * @brief Set Settings
 * @param[in] pointer to struct net_device.
 * @param[in] pointer to struct ethtool_cmd.
 */
static int32_t nss_gmac_set_settings(struct net_device *netdev,
			      struct ethtool_cmd *ecmd)
{
	struct nss_gmac_dev *gmacdev = NULL;
	struct phy_device *phydev = NULL;

	gmacdev = (struct nss_gmac_dev *)netdev_priv(netdev);
	BUG_ON(gmacdev == NULL);

	/*
	 * If the speed for this GMAC is forced, and link polling
	 * is disabled by platform, do not proceed with the
	 * changes below. This would be true for GMACs connected
	 * to switch and interfaces that do not use a PHY.
	 */
	if ((gmacdev->forced_speed != SPEED_UNKNOWN)
	    && (!test_bit(__NSS_GMAC_LINKPOLL, &gmacdev->flags)))
		return -EPERM;

	phydev = gmacdev->phydev;

	mutex_lock(&gmacdev->link_mutex);
	nss_gmac_linkdown(gmacdev);
	mutex_unlock(&gmacdev->link_mutex);

	phydev->advertising = ecmd->advertising;
	phydev->autoneg = ecmd->autoneg;

	phydev->speed = ethtool_cmd_speed(ecmd);
	phydev->duplex = ecmd->duplex;

	if (ecmd->autoneg == AUTONEG_ENABLE)
		set_bit(__NSS_GMAC_AUTONEG, &gmacdev->flags);
	else
		clear_bit(__NSS_GMAC_AUTONEG, &gmacdev->flags);

	genphy_config_aneg(phydev);

	return 0;
}
/* Returns speed in Mb/s */
static guint32
ethtool_get_speed (NMDeviceWired *self)
{
	int fd;
	struct ifreq ifr;
	struct ethtool_cmd edata = {
		.cmd = ETHTOOL_GSET,
	};
	guint32 speed = 0;

	g_return_val_if_fail (self != NULL, 0);

	fd = socket (PF_INET, SOCK_DGRAM, 0);
	if (fd < 0) {
		nm_log_warn (LOGD_HW, "couldn't open control socket.");
		return 0;
	}

	memset (&ifr, 0, sizeof (struct ifreq));
	strncpy (ifr.ifr_name, nm_device_get_iface (NM_DEVICE (self)), IFNAMSIZ);
	ifr.ifr_data = (char *) &edata;

	if (ioctl (fd, SIOCETHTOOL, &ifr) < 0)
		goto out;

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
	speed = edata.speed;
#else
	speed = ethtool_cmd_speed (&edata);
#endif

	if (speed == G_MAXUINT16 || speed == G_MAXUINT32)
		speed = 0;

out:
	close (fd);
	return speed;
}
Ejemplo n.º 20
0
gboolean
nmp_utils_ethtool_get_link_speed (const char *ifname, guint32 *out_speed)
{
	struct ethtool_cmd edata = {
		.cmd = ETHTOOL_GSET,
	};
	guint32 speed;

	if (!ethtool_get (ifname, &edata))
		return FALSE;

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
	speed = edata.speed;
#else
	speed = ethtool_cmd_speed (&edata);
#endif
	if (speed == G_MAXUINT16 || speed == G_MAXUINT32)
		speed = 0;

	if (out_speed)
		*out_speed = speed;
	return TRUE;
}
static int pch_gbe_set_settings(struct net_device *netdev,
				 struct ethtool_cmd *ecmd)
{
	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
	struct pch_gbe_hw *hw = &adapter->hw;
	u32 speed = ethtool_cmd_speed(ecmd);
	int ret;

	pch_gbe_hal_write_phy_reg(hw, MII_BMCR, BMCR_RESET);

	/*                                                            
                                                          */
	if (speed == UINT_MAX) {
		speed = SPEED_1000;
		ecmd->duplex = DUPLEX_FULL;
	}
	ret = mii_ethtool_sset(&adapter->mii, ecmd);
	if (ret) {
		pr_err("Error: mii_ethtool_sset\n");
		return ret;
	}
	hw->mac.link_speed = speed;
	hw->mac.link_duplex = ecmd->duplex;
	hw->phy.autoneg_advertised = ecmd->advertising;
	hw->mac.autoneg = ecmd->autoneg;
	pch_gbe_hal_phy_sw_reset(hw);

	/*                */
	if (netif_running(adapter->netdev)) {
		pch_gbe_down(adapter);
		ret = pch_gbe_up(adapter);
	} else {
		pch_gbe_reset(adapter);
	}
	return ret;
}
Ejemplo n.º 22
0
Archivo: sioc.c Proyecto: ckousik/rr
int main(void) {
  int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
  struct ifreq req;
  char name[PATH_MAX];
  int index;
  struct ethtool_cmd etc;
  int err, ret;
  struct iwreq wreq;

  get_ifconfig(sockfd, &req);
  strcpy(name, req.ifr_name);

  req.ifr_ifindex = -1;
  strcpy(req.ifr_name, name);
  ret = ioctl(sockfd, SIOCGIFINDEX, &req);
  atomic_printf("SIOCGIFINDEX(ret:%d): %s index is %d\n", ret, req.ifr_name,
                req.ifr_ifindex);
  test_assert(0 == ret);
  index = req.ifr_ifindex;

  memset(&req.ifr_name, 0x5a, sizeof(req.ifr_name));
  req.ifr_ifindex = index;
  ret = ioctl(sockfd, SIOCGIFNAME, &req);
  atomic_printf("SIOCGIFNAME(ret:%d): index %d(%s) name is %s\n", ret, index,
                name, req.ifr_name);
  test_assert(0 == ret);
  test_assert(!strcmp(name, req.ifr_name));

  memset(&req.ifr_addr, 0x5a, sizeof(req.ifr_addr));
  ret = ioctl(sockfd, SIOCGIFADDR, &req);
  atomic_printf("SIOCGIFADDR(ret:%d): %s addr is", ret, req.ifr_name);
  atomic_printf(" %s\n", sockaddr_name(&req.ifr_addr));
  test_assert(0 == ret);

  memset(&req.ifr_addr, 0x5a, sizeof(req.ifr_addr));
  ret = ioctl(sockfd, SIOCGIFHWADDR, &req);
  atomic_printf("SIOCGIFHWADDR(ret:%d): %s addr is", ret, req.ifr_name);
  atomic_printf(" %s\n", sockaddr_hw_name(&req.ifr_addr));
  test_assert(0 == ret);

  memset(&req.ifr_flags, 0x5a, sizeof(req.ifr_flags));
  ret = ioctl(sockfd, SIOCGIFFLAGS, &req);
  atomic_printf("SIOCGIFFLAGS(ret:%d): %s flags are", ret, req.ifr_name);
  test_assert(0 == ret);
  atomic_printf(" %#x\n", req.ifr_flags);

  memset(&req.ifr_flags, 0x5a, sizeof(req.ifr_mtu));
  ret = ioctl(sockfd, SIOCGIFMTU, &req);
  atomic_printf("SIOCGIFMTU(ret:%d): %s MTU is", ret, req.ifr_name);
  test_assert(0 == ret);
  atomic_printf(" %d\n", req.ifr_mtu);

  memset(&etc, 0, sizeof(etc));
  etc.cmd = ETHTOOL_GSET;
  req.ifr_data = (char*)&etc;
  ret = ioctl(sockfd, SIOCETHTOOL, &req);
  err = errno;
  atomic_printf("SIOCETHTOOL(ret:%d): %s ethtool data:\n", ret, req.ifr_name);
  atomic_printf("  speed:%#x duplex:%#x port:%#x physaddr:%#x, maxtxpkt:%u "
                "maxrxpkt:%u ...\n",
                ethtool_cmd_speed(&etc), etc.duplex, etc.port, etc.phy_address,
                etc.maxtxpkt, etc.maxrxpkt);
  if (-1 == ret) {
    atomic_printf("WARNING: %s doesn't appear to support SIOCETHTOOL; the test "
                  "may have been meaningless (%s/%d)\n",
                  name, strerror(err), err);
    test_assert(EOPNOTSUPP == err || EPERM == err);
  }

  memset(&wreq, 0x5a, sizeof(wreq));
  strcpy(wreq.ifr_ifrn.ifrn_name, name);
  ret = ioctl(sockfd, SIOCGIWRATE, &wreq);
  err = errno;
  atomic_printf("SIOCGIWRATE(ret:%d): %s:\n", ret, wreq.ifr_name);
  atomic_printf("  bitrate:%d (fixed? %s; disabled? %s) flags:%#x\n",
                wreq.u.bitrate.value, wreq.u.bitrate.fixed ? "yes" : "no",
                wreq.u.bitrate.disabled ? "yes" : "no", wreq.u.bitrate.flags);
  if (-1 == ret) {
    atomic_printf("WARNING: %s doesn't appear to be a wireless iface; "
                  "SIOCGIWRATE test may have been meaningless (%s/%d)\n",
                  name, strerror(err), err);
    test_assert(EOPNOTSUPP == err || EPERM == err);
  }

  atomic_puts("EXIT-SUCCESS");
  return 0;
}
Ejemplo n.º 23
0
Archivo: ethtool.c Proyecto: A-K/linux
static int e1000_set_settings(struct net_device *netdev,
			      struct ethtool_cmd *ecmd)
{
	struct e1000_adapter *adapter = netdev_priv(netdev);
	struct e1000_hw *hw = &adapter->hw;

	/*
	 * When SoL/IDER sessions are active, autoneg/speed/duplex
	 * cannot be changed
	 */
	if (hw->phy.ops.check_reset_block &&
	    hw->phy.ops.check_reset_block(hw)) {
		e_err("Cannot change link characteristics when SoL/IDER is active.\n");
		return -EINVAL;
	}

	/*
	 * MDI setting is only allowed when autoneg enabled because
	 * some hardware doesn't allow MDI setting when speed or
	 * duplex is forced.
	 */
	if (ecmd->eth_tp_mdix_ctrl) {
		if (hw->phy.media_type != e1000_media_type_copper)
			return -EOPNOTSUPP;

		if ((ecmd->eth_tp_mdix_ctrl != ETH_TP_MDI_AUTO) &&
		    (ecmd->autoneg != AUTONEG_ENABLE)) {
			e_err("forcing MDI/MDI-X state is not supported when link speed and/or duplex are forced\n");
			return -EINVAL;
		}
	}

	while (test_and_set_bit(__E1000_RESETTING, &adapter->state))
		usleep_range(1000, 2000);

	if (ecmd->autoneg == AUTONEG_ENABLE) {
		hw->mac.autoneg = 1;
		if (hw->phy.media_type == e1000_media_type_fiber)
			hw->phy.autoneg_advertised = ADVERTISED_1000baseT_Full |
						     ADVERTISED_FIBRE |
						     ADVERTISED_Autoneg;
		else
			hw->phy.autoneg_advertised = ecmd->advertising |
						     ADVERTISED_TP |
						     ADVERTISED_Autoneg;
		ecmd->advertising = hw->phy.autoneg_advertised;
		if (adapter->fc_autoneg)
			hw->fc.requested_mode = e1000_fc_default;
	} else {
		u32 speed = ethtool_cmd_speed(ecmd);
		/* calling this overrides forced MDI setting */
		if (e1000_set_spd_dplx(adapter, speed, ecmd->duplex)) {
			clear_bit(__E1000_RESETTING, &adapter->state);
			return -EINVAL;
		}
	}

	/* MDI-X => 2; MDI => 1; Auto => 3 */
	if (ecmd->eth_tp_mdix_ctrl) {
		/*
		 * fix up the value for auto (3 => 0) as zero is mapped
		 * internally to auto
		 */
		if (ecmd->eth_tp_mdix_ctrl == ETH_TP_MDI_AUTO)
			hw->phy.mdix = AUTO_ALL_MODES;
		else
			hw->phy.mdix = ecmd->eth_tp_mdix_ctrl;
	}

	/* reset the link */

	if (netif_running(adapter->netdev)) {
		e1000e_down(adapter);
		e1000e_up(adapter);
	} else
		e1000e_reset(adapter);

	clear_bit(__E1000_RESETTING, &adapter->state);
	return 0;
}
Ejemplo n.º 24
0
/**
 * mdio45_ethtool_gset_npage - get settings for ETHTOOL_GSET
 * @mdio: MDIO interface
 * @ecmd: Ethtool request structure
 * @npage_adv: Modes currently advertised on next pages
 * @npage_lpa: Modes advertised by link partner on next pages
 *
 * The @ecmd parameter is expected to have been cleared before calling
 * mdio45_ethtool_gset_npage().
 *
 * Since the CSRs for auto-negotiation using next pages are not fully
 * standardised, this function does not attempt to decode them.  The
 * caller must pass them in.
 */
void mdio45_ethtool_gset_npage(const struct mdio_if_info *mdio,
			       struct ethtool_cmd *ecmd,
			       u32 npage_adv, u32 npage_lpa)
{
	int reg;
	u32 speed;

#if 0
	BUILD_BUG_ON(MDIO_SUPPORTS_C22 != ETH_MDIO_SUPPORTS_C22);
	BUILD_BUG_ON(MDIO_SUPPORTS_C45 != ETH_MDIO_SUPPORTS_C45);
#endif

	ecmd->transceiver = XCVR_INTERNAL;
	ecmd->phy_address = mdio->prtad;
	ecmd->mdio_support =
		mdio->mode_support & (MDIO_SUPPORTS_C45 | MDIO_SUPPORTS_C22);

	reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
			      MDIO_CTRL2);
	switch (reg & MDIO_PMA_CTRL2_TYPE) {
	case MDIO_PMA_CTRL2_10GBT:
	case MDIO_PMA_CTRL2_1000BT:
	case MDIO_PMA_CTRL2_100BTX:
	case MDIO_PMA_CTRL2_10BT:
		ecmd->port = PORT_TP;
		ecmd->supported = SUPPORTED_TP;
		reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
				      MDIO_SPEED);
		if (reg & MDIO_SPEED_10G)
			ecmd->supported |= SUPPORTED_10000baseT_Full;
		if (reg & MDIO_PMA_SPEED_1000)
			ecmd->supported |= (SUPPORTED_1000baseT_Full |
					    SUPPORTED_1000baseT_Half);
		if (reg & MDIO_PMA_SPEED_100)
			ecmd->supported |= (SUPPORTED_100baseT_Full |
					    SUPPORTED_100baseT_Half);
		if (reg & MDIO_PMA_SPEED_10)
			ecmd->supported |= (SUPPORTED_10baseT_Full |
					    SUPPORTED_10baseT_Half);
		ecmd->advertising = ADVERTISED_TP;
		break;

	case MDIO_PMA_CTRL2_10GBCX4:
		ecmd->port = PORT_OTHER;
		ecmd->supported = 0;
		ecmd->advertising = 0;
		break;

	case MDIO_PMA_CTRL2_10GBKX4:
	case MDIO_PMA_CTRL2_10GBKR:
	case MDIO_PMA_CTRL2_1000BKX:
		ecmd->port = PORT_OTHER;
		ecmd->supported = SUPPORTED_Backplane;
		reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
				      MDIO_PMA_EXTABLE);
		if (reg & MDIO_PMA_EXTABLE_10GBKX4)
			ecmd->supported |= SUPPORTED_10000baseKX4_Full;
		if (reg & MDIO_PMA_EXTABLE_10GBKR)
			ecmd->supported |= SUPPORTED_10000baseKR_Full;
		if (reg & MDIO_PMA_EXTABLE_1000BKX)
			ecmd->supported |= SUPPORTED_1000baseKX_Full;
		reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
				      MDIO_PMA_10GBR_FECABLE);
		if (reg & MDIO_PMA_10GBR_FECABLE_ABLE)
			ecmd->supported |= SUPPORTED_10000baseR_FEC;
		ecmd->advertising = ADVERTISED_Backplane;
		break;

	/* All the other defined modes are flavours of optical */
	default:
		ecmd->port = PORT_FIBRE;
		ecmd->supported = SUPPORTED_FIBRE;
		ecmd->advertising = ADVERTISED_FIBRE;
		break;
	}

	if (mdio->mmds & MDIO_DEVS_AN) {
		ecmd->supported |= SUPPORTED_Autoneg;
		reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_AN,
				      MDIO_CTRL1);
		if (reg & MDIO_AN_CTRL1_ENABLE) {
			ecmd->autoneg = AUTONEG_ENABLE;
			ecmd->advertising |=
				ADVERTISED_Autoneg |
				mdio45_get_an(mdio, MDIO_AN_ADVERTISE) |
				npage_adv;
		} else {
			ecmd->autoneg = AUTONEG_DISABLE;
		}
	} else {
		ecmd->autoneg = AUTONEG_DISABLE;
	}

	if (ecmd->autoneg) {
		u32 modes = 0;
		int an_stat = mdio->mdio_read(mdio->dev, mdio->prtad,
					      MDIO_MMD_AN, MDIO_STAT1);

		/* If AN is complete and successful, report best common
		 * mode, otherwise report best advertised mode. */
		if (an_stat & MDIO_AN_STAT1_COMPLETE) {
			ecmd->lp_advertising =
				mdio45_get_an(mdio, MDIO_AN_LPA) | npage_lpa;
			if (an_stat & MDIO_AN_STAT1_LPABLE)
				ecmd->lp_advertising |= ADVERTISED_Autoneg;
			modes = ecmd->advertising & ecmd->lp_advertising;
		}
		if ((modes & ~ADVERTISED_Autoneg) == 0)
			modes = ecmd->advertising;

		if (modes & (ADVERTISED_10000baseT_Full |
			     ADVERTISED_10000baseKX4_Full |
			     ADVERTISED_10000baseKR_Full)) {
			speed = SPEED_10000;
			ecmd->duplex = DUPLEX_FULL;
		} else if (modes & (ADVERTISED_1000baseT_Full |
				    ADVERTISED_1000baseT_Half |
				    ADVERTISED_1000baseKX_Full)) {
			speed = SPEED_1000;
			ecmd->duplex = !(modes & ADVERTISED_1000baseT_Half);
		} else if (modes & (ADVERTISED_100baseT_Full |
				    ADVERTISED_100baseT_Half)) {
			speed = SPEED_100;
			ecmd->duplex = !!(modes & ADVERTISED_100baseT_Full);
		} else {
			speed = SPEED_10;
			ecmd->duplex = !!(modes & ADVERTISED_10baseT_Full);
		}
	} else {
		/* Report forced settings */
		reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
				      MDIO_CTRL1);
		speed = (((reg & MDIO_PMA_CTRL1_SPEED1000) ? 100 : 1)
			 * ((reg & MDIO_PMA_CTRL1_SPEED100) ? 100 : 10));
		ecmd->duplex = (reg & MDIO_CTRL1_FULLDPLX ||
				speed == SPEED_10000);
	}

	ethtool_cmd_speed_set(ecmd, speed);

	/* 10GBASE-T MDI/MDI-X */
	if (ecmd->port == PORT_TP
	    && (ethtool_cmd_speed(ecmd) == SPEED_10000)) {
		switch (mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
					MDIO_PMA_10GBT_SWAPPOL)) {
		case MDIO_PMA_10GBT_SWAPPOL_ABNX | MDIO_PMA_10GBT_SWAPPOL_CDNX:
			ecmd->eth_tp_mdix = ETH_TP_MDI;
			break;
		case 0:
			ecmd->eth_tp_mdix = ETH_TP_MDI_X;
			break;
		default:
			/* It's complicated... */
			ecmd->eth_tp_mdix = ETH_TP_MDI_INVALID;
			break;
		}
	}
}
Ejemplo n.º 25
0
struct replay_list* load_interfaces() {

	struct replay_interface *iface;
	struct replay_list *new_item, *prev_item;
	struct ifreq *ifr;
	struct ifconf ifc;
	struct ethtool_cmd cmd;
	int s, rc, i;
	int numif;

	// find number of interfaces.
	memset(&ifc,0,sizeof(ifc));
	ifc.ifc_ifcu.ifcu_req = NULL;
	ifc.ifc_len = 0;

	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
		replay_error("find_interface: unable to open socket");
	}

	if ((rc = ioctl(s, SIOCGIFCONF, &ifc)) < 0) {
		replay_error("find_interface: error on 1st ioctl");
	}

	numif = ifc.ifc_len / sizeof(*ifr);
	if ((ifr = malloc(ifc.ifc_len)) == NULL) {
		replay_error("find_interface: error on malloc of ifreq");
	}
	ifc.ifc_ifcu.ifcu_req = ifr;

	prev_item = NULL;

	for(i = 0; i < numif; i++) {

		if ((rc = ioctl(s, SIOCGIFCONF, &ifc)) < 0) {
				replay_error("find_interface: error on get IP ioctl");
		}
		struct ifreq *r = &ifr[i];

		iface = malloc(sizeof(*iface));
		memset(iface,0,sizeof(*iface));
		new_item = malloc(sizeof(*new_item));
		memset(new_item,0,sizeof(*new_item));

		iface->index = i;
		iface->ip.s_addr = ((struct sockaddr_in *)&r->ifr_addr)->sin_addr.s_addr;
		//iface->mtu = r->ifr_mtu;
		strcpy(iface->name,r->ifr_name);
		iface->ifr = malloc(sizeof(*iface->ifr));
		memcpy(iface->ifr,r,sizeof(*iface->ifr));

		new_item->next = prev_item;
		new_item->object = (void *) iface;

		// get interface speed / duplex settings
		r->ifr_data = (void *)&cmd;
		cmd.cmd = ETHTOOL_GSET; /* "Get settings" */
		if (ioctl(s, SIOCETHTOOL, r) == -1) {
			/* Unknown */
			iface->speed = -1L;
			iface->duplex = DUPLEX_UNKNOWN;
		} else {
			iface->speed = ethtool_cmd_speed(&cmd);
		    iface->duplex = cmd.duplex;
		}

		// get interface flags
		if (ioctl(s, SIOCGIFFLAGS, r) == -1) {
			iface->flags = 0;
		} else {
			iface->flags = r->ifr_flags;
		}

		// get interface netmask
		if (ioctl(s, SIOCGIFNETMASK, r) == -1) {
			replay_error("load_interfaces: error getting interface netmask");
		} else {
			iface->mask.s_addr = ((struct sockaddr_in *)&r->ifr_netmask)->sin_addr.s_addr;
		}

		// get interface MTU
		if (ioctl(s, SIOCGIFMTU, r) == -1) {
			replay_error("load_interfaces: error getting interface MTU");
		} else {
			iface->mtu = r->ifr_mtu;
		}

		prev_item = new_item;
	}

	close(s);

	return prev_item;
}
Ejemplo n.º 26
0
Archivo: sioc.c Proyecto: glandium/rr
int main(void) {
  int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
  struct ifreq* req;
  struct ifreq* eth_req;
  char name[PATH_MAX];
  int index;
  struct ethtool_cmd* etc;
  int err, ret;
  struct iwreq* wreq;
  char buf[1024];

  ALLOCATE_GUARD(req, 'a');
  ALLOCATE_GUARD(eth_req, 'a');
  get_ifconfig(sockfd, req, eth_req);
  strcpy(name, req->ifr_name);

  req->ifr_ifindex = -1;
  strcpy(req->ifr_name, name);
  ret = ioctl(sockfd, SIOCGIFINDEX, req);
  VERIFY_GUARD(req);
  atomic_printf("SIOCGIFINDEX(ret:%d): %s index is %d\n", ret, req->ifr_name,
                req->ifr_ifindex);
  test_assert(0 == ret);
  test_assert(req->ifr_ifindex != -1);
  index = req->ifr_ifindex;

  memset(&req->ifr_name, 0xff, sizeof(req->ifr_name));
  req->ifr_ifindex = index;
  ret = ioctl(sockfd, SIOCGIFNAME, req);
  VERIFY_GUARD(req);
  atomic_printf("SIOCGIFNAME(ret:%d): index %d(%s) name is %s\n", ret, index,
                name, req->ifr_name);
  test_assert(0 == ret);
  test_assert(!strcmp(name, req->ifr_name));

  GENERIC_REQUEST_BY_NAME(SIOCGIFFLAGS);
  atomic_printf("flags are %#x\n", req->ifr_flags);

  GENERIC_REQUEST_BY_NAME(SIOCGIFADDR);
  atomic_printf("addr is %s\n", sockaddr_name(&req->ifr_addr));

  GENERIC_REQUEST_BY_NAME(SIOCGIFDSTADDR);
  atomic_printf("addr is %s\n", sockaddr_name(&req->ifr_addr));

  GENERIC_REQUEST_BY_NAME(SIOCGIFBRDADDR);
  atomic_printf("addr is %s\n", sockaddr_name(&req->ifr_addr));

  GENERIC_REQUEST_BY_NAME(SIOCGIFNETMASK);
  atomic_printf("netmask is %s\n", sockaddr_name(&req->ifr_addr));

  GENERIC_REQUEST_BY_NAME(SIOCGIFMETRIC);
  atomic_printf("metric is %d\n", req->ifr_metric);

  memset(&req->ifr_metric, 0xff, sizeof(req->ifr_metric));
  ret = ioctl(sockfd, SIOCGIFMEM, req);
  VERIFY_GUARD(req);
  test_assert(-1 == ret && errno == ENOTTY);

  GENERIC_REQUEST_BY_NAME(SIOCGIFMTU);
  atomic_printf("MTU is %d\n", req->ifr_mtu);

  GENERIC_REQUEST_BY_NAME(SIOCGIFHWADDR);
  atomic_printf("hwaddr %s\n", sockaddr_hw_name(&req->ifr_addr));

  memset(&req->ifr_flags, 0xff, sizeof(req->ifr_flags));
  ret = ioctl(sockfd, SIOCGIFPFLAGS, req);
  VERIFY_GUARD(req);
  if (ret != -1 || errno != EINVAL) {
    test_assert(0 == ret);
    atomic_printf("SIOCGIFPFLAGS(ret:%d): %s flags are", ret, req->ifr_name);
    atomic_printf(" %#x\n", req->ifr_flags);
  }

  GENERIC_REQUEST_BY_NAME(SIOCGIFTXQLEN);
  atomic_printf("qlen is %d\n", req->ifr_qlen);

  ALLOCATE_GUARD(etc, 'b');
  etc->cmd = ETHTOOL_GSET;
  req->ifr_data = (char*)&etc;
  ret = ioctl(sockfd, SIOCETHTOOL, req);
  VERIFY_GUARD(req);
  VERIFY_GUARD(etc);
  err = errno;
  atomic_printf("SIOCETHTOOL(ret:%d): %s ethtool data: ", ret, req->ifr_name);
  if (-1 == ret) {
    atomic_printf("WARNING: %s doesn't appear to support SIOCETHTOOL\n", name);
    test_assert(EOPNOTSUPP == err || EPERM == err);
  } else {
    atomic_printf("speed:%#x duplex:%#x port:%#x physaddr:%#x, maxtxpkt:%u "
                  "maxrxpkt:%u ...\n",
                  ethtool_cmd_speed(etc), etc->duplex, etc->port,
                  etc->phy_address, etc->maxtxpkt, etc->maxrxpkt);
  }

  GENERIC_WIRELESS_PARAM_REQUEST_BY_NAME(SIOCGIWRATE, bitrate);

  GENERIC_WIRELESS_REQUEST_BY_NAME(SIOCGIWNAME,
                                   ("wireless protocol name:%s", wreq->u.name));

  GENERIC_WIRELESS_REQUEST_BY_NAME(SIOCGIWMODE,
                                   (" wireless mode:%d", wreq->u.mode));

  ALLOCATE_GUARD(wreq, 'e');
  strcpy(wreq->ifr_ifrn.ifrn_name, name);
  wreq->u.essid.length = sizeof(buf);
  wreq->u.essid.pointer = buf;
  wreq->u.essid.flags = 0;
  ret = ioctl(sockfd, SIOCGIWESSID, wreq);
  VERIFY_GUARD(wreq);
  err = errno;
  atomic_printf("SIOCGIWESSID(ret:%d): %s: ", ret, wreq->ifr_name);
  if (-1 == ret) {
    atomic_printf("WARNING: %s doesn't appear to be a wireless iface\n", name);
    test_assert(EOPNOTSUPP == err || EPERM == err || EINVAL == err);
  } else {
    atomic_printf("wireless ESSID:%s\n", buf);
  }

  GENERIC_WIRELESS_PARAM_REQUEST_BY_NAME(SIOCGIWSENS, sens);

  atomic_puts("EXIT-SUCCESS");
  return 0;
}
Ejemplo n.º 27
0
static int bnxt_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
	int rc = 0;
	struct bnxt *bp = netdev_priv(dev);
	struct bnxt_link_info *link_info = &bp->link_info;
	u32 speed, fw_advertising = 0;
	bool set_pause = false;

	if (BNXT_VF(bp))
		return rc;

	if (cmd->autoneg == AUTONEG_ENABLE) {
		if (link_info->media_type != PORT_PHY_QCFG_RESP_MEDIA_TYPE_TP) {
			netdev_err(dev, "Media type doesn't support autoneg\n");
			rc = -EINVAL;
			goto set_setting_exit;
		}
		if (cmd->advertising & ~(BNXT_ALL_COPPER_ETHTOOL_SPEED |
					 ADVERTISED_Autoneg |
					 ADVERTISED_TP |
					 ADVERTISED_Pause |
					 ADVERTISED_Asym_Pause)) {
			netdev_err(dev, "Unsupported advertising mask (adv: 0x%x)\n",
				   cmd->advertising);
			rc = -EINVAL;
			goto set_setting_exit;
		}
		fw_advertising = bnxt_get_fw_auto_link_speeds(cmd->advertising);
		if (fw_advertising & ~link_info->support_speeds) {
			netdev_err(dev, "Advertising parameters are not supported! (adv: 0x%x)\n",
				   cmd->advertising);
			rc = -EINVAL;
			goto set_setting_exit;
		}
		link_info->autoneg |= BNXT_AUTONEG_SPEED;
		if (!fw_advertising)
			link_info->advertising = link_info->support_speeds;
		else
			link_info->advertising = fw_advertising;
		/* any change to autoneg will cause link change, therefore the
		 * driver should put back the original pause setting in autoneg
		 */
		set_pause = true;
	} else {
		/* TODO: currently don't support half duplex */
		if (cmd->duplex == DUPLEX_HALF) {
			netdev_err(dev, "HALF DUPLEX is not supported!\n");
			rc = -EINVAL;
			goto set_setting_exit;
		}
		/* If received a request for an unknown duplex, assume full*/
		if (cmd->duplex == DUPLEX_UNKNOWN)
			cmd->duplex = DUPLEX_FULL;
		speed = ethtool_cmd_speed(cmd);
		link_info->req_link_speed = bnxt_get_fw_speed(dev, speed);
		link_info->req_duplex = BNXT_LINK_DUPLEX_FULL;
		link_info->autoneg &= ~BNXT_AUTONEG_SPEED;
		link_info->advertising = 0;
	}

	if (netif_running(dev))
		rc = bnxt_hwrm_set_link_setting(bp, set_pause);

set_setting_exit:
	return rc;
}
Ejemplo n.º 28
0
int ethtool_get_driver(int *fd, const char *ifname, char **ret) {
        struct ethtool_drvinfo ecmd = {
                .cmd = ETHTOOL_GDRVINFO
        };
        struct ifreq ifr = {
                .ifr_data = (void*) &ecmd
        };
        char *d;
        int r;

        if (*fd < 0) {
                r = ethtool_connect(fd);
                if (r < 0) {
                        log_warning("link_config: could not connect to ethtool: %s", strerror(-r));
                        return r;
                }
        }

        strscpy(ifr.ifr_name, IFNAMSIZ, ifname);

        r = ioctl(*fd, SIOCETHTOOL, &ifr);
        if (r < 0)
                return -errno;

        d = strdup(ecmd.driver);
        if (!d)
                return -ENOMEM;

        *ret = d;
        return 0;
}

int ethtool_set_speed(int *fd, const char *ifname, unsigned int speed, Duplex duplex)
{
        struct ethtool_cmd ecmd = {
                .cmd = ETHTOOL_GSET
        };
        struct ifreq ifr = {
                .ifr_data = (void*) &ecmd
        };
        bool need_update = false;
        int r;

        if (speed == 0 && duplex == _DUP_INVALID)
                return 0;

        if (*fd < 0) {
                r = ethtool_connect(fd);
                if (r < 0) {
                        log_warning("link_config: could not connect to ethtool: %s", strerror(-r));
                        return r;
                }
        }

        strscpy(ifr.ifr_name, IFNAMSIZ, ifname);

        r = ioctl(*fd, SIOCETHTOOL, &ifr);
        if (r < 0)
                return -errno;

        if (ethtool_cmd_speed(&ecmd) != speed) {
                ethtool_cmd_speed_set(&ecmd, speed);
                need_update = true;
        }

        switch (duplex) {
                case DUP_HALF:
                        if (ecmd.duplex != DUPLEX_HALF) {
                                ecmd.duplex = DUPLEX_HALF;
                                need_update = true;
                        }
                        break;
                case DUP_FULL:
                        if (ecmd.duplex != DUPLEX_FULL) {
                                ecmd.duplex = DUPLEX_FULL;
                                need_update = true;
                        }
                        break;
                default:
                        break;
        }

        if (need_update) {
                ecmd.cmd = ETHTOOL_SSET;

                r = ioctl(*fd, SIOCETHTOOL, &ifr);
                if (r < 0)
                        return -errno;
        }

        return 0;
}

int ethtool_set_wol(int *fd, const char *ifname, WakeOnLan wol) {
        struct ethtool_wolinfo ecmd = {
                .cmd = ETHTOOL_GWOL
        };
        struct ifreq ifr = {
                .ifr_data = (void*) &ecmd
        };
        bool need_update = false;
        int r;

        if (wol == _WOL_INVALID)
                return 0;

        if (*fd < 0) {
                r = ethtool_connect(fd);
                if (r < 0) {
                        log_warning("link_config: could not connect to ethtool: %s", strerror(-r));
                        return r;
                }
        }

        strscpy(ifr.ifr_name, IFNAMSIZ, ifname);

        r = ioctl(*fd, SIOCETHTOOL, &ifr);
        if (r < 0)
                return -errno;

        switch (wol) {
                case WOL_PHY:
                        if (ecmd.wolopts != WAKE_PHY) {
                                ecmd.wolopts = WAKE_PHY;
                                need_update = true;
                        }
                        break;
                case WOL_MAGIC:
                        if (ecmd.wolopts != WAKE_MAGIC) {
                                ecmd.wolopts = WAKE_MAGIC;
                                need_update = true;
                        }
                        break;
                case WOL_OFF:
                        if (ecmd.wolopts != 0) {
                                ecmd.wolopts = 0;
                                need_update = true;
                        }
                        break;
                default:
                        break;
        }

        if (need_update) {
                ecmd.cmd = ETHTOOL_SWOL;

                r = ioctl(*fd, SIOCETHTOOL, &ifr);
                if (r < 0)
                        return -errno;
        }

        return 0;
}
Ejemplo n.º 29
0
/**
 * mii_ethtool_sset - set settings that are specified in @ecmd
 * @mii: MII interface
 * @ecmd: requested ethtool_cmd
 *
 * Returns 0 for success, negative on error.
 */
int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
{
	struct net_device *dev = mii->dev;
	u32 speed = ethtool_cmd_speed(ecmd);

	if (speed != SPEED_10 &&
	    speed != SPEED_100 &&
	    speed != SPEED_1000)
		return -EINVAL;
	if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL)
		return -EINVAL;
	if (ecmd->port != PORT_MII)
		return -EINVAL;
	if (ecmd->transceiver != XCVR_INTERNAL)
		return -EINVAL;
	if (ecmd->phy_address != mii->phy_id)
		return -EINVAL;
	if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE)
		return -EINVAL;
	if ((speed == SPEED_1000) && (!mii->supports_gmii))
		return -EINVAL;

	/* ignore supported, maxtxpkt, maxrxpkt */

	if (ecmd->autoneg == AUTONEG_ENABLE) {
		u32 bmcr, advert, tmp;
		u32 advert2 = 0, tmp2 = 0;

		if ((ecmd->advertising & (ADVERTISED_10baseT_Half |
					  ADVERTISED_10baseT_Full |
					  ADVERTISED_100baseT_Half |
					  ADVERTISED_100baseT_Full |
					  ADVERTISED_1000baseT_Half |
					  ADVERTISED_1000baseT_Full)) == 0)
			return -EINVAL;

		/* advertise only what has been requested */
		advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE);
		tmp = advert & ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
		if (mii->supports_gmii) {
			advert2 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000);
			tmp2 = advert2 & ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL);
		}
		if (ecmd->advertising & ADVERTISED_10baseT_Half)
			tmp |= ADVERTISE_10HALF;
		if (ecmd->advertising & ADVERTISED_10baseT_Full)
			tmp |= ADVERTISE_10FULL;
		if (ecmd->advertising & ADVERTISED_100baseT_Half)
			tmp |= ADVERTISE_100HALF;
		if (ecmd->advertising & ADVERTISED_100baseT_Full)
			tmp |= ADVERTISE_100FULL;
		if (mii->supports_gmii) {
			if (ecmd->advertising & ADVERTISED_1000baseT_Half)
				tmp2 |= ADVERTISE_1000HALF;
			if (ecmd->advertising & ADVERTISED_1000baseT_Full)
				tmp2 |= ADVERTISE_1000FULL;
		}
		if (advert != tmp) {
			mii->mdio_write(dev, mii->phy_id, MII_ADVERTISE, tmp);
			mii->advertising = tmp;
		}
		if ((mii->supports_gmii) && (advert2 != tmp2))
			mii->mdio_write(dev, mii->phy_id, MII_CTRL1000, tmp2);

		/* turn on autonegotiation, and force a renegotiate */
		bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
		bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
		mii->mdio_write(dev, mii->phy_id, MII_BMCR, bmcr);

		mii->force_media = 0;
	} else {
		u32 bmcr, tmp;

		/* turn off auto negotiation, set speed and duplexity */
		bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
		tmp = bmcr & ~(BMCR_ANENABLE | BMCR_SPEED100 |
			       BMCR_SPEED1000 | BMCR_FULLDPLX);
		if (speed == SPEED_1000)
			tmp |= BMCR_SPEED1000;
		else if (speed == SPEED_100)
			tmp |= BMCR_SPEED100;
		if (ecmd->duplex == DUPLEX_FULL) {
			tmp |= BMCR_FULLDPLX;
			mii->full_duplex = 1;
		} else
			mii->full_duplex = 0;
		if (bmcr != tmp)
			mii->mdio_write(dev, mii->phy_id, MII_BMCR, tmp);

		mii->force_media = 1;
	}
	return 0;
}
Ejemplo n.º 30
0
bool
update_device_status( ether_device *device ) {
    assert( device != NULL );
    assert( strlen( device->name ) > 0 );

    int fd = socket( PF_INET, SOCK_DGRAM, 0 );
    if ( fd < 0 ) {
        char error_string[ ERROR_STRING_SIZE ];
        error( "Failed to open a socket ( ret = %d, errno = %s [%d] ).",
               fd, safe_strerror_r( errno, error_string, sizeof( error_string ) ), errno );
        return false;
    }

    struct ifreq ifr;
    memset( &ifr, 0, sizeof( ifr ) );
    strncpy( ifr.ifr_name, device->name, IFNAMSIZ );
    ifr.ifr_name[ IFNAMSIZ - 1 ] = '\0';

    struct ethtool_value ev;
    memset( &ev, 0, sizeof( struct ethtool_value ) );
    ev.cmd = ETHTOOL_GLINK;
    ifr.ifr_data = ( char * ) &ev;
    int ret = ioctl( fd, SIOCETHTOOL, &ifr );
    if ( ret == -1 ) {
        char error_string[ ERROR_STRING_SIZE ];
        error( "Failed to retrieve link status of %s ( ret = %d, error = %s [%d] ).",
               device->name, ret, safe_strerror_r( errno, error_string, sizeof( error_string ) ), errno );
        warn( "Assuming link is up ( device = %s ).", device->name );
        device->status.up = true;
    } else {
        if ( ev.data > 0 ) {
            device->status.up = true;
        } else {
            device->status.up = false;
        }
    }

    struct ethtool_cmd ec;
    memset( &ec, 0, sizeof( struct ethtool_cmd ) );
    if ( device->status.can_retrieve_link_status ) {
        ec.cmd = ETHTOOL_GSET;
        ifr.ifr_data = ( char * ) &ec;
        ret = ioctl( fd, SIOCETHTOOL, &ifr );
        if ( ret == -1 ) {
            char error_string[ ERROR_STRING_SIZE ];
            warn( "Failed to retrieve statuses of %s ( ret = %d, error = %s [%d] ).",
                  device->name, ret, safe_strerror_r( errno, error_string, sizeof( error_string ) ), errno );
            warn( "Assuming 100Mbps/Full Duplex/Twisted Pair link ( device = %s ).", device->name );
            device->status.can_retrieve_link_status = false;
        }
    }
    if ( !device->status.can_retrieve_link_status ) {
        ethtool_cmd_speed_set( &ec, SPEED_100 );
        ec.duplex = DUPLEX_FULL;
        ec.port = PORT_TP;
        ec.advertising = ADVERTISED_100baseT_Full | ADVERTISED_TP;
        ec.supported = SUPPORTED_100baseT_Full | SUPPORTED_TP;
    }

    struct ethtool_pauseparam ep;
    memset( &ep, 0, sizeof( struct ethtool_pauseparam ) );
    if ( device->status.can_retrieve_pause ) {
        ep.cmd = ETHTOOL_GPAUSEPARAM;
        ifr.ifr_data = ( char * ) &ep;
        ret = ioctl( fd, SIOCETHTOOL, &ifr );
        if ( ret == -1 ) {
            char error_string[ ERROR_STRING_SIZE ];
            warn( "Failed to retrieve pause parameters of %s ( ret = %d, error = %s [%d] ).",
                  device->name, ret, safe_strerror_r( errno, error_string, sizeof( error_string ) ), errno );
            warn( "Assuming pause is disabled ( device = %s ).", device->name );
            device->status.can_retrieve_pause = false;
        }
    }

    close( fd );

    device->status.curr = make_current_ofp_port_features( ethtool_cmd_speed( &ec ), ec.duplex, ec.port,
                          ec.autoneg, ep.rx_pause, ep.tx_pause );
    device->status.advertised = make_supported_ofp_port_features( ec.advertising );
    device->status.supported = make_supported_ofp_port_features( ec.supported );
    device->status.peer = device->status.curr; // FIMXE: how to know the correct value?
    device->status.curr_speed = 0; // Since we set curr flags, this field might be meaningless.
    device->status.max_speed = 0; // Since we set supported flags, this field might be meaningless.

    return true;
}