Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 204317
b: refs/heads/master
c: 706eca4
h: refs/heads/master
i:
  204315: ab67111
v: v3
  • Loading branch information
Swen Schillig authored and James Bottomley committed Jul 28, 2010
1 parent 43066aa commit dd164c5
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 140 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 01b047599ade30051bf6c14fbe64181d1fec3dfa
refs/heads/master: 706eca49a044a1ea89352dcc4b96ffc1631b2cb5
10 changes: 4 additions & 6 deletions trunk/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 trunk/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 dd164c5

Please sign in to comment.