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

Commit bd63eaf4 authored by Swen Schillig's avatar Swen Schillig Committed by James Bottomley
Browse files

[SCSI] zfcp: fix layering oddities between zfcp_fsf and zfcp_qdio



There is no need for the QDIO layer to have knowledge or do things
wich are done better by the FSF layer and vice versa.  Straighten a
few things to improve vividness.

Signed-off-by: default avatarSwen Schillig <swen@vnet.ibm.com>
Signed-off-by: default avatarChristof Schmitt <christof.schmitt@de.ibm.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent 55c770fa
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -133,11 +133,11 @@ extern int zfcp_fsf_send_ct(struct zfcp_send_ct *, mempool_t *,
extern int zfcp_fsf_send_els(struct zfcp_send_els *);
extern int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *,
					  struct scsi_cmnd *);
extern void zfcp_fsf_req_complete(struct zfcp_fsf_req *);
extern void zfcp_fsf_req_free(struct zfcp_fsf_req *);
extern struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *, u8);
extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long,
						       struct zfcp_unit *);
extern void zfcp_fsf_reqid_check(struct zfcp_adapter *, int);

/* zfcp_qdio.c */
extern int zfcp_qdio_allocate(struct zfcp_adapter *);
+70 −30
Original line number Diff line number Diff line
@@ -122,35 +122,6 @@ void zfcp_fsf_req_free(struct zfcp_fsf_req *req)
	}
}

/**
 * zfcp_fsf_req_dismiss_all - dismiss all fsf requests
 * @adapter: pointer to struct zfcp_adapter
 *
 * Never ever call this without shutting down the adapter first.
 * Otherwise the adapter would continue using and corrupting s390 storage.
 * Included BUG_ON() call to ensure this is done.
 * ERP is supposed to be the only user of this function.
 */
void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter)
{
	struct zfcp_fsf_req *req, *tmp;
	unsigned long flags;
	LIST_HEAD(remove_queue);
	unsigned int i;

	BUG_ON(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP);
	spin_lock_irqsave(&adapter->req_list_lock, flags);
	for (i = 0; i < REQUEST_LIST_SIZE; i++)
		list_splice_init(&adapter->req_list[i], &remove_queue);
	spin_unlock_irqrestore(&adapter->req_list_lock, flags);

	list_for_each_entry_safe(req, tmp, &remove_queue, list) {
		list_del(&req->list);
		req->status |= ZFCP_STATUS_FSFREQ_DISMISSED;
		zfcp_fsf_req_complete(req);
	}
}

static void zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *req)
{
	struct fsf_status_read_buffer *sr_buf = req->data;
@@ -459,7 +430,7 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req)
 * is called to process the completion status and trigger further
 * events related to the FSF request.
 */
void zfcp_fsf_req_complete(struct zfcp_fsf_req *req)
static void zfcp_fsf_req_complete(struct zfcp_fsf_req *req)
{
	if (unlikely(req->fsf_command == FSF_QTCB_UNSOLICITED_STATUS)) {
		zfcp_fsf_status_read_handler(req);
@@ -492,6 +463,35 @@ void zfcp_fsf_req_complete(struct zfcp_fsf_req *req)
		wake_up(&req->completion_wq);
}

/**
 * zfcp_fsf_req_dismiss_all - dismiss all fsf requests
 * @adapter: pointer to struct zfcp_adapter
 *
 * Never ever call this without shutting down the adapter first.
 * Otherwise the adapter would continue using and corrupting s390 storage.
 * Included BUG_ON() call to ensure this is done.
 * ERP is supposed to be the only user of this function.
 */
void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter)
{
	struct zfcp_fsf_req *req, *tmp;
	unsigned long flags;
	LIST_HEAD(remove_queue);
	unsigned int i;

	BUG_ON(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP);
	spin_lock_irqsave(&adapter->req_list_lock, flags);
	for (i = 0; i < REQUEST_LIST_SIZE; i++)
		list_splice_init(&adapter->req_list[i], &remove_queue);
	spin_unlock_irqrestore(&adapter->req_list_lock, flags);

	list_for_each_entry_safe(req, tmp, &remove_queue, list) {
		list_del(&req->list);
		req->status |= ZFCP_STATUS_FSFREQ_DISMISSED;
		zfcp_fsf_req_complete(req);
	}
}

static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req)
{
	struct fsf_qtcb_bottom_config *bottom;
@@ -2578,3 +2578,43 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
	}
	return ERR_PTR(retval);
}

/**
 * zfcp_fsf_reqid_check - validate req_id contained in SBAL returned by QDIO
 * @adapter: pointer to struct zfcp_adapter
 * @sbal_idx: response queue index of SBAL to be processed
 */
void zfcp_fsf_reqid_check(struct zfcp_adapter *adapter, int sbal_idx)
{
	struct qdio_buffer *sbal = adapter->resp_q.sbal[sbal_idx];
	struct qdio_buffer_element *sbale;
	struct zfcp_fsf_req *fsf_req;
	unsigned long flags, req_id;
	int idx;

	for (idx = 0; idx < QDIO_MAX_ELEMENTS_PER_BUFFER; idx++) {

		sbale = &sbal->element[idx];
		req_id = (unsigned long) sbale->addr;
		spin_lock_irqsave(&adapter->req_list_lock, flags);
		fsf_req = zfcp_reqlist_find(adapter, req_id);

		if (!fsf_req)
			/*
			 * Unknown request means that we have potentially memory
			 * corruption and must stop the machine immediately.
			 */
			panic("error: unknown req_id (%lx) on adapter %s.\n",
			      req_id, dev_name(&adapter->ccw_device->dev));

		list_del(&fsf_req->list);
		spin_unlock_irqrestore(&adapter->req_list_lock, flags);

		fsf_req->sbal_response = sbal_idx;
		fsf_req->qdio_inb_usage = atomic_read(&adapter->resp_q.count);
		zfcp_fsf_req_complete(fsf_req);

		if (likely(sbale->flags & SBAL_FLAGS_LAST_ENTRY))
			break;
	}
}
+2 −43
Original line number Diff line number Diff line
@@ -112,31 +112,6 @@ static void zfcp_qdio_int_req(struct ccw_device *cdev, unsigned int qdio_err,
	wake_up(&adapter->request_wq);
}

static void zfcp_qdio_reqid_check(struct zfcp_adapter *adapter,
				  unsigned long req_id, int sbal_idx)
{
	struct zfcp_fsf_req *fsf_req;
	unsigned long flags;

	spin_lock_irqsave(&adapter->req_list_lock, flags);
	fsf_req = zfcp_reqlist_find(adapter, req_id);

	if (!fsf_req)
		/*
		 * Unknown request means that we have potentially memory
		 * corruption and must stop the machine immediatly.
		 */
		panic("error: unknown request id (%lx) on adapter %s.\n",
		      req_id, dev_name(&adapter->ccw_device->dev));

	zfcp_reqlist_remove(adapter, fsf_req);
	spin_unlock_irqrestore(&adapter->req_list_lock, flags);

	fsf_req->sbal_response = sbal_idx;
	fsf_req->qdio_inb_usage = atomic_read(&adapter->resp_q.count);
	zfcp_fsf_req_complete(fsf_req);
}

static void zfcp_qdio_resp_put_back(struct zfcp_adapter *adapter, int processed)
{
	struct zfcp_qdio_queue *queue = &adapter->resp_q;
@@ -163,9 +138,7 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err,
			       unsigned long parm)
{
	struct zfcp_adapter *adapter = (struct zfcp_adapter *) parm;
	struct zfcp_qdio_queue *queue = &adapter->resp_q;
	struct qdio_buffer_element *sbale;
	int sbal_idx, sbale_idx, sbal_no;
	int sbal_idx, sbal_no;

	if (unlikely(qdio_err)) {
		zfcp_hba_dbf_event_qdio(adapter, qdio_err, first, count);
@@ -179,22 +152,8 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err,
	 */
	for (sbal_no = 0; sbal_no < count; sbal_no++) {
		sbal_idx = (first + sbal_no) % QDIO_MAX_BUFFERS_PER_Q;

		/* go through all SBALEs of SBAL */
		for (sbale_idx = 0; sbale_idx < QDIO_MAX_ELEMENTS_PER_BUFFER;
		     sbale_idx++) {
			sbale = zfcp_qdio_sbale(queue, sbal_idx, sbale_idx);
			zfcp_qdio_reqid_check(adapter,
					      (unsigned long) sbale->addr,
					      sbal_idx);
			if (likely(sbale->flags & SBAL_FLAGS_LAST_ENTRY))
				break;
		};

		if (unlikely(!(sbale->flags & SBAL_FLAGS_LAST_ENTRY)))
			dev_warn(&adapter->ccw_device->dev,
				 "A QDIO protocol error occurred, "
				 "operations continue\n");
		zfcp_fsf_reqid_check(adapter, sbal_idx);
	}

	/*