diff options
Diffstat (limited to 'drivers/s390/scsi/zfcp_qdio.c')
-rw-r--r-- | drivers/s390/scsi/zfcp_qdio.c | 141 |
1 files changed, 48 insertions, 93 deletions
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index 7ab1ac16a11f..a638278c6025 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c @@ -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; } @@ -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 * @@ -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 @@ -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; } @@ -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); @@ -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; } @@ -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); } /** @@ -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); @@ -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); } /** @@ -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); @@ -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; @@ -438,7 +397,6 @@ failed_establish: void zfcp_qdio_destroy(struct zfcp_qdio *qdio) { - struct qdio_buffer **sbal_req, **sbal_resp; int p; if (!qdio) @@ -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); |