Blame view
drivers/s390/cio/qdio_setup.c
15.3 KB
779e6e1c7
|
1 |
/* |
779e6e1c7
|
2 3 |
* qdio queue initialization * |
a53c8fab3
|
4 |
* Copyright IBM Corp. 2008 |
779e6e1c7
|
5 6 7 8 |
* Author(s): Jan Glauber <jang@linux.vnet.ibm.com> */ #include <linux/kernel.h> #include <linux/slab.h> |
3a4c5d596
|
9 |
#include <linux/export.h> |
779e6e1c7
|
10 11 12 13 14 15 16 17 18 |
#include <asm/qdio.h> #include "cio.h" #include "css.h" #include "device.h" #include "ioasm.h" #include "chsc.h" #include "qdio.h" #include "qdio_debug.h" |
5245c924c
|
19 |
#define QBUFF_PER_PAGE (PAGE_SIZE / sizeof(struct qdio_buffer)) |
779e6e1c7
|
20 |
static struct kmem_cache *qdio_q_cache; |
104ea556e
|
21 |
static struct kmem_cache *qdio_aob_cache; |
400d82915
|
22 |
struct qaob *qdio_allocate_aob(void) |
104ea556e
|
23 |
{ |
400d82915
|
24 |
return kmem_cache_zalloc(qdio_aob_cache, GFP_ATOMIC); |
104ea556e
|
25 26 27 28 29 30 31 32 |
} EXPORT_SYMBOL_GPL(qdio_allocate_aob); void qdio_release_aob(struct qaob *aob) { kmem_cache_free(qdio_aob_cache, aob); } EXPORT_SYMBOL_GPL(qdio_release_aob); |
779e6e1c7
|
33 |
|
5245c924c
|
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
/** * qdio_free_buffers() - free qdio buffers * @buf: array of pointers to qdio buffers * @count: number of qdio buffers to free */ void qdio_free_buffers(struct qdio_buffer **buf, unsigned int count) { int pos; for (pos = 0; pos < count; pos += QBUFF_PER_PAGE) free_page((unsigned long) buf[pos]); } EXPORT_SYMBOL_GPL(qdio_free_buffers); /** * qdio_alloc_buffers() - allocate qdio buffers * @buf: array of pointers to qdio buffers * @count: number of qdio buffers to allocate */ int qdio_alloc_buffers(struct qdio_buffer **buf, unsigned int count) { int pos; for (pos = 0; pos < count; pos += QBUFF_PER_PAGE) { buf[pos] = (void *) get_zeroed_page(GFP_KERNEL); if (!buf[pos]) { qdio_free_buffers(buf, count); return -ENOMEM; } } for (pos = 0; pos < count; pos++) if (pos % QBUFF_PER_PAGE) buf[pos] = buf[pos - 1] + 1; return 0; } EXPORT_SYMBOL_GPL(qdio_alloc_buffers); /** * qdio_reset_buffers() - reset qdio buffers * @buf: array of pointers to qdio buffers * @count: number of qdio buffers that will be zeroed */ void qdio_reset_buffers(struct qdio_buffer **buf, unsigned int count) { int pos; for (pos = 0; pos < count; pos++) memset(buf[pos], 0, sizeof(struct qdio_buffer)); } EXPORT_SYMBOL_GPL(qdio_reset_buffers); |
779e6e1c7
|
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
/* * qebsm is only available under 64bit but the adapter sets the feature * flag anyway, so we manually override it. */ static inline int qebsm_possible(void) { #ifdef CONFIG_64BIT return css_general_characteristics.qebsm; #endif return 0; } /* * qib_param_field: pointer to 128 bytes or NULL, if no param field * nr_input_qs: pointer to nr_queues*128 words of data or NULL */ static void set_impl_params(struct qdio_irq *irq_ptr, unsigned int qib_param_field_format, unsigned char *qib_param_field, unsigned long *input_slib_elements, unsigned long *output_slib_elements) { struct qdio_q *q; int i, j; if (!irq_ptr) return; |
779e6e1c7
|
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
irq_ptr->qib.pfmt = qib_param_field_format; if (qib_param_field) memcpy(irq_ptr->qib.parm, qib_param_field, QDIO_MAX_BUFFERS_PER_Q); if (!input_slib_elements) goto output; for_each_input_queue(irq_ptr, q, i) { for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++) q->slib->slibe[j].parms = input_slib_elements[i * QDIO_MAX_BUFFERS_PER_Q + j]; } output: if (!output_slib_elements) return; for_each_output_queue(irq_ptr, q, i) { for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++) q->slib->slibe[j].parms = output_slib_elements[i * QDIO_MAX_BUFFERS_PER_Q + j]; } } static int __qdio_allocate_qs(struct qdio_q **irq_ptr_qs, int nr_queues) { struct qdio_q *q; int i; for (i = 0; i < nr_queues; i++) { q = kmem_cache_alloc(qdio_q_cache, GFP_KERNEL); if (!q) return -ENOMEM; |
779e6e1c7
|
144 145 146 147 148 149 |
q->slib = (struct slib *) __get_free_page(GFP_KERNEL); if (!q->slib) { kmem_cache_free(qdio_q_cache, q); return -ENOMEM; } |
779e6e1c7
|
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
irq_ptr_qs[i] = q; } return 0; } int qdio_allocate_qs(struct qdio_irq *irq_ptr, int nr_input_qs, int nr_output_qs) { int rc; rc = __qdio_allocate_qs(irq_ptr->input_qs, nr_input_qs); if (rc) return rc; rc = __qdio_allocate_qs(irq_ptr->output_qs, nr_output_qs); return rc; } static void setup_queues_misc(struct qdio_q *q, struct qdio_irq *irq_ptr, qdio_handler_t *handler, int i) { |
5382fe11d
|
169 |
struct slib *slib = q->slib; |
779e6e1c7
|
170 |
|
5382fe11d
|
171 172 173 174 |
/* queue must be cleared for qdio_establish */ memset(q, 0, sizeof(*q)); memset(slib, 0, PAGE_SIZE); q->slib = slib; |
779e6e1c7
|
175 176 177 178 179 180 181 |
q->irq_ptr = irq_ptr; q->mask = 1 << (31 - i); q->nr = i; q->handler = handler; } static void setup_storage_lists(struct qdio_q *q, struct qdio_irq *irq_ptr, |
22f993476
|
182 |
void **sbals_array, int i) |
779e6e1c7
|
183 184 185 |
{ struct qdio_q *prev; int j; |
22f993476
|
186 |
DBF_HEX(&q, sizeof(void *)); |
779e6e1c7
|
187 188 189 |
q->sl = (struct sl *)((char *)q->slib + PAGE_SIZE / 2); /* fill in sbal */ |
ce1d80146
|
190 |
for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++) |
779e6e1c7
|
191 |
q->sbal[j] = *sbals_array++; |
779e6e1c7
|
192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
/* fill in slib */ if (i > 0) { prev = (q->is_input_q) ? irq_ptr->input_qs[i - 1] : irq_ptr->output_qs[i - 1]; prev->slib->nsliba = (unsigned long)q->slib; } q->slib->sla = (unsigned long)q->sl; q->slib->slsba = (unsigned long)&q->slsb.val[0]; /* fill in sl */ for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++) q->sl->element[j].sbal = (unsigned long)q->sbal[j]; |
779e6e1c7
|
206 207 208 209 210 |
} static void setup_queues(struct qdio_irq *irq_ptr, struct qdio_initialize *qdio_init) { |
779e6e1c7
|
211 212 213 |
struct qdio_q *q; void **input_sbal_array = qdio_init->input_sbal_addr_array; void **output_sbal_array = qdio_init->output_sbal_addr_array; |
104ea556e
|
214 215 |
struct qdio_outbuf_state *output_sbal_state_array = qdio_init->output_sbal_state_array; |
779e6e1c7
|
216 |
int i; |
779e6e1c7
|
217 |
for_each_input_queue(irq_ptr, q, i) { |
104ea556e
|
218 |
DBF_EVENT("inq:%1d", i); |
779e6e1c7
|
219 220 221 |
setup_queues_misc(q, irq_ptr, qdio_init->input_handler, i); q->is_input_q = 1; |
e58b0d902
|
222 223 |
q->u.in.queue_start_poll = qdio_init->queue_start_poll_array ? qdio_init->queue_start_poll_array[i] : NULL; |
104ea556e
|
224 |
|
22f993476
|
225 |
setup_storage_lists(q, irq_ptr, input_sbal_array, i); |
779e6e1c7
|
226 |
input_sbal_array += QDIO_MAX_BUFFERS_PER_Q; |
104ea556e
|
227 |
if (is_thinint_irq(irq_ptr)) { |
779e6e1c7
|
228 229 |
tasklet_init(&q->tasklet, tiqdio_inbound_processing, (unsigned long) q); |
104ea556e
|
230 |
} else { |
779e6e1c7
|
231 232 |
tasklet_init(&q->tasklet, qdio_inbound_processing, (unsigned long) q); |
104ea556e
|
233 |
} |
779e6e1c7
|
234 235 236 |
} for_each_output_queue(irq_ptr, q, i) { |
22f993476
|
237 |
DBF_EVENT("outq:%1d", i); |
779e6e1c7
|
238 |
setup_queues_misc(q, irq_ptr, qdio_init->output_handler, i); |
104ea556e
|
239 240 |
q->u.out.sbal_state = output_sbal_state_array; output_sbal_state_array += QDIO_MAX_BUFFERS_PER_Q; |
779e6e1c7
|
241 |
q->is_input_q = 0; |
3d6c76ff3
|
242 |
q->u.out.scan_threshold = qdio_init->scan_threshold; |
22f993476
|
243 |
setup_storage_lists(q, irq_ptr, output_sbal_array, i); |
779e6e1c7
|
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 |
output_sbal_array += QDIO_MAX_BUFFERS_PER_Q; tasklet_init(&q->tasklet, qdio_outbound_processing, (unsigned long) q); setup_timer(&q->u.out.timer, (void(*)(unsigned long)) &qdio_outbound_timer, (unsigned long)q); } } static void process_ac_flags(struct qdio_irq *irq_ptr, unsigned char qdioac) { if (qdioac & AC1_SIGA_INPUT_NEEDED) irq_ptr->siga_flag.input = 1; if (qdioac & AC1_SIGA_OUTPUT_NEEDED) irq_ptr->siga_flag.output = 1; if (qdioac & AC1_SIGA_SYNC_NEEDED) irq_ptr->siga_flag.sync = 1; |
90adac58d
|
261 262 263 264 |
if (!(qdioac & AC1_AUTOMATIC_SYNC_ON_THININT)) irq_ptr->siga_flag.sync_after_ai = 1; if (!(qdioac & AC1_AUTOMATIC_SYNC_ON_OUT_PCI)) irq_ptr->siga_flag.sync_out_after_pci = 1; |
779e6e1c7
|
265 266 267 268 269 |
} static void check_and_setup_qebsm(struct qdio_irq *irq_ptr, unsigned char qdioac, unsigned long token) { |
779e6e1c7
|
270 271 272 273 274 275 276 |
if (!(irq_ptr->qib.rflags & QIB_RFLAGS_ENABLE_QEBSM)) goto no_qebsm; if (!(qdioac & AC1_SC_QEBSM_AVAILABLE) || (!(qdioac & AC1_SC_QEBSM_ENABLED))) goto no_qebsm; irq_ptr->sch_token = token; |
22f993476
|
277 278 |
DBF_EVENT("V=V:1"); DBF_EVENT("%8lx", irq_ptr->sch_token); |
779e6e1c7
|
279 280 281 282 283 |
return; no_qebsm: irq_ptr->sch_token = 0; irq_ptr->qib.rflags &= ~QIB_RFLAGS_ENABLE_QEBSM; |
22f993476
|
284 |
DBF_EVENT("noV=V"); |
779e6e1c7
|
285 |
} |
bbd50e172
|
286 287 288 289 290 291 292 |
/* * If there is a qdio_irq we use the chsc_page and store the information * in the qdio_irq, otherwise we copy it to the specified structure. */ int qdio_setup_get_ssqd(struct qdio_irq *irq_ptr, struct subchannel_id *schid, struct qdio_ssqd_desc *data) |
779e6e1c7
|
293 294 295 |
{ struct chsc_ssqd_area *ssqd; int rc; |
22f993476
|
296 |
DBF_EVENT("getssqd:%4x", schid->sch_no); |
da5b6cb16
|
297 |
if (!irq_ptr) { |
bbd50e172
|
298 |
ssqd = (struct chsc_ssqd_area *)__get_free_page(GFP_KERNEL); |
da5b6cb16
|
299 300 301 302 303 304 305 |
if (!ssqd) return -ENOMEM; } else { ssqd = (struct chsc_ssqd_area *)irq_ptr->chsc_page; } rc = chsc_ssqd(*schid, ssqd); |
779e6e1c7
|
306 |
if (rc) |
da5b6cb16
|
307 |
goto out; |
779e6e1c7
|
308 309 310 |
if (!(ssqd->qdio_ssqd.flags & CHSC_FLAG_QDIO_CAPABILITY) || !(ssqd->qdio_ssqd.flags & CHSC_FLAG_VALIDITY) || |
bbd50e172
|
311 |
(ssqd->qdio_ssqd.sch != schid->sch_no)) |
da5b6cb16
|
312 313 314 315 316 317 318 |
rc = -EINVAL; if (!rc) memcpy(data, &ssqd->qdio_ssqd, sizeof(*data)); out: if (!irq_ptr) |
bbd50e172
|
319 |
free_page((unsigned long)ssqd); |
da5b6cb16
|
320 321 |
return rc; |
779e6e1c7
|
322 323 324 325 326 |
} void qdio_setup_ssqd_info(struct qdio_irq *irq_ptr) { unsigned char qdioac; |
779e6e1c7
|
327 |
int rc; |
da5b6cb16
|
328 |
rc = qdio_setup_get_ssqd(irq_ptr, &irq_ptr->schid, &irq_ptr->ssqd_desc); |
779e6e1c7
|
329 |
if (rc) { |
22f993476
|
330 331 |
DBF_ERROR("%4x ssqd ERR", irq_ptr->schid.sch_no); DBF_ERROR("rc:%x", rc); |
779e6e1c7
|
332 333 334 335 336 337 338 339 |
/* all flags set, worst case */ qdioac = AC1_SIGA_INPUT_NEEDED | AC1_SIGA_OUTPUT_NEEDED | AC1_SIGA_SYNC_NEEDED; } else qdioac = irq_ptr->ssqd_desc.qdioac1; check_and_setup_qebsm(irq_ptr, qdioac, irq_ptr->ssqd_desc.sch_token); process_ac_flags(irq_ptr, qdioac); |
61d84979a
|
340 341 |
DBF_EVENT("ac 1:%2x 2:%4x", qdioac, irq_ptr->ssqd_desc.qdioac2); DBF_EVENT("3:%4x qib:%4x", irq_ptr->ssqd_desc.qdioac3, irq_ptr->qib.ac); |
779e6e1c7
|
342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 |
} void qdio_release_memory(struct qdio_irq *irq_ptr) { struct qdio_q *q; int i; /* * Must check queue array manually since irq_ptr->nr_input_queues / * irq_ptr->nr_input_queues may not yet be set. */ for (i = 0; i < QDIO_MAX_QUEUES_PER_IRQ; i++) { q = irq_ptr->input_qs[i]; if (q) { free_page((unsigned long) q->slib); kmem_cache_free(qdio_q_cache, q); } } for (i = 0; i < QDIO_MAX_QUEUES_PER_IRQ; i++) { q = irq_ptr->output_qs[i]; if (q) { |
104ea556e
|
363 364 365 366 367 368 369 370 371 372 373 374 375 |
if (q->u.out.use_cq) { int n; for (n = 0; n < QDIO_MAX_BUFFERS_PER_Q; ++n) { struct qaob *aob = q->u.out.aobs[n]; if (aob) { qdio_release_aob(aob); q->u.out.aobs[n] = NULL; } } qdio_disable_async_operation(&q->u.out); } |
779e6e1c7
|
376 377 378 379 |
free_page((unsigned long) q->slib); kmem_cache_free(qdio_q_cache, q); } } |
3b8e3004a
|
380 |
free_page((unsigned long) irq_ptr->qdr); |
779e6e1c7
|
381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 |
free_page(irq_ptr->chsc_page); free_page((unsigned long) irq_ptr); } static void __qdio_allocate_fill_qdr(struct qdio_irq *irq_ptr, struct qdio_q **irq_ptr_qs, int i, int nr) { irq_ptr->qdr->qdf0[i + nr].sliba = (unsigned long)irq_ptr_qs[i]->slib; irq_ptr->qdr->qdf0[i + nr].sla = (unsigned long)irq_ptr_qs[i]->sl; irq_ptr->qdr->qdf0[i + nr].slsba = (unsigned long)&irq_ptr_qs[i]->slsb.val[0]; |
d1bf85902
|
397 398 399 400 |
irq_ptr->qdr->qdf0[i + nr].akey = PAGE_DEFAULT_KEY >> 4; irq_ptr->qdr->qdf0[i + nr].bkey = PAGE_DEFAULT_KEY >> 4; irq_ptr->qdr->qdf0[i + nr].ckey = PAGE_DEFAULT_KEY >> 4; irq_ptr->qdr->qdf0[i + nr].dkey = PAGE_DEFAULT_KEY >> 4; |
779e6e1c7
|
401 402 403 404 405 406 407 408 |
} static void setup_qdr(struct qdio_irq *irq_ptr, struct qdio_initialize *qdio_init) { int i; irq_ptr->qdr->qfmt = qdio_init->q_format; |
dfe5bb506
|
409 |
irq_ptr->qdr->ac = qdio_init->qdr_ac; |
779e6e1c7
|
410 411 412 413 414 |
irq_ptr->qdr->iqdcnt = qdio_init->no_input_qs; irq_ptr->qdr->oqdcnt = qdio_init->no_output_qs; irq_ptr->qdr->iqdsz = sizeof(struct qdesfmt0) / 4; /* size in words */ irq_ptr->qdr->oqdsz = sizeof(struct qdesfmt0) / 4; irq_ptr->qdr->qiba = (unsigned long)&irq_ptr->qib; |
d1bf85902
|
415 |
irq_ptr->qdr->qkey = PAGE_DEFAULT_KEY >> 4; |
779e6e1c7
|
416 417 418 419 420 421 422 423 424 425 426 427 428 429 |
for (i = 0; i < qdio_init->no_input_qs; i++) __qdio_allocate_fill_qdr(irq_ptr, irq_ptr->input_qs, i, 0); for (i = 0; i < qdio_init->no_output_qs; i++) __qdio_allocate_fill_qdr(irq_ptr, irq_ptr->output_qs, i, qdio_init->no_input_qs); } static void setup_qib(struct qdio_irq *irq_ptr, struct qdio_initialize *init_data) { if (qebsm_possible()) irq_ptr->qib.rflags |= QIB_RFLAGS_ENABLE_QEBSM; |
dcc18f48a
|
430 |
irq_ptr->qib.rflags |= init_data->qib_rflags; |
779e6e1c7
|
431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 |
irq_ptr->qib.qfmt = init_data->q_format; if (init_data->no_input_qs) irq_ptr->qib.isliba = (unsigned long)(irq_ptr->input_qs[0]->slib); if (init_data->no_output_qs) irq_ptr->qib.osliba = (unsigned long)(irq_ptr->output_qs[0]->slib); memcpy(irq_ptr->qib.ebcnam, init_data->adapter_name, 8); } int qdio_setup_irq(struct qdio_initialize *init_data) { struct ciw *ciw; struct qdio_irq *irq_ptr = init_data->cdev->private->qdio_data; int rc; |
432ac5e04
|
446 447 448 449 450 451 452 453 |
memset(&irq_ptr->qib, 0, sizeof(irq_ptr->qib)); memset(&irq_ptr->siga_flag, 0, sizeof(irq_ptr->siga_flag)); memset(&irq_ptr->ccw, 0, sizeof(irq_ptr->ccw)); memset(&irq_ptr->ssqd_desc, 0, sizeof(irq_ptr->ssqd_desc)); memset(&irq_ptr->perf_stat, 0, sizeof(irq_ptr->perf_stat)); irq_ptr->debugfs_dev = irq_ptr->debugfs_perf = NULL; irq_ptr->sch_token = irq_ptr->state = irq_ptr->perf_stat_enabled = 0; |
779e6e1c7
|
454 455 456 457 458 459 |
/* wipes qib.ac, required by ar7063 */ memset(irq_ptr->qdr, 0, sizeof(struct qdr)); irq_ptr->int_parm = init_data->int_parm; irq_ptr->nr_input_qs = init_data->no_input_qs; irq_ptr->nr_output_qs = init_data->no_output_qs; |
779e6e1c7
|
460 |
irq_ptr->cdev = init_data->cdev; |
287a09332
|
461 |
ccw_device_get_schid(irq_ptr->cdev, &irq_ptr->schid); |
779e6e1c7
|
462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 |
setup_queues(irq_ptr, init_data); setup_qib(irq_ptr, init_data); qdio_setup_thinint(irq_ptr); set_impl_params(irq_ptr, init_data->qib_param_field_format, init_data->qib_param_field, init_data->input_slib_elements, init_data->output_slib_elements); /* fill input and output descriptors */ setup_qdr(irq_ptr, init_data); /* qdr, qib, sls, slsbs, slibs, sbales are filled now */ /* get qdio commands */ ciw = ccw_device_get_ciw(init_data->cdev, CIW_TYPE_EQUEUE); if (!ciw) { |
22f993476
|
479 |
DBF_ERROR("%4x NO EQ", irq_ptr->schid.sch_no); |
779e6e1c7
|
480 481 482 483 484 485 486 |
rc = -EINVAL; goto out_err; } irq_ptr->equeue = *ciw; ciw = ccw_device_get_ciw(init_data->cdev, CIW_TYPE_AQUEUE); if (!ciw) { |
22f993476
|
487 |
DBF_ERROR("%4x NO AQ", irq_ptr->schid.sch_no); |
779e6e1c7
|
488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 |
rc = -EINVAL; goto out_err; } irq_ptr->aqueue = *ciw; /* set new interrupt handler */ irq_ptr->orig_handler = init_data->cdev->handler; init_data->cdev->handler = qdio_int_handler; return 0; out_err: qdio_release_memory(irq_ptr); return rc; } void qdio_print_subchannel_info(struct qdio_irq *irq_ptr, struct ccw_device *cdev) { char s[80]; |
22f993476
|
506 |
snprintf(s, 80, "qdio: %s %s on SC %x using " |
6726a807c
|
507 508 |
"AI:%d QEBSM:%d PRI:%d TDD:%d SIGA:%s%s%s%s%s ", |
22f993476
|
509 510 511 512 513 514 515 516 517 518 519 |
dev_name(&cdev->dev), (irq_ptr->qib.qfmt == QDIO_QETH_QFMT) ? "OSA" : ((irq_ptr->qib.qfmt == QDIO_ZFCP_QFMT) ? "ZFCP" : "HS"), irq_ptr->schid.sch_no, is_thinint_irq(irq_ptr), (irq_ptr->sch_token) ? 1 : 0, (irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED) ? 1 : 0, css_general_characteristics.aif_tdd, (irq_ptr->siga_flag.input) ? "R" : " ", (irq_ptr->siga_flag.output) ? "W" : " ", (irq_ptr->siga_flag.sync) ? "S" : " ", |
90adac58d
|
520 521 |
(irq_ptr->siga_flag.sync_after_ai) ? "A" : " ", (irq_ptr->siga_flag.sync_out_after_pci) ? "P" : " "); |
75f627618
|
522 |
printk(KERN_INFO "%s", s); |
779e6e1c7
|
523 |
} |
104ea556e
|
524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 |
int qdio_enable_async_operation(struct qdio_output_q *outq) { outq->aobs = kzalloc(sizeof(struct qaob *) * QDIO_MAX_BUFFERS_PER_Q, GFP_ATOMIC); if (!outq->aobs) { outq->use_cq = 0; return -ENOMEM; } outq->use_cq = 1; return 0; } void qdio_disable_async_operation(struct qdio_output_q *q) { kfree(q->aobs); q->aobs = NULL; q->use_cq = 0; } |
779e6e1c7
|
542 543 |
int __init qdio_setup_init(void) { |
104ea556e
|
544 |
int rc; |
779e6e1c7
|
545 546 547 548 |
qdio_q_cache = kmem_cache_create("qdio_q", sizeof(struct qdio_q), 256, 0, NULL); if (!qdio_q_cache) return -ENOMEM; |
104ea556e
|
549 550 551 552 553 554 555 556 557 |
qdio_aob_cache = kmem_cache_create("qdio_aob", sizeof(struct qaob), sizeof(struct qaob), 0, NULL); if (!qdio_aob_cache) { rc = -ENOMEM; goto free_qdio_q_cache; } |
779e6e1c7
|
558 |
/* Check for OSA/FCP thin interrupts (bit 67). */ |
22f993476
|
559 560 |
DBF_EVENT("thinint:%1d", (css_general_characteristics.aif_osa) ? 1 : 0); |
779e6e1c7
|
561 562 |
/* Check for QEBSM support in general (bit 58). */ |
22f993476
|
563 |
DBF_EVENT("cssQEBSM:%1d", (qebsm_possible()) ? 1 : 0); |
104ea556e
|
564 565 566 567 568 569 |
rc = 0; out: return rc; free_qdio_q_cache: kmem_cache_destroy(qdio_q_cache); goto out; |
779e6e1c7
|
570 |
} |
3f1934bc1
|
571 |
void qdio_setup_exit(void) |
779e6e1c7
|
572 |
{ |
104ea556e
|
573 |
kmem_cache_destroy(qdio_aob_cache); |
779e6e1c7
|
574 575 |
kmem_cache_destroy(qdio_q_cache); } |