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

Commit 2edb3898 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6: (23 commits)
  [SCSI] sd: Avoid sending extended inquiry to legacy devices
  [SCSI] libsas: fix wide port hotplug issues
  [SCSI] libfc: fix a circular locking warning during sending RRQ
  [SCSI] qla4xxx: Remove hiwat code so scsi eh does not get escalated when we can make progress
  [SCSI] qla4xxx: Fix srb lookup in qla4xxx_eh_device_reset
  [SCSI] qla4xxx: Fix Driver Fault Recovery Completion
  [SCSI] qla4xxx: add timeout handler
  [SCSI] qla4xxx: Correct Extended Sense Data Errors
  [SCSI] libiscsi: disable bh in and abort handler.
  [SCSI] zfcp: Fix tracing of request id for abort requests
  [SCSI] zfcp: Fix wka port processing
  [SCSI] zfcp: avoid double notify in lowmem scenario
  [SCSI] zfcp: Add port only once to FC transport class
  [SCSI] zfcp: Recover from stalled outbound queue
  [SCSI] zfcp: Fix erp escalation procedure
  [SCSI] zfcp: Fix logic for physical port close
  [SCSI] zfcp: Use -EIO for SBAL allocation failures
  [SCSI] zfcp: Use unchained mode for small ct and els requests
  [SCSI] zfcp: Use correct flags for zfcp_erp_notify
  [SCSI] zfcp: Return -ENOMEM for allocation failures in zfcp_fsf
  ...
parents c71c090f ffd4bc2a
Loading
Loading
Loading
Loading
+36 −32
Original line number Diff line number Diff line
@@ -553,40 +553,35 @@ static void _zfcp_erp_unit_reopen_all(struct zfcp_port *port, int clear,
		_zfcp_erp_unit_reopen(unit, clear, id, ref);
}

static void zfcp_erp_strategy_followup_actions(struct zfcp_erp_action *act)
static void zfcp_erp_strategy_followup_failed(struct zfcp_erp_action *act)
{
	struct zfcp_adapter *adapter = act->adapter;
	struct zfcp_port *port = act->port;
	struct zfcp_unit *unit = act->unit;
	u32 status = act->status;

	/* initiate follow-up actions depending on success of finished action */
	switch (act->action) {

	case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
		if (status == ZFCP_ERP_SUCCEEDED)
			_zfcp_erp_port_reopen_all(adapter, 0, "ersfa_1", NULL);
		else
			_zfcp_erp_adapter_reopen(adapter, 0, "ersfa_2", NULL);
		_zfcp_erp_adapter_reopen(act->adapter, 0, "ersff_1", NULL);
		break;

	case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
		if (status == ZFCP_ERP_SUCCEEDED)
			_zfcp_erp_port_reopen(port, 0, "ersfa_3", NULL);
		else
			_zfcp_erp_adapter_reopen(adapter, 0, "ersfa_4", NULL);
		_zfcp_erp_port_forced_reopen(act->port, 0, "ersff_2", NULL);
		break;

	case ZFCP_ERP_ACTION_REOPEN_PORT:
		if (status == ZFCP_ERP_SUCCEEDED)
			_zfcp_erp_unit_reopen_all(port, 0, "ersfa_5", NULL);
		else
			_zfcp_erp_port_forced_reopen(port, 0, "ersfa_6", NULL);
		_zfcp_erp_port_reopen(act->port, 0, "ersff_3", NULL);
		break;

	case ZFCP_ERP_ACTION_REOPEN_UNIT:
		if (status != ZFCP_ERP_SUCCEEDED)
			_zfcp_erp_port_reopen(unit->port, 0, "ersfa_7", NULL);
		_zfcp_erp_unit_reopen(act->unit, 0, "ersff_4", NULL);
		break;
	}
}

static void zfcp_erp_strategy_followup_success(struct zfcp_erp_action *act)
{
	switch (act->action) {
	case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
		_zfcp_erp_port_reopen_all(act->adapter, 0, "ersfs_1", NULL);
		break;
	case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
		_zfcp_erp_port_reopen(act->port, 0, "ersfs_2", NULL);
		break;
	case ZFCP_ERP_ACTION_REOPEN_PORT:
		_zfcp_erp_unit_reopen_all(act->port, 0, "ersfs_3", NULL);
		break;
	}
}
@@ -801,7 +796,7 @@ static int zfcp_erp_port_forced_strategy(struct zfcp_erp_action *erp_action)
			return ZFCP_ERP_FAILED;

	case ZFCP_ERP_STEP_PHYS_PORT_CLOSING:
		if (status & ZFCP_STATUS_PORT_PHYS_OPEN)
		if (!(status & ZFCP_STATUS_PORT_PHYS_OPEN))
			return ZFCP_ERP_SUCCEEDED;
	}
	return ZFCP_ERP_FAILED;
@@ -853,11 +848,17 @@ void zfcp_erp_port_strategy_open_lookup(struct work_struct *work)
					      gid_pn_work);

	retval = zfcp_fc_ns_gid_pn(&port->erp_action);
	if (retval == -ENOMEM)
		zfcp_erp_notify(&port->erp_action, ZFCP_ERP_NOMEM);
	if (!retval) {
		port->erp_action.step = ZFCP_ERP_STEP_NAMESERVER_LOOKUP;
	if (retval)
		zfcp_erp_notify(&port->erp_action, ZFCP_ERP_FAILED);
		goto out;
	}
	if (retval == -ENOMEM) {
		zfcp_erp_notify(&port->erp_action, ZFCP_STATUS_ERP_LOWMEM);
		goto out;
	}
	/* all other error condtions */
	zfcp_erp_notify(&port->erp_action, 0);
out:
	zfcp_port_put(port);
}

@@ -1289,7 +1290,10 @@ static int zfcp_erp_strategy(struct zfcp_erp_action *erp_action)
	retval = zfcp_erp_strategy_statechange(erp_action, retval);
	if (retval == ZFCP_ERP_EXIT)
		goto unlock;
	zfcp_erp_strategy_followup_actions(erp_action);
	if (retval == ZFCP_ERP_SUCCEEDED)
		zfcp_erp_strategy_followup_success(erp_action);
	if (retval == ZFCP_ERP_FAILED)
		zfcp_erp_strategy_followup_failed(erp_action);

 unlock:
	write_unlock(&adapter->erp_lock);
+3 −5
Original line number Diff line number Diff line
@@ -79,11 +79,9 @@ static int zfcp_wka_port_get(struct zfcp_wka_port *wka_port)

	mutex_unlock(&wka_port->mutex);

	wait_event_timeout(
		wka_port->completion_wq,
	wait_event(wka_port->completion_wq,
		   wka_port->status == ZFCP_WKA_PORT_ONLINE ||
		wka_port->status == ZFCP_WKA_PORT_OFFLINE,
		HZ >> 1);
		   wka_port->status == ZFCP_WKA_PORT_OFFLINE);

	if (wka_port->status == ZFCP_WKA_PORT_ONLINE) {
		atomic_inc(&wka_port->refcount);
+38 −18
Original line number Diff line number Diff line
@@ -670,8 +670,11 @@ static int zfcp_fsf_req_sbal_get(struct zfcp_adapter *adapter)
			       zfcp_fsf_sbal_check(adapter), 5 * HZ);
	if (ret > 0)
		return 0;
	if (!ret)
	if (!ret) {
		atomic_inc(&adapter->qdio_outb_full);
		/* assume hanging outbound queue, try queue recovery */
		zfcp_erp_adapter_reopen(adapter, 0, "fsrsg_1", NULL);
	}

	spin_lock_bh(&adapter->req_q_lock);
	return -EIO;
@@ -722,7 +725,7 @@ static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_adapter *adapter,
		req = zfcp_fsf_alloc_qtcb(pool);

	if (unlikely(!req))
		return ERR_PTR(-EIO);
		return ERR_PTR(-ENOMEM);

	if (adapter->req_no == 0)
		adapter->req_no++;
@@ -1010,6 +1013,23 @@ skip_fsfstatus:
		send_ct->handler(send_ct->handler_data);
}

static void zfcp_fsf_setup_ct_els_unchained(struct qdio_buffer_element *sbale,
					    struct scatterlist *sg_req,
					    struct scatterlist *sg_resp)
{
	sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE_READ;
	sbale[2].addr   = sg_virt(sg_req);
	sbale[2].length = sg_req->length;
	sbale[3].addr   = sg_virt(sg_resp);
	sbale[3].length = sg_resp->length;
	sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY;
}

static int zfcp_fsf_one_sbal(struct scatterlist *sg)
{
	return sg_is_last(sg) && sg->length <= PAGE_SIZE;
}

static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req,
				       struct scatterlist *sg_req,
				       struct scatterlist *sg_resp,
@@ -1020,30 +1040,30 @@ static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req,
	int bytes;

	if (!(feat & FSF_FEATURE_ELS_CT_CHAINED_SBALS)) {
		if (sg_req->length > PAGE_SIZE || sg_resp->length > PAGE_SIZE ||
		    !sg_is_last(sg_req) || !sg_is_last(sg_resp))
		if (!zfcp_fsf_one_sbal(sg_req) || !zfcp_fsf_one_sbal(sg_resp))
			return -EOPNOTSUPP;

		sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE_READ;
		sbale[2].addr   = sg_virt(sg_req);
		sbale[2].length = sg_req->length;
		sbale[3].addr   = sg_virt(sg_resp);
		sbale[3].length = sg_resp->length;
		sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY;
		zfcp_fsf_setup_ct_els_unchained(sbale, sg_req, sg_resp);
		return 0;
	}

	/* use single, unchained SBAL if it can hold the request */
	if (zfcp_fsf_one_sbal(sg_req) && zfcp_fsf_one_sbal(sg_resp)) {
		zfcp_fsf_setup_ct_els_unchained(sbale, sg_req, sg_resp);
		return 0;
	}

	bytes = zfcp_qdio_sbals_from_sg(req, SBAL_FLAGS0_TYPE_WRITE_READ,
					sg_req, max_sbals);
	if (bytes <= 0)
		return -ENOMEM;
		return -EIO;
	req->qtcb->bottom.support.req_buf_length = bytes;
	req->sbale_curr = ZFCP_LAST_SBALE_PER_SBAL;

	bytes = zfcp_qdio_sbals_from_sg(req, SBAL_FLAGS0_TYPE_WRITE_READ,
					sg_resp, max_sbals);
	if (bytes <= 0)
		return -ENOMEM;
		return -EIO;
	req->qtcb->bottom.support.resp_buf_length = bytes;

	return 0;
@@ -1607,10 +1627,10 @@ static void zfcp_fsf_open_wka_port_handler(struct zfcp_fsf_req *req)
	case FSF_ACCESS_DENIED:
		wka_port->status = ZFCP_WKA_PORT_OFFLINE;
		break;
	case FSF_PORT_ALREADY_OPEN:
		break;
	case FSF_GOOD:
		wka_port->handle = header->port_handle;
		/* fall through */
	case FSF_PORT_ALREADY_OPEN:
		wka_port->status = ZFCP_WKA_PORT_ONLINE;
	}
out:
@@ -1731,15 +1751,16 @@ static void zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *req)
		zfcp_fsf_access_denied_port(req, port);
		break;
	case FSF_PORT_BOXED:
		zfcp_erp_port_boxed(port, "fscpph2", req);
		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
			       ZFCP_STATUS_FSFREQ_RETRY;
		/* can't use generic zfcp_erp_modify_port_status because
		 * ZFCP_STATUS_COMMON_OPEN must not be reset for the port */
		atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
		list_for_each_entry(unit, &port->unit_list_head, list)
			atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
					  &unit->status);
		zfcp_erp_port_boxed(port, "fscpph2", req);
		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
			       ZFCP_STATUS_FSFREQ_RETRY;

		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
		switch (header->fsf_status_qual.word[0]) {
@@ -2541,7 +2562,6 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
	bytes = zfcp_qdio_sbals_from_sg(req, direction, fsf_cfdc->sg,
					FSF_MAX_SBALS_PER_REQ);
	if (bytes != ZFCP_CFDC_MAX_SIZE) {
		retval = -ENOMEM;
		zfcp_fsf_req_free(req);
		goto out;
	}
+16 −9
Original line number Diff line number Diff line
@@ -167,20 +167,21 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
	struct zfcp_unit *unit = scpnt->device->hostdata;
	struct zfcp_fsf_req *old_req, *abrt_req;
	unsigned long flags;
	unsigned long old_req_id = (unsigned long) scpnt->host_scribble;
	unsigned long old_reqid = (unsigned long) scpnt->host_scribble;
	int retval = SUCCESS;
	int retry = 3;
	char *dbf_tag;

	/* avoid race condition between late normal completion and abort */
	write_lock_irqsave(&adapter->abort_lock, flags);

	spin_lock(&adapter->req_list_lock);
	old_req = zfcp_reqlist_find(adapter, old_req_id);
	old_req = zfcp_reqlist_find(adapter, old_reqid);
	spin_unlock(&adapter->req_list_lock);
	if (!old_req) {
		write_unlock_irqrestore(&adapter->abort_lock, flags);
		zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL,
					  old_req_id);
					  old_reqid);
		return FAILED; /* completion could be in progress */
	}
	old_req->data = NULL;
@@ -189,7 +190,7 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
	write_unlock_irqrestore(&adapter->abort_lock, flags);

	while (retry--) {
		abrt_req = zfcp_fsf_abort_fcp_command(old_req_id, unit);
		abrt_req = zfcp_fsf_abort_fcp_command(old_reqid, unit);
		if (abrt_req)
			break;

@@ -197,7 +198,7 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
		if (!(atomic_read(&adapter->status) &
		      ZFCP_STATUS_COMMON_RUNNING)) {
			zfcp_scsi_dbf_event_abort("nres", adapter, scpnt, NULL,
						  old_req_id);
						  old_reqid);
			return SUCCESS;
		}
	}
@@ -208,13 +209,14 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
		   abrt_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);

	if (abrt_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED)
		zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, abrt_req, 0);
		dbf_tag = "okay";
	else if (abrt_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED)
		zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, abrt_req, 0);
		dbf_tag = "lte2";
	else {
		zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, abrt_req, 0);
		dbf_tag = "fail";
		retval = FAILED;
	}
	zfcp_scsi_dbf_event_abort(dbf_tag, adapter, scpnt, abrt_req, old_reqid);
	zfcp_fsf_req_free(abrt_req);
	return retval;
}
@@ -534,6 +536,9 @@ static void zfcp_scsi_rport_register(struct zfcp_port *port)
	struct fc_rport_identifiers ids;
	struct fc_rport *rport;

	if (port->rport)
		return;

	ids.node_name = port->wwnn;
	ids.port_name = port->wwpn;
	ids.port_id = port->d_id;
@@ -557,8 +562,10 @@ static void zfcp_scsi_rport_block(struct zfcp_port *port)
{
	struct fc_rport *rport = port->rport;

	if (rport)
	if (rport) {
		fc_remote_port_delete(rport);
		port->rport = NULL;
	}
}

void zfcp_scsi_schedule_rport_register(struct zfcp_port *port)
+6 −1
Original line number Diff line number Diff line
@@ -494,9 +494,14 @@ static ssize_t zfcp_sysfs_adapter_q_full_show(struct device *dev,
	struct Scsi_Host *scsi_host = class_to_shost(dev);
	struct zfcp_adapter *adapter =
		(struct zfcp_adapter *) scsi_host->hostdata[0];
	u64 util;

	spin_lock_bh(&adapter->qdio_stat_lock);
	util = adapter->req_q_util;
	spin_unlock_bh(&adapter->qdio_stat_lock);

	return sprintf(buf, "%d %llu\n", atomic_read(&adapter->qdio_outb_full),
		       (unsigned long long)adapter->req_q_util);
		       (unsigned long long)util);
}
static DEVICE_ATTR(queue_full, S_IRUGO, zfcp_sysfs_adapter_q_full_show, NULL);

Loading