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

Commit a46171d0 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull SCSI target fixes from Nicholas Bellinger:
 "Here are the target-pending fixes queued for v3.18-rc6.

  The highlights include:

   - target-core OOPs fix with tcm_qla2xxx + vxworks FC initiators +
     zero length SCSI commands having a transfer direction set.  (Roland
     + Craig Watson)

   - vhost-scsi OOPs fix to explicitly prevent WWPN endpoint configfs
     group removal while qemu still has an active reference.  (Paolo +
     nab)

   - ib_srpt fix for RDMA hardware with lower srp_sq_size limits.
     (Bart)

   - two ib_isert work-arounds for running on ocrdma hardware (Or + Sagi
     + Chris)

   - iscsi-target discovery portal typo + SPC-3 PR Preempt SA key
     matching fix (Steve)"

* git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending:
  IB/isert: Adjust CQ size to HW limits
  target: return CONFLICT only when SA key unmatched
  iser-target: Handle DEVICE_REMOVAL event on network portal listener correctly
  ib_isert: Add max_send_sge=2 minimum for control PDU responses
  srp-target: Retry when QP creation fails with ENOMEM
  iscsi-target: return the correct port in SendTargets
  vhost-scsi: Take configfs group dependency during VHOST_SCSI_SET_ENDPOINT
  target: Don't call TFO->write_pending if data_length == 0
parents 4ec69c7e b1a5ad00
Loading
Loading
Loading
Loading
+30 −14
Original line number Diff line number Diff line
@@ -115,9 +115,12 @@ isert_conn_setup_qp(struct isert_conn *isert_conn, struct rdma_cm_id *cma_id,
	attr.cap.max_recv_wr = ISERT_QP_MAX_RECV_DTOS;
	/*
	 * FIXME: Use devattr.max_sge - 2 for max_send_sge as
	 * work-around for RDMA_READ..
	 * work-around for RDMA_READs with ConnectX-2.
	 *
	 * Also, still make sure to have at least two SGEs for
	 * outgoing control PDU responses.
	 */
	attr.cap.max_send_sge = device->dev_attr.max_sge - 2;
	attr.cap.max_send_sge = max(2, device->dev_attr.max_sge - 2);
	isert_conn->max_sge = attr.cap.max_send_sge;

	attr.cap.max_recv_sge = 1;
@@ -225,12 +228,16 @@ isert_create_device_ib_res(struct isert_device *device)
	struct isert_cq_desc *cq_desc;
	struct ib_device_attr *dev_attr;
	int ret = 0, i, j;
	int max_rx_cqe, max_tx_cqe;

	dev_attr = &device->dev_attr;
	ret = isert_query_device(ib_dev, dev_attr);
	if (ret)
		return ret;

	max_rx_cqe = min(ISER_MAX_RX_CQ_LEN, dev_attr->max_cqe);
	max_tx_cqe = min(ISER_MAX_TX_CQ_LEN, dev_attr->max_cqe);

	/* asign function handlers */
	if (dev_attr->device_cap_flags & IB_DEVICE_MEM_MGT_EXTENSIONS &&
	    dev_attr->device_cap_flags & IB_DEVICE_SIGNATURE_HANDOVER) {
@@ -272,7 +279,7 @@ isert_create_device_ib_res(struct isert_device *device)
						isert_cq_rx_callback,
						isert_cq_event_callback,
						(void *)&cq_desc[i],
						ISER_MAX_RX_CQ_LEN, i);
						max_rx_cqe, i);
		if (IS_ERR(device->dev_rx_cq[i])) {
			ret = PTR_ERR(device->dev_rx_cq[i]);
			device->dev_rx_cq[i] = NULL;
@@ -284,7 +291,7 @@ isert_create_device_ib_res(struct isert_device *device)
						isert_cq_tx_callback,
						isert_cq_event_callback,
						(void *)&cq_desc[i],
						ISER_MAX_TX_CQ_LEN, i);
						max_tx_cqe, i);
		if (IS_ERR(device->dev_tx_cq[i])) {
			ret = PTR_ERR(device->dev_tx_cq[i]);
			device->dev_tx_cq[i] = NULL;
@@ -803,14 +810,25 @@ isert_disconnect_work(struct work_struct *work)
	complete(&isert_conn->conn_wait);
}

static void
static int
isert_disconnected_handler(struct rdma_cm_id *cma_id, bool disconnect)
{
	struct isert_conn *isert_conn = (struct isert_conn *)cma_id->context;
	struct isert_conn *isert_conn;

	if (!cma_id->qp) {
		struct isert_np *isert_np = cma_id->context;

		isert_np->np_cm_id = NULL;
		return -1;
	}

	isert_conn = (struct isert_conn *)cma_id->context;

	isert_conn->disconnect = disconnect;
	INIT_WORK(&isert_conn->conn_logout_work, isert_disconnect_work);
	schedule_work(&isert_conn->conn_logout_work);

	return 0;
}

static int
@@ -825,6 +843,9 @@ isert_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
	switch (event->event) {
	case RDMA_CM_EVENT_CONNECT_REQUEST:
		ret = isert_connect_request(cma_id, event);
		if (ret)
			pr_err("isert_cma_handler failed RDMA_CM_EVENT: 0x%08x %d\n",
				event->event, ret);
		break;
	case RDMA_CM_EVENT_ESTABLISHED:
		isert_connected_handler(cma_id);
@@ -834,7 +855,7 @@ isert_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
	case RDMA_CM_EVENT_DEVICE_REMOVAL: /* FALLTHRU */
		disconnect = true;
	case RDMA_CM_EVENT_TIMEWAIT_EXIT:  /* FALLTHRU */
		isert_disconnected_handler(cma_id, disconnect);
		ret = isert_disconnected_handler(cma_id, disconnect);
		break;
	case RDMA_CM_EVENT_CONNECT_ERROR:
	default:
@@ -842,12 +863,6 @@ isert_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
		break;
	}

	if (ret != 0) {
		pr_err("isert_cma_handler failed RDMA_CM_EVENT: 0x%08x %d\n",
		       event->event, ret);
		dump_stack();
	}

	return ret;
}

@@ -3190,6 +3205,7 @@ isert_free_np(struct iscsi_np *np)
{
	struct isert_np *isert_np = (struct isert_np *)np->np_context;

	if (isert_np->np_cm_id)
		rdma_destroy_id(isert_np->np_cm_id);

	np->np_context = NULL;
+8 −0
Original line number Diff line number Diff line
@@ -2092,6 +2092,7 @@ static int srpt_create_ch_ib(struct srpt_rdma_ch *ch)
	if (!qp_init)
		goto out;

retry:
	ch->cq = ib_create_cq(sdev->device, srpt_completion, NULL, ch,
			      ch->rq_size + srp_sq_size, 0);
	if (IS_ERR(ch->cq)) {
@@ -2115,6 +2116,13 @@ static int srpt_create_ch_ib(struct srpt_rdma_ch *ch)
	ch->qp = ib_create_qp(sdev->pd, qp_init);
	if (IS_ERR(ch->qp)) {
		ret = PTR_ERR(ch->qp);
		if (ret == -ENOMEM) {
			srp_sq_size /= 2;
			if (srp_sq_size >= MIN_SRPT_SQ_SIZE) {
				ib_destroy_cq(ch->cq);
				goto retry;
			}
		}
		printk(KERN_ERR "failed to create_qp ret= %d\n", ret);
		goto err_destroy_cq;
	}
+1 −1
Original line number Diff line number Diff line
@@ -3491,7 +3491,7 @@ iscsit_build_sendtargets_response(struct iscsi_cmd *cmd,
				len = sprintf(buf, "TargetAddress="
					"%s:%hu,%hu",
					inaddr_any ? conn->local_ip : np->np_ip,
					inaddr_any ? conn->local_port : np->np_port,
					np->np_port,
					tpg->tpgt);
				len += 1;

+5 −4
Original line number Diff line number Diff line
@@ -2738,7 +2738,8 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
	struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_reg_n, *pr_res_holder;
	struct t10_reservation *pr_tmpl = &dev->t10_pr;
	u32 pr_res_mapped_lun = 0;
	int all_reg = 0, calling_it_nexus = 0, released_regs = 0;
	int all_reg = 0, calling_it_nexus = 0;
	bool sa_res_key_unmatched = sa_res_key != 0;
	int prh_type = 0, prh_scope = 0;

	if (!se_sess)
@@ -2813,6 +2814,7 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
			if (!all_reg) {
				if (pr_reg->pr_res_key != sa_res_key)
					continue;
				sa_res_key_unmatched = false;

				calling_it_nexus = (pr_reg_n == pr_reg) ? 1 : 0;
				pr_reg_nacl = pr_reg->pr_reg_nacl;
@@ -2820,7 +2822,6 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
				__core_scsi3_free_registration(dev, pr_reg,
					(preempt_type == PREEMPT_AND_ABORT) ? &preempt_and_abort_list :
						NULL, calling_it_nexus);
				released_regs++;
			} else {
				/*
				 * Case for any existing all registrants type
@@ -2838,6 +2839,7 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
				if ((sa_res_key) &&
				     (pr_reg->pr_res_key != sa_res_key))
					continue;
				sa_res_key_unmatched = false;

				calling_it_nexus = (pr_reg_n == pr_reg) ? 1 : 0;
				if (calling_it_nexus)
@@ -2848,7 +2850,6 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
				__core_scsi3_free_registration(dev, pr_reg,
					(preempt_type == PREEMPT_AND_ABORT) ? &preempt_and_abort_list :
						NULL, 0);
				released_regs++;
			}
			if (!calling_it_nexus)
				core_scsi3_ua_allocate(pr_reg_nacl,
@@ -2863,7 +2864,7 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
		 * registered reservation key, then the device server shall
		 * complete the command with RESERVATION CONFLICT status.
		 */
		if (!released_regs) {
		if (sa_res_key_unmatched) {
			spin_unlock(&dev->dev_reservation_lock);
			core_scsi3_put_pr_reg(pr_reg_n);
			return TCM_RESERVATION_CONFLICT;
+1 −1
Original line number Diff line number Diff line
@@ -2292,7 +2292,7 @@ transport_generic_new_cmd(struct se_cmd *cmd)
	 * and let it call back once the write buffers are ready.
	 */
	target_add_to_state_list(cmd);
	if (cmd->data_direction != DMA_TO_DEVICE) {
	if (cmd->data_direction != DMA_TO_DEVICE || cmd->data_length == 0) {
		target_execute_cmd(cmd);
		return 0;
	}
Loading