Commit dd91b5e1 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull rdma updates from Jason Gunthorpe:
 "Usual collection of driver fixes:

   - Small bug fixes and cleansup in hfi, hns, rxe, mlx5, mana siw

   - Further ODP functionality in rxe

   - Remote access MRs in mana, along with more page sizes

   - Improve CM scalability with a rwlock around the agent

   - More trace points for hns

   - ODP hmm conversion to the new two step dma API

   - Support the ethernet HW device in mana as well as the RNIC

   - Cleanups:
       - Use secs_to_jiffies() when appropriate
       - Use ERR_CAST() instead of naked casts
       - Don't use %pK in printk
       - Unusued functions removed
       - Allocation type matching"

* tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma: (57 commits)
  RDMA/cma: Fix hang when cma_netevent_callback fails to queue_work
  RDMA/bnxt_re: Support extended stats for Thor2 VF
  RDMA/hns: Fix endian issue in trace events
  RDMA/mlx5: Avoid flexible array warning
  IB/cm: Remove dead code and adjust naming
  RDMA/core: Avoid hmm_dma_map_alloc() for virtual DMA devices
  RDMA/rxe: Break endless pagefault loop for RO pages
  RDMA/bnxt_re: Fix return code of bnxt_re_configure_cc
  RDMA/bnxt_re: Fix missing error handling for tx_queue
  RDMA/bnxt_re: Fix incorrect display of inactivity_cp in debugfs output
  RDMA/mlx5: Add support for 200Gbps per lane speeds
  RDMA/mlx5: Remove the redundant MLX5_IB_STAGE_UAR stage
  RDMA/iwcm: Fix use-after-free of work objects after cm_id destruction
  net: mana: Add support for auxiliary device servicing events
  RDMA/mana_ib: unify mana_ib functions to support any gdma device
  RDMA/mana_ib: Add support of mana_ib for RNIC and ETH nic
  net: mana: Probe rdma device in mana driver
  RDMA/siw: replace redundant ternary operator with just rv
  RDMA/umem: Separate implicit ODP initialization from explicit ODP
  RDMA/core: Convert UMEM ODP DMA mapping to caching IOVA and page linkage
  ...
parents 883e3c9f 92a251c3
Loading
Loading
Loading
Loading
+20 −58
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ MODULE_LICENSE("Dual BSD/GPL");

#define CM_DESTROY_ID_WAIT_TIMEOUT 10000 /* msecs */
#define CM_DIRECT_RETRY_CTX ((void *) 1UL)
#define CM_MRA_SETTING 24 /* 4.096us * 2^24 = ~68.7 seconds */

static const char * const ibcm_rej_reason_strs[] = {
	[IB_CM_REJ_NO_QP]			= "no QP",
@@ -167,7 +168,7 @@ struct cm_port {
struct cm_device {
	struct kref kref;
	struct list_head list;
	spinlock_t mad_agent_lock;
	rwlock_t mad_agent_lock;
	struct ib_device *ib_device;
	u8 ack_delay;
	int going_down;
@@ -241,7 +242,6 @@ struct cm_id_private {
	u8 initiator_depth;
	u8 retry_count;
	u8 rnr_retry_count;
	u8 service_timeout;
	u8 target_ack_delay;

	struct list_head work_list;
@@ -285,7 +285,7 @@ static struct ib_mad_send_buf *cm_alloc_msg(struct cm_id_private *cm_id_priv)
	if (!cm_id_priv->av.port)
		return ERR_PTR(-EINVAL);

	spin_lock(&cm_id_priv->av.port->cm_dev->mad_agent_lock);
	read_lock(&cm_id_priv->av.port->cm_dev->mad_agent_lock);
	mad_agent = cm_id_priv->av.port->mad_agent;
	if (!mad_agent) {
		m = ERR_PTR(-EINVAL);
@@ -311,7 +311,7 @@ static struct ib_mad_send_buf *cm_alloc_msg(struct cm_id_private *cm_id_priv)
	m->ah = ah;

out:
	spin_unlock(&cm_id_priv->av.port->cm_dev->mad_agent_lock);
	read_unlock(&cm_id_priv->av.port->cm_dev->mad_agent_lock);
	return m;
}

@@ -1297,10 +1297,10 @@ static __be64 cm_form_tid(struct cm_id_private *cm_id_priv)
	if (!cm_id_priv->av.port)
		return cpu_to_be64(low_tid);

	spin_lock(&cm_id_priv->av.port->cm_dev->mad_agent_lock);
	read_lock(&cm_id_priv->av.port->cm_dev->mad_agent_lock);
	if (cm_id_priv->av.port->mad_agent)
		hi_tid = ((u64)cm_id_priv->av.port->mad_agent->hi_tid) << 32;
	spin_unlock(&cm_id_priv->av.port->cm_dev->mad_agent_lock);
	read_unlock(&cm_id_priv->av.port->cm_dev->mad_agent_lock);
	return cpu_to_be64(hi_tid | low_tid);
}

@@ -1872,7 +1872,7 @@ static void cm_process_work(struct cm_id_private *cm_id_priv,

static void cm_format_mra(struct cm_mra_msg *mra_msg,
			  struct cm_id_private *cm_id_priv,
			  enum cm_msg_response msg_mraed, u8 service_timeout,
			  enum cm_msg_response msg_mraed,
			  const void *private_data, u8 private_data_len)
{
	cm_format_mad_hdr(&mra_msg->hdr, CM_MRA_ATTR_ID, cm_id_priv->tid);
@@ -1881,7 +1881,7 @@ static void cm_format_mra(struct cm_mra_msg *mra_msg,
		be32_to_cpu(cm_id_priv->id.local_id));
	IBA_SET(CM_MRA_REMOTE_COMM_ID, mra_msg,
		be32_to_cpu(cm_id_priv->id.remote_id));
	IBA_SET(CM_MRA_SERVICE_TIMEOUT, mra_msg, service_timeout);
	IBA_SET(CM_MRA_SERVICE_TIMEOUT, mra_msg, CM_MRA_SETTING);

	if (private_data && private_data_len)
		IBA_SET_MEM(CM_MRA_PRIVATE_DATA, mra_msg, private_data,
@@ -1960,7 +1960,7 @@ static void cm_dup_req_handler(struct cm_work *work,
	switch (cm_id_priv->id.state) {
	case IB_CM_MRA_REQ_SENT:
		cm_format_mra((struct cm_mra_msg *) msg->mad, cm_id_priv,
			      CM_MSG_RESPONSE_REQ, cm_id_priv->service_timeout,
			      CM_MSG_RESPONSE_REQ,
			      cm_id_priv->private_data,
			      cm_id_priv->private_data_len);
		break;
@@ -2454,7 +2454,7 @@ static void cm_dup_rep_handler(struct cm_work *work)
			      cm_id_priv->private_data_len);
	else if (cm_id_priv->id.state == IB_CM_MRA_REP_SENT)
		cm_format_mra((struct cm_mra_msg *) msg->mad, cm_id_priv,
			      CM_MSG_RESPONSE_REP, cm_id_priv->service_timeout,
			      CM_MSG_RESPONSE_REP,
			      cm_id_priv->private_data,
			      cm_id_priv->private_data_len);
	else
@@ -3094,26 +3094,13 @@ static int cm_rej_handler(struct cm_work *work)
	return -EINVAL;
}

int ib_send_cm_mra(struct ib_cm_id *cm_id,
		   u8 service_timeout,
		   const void *private_data,
		   u8 private_data_len)
int ib_prepare_cm_mra(struct ib_cm_id *cm_id)
{
	struct cm_id_private *cm_id_priv;
	struct ib_mad_send_buf *msg;
	enum ib_cm_state cm_state;
	enum ib_cm_lap_state lap_state;
	enum cm_msg_response msg_response;
	void *data;
	unsigned long flags;
	int ret;

	if (private_data && private_data_len > IB_CM_MRA_PRIVATE_DATA_SIZE)
		return -EINVAL;

	data = cm_copy_private_data(private_data, private_data_len);
	if (IS_ERR(data))
		return PTR_ERR(data);
	int ret = 0;

	cm_id_priv = container_of(cm_id, struct cm_id_private, id);

@@ -3122,58 +3109,33 @@ int ib_send_cm_mra(struct ib_cm_id *cm_id,
	case IB_CM_REQ_RCVD:
		cm_state = IB_CM_MRA_REQ_SENT;
		lap_state = cm_id->lap_state;
		msg_response = CM_MSG_RESPONSE_REQ;
		break;
	case IB_CM_REP_RCVD:
		cm_state = IB_CM_MRA_REP_SENT;
		lap_state = cm_id->lap_state;
		msg_response = CM_MSG_RESPONSE_REP;
		break;
	case IB_CM_ESTABLISHED:
		if (cm_id->lap_state == IB_CM_LAP_RCVD) {
			cm_state = cm_id->state;
			lap_state = IB_CM_MRA_LAP_SENT;
			msg_response = CM_MSG_RESPONSE_OTHER;
			break;
		}
		fallthrough;
	default:
		trace_icm_send_mra_unknown_err(&cm_id_priv->id);
		trace_icm_prepare_mra_unknown_err(&cm_id_priv->id);
		ret = -EINVAL;
		goto error_unlock;
	}

	if (!(service_timeout & IB_CM_MRA_FLAG_DELAY)) {
		msg = cm_alloc_msg(cm_id_priv);
		if (IS_ERR(msg)) {
			ret = PTR_ERR(msg);
			goto error_unlock;
		}

		cm_format_mra((struct cm_mra_msg *) msg->mad, cm_id_priv,
			      msg_response, service_timeout,
			      private_data, private_data_len);
		trace_icm_send_mra(cm_id);
		ret = ib_post_send_mad(msg, NULL);
		if (ret)
			goto error_free_msg;
	}

	cm_id->state = cm_state;
	cm_id->lap_state = lap_state;
	cm_id_priv->service_timeout = service_timeout;
	cm_set_private_data(cm_id_priv, data, private_data_len);
	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
	return 0;
	cm_set_private_data(cm_id_priv, NULL, 0);

error_free_msg:
	cm_free_msg(msg);
error_unlock:
	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
	kfree(data);
	return ret;
}
EXPORT_SYMBOL(ib_send_cm_mra);
EXPORT_SYMBOL(ib_prepare_cm_mra);

static struct cm_id_private *cm_acquire_mraed_id(struct cm_mra_msg *mra_msg)
{
@@ -3377,7 +3339,6 @@ static int cm_lap_handler(struct cm_work *work)

		cm_format_mra((struct cm_mra_msg *) msg->mad, cm_id_priv,
			      CM_MSG_RESPONSE_OTHER,
			      cm_id_priv->service_timeout,
			      cm_id_priv->private_data,
			      cm_id_priv->private_data_len);
		spin_unlock_irq(&cm_id_priv->lock);
@@ -3786,7 +3747,8 @@ static void cm_process_send_error(struct cm_id_private *cm_id_priv,
	spin_lock_irq(&cm_id_priv->lock);
	if (msg != cm_id_priv->msg) {
		spin_unlock_irq(&cm_id_priv->lock);
		cm_free_priv_msg(msg);
		cm_free_msg(msg);
		cm_deref_id(cm_id_priv);
		return;
	}
	cm_free_priv_msg(msg);
@@ -4378,7 +4340,7 @@ static int cm_add_one(struct ib_device *ib_device)
		return -ENOMEM;

	kref_init(&cm_dev->kref);
	spin_lock_init(&cm_dev->mad_agent_lock);
	rwlock_init(&cm_dev->mad_agent_lock);
	cm_dev->ib_device = ib_device;
	cm_dev->ack_delay = ib_device->attrs.local_ca_ack_delay;
	cm_dev->going_down = 0;
@@ -4494,9 +4456,9 @@ static void cm_remove_one(struct ib_device *ib_device, void *client_data)
		 * The above ensures no call paths from the work are running,
		 * the remaining paths all take the mad_agent_lock.
		 */
		spin_lock(&cm_dev->mad_agent_lock);
		write_lock(&cm_dev->mad_agent_lock);
		port->mad_agent = NULL;
		spin_unlock(&cm_dev->mad_agent_lock);
		write_unlock(&cm_dev->mad_agent_lock);
		ib_unregister_mad_agent(mad_agent);
		ib_port_unregister_client_groups(ib_device, i,
						 cm_counter_groups);
+1 −1
Original line number Diff line number Diff line
@@ -229,7 +229,7 @@ DEFINE_CM_ERR_EVENT(send_drep);
DEFINE_CM_ERR_EVENT(dreq_unknown);
DEFINE_CM_ERR_EVENT(send_unknown_rej);
DEFINE_CM_ERR_EVENT(rej_unknown);
DEFINE_CM_ERR_EVENT(send_mra_unknown);
DEFINE_CM_ERR_EVENT(prepare_mra_unknown);
DEFINE_CM_ERR_EVENT(mra_unknown);
DEFINE_CM_ERR_EVENT(qp_init);
DEFINE_CM_ERR_EVENT(qp_rtr);
+6 −19
Original line number Diff line number Diff line
@@ -46,7 +46,6 @@ MODULE_LICENSE("Dual BSD/GPL");

#define CMA_CM_RESPONSE_TIMEOUT 20
#define CMA_MAX_CM_RETRIES 15
#define CMA_CM_MRA_SETTING (IB_CM_MRA_FLAG_DELAY | 24)
#define CMA_IBOE_PACKET_LIFETIME 16
#define CMA_PREFERRED_ROCE_GID_TYPE IB_GID_TYPE_ROCE_UDP_ENCAP

@@ -146,19 +145,6 @@ struct iw_cm_id *rdma_iw_cm_id(struct rdma_cm_id *id)
}
EXPORT_SYMBOL(rdma_iw_cm_id);

/**
 * rdma_res_to_id() - return the rdma_cm_id pointer for this restrack.
 * @res: rdma resource tracking entry pointer
 */
struct rdma_cm_id *rdma_res_to_id(struct rdma_restrack_entry *res)
{
	struct rdma_id_private *id_priv =
		container_of(res, struct rdma_id_private, res);

	return &id_priv->id;
}
EXPORT_SYMBOL(rdma_res_to_id);

static int cma_add_one(struct ib_device *device);
static void cma_remove_one(struct ib_device *device, void *client_data);

@@ -2214,8 +2200,8 @@ static int cma_ib_handler(struct ib_cm_id *cm_id,
	case IB_CM_REP_RECEIVED:
		if (state == RDMA_CM_CONNECT &&
		    (id_priv->id.qp_type != IB_QPT_UD)) {
			trace_cm_send_mra(id_priv);
			ib_send_cm_mra(cm_id, CMA_CM_MRA_SETTING, NULL, 0);
			trace_cm_prepare_mra(id_priv);
			ib_prepare_cm_mra(cm_id);
		}
		if (id_priv->id.qp) {
			event.status = cma_rep_recv(id_priv);
@@ -2476,8 +2462,8 @@ static int cma_ib_req_handler(struct ib_cm_id *cm_id,

	if (READ_ONCE(conn_id->state) == RDMA_CM_CONNECT &&
	    conn_id->id.qp_type != IB_QPT_UD) {
		trace_cm_send_mra(cm_id->context);
		ib_send_cm_mra(cm_id, CMA_CM_MRA_SETTING, NULL, 0);
		trace_cm_prepare_mra(cm_id->context);
		ib_prepare_cm_mra(cm_id);
	}
	mutex_unlock(&conn_id->handler_mutex);

@@ -5245,7 +5231,8 @@ static int cma_netevent_callback(struct notifier_block *self,
			   neigh->ha, ETH_ALEN))
			continue;
		cma_id_get(current_id);
		queue_work(cma_wq, &current_id->id.net_work);
		if (!queue_work(cma_wq, &current_id->id.net_work))
			cma_id_put(current_id);
	}
out:
	spin_unlock_irqrestore(&id_table_lock, flags);
+1 −1
Original line number Diff line number Diff line
@@ -55,7 +55,7 @@ DECLARE_EVENT_CLASS(cma_fsm_class,

DEFINE_CMA_FSM_EVENT(send_rtu);
DEFINE_CMA_FSM_EVENT(send_rej);
DEFINE_CMA_FSM_EVENT(send_mra);
DEFINE_CMA_FSM_EVENT(prepare_mra);
DEFINE_CMA_FSM_EVENT(send_sidr_req);
DEFINE_CMA_FSM_EVENT(send_sidr_rep);
DEFINE_CMA_FSM_EVENT(disconnect);
+15 −14
Original line number Diff line number Diff line
@@ -368,12 +368,9 @@ EXPORT_SYMBOL(iw_cm_disconnect);
/*
 * CM_ID <-- DESTROYING
 *
 * Clean up all resources associated with the connection and release
 * the initial reference taken by iw_create_cm_id.
 *
 * Returns true if and only if the last cm_id_priv reference has been dropped.
 * Clean up all resources associated with the connection.
 */
static bool destroy_cm_id(struct iw_cm_id *cm_id)
static void destroy_cm_id(struct iw_cm_id *cm_id)
{
	struct iwcm_id_private *cm_id_priv;
	struct ib_qp *qp;
@@ -442,20 +439,22 @@ static bool destroy_cm_id(struct iw_cm_id *cm_id)
		iwpm_remove_mapinfo(&cm_id->local_addr, &cm_id->m_local_addr);
		iwpm_remove_mapping(&cm_id->local_addr, RDMA_NL_IWCM);
	}

	return iwcm_deref_id(cm_id_priv);
}

/*
 * This function is only called by the application thread and cannot
 * be called by the event thread. The function will wait for all
 * references to be released on the cm_id and then kfree the cm_id
 * object.
 * Destroy cm_id. If the cm_id still has other references, wait for all
 * references to be released on the cm_id and then release the initial
 * reference taken by iw_create_cm_id.
 */
void iw_destroy_cm_id(struct iw_cm_id *cm_id)
{
	if (!destroy_cm_id(cm_id))
	struct iwcm_id_private *cm_id_priv;

	cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
	destroy_cm_id(cm_id);
	if (refcount_read(&cm_id_priv->refcount) > 1)
		flush_workqueue(iwcm_wq);
	iwcm_deref_id(cm_id_priv);
}
EXPORT_SYMBOL(iw_destroy_cm_id);

@@ -1035,8 +1034,10 @@ static void cm_work_handler(struct work_struct *_work)

		if (!test_bit(IWCM_F_DROP_EVENTS, &cm_id_priv->flags)) {
			ret = process_event(cm_id_priv, &levent);
			if (ret)
				WARN_ON_ONCE(destroy_cm_id(&cm_id_priv->id));
			if (ret) {
				destroy_cm_id(&cm_id_priv->id);
				WARN_ON_ONCE(iwcm_deref_id(cm_id_priv));
			}
		} else
			pr_debug("dropping event %d\n", levent.event);
		if (iwcm_deref_id(cm_id_priv))
Loading