aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorSebastian Ott <sebott@linux.vnet.ibm.com>2014-06-27 11:09:25 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2014-07-22 03:26:15 -0400
commitd445a4e28c0ff740e946ae22860be85428814c39 (patch)
tree500daa23bf7efe87fa5e1bbb91f77994f041e787 /drivers/s390
parent6d284bde2beef9d4d067281b08f86554f41de799 (diff)
s390/qeth: extract qdio buffers from output buffer struct
Because of the embedded qdio_buffer array struct qeth_qdio_out_q is quite large resulting in an order 4 allocation. This is likely to fail at runtime and wastes a lot of memory since the actual size is just about 34K. Since there is no need for this buffer to be contiguous split it up using qdio buffer helpers. Reported-by: Neale Ferguson <neale@sinenomine.net> Reviewed-by: Ursula Braun <ursula.braun@de.ibm.com> Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/net/qeth_core.h4
-rw-r--r--drivers/s390/net/qeth_core_main.c91
2 files changed, 58 insertions, 37 deletions
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index 4f9a3180f663..4b32608e79f9 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -465,7 +465,7 @@ enum qeth_out_q_states {
465}; 465};
466 466
467struct qeth_qdio_out_q { 467struct qeth_qdio_out_q {
468 struct qdio_buffer qdio_bufs[QDIO_MAX_BUFFERS_PER_Q]; 468 struct qdio_buffer *qdio_bufs[QDIO_MAX_BUFFERS_PER_Q];
469 struct qeth_qdio_out_buffer *bufs[QDIO_MAX_BUFFERS_PER_Q]; 469 struct qeth_qdio_out_buffer *bufs[QDIO_MAX_BUFFERS_PER_Q];
470 struct qdio_outbuf_state *bufstates; /* convenience pointer */ 470 struct qdio_outbuf_state *bufstates; /* convenience pointer */
471 int queue_no; 471 int queue_no;
@@ -483,7 +483,7 @@ struct qeth_qdio_out_q {
483 atomic_t used_buffers; 483 atomic_t used_buffers;
484 /* indicates whether PCI flag must be set (or if one is outstanding) */ 484 /* indicates whether PCI flag must be set (or if one is outstanding) */
485 atomic_t set_pci_flags_count; 485 atomic_t set_pci_flags_count;
486} __attribute__ ((aligned(256))); 486};
487 487
488struct qeth_qdio_info { 488struct qeth_qdio_info {
489 atomic_t state; 489 atomic_t state;
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index acedba8539e4..bececacbc836 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -1302,35 +1302,6 @@ static void qeth_free_buffer_pool(struct qeth_card *card)
1302 } 1302 }
1303} 1303}
1304 1304
1305static void qeth_free_qdio_buffers(struct qeth_card *card)
1306{
1307 int i, j;
1308
1309 if (atomic_xchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED) ==
1310 QETH_QDIO_UNINITIALIZED)
1311 return;
1312
1313 qeth_free_cq(card);
1314 cancel_delayed_work_sync(&card->buffer_reclaim_work);
1315 for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
1316 if (card->qdio.in_q->bufs[j].rx_skb)
1317 dev_kfree_skb_any(card->qdio.in_q->bufs[j].rx_skb);
1318 }
1319 qeth_free_qdio_queue(card->qdio.in_q);
1320 card->qdio.in_q = NULL;
1321 /* inbound buffer pool */
1322 qeth_free_buffer_pool(card);
1323 /* free outbound qdio_qs */
1324 if (card->qdio.out_qs) {
1325 for (i = 0; i < card->qdio.no_out_queues; ++i) {
1326 qeth_clear_outq_buffers(card->qdio.out_qs[i], 1);
1327 kfree(card->qdio.out_qs[i]);
1328 }
1329 kfree(card->qdio.out_qs);
1330 card->qdio.out_qs = NULL;
1331 }
1332}
1333
1334static void qeth_clean_channel(struct qeth_channel *channel) 1305static void qeth_clean_channel(struct qeth_channel *channel)
1335{ 1306{
1336 int cnt; 1307 int cnt;
@@ -2412,7 +2383,7 @@ static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *q, int bidx)
2412 rc = -ENOMEM; 2383 rc = -ENOMEM;
2413 goto out; 2384 goto out;
2414 } 2385 }
2415 newbuf->buffer = &q->qdio_bufs[bidx]; 2386 newbuf->buffer = q->qdio_bufs[bidx];
2416 skb_queue_head_init(&newbuf->skb_list); 2387 skb_queue_head_init(&newbuf->skb_list);
2417 lockdep_set_class(&newbuf->skb_list.lock, &qdio_out_skb_queue_key); 2388 lockdep_set_class(&newbuf->skb_list.lock, &qdio_out_skb_queue_key);
2418 newbuf->q = q; 2389 newbuf->q = q;
@@ -2431,6 +2402,28 @@ out:
2431 return rc; 2402 return rc;
2432} 2403}
2433 2404
2405static void qeth_free_qdio_out_buf(struct qeth_qdio_out_q *q)
2406{
2407 if (!q)
2408 return;
2409
2410 qdio_free_buffers(q->qdio_bufs, QDIO_MAX_BUFFERS_PER_Q);
2411 kfree(q);
2412}
2413
2414static struct qeth_qdio_out_q *qeth_alloc_qdio_out_buf(void)
2415{
2416 struct qeth_qdio_out_q *q = kzalloc(sizeof(*q), GFP_KERNEL);
2417
2418 if (!q)
2419 return NULL;
2420
2421 if (qdio_alloc_buffers(q->qdio_bufs, QDIO_MAX_BUFFERS_PER_Q)) {
2422 kfree(q);
2423 return NULL;
2424 }
2425 return q;
2426}
2434 2427
2435static int qeth_alloc_qdio_buffers(struct qeth_card *card) 2428static int qeth_alloc_qdio_buffers(struct qeth_card *card)
2436{ 2429{
@@ -2458,8 +2451,7 @@ static int qeth_alloc_qdio_buffers(struct qeth_card *card)
2458 if (!card->qdio.out_qs) 2451 if (!card->qdio.out_qs)
2459 goto out_freepool; 2452 goto out_freepool;
2460 for (i = 0; i < card->qdio.no_out_queues; ++i) { 2453 for (i = 0; i < card->qdio.no_out_queues; ++i) {
2461 card->qdio.out_qs[i] = kzalloc(sizeof(struct qeth_qdio_out_q), 2454 card->qdio.out_qs[i] = qeth_alloc_qdio_out_buf();
2462 GFP_KERNEL);
2463 if (!card->qdio.out_qs[i]) 2455 if (!card->qdio.out_qs[i])
2464 goto out_freeoutq; 2456 goto out_freeoutq;
2465 QETH_DBF_TEXT_(SETUP, 2, "outq %i", i); 2457 QETH_DBF_TEXT_(SETUP, 2, "outq %i", i);
@@ -2488,7 +2480,7 @@ out_freeoutqbufs:
2488 } 2480 }
2489out_freeoutq: 2481out_freeoutq:
2490 while (i > 0) { 2482 while (i > 0) {
2491 kfree(card->qdio.out_qs[--i]); 2483 qeth_free_qdio_out_buf(card->qdio.out_qs[--i]);
2492 qeth_clear_outq_buffers(card->qdio.out_qs[i], 1); 2484 qeth_clear_outq_buffers(card->qdio.out_qs[i], 1);
2493 } 2485 }
2494 kfree(card->qdio.out_qs); 2486 kfree(card->qdio.out_qs);
@@ -2503,6 +2495,35 @@ out_nomem:
2503 return -ENOMEM; 2495 return -ENOMEM;
2504} 2496}
2505 2497
2498static void qeth_free_qdio_buffers(struct qeth_card *card)
2499{
2500 int i, j;
2501
2502 if (atomic_xchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED) ==
2503 QETH_QDIO_UNINITIALIZED)
2504 return;
2505
2506 qeth_free_cq(card);
2507 cancel_delayed_work_sync(&card->buffer_reclaim_work);
2508 for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
2509 if (card->qdio.in_q->bufs[j].rx_skb)
2510 dev_kfree_skb_any(card->qdio.in_q->bufs[j].rx_skb);
2511 }
2512 qeth_free_qdio_queue(card->qdio.in_q);
2513 card->qdio.in_q = NULL;
2514 /* inbound buffer pool */
2515 qeth_free_buffer_pool(card);
2516 /* free outbound qdio_qs */
2517 if (card->qdio.out_qs) {
2518 for (i = 0; i < card->qdio.no_out_queues; ++i) {
2519 qeth_clear_outq_buffers(card->qdio.out_qs[i], 1);
2520 qeth_free_qdio_out_buf(card->qdio.out_qs[i]);
2521 }
2522 kfree(card->qdio.out_qs);
2523 card->qdio.out_qs = NULL;
2524 }
2525}
2526
2506static void qeth_create_qib_param_field(struct qeth_card *card, 2527static void qeth_create_qib_param_field(struct qeth_card *card,
2507 char *param_field) 2528 char *param_field)
2508{ 2529{
@@ -2823,8 +2844,8 @@ int qeth_init_qdio_queues(struct qeth_card *card)
2823 2844
2824 /* outbound queue */ 2845 /* outbound queue */
2825 for (i = 0; i < card->qdio.no_out_queues; ++i) { 2846 for (i = 0; i < card->qdio.no_out_queues; ++i) {
2826 memset(card->qdio.out_qs[i]->qdio_bufs, 0, 2847 qdio_reset_buffers(card->qdio.out_qs[i]->qdio_bufs,
2827 QDIO_MAX_BUFFERS_PER_Q * sizeof(struct qdio_buffer)); 2848 QDIO_MAX_BUFFERS_PER_Q);
2828 for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) { 2849 for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
2829 qeth_clear_output_buffer(card->qdio.out_qs[i], 2850 qeth_clear_output_buffer(card->qdio.out_qs[i],
2830 card->qdio.out_qs[i]->bufs[j], 2851 card->qdio.out_qs[i]->bufs[j],