mips: add export.h to files using EXPORT_SYMBOL/THIS_MODULE
[deliverable/linux.git] / drivers / s390 / scsi / zfcp_qdio.c
CommitLineData
1da177e4 1/*
00bab910 2 * zfcp device driver
1da177e4 3 *
00bab910 4 * Setup and helper functions to access QDIO.
1da177e4 5 *
1674b405 6 * Copyright IBM Corporation 2002, 2010
1da177e4
LT
7 */
8
ecf39d42
CS
9#define KMSG_COMPONENT "zfcp"
10#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
11
5a0e3ad6 12#include <linux/slab.h>
1da177e4 13#include "zfcp_ext.h"
34c2b712 14#include "zfcp_qdio.h"
1da177e4 15
5d4e2262 16#define QBUFF_PER_PAGE (PAGE_SIZE / sizeof(struct qdio_buffer))
1da177e4 17
86a9668a
SS
18static bool enable_multibuffer;
19module_param_named(datarouter, enable_multibuffer, bool, 0400);
20MODULE_PARM_DESC(datarouter, "Enable hardware data router support");
21
00bab910 22static int zfcp_qdio_buffers_enqueue(struct qdio_buffer **sbal)
1da177e4 23{
b4e44590 24 int pos;
1da177e4 25
b4e44590 26 for (pos = 0; pos < QDIO_MAX_BUFFERS_PER_Q; pos += QBUFF_PER_PAGE) {
00bab910
SS
27 sbal[pos] = (struct qdio_buffer *) get_zeroed_page(GFP_KERNEL);
28 if (!sbal[pos])
b4e44590 29 return -ENOMEM;
b4e44590
SS
30 }
31 for (pos = 0; pos < QDIO_MAX_BUFFERS_PER_Q; pos++)
32 if (pos % QBUFF_PER_PAGE)
00bab910 33 sbal[pos] = sbal[pos - 1] + 1;
b4e44590 34 return 0;
1da177e4
LT
35}
36
339f4f4e
CS
37static void zfcp_qdio_handler_error(struct zfcp_qdio *qdio, char *id,
38 unsigned int qdio_err)
1da177e4 39{
564e1c86
SS
40 struct zfcp_adapter *adapter = qdio->adapter;
41
ff3b24fa 42 dev_warn(&adapter->ccw_device->dev, "A QDIO problem occurred\n");
1da177e4 43
86a9668a 44 if (qdio_err & QDIO_ERROR_SLSB_STATE) {
339f4f4e 45 zfcp_qdio_siosl(adapter);
86a9668a
SS
46 zfcp_erp_adapter_shutdown(adapter, 0, id);
47 return;
48 }
00bab910
SS
49 zfcp_erp_adapter_reopen(adapter,
50 ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
ea4a3a6a 51 ZFCP_STATUS_COMMON_ERP_FAILED, id);
1da177e4
LT
52}
53
5d4e2262
CS
54static void zfcp_qdio_zero_sbals(struct qdio_buffer *sbal[], int first, int cnt)
55{
56 int i, sbal_idx;
57
58 for (i = first; i < first + cnt; i++) {
59 sbal_idx = i % QDIO_MAX_BUFFERS_PER_Q;
60 memset(sbal[sbal_idx], 0, sizeof(struct qdio_buffer));
61 }
62}
63
94506fd1 64/* this needs to be called prior to updating the queue fill level */
41e05a12 65static inline void zfcp_qdio_account(struct zfcp_qdio *qdio)
94506fd1 66{
41e05a12 67 unsigned long long now, span;
706eca49 68 int used;
94506fd1 69
41e05a12
HC
70 now = get_clock_monotonic();
71 span = (now - qdio->req_q_time) >> 12;
706eca49 72 used = QDIO_MAX_BUFFERS_PER_Q - atomic_read(&qdio->req_q_free);
564e1c86
SS
73 qdio->req_q_util += used * span;
74 qdio->req_q_time = now;
94506fd1
MP
75}
76
779e6e1c 77static void zfcp_qdio_int_req(struct ccw_device *cdev, unsigned int qdio_err,
706eca49 78 int queue_no, int idx, int count,
00bab910 79 unsigned long parm)
1da177e4 80{
564e1c86 81 struct zfcp_qdio *qdio = (struct zfcp_qdio *) parm;
1da177e4 82
779e6e1c 83 if (unlikely(qdio_err)) {
339f4f4e 84 zfcp_qdio_handler_error(qdio, "qdireq1", qdio_err);
00bab910
SS
85 return;
86 }
1da177e4
LT
87
88 /* cleanup all SBALs being program-owned now */
706eca49 89 zfcp_qdio_zero_sbals(qdio->req_q, idx, count);
1da177e4 90
44a24cb3 91 spin_lock_irq(&qdio->stat_lock);
564e1c86 92 zfcp_qdio_account(qdio);
44a24cb3 93 spin_unlock_irq(&qdio->stat_lock);
706eca49 94 atomic_add(count, &qdio->req_q_free);
564e1c86 95 wake_up(&qdio->req_q_wq);
1da177e4
LT
96}
97
779e6e1c 98static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err,
706eca49 99 int queue_no, int idx, int count,
00bab910
SS
100 unsigned long parm)
101{
564e1c86 102 struct zfcp_qdio *qdio = (struct zfcp_qdio *) parm;
86a9668a
SS
103 struct zfcp_adapter *adapter = qdio->adapter;
104 struct qdio_buffer_element *sbale;
105 int sbal_no, sbal_idx;
106 void *pl[ZFCP_QDIO_MAX_SBALS_PER_REQ + 1];
107 u64 req_id;
108 u8 scount;
00bab910 109
779e6e1c 110 if (unlikely(qdio_err)) {
86a9668a
SS
111 memset(pl, 0, ZFCP_QDIO_MAX_SBALS_PER_REQ * sizeof(void *));
112 if (zfcp_adapter_multi_buffer_active(adapter)) {
113 sbale = qdio->res_q[idx]->element;
114 req_id = (u64) sbale->addr;
115 scount = sbale->scount + 1; /* incl. signaling SBAL */
116
117 for (sbal_no = 0; sbal_no < scount; sbal_no++) {
118 sbal_idx = (idx + sbal_no) %
119 QDIO_MAX_BUFFERS_PER_Q;
120 pl[sbal_no] = qdio->res_q[sbal_idx];
121 }
122 zfcp_dbf_hba_def_err(adapter, req_id, scount, pl);
123 }
339f4f4e 124 zfcp_qdio_handler_error(qdio, "qdires1", qdio_err);
00bab910
SS
125 return;
126 }
1da177e4 127
1da177e4
LT
128 /*
129 * go through all SBALs from input queue currently
130 * returned by QDIO layer
131 */
00bab910 132 for (sbal_no = 0; sbal_no < count; sbal_no++) {
706eca49 133 sbal_idx = (idx + sbal_no) % QDIO_MAX_BUFFERS_PER_Q;
1da177e4 134 /* go through all SBALEs of SBAL */
564e1c86 135 zfcp_fsf_reqid_check(qdio, sbal_idx);
1da177e4
LT
136 }
137
138 /*
706eca49 139 * put SBALs back to response queue
1da177e4 140 */
706eca49 141 if (do_QDIO(cdev, QDIO_FLAG_SYNC_INPUT, 0, idx, count))
ea4a3a6a 142 zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdires2");
1da177e4
LT
143}
144
44cc76f2 145static struct qdio_buffer_element *
1674b405 146zfcp_qdio_sbal_chain(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
1da177e4 147{
44cc76f2 148 struct qdio_buffer_element *sbale;
1da177e4
LT
149
150 /* set last entry flag in current SBALE of current SBAL */
564e1c86 151 sbale = zfcp_qdio_sbale_curr(qdio, q_req);
3ec90878 152 sbale->eflags |= SBAL_EFLAGS_LAST_ENTRY;
1da177e4
LT
153
154 /* don't exceed last allowed SBAL */
42428f74 155 if (q_req->sbal_last == q_req->sbal_limit)
1da177e4
LT
156 return NULL;
157
158 /* set chaining flag in first SBALE of current SBAL */
564e1c86 159 sbale = zfcp_qdio_sbale_req(qdio, q_req);
3ec90878 160 sbale->sflags |= SBAL_SFLAGS0_MORE_SBALS;
1da177e4
LT
161
162 /* calculate index of next SBAL */
42428f74
SS
163 q_req->sbal_last++;
164 q_req->sbal_last %= QDIO_MAX_BUFFERS_PER_Q;
1da177e4
LT
165
166 /* keep this requests number of SBALs up-to-date */
42428f74 167 q_req->sbal_number++;
01b04759 168 BUG_ON(q_req->sbal_number > ZFCP_QDIO_MAX_SBALS_PER_REQ);
1da177e4
LT
169
170 /* start at first SBALE of new SBAL */
42428f74 171 q_req->sbale_curr = 0;
1da177e4
LT
172
173 /* set storage-block type for new SBAL */
564e1c86 174 sbale = zfcp_qdio_sbale_curr(qdio, q_req);
3ec90878 175 sbale->sflags |= q_req->sbtype;
1da177e4
LT
176
177 return sbale;
178}
179
44cc76f2 180static struct qdio_buffer_element *
1674b405 181zfcp_qdio_sbale_next(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
1da177e4 182{
86a9668a 183 if (q_req->sbale_curr == qdio->max_sbale_per_sbal - 1)
1674b405 184 return zfcp_qdio_sbal_chain(qdio, q_req);
42428f74 185 q_req->sbale_curr++;
564e1c86 186 return zfcp_qdio_sbale_curr(qdio, q_req);
1da177e4
LT
187}
188
1da177e4
LT
189/**
190 * zfcp_qdio_sbals_from_sg - fill SBALs from scatter-gather list
1674b405
CS
191 * @qdio: pointer to struct zfcp_qdio
192 * @q_req: pointer to struct zfcp_qdio_req
1da177e4 193 * @sg: scatter-gather list
1da177e4 194 * @max_sbals: upper bound for number of SBALs to be used
86a9668a 195 * Returns: zero or -EINVAL on error
1da177e4 196 */
34c2b712 197int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
01b04759 198 struct scatterlist *sg)
1da177e4 199{
44cc76f2 200 struct qdio_buffer_element *sbale;
1da177e4 201
00bab910 202 /* set storage-block type for this request */
564e1c86 203 sbale = zfcp_qdio_sbale_req(qdio, q_req);
3ec90878 204 sbale->sflags |= q_req->sbtype;
1da177e4 205
00bab910 206 for (; sg; sg = sg_next(sg)) {
1674b405 207 sbale = zfcp_qdio_sbale_next(qdio, q_req);
68322984
CS
208 if (!sbale) {
209 atomic_inc(&qdio->req_q_full);
706eca49
SS
210 zfcp_qdio_zero_sbals(qdio->req_q, q_req->sbal_first,
211 q_req->sbal_number);
68322984
CS
212 return -EINVAL;
213 }
68322984
CS
214 sbale->addr = sg_virt(sg);
215 sbale->length = sg->length;
1da177e4 216 }
86a9668a 217 return 0;
1da177e4
LT
218}
219
6b9e1520
CS
220static int zfcp_qdio_sbal_check(struct zfcp_qdio *qdio)
221{
44a24cb3 222 spin_lock_irq(&qdio->req_q_lock);
706eca49 223 if (atomic_read(&qdio->req_q_free) ||
c2af7545 224 !(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP))
6b9e1520 225 return 1;
44a24cb3 226 spin_unlock_irq(&qdio->req_q_lock);
6b9e1520
CS
227 return 0;
228}
229
230/**
231 * zfcp_qdio_sbal_get - get free sbal in request queue, wait if necessary
232 * @qdio: pointer to struct zfcp_qdio
233 *
234 * The req_q_lock must be held by the caller of this function, and
235 * this function may only be called from process context; it will
236 * sleep when waiting for a free sbal.
237 *
238 * Returns: 0 on success, -EIO if there is no free sbal after waiting.
239 */
240int zfcp_qdio_sbal_get(struct zfcp_qdio *qdio)
241{
242 long ret;
243
44a24cb3 244 spin_unlock_irq(&qdio->req_q_lock);
6b9e1520
CS
245 ret = wait_event_interruptible_timeout(qdio->req_q_wq,
246 zfcp_qdio_sbal_check(qdio), 5 * HZ);
c2af7545
CS
247
248 if (!(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP))
249 return -EIO;
250
6b9e1520
CS
251 if (ret > 0)
252 return 0;
c2af7545 253
6b9e1520
CS
254 if (!ret) {
255 atomic_inc(&qdio->req_q_full);
256 /* assume hanging outbound queue, try queue recovery */
ea4a3a6a 257 zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdsbg_1");
6b9e1520
CS
258 }
259
44a24cb3 260 spin_lock_irq(&qdio->req_q_lock);
6b9e1520
CS
261 return -EIO;
262}
263
1da177e4 264/**
00bab910 265 * zfcp_qdio_send - set PCI flag in first SBALE and send req to QDIO
564e1c86 266 * @qdio: pointer to struct zfcp_qdio
34c2b712 267 * @q_req: pointer to struct zfcp_qdio_req
00bab910 268 * Returns: 0 on success, error otherwise
1da177e4 269 */
34c2b712 270int zfcp_qdio_send(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
1da177e4 271{
21ddaa53 272 int retval;
706eca49 273 u8 sbal_number = q_req->sbal_number;
00bab910 274
44a24cb3 275 spin_lock(&qdio->stat_lock);
564e1c86 276 zfcp_qdio_account(qdio);
44a24cb3 277 spin_unlock(&qdio->stat_lock);
94506fd1 278
706eca49
SS
279 retval = do_QDIO(qdio->adapter->ccw_device, QDIO_FLAG_SYNC_OUTPUT, 0,
280 q_req->sbal_first, sbal_number);
281
00bab910 282 if (unlikely(retval)) {
706eca49
SS
283 zfcp_qdio_zero_sbals(qdio->req_q, q_req->sbal_first,
284 sbal_number);
00bab910
SS
285 return retval;
286 }
287
288 /* account for transferred buffers */
706eca49
SS
289 atomic_sub(sbal_number, &qdio->req_q_free);
290 qdio->req_q_idx += sbal_number;
291 qdio->req_q_idx %= QDIO_MAX_BUFFERS_PER_Q;
292
00bab910 293 return 0;
1da177e4
LT
294}
295
564e1c86
SS
296
297static void zfcp_qdio_setup_init_data(struct qdio_initialize *id,
298 struct zfcp_qdio *qdio)
299{
d36deae7 300 memset(id, 0, sizeof(*id));
564e1c86
SS
301 id->cdev = qdio->adapter->ccw_device;
302 id->q_format = QDIO_ZFCP_QFMT;
303 memcpy(id->adapter_name, dev_name(&id->cdev->dev), 8);
304 ASCEBC(id->adapter_name, 8);
dcc18f48 305 id->qib_rflags = QIB_RFLAGS_ENABLE_DATA_DIV;
86a9668a
SS
306 if (enable_multibuffer)
307 id->qdr_ac |= QDR_AC_MULTI_BUFFER_ENABLE;
564e1c86
SS
308 id->no_input_qs = 1;
309 id->no_output_qs = 1;
310 id->input_handler = zfcp_qdio_int_resp;
311 id->output_handler = zfcp_qdio_int_req;
312 id->int_parm = (unsigned long) qdio;
706eca49
SS
313 id->input_sbal_addr_array = (void **) (qdio->res_q);
314 id->output_sbal_addr_array = (void **) (qdio->req_q);
3d6c76ff
JG
315 id->scan_threshold =
316 QDIO_MAX_BUFFERS_PER_Q - ZFCP_QDIO_MAX_SBALS_PER_REQ * 2;
564e1c86 317}
dcc18f48 318
00bab910
SS
319/**
320 * zfcp_qdio_allocate - allocate queue memory and initialize QDIO data
321 * @adapter: pointer to struct zfcp_adapter
322 * Returns: -ENOMEM on memory allocation error or return value from
323 * qdio_allocate
324 */
d5a282a1 325static int zfcp_qdio_allocate(struct zfcp_qdio *qdio)
00bab910 326{
564e1c86 327 struct qdio_initialize init_data;
00bab910 328
706eca49
SS
329 if (zfcp_qdio_buffers_enqueue(qdio->req_q) ||
330 zfcp_qdio_buffers_enqueue(qdio->res_q))
00bab910
SS
331 return -ENOMEM;
332
564e1c86 333 zfcp_qdio_setup_init_data(&init_data, qdio);
3d63d3b4 334 init_waitqueue_head(&qdio->req_q_wq);
564e1c86
SS
335
336 return qdio_allocate(&init_data);
00bab910
SS
337}
338
339/**
340 * zfcp_close_qdio - close qdio queues for an adapter
564e1c86 341 * @qdio: pointer to structure zfcp_qdio
1da177e4 342 */
564e1c86 343void zfcp_qdio_close(struct zfcp_qdio *qdio)
1da177e4 344{
706eca49
SS
345 struct zfcp_adapter *adapter = qdio->adapter;
346 int idx, count;
00bab910 347
706eca49 348 if (!(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP))
00bab910
SS
349 return;
350
351 /* clear QDIOUP flag, thus do_QDIO is not called during qdio_shutdown */
44a24cb3 352 spin_lock_irq(&qdio->req_q_lock);
706eca49 353 atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status);
44a24cb3 354 spin_unlock_irq(&qdio->req_q_lock);
00bab910 355
c2af7545
CS
356 wake_up(&qdio->req_q_wq);
357
706eca49 358 qdio_shutdown(adapter->ccw_device, QDIO_FLAG_CLEANUP_USING_CLEAR);
00bab910
SS
359
360 /* cleanup used outbound sbals */
706eca49 361 count = atomic_read(&qdio->req_q_free);
00bab910 362 if (count < QDIO_MAX_BUFFERS_PER_Q) {
706eca49 363 idx = (qdio->req_q_idx + count) % QDIO_MAX_BUFFERS_PER_Q;
00bab910 364 count = QDIO_MAX_BUFFERS_PER_Q - count;
706eca49 365 zfcp_qdio_zero_sbals(qdio->req_q, idx, count);
1da177e4 366 }
706eca49
SS
367 qdio->req_q_idx = 0;
368 atomic_set(&qdio->req_q_free, 0);
1da177e4
LT
369}
370
00bab910
SS
371/**
372 * zfcp_qdio_open - prepare and initialize response queue
564e1c86 373 * @qdio: pointer to struct zfcp_qdio
00bab910
SS
374 * Returns: 0 on success, otherwise -EIO
375 */
564e1c86 376int zfcp_qdio_open(struct zfcp_qdio *qdio)
00bab910 377{
44cc76f2 378 struct qdio_buffer_element *sbale;
564e1c86 379 struct qdio_initialize init_data;
706eca49
SS
380 struct zfcp_adapter *adapter = qdio->adapter;
381 struct ccw_device *cdev = adapter->ccw_device;
dcc18f48 382 struct qdio_ssqd_desc ssqd;
00bab910
SS
383 int cc;
384
706eca49 385 if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP)
00bab910
SS
386 return -EIO;
387
339f4f4e
CS
388 atomic_clear_mask(ZFCP_STATUS_ADAPTER_SIOSL_ISSUED,
389 &qdio->adapter->status);
390
564e1c86
SS
391 zfcp_qdio_setup_init_data(&init_data, qdio);
392
393 if (qdio_establish(&init_data))
ff3b24fa 394 goto failed_establish;
00bab910 395
dcc18f48
CS
396 if (qdio_get_ssqd_desc(init_data.cdev, &ssqd))
397 goto failed_qdio;
398
399 if (ssqd.qdioac2 & CHSC_AC2_DATA_DIV_ENABLED)
400 atomic_set_mask(ZFCP_STATUS_ADAPTER_DATA_DIV_ENABLED,
401 &qdio->adapter->status);
402
86a9668a
SS
403 if (ssqd.qdioac2 & CHSC_AC2_MULTI_BUFFER_ENABLED) {
404 atomic_set_mask(ZFCP_STATUS_ADAPTER_MB_ACT, &adapter->status);
405 qdio->max_sbale_per_sbal = QDIO_MAX_ELEMENTS_PER_BUFFER;
406 } else {
407 atomic_clear_mask(ZFCP_STATUS_ADAPTER_MB_ACT, &adapter->status);
408 qdio->max_sbale_per_sbal = QDIO_MAX_ELEMENTS_PER_BUFFER - 1;
409 }
410
411 qdio->max_sbale_per_req =
412 ZFCP_QDIO_MAX_SBALS_PER_REQ * qdio->max_sbale_per_sbal
413 - 2;
564e1c86 414 if (qdio_activate(cdev))
00bab910 415 goto failed_qdio;
00bab910
SS
416
417 for (cc = 0; cc < QDIO_MAX_BUFFERS_PER_Q; cc++) {
706eca49 418 sbale = &(qdio->res_q[cc]->element[0]);
00bab910 419 sbale->length = 0;
3ec90878
JG
420 sbale->eflags = SBAL_EFLAGS_LAST_ENTRY;
421 sbale->sflags = 0;
00bab910
SS
422 sbale->addr = NULL;
423 }
424
706eca49 425 if (do_QDIO(cdev, QDIO_FLAG_SYNC_INPUT, 0, 0, QDIO_MAX_BUFFERS_PER_Q))
00bab910 426 goto failed_qdio;
00bab910 427
25985edc 428 /* set index of first available SBALS / number of available SBALS */
706eca49
SS
429 qdio->req_q_idx = 0;
430 atomic_set(&qdio->req_q_free, QDIO_MAX_BUFFERS_PER_Q);
3d63d3b4 431 atomic_set_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &qdio->adapter->status);
00bab910 432
86a9668a
SS
433 if (adapter->scsi_host) {
434 adapter->scsi_host->sg_tablesize = qdio->max_sbale_per_req;
435 adapter->scsi_host->max_sectors = qdio->max_sbale_per_req * 8;
436 }
437
00bab910
SS
438 return 0;
439
440failed_qdio:
564e1c86 441 qdio_shutdown(cdev, QDIO_FLAG_CLEANUP_USING_CLEAR);
ff3b24fa 442failed_establish:
564e1c86 443 dev_err(&cdev->dev,
ff3b24fa 444 "Setting up the QDIO connection to the FCP adapter failed\n");
00bab910
SS
445 return -EIO;
446}
d5a282a1
SS
447
448void zfcp_qdio_destroy(struct zfcp_qdio *qdio)
449{
d5a282a1
SS
450 int p;
451
452 if (!qdio)
453 return;
454
455 if (qdio->adapter->ccw_device)
456 qdio_free(qdio->adapter->ccw_device);
457
d5a282a1 458 for (p = 0; p < QDIO_MAX_BUFFERS_PER_Q; p += QBUFF_PER_PAGE) {
706eca49
SS
459 free_page((unsigned long) qdio->req_q[p]);
460 free_page((unsigned long) qdio->res_q[p]);
d5a282a1
SS
461 }
462
463 kfree(qdio);
464}
465
466int zfcp_qdio_setup(struct zfcp_adapter *adapter)
467{
468 struct zfcp_qdio *qdio;
469
470 qdio = kzalloc(sizeof(struct zfcp_qdio), GFP_KERNEL);
471 if (!qdio)
472 return -ENOMEM;
473
474 qdio->adapter = adapter;
475
476 if (zfcp_qdio_allocate(qdio)) {
477 zfcp_qdio_destroy(qdio);
478 return -ENOMEM;
479 }
480
481 spin_lock_init(&qdio->req_q_lock);
482 spin_lock_init(&qdio->stat_lock);
483
484 adapter->qdio = qdio;
485 return 0;
486}
487
339f4f4e
CS
488/**
489 * zfcp_qdio_siosl - Trigger logging in FCP channel
490 * @adapter: The zfcp_adapter where to trigger logging
491 *
492 * Call the cio siosl function to trigger hardware logging. This
493 * wrapper function sets a flag to ensure hardware logging is only
494 * triggered once before going through qdio shutdown.
495 *
496 * The triggers are always run from qdio tasklet context, so no
497 * additional synchronization is necessary.
498 */
499void zfcp_qdio_siosl(struct zfcp_adapter *adapter)
500{
501 int rc;
502
503 if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_SIOSL_ISSUED)
504 return;
505
506 rc = ccw_device_siosl(adapter->ccw_device);
507 if (!rc)
508 atomic_set_mask(ZFCP_STATUS_ADAPTER_SIOSL_ISSUED,
509 &adapter->status);
510}
This page took 4.651778 seconds and 5 git commands to generate.