|
@@ -1302,35 +1302,6 @@ static void qeth_free_buffer_pool(struct qeth_card *card)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-static void qeth_free_qdio_buffers(struct qeth_card *card)
|
|
|
|
-{
|
|
|
|
- int i, j;
|
|
|
|
-
|
|
|
|
- if (atomic_xchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED) ==
|
|
|
|
- QETH_QDIO_UNINITIALIZED)
|
|
|
|
- return;
|
|
|
|
-
|
|
|
|
- qeth_free_cq(card);
|
|
|
|
- cancel_delayed_work_sync(&card->buffer_reclaim_work);
|
|
|
|
- for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
|
|
|
|
- if (card->qdio.in_q->bufs[j].rx_skb)
|
|
|
|
- dev_kfree_skb_any(card->qdio.in_q->bufs[j].rx_skb);
|
|
|
|
- }
|
|
|
|
- qeth_free_qdio_queue(card->qdio.in_q);
|
|
|
|
- card->qdio.in_q = NULL;
|
|
|
|
- /* inbound buffer pool */
|
|
|
|
- qeth_free_buffer_pool(card);
|
|
|
|
- /* free outbound qdio_qs */
|
|
|
|
- if (card->qdio.out_qs) {
|
|
|
|
- for (i = 0; i < card->qdio.no_out_queues; ++i) {
|
|
|
|
- qeth_clear_outq_buffers(card->qdio.out_qs[i], 1);
|
|
|
|
- kfree(card->qdio.out_qs[i]);
|
|
|
|
- }
|
|
|
|
- kfree(card->qdio.out_qs);
|
|
|
|
- card->qdio.out_qs = NULL;
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static void qeth_clean_channel(struct qeth_channel *channel)
|
|
static void qeth_clean_channel(struct qeth_channel *channel)
|
|
{
|
|
{
|
|
int cnt;
|
|
int cnt;
|
|
@@ -2412,7 +2383,7 @@ static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *q, int bidx)
|
|
rc = -ENOMEM;
|
|
rc = -ENOMEM;
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
- newbuf->buffer = &q->qdio_bufs[bidx];
|
|
|
|
|
|
+ newbuf->buffer = q->qdio_bufs[bidx];
|
|
skb_queue_head_init(&newbuf->skb_list);
|
|
skb_queue_head_init(&newbuf->skb_list);
|
|
lockdep_set_class(&newbuf->skb_list.lock, &qdio_out_skb_queue_key);
|
|
lockdep_set_class(&newbuf->skb_list.lock, &qdio_out_skb_queue_key);
|
|
newbuf->q = q;
|
|
newbuf->q = q;
|
|
@@ -2431,6 +2402,28 @@ out:
|
|
return rc;
|
|
return rc;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void qeth_free_qdio_out_buf(struct qeth_qdio_out_q *q)
|
|
|
|
+{
|
|
|
|
+ if (!q)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ qdio_free_buffers(q->qdio_bufs, QDIO_MAX_BUFFERS_PER_Q);
|
|
|
|
+ kfree(q);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static struct qeth_qdio_out_q *qeth_alloc_qdio_out_buf(void)
|
|
|
|
+{
|
|
|
|
+ struct qeth_qdio_out_q *q = kzalloc(sizeof(*q), GFP_KERNEL);
|
|
|
|
+
|
|
|
|
+ if (!q)
|
|
|
|
+ return NULL;
|
|
|
|
+
|
|
|
|
+ if (qdio_alloc_buffers(q->qdio_bufs, QDIO_MAX_BUFFERS_PER_Q)) {
|
|
|
|
+ kfree(q);
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
|
|
+ return q;
|
|
|
|
+}
|
|
|
|
|
|
static int qeth_alloc_qdio_buffers(struct qeth_card *card)
|
|
static int qeth_alloc_qdio_buffers(struct qeth_card *card)
|
|
{
|
|
{
|
|
@@ -2458,8 +2451,7 @@ static int qeth_alloc_qdio_buffers(struct qeth_card *card)
|
|
if (!card->qdio.out_qs)
|
|
if (!card->qdio.out_qs)
|
|
goto out_freepool;
|
|
goto out_freepool;
|
|
for (i = 0; i < card->qdio.no_out_queues; ++i) {
|
|
for (i = 0; i < card->qdio.no_out_queues; ++i) {
|
|
- card->qdio.out_qs[i] = kzalloc(sizeof(struct qeth_qdio_out_q),
|
|
|
|
- GFP_KERNEL);
|
|
|
|
|
|
+ card->qdio.out_qs[i] = qeth_alloc_qdio_out_buf();
|
|
if (!card->qdio.out_qs[i])
|
|
if (!card->qdio.out_qs[i])
|
|
goto out_freeoutq;
|
|
goto out_freeoutq;
|
|
QETH_DBF_TEXT_(SETUP, 2, "outq %i", i);
|
|
QETH_DBF_TEXT_(SETUP, 2, "outq %i", i);
|
|
@@ -2488,7 +2480,7 @@ out_freeoutqbufs:
|
|
}
|
|
}
|
|
out_freeoutq:
|
|
out_freeoutq:
|
|
while (i > 0) {
|
|
while (i > 0) {
|
|
- kfree(card->qdio.out_qs[--i]);
|
|
|
|
|
|
+ qeth_free_qdio_out_buf(card->qdio.out_qs[--i]);
|
|
qeth_clear_outq_buffers(card->qdio.out_qs[i], 1);
|
|
qeth_clear_outq_buffers(card->qdio.out_qs[i], 1);
|
|
}
|
|
}
|
|
kfree(card->qdio.out_qs);
|
|
kfree(card->qdio.out_qs);
|
|
@@ -2503,6 +2495,35 @@ out_nomem:
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void qeth_free_qdio_buffers(struct qeth_card *card)
|
|
|
|
+{
|
|
|
|
+ int i, j;
|
|
|
|
+
|
|
|
|
+ if (atomic_xchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED) ==
|
|
|
|
+ QETH_QDIO_UNINITIALIZED)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ qeth_free_cq(card);
|
|
|
|
+ cancel_delayed_work_sync(&card->buffer_reclaim_work);
|
|
|
|
+ for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
|
|
|
|
+ if (card->qdio.in_q->bufs[j].rx_skb)
|
|
|
|
+ dev_kfree_skb_any(card->qdio.in_q->bufs[j].rx_skb);
|
|
|
|
+ }
|
|
|
|
+ qeth_free_qdio_queue(card->qdio.in_q);
|
|
|
|
+ card->qdio.in_q = NULL;
|
|
|
|
+ /* inbound buffer pool */
|
|
|
|
+ qeth_free_buffer_pool(card);
|
|
|
|
+ /* free outbound qdio_qs */
|
|
|
|
+ if (card->qdio.out_qs) {
|
|
|
|
+ for (i = 0; i < card->qdio.no_out_queues; ++i) {
|
|
|
|
+ qeth_clear_outq_buffers(card->qdio.out_qs[i], 1);
|
|
|
|
+ qeth_free_qdio_out_buf(card->qdio.out_qs[i]);
|
|
|
|
+ }
|
|
|
|
+ kfree(card->qdio.out_qs);
|
|
|
|
+ card->qdio.out_qs = NULL;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
static void qeth_create_qib_param_field(struct qeth_card *card,
|
|
static void qeth_create_qib_param_field(struct qeth_card *card,
|
|
char *param_field)
|
|
char *param_field)
|
|
{
|
|
{
|
|
@@ -2823,8 +2844,8 @@ int qeth_init_qdio_queues(struct qeth_card *card)
|
|
|
|
|
|
/* outbound queue */
|
|
/* outbound queue */
|
|
for (i = 0; i < card->qdio.no_out_queues; ++i) {
|
|
for (i = 0; i < card->qdio.no_out_queues; ++i) {
|
|
- memset(card->qdio.out_qs[i]->qdio_bufs, 0,
|
|
|
|
- QDIO_MAX_BUFFERS_PER_Q * sizeof(struct qdio_buffer));
|
|
|
|
|
|
+ qdio_reset_buffers(card->qdio.out_qs[i]->qdio_bufs,
|
|
|
|
+ QDIO_MAX_BUFFERS_PER_Q);
|
|
for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
|
|
for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
|
|
qeth_clear_output_buffer(card->qdio.out_qs[i],
|
|
qeth_clear_output_buffer(card->qdio.out_qs[i],
|
|
card->qdio.out_qs[i]->bufs[j],
|
|
card->qdio.out_qs[i]->bufs[j],
|