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

📄 1005.tango2enet.patch

📁 sm86xx内核源包括补丁( GPL )的
💻 PATCH
📖 第 1 页 / 共 5 页
字号:
+			}+		}+	}++        return IRQ_HANDLED;+}++/*+ * start/stop dma engine+ */+static __inline void enet_start_dma(struct tango2_enet_priv *priv)+{+	/* send start command to rx & tx dma */+	enet_writel(ENET_DMA_CR, CR_SF | CR_SR | CR_ST);+}++static __inline void enet_stop_dma(struct tango2_enet_priv *priv)+{+	unsigned long val;++	/* send stop command to rx & tx dma */+	enet_writel(ENET_DMA_CR, 0);++	/* wait for them to reach stopped state, should not be long */+	do {+		udelay(1);+		val = enet_readl(ENET_DMA_SR);+		if ((val & SR_TPS) && (val & SR_RPS))+			break;+	} while (1);+}++/*+ * reconfigure mac for new link state+ */+static void enet_link_reconfigure(struct net_device *dev)+{+	struct tango2_enet_priv *priv;+	unsigned long val;++	priv = netdev_priv(dev);++	if (dev->flags & IFF_UP)+		enet_stop_dma(priv);++	/* reflect duplex status in dma register */+	spin_lock(&priv->maccr_lock);+	val = enet_readl(ENET_MAC_MACCR);+	if (priv->mii.full_duplex)+		val |= MACCR_F;+	else+		val &= ~MACCR_F;+	enet_writel(ENET_MAC_MACCR, val);+	spin_unlock(&priv->maccr_lock);++	if (dev->flags & IFF_UP)+		enet_start_dma(priv);+}++/*+ * link check timer callback+ */+static void enet_link_check(unsigned long data)+{+	struct net_device *dev;+	struct tango2_enet_priv *priv;+	int ret;++	dev = (struct net_device *)data;+	priv = netdev_priv(dev);++	/* check for duplex change */+	spin_lock(&priv->mii_lock);+	ret = mii_check_media(&priv->mii, 1, 0);+	spin_unlock(&priv->mii_lock);++	if (ret)+		enet_link_reconfigure(dev);++	/* reschedule timer */+	priv->link_check_timer.expires = jiffies + LINK_CHECK_TIMER_FREQ;+	add_timer(&priv->link_check_timer);+}++/*+ * program given mac address in hw registers+ */+static int enet_set_mac_address(struct net_device *dev, void *addr)+{+	unsigned long hi_mac, low_mac;++	/* to make it safe, we won't do this while running */+	if (netif_running(dev))+		return -EBUSY;++	memcpy(dev->dev_addr, addr, ETH_ALEN);++	hi_mac = (dev->dev_addr[5] << 8) | dev->dev_addr[4];+	low_mac = (dev->dev_addr[3] << 24)| (dev->dev_addr[2] << 16) |+		(dev->dev_addr[1] << 8) | dev->dev_addr[0];++	enet_writel(ENET_MAC_MACAHR, hi_mac);+	enet_writel(ENET_MAC_MACALR, low_mac);++	return 0;+}++/*+ * update hash table to reflect new device multicast address list+ */+static void enet_set_multicast_list(struct net_device *dev)+{+	struct tango2_enet_priv *priv;+	struct dev_mc_list *mclist;+	unsigned long val;+	uint32_t mc_filter[2];+	int i;++	priv = netdev_priv(dev);++	/* the link check timer might change MACCR, we need to protect+	 * against it */+	spin_lock_bh(&priv->maccr_lock);+	val = enet_readl(ENET_MAC_MACCR);++        if (dev->flags & IFF_PROMISC) {+                val |= MACCR_PR | MACCR_PM;+	} else {+		val &= ~MACCR_PR;+		/* if we want all multicast or if address count is too+		 * high, don't try to compute hash value */+		if (dev->mc_count > 64 || dev->flags & IFF_ALLMULTI) {+			val |= MACCR_PM;+		}+	}+	enet_writel(ENET_MAC_MACCR, val);+	spin_unlock_bh(&priv->maccr_lock);++	/* we  don't  need  to  update  hash  table  if  we  pass  all+	 * multicast */+	if (val & MACCR_PM)+		return;++	mc_filter[0] = mc_filter[1] = 0;+	mclist = dev->mc_list;++	for (i = 0; i < dev->mc_count; i++) {+		unsigned int n;+		char *addr;++		addr = mclist->dmi_addr;+		mclist = mclist->next;+		if (!(*addr & 1))+			continue;++		n = ether_crc(ETH_ALEN, addr) >> 26;+		mc_filter[n >> 5] |= 1 << (n & 31);+	}++	enet_writel(ENET_MAC_MALR, mc_filter[0]);+	enet_writel(ENET_MAC_MAHR, mc_filter[1]);+}++/*+ * open callback+ */+static int enet_open(struct net_device *dev)+{+	struct tango2_enet_priv *priv;+	unsigned long val;++	priv = netdev_priv(dev);++	/* check link */+	if (mii_check_media(&priv->mii, 1, 1))+		enet_link_reconfigure(dev);++	/* start rx & tx dma engine */+	enet_start_dma(priv);++	/* enable mac rx & tx */+	val = enet_readl(ENET_MAC_MACCR);+	val |= MACCR_TE | MACCR_RE;+	enet_writel(ENET_MAC_MACCR, val);++	/*+	 * clear & enable interrupts, we want:+	 * - receive complete+	 * - transmit complete+	 */+	enet_writel(ENET_DMA_SR, SR_NIS | SR_R | SR_T);+	enet_enable_interrupts(priv, 0);++	/* start link check & tx reclaim timer */+	priv->link_check_timer.expires = jiffies + LINK_CHECK_TIMER_FREQ;+	add_timer(&priv->link_check_timer);++	priv->tx_reclaim_timer.expires = jiffies + TX_RECLAIM_TIMER_FREQ;+	add_timer(&priv->tx_reclaim_timer);++	/* and finally start tx queue */+	netif_start_queue(dev);++	return 0;+}++/*+ * stop callback+ */+static int enet_stop(struct net_device *dev)+{+	struct tango2_enet_priv *priv;+	unsigned long val;+	int i;++	priv = netdev_priv(dev);++	/* stop link timer */+	del_timer_sync(&priv->link_check_timer);++	/* stop tx queue */+	netif_stop_queue(dev);++	/* wait for all tx buffers to be reclaimed */+	while (priv->free_tx_desc_count != ENET_TX_DESC_COUNT)+		yield();++	/* stop tx reclaim timer */+	del_timer_sync(&priv->tx_reclaim_timer);++	/* disable all interrupts */+	enet_disable_interrupts(priv, 0);++	/* stop dma */+	enet_stop_dma(priv);++	/* stop mac rx & tx */+	val = enet_readl(ENET_MAC_MACCR);+	val &= ~(MACCR_TE | MACCR_RE);+	enet_writel(ENET_MAC_MACCR, val);++	/* while we were stopping it,  the rx dma may have filled some+	 * buffer, consider it junk and rearm all descriptor */+	for (i = 0; i < ENET_RX_DESC_COUNT; i++) {+		volatile struct enet_rx_desc *rx;++		rx = &priv->rx_descs[i];+		rx->rdes0 = RDES0_OWN;+	}++	/* make  the dma engine  restarts at  first descriptor  in the+	 * list */+	enet_writel(ENET_DMA_RBAR, PHYSADDR(priv->rx_descs));+	enet_writel(ENET_DMA_TBAR, PHYSADDR(priv->tx_descs));+	priv->dirty_tx_desc = priv->next_tx_desc = 0;+	priv->last_rx_desc = 0;++	return 0;+}++/*+ * get_stats callback+ */+static struct net_device_stats *enet_get_stats(struct net_device *dev)+{+	struct tango2_enet_priv *priv;++	priv = netdev_priv(dev);++	return &priv->stats;+}++/*+ * ethtool callbacks+ */+static int enet_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)+{+	struct tango2_enet_priv *priv;+	int ret;++	priv = netdev_priv(dev);++	spin_lock_bh(&priv->mii_lock);+	ret = mii_ethtool_gset(&priv->mii, cmd);+	spin_unlock_bh(&priv->mii_lock);++	return ret;+}++static int enet_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)+{+	struct tango2_enet_priv *priv;+	int ret;++	priv = netdev_priv(dev);++	spin_lock_bh(&priv->mii_lock);+	ret = mii_ethtool_sset(&priv->mii, cmd);+	spin_unlock_bh(&priv->mii_lock);++	return ret;+}++static int enet_nway_reset(struct net_device *dev)+{+	struct tango2_enet_priv *priv;+	int ret;++	priv = netdev_priv(dev);++	spin_lock_bh(&priv->mii_lock);+	ret = mii_nway_restart(&priv->mii);+	spin_unlock_bh(&priv->mii_lock);++	return ret;+}++static u32 enet_get_link(struct net_device *dev)+{+	struct tango2_enet_priv *priv;+	int ret;++	priv = netdev_priv(dev);++	spin_lock_bh(&priv->mii_lock);+	ret = mii_link_ok(&priv->mii);+	spin_unlock_bh(&priv->mii_lock);++	return ret;+}++static struct ethtool_ops enet_ethtool_ops = {+	.get_settings		= enet_get_settings,+	.set_settings		= enet_set_settings,+	.nway_reset		= enet_nway_reset,+	.get_link		= enet_get_link,+};++static int enet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)+{+	struct tango2_enet_priv *priv;+	int ret;++	priv = netdev_priv(dev);++	spin_lock_bh(&priv->mii);+	ret = generic_mii_ioctl(&priv->mii, if_mii(rq), cmd, NULL);+	spin_unlock_bh(&priv->mii);++	return ret;+}++/*+ * dma ring allocation is done here+ */+static int enet_dma_init(struct tango2_enet_priv *priv)+{+	unsigned int size;+	int i;++	/*+	 * allocate rx descriptor list & rx buffers+	 *+	 * We allocate  skb now and fill buffer  with their addresses,+	 * note that we reserve 4 bytes at beginning of data buffer to+	 * store skb address.+	 *+	 */+	size = ENET_RX_DESC_COUNT * sizeof (struct enet_rx_desc);+	if (!(priv->rx_descs_cached = kmalloc(size, GFP_KERNEL)))+		return -ENOMEM;+	priv->rx_descs = (volatile struct enet_rx_desc *)+		CACHE_TO_NONCACHE((unsigned long)priv->rx_descs_cached);+	dma_cache_wback_inv((unsigned long)priv->rx_descs_cached, size);++	/*+	 * initialize all rx descs+	 */+	for (i = 0; i < ENET_RX_DESC_COUNT; i++) {+		volatile struct enet_rx_desc *rx;+		struct sk_buff *skb;++		rx = &priv->rx_descs[i];+		rx->rdes0 = RDES0_OWN;++		rx->rdes1 = RDES1_RBS2(0) | RDES1_RBS1(RX_BUF_SIZE);+		if (i == ENET_RX_DESC_COUNT - 1)+			rx->rdes1 |= RDES1_RER;++		skb = dev_alloc_skb(RX_BUF_SIZE + SKB_RESERVE_SIZE);+		if (!skb)+			return -ENOMEM;++		skb_reserve(skb, SKB_RESERVE_SIZE);+		rx->rdes2 = PHYSADDR(skb->data);+		rx->rdes3 = 0;++		dma_cache_inv((unsigned long)skb->data, RX_BUF_SIZE);+		priv->rx_skbs[i] = skb;+	}+	priv->last_rx_desc = 0;++	/*+	 * allocate tx descriptor list+	 *+	 * We allocate  only the descriptor list and  prepare them for+	 * further use. When tx is needed, we will set the right flags+	 * and kick the dma.+	 */+	size = ENET_TX_DESC_COUNT * sizeof (struct enet_tx_desc);+	if (!(priv->tx_descs_cached = kmalloc(size, GFP_KERNEL)))+		return -ENOMEM;+	priv->tx_descs = (volatile struct enet_tx_desc *)+		CACHE_TO_NONCACHE((unsigned long)priv->tx_descs_cached);+	dma_cache_wback_inv((unsigned long)priv->tx_descs_cached, size);++	/*+	 * initialize tx descs+	 */+	for (i = 0; i < ENET_TX_DESC_COUNT; i++) {+		volatile struct enet_tx_desc *tx;++		tx = &priv->tx_descs[i];+		tx->tdes0 = 0;+		tx->tdes1 = 0;+		if (i == ENET_TX_DESC_COUNT - 1)+			tx->tdes1 |= TDES1_TER;+		tx->tdes2 = 0;+		tx->tdes3 = 0;+	}+	priv->dirty_tx_desc = priv->next_tx_desc = 0;+	priv->free_tx_desc_count = ENET_TX_DESC_COUNT;++	/*+	 * write rx desc list & tx desc list addresses in registers+	 */+	enet_writel(ENET_DMA_RBAR, PHYSADDR(priv->rx_descs));+	enet_writel(ENET_DMA_TBAR, PHYSADDR(priv->tx_descs));++	return 0;+}++/*+ * free  all dma rings  memory, called  at uninit  time or  when error+ * occurs at init time+ */+static void enet_dma_free(struct tango2_enet_priv *priv)+{+	int i;++	/* note: kfree(NULL) is ok */+	kfree(priv->rx_descs_cached);+	kfree(priv->tx_descs_cached);++	/* note: kfree_skb(NULL) is _not_ ok */+	for (i = 0; i < ENET_RX_DESC_COUNT; i++) {+		if (priv->rx_skbs[i])+			kfree_skb(priv->rx_skbs[i]);+	}+

⌨️ 快捷键说明

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