diff options
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/net/qeth_core.h | 28 | ||||
-rw-r--r-- | drivers/s390/net/qeth_core_main.c | 495 |
2 files changed, 480 insertions, 43 deletions
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 8a58820b4c0f..2c25ed0a49ca 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h | |||
@@ -110,6 +110,10 @@ struct qeth_perf_stats { | |||
110 | 110 | ||
111 | unsigned int sc_dp_p; | 111 | unsigned int sc_dp_p; |
112 | unsigned int sc_p_dp; | 112 | unsigned int sc_p_dp; |
113 | /* qdio_cq_handler: number of times called, time spent in */ | ||
114 | __u64 cq_start_time; | ||
115 | unsigned int cq_cnt; | ||
116 | unsigned int cq_time; | ||
113 | /* qdio_input_handler: number of times called, time spent in */ | 117 | /* qdio_input_handler: number of times called, time spent in */ |
114 | __u64 inbound_start_time; | 118 | __u64 inbound_start_time; |
115 | unsigned int inbound_cnt; | 119 | unsigned int inbound_cnt; |
@@ -376,6 +380,11 @@ enum qeth_qdio_buffer_states { | |||
376 | * outbound: filled by driver; owned by hardware in order to be sent | 380 | * outbound: filled by driver; owned by hardware in order to be sent |
377 | */ | 381 | */ |
378 | QETH_QDIO_BUF_PRIMED, | 382 | QETH_QDIO_BUF_PRIMED, |
383 | /* | ||
384 | * inbound: not applicable | ||
385 | * outbound: handled via transfer pending / completion queue | ||
386 | */ | ||
387 | QETH_QDIO_BUF_HANDLED_DELAYED, | ||
379 | }; | 388 | }; |
380 | 389 | ||
381 | enum qeth_qdio_info_states { | 390 | enum qeth_qdio_info_states { |
@@ -413,8 +422,11 @@ struct qeth_qdio_out_buffer { | |||
413 | atomic_t state; | 422 | atomic_t state; |
414 | int next_element_to_fill; | 423 | int next_element_to_fill; |
415 | struct sk_buff_head skb_list; | 424 | struct sk_buff_head skb_list; |
416 | struct list_head ctx_list; | ||
417 | int is_header[16]; | 425 | int is_header[16]; |
426 | |||
427 | struct qaob *aob; | ||
428 | struct qeth_qdio_out_q *q; | ||
429 | struct qeth_qdio_out_buffer *next_pending; | ||
418 | }; | 430 | }; |
419 | 431 | ||
420 | struct qeth_card; | 432 | struct qeth_card; |
@@ -427,7 +439,8 @@ enum qeth_out_q_states { | |||
427 | 439 | ||
428 | struct qeth_qdio_out_q { | 440 | struct qeth_qdio_out_q { |
429 | struct qdio_buffer qdio_bufs[QDIO_MAX_BUFFERS_PER_Q]; | 441 | struct qdio_buffer qdio_bufs[QDIO_MAX_BUFFERS_PER_Q]; |
430 | struct qeth_qdio_out_buffer bufs[QDIO_MAX_BUFFERS_PER_Q]; | 442 | struct qeth_qdio_out_buffer *bufs[QDIO_MAX_BUFFERS_PER_Q]; |
443 | struct qdio_outbuf_state *bufstates; /* convenience pointer */ | ||
431 | int queue_no; | 444 | int queue_no; |
432 | struct qeth_card *card; | 445 | struct qeth_card *card; |
433 | atomic_t state; | 446 | atomic_t state; |
@@ -448,7 +461,9 @@ struct qeth_qdio_out_q { | |||
448 | struct qeth_qdio_info { | 461 | struct qeth_qdio_info { |
449 | atomic_t state; | 462 | atomic_t state; |
450 | /* input */ | 463 | /* input */ |
464 | int no_in_queues; | ||
451 | struct qeth_qdio_q *in_q; | 465 | struct qeth_qdio_q *in_q; |
466 | struct qeth_qdio_q *c_q; | ||
452 | struct qeth_qdio_buffer_pool in_buf_pool; | 467 | struct qeth_qdio_buffer_pool in_buf_pool; |
453 | struct qeth_qdio_buffer_pool init_pool; | 468 | struct qeth_qdio_buffer_pool init_pool; |
454 | int in_buf_size; | 469 | int in_buf_size; |
@@ -456,6 +471,7 @@ struct qeth_qdio_info { | |||
456 | /* output */ | 471 | /* output */ |
457 | int no_out_queues; | 472 | int no_out_queues; |
458 | struct qeth_qdio_out_q **out_qs; | 473 | struct qeth_qdio_out_q **out_qs; |
474 | struct qdio_outbuf_state *out_bufstates; | ||
459 | 475 | ||
460 | /* priority queueing */ | 476 | /* priority queueing */ |
461 | int do_prio_queueing; | 477 | int do_prio_queueing; |
@@ -527,6 +543,12 @@ enum qeth_cmd_buffer_state { | |||
527 | BUF_STATE_PROCESSED, | 543 | BUF_STATE_PROCESSED, |
528 | }; | 544 | }; |
529 | 545 | ||
546 | enum qeth_cq { | ||
547 | QETH_CQ_DISABLED = 0, | ||
548 | QETH_CQ_ENABLED = 1, | ||
549 | QETH_CQ_NOTAVAILABLE = 2, | ||
550 | }; | ||
551 | |||
530 | struct qeth_ipato { | 552 | struct qeth_ipato { |
531 | int enabled; | 553 | int enabled; |
532 | int invert4; | 554 | int invert4; |
@@ -651,6 +673,7 @@ struct qeth_card_options { | |||
651 | int rx_sg_cb; | 673 | int rx_sg_cb; |
652 | enum qeth_ipa_isolation_modes isolation; | 674 | enum qeth_ipa_isolation_modes isolation; |
653 | int sniffer; | 675 | int sniffer; |
676 | enum qeth_cq cq; | ||
654 | }; | 677 | }; |
655 | 678 | ||
656 | /* | 679 | /* |
@@ -888,6 +911,7 @@ void qeth_dbf_longtext(debug_info_t *id, int level, char *text, ...); | |||
888 | int qeth_core_ethtool_get_settings(struct net_device *, struct ethtool_cmd *); | 911 | int qeth_core_ethtool_get_settings(struct net_device *, struct ethtool_cmd *); |
889 | int qeth_set_access_ctrl_online(struct qeth_card *card); | 912 | int qeth_set_access_ctrl_online(struct qeth_card *card); |
890 | int qeth_hdr_chk_and_bounce(struct sk_buff *, int); | 913 | int qeth_hdr_chk_and_bounce(struct sk_buff *, int); |
914 | int qeth_configure_cq(struct qeth_card *, enum qeth_cq); | ||
891 | int qeth_hw_trap(struct qeth_card *, enum qeth_diags_trap_action); | 915 | int qeth_hw_trap(struct qeth_card *, enum qeth_diags_trap_action); |
892 | int qeth_query_ipassists(struct qeth_card *, enum qeth_prot_versions prot); | 916 | int qeth_query_ipassists(struct qeth_card *, enum qeth_prot_versions prot); |
893 | 917 | ||
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 8d804be9f043..68a92b06526b 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c | |||
@@ -44,6 +44,7 @@ struct qeth_card_list_struct qeth_core_card_list; | |||
44 | EXPORT_SYMBOL_GPL(qeth_core_card_list); | 44 | EXPORT_SYMBOL_GPL(qeth_core_card_list); |
45 | struct kmem_cache *qeth_core_header_cache; | 45 | struct kmem_cache *qeth_core_header_cache; |
46 | EXPORT_SYMBOL_GPL(qeth_core_header_cache); | 46 | EXPORT_SYMBOL_GPL(qeth_core_header_cache); |
47 | static struct kmem_cache *qeth_qdio_outbuf_cache; | ||
47 | 48 | ||
48 | static struct device *qeth_core_root_dev; | 49 | static struct device *qeth_core_root_dev; |
49 | static unsigned int known_devices[][6] = QETH_MODELLIST_ARRAY; | 50 | static unsigned int known_devices[][6] = QETH_MODELLIST_ARRAY; |
@@ -56,6 +57,10 @@ static struct qeth_cmd_buffer *qeth_get_buffer(struct qeth_channel *); | |||
56 | static void qeth_setup_ccw(struct qeth_channel *, unsigned char *, __u32); | 57 | static void qeth_setup_ccw(struct qeth_channel *, unsigned char *, __u32); |
57 | static void qeth_free_buffer_pool(struct qeth_card *); | 58 | static void qeth_free_buffer_pool(struct qeth_card *); |
58 | static int qeth_qdio_establish(struct qeth_card *); | 59 | static int qeth_qdio_establish(struct qeth_card *); |
60 | static void qeth_free_qdio_buffers(struct qeth_card *); | ||
61 | static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, | ||
62 | struct qeth_qdio_out_buffer *buf, | ||
63 | enum qeth_qdio_buffer_states newbufstate); | ||
59 | 64 | ||
60 | 65 | ||
61 | static inline const char *qeth_get_cardname(struct qeth_card *card) | 66 | static inline const char *qeth_get_cardname(struct qeth_card *card) |
@@ -239,6 +244,150 @@ int qeth_realloc_buffer_pool(struct qeth_card *card, int bufcnt) | |||
239 | } | 244 | } |
240 | EXPORT_SYMBOL_GPL(qeth_realloc_buffer_pool); | 245 | EXPORT_SYMBOL_GPL(qeth_realloc_buffer_pool); |
241 | 246 | ||
247 | static inline int qeth_cq_init(struct qeth_card *card) | ||
248 | { | ||
249 | int rc; | ||
250 | |||
251 | if (card->options.cq == QETH_CQ_ENABLED) { | ||
252 | QETH_DBF_TEXT(SETUP, 2, "cqinit"); | ||
253 | memset(card->qdio.c_q->qdio_bufs, 0, | ||
254 | QDIO_MAX_BUFFERS_PER_Q * sizeof(struct qdio_buffer)); | ||
255 | card->qdio.c_q->next_buf_to_init = 127; | ||
256 | rc = do_QDIO(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT, | ||
257 | card->qdio.no_in_queues - 1, 0, | ||
258 | 127); | ||
259 | if (rc) { | ||
260 | QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc); | ||
261 | goto out; | ||
262 | } | ||
263 | } | ||
264 | rc = 0; | ||
265 | out: | ||
266 | return rc; | ||
267 | } | ||
268 | |||
269 | static inline int qeth_alloc_cq(struct qeth_card *card) | ||
270 | { | ||
271 | int rc; | ||
272 | |||
273 | if (card->options.cq == QETH_CQ_ENABLED) { | ||
274 | int i; | ||
275 | struct qdio_outbuf_state *outbuf_states; | ||
276 | |||
277 | QETH_DBF_TEXT(SETUP, 2, "cqon"); | ||
278 | card->qdio.c_q = kzalloc(sizeof(struct qeth_qdio_q), | ||
279 | GFP_KERNEL); | ||
280 | if (!card->qdio.c_q) { | ||
281 | rc = -1; | ||
282 | goto kmsg_out; | ||
283 | } | ||
284 | QETH_DBF_HEX(SETUP, 2, &card->qdio.c_q, sizeof(void *)); | ||
285 | |||
286 | for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i) { | ||
287 | card->qdio.c_q->bufs[i].buffer = | ||
288 | &card->qdio.c_q->qdio_bufs[i]; | ||
289 | } | ||
290 | |||
291 | card->qdio.no_in_queues = 2; | ||
292 | |||
293 | card->qdio.out_bufstates = (struct qdio_outbuf_state *) | ||
294 | kzalloc(card->qdio.no_out_queues * | ||
295 | QDIO_MAX_BUFFERS_PER_Q * | ||
296 | sizeof(struct qdio_outbuf_state), GFP_KERNEL); | ||
297 | outbuf_states = card->qdio.out_bufstates; | ||
298 | if (outbuf_states == NULL) { | ||
299 | rc = -1; | ||
300 | goto free_cq_out; | ||
301 | } | ||
302 | for (i = 0; i < card->qdio.no_out_queues; ++i) { | ||
303 | card->qdio.out_qs[i]->bufstates = outbuf_states; | ||
304 | outbuf_states += QDIO_MAX_BUFFERS_PER_Q; | ||
305 | } | ||
306 | } else { | ||
307 | QETH_DBF_TEXT(SETUP, 2, "nocq"); | ||
308 | card->qdio.c_q = NULL; | ||
309 | card->qdio.no_in_queues = 1; | ||
310 | } | ||
311 | QETH_DBF_TEXT_(SETUP, 2, "iqc%d", card->qdio.no_in_queues); | ||
312 | rc = 0; | ||
313 | out: | ||
314 | return rc; | ||
315 | free_cq_out: | ||
316 | kfree(card->qdio.c_q); | ||
317 | card->qdio.c_q = NULL; | ||
318 | kmsg_out: | ||
319 | dev_err(&card->gdev->dev, "Failed to create completion queue\n"); | ||
320 | goto out; | ||
321 | } | ||
322 | |||
323 | static inline void qeth_free_cq(struct qeth_card *card) | ||
324 | { | ||
325 | if (card->qdio.c_q) { | ||
326 | --card->qdio.no_in_queues; | ||
327 | kfree(card->qdio.c_q); | ||
328 | card->qdio.c_q = NULL; | ||
329 | } | ||
330 | kfree(card->qdio.out_bufstates); | ||
331 | card->qdio.out_bufstates = NULL; | ||
332 | } | ||
333 | |||
334 | static inline void qeth_cleanup_handled_pending(struct qeth_qdio_out_q *q, | ||
335 | int bidx, int forced_cleanup) | ||
336 | { | ||
337 | if (q->bufs[bidx]->next_pending != NULL) { | ||
338 | struct qeth_qdio_out_buffer *head = q->bufs[bidx]; | ||
339 | struct qeth_qdio_out_buffer *c = q->bufs[bidx]->next_pending; | ||
340 | |||
341 | while (c) { | ||
342 | if (forced_cleanup || | ||
343 | atomic_read(&c->state) == | ||
344 | QETH_QDIO_BUF_HANDLED_DELAYED) { | ||
345 | struct qeth_qdio_out_buffer *f = c; | ||
346 | QETH_CARD_TEXT(f->q->card, 5, "fp"); | ||
347 | QETH_CARD_TEXT_(f->q->card, 5, "%lx", (long) f); | ||
348 | c = f->next_pending; | ||
349 | BUG_ON(head->next_pending != f); | ||
350 | head->next_pending = c; | ||
351 | kmem_cache_free(qeth_qdio_outbuf_cache, f); | ||
352 | } else { | ||
353 | head = c; | ||
354 | c = c->next_pending; | ||
355 | } | ||
356 | |||
357 | } | ||
358 | } | ||
359 | } | ||
360 | |||
361 | |||
362 | static inline void qeth_qdio_handle_aob(struct qeth_card *card, | ||
363 | unsigned long phys_aob_addr) { | ||
364 | struct qaob *aob; | ||
365 | struct qeth_qdio_out_buffer *buffer; | ||
366 | |||
367 | aob = (struct qaob *) phys_to_virt(phys_aob_addr); | ||
368 | QETH_CARD_TEXT(card, 5, "haob"); | ||
369 | QETH_CARD_TEXT_(card, 5, "%lx", phys_aob_addr); | ||
370 | buffer = (struct qeth_qdio_out_buffer *) aob->user1; | ||
371 | QETH_CARD_TEXT_(card, 5, "%lx", aob->user1); | ||
372 | |||
373 | BUG_ON(buffer == NULL); | ||
374 | |||
375 | buffer->aob = NULL; | ||
376 | qeth_clear_output_buffer(buffer->q, buffer, | ||
377 | QETH_QDIO_BUF_HANDLED_DELAYED); | ||
378 | /* from here on: do not touch buffer anymore */ | ||
379 | qdio_release_aob(aob); | ||
380 | } | ||
381 | |||
382 | static inline int qeth_is_cq(struct qeth_card *card, unsigned int queue) | ||
383 | { | ||
384 | return card->options.cq == QETH_CQ_ENABLED && | ||
385 | card->qdio.c_q != NULL && | ||
386 | queue != 0 && | ||
387 | queue == card->qdio.no_in_queues - 1; | ||
388 | } | ||
389 | |||
390 | |||
242 | static int qeth_issue_next_read(struct qeth_card *card) | 391 | static int qeth_issue_next_read(struct qeth_card *card) |
243 | { | 392 | { |
244 | int rc; | 393 | int rc; |
@@ -681,6 +830,7 @@ EXPORT_SYMBOL_GPL(qeth_do_run_thread); | |||
681 | void qeth_schedule_recovery(struct qeth_card *card) | 830 | void qeth_schedule_recovery(struct qeth_card *card) |
682 | { | 831 | { |
683 | QETH_CARD_TEXT(card, 2, "startrec"); | 832 | QETH_CARD_TEXT(card, 2, "startrec"); |
833 | WARN_ON(1); | ||
684 | if (qeth_set_thread_start_bit(card, QETH_RECOVER_THREAD) == 0) | 834 | if (qeth_set_thread_start_bit(card, QETH_RECOVER_THREAD) == 0) |
685 | schedule_work(&card->kernel_thread_starter); | 835 | schedule_work(&card->kernel_thread_starter); |
686 | } | 836 | } |
@@ -884,7 +1034,8 @@ out: | |||
884 | } | 1034 | } |
885 | 1035 | ||
886 | static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, | 1036 | static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, |
887 | struct qeth_qdio_out_buffer *buf) | 1037 | struct qeth_qdio_out_buffer *buf, |
1038 | enum qeth_qdio_buffer_states newbufstate) | ||
888 | { | 1039 | { |
889 | int i; | 1040 | int i; |
890 | struct sk_buff *skb; | 1041 | struct sk_buff *skb; |
@@ -912,21 +1063,36 @@ static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, | |||
912 | buf->buffer->element[15].eflags = 0; | 1063 | buf->buffer->element[15].eflags = 0; |
913 | buf->buffer->element[15].sflags = 0; | 1064 | buf->buffer->element[15].sflags = 0; |
914 | buf->next_element_to_fill = 0; | 1065 | buf->next_element_to_fill = 0; |
915 | atomic_set(&buf->state, QETH_QDIO_BUF_EMPTY); | 1066 | atomic_set(&buf->state, newbufstate); |
1067 | } | ||
1068 | |||
1069 | static void qeth_clear_outq_buffers(struct qeth_qdio_out_q *q, int free) | ||
1070 | { | ||
1071 | int j; | ||
1072 | |||
1073 | for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) { | ||
1074 | if (!q->bufs[j]) | ||
1075 | continue; | ||
1076 | qeth_cleanup_handled_pending(q, j, free); | ||
1077 | qeth_clear_output_buffer(q, q->bufs[j], QETH_QDIO_BUF_EMPTY); | ||
1078 | if (free) { | ||
1079 | kmem_cache_free(qeth_qdio_outbuf_cache, q->bufs[j]); | ||
1080 | q->bufs[j] = NULL; | ||
1081 | } | ||
1082 | } | ||
916 | } | 1083 | } |
917 | 1084 | ||
918 | void qeth_clear_qdio_buffers(struct qeth_card *card) | 1085 | void qeth_clear_qdio_buffers(struct qeth_card *card) |
919 | { | 1086 | { |
920 | int i, j; | 1087 | int i; |
921 | 1088 | ||
922 | QETH_CARD_TEXT(card, 2, "clearqdbf"); | 1089 | QETH_CARD_TEXT(card, 2, "clearqdbf"); |
923 | /* clear outbound buffers to free skbs */ | 1090 | /* clear outbound buffers to free skbs */ |
924 | for (i = 0; i < card->qdio.no_out_queues; ++i) | 1091 | for (i = 0; i < card->qdio.no_out_queues; ++i) { |
925 | if (card->qdio.out_qs[i]) { | 1092 | if (card->qdio.out_qs[i]) { |
926 | for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) | 1093 | qeth_clear_outq_buffers(card->qdio.out_qs[i], 0); |
927 | qeth_clear_output_buffer(card->qdio.out_qs[i], | ||
928 | &card->qdio.out_qs[i]->bufs[j]); | ||
929 | } | 1094 | } |
1095 | } | ||
930 | } | 1096 | } |
931 | EXPORT_SYMBOL_GPL(qeth_clear_qdio_buffers); | 1097 | EXPORT_SYMBOL_GPL(qeth_clear_qdio_buffers); |
932 | 1098 | ||
@@ -945,11 +1111,14 @@ static void qeth_free_buffer_pool(struct qeth_card *card) | |||
945 | 1111 | ||
946 | static void qeth_free_qdio_buffers(struct qeth_card *card) | 1112 | static void qeth_free_qdio_buffers(struct qeth_card *card) |
947 | { | 1113 | { |
948 | int i, j; | 1114 | int i; |
949 | 1115 | ||
950 | if (atomic_xchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED) == | 1116 | if (atomic_xchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED) == |
951 | QETH_QDIO_UNINITIALIZED) | 1117 | QETH_QDIO_UNINITIALIZED) |
952 | return; | 1118 | return; |
1119 | |||
1120 | qeth_free_cq(card); | ||
1121 | |||
953 | kfree(card->qdio.in_q); | 1122 | kfree(card->qdio.in_q); |
954 | card->qdio.in_q = NULL; | 1123 | card->qdio.in_q = NULL; |
955 | /* inbound buffer pool */ | 1124 | /* inbound buffer pool */ |
@@ -957,9 +1126,7 @@ static void qeth_free_qdio_buffers(struct qeth_card *card) | |||
957 | /* free outbound qdio_qs */ | 1126 | /* free outbound qdio_qs */ |
958 | if (card->qdio.out_qs) { | 1127 | if (card->qdio.out_qs) { |
959 | for (i = 0; i < card->qdio.no_out_queues; ++i) { | 1128 | for (i = 0; i < card->qdio.no_out_queues; ++i) { |
960 | for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) | 1129 | qeth_clear_outq_buffers(card->qdio.out_qs[i], 1); |
961 | qeth_clear_output_buffer(card->qdio.out_qs[i], | ||
962 | &card->qdio.out_qs[i]->bufs[j]); | ||
963 | kfree(card->qdio.out_qs[i]); | 1130 | kfree(card->qdio.out_qs[i]); |
964 | } | 1131 | } |
965 | kfree(card->qdio.out_qs); | 1132 | kfree(card->qdio.out_qs); |
@@ -1053,6 +1220,7 @@ static void qeth_set_intial_options(struct qeth_card *card) | |||
1053 | card->options.performance_stats = 0; | 1220 | card->options.performance_stats = 0; |
1054 | card->options.rx_sg_cb = QETH_RX_SG_CB; | 1221 | card->options.rx_sg_cb = QETH_RX_SG_CB; |
1055 | card->options.isolation = ISOLATION_MODE_NONE; | 1222 | card->options.isolation = ISOLATION_MODE_NONE; |
1223 | card->options.cq = QETH_CQ_DISABLED; | ||
1056 | } | 1224 | } |
1057 | 1225 | ||
1058 | static int qeth_do_start_thread(struct qeth_card *card, unsigned long thread) | 1226 | static int qeth_do_start_thread(struct qeth_card *card, unsigned long thread) |
@@ -1182,6 +1350,7 @@ static int qeth_determine_card_type(struct qeth_card *card) | |||
1182 | card->info.type = known_devices[i][QETH_DEV_MODEL_IND]; | 1350 | card->info.type = known_devices[i][QETH_DEV_MODEL_IND]; |
1183 | card->qdio.no_out_queues = | 1351 | card->qdio.no_out_queues = |
1184 | known_devices[i][QETH_QUEUE_NO_IND]; | 1352 | known_devices[i][QETH_QUEUE_NO_IND]; |
1353 | card->qdio.no_in_queues = 1; | ||
1185 | card->info.is_multicast_different = | 1354 | card->info.is_multicast_different = |
1186 | known_devices[i][QETH_MULTICAST_IND]; | 1355 | known_devices[i][QETH_MULTICAST_IND]; |
1187 | qeth_get_channel_path_desc(card); | 1356 | qeth_get_channel_path_desc(card); |
@@ -2029,6 +2198,37 @@ static int qeth_ulp_setup(struct qeth_card *card) | |||
2029 | return rc; | 2198 | return rc; |
2030 | } | 2199 | } |
2031 | 2200 | ||
2201 | static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *q, int bidx) | ||
2202 | { | ||
2203 | int rc; | ||
2204 | struct qeth_qdio_out_buffer *newbuf; | ||
2205 | |||
2206 | rc = 0; | ||
2207 | newbuf = kmem_cache_zalloc(qeth_qdio_outbuf_cache, GFP_ATOMIC); | ||
2208 | if (!newbuf) { | ||
2209 | rc = -ENOMEM; | ||
2210 | goto out; | ||
2211 | } | ||
2212 | newbuf->buffer = &q->qdio_bufs[bidx]; | ||
2213 | skb_queue_head_init(&newbuf->skb_list); | ||
2214 | lockdep_set_class(&newbuf->skb_list.lock, &qdio_out_skb_queue_key); | ||
2215 | newbuf->q = q; | ||
2216 | newbuf->aob = NULL; | ||
2217 | newbuf->next_pending = q->bufs[bidx]; | ||
2218 | atomic_set(&newbuf->state, QETH_QDIO_BUF_EMPTY); | ||
2219 | q->bufs[bidx] = newbuf; | ||
2220 | if (q->bufstates) { | ||
2221 | q->bufstates[bidx].user = newbuf; | ||
2222 | QETH_CARD_TEXT_(q->card, 2, "nbs%d", bidx); | ||
2223 | QETH_CARD_TEXT_(q->card, 2, "%lx", (long) newbuf); | ||
2224 | QETH_CARD_TEXT_(q->card, 2, "%lx", | ||
2225 | (long) newbuf->next_pending); | ||
2226 | } | ||
2227 | out: | ||
2228 | return rc; | ||
2229 | } | ||
2230 | |||
2231 | |||
2032 | static int qeth_alloc_qdio_buffers(struct qeth_card *card) | 2232 | static int qeth_alloc_qdio_buffers(struct qeth_card *card) |
2033 | { | 2233 | { |
2034 | int i, j; | 2234 | int i, j; |
@@ -2040,7 +2240,7 @@ static int qeth_alloc_qdio_buffers(struct qeth_card *card) | |||
2040 | return 0; | 2240 | return 0; |
2041 | 2241 | ||
2042 | card->qdio.in_q = kmalloc(sizeof(struct qeth_qdio_q), | 2242 | card->qdio.in_q = kmalloc(sizeof(struct qeth_qdio_q), |
2043 | GFP_KERNEL); | 2243 | GFP_KERNEL); |
2044 | if (!card->qdio.in_q) | 2244 | if (!card->qdio.in_q) |
2045 | goto out_nomem; | 2245 | goto out_nomem; |
2046 | QETH_DBF_TEXT(SETUP, 2, "inq"); | 2246 | QETH_DBF_TEXT(SETUP, 2, "inq"); |
@@ -2053,6 +2253,7 @@ static int qeth_alloc_qdio_buffers(struct qeth_card *card) | |||
2053 | /* inbound buffer pool */ | 2253 | /* inbound buffer pool */ |
2054 | if (qeth_alloc_buffer_pool(card)) | 2254 | if (qeth_alloc_buffer_pool(card)) |
2055 | goto out_freeinq; | 2255 | goto out_freeinq; |
2256 | |||
2056 | /* outbound */ | 2257 | /* outbound */ |
2057 | card->qdio.out_qs = | 2258 | card->qdio.out_qs = |
2058 | kmalloc(card->qdio.no_out_queues * | 2259 | kmalloc(card->qdio.no_out_queues * |
@@ -2070,21 +2271,30 @@ static int qeth_alloc_qdio_buffers(struct qeth_card *card) | |||
2070 | card->qdio.out_qs[i]->queue_no = i; | 2271 | card->qdio.out_qs[i]->queue_no = i; |
2071 | /* give outbound qeth_qdio_buffers their qdio_buffers */ | 2272 | /* give outbound qeth_qdio_buffers their qdio_buffers */ |
2072 | for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) { | 2273 | for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) { |
2073 | card->qdio.out_qs[i]->bufs[j].buffer = | 2274 | BUG_ON(card->qdio.out_qs[i]->bufs[j] != NULL); |
2074 | &card->qdio.out_qs[i]->qdio_bufs[j]; | 2275 | if (qeth_init_qdio_out_buf(card->qdio.out_qs[i], j)) |
2075 | skb_queue_head_init(&card->qdio.out_qs[i]->bufs[j]. | 2276 | goto out_freeoutqbufs; |
2076 | skb_list); | ||
2077 | lockdep_set_class( | ||
2078 | &card->qdio.out_qs[i]->bufs[j].skb_list.lock, | ||
2079 | &qdio_out_skb_queue_key); | ||
2080 | INIT_LIST_HEAD(&card->qdio.out_qs[i]->bufs[j].ctx_list); | ||
2081 | } | 2277 | } |
2082 | } | 2278 | } |
2279 | |||
2280 | /* completion */ | ||
2281 | if (qeth_alloc_cq(card)) | ||
2282 | goto out_freeoutq; | ||
2283 | |||
2083 | return 0; | 2284 | return 0; |
2084 | 2285 | ||
2286 | out_freeoutqbufs: | ||
2287 | while (j > 0) { | ||
2288 | --j; | ||
2289 | kmem_cache_free(qeth_qdio_outbuf_cache, | ||
2290 | card->qdio.out_qs[i]->bufs[j]); | ||
2291 | card->qdio.out_qs[i]->bufs[j] = NULL; | ||
2292 | } | ||
2085 | out_freeoutq: | 2293 | out_freeoutq: |
2086 | while (i > 0) | 2294 | while (i > 0) { |
2087 | kfree(card->qdio.out_qs[--i]); | 2295 | kfree(card->qdio.out_qs[--i]); |
2296 | qeth_clear_outq_buffers(card->qdio.out_qs[i], 1); | ||
2297 | } | ||
2088 | kfree(card->qdio.out_qs); | 2298 | kfree(card->qdio.out_qs); |
2089 | card->qdio.out_qs = NULL; | 2299 | card->qdio.out_qs = NULL; |
2090 | out_freepool: | 2300 | out_freepool: |
@@ -2401,13 +2611,21 @@ int qeth_init_qdio_queues(struct qeth_card *card) | |||
2401 | QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc); | 2611 | QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc); |
2402 | return rc; | 2612 | return rc; |
2403 | } | 2613 | } |
2614 | |||
2615 | /* completion */ | ||
2616 | rc = qeth_cq_init(card); | ||
2617 | if (rc) { | ||
2618 | return rc; | ||
2619 | } | ||
2620 | |||
2404 | /* outbound queue */ | 2621 | /* outbound queue */ |
2405 | for (i = 0; i < card->qdio.no_out_queues; ++i) { | 2622 | for (i = 0; i < card->qdio.no_out_queues; ++i) { |
2406 | memset(card->qdio.out_qs[i]->qdio_bufs, 0, | 2623 | memset(card->qdio.out_qs[i]->qdio_bufs, 0, |
2407 | QDIO_MAX_BUFFERS_PER_Q * sizeof(struct qdio_buffer)); | 2624 | QDIO_MAX_BUFFERS_PER_Q * sizeof(struct qdio_buffer)); |
2408 | for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) { | 2625 | for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) { |
2409 | qeth_clear_output_buffer(card->qdio.out_qs[i], | 2626 | qeth_clear_output_buffer(card->qdio.out_qs[i], |
2410 | &card->qdio.out_qs[i]->bufs[j]); | 2627 | card->qdio.out_qs[i]->bufs[j], |
2628 | QETH_QDIO_BUF_EMPTY); | ||
2411 | } | 2629 | } |
2412 | card->qdio.out_qs[i]->card = card; | 2630 | card->qdio.out_qs[i]->card = card; |
2413 | card->qdio.out_qs[i]->next_buf_to_fill = 0; | 2631 | card->qdio.out_qs[i]->next_buf_to_fill = 0; |
@@ -2789,8 +3007,6 @@ void qeth_queue_input_buffer(struct qeth_card *card, int index) | |||
2789 | qeth_get_micros() - | 3007 | qeth_get_micros() - |
2790 | card->perf_stats.inbound_do_qdio_start_time; | 3008 | card->perf_stats.inbound_do_qdio_start_time; |
2791 | if (rc) { | 3009 | if (rc) { |
2792 | dev_warn(&card->gdev->dev, | ||
2793 | "QDIO reported an error, rc=%i\n", rc); | ||
2794 | QETH_CARD_TEXT(card, 2, "qinberr"); | 3010 | QETH_CARD_TEXT(card, 2, "qinberr"); |
2795 | } | 3011 | } |
2796 | queue->next_buf_to_init = (queue->next_buf_to_init + count) % | 3012 | queue->next_buf_to_init = (queue->next_buf_to_init + count) % |
@@ -2864,12 +3080,12 @@ static int qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue) | |||
2864 | queue->card->perf_stats.sc_p_dp++; | 3080 | queue->card->perf_stats.sc_p_dp++; |
2865 | queue->do_pack = 0; | 3081 | queue->do_pack = 0; |
2866 | /* flush packing buffers */ | 3082 | /* flush packing buffers */ |
2867 | buffer = &queue->bufs[queue->next_buf_to_fill]; | 3083 | buffer = queue->bufs[queue->next_buf_to_fill]; |
2868 | if ((atomic_read(&buffer->state) == | 3084 | if ((atomic_read(&buffer->state) == |
2869 | QETH_QDIO_BUF_EMPTY) && | 3085 | QETH_QDIO_BUF_EMPTY) && |
2870 | (buffer->next_element_to_fill > 0)) { | 3086 | (buffer->next_element_to_fill > 0)) { |
2871 | atomic_set(&buffer->state, | 3087 | atomic_set(&buffer->state, |
2872 | QETH_QDIO_BUF_PRIMED); | 3088 | QETH_QDIO_BUF_PRIMED); |
2873 | flush_count++; | 3089 | flush_count++; |
2874 | queue->next_buf_to_fill = | 3090 | queue->next_buf_to_fill = |
2875 | (queue->next_buf_to_fill + 1) % | 3091 | (queue->next_buf_to_fill + 1) % |
@@ -2880,6 +3096,7 @@ static int qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue) | |||
2880 | return flush_count; | 3096 | return flush_count; |
2881 | } | 3097 | } |
2882 | 3098 | ||
3099 | |||
2883 | /* | 3100 | /* |
2884 | * Called to flush a packing buffer if no more pci flags are on the queue. | 3101 | * Called to flush a packing buffer if no more pci flags are on the queue. |
2885 | * Checks if there is a packing buffer and prepares it to be flushed. | 3102 | * Checks if there is a packing buffer and prepares it to be flushed. |
@@ -2889,7 +3106,7 @@ static int qeth_flush_buffers_on_no_pci(struct qeth_qdio_out_q *queue) | |||
2889 | { | 3106 | { |
2890 | struct qeth_qdio_out_buffer *buffer; | 3107 | struct qeth_qdio_out_buffer *buffer; |
2891 | 3108 | ||
2892 | buffer = &queue->bufs[queue->next_buf_to_fill]; | 3109 | buffer = queue->bufs[queue->next_buf_to_fill]; |
2893 | if ((atomic_read(&buffer->state) == QETH_QDIO_BUF_EMPTY) && | 3110 | if ((atomic_read(&buffer->state) == QETH_QDIO_BUF_EMPTY) && |
2894 | (buffer->next_element_to_fill > 0)) { | 3111 | (buffer->next_element_to_fill > 0)) { |
2895 | /* it's a packing buffer */ | 3112 | /* it's a packing buffer */ |
@@ -2910,10 +3127,14 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index, | |||
2910 | unsigned int qdio_flags; | 3127 | unsigned int qdio_flags; |
2911 | 3128 | ||
2912 | for (i = index; i < index + count; ++i) { | 3129 | for (i = index; i < index + count; ++i) { |
2913 | buf = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q]; | 3130 | int bidx = i % QDIO_MAX_BUFFERS_PER_Q; |
3131 | buf = queue->bufs[bidx]; | ||
2914 | buf->buffer->element[buf->next_element_to_fill - 1].eflags |= | 3132 | buf->buffer->element[buf->next_element_to_fill - 1].eflags |= |
2915 | SBAL_EFLAGS_LAST_ENTRY; | 3133 | SBAL_EFLAGS_LAST_ENTRY; |
2916 | 3134 | ||
3135 | if (queue->bufstates) | ||
3136 | queue->bufstates[bidx].user = buf; | ||
3137 | |||
2917 | if (queue->card->info.type == QETH_CARD_TYPE_IQD) | 3138 | if (queue->card->info.type == QETH_CARD_TYPE_IQD) |
2918 | continue; | 3139 | continue; |
2919 | 3140 | ||
@@ -2965,6 +3186,9 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index, | |||
2965 | if (rc == QDIO_ERROR_SIGA_TARGET) | 3186 | if (rc == QDIO_ERROR_SIGA_TARGET) |
2966 | return; | 3187 | return; |
2967 | QETH_CARD_TEXT(queue->card, 2, "flushbuf"); | 3188 | QETH_CARD_TEXT(queue->card, 2, "flushbuf"); |
3189 | QETH_CARD_TEXT_(queue->card, 2, " q%d", queue->queue_no); | ||
3190 | QETH_CARD_TEXT_(queue->card, 2, " idx%d", index); | ||
3191 | QETH_CARD_TEXT_(queue->card, 2, " c%d", count); | ||
2968 | QETH_CARD_TEXT_(queue->card, 2, " err%d", rc); | 3192 | QETH_CARD_TEXT_(queue->card, 2, " err%d", rc); |
2969 | 3193 | ||
2970 | /* this must not happen under normal circumstances. if it | 3194 | /* this must not happen under normal circumstances. if it |
@@ -3026,14 +3250,120 @@ void qeth_qdio_start_poll(struct ccw_device *ccwdev, int queue, | |||
3026 | } | 3250 | } |
3027 | EXPORT_SYMBOL_GPL(qeth_qdio_start_poll); | 3251 | EXPORT_SYMBOL_GPL(qeth_qdio_start_poll); |
3028 | 3252 | ||
3253 | int qeth_configure_cq(struct qeth_card *card, enum qeth_cq cq) | ||
3254 | { | ||
3255 | int rc; | ||
3256 | |||
3257 | if (card->options.cq == QETH_CQ_NOTAVAILABLE) { | ||
3258 | rc = -1; | ||
3259 | goto out; | ||
3260 | } else { | ||
3261 | if (card->options.cq == cq) { | ||
3262 | rc = 0; | ||
3263 | goto out; | ||
3264 | } | ||
3265 | |||
3266 | if (card->state != CARD_STATE_DOWN && | ||
3267 | card->state != CARD_STATE_RECOVER) { | ||
3268 | rc = -1; | ||
3269 | goto out; | ||
3270 | } | ||
3271 | |||
3272 | qeth_free_qdio_buffers(card); | ||
3273 | card->options.cq = cq; | ||
3274 | rc = 0; | ||
3275 | } | ||
3276 | out: | ||
3277 | return rc; | ||
3278 | |||
3279 | } | ||
3280 | EXPORT_SYMBOL_GPL(qeth_configure_cq); | ||
3281 | |||
3282 | |||
3283 | static void qeth_qdio_cq_handler(struct qeth_card *card, | ||
3284 | unsigned int qdio_err, | ||
3285 | unsigned int queue, int first_element, int count) { | ||
3286 | struct qeth_qdio_q *cq = card->qdio.c_q; | ||
3287 | int i; | ||
3288 | int rc; | ||
3289 | |||
3290 | if (!qeth_is_cq(card, queue)) | ||
3291 | goto out; | ||
3292 | |||
3293 | QETH_CARD_TEXT_(card, 5, "qcqhe%d", first_element); | ||
3294 | QETH_CARD_TEXT_(card, 5, "qcqhc%d", count); | ||
3295 | QETH_CARD_TEXT_(card, 5, "qcqherr%d", qdio_err); | ||
3296 | |||
3297 | if (qdio_err) { | ||
3298 | netif_stop_queue(card->dev); | ||
3299 | qeth_schedule_recovery(card); | ||
3300 | goto out; | ||
3301 | } | ||
3302 | |||
3303 | if (card->options.performance_stats) { | ||
3304 | card->perf_stats.cq_cnt++; | ||
3305 | card->perf_stats.cq_start_time = qeth_get_micros(); | ||
3306 | } | ||
3307 | |||
3308 | for (i = first_element; i < first_element + count; ++i) { | ||
3309 | int bidx = i % QDIO_MAX_BUFFERS_PER_Q; | ||
3310 | struct qdio_buffer *buffer = &cq->qdio_bufs[bidx]; | ||
3311 | int e; | ||
3312 | |||
3313 | e = 0; | ||
3314 | while (buffer->element[e].addr) { | ||
3315 | unsigned long phys_aob_addr; | ||
3316 | |||
3317 | phys_aob_addr = (unsigned long) buffer->element[e].addr; | ||
3318 | qeth_qdio_handle_aob(card, phys_aob_addr); | ||
3319 | buffer->element[e].addr = NULL; | ||
3320 | buffer->element[e].eflags = 0; | ||
3321 | buffer->element[e].sflags = 0; | ||
3322 | buffer->element[e].length = 0; | ||
3323 | |||
3324 | ++e; | ||
3325 | } | ||
3326 | |||
3327 | buffer->element[15].eflags = 0; | ||
3328 | buffer->element[15].sflags = 0; | ||
3329 | } | ||
3330 | rc = do_QDIO(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT, queue, | ||
3331 | card->qdio.c_q->next_buf_to_init, | ||
3332 | count); | ||
3333 | if (rc) { | ||
3334 | dev_warn(&card->gdev->dev, | ||
3335 | "QDIO reported an error, rc=%i\n", rc); | ||
3336 | QETH_CARD_TEXT(card, 2, "qcqherr"); | ||
3337 | } | ||
3338 | card->qdio.c_q->next_buf_to_init = (card->qdio.c_q->next_buf_to_init | ||
3339 | + count) % QDIO_MAX_BUFFERS_PER_Q; | ||
3340 | |||
3341 | netif_wake_queue(card->dev); | ||
3342 | |||
3343 | if (card->options.performance_stats) { | ||
3344 | int delta_t = qeth_get_micros(); | ||
3345 | delta_t -= card->perf_stats.cq_start_time; | ||
3346 | card->perf_stats.cq_time += delta_t; | ||
3347 | } | ||
3348 | out: | ||
3349 | return; | ||
3350 | } | ||
3351 | |||
3029 | void qeth_qdio_input_handler(struct ccw_device *ccwdev, unsigned int qdio_err, | 3352 | void qeth_qdio_input_handler(struct ccw_device *ccwdev, unsigned int qdio_err, |
3030 | unsigned int queue, int first_element, int count, | 3353 | unsigned int queue, int first_elem, int count, |
3031 | unsigned long card_ptr) | 3354 | unsigned long card_ptr) |
3032 | { | 3355 | { |
3033 | struct qeth_card *card = (struct qeth_card *)card_ptr; | 3356 | struct qeth_card *card = (struct qeth_card *)card_ptr; |
3034 | 3357 | ||
3035 | if (qdio_err) | 3358 | QETH_CARD_TEXT_(card, 2, "qihq%d", queue); |
3359 | QETH_CARD_TEXT_(card, 2, "qiec%d", qdio_err); | ||
3360 | |||
3361 | if (qeth_is_cq(card, queue)) | ||
3362 | qeth_qdio_cq_handler(card, qdio_err, queue, first_elem, count); | ||
3363 | else if (qdio_err) | ||
3036 | qeth_schedule_recovery(card); | 3364 | qeth_schedule_recovery(card); |
3365 | |||
3366 | |||
3037 | } | 3367 | } |
3038 | EXPORT_SYMBOL_GPL(qeth_qdio_input_handler); | 3368 | EXPORT_SYMBOL_GPL(qeth_qdio_input_handler); |
3039 | 3369 | ||
@@ -3059,9 +3389,26 @@ void qeth_qdio_output_handler(struct ccw_device *ccwdev, | |||
3059 | qeth_get_micros(); | 3389 | qeth_get_micros(); |
3060 | } | 3390 | } |
3061 | for (i = first_element; i < (first_element + count); ++i) { | 3391 | for (i = first_element; i < (first_element + count); ++i) { |
3062 | buffer = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q]; | 3392 | int bidx = i % QDIO_MAX_BUFFERS_PER_Q; |
3393 | buffer = queue->bufs[bidx]; | ||
3063 | qeth_handle_send_error(card, buffer, qdio_error); | 3394 | qeth_handle_send_error(card, buffer, qdio_error); |
3064 | qeth_clear_output_buffer(queue, buffer); | 3395 | |
3396 | if (queue->bufstates && | ||
3397 | (queue->bufstates[bidx].flags & | ||
3398 | QDIO_OUTBUF_STATE_FLAG_PENDING) != 0) { | ||
3399 | buffer->aob = queue->bufstates[bidx].aob; | ||
3400 | QETH_CARD_TEXT_(queue->card, 5, "pel%d", bidx); | ||
3401 | QETH_CARD_TEXT_(queue->card, 5, "aob"); | ||
3402 | QETH_CARD_TEXT_(queue->card, 5, "%lx", | ||
3403 | virt_to_phys(buffer->aob)); | ||
3404 | BUG_ON(bidx < 0 || bidx >= QDIO_MAX_BUFFERS_PER_Q); | ||
3405 | if (qeth_init_qdio_out_buf(queue, bidx)) | ||
3406 | qeth_schedule_recovery(card); | ||
3407 | } else { | ||
3408 | qeth_clear_output_buffer(queue, buffer, | ||
3409 | QETH_QDIO_BUF_EMPTY); | ||
3410 | } | ||
3411 | qeth_cleanup_handled_pending(queue, bidx, 0); | ||
3065 | } | 3412 | } |
3066 | atomic_sub(count, &queue->used_buffers); | 3413 | atomic_sub(count, &queue->used_buffers); |
3067 | /* check if we need to do something on this outbound queue */ | 3414 | /* check if we need to do something on this outbound queue */ |
@@ -3293,7 +3640,7 @@ int qeth_do_send_packet_fast(struct qeth_card *card, | |||
3293 | QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED); | 3640 | QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED); |
3294 | /* ... now we've got the queue */ | 3641 | /* ... now we've got the queue */ |
3295 | index = queue->next_buf_to_fill; | 3642 | index = queue->next_buf_to_fill; |
3296 | buffer = &queue->bufs[queue->next_buf_to_fill]; | 3643 | buffer = queue->bufs[queue->next_buf_to_fill]; |
3297 | /* | 3644 | /* |
3298 | * check if buffer is empty to make sure that we do not 'overtake' | 3645 | * check if buffer is empty to make sure that we do not 'overtake' |
3299 | * ourselves and try to fill a buffer that is already primed | 3646 | * ourselves and try to fill a buffer that is already primed |
@@ -3327,7 +3674,7 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, | |||
3327 | while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED, | 3674 | while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED, |
3328 | QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED); | 3675 | QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED); |
3329 | start_index = queue->next_buf_to_fill; | 3676 | start_index = queue->next_buf_to_fill; |
3330 | buffer = &queue->bufs[queue->next_buf_to_fill]; | 3677 | buffer = queue->bufs[queue->next_buf_to_fill]; |
3331 | /* | 3678 | /* |
3332 | * check if buffer is empty to make sure that we do not 'overtake' | 3679 | * check if buffer is empty to make sure that we do not 'overtake' |
3333 | * ourselves and try to fill a buffer that is already primed | 3680 | * ourselves and try to fill a buffer that is already primed |
@@ -3349,7 +3696,7 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, | |||
3349 | queue->next_buf_to_fill = | 3696 | queue->next_buf_to_fill = |
3350 | (queue->next_buf_to_fill + 1) % | 3697 | (queue->next_buf_to_fill + 1) % |
3351 | QDIO_MAX_BUFFERS_PER_Q; | 3698 | QDIO_MAX_BUFFERS_PER_Q; |
3352 | buffer = &queue->bufs[queue->next_buf_to_fill]; | 3699 | buffer = queue->bufs[queue->next_buf_to_fill]; |
3353 | /* we did a step forward, so check buffer state | 3700 | /* we did a step forward, so check buffer state |
3354 | * again */ | 3701 | * again */ |
3355 | if (atomic_read(&buffer->state) != | 3702 | if (atomic_read(&buffer->state) != |
@@ -3927,6 +4274,20 @@ static void qeth_determine_capabilities(struct qeth_card *card) | |||
3927 | if (rc) | 4274 | if (rc) |
3928 | QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc); | 4275 | QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc); |
3929 | 4276 | ||
4277 | QETH_DBF_TEXT_(SETUP, 2, "qfmt%d", card->ssqd.qfmt); | ||
4278 | QETH_DBF_TEXT_(SETUP, 2, "%d", card->ssqd.qdioac1); | ||
4279 | QETH_DBF_TEXT_(SETUP, 2, "%d", card->ssqd.qdioac3); | ||
4280 | QETH_DBF_TEXT_(SETUP, 2, "icnt%d", card->ssqd.icnt); | ||
4281 | if (!((card->ssqd.qfmt != QDIO_IQDIO_QFMT) || | ||
4282 | ((card->ssqd.qdioac1 & CHSC_AC1_INITIATE_INPUTQ) == 0) || | ||
4283 | ((card->ssqd.qdioac3 & CHSC_AC3_FORMAT2_CQ_AVAILABLE) == 0))) { | ||
4284 | dev_info(&card->gdev->dev, | ||
4285 | "Completion Queueing supported\n"); | ||
4286 | } else { | ||
4287 | card->options.cq = QETH_CQ_NOTAVAILABLE; | ||
4288 | } | ||
4289 | |||
4290 | |||
3930 | out_offline: | 4291 | out_offline: |
3931 | if (ddev_offline == 1) | 4292 | if (ddev_offline == 1) |
3932 | ccw_device_set_offline(ddev); | 4293 | ccw_device_set_offline(ddev); |
@@ -3934,6 +4295,24 @@ out: | |||
3934 | return; | 4295 | return; |
3935 | } | 4296 | } |
3936 | 4297 | ||
4298 | static inline void qeth_qdio_establish_cq(struct qeth_card *card, | ||
4299 | struct qdio_buffer **in_sbal_ptrs, | ||
4300 | void (**queue_start_poll) (struct ccw_device *, int, unsigned long)) { | ||
4301 | int i; | ||
4302 | |||
4303 | if (card->options.cq == QETH_CQ_ENABLED) { | ||
4304 | int offset = QDIO_MAX_BUFFERS_PER_Q * | ||
4305 | (card->qdio.no_in_queues - 1); | ||
4306 | i = QDIO_MAX_BUFFERS_PER_Q * (card->qdio.no_in_queues - 1); | ||
4307 | for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i) { | ||
4308 | in_sbal_ptrs[offset + i] = (struct qdio_buffer *) | ||
4309 | virt_to_phys(card->qdio.c_q->bufs[i].buffer); | ||
4310 | } | ||
4311 | |||
4312 | queue_start_poll[card->qdio.no_in_queues - 1] = NULL; | ||
4313 | } | ||
4314 | } | ||
4315 | |||
3937 | static int qeth_qdio_establish(struct qeth_card *card) | 4316 | static int qeth_qdio_establish(struct qeth_card *card) |
3938 | { | 4317 | { |
3939 | struct qdio_initialize init_data; | 4318 | struct qdio_initialize init_data; |
@@ -3956,22 +4335,28 @@ static int qeth_qdio_establish(struct qeth_card *card) | |||
3956 | qeth_create_qib_param_field(card, qib_param_field); | 4335 | qeth_create_qib_param_field(card, qib_param_field); |
3957 | qeth_create_qib_param_field_blkt(card, qib_param_field); | 4336 | qeth_create_qib_param_field_blkt(card, qib_param_field); |
3958 | 4337 | ||
3959 | in_sbal_ptrs = kmalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof(void *), | 4338 | in_sbal_ptrs = kmalloc(card->qdio.no_in_queues * |
4339 | QDIO_MAX_BUFFERS_PER_Q * sizeof(void *), | ||
3960 | GFP_KERNEL); | 4340 | GFP_KERNEL); |
3961 | if (!in_sbal_ptrs) { | 4341 | if (!in_sbal_ptrs) { |
3962 | rc = -ENOMEM; | 4342 | rc = -ENOMEM; |
3963 | goto out_free_qib_param; | 4343 | goto out_free_qib_param; |
3964 | } | 4344 | } |
3965 | for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i) | 4345 | for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i) { |
3966 | in_sbal_ptrs[i] = (struct qdio_buffer *) | 4346 | in_sbal_ptrs[i] = (struct qdio_buffer *) |
3967 | virt_to_phys(card->qdio.in_q->bufs[i].buffer); | 4347 | virt_to_phys(card->qdio.in_q->bufs[i].buffer); |
4348 | } | ||
3968 | 4349 | ||
3969 | queue_start_poll = kmalloc(sizeof(void *) * 1, GFP_KERNEL); | 4350 | queue_start_poll = kzalloc(sizeof(void *) * card->qdio.no_in_queues, |
4351 | GFP_KERNEL); | ||
3970 | if (!queue_start_poll) { | 4352 | if (!queue_start_poll) { |
3971 | rc = -ENOMEM; | 4353 | rc = -ENOMEM; |
3972 | goto out_free_in_sbals; | 4354 | goto out_free_in_sbals; |
3973 | } | 4355 | } |
3974 | queue_start_poll[0] = card->discipline.start_poll; | 4356 | for (i = 0; i < card->qdio.no_in_queues; ++i) |
4357 | queue_start_poll[i] = card->discipline.start_poll; | ||
4358 | |||
4359 | qeth_qdio_establish_cq(card, in_sbal_ptrs, queue_start_poll); | ||
3975 | 4360 | ||
3976 | out_sbal_ptrs = | 4361 | out_sbal_ptrs = |
3977 | kmalloc(card->qdio.no_out_queues * QDIO_MAX_BUFFERS_PER_Q * | 4362 | kmalloc(card->qdio.no_out_queues * QDIO_MAX_BUFFERS_PER_Q * |
@@ -3983,7 +4368,7 @@ static int qeth_qdio_establish(struct qeth_card *card) | |||
3983 | for (i = 0, k = 0; i < card->qdio.no_out_queues; ++i) | 4368 | for (i = 0, k = 0; i < card->qdio.no_out_queues; ++i) |
3984 | for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j, ++k) { | 4369 | for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j, ++k) { |
3985 | out_sbal_ptrs[k] = (struct qdio_buffer *)virt_to_phys( | 4370 | out_sbal_ptrs[k] = (struct qdio_buffer *)virt_to_phys( |
3986 | card->qdio.out_qs[i]->bufs[j].buffer); | 4371 | card->qdio.out_qs[i]->bufs[j]->buffer); |
3987 | } | 4372 | } |
3988 | 4373 | ||
3989 | memset(&init_data, 0, sizeof(struct qdio_initialize)); | 4374 | memset(&init_data, 0, sizeof(struct qdio_initialize)); |
@@ -3991,7 +4376,7 @@ static int qeth_qdio_establish(struct qeth_card *card) | |||
3991 | init_data.q_format = qeth_get_qdio_q_format(card); | 4376 | init_data.q_format = qeth_get_qdio_q_format(card); |
3992 | init_data.qib_param_field_format = 0; | 4377 | init_data.qib_param_field_format = 0; |
3993 | init_data.qib_param_field = qib_param_field; | 4378 | init_data.qib_param_field = qib_param_field; |
3994 | init_data.no_input_qs = 1; | 4379 | init_data.no_input_qs = card->qdio.no_in_queues; |
3995 | init_data.no_output_qs = card->qdio.no_out_queues; | 4380 | init_data.no_output_qs = card->qdio.no_out_queues; |
3996 | init_data.input_handler = card->discipline.input_handler; | 4381 | init_data.input_handler = card->discipline.input_handler; |
3997 | init_data.output_handler = card->discipline.output_handler; | 4382 | init_data.output_handler = card->discipline.output_handler; |
@@ -3999,6 +4384,7 @@ static int qeth_qdio_establish(struct qeth_card *card) | |||
3999 | init_data.int_parm = (unsigned long) card; | 4384 | init_data.int_parm = (unsigned long) card; |
4000 | init_data.input_sbal_addr_array = (void **) in_sbal_ptrs; | 4385 | init_data.input_sbal_addr_array = (void **) in_sbal_ptrs; |
4001 | init_data.output_sbal_addr_array = (void **) out_sbal_ptrs; | 4386 | init_data.output_sbal_addr_array = (void **) out_sbal_ptrs; |
4387 | init_data.output_sbal_state_array = card->qdio.out_bufstates; | ||
4002 | init_data.scan_threshold = | 4388 | init_data.scan_threshold = |
4003 | (card->info.type == QETH_CARD_TYPE_IQD) ? 8 : 32; | 4389 | (card->info.type == QETH_CARD_TYPE_IQD) ? 8 : 32; |
4004 | 4390 | ||
@@ -4015,6 +4401,17 @@ static int qeth_qdio_establish(struct qeth_card *card) | |||
4015 | qdio_free(CARD_DDEV(card)); | 4401 | qdio_free(CARD_DDEV(card)); |
4016 | } | 4402 | } |
4017 | } | 4403 | } |
4404 | |||
4405 | switch (card->options.cq) { | ||
4406 | case QETH_CQ_ENABLED: | ||
4407 | dev_info(&card->gdev->dev, "Completion Queue support enabled"); | ||
4408 | break; | ||
4409 | case QETH_CQ_DISABLED: | ||
4410 | dev_info(&card->gdev->dev, "Completion Queue support disabled"); | ||
4411 | break; | ||
4412 | default: | ||
4413 | break; | ||
4414 | } | ||
4018 | out: | 4415 | out: |
4019 | kfree(out_sbal_ptrs); | 4416 | kfree(out_sbal_ptrs); |
4020 | out_free_queue_start_poll: | 4417 | out_free_queue_start_poll: |
@@ -4193,6 +4590,8 @@ static inline int qeth_create_skb_frag(struct qdio_buffer_element *element, | |||
4193 | (*pskb)->truesize += data_len; | 4590 | (*pskb)->truesize += data_len; |
4194 | (*pfrag)++; | 4591 | (*pfrag)++; |
4195 | } | 4592 | } |
4593 | |||
4594 | |||
4196 | return 0; | 4595 | return 0; |
4197 | } | 4596 | } |
4198 | 4597 | ||
@@ -4666,6 +5065,8 @@ static struct { | |||
4666 | {"tx do_QDIO count"}, | 5065 | {"tx do_QDIO count"}, |
4667 | {"tx csum"}, | 5066 | {"tx csum"}, |
4668 | {"tx lin"}, | 5067 | {"tx lin"}, |
5068 | {"cq handler count"}, | ||
5069 | {"cq handler time"} | ||
4669 | }; | 5070 | }; |
4670 | 5071 | ||
4671 | int qeth_core_get_sset_count(struct net_device *dev, int stringset) | 5072 | int qeth_core_get_sset_count(struct net_device *dev, int stringset) |
@@ -4724,6 +5125,8 @@ void qeth_core_get_ethtool_stats(struct net_device *dev, | |||
4724 | data[32] = card->perf_stats.outbound_do_qdio_cnt; | 5125 | data[32] = card->perf_stats.outbound_do_qdio_cnt; |
4725 | data[33] = card->perf_stats.tx_csum; | 5126 | data[33] = card->perf_stats.tx_csum; |
4726 | data[34] = card->perf_stats.tx_lin; | 5127 | data[34] = card->perf_stats.tx_lin; |
5128 | data[35] = card->perf_stats.cq_cnt; | ||
5129 | data[36] = card->perf_stats.cq_time; | ||
4727 | } | 5130 | } |
4728 | EXPORT_SYMBOL_GPL(qeth_core_get_ethtool_stats); | 5131 | EXPORT_SYMBOL_GPL(qeth_core_get_ethtool_stats); |
4729 | 5132 | ||
@@ -4882,7 +5285,16 @@ static int __init qeth_core_init(void) | |||
4882 | goto slab_err; | 5285 | goto slab_err; |
4883 | } | 5286 | } |
4884 | 5287 | ||
5288 | qeth_qdio_outbuf_cache = kmem_cache_create("qeth_buf", | ||
5289 | sizeof(struct qeth_qdio_out_buffer), 0, 0, NULL); | ||
5290 | if (!qeth_qdio_outbuf_cache) { | ||
5291 | rc = -ENOMEM; | ||
5292 | goto cqslab_err; | ||
5293 | } | ||
5294 | |||
4885 | return 0; | 5295 | return 0; |
5296 | cqslab_err: | ||
5297 | kmem_cache_destroy(qeth_core_header_cache); | ||
4886 | slab_err: | 5298 | slab_err: |
4887 | root_device_unregister(qeth_core_root_dev); | 5299 | root_device_unregister(qeth_core_root_dev); |
4888 | register_err: | 5300 | register_err: |
@@ -4907,6 +5319,7 @@ static void __exit qeth_core_exit(void) | |||
4907 | &driver_attr_group); | 5319 | &driver_attr_group); |
4908 | ccwgroup_driver_unregister(&qeth_core_ccwgroup_driver); | 5320 | ccwgroup_driver_unregister(&qeth_core_ccwgroup_driver); |
4909 | ccw_driver_unregister(&qeth_ccw_driver); | 5321 | ccw_driver_unregister(&qeth_ccw_driver); |
5322 | kmem_cache_destroy(qeth_qdio_outbuf_cache); | ||
4910 | kmem_cache_destroy(qeth_core_header_cache); | 5323 | kmem_cache_destroy(qeth_core_header_cache); |
4911 | qeth_unregister_dbf_views(); | 5324 | qeth_unregister_dbf_views(); |
4912 | pr_info("core functions removed\n"); | 5325 | pr_info("core functions removed\n"); |