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

📄 ipoib_ib.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 2 页
字号:
			ib_destroy_ah(ah->ah);			kfree(ah);		}	spin_unlock(&priv->lock);	spin_unlock_irq(&priv->tx_lock);}void ipoib_reap_ah(struct work_struct *work){	struct ipoib_dev_priv *priv =		container_of(work, struct ipoib_dev_priv, ah_reap_task.work);	struct net_device *dev = priv->dev;	__ipoib_reap_ah(dev);	if (!test_bit(IPOIB_STOP_REAPER, &priv->flags))		queue_delayed_work(ipoib_workqueue, &priv->ah_reap_task,				   round_jiffies_relative(HZ));}int ipoib_ib_dev_open(struct net_device *dev){	struct ipoib_dev_priv *priv = netdev_priv(dev);	int ret;	if (ib_find_pkey(priv->ca, priv->port, priv->pkey, &priv->pkey_index)) {		ipoib_warn(priv, "P_Key 0x%04x not found\n", priv->pkey);		clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);		return -1;	}	set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);	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);		ipoib_ib_dev_stop(dev, 1);		return -1;	}	ret = ipoib_cm_dev_open(dev);	if (ret) {		ipoib_warn(priv, "ipoib_cm_dev_open returned %d\n", ret);		ipoib_ib_dev_stop(dev, 1);		return -1;	}	clear_bit(IPOIB_STOP_REAPER, &priv->flags);	queue_delayed_work(ipoib_workqueue, &priv->ah_reap_task,			   round_jiffies_relative(HZ));	set_bit(IPOIB_FLAG_INITIALIZED, &priv->flags);	return 0;}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);}int ipoib_ib_dev_up(struct net_device *dev){	struct ipoib_dev_priv *priv = netdev_priv(dev);	ipoib_pkey_dev_check_presence(dev);	if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) {		ipoib_dbg(priv, "PKEY is not assigned.\n");		return 0;	}	set_bit(IPOIB_FLAG_OPER_UP, &priv->flags);	return ipoib_mcast_start_thread(dev);}int ipoib_ib_dev_down(struct net_device *dev, int flush){	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)) {		mutex_lock(&pkey_mutex);		set_bit(IPOIB_PKEY_STOP, &priv->flags);		cancel_delayed_work(&priv->pkey_poll_task);		mutex_unlock(&pkey_mutex);		if (flush)			flush_workqueue(ipoib_workqueue);	}	ipoib_mcast_stop_thread(dev, flush);	ipoib_mcast_dev_flush(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_recvq_size; ++i)		if (priv->rx_ring[i].skb)			++pending;	return pending;}void ipoib_drain_cq(struct net_device *dev){	struct ipoib_dev_priv *priv = netdev_priv(dev);	int i, n;	do {		n = ib_poll_cq(priv->cq, IPOIB_NUM_WC, priv->ibwc);		for (i = 0; i < n; ++i) {			/*			 * Convert any successful completions to flush			 * errors to avoid passing packets up the			 * stack after bringing the device down.			 */			if (priv->ibwc[i].status == IB_WC_SUCCESS)				priv->ibwc[i].status = IB_WC_WR_FLUSH_ERR;			if (priv->ibwc[i].wr_id & IPOIB_OP_RECV) {				if (priv->ibwc[i].wr_id & IPOIB_OP_CM)					ipoib_cm_handle_rx_wc(dev, priv->ibwc + i);				else					ipoib_ib_handle_rx_wc(dev, priv->ibwc + i);			} else {				if (priv->ibwc[i].wr_id & IPOIB_OP_CM)					ipoib_cm_handle_tx_wc(dev, priv->ibwc + i);				else					ipoib_ib_handle_tx_wc(dev, priv->ibwc + i);			}		}	} while (n == IPOIB_NUM_WC);}int ipoib_ib_dev_stop(struct net_device *dev, int flush){	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;	clear_bit(IPOIB_FLAG_INITIALIZED, &priv->flags);	ipoib_cm_dev_stop(dev);	/*	 * 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_sendq_size - 1)];				ib_dma_unmap_single(priv->ca,						    tx_req->mapping,						    tx_req->skb->len,						    DMA_TO_DEVICE);				dev_kfree_skb_any(tx_req->skb);				++priv->tx_tail;				--priv->tx_outstanding;			}			for (i = 0; i < ipoib_recvq_size; ++i) {				struct ipoib_rx_buf *rx_req;				rx_req = &priv->rx_ring[i];				if (!rx_req->skb)					continue;				ib_dma_unmap_single(priv->ca,						    rx_req->mapping,						    IPOIB_BUF_SIZE,						    DMA_FROM_DEVICE);				dev_kfree_skb_any(rx_req->skb);				rx_req->skb = NULL;			}			goto timeout;		}		ipoib_drain_cq(dev);		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);	if (flush)		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);	}	ib_req_notify_cq(priv->cq, IB_CQ_NEXT_COMP);	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;}static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv, int pkey_event){	struct ipoib_dev_priv *cpriv;	struct net_device *dev = priv->dev;	u16 new_index;	mutex_lock(&priv->vlan_mutex);	/*	 * Flush any child interfaces too -- they might be up even if	 * the parent is down.	 */	list_for_each_entry(cpriv, &priv->child_intfs, list)		__ipoib_ib_dev_flush(cpriv, pkey_event);	mutex_unlock(&priv->vlan_mutex);	if (!test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags)) {		ipoib_dbg(priv, "Not flushing - IPOIB_FLAG_INITIALIZED not set.\n");		return;	}	if (!test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) {		ipoib_dbg(priv, "Not flushing - IPOIB_FLAG_ADMIN_UP not set.\n");		return;	}	if (pkey_event) {		if (ib_find_pkey(priv->ca, priv->port, priv->pkey, &new_index)) {			clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);			ipoib_ib_dev_down(dev, 0);			ipoib_pkey_dev_delay_open(dev);			return;		}		set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);		/* restart QP only if P_Key index is changed */		if (new_index == priv->pkey_index) {			ipoib_dbg(priv, "Not flushing - P_Key index not changed.\n");			return;		}		priv->pkey_index = new_index;	}	ipoib_dbg(priv, "flushing\n");	ipoib_ib_dev_down(dev, 0);	if (pkey_event) {		ipoib_ib_dev_stop(dev, 0);		ipoib_ib_dev_open(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);		ipoib_mcast_restart_task(&priv->restart_task);	}}void ipoib_ib_dev_flush(struct work_struct *work){	struct ipoib_dev_priv *priv =		container_of(work, struct ipoib_dev_priv, flush_task);	ipoib_dbg(priv, "Flushing %s\n", priv->dev->name);	__ipoib_ib_dev_flush(priv, 0);}void ipoib_pkey_event(struct work_struct *work){	struct ipoib_dev_priv *priv =		container_of(work, struct ipoib_dev_priv, pkey_event_task);	ipoib_dbg(priv, "Flushing %s and restarting its QP\n", priv->dev->name);	__ipoib_ib_dev_flush(priv, 1);}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);	ipoib_mcast_dev_flush(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. */void ipoib_pkey_poll(struct work_struct *work){	struct ipoib_dev_priv *priv =		container_of(work, struct ipoib_dev_priv, pkey_poll_task.work);	struct net_device *dev = priv->dev;	ipoib_pkey_dev_check_presence(dev);	if (test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags))		ipoib_open(dev);	else {		mutex_lock(&pkey_mutex);		if (!test_bit(IPOIB_PKEY_STOP, &priv->flags))			queue_delayed_work(ipoib_workqueue,					   &priv->pkey_poll_task,					   HZ);		mutex_unlock(&pkey_mutex);	}}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)) {		mutex_lock(&pkey_mutex);		clear_bit(IPOIB_PKEY_STOP, &priv->flags);		queue_delayed_work(ipoib_workqueue,				   &priv->pkey_poll_task,				   HZ);		mutex_unlock(&pkey_mutex);		return 1;	}	return 0;}

⌨️ 快捷键说明

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