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

📄 ipoib_ib.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
	addr = dma_map_single(priv->ca->dma_device, skb->data, skb->len,			      DMA_TO_DEVICE);	pci_unmap_addr_set(tx_req, mapping, addr);	if (unlikely(post_send(priv, priv->tx_head & (IPOIB_TX_RING_SIZE - 1),			       address->ah, qpn, addr, skb->len))) {		ipoib_warn(priv, "post_send failed\n");		++priv->stats.tx_errors;		dma_unmap_single(priv->ca->dma_device, addr, skb->len,				 DMA_TO_DEVICE);		dev_kfree_skb_any(skb);	} else {		dev->trans_start = jiffies;		address->last_send = priv->tx_head;		++priv->tx_head;		if (priv->tx_head - priv->tx_tail == IPOIB_TX_RING_SIZE) {			ipoib_dbg(priv, "TX ring full, stopping kernel net queue\n");			netif_stop_queue(dev);		}	}}static void __ipoib_reap_ah(struct net_device *dev){	struct ipoib_dev_priv *priv = netdev_priv(dev);	struct ipoib_ah *ah, *tah;	LIST_HEAD(remove_list);	spin_lock_irq(&priv->lock);	list_for_each_entry_safe(ah, tah, &priv->dead_ahs, list)		if ((int) priv->tx_tail - (int) ah->last_send >= 0) {			list_del(&ah->list);			list_add_tail(&ah->list, &remove_list);		}	spin_unlock_irq(&priv->lock);	list_for_each_entry_safe(ah, tah, &remove_list, list) {		ipoib_dbg(priv, "Reaping ah %p\n", ah->ah);		ib_destroy_ah(ah->ah);		kfree(ah);	}}void ipoib_reap_ah(void *dev_ptr){	struct net_device *dev = dev_ptr;	struct ipoib_dev_priv *priv = netdev_priv(dev);	__ipoib_reap_ah(dev);	if (!test_bit(IPOIB_STOP_REAPER, &priv->flags))		queue_delayed_work(ipoib_workqueue, &priv->ah_reap_task, HZ);}int ipoib_ib_dev_open(struct net_device *dev){	struct ipoib_dev_priv *priv = netdev_priv(dev);	int ret;	ret = ipoib_init_qp(dev);	if (ret) {		ipoib_warn(priv, "ipoib_init_qp returned %d\n", ret);		return -1;	}	ret = ipoib_ib_post_receives(dev);	if (ret) {		ipoib_warn(priv, "ipoib_ib_post_receives returned %d\n", ret);		return -1;	}	clear_bit(IPOIB_STOP_REAPER, &priv->flags);	queue_delayed_work(ipoib_workqueue, &priv->ah_reap_task, HZ);	return 0;}int ipoib_ib_dev_up(struct net_device *dev){	struct ipoib_dev_priv *priv = netdev_priv(dev);	set_bit(IPOIB_FLAG_OPER_UP, &priv->flags);	return ipoib_mcast_start_thread(dev);}int ipoib_ib_dev_down(struct net_device *dev){	struct ipoib_dev_priv *priv = netdev_priv(dev);	ipoib_dbg(priv, "downing ib_dev\n");	clear_bit(IPOIB_FLAG_OPER_UP, &priv->flags);	netif_carrier_off(dev);	/* Shutdown the P_Key thread if still active */	if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) {		down(&pkey_sem);		set_bit(IPOIB_PKEY_STOP, &priv->flags);		cancel_delayed_work(&priv->pkey_task);		up(&pkey_sem);		flush_workqueue(ipoib_workqueue);	}	ipoib_mcast_stop_thread(dev, 1);	/*	 * Flush the multicast groups first so we stop any multicast joins. The	 * completion thread may have already died and we may deadlock waiting	 * for the completion thread to finish some multicast joins.	 */	ipoib_mcast_dev_flush(dev);	/* Delete broadcast and local addresses since they will be recreated */	ipoib_mcast_dev_down(dev);	ipoib_flush_paths(dev);	return 0;}static int recvs_pending(struct net_device *dev){	struct ipoib_dev_priv *priv = netdev_priv(dev);	int pending = 0;	int i;	for (i = 0; i < IPOIB_RX_RING_SIZE; ++i)		if (priv->rx_ring[i].skb)			++pending;	return pending;}int ipoib_ib_dev_stop(struct net_device *dev){	struct ipoib_dev_priv *priv = netdev_priv(dev);	struct ib_qp_attr qp_attr;	unsigned long begin;	struct ipoib_tx_buf *tx_req;	int i;	/*	 * Move our QP to the error state and then reinitialize in	 * when all work requests have completed or have been flushed.	 */	qp_attr.qp_state = IB_QPS_ERR;	if (ib_modify_qp(priv->qp, &qp_attr, IB_QP_STATE))		ipoib_warn(priv, "Failed to modify QP to ERROR state\n");	/* Wait for all sends and receives to complete */	begin = jiffies;	while (priv->tx_head != priv->tx_tail || recvs_pending(dev)) {		if (time_after(jiffies, begin + 5 * HZ)) {			ipoib_warn(priv, "timing out; %d sends %d receives not completed\n",				   priv->tx_head - priv->tx_tail, recvs_pending(dev));			/*			 * assume the HW is wedged and just free up			 * all our pending work requests.			 */			while ((int) priv->tx_tail - (int) priv->tx_head < 0) {				tx_req = &priv->tx_ring[priv->tx_tail &							(IPOIB_TX_RING_SIZE - 1)];				dma_unmap_single(priv->ca->dma_device,						 pci_unmap_addr(tx_req, mapping),						 tx_req->skb->len,						 DMA_TO_DEVICE);				dev_kfree_skb_any(tx_req->skb);				++priv->tx_tail;			}			for (i = 0; i < IPOIB_RX_RING_SIZE; ++i)				if (priv->rx_ring[i].skb) {					dma_unmap_single(priv->ca->dma_device,							 pci_unmap_addr(&priv->rx_ring[i],									mapping),							 IPOIB_BUF_SIZE,							 DMA_FROM_DEVICE);					dev_kfree_skb_any(priv->rx_ring[i].skb);					priv->rx_ring[i].skb = NULL;				}			goto timeout;		}		msleep(1);	}	ipoib_dbg(priv, "All sends and receives done.\n");timeout:	qp_attr.qp_state = IB_QPS_RESET;	if (ib_modify_qp(priv->qp, &qp_attr, IB_QP_STATE))		ipoib_warn(priv, "Failed to modify QP to RESET state\n");	/* Wait for all AHs to be reaped */	set_bit(IPOIB_STOP_REAPER, &priv->flags);	cancel_delayed_work(&priv->ah_reap_task);	flush_workqueue(ipoib_workqueue);	begin = jiffies;	while (!list_empty(&priv->dead_ahs)) {		__ipoib_reap_ah(dev);		if (time_after(jiffies, begin + HZ)) {			ipoib_warn(priv, "timing out; will leak address handles\n");			break;		}		msleep(1);	}	return 0;}int ipoib_ib_dev_init(struct net_device *dev, struct ib_device *ca, int port){	struct ipoib_dev_priv *priv = netdev_priv(dev);	priv->ca = ca;	priv->port = port;	priv->qp = NULL;	if (ipoib_transport_dev_init(dev, ca)) {		printk(KERN_WARNING "%s: ipoib_transport_dev_init failed\n", ca->name);		return -ENODEV;	}	if (dev->flags & IFF_UP) {		if (ipoib_ib_dev_open(dev)) {			ipoib_transport_dev_cleanup(dev);			return -ENODEV;		}	}	return 0;}void ipoib_ib_dev_flush(void *_dev){	struct net_device *dev = (struct net_device *)_dev;	struct ipoib_dev_priv *priv = netdev_priv(dev), *cpriv;	if (!test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags))		return;	ipoib_dbg(priv, "flushing\n");	ipoib_ib_dev_down(dev);	/*	 * The device could have been brought down between the start and when	 * we get here, don't bring it back up if it's not configured up	 */	if (test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags))		ipoib_ib_dev_up(dev);	down(&priv->vlan_mutex);	/* Flush any child interfaces too */	list_for_each_entry(cpriv, &priv->child_intfs, list)		ipoib_ib_dev_flush(&cpriv->dev);	up(&priv->vlan_mutex);}void ipoib_ib_dev_cleanup(struct net_device *dev){	struct ipoib_dev_priv *priv = netdev_priv(dev);	ipoib_dbg(priv, "cleaning up ib_dev\n");	ipoib_mcast_stop_thread(dev, 1);	/* Delete the broadcast address and the local address */	ipoib_mcast_dev_down(dev);	ipoib_transport_dev_cleanup(dev);}/* * Delayed P_Key Assigment Interim Support * * The following is initial implementation of delayed P_Key assigment * mechanism. It is using the same approach implemented for the multicast * group join. The single goal of this implementation is to quickly address * Bug #2507. This implementation will probably be removed when the P_Key * change async notification is available. */static void ipoib_pkey_dev_check_presence(struct net_device *dev){	struct ipoib_dev_priv *priv = netdev_priv(dev);	u16 pkey_index = 0;	if (ib_find_cached_pkey(priv->ca, priv->port, priv->pkey, &pkey_index))		clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);	else		set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);}void ipoib_pkey_poll(void *dev_ptr){	struct net_device *dev = dev_ptr;	struct ipoib_dev_priv *priv = netdev_priv(dev);	ipoib_pkey_dev_check_presence(dev);	if (test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags))		ipoib_open(dev);	else {		down(&pkey_sem);		if (!test_bit(IPOIB_PKEY_STOP, &priv->flags))			queue_delayed_work(ipoib_workqueue,					   &priv->pkey_task,					   HZ);		up(&pkey_sem);	}}int ipoib_pkey_dev_delay_open(struct net_device *dev){	struct ipoib_dev_priv *priv = netdev_priv(dev);	/* Look for the interface pkey value in the IB Port P_Key table and */	/* set the interface pkey assigment flag                            */	ipoib_pkey_dev_check_presence(dev);	/* P_Key value not assigned yet - start polling */	if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) {		down(&pkey_sem);		clear_bit(IPOIB_PKEY_STOP, &priv->flags);		queue_delayed_work(ipoib_workqueue,				   &priv->pkey_task,				   HZ);		up(&pkey_sem);		return 1;	}	return 0;}

⌨️ 快捷键说明

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