Skip to content

Commit

Permalink
[SCSI] zfcp: Cleanup QDIO attachment and improve processing.
Browse files Browse the repository at this point in the history
Some definitions and structures in the zfcp QDIO processing are
improved by the removal of not required variables and processing steps.
I addition the naming of some variables is changed to make their purpose
more clear.

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 Jul 28, 2010
1 parent 01b0475 commit 706eca4
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 139 deletions.
10 changes: 4 additions & 6 deletions drivers/s390/scsi/zfcp_fsf.c
Original file line number Diff line number Diff line change
Expand Up @@ -732,7 +732,7 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *req)

zfcp_reqlist_add(adapter->req_list, req);

req->qdio_req.qdio_outb_usage = atomic_read(&qdio->req_q.count);
req->qdio_req.qdio_outb_usage = atomic_read(&qdio->req_q_free);
req->issued = get_clock();
if (zfcp_qdio_send(qdio, &req->qdio_req)) {
del_timer(&req->timer);
Expand Down Expand Up @@ -2025,7 +2025,7 @@ static void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi)
blktrc.magic = ZFCP_BLK_DRV_DATA_MAGIC;
if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
blktrc.flags |= ZFCP_BLK_REQ_ERROR;
blktrc.inb_usage = req->qdio_req.qdio_inb_usage;
blktrc.inb_usage = 0;
blktrc.outb_usage = req->qdio_req.qdio_outb_usage;

if (req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA &&
Expand Down Expand Up @@ -2207,7 +2207,7 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit,
return -EBUSY;

spin_lock(&qdio->req_q_lock);
if (atomic_read(&qdio->req_q.count) <= 0) {
if (atomic_read(&qdio->req_q_free) <= 0) {
atomic_inc(&qdio->req_q_full);
goto out;
}
Expand Down Expand Up @@ -2407,7 +2407,7 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
void zfcp_fsf_reqid_check(struct zfcp_qdio *qdio, int sbal_idx)
{
struct zfcp_adapter *adapter = qdio->adapter;
struct qdio_buffer *sbal = qdio->resp_q.sbal[sbal_idx];
struct qdio_buffer *sbal = qdio->res_q[sbal_idx];
struct qdio_buffer_element *sbale;
struct zfcp_fsf_req *fsf_req;
unsigned long req_id;
Expand All @@ -2428,8 +2428,6 @@ void zfcp_fsf_reqid_check(struct zfcp_qdio *qdio, int sbal_idx)
req_id, dev_name(&adapter->ccw_device->dev));

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

if (likely(sbale->flags & SBAL_FLAGS_LAST_ENTRY))
Expand Down
141 changes: 48 additions & 93 deletions drivers/s390/scsi/zfcp_qdio.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,71 +55,46 @@ static void zfcp_qdio_zero_sbals(struct qdio_buffer *sbal[], int first, int cnt)
static inline void zfcp_qdio_account(struct zfcp_qdio *qdio)
{
unsigned long long now, span;
int free, used;
int used;

spin_lock(&qdio->stat_lock);
now = get_clock_monotonic();
span = (now - qdio->req_q_time) >> 12;
free = atomic_read(&qdio->req_q.count);
used = QDIO_MAX_BUFFERS_PER_Q - free;
used = QDIO_MAX_BUFFERS_PER_Q - atomic_read(&qdio->req_q_free);
qdio->req_q_util += used * span;
qdio->req_q_time = now;
spin_unlock(&qdio->stat_lock);
}

static void zfcp_qdio_int_req(struct ccw_device *cdev, unsigned int qdio_err,
int queue_no, int first, int count,
int queue_no, int idx, int count,
unsigned long parm)
{
struct zfcp_qdio *qdio = (struct zfcp_qdio *) parm;
struct zfcp_qdio_queue *queue = &qdio->req_q;

if (unlikely(qdio_err)) {
zfcp_dbf_hba_qdio(qdio->adapter->dbf, qdio_err, first,
count);
zfcp_dbf_hba_qdio(qdio->adapter->dbf, qdio_err, idx, count);
zfcp_qdio_handler_error(qdio, "qdireq1");
return;
}

/* cleanup all SBALs being program-owned now */
zfcp_qdio_zero_sbals(queue->sbal, first, count);
zfcp_qdio_zero_sbals(qdio->req_q, idx, count);

zfcp_qdio_account(qdio);
atomic_add(count, &queue->count);
atomic_add(count, &qdio->req_q_free);
wake_up(&qdio->req_q_wq);
}

static void zfcp_qdio_resp_put_back(struct zfcp_qdio *qdio, int processed)
{
struct zfcp_qdio_queue *queue = &qdio->resp_q;
struct ccw_device *cdev = qdio->adapter->ccw_device;
u8 count, start = queue->first;
unsigned int retval;

count = atomic_read(&queue->count) + processed;

retval = do_QDIO(cdev, QDIO_FLAG_SYNC_INPUT, 0, start, count);

if (unlikely(retval)) {
atomic_set(&queue->count, count);
zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdrpb_1", NULL);
} else {
queue->first += count;
queue->first %= QDIO_MAX_BUFFERS_PER_Q;
atomic_set(&queue->count, 0);
}
}

static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err,
int queue_no, int first, int count,
int queue_no, int idx, int count,
unsigned long parm)
{
struct zfcp_qdio *qdio = (struct zfcp_qdio *) parm;
int sbal_idx, sbal_no;

if (unlikely(qdio_err)) {
zfcp_dbf_hba_qdio(qdio->adapter->dbf, qdio_err, first,
count);
zfcp_dbf_hba_qdio(qdio->adapter->dbf, qdio_err, idx, count);
zfcp_qdio_handler_error(qdio, "qdires1");
return;
}
Expand All @@ -129,16 +104,16 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err,
* returned by QDIO layer
*/
for (sbal_no = 0; sbal_no < count; sbal_no++) {
sbal_idx = (first + sbal_no) % QDIO_MAX_BUFFERS_PER_Q;
sbal_idx = (idx + sbal_no) % QDIO_MAX_BUFFERS_PER_Q;
/* go through all SBALEs of SBAL */
zfcp_fsf_reqid_check(qdio, sbal_idx);
}

/*
* put range of SBALs back to response queue
* (including SBALs which have already been free before)
* put SBALs back to response queue
*/
zfcp_qdio_resp_put_back(qdio, count);
if (do_QDIO(cdev, QDIO_FLAG_SYNC_INPUT, 0, idx, count))
zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdires2", NULL);
}

static struct qdio_buffer_element *
Expand Down Expand Up @@ -185,17 +160,6 @@ zfcp_qdio_sbale_next(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
return zfcp_qdio_sbale_curr(qdio, q_req);
}

static void zfcp_qdio_undo_sbals(struct zfcp_qdio *qdio,
struct zfcp_qdio_req *q_req)
{
struct qdio_buffer **sbal = qdio->req_q.sbal;
int first = q_req->sbal_first;
int last = q_req->sbal_last;
int count = (last - first + QDIO_MAX_BUFFERS_PER_Q) %
QDIO_MAX_BUFFERS_PER_Q + 1;
zfcp_qdio_zero_sbals(sbal, first, count);
}

/**
* zfcp_qdio_sbals_from_sg - fill SBALs from scatter-gather list
* @qdio: pointer to struct zfcp_qdio
Expand All @@ -218,7 +182,8 @@ int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
sbale = zfcp_qdio_sbale_next(qdio, q_req);
if (!sbale) {
atomic_inc(&qdio->req_q_full);
zfcp_qdio_undo_sbals(qdio, q_req);
zfcp_qdio_zero_sbals(qdio->req_q, q_req->sbal_first,
q_req->sbal_number);
return -EINVAL;
}

Expand All @@ -237,10 +202,8 @@ int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,

static int zfcp_qdio_sbal_check(struct zfcp_qdio *qdio)
{
struct zfcp_qdio_queue *req_q = &qdio->req_q;

spin_lock_bh(&qdio->req_q_lock);
if (atomic_read(&req_q->count) ||
if (atomic_read(&qdio->req_q_free) ||
!(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP))
return 1;
spin_unlock_bh(&qdio->req_q_lock);
Expand Down Expand Up @@ -289,25 +252,25 @@ int zfcp_qdio_sbal_get(struct zfcp_qdio *qdio)
*/
int zfcp_qdio_send(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
{
struct zfcp_qdio_queue *req_q = &qdio->req_q;
int first = q_req->sbal_first;
int count = q_req->sbal_number;
int retval;
unsigned int qdio_flags = QDIO_FLAG_SYNC_OUTPUT;
u8 sbal_number = q_req->sbal_number;

zfcp_qdio_account(qdio);

retval = do_QDIO(qdio->adapter->ccw_device, qdio_flags, 0, first,
count);
retval = do_QDIO(qdio->adapter->ccw_device, QDIO_FLAG_SYNC_OUTPUT, 0,
q_req->sbal_first, sbal_number);

if (unlikely(retval)) {
zfcp_qdio_zero_sbals(req_q->sbal, first, count);
zfcp_qdio_zero_sbals(qdio->req_q, q_req->sbal_first,
sbal_number);
return retval;
}

/* account for transferred buffers */
atomic_sub(count, &req_q->count);
req_q->first += count;
req_q->first %= QDIO_MAX_BUFFERS_PER_Q;
atomic_sub(sbal_number, &qdio->req_q_free);
qdio->req_q_idx += sbal_number;
qdio->req_q_idx %= QDIO_MAX_BUFFERS_PER_Q;

return 0;
}

Expand All @@ -329,8 +292,8 @@ static void zfcp_qdio_setup_init_data(struct qdio_initialize *id,
id->input_handler = zfcp_qdio_int_resp;
id->output_handler = zfcp_qdio_int_req;
id->int_parm = (unsigned long) qdio;
id->input_sbal_addr_array = (void **) (qdio->resp_q.sbal);
id->output_sbal_addr_array = (void **) (qdio->req_q.sbal);
id->input_sbal_addr_array = (void **) (qdio->res_q);
id->output_sbal_addr_array = (void **) (qdio->req_q);

}
/**
Expand All @@ -343,8 +306,8 @@ static int zfcp_qdio_allocate(struct zfcp_qdio *qdio)
{
struct qdio_initialize init_data;

if (zfcp_qdio_buffers_enqueue(qdio->req_q.sbal) ||
zfcp_qdio_buffers_enqueue(qdio->resp_q.sbal))
if (zfcp_qdio_buffers_enqueue(qdio->req_q) ||
zfcp_qdio_buffers_enqueue(qdio->res_q))
return -ENOMEM;

zfcp_qdio_setup_init_data(&init_data, qdio);
Expand All @@ -358,34 +321,30 @@ static int zfcp_qdio_allocate(struct zfcp_qdio *qdio)
*/
void zfcp_qdio_close(struct zfcp_qdio *qdio)
{
struct zfcp_qdio_queue *req_q;
int first, count;
struct zfcp_adapter *adapter = qdio->adapter;
int idx, count;

if (!(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP))
if (!(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP))
return;

/* clear QDIOUP flag, thus do_QDIO is not called during qdio_shutdown */
req_q = &qdio->req_q;
spin_lock_bh(&qdio->req_q_lock);
atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &qdio->adapter->status);
atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status);
spin_unlock_bh(&qdio->req_q_lock);

wake_up(&qdio->req_q_wq);

qdio_shutdown(qdio->adapter->ccw_device,
QDIO_FLAG_CLEANUP_USING_CLEAR);
qdio_shutdown(adapter->ccw_device, QDIO_FLAG_CLEANUP_USING_CLEAR);

/* cleanup used outbound sbals */
count = atomic_read(&req_q->count);
count = atomic_read(&qdio->req_q_free);
if (count < QDIO_MAX_BUFFERS_PER_Q) {
first = (req_q->first + count) % QDIO_MAX_BUFFERS_PER_Q;
idx = (qdio->req_q_idx + count) % QDIO_MAX_BUFFERS_PER_Q;
count = QDIO_MAX_BUFFERS_PER_Q - count;
zfcp_qdio_zero_sbals(req_q->sbal, first, count);
zfcp_qdio_zero_sbals(qdio->req_q, idx, count);
}
req_q->first = 0;
atomic_set(&req_q->count, 0);
qdio->resp_q.first = 0;
atomic_set(&qdio->resp_q.count, 0);
qdio->req_q_idx = 0;
atomic_set(&qdio->req_q_free, 0);
}

/**
Expand All @@ -397,10 +356,11 @@ int zfcp_qdio_open(struct zfcp_qdio *qdio)
{
struct qdio_buffer_element *sbale;
struct qdio_initialize init_data;
struct ccw_device *cdev = qdio->adapter->ccw_device;
struct zfcp_adapter *adapter = qdio->adapter;
struct ccw_device *cdev = adapter->ccw_device;
int cc;

if (atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP)
if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP)
return -EIO;

zfcp_qdio_setup_init_data(&init_data, qdio);
Expand All @@ -412,19 +372,18 @@ int zfcp_qdio_open(struct zfcp_qdio *qdio)
goto failed_qdio;

for (cc = 0; cc < QDIO_MAX_BUFFERS_PER_Q; cc++) {
sbale = &(qdio->resp_q.sbal[cc]->element[0]);
sbale = &(qdio->res_q[cc]->element[0]);
sbale->length = 0;
sbale->flags = SBAL_FLAGS_LAST_ENTRY;
sbale->addr = NULL;
}

if (do_QDIO(cdev, QDIO_FLAG_SYNC_INPUT, 0, 0,
QDIO_MAX_BUFFERS_PER_Q))
if (do_QDIO(cdev, QDIO_FLAG_SYNC_INPUT, 0, 0, QDIO_MAX_BUFFERS_PER_Q))
goto failed_qdio;

/* set index of first avalable SBALS / number of available SBALS */
qdio->req_q.first = 0;
atomic_set(&qdio->req_q.count, QDIO_MAX_BUFFERS_PER_Q);
qdio->req_q_idx = 0;
atomic_set(&qdio->req_q_free, QDIO_MAX_BUFFERS_PER_Q);

return 0;

Expand All @@ -438,7 +397,6 @@ int zfcp_qdio_open(struct zfcp_qdio *qdio)

void zfcp_qdio_destroy(struct zfcp_qdio *qdio)
{
struct qdio_buffer **sbal_req, **sbal_resp;
int p;

if (!qdio)
Expand All @@ -447,12 +405,9 @@ void zfcp_qdio_destroy(struct zfcp_qdio *qdio)
if (qdio->adapter->ccw_device)
qdio_free(qdio->adapter->ccw_device);

sbal_req = qdio->req_q.sbal;
sbal_resp = qdio->resp_q.sbal;

for (p = 0; p < QDIO_MAX_BUFFERS_PER_Q; p += QBUFF_PER_PAGE) {
free_page((unsigned long) sbal_req[p]);
free_page((unsigned long) sbal_resp[p]);
free_page((unsigned long) qdio->req_q[p]);
free_page((unsigned long) qdio->res_q[p]);
}

kfree(qdio);
Expand Down
Loading

0 comments on commit 706eca4

Please sign in to comment.