From: Julian Wiedmann <jwi@linux.ibm.com>
Subject: s390/qeth: don't restrict qeth_card to DMA memory
Patch-mainline: v4.19-rc1
Git-commit: f15cdaf237e9acc2ee14663ba53b872a27ee7015
References: FATE#326350, LTC#169511, bsc#1113509

Summary:     qeth: performance improvements
Description: This adds recent functional and performance improvements for the
             qeth network driver.
             Primarily this brings Scatter-Gather support for HiperSockets,
             reduced CPU consumption in the L3 IPv4 transmit path for OSA,
             improved Promiscuous Mode performance due to IFF_UNICAST_FLT,
             support for Scatter-Gather on z/VM virtual NICs, and
             support for delayed GRO flushing.

             For sanity & stability reasons, this effectively constitutes a
             backport of the qeth device driver from 4.19 mainline.
             

Upstream-Description:

             s390/qeth: don't restrict qeth_card to DMA memory

             Allocating the main qeth_card struct with GFP_DMA blocks us from moving
             it into netdev_priv(). But the only reason why we need DMA memory is the
             ccw1 structs embedded into each ccw channel. So extract those into
             separate allocations, like we already do for the cmd buffers.

             Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com>
             Signed-off-by: David S. Miller <davem@davemloft.net>

Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com>
Acked-by: Petr Tesarik <ptesarik@suse.com>
---
 drivers/s390/net/qeth_core.h      |    2 +-
 drivers/s390/net/qeth_core_main.c |   29 +++++++++++++++++------------
 drivers/s390/net/qeth_l2_main.c   |    2 +-
 3 files changed, 19 insertions(+), 14 deletions(-)

--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -592,7 +592,7 @@ static inline struct qeth_ipa_cmd *__ipa
  */
 struct qeth_channel {
 	enum qeth_channel_states state;
-	struct ccw1 ccw;
+	struct ccw1 *ccw;
 	spinlock_t iob_lock;
 	wait_queue_head_t wait_q;
 	struct ccw_device *ccwdev;
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -555,9 +555,9 @@ static int __qeth_issue_next_read(struct
 			"available\n", dev_name(&card->gdev->dev));
 		return -ENOMEM;
 	}
-	qeth_setup_ccw(&channel->ccw, CCW_CMD_READ, QETH_BUFSIZE, iob->data);
+	qeth_setup_ccw(channel->ccw, CCW_CMD_READ, QETH_BUFSIZE, iob->data);
 	QETH_CARD_TEXT(card, 6, "noirqpnd");
-	rc = ccw_device_start(channel->ccwdev, &channel->ccw,
+	rc = ccw_device_start(channel->ccwdev, channel->ccw,
 			      (addr_t) iob, 0, 0);
 	if (rc) {
 		QETH_DBF_MESSAGE(2, "%s error in starting next read ccw! "
@@ -906,6 +906,9 @@ static int qeth_setup_channel(struct qet
 
 	QETH_DBF_TEXT(SETUP, 2, "setupch");
 
+	channel->ccw = kmalloc(sizeof(struct ccw1), GFP_KERNEL | GFP_DMA);
+	if (!channel->ccw)
+		return -ENOMEM;
 	channel->state = CH_STATE_DOWN;
 	atomic_set(&channel->irq_pending, 0);
 	init_waitqueue_head(&channel->wait_q);
@@ -924,6 +927,7 @@ static int qeth_setup_channel(struct qet
 		channel->iob[cnt].rc = 0;
 	}
 	if (cnt < QETH_CMD_BUFFER_NO) {
+		kfree(channel->ccw);
 		while (cnt-- > 0)
 			kfree(channel->iob[cnt].data);
 		return -ENOMEM;
@@ -1337,6 +1341,7 @@ static void qeth_clean_channel(struct qe
 	QETH_DBF_TEXT(SETUP, 2, "freech");
 	for (cnt = 0; cnt < QETH_CMD_BUFFER_NO; cnt++)
 		kfree(channel->iob[cnt].data);
+	kfree(channel->ccw);
 }
 
 static void qeth_set_single_write_queues(struct qeth_card *card)
@@ -1494,7 +1499,7 @@ static struct qeth_card *qeth_alloc_card
 	struct qeth_card *card;
 
 	QETH_DBF_TEXT(SETUP, 2, "alloccrd");
-	card = kzalloc(sizeof(struct qeth_card), GFP_DMA|GFP_KERNEL);
+	card = kzalloc(sizeof(*card), GFP_KERNEL);
 	if (!card)
 		goto out;
 	QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
@@ -1659,10 +1664,10 @@ static int qeth_read_conf_data(struct qe
 	if (!rcd_buf)
 		return -ENOMEM;
 
-	qeth_setup_ccw(&channel->ccw, ciw->cmd, ciw->count, rcd_buf);
+	qeth_setup_ccw(channel->ccw, ciw->cmd, ciw->count, rcd_buf);
 	channel->state = CH_STATE_RCD;
 	spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
-	ret = ccw_device_start_timeout(channel->ccwdev, &channel->ccw,
+	ret = ccw_device_start_timeout(channel->ccwdev, channel->ccw,
 				       QETH_RCD_PARM, LPM_ANYPATH, 0,
 				       QETH_RCD_TIMEOUT);
 	spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
@@ -1833,13 +1838,13 @@ static int qeth_idx_activate_get_answer(
 	if (!iob)
 		return -ENOMEM;
 	iob->callback = idx_reply_cb;
-	qeth_setup_ccw(&channel->ccw, CCW_CMD_READ, QETH_BUFSIZE, iob->data);
+	qeth_setup_ccw(channel->ccw, CCW_CMD_READ, QETH_BUFSIZE, iob->data);
 
 	wait_event(card->wait_q,
 		   atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
 	QETH_DBF_TEXT(SETUP, 6, "noirqpnd");
 	spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
-	rc = ccw_device_start_timeout(channel->ccwdev, &channel->ccw,
+	rc = ccw_device_start_timeout(channel->ccwdev, channel->ccw,
 				      (addr_t) iob, 0, 0, QETH_TIMEOUT);
 	spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
 
@@ -1882,7 +1887,7 @@ static int qeth_idx_activate_channel(str
 	if (!iob)
 		return -ENOMEM;
 	iob->callback = idx_reply_cb;
-	qeth_setup_ccw(&channel->ccw, CCW_CMD_WRITE, IDX_ACTIVATE_SIZE,
+	qeth_setup_ccw(channel->ccw, CCW_CMD_WRITE, IDX_ACTIVATE_SIZE,
 		       iob->data);
 	if (channel == &card->write) {
 		memcpy(iob->data, IDX_ACTIVATE_WRITE, IDX_ACTIVATE_SIZE);
@@ -1909,7 +1914,7 @@ static int qeth_idx_activate_channel(str
 		   atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
 	QETH_DBF_TEXT(SETUP, 6, "noirqpnd");
 	spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
-	rc = ccw_device_start_timeout(channel->ccwdev, &channel->ccw,
+	rc = ccw_device_start_timeout(channel->ccwdev, channel->ccw,
 				      (addr_t) iob, 0, 0, QETH_TIMEOUT);
 	spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
 
@@ -2043,7 +2048,7 @@ out:
 void qeth_prepare_control_data(struct qeth_card *card, int len,
 		struct qeth_cmd_buffer *iob)
 {
-	qeth_setup_ccw(&iob->channel->ccw, CCW_CMD_WRITE, len, iob->data);
+	qeth_setup_ccw(iob->channel->ccw, CCW_CMD_WRITE, len, iob->data);
 	iob->callback = qeth_release_buffer;
 
 	memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data),
@@ -2132,7 +2137,7 @@ int qeth_send_control_data(struct qeth_c
 
 	QETH_CARD_TEXT(card, 6, "noirqpnd");
 	spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
-	rc = ccw_device_start_timeout(channel->ccwdev, &channel->ccw,
+	rc = ccw_device_start_timeout(channel->ccwdev, channel->ccw,
 				      (addr_t) iob, 0, 0, event_timeout);
 	spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
 	if (rc) {
@@ -5029,11 +5034,11 @@ out_free_nothing:
 
 static void qeth_core_free_card(struct qeth_card *card)
 {
-
 	QETH_DBF_TEXT(SETUP, 2, "freecrd");
 	QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
 	qeth_clean_channel(&card->read);
 	qeth_clean_channel(&card->write);
+	qeth_clean_channel(&card->data);
 	qeth_free_qdio_buffers(card);
 	unregister_service_level(&card->qeth_service_level);
 	kfree(card);
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -1250,7 +1250,7 @@ static int qeth_osn_send_control_data(st
 	qeth_prepare_control_data(card, len, iob);
 	QETH_CARD_TEXT(card, 6, "osnoirqp");
 	spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
-	rc = ccw_device_start_timeout(channel->ccwdev, &channel->ccw,
+	rc = ccw_device_start_timeout(channel->ccwdev, channel->ccw,
 				      (addr_t) iob, 0, 0, QETH_IPA_TIMEOUT);
 	spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
 	if (rc) {
