diff options
Diffstat (limited to 'drivers/s390/scsi/zfcp_qdio.c')
-rw-r--r-- | drivers/s390/scsi/zfcp_qdio.c | 47 |
1 files changed, 25 insertions, 22 deletions
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index 33e0a206a0a4..e0a215309df0 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c | |||
@@ -11,9 +11,6 @@ | |||
11 | 11 | ||
12 | #include "zfcp_ext.h" | 12 | #include "zfcp_ext.h" |
13 | 13 | ||
14 | /* FIXME(tune): free space should be one max. SBAL chain plus what? */ | ||
15 | #define ZFCP_QDIO_PCI_INTERVAL (QDIO_MAX_BUFFERS_PER_Q \ | ||
16 | - (FSF_MAX_SBALS_PER_REQ + 4)) | ||
17 | #define QBUFF_PER_PAGE (PAGE_SIZE / sizeof(struct qdio_buffer)) | 14 | #define QBUFF_PER_PAGE (PAGE_SIZE / sizeof(struct qdio_buffer)) |
18 | 15 | ||
19 | static int zfcp_qdio_buffers_enqueue(struct qdio_buffer **sbal) | 16 | static int zfcp_qdio_buffers_enqueue(struct qdio_buffer **sbal) |
@@ -58,7 +55,7 @@ void zfcp_qdio_free(struct zfcp_adapter *adapter) | |||
58 | } | 55 | } |
59 | } | 56 | } |
60 | 57 | ||
61 | static void zfcp_qdio_handler_error(struct zfcp_adapter *adapter, u8 id) | 58 | static void zfcp_qdio_handler_error(struct zfcp_adapter *adapter, char *id) |
62 | { | 59 | { |
63 | dev_warn(&adapter->ccw_device->dev, "A QDIO problem occurred\n"); | 60 | dev_warn(&adapter->ccw_device->dev, "A QDIO problem occurred\n"); |
64 | 61 | ||
@@ -77,6 +74,23 @@ static void zfcp_qdio_zero_sbals(struct qdio_buffer *sbal[], int first, int cnt) | |||
77 | } | 74 | } |
78 | } | 75 | } |
79 | 76 | ||
77 | /* this needs to be called prior to updating the queue fill level */ | ||
78 | static void zfcp_qdio_account(struct zfcp_adapter *adapter) | ||
79 | { | ||
80 | ktime_t now; | ||
81 | s64 span; | ||
82 | int free, used; | ||
83 | |||
84 | spin_lock(&adapter->qdio_stat_lock); | ||
85 | now = ktime_get(); | ||
86 | span = ktime_us_delta(now, adapter->req_q_time); | ||
87 | free = max(0, atomic_read(&adapter->req_q.count)); | ||
88 | used = QDIO_MAX_BUFFERS_PER_Q - free; | ||
89 | adapter->req_q_util += used * span; | ||
90 | adapter->req_q_time = now; | ||
91 | spin_unlock(&adapter->qdio_stat_lock); | ||
92 | } | ||
93 | |||
80 | static void zfcp_qdio_int_req(struct ccw_device *cdev, unsigned int qdio_err, | 94 | static void zfcp_qdio_int_req(struct ccw_device *cdev, unsigned int qdio_err, |
81 | int queue_no, int first, int count, | 95 | int queue_no, int first, int count, |
82 | unsigned long parm) | 96 | unsigned long parm) |
@@ -86,13 +100,14 @@ static void zfcp_qdio_int_req(struct ccw_device *cdev, unsigned int qdio_err, | |||
86 | 100 | ||
87 | if (unlikely(qdio_err)) { | 101 | if (unlikely(qdio_err)) { |
88 | zfcp_hba_dbf_event_qdio(adapter, qdio_err, first, count); | 102 | zfcp_hba_dbf_event_qdio(adapter, qdio_err, first, count); |
89 | zfcp_qdio_handler_error(adapter, 140); | 103 | zfcp_qdio_handler_error(adapter, "qdireq1"); |
90 | return; | 104 | return; |
91 | } | 105 | } |
92 | 106 | ||
93 | /* cleanup all SBALs being program-owned now */ | 107 | /* cleanup all SBALs being program-owned now */ |
94 | zfcp_qdio_zero_sbals(queue->sbal, first, count); | 108 | zfcp_qdio_zero_sbals(queue->sbal, first, count); |
95 | 109 | ||
110 | zfcp_qdio_account(adapter); | ||
96 | atomic_add(count, &queue->count); | 111 | atomic_add(count, &queue->count); |
97 | wake_up(&adapter->request_wq); | 112 | wake_up(&adapter->request_wq); |
98 | } | 113 | } |
@@ -154,7 +169,7 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err, | |||
154 | 169 | ||
155 | if (unlikely(qdio_err)) { | 170 | if (unlikely(qdio_err)) { |
156 | zfcp_hba_dbf_event_qdio(adapter, qdio_err, first, count); | 171 | zfcp_hba_dbf_event_qdio(adapter, qdio_err, first, count); |
157 | zfcp_qdio_handler_error(adapter, 147); | 172 | zfcp_qdio_handler_error(adapter, "qdires1"); |
158 | return; | 173 | return; |
159 | } | 174 | } |
160 | 175 | ||
@@ -346,21 +361,12 @@ int zfcp_qdio_send(struct zfcp_fsf_req *fsf_req) | |||
346 | struct zfcp_qdio_queue *req_q = &adapter->req_q; | 361 | struct zfcp_qdio_queue *req_q = &adapter->req_q; |
347 | int first = fsf_req->sbal_first; | 362 | int first = fsf_req->sbal_first; |
348 | int count = fsf_req->sbal_number; | 363 | int count = fsf_req->sbal_number; |
349 | int retval, pci, pci_batch; | 364 | int retval; |
350 | struct qdio_buffer_element *sbale; | 365 | unsigned int qdio_flags = QDIO_FLAG_SYNC_OUTPUT; |
351 | 366 | ||
352 | /* acknowledgements for transferred buffers */ | 367 | zfcp_qdio_account(adapter); |
353 | pci_batch = adapter->req_q_pci_batch + count; | ||
354 | if (unlikely(pci_batch >= ZFCP_QDIO_PCI_INTERVAL)) { | ||
355 | pci_batch %= ZFCP_QDIO_PCI_INTERVAL; | ||
356 | pci = first + count - (pci_batch + 1); | ||
357 | pci %= QDIO_MAX_BUFFERS_PER_Q; | ||
358 | sbale = zfcp_qdio_sbale(req_q, pci, 0); | ||
359 | sbale->flags |= SBAL_FLAGS0_PCI; | ||
360 | } | ||
361 | 368 | ||
362 | retval = do_QDIO(adapter->ccw_device, QDIO_FLAG_SYNC_OUTPUT, 0, first, | 369 | retval = do_QDIO(adapter->ccw_device, qdio_flags, 0, first, count); |
363 | count); | ||
364 | if (unlikely(retval)) { | 370 | if (unlikely(retval)) { |
365 | zfcp_qdio_zero_sbals(req_q->sbal, first, count); | 371 | zfcp_qdio_zero_sbals(req_q->sbal, first, count); |
366 | return retval; | 372 | return retval; |
@@ -370,7 +376,6 @@ int zfcp_qdio_send(struct zfcp_fsf_req *fsf_req) | |||
370 | atomic_sub(count, &req_q->count); | 376 | atomic_sub(count, &req_q->count); |
371 | req_q->first += count; | 377 | req_q->first += count; |
372 | req_q->first %= QDIO_MAX_BUFFERS_PER_Q; | 378 | req_q->first %= QDIO_MAX_BUFFERS_PER_Q; |
373 | adapter->req_q_pci_batch = pci_batch; | ||
374 | return 0; | 379 | return 0; |
375 | } | 380 | } |
376 | 381 | ||
@@ -441,7 +446,6 @@ void zfcp_qdio_close(struct zfcp_adapter *adapter) | |||
441 | } | 446 | } |
442 | req_q->first = 0; | 447 | req_q->first = 0; |
443 | atomic_set(&req_q->count, 0); | 448 | atomic_set(&req_q->count, 0); |
444 | adapter->req_q_pci_batch = 0; | ||
445 | adapter->resp_q.first = 0; | 449 | adapter->resp_q.first = 0; |
446 | atomic_set(&adapter->resp_q.count, 0); | 450 | atomic_set(&adapter->resp_q.count, 0); |
447 | } | 451 | } |
@@ -479,7 +483,6 @@ int zfcp_qdio_open(struct zfcp_adapter *adapter) | |||
479 | /* set index of first avalable SBALS / number of available SBALS */ | 483 | /* set index of first avalable SBALS / number of available SBALS */ |
480 | adapter->req_q.first = 0; | 484 | adapter->req_q.first = 0; |
481 | atomic_set(&adapter->req_q.count, QDIO_MAX_BUFFERS_PER_Q); | 485 | atomic_set(&adapter->req_q.count, QDIO_MAX_BUFFERS_PER_Q); |
482 | adapter->req_q_pci_batch = 0; | ||
483 | 486 | ||
484 | return 0; | 487 | return 0; |
485 | 488 | ||