Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0534c8cb authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband:
  RDMA/nes: Add support for new SFP+ PHY
  RDMA/nes: Add wide_ppm_offset parm for switch compatibility
  RDMA/nes: Fix SFP+ PHY initialization
  RDMA/nes: Fix nes_nic_cm_xmit() error handling
  RDMA/nes: Fix error handling issues
  RDMA/nes: Fix incorrect casts on 32-bit architectures
  IPoIB: Document newish features
  RDMA/cma: Create cm id even when IB port is down
  RDMA/cma: Use rate from IPoIB broadcast when joining IPoIB multicast groups
  IPoIB: Avoid free_netdev() BUG when destroying a child interface
  mlx4_core: Don't leak mailbox for SET_PORT on Ethernet ports
  RDMA/cxgb3: Release dependent resources only when endpoint memory is freed.
  RDMA/cxgb3: Handle EEH events
  IB/mlx4: Use pgprot_writecombine() for BlueFlame pages
parents 54f93b74 07306c0b
Loading
Loading
Loading
Loading
+45 −0
Original line number Original line Diff line number Diff line
@@ -24,6 +24,49 @@ Partitions and P_Keys
  The P_Key for any interface is given by the "pkey" file, and the
  The P_Key for any interface is given by the "pkey" file, and the
  main interface for a subinterface is in "parent."
  main interface for a subinterface is in "parent."


Datagram vs Connected modes

  The IPoIB driver supports two modes of operation: datagram and
  connected.  The mode is set and read through an interface's
  /sys/class/net/<intf name>/mode file.

  In datagram mode, the IB UD (Unreliable Datagram) transport is used
  and so the interface MTU has is equal to the IB L2 MTU minus the
  IPoIB encapsulation header (4 bytes).  For example, in a typical IB
  fabric with a 2K MTU, the IPoIB MTU will be 2048 - 4 = 2044 bytes.

  In connected mode, the IB RC (Reliable Connected) transport is used.
  Connected mode is to takes advantage of the connected nature of the
  IB transport and allows an MTU up to the maximal IP packet size of
  64K, which reduces the number of IP packets needed for handling
  large UDP datagrams, TCP segments, etc and increases the performance
  for large messages.

  In connected mode, the interface's UD QP is still used for multicast
  and communication with peers that don't support connected mode. In
  this case, RX emulation of ICMP PMTU packets is used to cause the
  networking stack to use the smaller UD MTU for these neighbours.

Stateless offloads

  If the IB HW supports IPoIB stateless offloads, IPoIB advertises
  TCP/IP checksum and/or Large Send (LSO) offloading capability to the
  network stack.

  Large Receive (LRO) offloading is also implemented and may be turned
  on/off using ethtool calls.  Currently LRO is supported only for
  checksum offload capable devices.

  Stateless offloads are supported only in datagram mode.  

Interrupt moderation

  If the underlying IB device supports CQ event moderation, one can
  use ethtool to set interrupt mitigation parameters and thus reduce
  the overhead incurred by handling interrupts.  The main code path of
  IPoIB doesn't use events for TX completion signaling so only RX
  moderation is supported.

Debugging Information
Debugging Information


  By compiling the IPoIB driver with CONFIG_INFINIBAND_IPOIB_DEBUG set
  By compiling the IPoIB driver with CONFIG_INFINIBAND_IPOIB_DEBUG set
@@ -55,3 +98,5 @@ References
    http://ietf.org/rfc/rfc4391.txt 
    http://ietf.org/rfc/rfc4391.txt 
  IP over InfiniBand (IPoIB) Architecture (RFC 4392)
  IP over InfiniBand (IPoIB) Architecture (RFC 4392)
    http://ietf.org/rfc/rfc4392.txt 
    http://ietf.org/rfc/rfc4392.txt 
  IP over InfiniBand: Connected Mode (RFC 4755)
    http://ietf.org/rfc/rfc4755.txt
+31 −14
Original line number Original line Diff line number Diff line
@@ -297,21 +297,25 @@ static void cma_detach_from_dev(struct rdma_id_private *id_priv)
	id_priv->cma_dev = NULL;
	id_priv->cma_dev = NULL;
}
}


static int cma_set_qkey(struct ib_device *device, u8 port_num,
static int cma_set_qkey(struct rdma_id_private *id_priv)
			enum rdma_port_space ps,
			struct rdma_dev_addr *dev_addr, u32 *qkey)
{
{
	struct ib_sa_mcmember_rec rec;
	struct ib_sa_mcmember_rec rec;
	int ret = 0;
	int ret = 0;


	switch (ps) {
	if (id_priv->qkey)
		return 0;

	switch (id_priv->id.ps) {
	case RDMA_PS_UDP:
	case RDMA_PS_UDP:
		*qkey = RDMA_UDP_QKEY;
		id_priv->qkey = RDMA_UDP_QKEY;
		break;
		break;
	case RDMA_PS_IPOIB:
	case RDMA_PS_IPOIB:
		ib_addr_get_mgid(dev_addr, &rec.mgid);
		ib_addr_get_mgid(&id_priv->id.route.addr.dev_addr, &rec.mgid);
		ret = ib_sa_get_mcmember_rec(device, port_num, &rec.mgid, &rec);
		ret = ib_sa_get_mcmember_rec(id_priv->id.device,
		*qkey = be32_to_cpu(rec.qkey);
					     id_priv->id.port_num, &rec.mgid,
					     &rec);
		if (!ret)
			id_priv->qkey = be32_to_cpu(rec.qkey);
		break;
		break;
	default:
	default:
		break;
		break;
@@ -341,11 +345,6 @@ static int cma_acquire_dev(struct rdma_id_private *id_priv)
		ret = ib_find_cached_gid(cma_dev->device, &gid,
		ret = ib_find_cached_gid(cma_dev->device, &gid,
					 &id_priv->id.port_num, NULL);
					 &id_priv->id.port_num, NULL);
		if (!ret) {
		if (!ret) {
			ret = cma_set_qkey(cma_dev->device,
					   id_priv->id.port_num,
					   id_priv->id.ps, dev_addr,
					   &id_priv->qkey);
			if (!ret)
			cma_attach_to_dev(id_priv, cma_dev);
			cma_attach_to_dev(id_priv, cma_dev);
			break;
			break;
		}
		}
@@ -578,6 +577,10 @@ static int cma_ib_init_qp_attr(struct rdma_id_private *id_priv,
	*qp_attr_mask = IB_QP_STATE | IB_QP_PKEY_INDEX | IB_QP_PORT;
	*qp_attr_mask = IB_QP_STATE | IB_QP_PKEY_INDEX | IB_QP_PORT;


	if (cma_is_ud_ps(id_priv->id.ps)) {
	if (cma_is_ud_ps(id_priv->id.ps)) {
		ret = cma_set_qkey(id_priv);
		if (ret)
			return ret;

		qp_attr->qkey = id_priv->qkey;
		qp_attr->qkey = id_priv->qkey;
		*qp_attr_mask |= IB_QP_QKEY;
		*qp_attr_mask |= IB_QP_QKEY;
	} else {
	} else {
@@ -2201,6 +2204,12 @@ static int cma_sidr_rep_handler(struct ib_cm_id *cm_id,
			event.status = ib_event->param.sidr_rep_rcvd.status;
			event.status = ib_event->param.sidr_rep_rcvd.status;
			break;
			break;
		}
		}
		ret = cma_set_qkey(id_priv);
		if (ret) {
			event.event = RDMA_CM_EVENT_ADDR_ERROR;
			event.status = -EINVAL;
			break;
		}
		if (id_priv->qkey != rep->qkey) {
		if (id_priv->qkey != rep->qkey) {
			event.event = RDMA_CM_EVENT_UNREACHABLE;
			event.event = RDMA_CM_EVENT_UNREACHABLE;
			event.status = -EINVAL;
			event.status = -EINVAL;
@@ -2480,10 +2489,14 @@ static int cma_send_sidr_rep(struct rdma_id_private *id_priv,
			     const void *private_data, int private_data_len)
			     const void *private_data, int private_data_len)
{
{
	struct ib_cm_sidr_rep_param rep;
	struct ib_cm_sidr_rep_param rep;
	int ret;


	memset(&rep, 0, sizeof rep);
	memset(&rep, 0, sizeof rep);
	rep.status = status;
	rep.status = status;
	if (status == IB_SIDR_SUCCESS) {
	if (status == IB_SIDR_SUCCESS) {
		ret = cma_set_qkey(id_priv);
		if (ret)
			return ret;
		rep.qp_num = id_priv->qp_num;
		rep.qp_num = id_priv->qp_num;
		rep.qkey = id_priv->qkey;
		rep.qkey = id_priv->qkey;
	}
	}
@@ -2713,6 +2726,10 @@ static int cma_join_ib_multicast(struct rdma_id_private *id_priv,
		    IB_SA_MCMEMBER_REC_FLOW_LABEL |
		    IB_SA_MCMEMBER_REC_FLOW_LABEL |
		    IB_SA_MCMEMBER_REC_TRAFFIC_CLASS;
		    IB_SA_MCMEMBER_REC_TRAFFIC_CLASS;


	if (id_priv->id.ps == RDMA_PS_IPOIB)
		comp_mask |= IB_SA_MCMEMBER_REC_RATE |
			     IB_SA_MCMEMBER_REC_RATE_SELECTOR;

	mc->multicast.ib = ib_sa_join_multicast(&sa_client, id_priv->id.device,
	mc->multicast.ib = ib_sa_join_multicast(&sa_client, id_priv->id.device,
						id_priv->id.port_num, &rec,
						id_priv->id.port_num, &rec,
						comp_mask, GFP_KERNEL,
						comp_mask, GFP_KERNEL,
+5 −5
Original line number Original line Diff line number Diff line
@@ -152,7 +152,7 @@ static int cxio_hal_clear_qp_ctx(struct cxio_rdev *rdev_p, u32 qpid)
	sge_cmd = qpid << 8 | 3;
	sge_cmd = qpid << 8 | 3;
	wqe->sge_cmd = cpu_to_be64(sge_cmd);
	wqe->sge_cmd = cpu_to_be64(sge_cmd);
	skb->priority = CPL_PRIORITY_CONTROL;
	skb->priority = CPL_PRIORITY_CONTROL;
	return (cxgb3_ofld_send(rdev_p->t3cdev_p, skb));
	return iwch_cxgb3_ofld_send(rdev_p->t3cdev_p, skb);
}
}


int cxio_create_cq(struct cxio_rdev *rdev_p, struct t3_cq *cq)
int cxio_create_cq(struct cxio_rdev *rdev_p, struct t3_cq *cq)
@@ -571,7 +571,7 @@ static int cxio_hal_init_ctrl_qp(struct cxio_rdev *rdev_p)
	     (unsigned long long) rdev_p->ctrl_qp.dma_addr,
	     (unsigned long long) rdev_p->ctrl_qp.dma_addr,
	     rdev_p->ctrl_qp.workq, 1 << T3_CTRL_QP_SIZE_LOG2);
	     rdev_p->ctrl_qp.workq, 1 << T3_CTRL_QP_SIZE_LOG2);
	skb->priority = CPL_PRIORITY_CONTROL;
	skb->priority = CPL_PRIORITY_CONTROL;
	return (cxgb3_ofld_send(rdev_p->t3cdev_p, skb));
	return iwch_cxgb3_ofld_send(rdev_p->t3cdev_p, skb);
err:
err:
	kfree_skb(skb);
	kfree_skb(skb);
	return err;
	return err;
@@ -701,7 +701,7 @@ static int __cxio_tpt_op(struct cxio_rdev *rdev_p, u32 reset_tpt_entry,
	u32 stag_idx;
	u32 stag_idx;
	u32 wptr;
	u32 wptr;


	if (rdev_p->flags)
	if (cxio_fatal_error(rdev_p))
		return -EIO;
		return -EIO;


	stag_state = stag_state > 0;
	stag_state = stag_state > 0;
@@ -858,7 +858,7 @@ int cxio_rdma_init(struct cxio_rdev *rdev_p, struct t3_rdma_init_attr *attr)
	wqe->qp_dma_size = cpu_to_be32(attr->qp_dma_size);
	wqe->qp_dma_size = cpu_to_be32(attr->qp_dma_size);
	wqe->irs = cpu_to_be32(attr->irs);
	wqe->irs = cpu_to_be32(attr->irs);
	skb->priority = 0;	/* 0=>ToeQ; 1=>CtrlQ */
	skb->priority = 0;	/* 0=>ToeQ; 1=>CtrlQ */
	return (cxgb3_ofld_send(rdev_p->t3cdev_p, skb));
	return iwch_cxgb3_ofld_send(rdev_p->t3cdev_p, skb);
}
}


void cxio_register_ev_cb(cxio_hal_ev_callback_func_t ev_cb)
void cxio_register_ev_cb(cxio_hal_ev_callback_func_t ev_cb)
@@ -1041,9 +1041,9 @@ void cxio_rdev_close(struct cxio_rdev *rdev_p)
		cxio_hal_pblpool_destroy(rdev_p);
		cxio_hal_pblpool_destroy(rdev_p);
		cxio_hal_rqtpool_destroy(rdev_p);
		cxio_hal_rqtpool_destroy(rdev_p);
		list_del(&rdev_p->entry);
		list_del(&rdev_p->entry);
		rdev_p->t3cdev_p->ulp = NULL;
		cxio_hal_destroy_ctrl_qp(rdev_p);
		cxio_hal_destroy_ctrl_qp(rdev_p);
		cxio_hal_destroy_resource(rdev_p->rscp);
		cxio_hal_destroy_resource(rdev_p->rscp);
		rdev_p->t3cdev_p->ulp = NULL;
	}
	}
}
}


+6 −0
Original line number Original line Diff line number Diff line
@@ -115,6 +115,11 @@ struct cxio_rdev {
#define	CXIO_ERROR_FATAL	1
#define	CXIO_ERROR_FATAL	1
};
};


static inline int cxio_fatal_error(struct cxio_rdev *rdev_p)
{
	return rdev_p->flags & CXIO_ERROR_FATAL;
}

static inline int cxio_num_stags(struct cxio_rdev *rdev_p)
static inline int cxio_num_stags(struct cxio_rdev *rdev_p)
{
{
	return min((int)T3_MAX_NUM_STAG, (int)((rdev_p->rnic_info.tpt_top - rdev_p->rnic_info.tpt_base) >> 5));
	return min((int)T3_MAX_NUM_STAG, (int)((rdev_p->rnic_info.tpt_top - rdev_p->rnic_info.tpt_base) >> 5));
@@ -188,6 +193,7 @@ void cxio_count_scqes(struct t3_cq *cq, struct t3_wq *wq, int *count);
void cxio_flush_hw_cq(struct t3_cq *cq);
void cxio_flush_hw_cq(struct t3_cq *cq);
int cxio_poll_cq(struct t3_wq *wq, struct t3_cq *cq, struct t3_cqe *cqe,
int cxio_poll_cq(struct t3_wq *wq, struct t3_cq *cq, struct t3_cqe *cqe,
		     u8 *cqe_flushed, u64 *cookie, u32 *credit);
		     u8 *cqe_flushed, u64 *cookie, u32 *credit);
int iwch_cxgb3_ofld_send(struct t3cdev *tdev, struct sk_buff *skb);


#define MOD "iw_cxgb3: "
#define MOD "iw_cxgb3: "
#define PDBG(fmt, args...) pr_debug(MOD fmt, ## args)
#define PDBG(fmt, args...) pr_debug(MOD fmt, ## args)
+9 −2
Original line number Original line Diff line number Diff line
@@ -165,12 +165,19 @@ static void close_rnic_dev(struct t3cdev *tdev)
static void iwch_err_handler(struct t3cdev *tdev, u32 status, u32 error)
static void iwch_err_handler(struct t3cdev *tdev, u32 status, u32 error)
{
{
	struct cxio_rdev *rdev = tdev->ulp;
	struct cxio_rdev *rdev = tdev->ulp;
	struct iwch_dev *rnicp = rdev_to_iwch_dev(rdev);
	struct ib_event event;


	if (status == OFFLOAD_STATUS_DOWN)
	if (status == OFFLOAD_STATUS_DOWN) {
		rdev->flags = CXIO_ERROR_FATAL;
		rdev->flags = CXIO_ERROR_FATAL;


	return;
		event.device = &rnicp->ibdev;
		event.event  = IB_EVENT_DEVICE_FATAL;
		event.element.port_num = 0;
		ib_dispatch_event(&event);
	}


	return;
}
}


static int __init iwch_init_module(void)
static int __init iwch_init_module(void)
Loading