diff options
Diffstat (limited to 'drivers/s390/scsi/zfcp_qdio.c')
-rw-r--r-- | drivers/s390/scsi/zfcp_qdio.c | 206 |
1 files changed, 92 insertions, 114 deletions
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index 6fa5e0453176..b2635759721c 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c | |||
@@ -30,12 +30,15 @@ static int zfcp_qdio_buffers_enqueue(struct qdio_buffer **sbal) | |||
30 | return 0; | 30 | return 0; |
31 | } | 31 | } |
32 | 32 | ||
33 | static void zfcp_qdio_handler_error(struct zfcp_qdio *qdio, char *id) | 33 | static void zfcp_qdio_handler_error(struct zfcp_qdio *qdio, char *id, |
34 | unsigned int qdio_err) | ||
34 | { | 35 | { |
35 | struct zfcp_adapter *adapter = qdio->adapter; | 36 | struct zfcp_adapter *adapter = qdio->adapter; |
36 | 37 | ||
37 | dev_warn(&adapter->ccw_device->dev, "A QDIO problem occurred\n"); | 38 | dev_warn(&adapter->ccw_device->dev, "A QDIO problem occurred\n"); |
38 | 39 | ||
40 | if (qdio_err & QDIO_ERROR_SLSB_STATE) | ||
41 | zfcp_qdio_siosl(adapter); | ||
39 | zfcp_erp_adapter_reopen(adapter, | 42 | zfcp_erp_adapter_reopen(adapter, |
40 | ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | | 43 | ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | |
41 | ZFCP_STATUS_COMMON_ERP_FAILED, id, NULL); | 44 | ZFCP_STATUS_COMMON_ERP_FAILED, id, NULL); |
@@ -55,72 +58,47 @@ static void zfcp_qdio_zero_sbals(struct qdio_buffer *sbal[], int first, int cnt) | |||
55 | static inline void zfcp_qdio_account(struct zfcp_qdio *qdio) | 58 | static inline void zfcp_qdio_account(struct zfcp_qdio *qdio) |
56 | { | 59 | { |
57 | unsigned long long now, span; | 60 | unsigned long long now, span; |
58 | int free, used; | 61 | int used; |
59 | 62 | ||
60 | spin_lock(&qdio->stat_lock); | 63 | spin_lock(&qdio->stat_lock); |
61 | now = get_clock_monotonic(); | 64 | now = get_clock_monotonic(); |
62 | span = (now - qdio->req_q_time) >> 12; | 65 | span = (now - qdio->req_q_time) >> 12; |
63 | free = atomic_read(&qdio->req_q.count); | 66 | used = QDIO_MAX_BUFFERS_PER_Q - atomic_read(&qdio->req_q_free); |
64 | used = QDIO_MAX_BUFFERS_PER_Q - free; | ||
65 | qdio->req_q_util += used * span; | 67 | qdio->req_q_util += used * span; |
66 | qdio->req_q_time = now; | 68 | qdio->req_q_time = now; |
67 | spin_unlock(&qdio->stat_lock); | 69 | spin_unlock(&qdio->stat_lock); |
68 | } | 70 | } |
69 | 71 | ||
70 | static void zfcp_qdio_int_req(struct ccw_device *cdev, unsigned int qdio_err, | 72 | static void zfcp_qdio_int_req(struct ccw_device *cdev, unsigned int qdio_err, |
71 | int queue_no, int first, int count, | 73 | int queue_no, int idx, int count, |
72 | unsigned long parm) | 74 | unsigned long parm) |
73 | { | 75 | { |
74 | struct zfcp_qdio *qdio = (struct zfcp_qdio *) parm; | 76 | struct zfcp_qdio *qdio = (struct zfcp_qdio *) parm; |
75 | struct zfcp_qdio_queue *queue = &qdio->req_q; | ||
76 | 77 | ||
77 | if (unlikely(qdio_err)) { | 78 | if (unlikely(qdio_err)) { |
78 | zfcp_dbf_hba_qdio(qdio->adapter->dbf, qdio_err, first, | 79 | zfcp_dbf_hba_qdio(qdio->adapter->dbf, qdio_err, idx, count); |
79 | count); | 80 | zfcp_qdio_handler_error(qdio, "qdireq1", qdio_err); |
80 | zfcp_qdio_handler_error(qdio, "qdireq1"); | ||
81 | return; | 81 | return; |
82 | } | 82 | } |
83 | 83 | ||
84 | /* cleanup all SBALs being program-owned now */ | 84 | /* cleanup all SBALs being program-owned now */ |
85 | zfcp_qdio_zero_sbals(queue->sbal, first, count); | 85 | zfcp_qdio_zero_sbals(qdio->req_q, idx, count); |
86 | 86 | ||
87 | zfcp_qdio_account(qdio); | 87 | zfcp_qdio_account(qdio); |
88 | atomic_add(count, &queue->count); | 88 | atomic_add(count, &qdio->req_q_free); |
89 | wake_up(&qdio->req_q_wq); | 89 | wake_up(&qdio->req_q_wq); |
90 | } | 90 | } |
91 | 91 | ||
92 | static void zfcp_qdio_resp_put_back(struct zfcp_qdio *qdio, int processed) | ||
93 | { | ||
94 | struct zfcp_qdio_queue *queue = &qdio->resp_q; | ||
95 | struct ccw_device *cdev = qdio->adapter->ccw_device; | ||
96 | u8 count, start = queue->first; | ||
97 | unsigned int retval; | ||
98 | |||
99 | count = atomic_read(&queue->count) + processed; | ||
100 | |||
101 | retval = do_QDIO(cdev, QDIO_FLAG_SYNC_INPUT, 0, start, count); | ||
102 | |||
103 | if (unlikely(retval)) { | ||
104 | atomic_set(&queue->count, count); | ||
105 | zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdrpb_1", NULL); | ||
106 | } else { | ||
107 | queue->first += count; | ||
108 | queue->first %= QDIO_MAX_BUFFERS_PER_Q; | ||
109 | atomic_set(&queue->count, 0); | ||
110 | } | ||
111 | } | ||
112 | |||
113 | static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err, | 92 | static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err, |
114 | int queue_no, int first, int count, | 93 | int queue_no, int idx, int count, |
115 | unsigned long parm) | 94 | unsigned long parm) |
116 | { | 95 | { |
117 | struct zfcp_qdio *qdio = (struct zfcp_qdio *) parm; | 96 | struct zfcp_qdio *qdio = (struct zfcp_qdio *) parm; |
118 | int sbal_idx, sbal_no; | 97 | int sbal_idx, sbal_no; |
119 | 98 | ||
120 | if (unlikely(qdio_err)) { | 99 | if (unlikely(qdio_err)) { |
121 | zfcp_dbf_hba_qdio(qdio->adapter->dbf, qdio_err, first, | 100 | zfcp_dbf_hba_qdio(qdio->adapter->dbf, qdio_err, idx, count); |
122 | count); | 101 | zfcp_qdio_handler_error(qdio, "qdires1", qdio_err); |
123 | zfcp_qdio_handler_error(qdio, "qdires1"); | ||
124 | return; | 102 | return; |
125 | } | 103 | } |
126 | 104 | ||
@@ -129,25 +107,16 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err, | |||
129 | * returned by QDIO layer | 107 | * returned by QDIO layer |
130 | */ | 108 | */ |
131 | for (sbal_no = 0; sbal_no < count; sbal_no++) { | 109 | for (sbal_no = 0; sbal_no < count; sbal_no++) { |
132 | sbal_idx = (first + sbal_no) % QDIO_MAX_BUFFERS_PER_Q; | 110 | sbal_idx = (idx + sbal_no) % QDIO_MAX_BUFFERS_PER_Q; |
133 | /* go through all SBALEs of SBAL */ | 111 | /* go through all SBALEs of SBAL */ |
134 | zfcp_fsf_reqid_check(qdio, sbal_idx); | 112 | zfcp_fsf_reqid_check(qdio, sbal_idx); |
135 | } | 113 | } |
136 | 114 | ||
137 | /* | 115 | /* |
138 | * put range of SBALs back to response queue | 116 | * put SBALs back to response queue |
139 | * (including SBALs which have already been free before) | ||
140 | */ | 117 | */ |
141 | zfcp_qdio_resp_put_back(qdio, count); | 118 | if (do_QDIO(cdev, QDIO_FLAG_SYNC_INPUT, 0, idx, count)) |
142 | } | 119 | zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdires2", NULL); |
143 | |||
144 | static void zfcp_qdio_sbal_limit(struct zfcp_qdio *qdio, | ||
145 | struct zfcp_qdio_req *q_req, int max_sbals) | ||
146 | { | ||
147 | int count = atomic_read(&qdio->req_q.count); | ||
148 | count = min(count, max_sbals); | ||
149 | q_req->sbal_limit = (q_req->sbal_first + count - 1) | ||
150 | % QDIO_MAX_BUFFERS_PER_Q; | ||
151 | } | 120 | } |
152 | 121 | ||
153 | static struct qdio_buffer_element * | 122 | static struct qdio_buffer_element * |
@@ -173,6 +142,7 @@ zfcp_qdio_sbal_chain(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req) | |||
173 | 142 | ||
174 | /* keep this requests number of SBALs up-to-date */ | 143 | /* keep this requests number of SBALs up-to-date */ |
175 | q_req->sbal_number++; | 144 | q_req->sbal_number++; |
145 | BUG_ON(q_req->sbal_number > ZFCP_QDIO_MAX_SBALS_PER_REQ); | ||
176 | 146 | ||
177 | /* start at first SBALE of new SBAL */ | 147 | /* start at first SBALE of new SBAL */ |
178 | q_req->sbale_curr = 0; | 148 | q_req->sbale_curr = 0; |
@@ -193,17 +163,6 @@ zfcp_qdio_sbale_next(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req) | |||
193 | return zfcp_qdio_sbale_curr(qdio, q_req); | 163 | return zfcp_qdio_sbale_curr(qdio, q_req); |
194 | } | 164 | } |
195 | 165 | ||
196 | static void zfcp_qdio_undo_sbals(struct zfcp_qdio *qdio, | ||
197 | struct zfcp_qdio_req *q_req) | ||
198 | { | ||
199 | struct qdio_buffer **sbal = qdio->req_q.sbal; | ||
200 | int first = q_req->sbal_first; | ||
201 | int last = q_req->sbal_last; | ||
202 | int count = (last - first + QDIO_MAX_BUFFERS_PER_Q) % | ||
203 | QDIO_MAX_BUFFERS_PER_Q + 1; | ||
204 | zfcp_qdio_zero_sbals(sbal, first, count); | ||
205 | } | ||
206 | |||
207 | /** | 166 | /** |
208 | * zfcp_qdio_sbals_from_sg - fill SBALs from scatter-gather list | 167 | * zfcp_qdio_sbals_from_sg - fill SBALs from scatter-gather list |
209 | * @qdio: pointer to struct zfcp_qdio | 168 | * @qdio: pointer to struct zfcp_qdio |
@@ -213,14 +172,11 @@ static void zfcp_qdio_undo_sbals(struct zfcp_qdio *qdio, | |||
213 | * Returns: number of bytes, or error (negativ) | 172 | * Returns: number of bytes, or error (negativ) |
214 | */ | 173 | */ |
215 | int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req, | 174 | int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req, |
216 | struct scatterlist *sg, int max_sbals) | 175 | struct scatterlist *sg) |
217 | { | 176 | { |
218 | struct qdio_buffer_element *sbale; | 177 | struct qdio_buffer_element *sbale; |
219 | int bytes = 0; | 178 | int bytes = 0; |
220 | 179 | ||
221 | /* figure out last allowed SBAL */ | ||
222 | zfcp_qdio_sbal_limit(qdio, q_req, max_sbals); | ||
223 | |||
224 | /* set storage-block type for this request */ | 180 | /* set storage-block type for this request */ |
225 | sbale = zfcp_qdio_sbale_req(qdio, q_req); | 181 | sbale = zfcp_qdio_sbale_req(qdio, q_req); |
226 | sbale->flags |= q_req->sbtype; | 182 | sbale->flags |= q_req->sbtype; |
@@ -229,7 +185,8 @@ int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req, | |||
229 | sbale = zfcp_qdio_sbale_next(qdio, q_req); | 185 | sbale = zfcp_qdio_sbale_next(qdio, q_req); |
230 | if (!sbale) { | 186 | if (!sbale) { |
231 | atomic_inc(&qdio->req_q_full); | 187 | atomic_inc(&qdio->req_q_full); |
232 | zfcp_qdio_undo_sbals(qdio, q_req); | 188 | zfcp_qdio_zero_sbals(qdio->req_q, q_req->sbal_first, |
189 | q_req->sbal_number); | ||
233 | return -EINVAL; | 190 | return -EINVAL; |
234 | } | 191 | } |
235 | 192 | ||
@@ -239,19 +196,13 @@ int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req, | |||
239 | bytes += sg->length; | 196 | bytes += sg->length; |
240 | } | 197 | } |
241 | 198 | ||
242 | /* assume that no other SBALEs are to follow in the same SBAL */ | ||
243 | sbale = zfcp_qdio_sbale_curr(qdio, q_req); | ||
244 | sbale->flags |= SBAL_FLAGS_LAST_ENTRY; | ||
245 | |||
246 | return bytes; | 199 | return bytes; |
247 | } | 200 | } |
248 | 201 | ||
249 | static int zfcp_qdio_sbal_check(struct zfcp_qdio *qdio) | 202 | static int zfcp_qdio_sbal_check(struct zfcp_qdio *qdio) |
250 | { | 203 | { |
251 | struct zfcp_qdio_queue *req_q = &qdio->req_q; | ||
252 | |||
253 | spin_lock_bh(&qdio->req_q_lock); | 204 | spin_lock_bh(&qdio->req_q_lock); |
254 | if (atomic_read(&req_q->count) || | 205 | if (atomic_read(&qdio->req_q_free) || |
255 | !(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP)) | 206 | !(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP)) |
256 | return 1; | 207 | return 1; |
257 | spin_unlock_bh(&qdio->req_q_lock); | 208 | spin_unlock_bh(&qdio->req_q_lock); |
@@ -300,25 +251,25 @@ int zfcp_qdio_sbal_get(struct zfcp_qdio *qdio) | |||
300 | */ | 251 | */ |
301 | int zfcp_qdio_send(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req) | 252 | int zfcp_qdio_send(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req) |
302 | { | 253 | { |
303 | struct zfcp_qdio_queue *req_q = &qdio->req_q; | ||
304 | int first = q_req->sbal_first; | ||
305 | int count = q_req->sbal_number; | ||
306 | int retval; | 254 | int retval; |
307 | unsigned int qdio_flags = QDIO_FLAG_SYNC_OUTPUT; | 255 | u8 sbal_number = q_req->sbal_number; |
308 | 256 | ||
309 | zfcp_qdio_account(qdio); | 257 | zfcp_qdio_account(qdio); |
310 | 258 | ||
311 | retval = do_QDIO(qdio->adapter->ccw_device, qdio_flags, 0, first, | 259 | retval = do_QDIO(qdio->adapter->ccw_device, QDIO_FLAG_SYNC_OUTPUT, 0, |
312 | count); | 260 | q_req->sbal_first, sbal_number); |
261 | |||
313 | if (unlikely(retval)) { | 262 | if (unlikely(retval)) { |
314 | zfcp_qdio_zero_sbals(req_q->sbal, first, count); | 263 | zfcp_qdio_zero_sbals(qdio->req_q, q_req->sbal_first, |
264 | sbal_number); | ||
315 | return retval; | 265 | return retval; |
316 | } | 266 | } |
317 | 267 | ||
318 | /* account for transferred buffers */ | 268 | /* account for transferred buffers */ |
319 | atomic_sub(count, &req_q->count); | 269 | atomic_sub(sbal_number, &qdio->req_q_free); |
320 | req_q->first += count; | 270 | qdio->req_q_idx += sbal_number; |
321 | req_q->first %= QDIO_MAX_BUFFERS_PER_Q; | 271 | qdio->req_q_idx %= QDIO_MAX_BUFFERS_PER_Q; |
272 | |||
322 | return 0; | 273 | return 0; |
323 | } | 274 | } |
324 | 275 | ||
@@ -331,6 +282,7 @@ static void zfcp_qdio_setup_init_data(struct qdio_initialize *id, | |||
331 | id->q_format = QDIO_ZFCP_QFMT; | 282 | id->q_format = QDIO_ZFCP_QFMT; |
332 | memcpy(id->adapter_name, dev_name(&id->cdev->dev), 8); | 283 | memcpy(id->adapter_name, dev_name(&id->cdev->dev), 8); |
333 | ASCEBC(id->adapter_name, 8); | 284 | ASCEBC(id->adapter_name, 8); |
285 | id->qib_rflags = QIB_RFLAGS_ENABLE_DATA_DIV; | ||
334 | id->qib_param_field_format = 0; | 286 | id->qib_param_field_format = 0; |
335 | id->qib_param_field = NULL; | 287 | id->qib_param_field = NULL; |
336 | id->input_slib_elements = NULL; | 288 | id->input_slib_elements = NULL; |
@@ -340,10 +292,10 @@ static void zfcp_qdio_setup_init_data(struct qdio_initialize *id, | |||
340 | id->input_handler = zfcp_qdio_int_resp; | 292 | id->input_handler = zfcp_qdio_int_resp; |
341 | id->output_handler = zfcp_qdio_int_req; | 293 | id->output_handler = zfcp_qdio_int_req; |
342 | id->int_parm = (unsigned long) qdio; | 294 | id->int_parm = (unsigned long) qdio; |
343 | id->input_sbal_addr_array = (void **) (qdio->resp_q.sbal); | 295 | id->input_sbal_addr_array = (void **) (qdio->res_q); |
344 | id->output_sbal_addr_array = (void **) (qdio->req_q.sbal); | 296 | id->output_sbal_addr_array = (void **) (qdio->req_q); |
345 | |||
346 | } | 297 | } |
298 | |||
347 | /** | 299 | /** |
348 | * zfcp_qdio_allocate - allocate queue memory and initialize QDIO data | 300 | * zfcp_qdio_allocate - allocate queue memory and initialize QDIO data |
349 | * @adapter: pointer to struct zfcp_adapter | 301 | * @adapter: pointer to struct zfcp_adapter |
@@ -354,8 +306,8 @@ static int zfcp_qdio_allocate(struct zfcp_qdio *qdio) | |||
354 | { | 306 | { |
355 | struct qdio_initialize init_data; | 307 | struct qdio_initialize init_data; |
356 | 308 | ||
357 | if (zfcp_qdio_buffers_enqueue(qdio->req_q.sbal) || | 309 | if (zfcp_qdio_buffers_enqueue(qdio->req_q) || |
358 | zfcp_qdio_buffers_enqueue(qdio->resp_q.sbal)) | 310 | zfcp_qdio_buffers_enqueue(qdio->res_q)) |
359 | return -ENOMEM; | 311 | return -ENOMEM; |
360 | 312 | ||
361 | zfcp_qdio_setup_init_data(&init_data, qdio); | 313 | zfcp_qdio_setup_init_data(&init_data, qdio); |
@@ -369,34 +321,30 @@ static int zfcp_qdio_allocate(struct zfcp_qdio *qdio) | |||
369 | */ | 321 | */ |
370 | void zfcp_qdio_close(struct zfcp_qdio *qdio) | 322 | void zfcp_qdio_close(struct zfcp_qdio *qdio) |
371 | { | 323 | { |
372 | struct zfcp_qdio_queue *req_q; | 324 | struct zfcp_adapter *adapter = qdio->adapter; |
373 | int first, count; | 325 | int idx, count; |
374 | 326 | ||
375 | if (!(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP)) | 327 | if (!(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP)) |
376 | return; | 328 | return; |
377 | 329 | ||
378 | /* clear QDIOUP flag, thus do_QDIO is not called during qdio_shutdown */ | 330 | /* clear QDIOUP flag, thus do_QDIO is not called during qdio_shutdown */ |
379 | req_q = &qdio->req_q; | ||
380 | spin_lock_bh(&qdio->req_q_lock); | 331 | spin_lock_bh(&qdio->req_q_lock); |
381 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &qdio->adapter->status); | 332 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status); |
382 | spin_unlock_bh(&qdio->req_q_lock); | 333 | spin_unlock_bh(&qdio->req_q_lock); |
383 | 334 | ||
384 | wake_up(&qdio->req_q_wq); | 335 | wake_up(&qdio->req_q_wq); |
385 | 336 | ||
386 | qdio_shutdown(qdio->adapter->ccw_device, | 337 | qdio_shutdown(adapter->ccw_device, QDIO_FLAG_CLEANUP_USING_CLEAR); |
387 | QDIO_FLAG_CLEANUP_USING_CLEAR); | ||
388 | 338 | ||
389 | /* cleanup used outbound sbals */ | 339 | /* cleanup used outbound sbals */ |
390 | count = atomic_read(&req_q->count); | 340 | count = atomic_read(&qdio->req_q_free); |
391 | if (count < QDIO_MAX_BUFFERS_PER_Q) { | 341 | if (count < QDIO_MAX_BUFFERS_PER_Q) { |
392 | first = (req_q->first + count) % QDIO_MAX_BUFFERS_PER_Q; | 342 | idx = (qdio->req_q_idx + count) % QDIO_MAX_BUFFERS_PER_Q; |
393 | count = QDIO_MAX_BUFFERS_PER_Q - count; | 343 | count = QDIO_MAX_BUFFERS_PER_Q - count; |
394 | zfcp_qdio_zero_sbals(req_q->sbal, first, count); | 344 | zfcp_qdio_zero_sbals(qdio->req_q, idx, count); |
395 | } | 345 | } |
396 | req_q->first = 0; | 346 | qdio->req_q_idx = 0; |
397 | atomic_set(&req_q->count, 0); | 347 | atomic_set(&qdio->req_q_free, 0); |
398 | qdio->resp_q.first = 0; | ||
399 | atomic_set(&qdio->resp_q.count, 0); | ||
400 | } | 348 | } |
401 | 349 | ||
402 | /** | 350 | /** |
@@ -408,34 +356,45 @@ int zfcp_qdio_open(struct zfcp_qdio *qdio) | |||
408 | { | 356 | { |
409 | struct qdio_buffer_element *sbale; | 357 | struct qdio_buffer_element *sbale; |
410 | struct qdio_initialize init_data; | 358 | struct qdio_initialize init_data; |
411 | struct ccw_device *cdev = qdio->adapter->ccw_device; | 359 | struct zfcp_adapter *adapter = qdio->adapter; |
360 | struct ccw_device *cdev = adapter->ccw_device; | ||
361 | struct qdio_ssqd_desc ssqd; | ||
412 | int cc; | 362 | int cc; |
413 | 363 | ||
414 | if (atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP) | 364 | if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP) |
415 | return -EIO; | 365 | return -EIO; |
416 | 366 | ||
367 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_SIOSL_ISSUED, | ||
368 | &qdio->adapter->status); | ||
369 | |||
417 | zfcp_qdio_setup_init_data(&init_data, qdio); | 370 | zfcp_qdio_setup_init_data(&init_data, qdio); |
418 | 371 | ||
419 | if (qdio_establish(&init_data)) | 372 | if (qdio_establish(&init_data)) |
420 | goto failed_establish; | 373 | goto failed_establish; |
421 | 374 | ||
375 | if (qdio_get_ssqd_desc(init_data.cdev, &ssqd)) | ||
376 | goto failed_qdio; | ||
377 | |||
378 | if (ssqd.qdioac2 & CHSC_AC2_DATA_DIV_ENABLED) | ||
379 | atomic_set_mask(ZFCP_STATUS_ADAPTER_DATA_DIV_ENABLED, | ||
380 | &qdio->adapter->status); | ||
381 | |||
422 | if (qdio_activate(cdev)) | 382 | if (qdio_activate(cdev)) |
423 | goto failed_qdio; | 383 | goto failed_qdio; |
424 | 384 | ||
425 | for (cc = 0; cc < QDIO_MAX_BUFFERS_PER_Q; cc++) { | 385 | for (cc = 0; cc < QDIO_MAX_BUFFERS_PER_Q; cc++) { |
426 | sbale = &(qdio->resp_q.sbal[cc]->element[0]); | 386 | sbale = &(qdio->res_q[cc]->element[0]); |
427 | sbale->length = 0; | 387 | sbale->length = 0; |
428 | sbale->flags = SBAL_FLAGS_LAST_ENTRY; | 388 | sbale->flags = SBAL_FLAGS_LAST_ENTRY; |
429 | sbale->addr = NULL; | 389 | sbale->addr = NULL; |
430 | } | 390 | } |
431 | 391 | ||
432 | if (do_QDIO(cdev, QDIO_FLAG_SYNC_INPUT, 0, 0, | 392 | if (do_QDIO(cdev, QDIO_FLAG_SYNC_INPUT, 0, 0, QDIO_MAX_BUFFERS_PER_Q)) |
433 | QDIO_MAX_BUFFERS_PER_Q)) | ||
434 | goto failed_qdio; | 393 | goto failed_qdio; |
435 | 394 | ||
436 | /* set index of first avalable SBALS / number of available SBALS */ | 395 | /* set index of first avalable SBALS / number of available SBALS */ |
437 | qdio->req_q.first = 0; | 396 | qdio->req_q_idx = 0; |
438 | atomic_set(&qdio->req_q.count, QDIO_MAX_BUFFERS_PER_Q); | 397 | atomic_set(&qdio->req_q_free, QDIO_MAX_BUFFERS_PER_Q); |
439 | 398 | ||
440 | return 0; | 399 | return 0; |
441 | 400 | ||
@@ -449,7 +408,6 @@ failed_establish: | |||
449 | 408 | ||
450 | void zfcp_qdio_destroy(struct zfcp_qdio *qdio) | 409 | void zfcp_qdio_destroy(struct zfcp_qdio *qdio) |
451 | { | 410 | { |
452 | struct qdio_buffer **sbal_req, **sbal_resp; | ||
453 | int p; | 411 | int p; |
454 | 412 | ||
455 | if (!qdio) | 413 | if (!qdio) |
@@ -458,12 +416,9 @@ void zfcp_qdio_destroy(struct zfcp_qdio *qdio) | |||
458 | if (qdio->adapter->ccw_device) | 416 | if (qdio->adapter->ccw_device) |
459 | qdio_free(qdio->adapter->ccw_device); | 417 | qdio_free(qdio->adapter->ccw_device); |
460 | 418 | ||
461 | sbal_req = qdio->req_q.sbal; | ||
462 | sbal_resp = qdio->resp_q.sbal; | ||
463 | |||
464 | for (p = 0; p < QDIO_MAX_BUFFERS_PER_Q; p += QBUFF_PER_PAGE) { | 419 | for (p = 0; p < QDIO_MAX_BUFFERS_PER_Q; p += QBUFF_PER_PAGE) { |
465 | free_page((unsigned long) sbal_req[p]); | 420 | free_page((unsigned long) qdio->req_q[p]); |
466 | free_page((unsigned long) sbal_resp[p]); | 421 | free_page((unsigned long) qdio->res_q[p]); |
467 | } | 422 | } |
468 | 423 | ||
469 | kfree(qdio); | 424 | kfree(qdio); |
@@ -491,3 +446,26 @@ int zfcp_qdio_setup(struct zfcp_adapter *adapter) | |||
491 | return 0; | 446 | return 0; |
492 | } | 447 | } |
493 | 448 | ||
449 | /** | ||
450 | * zfcp_qdio_siosl - Trigger logging in FCP channel | ||
451 | * @adapter: The zfcp_adapter where to trigger logging | ||
452 | * | ||
453 | * Call the cio siosl function to trigger hardware logging. This | ||
454 | * wrapper function sets a flag to ensure hardware logging is only | ||
455 | * triggered once before going through qdio shutdown. | ||
456 | * | ||
457 | * The triggers are always run from qdio tasklet context, so no | ||
458 | * additional synchronization is necessary. | ||
459 | */ | ||
460 | void zfcp_qdio_siosl(struct zfcp_adapter *adapter) | ||
461 | { | ||
462 | int rc; | ||
463 | |||
464 | if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_SIOSL_ISSUED) | ||
465 | return; | ||
466 | |||
467 | rc = ccw_device_siosl(adapter->ccw_device); | ||
468 | if (!rc) | ||
469 | atomic_set_mask(ZFCP_STATUS_ADAPTER_SIOSL_ISSUED, | ||
470 | &adapter->status); | ||
471 | } | ||