⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kcompat_ethtool.c

📁 DELL755 Intel 网卡驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
static int ethtool_set_tx_csum(struct net_device *dev, char *useraddr){	struct ethtool_value edata;	if (!ethtool_ops->set_tx_csum)		return -EOPNOTSUPP;	if (copy_from_user(&edata, useraddr, sizeof(edata)))		return -EFAULT;	return ethtool_ops->set_tx_csum(dev, edata.data);}static int ethtool_get_sg(struct net_device *dev, char *useraddr){	struct ethtool_value edata = { ETHTOOL_GSG };	if (!ethtool_ops->get_sg)		return -EOPNOTSUPP;	edata.data = ethtool_ops->get_sg(dev);	if (copy_to_user(useraddr, &edata, sizeof(edata)))		return -EFAULT;	return 0;}static int ethtool_set_sg(struct net_device *dev, char *useraddr){	struct ethtool_value edata;	if (!ethtool_ops->set_sg)		return -EOPNOTSUPP;	if (copy_from_user(&edata, useraddr, sizeof(edata)))		return -EFAULT;	return ethtool_ops->set_sg(dev, edata.data);}static int ethtool_get_tso(struct net_device *dev, char *useraddr){	struct ethtool_value edata = { ETHTOOL_GTSO };	if (!ethtool_ops->get_tso)		return -EOPNOTSUPP;	edata.data = ethtool_ops->get_tso(dev);	if (copy_to_user(useraddr, &edata, sizeof(edata)))		return -EFAULT;	return 0;}static int ethtool_set_tso(struct net_device *dev, char *useraddr){	struct ethtool_value edata;	if (!ethtool_ops->set_tso)		return -EOPNOTSUPP;	if (copy_from_user(&edata, useraddr, sizeof(edata)))		return -EFAULT;	return ethtool_ops->set_tso(dev, edata.data);}static int ethtool_self_test(struct net_device *dev, char *useraddr){	struct ethtool_test test;	struct ethtool_ops *ops = ethtool_ops;	u64 *data;	int ret;	if (!ops->self_test || !ops->self_test_count)		return -EOPNOTSUPP;	if (copy_from_user(&test, useraddr, sizeof(test)))		return -EFAULT;	test.len = ops->self_test_count(dev);	data = kmalloc(test.len * sizeof(u64), GFP_USER);	if (!data)		return -ENOMEM;	ops->self_test(dev, &test, data);	ret = -EFAULT;	if (copy_to_user(useraddr, &test, sizeof(test)))		goto out;	useraddr += sizeof(test);	if (copy_to_user(useraddr, data, test.len * sizeof(u64)))		goto out;	ret = 0;out:	kfree(data);	return ret;}static int ethtool_get_strings(struct net_device *dev, void *useraddr){	struct ethtool_gstrings gstrings;	struct ethtool_ops *ops = ethtool_ops;	u8 *data;	int ret;	if (!ops->get_strings)		return -EOPNOTSUPP;	if (copy_from_user(&gstrings, useraddr, sizeof(gstrings)))		return -EFAULT;	switch (gstrings.string_set) {	case ETH_SS_TEST:		if (!ops->self_test_count)			return -EOPNOTSUPP;		gstrings.len = ops->self_test_count(dev);		break;	case ETH_SS_STATS:		if (!ops->get_stats_count)			return -EOPNOTSUPP;		gstrings.len = ops->get_stats_count(dev);		break;	default:		return -EINVAL;	}	data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER);	if (!data)		return -ENOMEM;	ops->get_strings(dev, gstrings.string_set, data);	ret = -EFAULT;	if (copy_to_user(useraddr, &gstrings, sizeof(gstrings)))		goto out;	useraddr += sizeof(gstrings);	if (copy_to_user(useraddr, data, gstrings.len * ETH_GSTRING_LEN))		goto out;	ret = 0;out:	kfree(data);	return ret;}static int ethtool_phys_id(struct net_device *dev, void *useraddr){	struct ethtool_value id;	if (!ethtool_ops->phys_id)		return -EOPNOTSUPP;	if (copy_from_user(&id, useraddr, sizeof(id)))		return -EFAULT;	return ethtool_ops->phys_id(dev, id.data);}static int ethtool_get_stats(struct net_device *dev, void *useraddr){	struct ethtool_stats stats;	struct ethtool_ops *ops = ethtool_ops;	u64 *data;	int ret;	if (!ops->get_ethtool_stats || !ops->get_stats_count)		return -EOPNOTSUPP;	if (copy_from_user(&stats, useraddr, sizeof(stats)))		return -EFAULT;	stats.n_stats = ops->get_stats_count(dev);	data = kmalloc(stats.n_stats * sizeof(u64), GFP_USER);	if (!data)		return -ENOMEM;	ops->get_ethtool_stats(dev, &stats, data);	ret = -EFAULT;	if (copy_to_user(useraddr, &stats, sizeof(stats)))		goto out;	useraddr += sizeof(stats);	if (copy_to_user(useraddr, data, stats.n_stats * sizeof(u64)))		goto out;	ret = 0;out:	kfree(data);	return ret;}/* The main entry point in this file.  Called from net/core/dev.c */#define ETHTOOL_OPS_COMPATint ethtool_ioctl(struct ifreq *ifr){	struct net_device *dev = __dev_get_by_name(ifr->ifr_name);	void *useraddr = (void *) ifr->ifr_data;	u32 ethcmd;	/*	 * XXX: This can be pushed down into the ethtool_* handlers that	 * need it.  Keep existing behavior for the moment.	 */	if (!capable(CAP_NET_ADMIN))		return -EPERM;	if (!dev || !netif_device_present(dev))		return -ENODEV;	if (copy_from_user(&ethcmd, useraddr, sizeof (ethcmd)))		return -EFAULT;	switch (ethcmd) {	case ETHTOOL_GSET:		return ethtool_get_settings(dev, useraddr);	case ETHTOOL_SSET:		return ethtool_set_settings(dev, useraddr);	case ETHTOOL_GDRVINFO:		return ethtool_get_drvinfo(dev, useraddr);	case ETHTOOL_GREGS:		return ethtool_get_regs(dev, useraddr);	case ETHTOOL_GWOL:		return ethtool_get_wol(dev, useraddr);	case ETHTOOL_SWOL:		return ethtool_set_wol(dev, useraddr);	case ETHTOOL_GMSGLVL:		return ethtool_get_msglevel(dev, useraddr);	case ETHTOOL_SMSGLVL:		return ethtool_set_msglevel(dev, useraddr);	case ETHTOOL_NWAY_RST:		return ethtool_nway_reset(dev);	case ETHTOOL_GLINK:		return ethtool_get_link(dev, useraddr);	case ETHTOOL_GEEPROM:		return ethtool_get_eeprom(dev, useraddr);	case ETHTOOL_SEEPROM:		return ethtool_set_eeprom(dev, useraddr);	case ETHTOOL_GCOALESCE:		return ethtool_get_coalesce(dev, useraddr);	case ETHTOOL_SCOALESCE:		return ethtool_set_coalesce(dev, useraddr);	case ETHTOOL_GRINGPARAM:		return ethtool_get_ringparam(dev, useraddr);	case ETHTOOL_SRINGPARAM:		return ethtool_set_ringparam(dev, useraddr);	case ETHTOOL_GPAUSEPARAM:		return ethtool_get_pauseparam(dev, useraddr);	case ETHTOOL_SPAUSEPARAM:		return ethtool_set_pauseparam(dev, useraddr);	case ETHTOOL_GRXCSUM:		return ethtool_get_rx_csum(dev, useraddr);	case ETHTOOL_SRXCSUM:		return ethtool_set_rx_csum(dev, useraddr);	case ETHTOOL_GTXCSUM:		return ethtool_get_tx_csum(dev, useraddr);	case ETHTOOL_STXCSUM:		return ethtool_set_tx_csum(dev, useraddr);	case ETHTOOL_GSG:		return ethtool_get_sg(dev, useraddr);	case ETHTOOL_SSG:		return ethtool_set_sg(dev, useraddr);	case ETHTOOL_GTSO:		return ethtool_get_tso(dev, useraddr);	case ETHTOOL_STSO:		return ethtool_set_tso(dev, useraddr);	case ETHTOOL_TEST:		return ethtool_self_test(dev, useraddr);	case ETHTOOL_GSTRINGS:		return ethtool_get_strings(dev, useraddr);	case ETHTOOL_PHYS_ID:		return ethtool_phys_id(dev, useraddr);	case ETHTOOL_GSTATS:		return ethtool_get_stats(dev, useraddr);	default:		return -EOPNOTSUPP;	}	return -EOPNOTSUPP;}#define mii_if_info _kc_mii_if_infostruct _kc_mii_if_info {	int phy_id;	int advertising;	int phy_id_mask;	int reg_num_mask;	unsigned int full_duplex : 1;	/* is full duplex? */	unsigned int force_media : 1;	/* is autoneg. disabled? */	struct net_device *dev;	int (*mdio_read) (struct net_device *dev, int phy_id, int location);	void (*mdio_write) (struct net_device *dev, int phy_id, int location, int val);};struct ethtool_cmd;struct mii_ioctl_data;#undef mii_link_ok#define mii_link_ok _kc_mii_link_ok#undef mii_nway_restart#define mii_nway_restart _kc_mii_nway_restart#undef mii_ethtool_gset#define mii_ethtool_gset _kc_mii_ethtool_gset#undef mii_ethtool_sset#define mii_ethtool_sset _kc_mii_ethtool_sset#undef mii_check_link#define mii_check_link _kc_mii_check_link#undef generic_mii_ioctl#define generic_mii_ioctl _kc_generic_mii_ioctlextern int _kc_mii_link_ok (struct mii_if_info *mii);extern int _kc_mii_nway_restart (struct mii_if_info *mii);extern int _kc_mii_ethtool_gset(struct mii_if_info *mii,                                struct ethtool_cmd *ecmd);extern int _kc_mii_ethtool_sset(struct mii_if_info *mii,                                struct ethtool_cmd *ecmd);extern void _kc_mii_check_link (struct mii_if_info *mii);extern int _kc_generic_mii_ioctl(struct mii_if_info *mii_if,                                 struct mii_ioctl_data *mii_data, int cmd,                                 unsigned int *duplex_changed);struct _kc_pci_dev_ext {	struct pci_dev *dev;	void *pci_drvdata;	struct pci_driver *driver;};struct _kc_net_dev_ext {	struct net_device *dev;	unsigned int carrier;};/**************************************//* mii support */int _kc_mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd){	struct net_device *dev = mii->dev;	u32 advert, bmcr, lpa, nego;	ecmd->supported =	    (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |	     SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |	     SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII);	/* only supports twisted-pair */	ecmd->port = PORT_MII;	/* only supports internal transceiver */	ecmd->transceiver = XCVR_INTERNAL;	/* this isn't fully supported at higher layers */	ecmd->phy_address = mii->phy_id;	ecmd->advertising = ADVERTISED_TP | ADVERTISED_MII;	advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE);	if (advert & ADVERTISE_10HALF)		ecmd->advertising |= ADVERTISED_10baseT_Half;	if (advert & ADVERTISE_10FULL)		ecmd->advertising |= ADVERTISED_10baseT_Full;	if (advert & ADVERTISE_100HALF)		ecmd->advertising |= ADVERTISED_100baseT_Half;	if (advert & ADVERTISE_100FULL)		ecmd->advertising |= ADVERTISED_100baseT_Full;	bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);	lpa = mii->mdio_read(dev, mii->phy_id, MII_LPA);	if (bmcr & BMCR_ANENABLE) {		ecmd->advertising |= ADVERTISED_Autoneg;		ecmd->autoneg = AUTONEG_ENABLE;				nego = mii_nway_result(advert & lpa);		if (nego == LPA_100FULL || nego == LPA_100HALF)			ecmd->speed = SPEED_100;		else			ecmd->speed = SPEED_10;		if (nego == LPA_100FULL || nego == LPA_10FULL) {			ecmd->duplex = DUPLEX_FULL;			mii->full_duplex = 1;		} else {			ecmd->duplex = DUPLEX_HALF;			mii->full_duplex = 0;		}	} else {		ecmd->autoneg = AUTONEG_DISABLE;		ecmd->speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10;		ecmd->duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;	}	/* ignore maxtxpkt, maxrxpkt for now */	return 0;}int _kc_mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd){	struct net_device *dev = mii->dev;	if (ecmd->speed != SPEED_10 && ecmd->speed != SPEED_100)		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;				  	/* ignore supported, maxtxpkt, maxrxpkt */		if (ecmd->autoneg == AUTONEG_ENABLE) {		u32 bmcr, advert, tmp;		if ((ecmd->advertising & (ADVERTISED_10baseT_Half |					  ADVERTISED_10baseT_Full |					  ADVERTISED_100baseT_Half |					  ADVERTISED_100baseT_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 (ADVERTISED_10baseT_Half)			tmp |= ADVERTISE_10HALF;		if (ADVERTISED_10baseT_Full)			tmp |= ADVERTISE_10FULL;		if (ADVERTISED_100baseT_Half)			tmp |= ADVERTISE_100HALF;		if (ADVERTISED_100baseT_Full)			tmp |= ADVERTISE_100FULL;		if (advert != tmp) {			mii->mdio_write(dev, mii->phy_id, MII_ADVERTISE, tmp);			mii->advertising = tmp;		}				/* 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_FULLDPLX);		if (ecmd->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;}int _kc_mii_link_ok (struct mii_if_info *mii){	/* first, a dummy read, needed to latch some MII phys */	mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR);	if (mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR) & BMSR_LSTATUS)		return 1;	return 0;}int _kc_mii_nway_restart (struct mii_if_info *mii){	int bmcr;	int r = -EINVAL;	/* if autoneg is off, it's an error */	bmcr = mii->mdio_read(mii->dev, mii->phy_id, MII_BMCR);	if (bmcr & BMCR_ANENABLE) {		bmcr |= BMCR_ANRESTART;		mii->mdio_write(mii->dev, mii->phy_id, MII_BMCR, bmcr);		r = 0;	}	return r;}void _kc_mii_check_link (struct mii_if_info *mii){	int cur_link = mii_link_ok(mii);	int prev_link = netif_carrier_ok(mii->dev);	if (cur_link && !prev_link)		netif_carrier_on(mii->dev);	else if (prev_link && !cur_link)		netif_carrier_off(mii->dev);}int _kc_generic_mii_ioctl(struct mii_if_info *mii_if,                          struct mii_ioctl_data *mii_data, int cmd,                          unsigned int *duplex_chg_out){	int rc = 0;	unsigned int duplex_changed = 0;	if (duplex_chg_out)		*duplex_chg_out = 0;	mii_data->phy_id &= mii_if->phy_id_mask;	mii_data->reg_num &= mii_if->reg_num_mask;	switch(cmd) {	case SIOCDEVPRIVATE:	/* binary compat, remove in 2.5 */	case SIOCGMIIPHY:		mii_data->phy_id = mii_if->phy_id;		/* fall through */	case SIOCDEVPRIVATE + 1:/* binary compat, remove in 2.5 */	case SIOCGMIIREG:		mii_data->val_out =			mii_if->mdio_read(mii_if->dev, mii_data->phy_id,					  mii_data->reg_num);		break;	case SIOCDEVPRIVATE + 2:/* binary compat, remove in 2.5 */	case SIOCSMIIREG: {		u16 val = mii_data->val_in;		if (!capable(CAP_NET_ADMIN))			return -EPERM;		if (mii_data->phy_id == mii_if->phy_id) {			switch(mii_data->reg_num) {			case MII_BMCR: {				unsigned int new_duplex = 0;				if (val & (BMCR_RESET|BMCR_ANENABLE))					mii_if->force_media = 0;				else					mii_if->force_media = 1;				if (mii_if->force_media &&				    (val & BMCR_FULLDPLX))					new_duplex = 1;				if (mii_if->full_duplex != new_duplex) {					duplex_changed = 1;					mii_if->full_duplex = new_duplex;				}				break;			}			case MII_ADVERTISE:				mii_if->advertising = val;				break;			default:				/* do nothing */				break;			}		}		mii_if->mdio_write(mii_if->dev, mii_data->phy_id,				   mii_data->reg_num, val);		break;	}	default:		rc = -EOPNOTSUPP;		break;	}	if ((rc == 0) && (duplex_chg_out) && (duplex_changed))		*duplex_chg_out = 1;	return rc;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -