Skip to content

Commit

Permalink
[SCSI] zfcp: fix layering oddities between zfcp_fsf and zfcp_qdio
Browse files Browse the repository at this point in the history
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: Swen Schillig <swen@vnet.ibm.com>
Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
  • Loading branch information
Swen Schillig authored and James Bottomley committed Sep 5, 2009
1 parent 55c770f commit bd63eaf
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 74 deletions.
2 changes: 1 addition & 1 deletion drivers/s390/scsi/zfcp_ext.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 *);
Expand Down
100 changes: 70 additions & 30 deletions drivers/s390/scsi/zfcp_fsf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
}
45 changes: 2 additions & 43 deletions drivers/s390/scsi/zfcp_qdio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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);
}

/*
Expand Down

0 comments on commit bd63eaf

Please sign in to comment.