cxgb2.c

来自「linux 内核源代码」· C语言 代码 · 共 1,428 行 · 第 1/3 页

C
1,428
字号
	*data++ = s->TxMulticastFramesOK;	*data++ = s->TxBroadcastFramesOK;	*data++ = s->TxPauseFrames;	*data++ = s->TxFramesWithDeferredXmissions;	*data++ = s->TxLateCollisions;	*data++ = s->TxTotalCollisions;	*data++ = s->TxFramesAbortedDueToXSCollisions;	*data++ = s->TxUnderrun;	*data++ = s->TxLengthErrors;	*data++ = s->TxInternalMACXmitError;	*data++ = s->TxFramesWithExcessiveDeferral;	*data++ = s->TxFCSErrors;	*data++ = s->TxJumboFramesOK;	*data++ = s->TxJumboOctetsOK;	*data++ = s->RxOctetsOK;	*data++ = s->RxOctetsBad;	*data++ = s->RxUnicastFramesOK;	*data++ = s->RxMulticastFramesOK;	*data++ = s->RxBroadcastFramesOK;	*data++ = s->RxPauseFrames;	*data++ = s->RxFCSErrors;	*data++ = s->RxAlignErrors;	*data++ = s->RxSymbolErrors;	*data++ = s->RxDataErrors;	*data++ = s->RxSequenceErrors;	*data++ = s->RxRuntErrors;	*data++ = s->RxJabberErrors;	*data++ = s->RxInternalMACRcvError;	*data++ = s->RxInRangeLengthErrors;	*data++ = s->RxOutOfRangeLengthField;	*data++ = s->RxFrameTooLongErrors;	*data++ = s->RxJumboFramesOK;	*data++ = s->RxJumboOctetsOK;	*data++ = ss.rx_cso_good;	*data++ = ss.tx_cso;	*data++ = ss.tx_tso;	*data++ = ss.vlan_xtract;	*data++ = ss.vlan_insert;	*data++ = ss.tx_need_hdrroom;		*data++ = t->rx_drops;	*data++ = t->pure_rsps;	*data++ = t->unhandled_irqs;	*data++ = t->respQ_empty;	*data++ = t->respQ_overflow;	*data++ = t->freelistQ_empty;	*data++ = t->pkt_too_big;	*data++ = t->pkt_mismatch;	*data++ = t->cmdQ_full[0];	*data++ = t->cmdQ_full[1];	if (adapter->espi) {		const struct espi_intr_counts *e;		e = t1_espi_get_intr_counts(adapter->espi);		*data++ = e->DIP2_parity_err;		*data++ = e->DIP4_err;		*data++ = e->rx_drops;		*data++ = e->tx_drops;		*data++ = e->rx_ovflw;		*data++ = e->parity_err;	}}static inline void reg_block_dump(struct adapter *ap, void *buf,				  unsigned int start, unsigned int end){	u32 *p = buf + start;	for ( ; start <= end; start += sizeof(u32))		*p++ = readl(ap->regs + start);}static void get_regs(struct net_device *dev, struct ethtool_regs *regs,		     void *buf){	struct adapter *ap = dev->priv;	/*	 * Version scheme: bits 0..9: chip version, bits 10..15: chip revision	 */	regs->version = 2;	memset(buf, 0, T2_REGMAP_SIZE);	reg_block_dump(ap, buf, 0, A_SG_RESPACCUTIMER);	reg_block_dump(ap, buf, A_MC3_CFG, A_MC4_INT_CAUSE);	reg_block_dump(ap, buf, A_TPI_ADDR, A_TPI_PAR);	reg_block_dump(ap, buf, A_TP_IN_CONFIG, A_TP_TX_DROP_COUNT);	reg_block_dump(ap, buf, A_RAT_ROUTE_CONTROL, A_RAT_INTR_CAUSE);	reg_block_dump(ap, buf, A_CSPI_RX_AE_WM, A_CSPI_INTR_ENABLE);	reg_block_dump(ap, buf, A_ESPI_SCH_TOKEN0, A_ESPI_GOSTAT);	reg_block_dump(ap, buf, A_ULP_ULIMIT, A_ULP_PIO_CTRL);	reg_block_dump(ap, buf, A_PL_ENABLE, A_PL_CAUSE);	reg_block_dump(ap, buf, A_MC5_CONFIG, A_MC5_MASK_WRITE_CMD);}static int get_settings(struct net_device *dev, struct ethtool_cmd *cmd){	struct adapter *adapter = dev->priv;	struct port_info *p = &adapter->port[dev->if_port];	cmd->supported = p->link_config.supported;	cmd->advertising = p->link_config.advertising;	if (netif_carrier_ok(dev)) {		cmd->speed = p->link_config.speed;		cmd->duplex = p->link_config.duplex;	} else {		cmd->speed = -1;		cmd->duplex = -1;	}	cmd->port = (cmd->supported & SUPPORTED_TP) ? PORT_TP : PORT_FIBRE;	cmd->phy_address = p->phy->addr;	cmd->transceiver = XCVR_EXTERNAL;	cmd->autoneg = p->link_config.autoneg;	cmd->maxtxpkt = 0;	cmd->maxrxpkt = 0;	return 0;}static int speed_duplex_to_caps(int speed, int duplex){	int cap = 0;	switch (speed) {	case SPEED_10:		if (duplex == DUPLEX_FULL)			cap = SUPPORTED_10baseT_Full;		else			cap = SUPPORTED_10baseT_Half;		break;	case SPEED_100:		if (duplex == DUPLEX_FULL)			cap = SUPPORTED_100baseT_Full;		else			cap = SUPPORTED_100baseT_Half;		break;	case SPEED_1000:		if (duplex == DUPLEX_FULL)			cap = SUPPORTED_1000baseT_Full;		else			cap = SUPPORTED_1000baseT_Half;		break;	case SPEED_10000:		if (duplex == DUPLEX_FULL)			cap = SUPPORTED_10000baseT_Full;	}	return cap;}#define ADVERTISED_MASK (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | \		      ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | \		      ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full | \		      ADVERTISED_10000baseT_Full)static int set_settings(struct net_device *dev, struct ethtool_cmd *cmd){	struct adapter *adapter = dev->priv;	struct port_info *p = &adapter->port[dev->if_port];	struct link_config *lc = &p->link_config;	if (!(lc->supported & SUPPORTED_Autoneg))		return -EOPNOTSUPP;             /* can't change speed/duplex */	if (cmd->autoneg == AUTONEG_DISABLE) {		int cap = speed_duplex_to_caps(cmd->speed, cmd->duplex);		if (!(lc->supported & cap) || cmd->speed == SPEED_1000)			return -EINVAL;		lc->requested_speed = cmd->speed;		lc->requested_duplex = cmd->duplex;		lc->advertising = 0;	} else {		cmd->advertising &= ADVERTISED_MASK;		if (cmd->advertising & (cmd->advertising - 1))			cmd->advertising = lc->supported;		cmd->advertising &= lc->supported;		if (!cmd->advertising)			return -EINVAL;		lc->requested_speed = SPEED_INVALID;		lc->requested_duplex = DUPLEX_INVALID;		lc->advertising = cmd->advertising | ADVERTISED_Autoneg;	}	lc->autoneg = cmd->autoneg;	if (netif_running(dev))		t1_link_start(p->phy, p->mac, lc);	return 0;}static void get_pauseparam(struct net_device *dev,			   struct ethtool_pauseparam *epause){	struct adapter *adapter = dev->priv;	struct port_info *p = &adapter->port[dev->if_port];	epause->autoneg = (p->link_config.requested_fc & PAUSE_AUTONEG) != 0;	epause->rx_pause = (p->link_config.fc & PAUSE_RX) != 0;	epause->tx_pause = (p->link_config.fc & PAUSE_TX) != 0;}static int set_pauseparam(struct net_device *dev,			  struct ethtool_pauseparam *epause){	struct adapter *adapter = dev->priv;	struct port_info *p = &adapter->port[dev->if_port];	struct link_config *lc = &p->link_config;	if (epause->autoneg == AUTONEG_DISABLE)		lc->requested_fc = 0;	else if (lc->supported & SUPPORTED_Autoneg)		lc->requested_fc = PAUSE_AUTONEG;	else		return -EINVAL;	if (epause->rx_pause)		lc->requested_fc |= PAUSE_RX;	if (epause->tx_pause)		lc->requested_fc |= PAUSE_TX;	if (lc->autoneg == AUTONEG_ENABLE) {		if (netif_running(dev))			t1_link_start(p->phy, p->mac, lc);	} else {		lc->fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);		if (netif_running(dev))			p->mac->ops->set_speed_duplex_fc(p->mac, -1, -1,							 lc->fc);	}	return 0;}static u32 get_rx_csum(struct net_device *dev){	struct adapter *adapter = dev->priv;	return (adapter->flags & RX_CSUM_ENABLED) != 0;}static int set_rx_csum(struct net_device *dev, u32 data){	struct adapter *adapter = dev->priv;	if (data)		adapter->flags |= RX_CSUM_ENABLED;	else		adapter->flags &= ~RX_CSUM_ENABLED;	return 0;}static int set_tso(struct net_device *dev, u32 value){	struct adapter *adapter = dev->priv;	if (!(adapter->flags & TSO_CAPABLE))		return value ? -EOPNOTSUPP : 0;	return ethtool_op_set_tso(dev, value);}static void get_sge_param(struct net_device *dev, struct ethtool_ringparam *e){	struct adapter *adapter = dev->priv;	int jumbo_fl = t1_is_T1B(adapter) ? 1 : 0;	e->rx_max_pending = MAX_RX_BUFFERS;	e->rx_mini_max_pending = 0;	e->rx_jumbo_max_pending = MAX_RX_JUMBO_BUFFERS;	e->tx_max_pending = MAX_CMDQ_ENTRIES;	e->rx_pending = adapter->params.sge.freelQ_size[!jumbo_fl];	e->rx_mini_pending = 0;	e->rx_jumbo_pending = adapter->params.sge.freelQ_size[jumbo_fl];	e->tx_pending = adapter->params.sge.cmdQ_size[0];}static int set_sge_param(struct net_device *dev, struct ethtool_ringparam *e){	struct adapter *adapter = dev->priv;	int jumbo_fl = t1_is_T1B(adapter) ? 1 : 0;	if (e->rx_pending > MAX_RX_BUFFERS || e->rx_mini_pending ||	    e->rx_jumbo_pending > MAX_RX_JUMBO_BUFFERS ||	    e->tx_pending > MAX_CMDQ_ENTRIES ||	    e->rx_pending < MIN_FL_ENTRIES ||	    e->rx_jumbo_pending < MIN_FL_ENTRIES ||	    e->tx_pending < (adapter->params.nports + 1) * (MAX_SKB_FRAGS + 1))		return -EINVAL;	if (adapter->flags & FULL_INIT_DONE)		return -EBUSY;	adapter->params.sge.freelQ_size[!jumbo_fl] = e->rx_pending;	adapter->params.sge.freelQ_size[jumbo_fl] = e->rx_jumbo_pending;	adapter->params.sge.cmdQ_size[0] = e->tx_pending;	adapter->params.sge.cmdQ_size[1] = e->tx_pending > MAX_CMDQ1_ENTRIES ?		MAX_CMDQ1_ENTRIES : e->tx_pending;	return 0;}static int set_coalesce(struct net_device *dev, struct ethtool_coalesce *c){	struct adapter *adapter = dev->priv;	adapter->params.sge.rx_coalesce_usecs = c->rx_coalesce_usecs;	adapter->params.sge.coalesce_enable = c->use_adaptive_rx_coalesce;	adapter->params.sge.sample_interval_usecs = c->rate_sample_interval;	t1_sge_set_coalesce_params(adapter->sge, &adapter->params.sge);	return 0;}static int get_coalesce(struct net_device *dev, struct ethtool_coalesce *c){	struct adapter *adapter = dev->priv;	c->rx_coalesce_usecs = adapter->params.sge.rx_coalesce_usecs;	c->rate_sample_interval = adapter->params.sge.sample_interval_usecs;	c->use_adaptive_rx_coalesce = adapter->params.sge.coalesce_enable;	return 0;}static int get_eeprom_len(struct net_device *dev){	struct adapter *adapter = dev->priv;	return t1_is_asic(adapter) ? EEPROM_SIZE : 0;}#define EEPROM_MAGIC(ap) \	(PCI_VENDOR_ID_CHELSIO | ((ap)->params.chip_version << 16))static int get_eeprom(struct net_device *dev, struct ethtool_eeprom *e,		      u8 *data){	int i;	u8 buf[EEPROM_SIZE] __attribute__((aligned(4)));	struct adapter *adapter = dev->priv;	e->magic = EEPROM_MAGIC(adapter);	for (i = e->offset & ~3; i < e->offset + e->len; i += sizeof(u32))		t1_seeprom_read(adapter, i, (u32 *)&buf[i]);	memcpy(data, buf + e->offset, e->len);	return 0;}static const struct ethtool_ops t1_ethtool_ops = {	.get_settings      = get_settings,	.set_settings      = set_settings,	.get_drvinfo       = get_drvinfo,	.get_msglevel      = get_msglevel,	.set_msglevel      = set_msglevel,	.get_ringparam     = get_sge_param,	.set_ringparam     = set_sge_param,	.get_coalesce      = get_coalesce,	.set_coalesce      = set_coalesce,	.get_eeprom_len    = get_eeprom_len,	.get_eeprom        = get_eeprom,	.get_pauseparam    = get_pauseparam,	.set_pauseparam    = set_pauseparam,	.get_rx_csum       = get_rx_csum,	.set_rx_csum       = set_rx_csum,	.set_tx_csum       = ethtool_op_set_tx_csum,	.set_sg            = ethtool_op_set_sg,	.get_link          = ethtool_op_get_link,	.get_strings       = get_strings,	.get_sset_count	   = get_sset_count,	.get_ethtool_stats = get_stats,	.get_regs_len      = get_regs_len,	.get_regs          = get_regs,	.set_tso           = set_tso,};static int t1_ioctl(struct net_device *dev, struct ifreq *req, int cmd){	struct adapter *adapter = dev->priv;	struct mii_ioctl_data *data = if_mii(req);	switch (cmd) {	case SIOCGMIIPHY:		data->phy_id = adapter->port[dev->if_port].phy->addr;		/* FALLTHRU */	case SIOCGMIIREG: {		struct cphy *phy = adapter->port[dev->if_port].phy;		u32 val;		if (!phy->mdio_read)			return -EOPNOTSUPP;		phy->mdio_read(adapter, data->phy_id, 0, data->reg_num & 0x1f,			       &val);		data->val_out = val;		break;	}	case SIOCSMIIREG: {		struct cphy *phy = adapter->port[dev->if_port].phy;		if (!capable(CAP_NET_ADMIN))		    return -EPERM;		if (!phy->mdio_write)			return -EOPNOTSUPP;		phy->mdio_write(adapter, data->phy_id, 0, data->reg_num & 0x1f,			        data->val_in);		break;	}	default:		return -EOPNOTSUPP;	}	return 0;}static int t1_change_mtu(struct net_device *dev, int new_mtu){	int ret;	struct adapter *adapter = dev->priv;	struct cmac *mac = adapter->port[dev->if_port].mac;	if (!mac->ops->set_mtu)		return -EOPNOTSUPP;	if (new_mtu < 68)		return -EINVAL;	if ((ret = mac->ops->set_mtu(mac, new_mtu)))		return ret;	dev->mtu = new_mtu;	return 0;}static int t1_set_mac_addr(struct net_device *dev, void *p){	struct adapter *adapter = dev->priv;	struct cmac *mac = adapter->port[dev->if_port].mac;	struct sockaddr *addr = p;	if (!mac->ops->macaddress_set)		return -EOPNOTSUPP;	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);	mac->ops->macaddress_set(mac, dev->dev_addr);	return 0;}#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)static void vlan_rx_register(struct net_device *dev,				   struct vlan_group *grp){	struct adapter *adapter = dev->priv;	spin_lock_irq(&adapter->async_lock);	adapter->vlan_grp = grp;	t1_set_vlan_accel(adapter, grp != NULL);	spin_unlock_irq(&adapter->async_lock);}#endif#ifdef CONFIG_NET_POLL_CONTROLLERstatic void t1_netpoll(struct net_device *dev){	unsigned long flags;	struct adapter *adapter = dev->priv;	local_irq_save(flags);	t1_interrupt(adapter->pdev->irq, adapter);	local_irq_restore(flags);}#endif/* * Periodic accumulation of MAC statistics.  This is used only if the MAC * does not have any other way to prevent stats counter overflow. */static void mac_stats_task(struct work_struct *work){	int i;	struct adapter *adapter =		container_of(work, struct adapter, stats_update_task.work);	for_each_port(adapter, i) {

⌨️ 快捷键说明

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