From: Julian Wiedmann <jwi@linux.ibm.com>
Subject: s390/qeth: fine-tune spinlocks
Patch-mainline: v4.20-rc1
Git-commit: ed47155bdcf38ff5a0f419b7a833dcbe49cb8abc
References: FATE#326377, LTC#169210, bsc#1115382
Summary: qeth: Full-blown TCP Segmentation Offload
Description: As of now, qeth only supports TCP Segmentation Offload (TSO)
for IPv4 in Layer3 devices. This feature extends the existing
support to IPv6, and adds support for TSO in both IP variants
for Layer2.
To cleanly pull in all the necessary changes to the transmit
code, update the qeth driver to the current 4.20 level.
Upstream-Description:
s390/qeth: fine-tune spinlocks
For quite a lot of code paths it's obvious that they will never run in
IRQ context. So replace their spin_lock_irqsave() calls with
spin_lock_irq().
While at it, get rid of the redundant card pointer in struct qeth_reply
that was used by qeth_send_control_data() to access the card's lock.
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 | 1
drivers/s390/net/qeth_core_main.c | 54 ++++++++++++++++----------------------
drivers/s390/net/qeth_l2_main.c | 5 +--
3 files changed, 25 insertions(+), 35 deletions(-)
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -638,7 +638,6 @@ struct qeth_reply {
atomic_t received;
int rc;
void *param;
- struct qeth_card *card;
refcount_t refcnt;
};
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -590,7 +590,6 @@ static struct qeth_reply *qeth_alloc_rep
if (reply) {
refcount_set(&reply->refcnt, 1);
atomic_set(&reply->received, 0);
- reply->card = card;
}
return reply;
}
@@ -1539,15 +1538,14 @@ out:
static int qeth_clear_channel(struct qeth_channel *channel)
{
- unsigned long flags;
struct qeth_card *card;
int rc;
card = CARD_FROM_CDEV(channel->ccwdev);
QETH_CARD_TEXT(card, 3, "clearch");
- spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
+ spin_lock_irq(get_ccwdev_lock(channel->ccwdev));
rc = ccw_device_clear(channel->ccwdev, QETH_CLEAR_CHANNEL_PARM);
- spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
+ spin_unlock_irq(get_ccwdev_lock(channel->ccwdev));
if (rc)
return rc;
@@ -1563,15 +1561,14 @@ static int qeth_clear_channel(struct qet
static int qeth_halt_channel(struct qeth_channel *channel)
{
- unsigned long flags;
struct qeth_card *card;
int rc;
card = CARD_FROM_CDEV(channel->ccwdev);
QETH_CARD_TEXT(card, 3, "haltch");
- spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
+ spin_lock_irq(get_ccwdev_lock(channel->ccwdev));
rc = ccw_device_halt(channel->ccwdev, QETH_HALT_CHANNEL_PARM);
- spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
+ spin_unlock_irq(get_ccwdev_lock(channel->ccwdev));
if (rc)
return rc;
@@ -1665,7 +1662,6 @@ static int qeth_read_conf_data(struct qe
char *rcd_buf;
int ret;
struct qeth_channel *channel = &card->data;
- unsigned long flags;
/*
* scan for RCD command in extended SenseID data
@@ -1679,11 +1675,11 @@ static int qeth_read_conf_data(struct qe
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);
+ spin_lock_irq(get_ccwdev_lock(channel->ccwdev));
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);
+ spin_unlock_irq(get_ccwdev_lock(channel->ccwdev));
if (!ret)
wait_event(card->wait_q,
(channel->state == CH_STATE_RCD_DONE ||
@@ -1841,7 +1837,6 @@ static int qeth_idx_activate_get_answer(
struct qeth_cmd_buffer *))
{
struct qeth_cmd_buffer *iob;
- unsigned long flags;
int rc;
struct qeth_card *card;
@@ -1856,10 +1851,10 @@ static int qeth_idx_activate_get_answer(
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);
+ spin_lock_irq(get_ccwdev_lock(channel->ccwdev));
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);
+ spin_unlock_irq(get_ccwdev_lock(channel->ccwdev));
if (rc) {
QETH_DBF_MESSAGE(2, "Error2 in activating channel rc=%d\n", rc);
@@ -1886,7 +1881,6 @@ static int qeth_idx_activate_channel(str
{
struct qeth_card *card;
struct qeth_cmd_buffer *iob;
- unsigned long flags;
__u16 temp;
__u8 tmp;
int rc;
@@ -1926,10 +1920,10 @@ static int qeth_idx_activate_channel(str
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);
+ spin_lock_irq(get_ccwdev_lock(channel->ccwdev));
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);
+ spin_unlock_irq(get_ccwdev_lock(channel->ccwdev));
if (rc) {
QETH_DBF_MESSAGE(2, "Error1 in activating channel. rc=%d\n",
@@ -2110,7 +2104,6 @@ int qeth_send_control_data(struct qeth_c
{
struct qeth_channel *channel = iob->channel;
int rc;
- unsigned long flags;
struct qeth_reply *reply = NULL;
unsigned long timeout, event_timeout;
struct qeth_ipa_cmd *cmd = NULL;
@@ -2143,25 +2136,26 @@ int qeth_send_control_data(struct qeth_c
}
qeth_prepare_control_data(card, len, iob);
- spin_lock_irqsave(&card->lock, flags);
+ spin_lock_irq(&card->lock);
list_add_tail(&reply->list, &card->cmd_waiter_list);
- spin_unlock_irqrestore(&card->lock, flags);
+ spin_unlock_irq(&card->lock);
+
timeout = jiffies + event_timeout;
QETH_CARD_TEXT(card, 6, "noirqpnd");
- spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
+ spin_lock_irq(get_ccwdev_lock(channel->ccwdev));
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);
+ spin_unlock_irq(get_ccwdev_lock(channel->ccwdev));
if (rc) {
QETH_DBF_MESSAGE(2, "%s qeth_send_control_data: "
"ccw_device_start rc = %i\n",
dev_name(&channel->ccwdev->dev), rc);
QETH_CARD_TEXT_(card, 2, " err%d", rc);
- spin_lock_irqsave(&card->lock, flags);
+ spin_lock_irq(&card->lock);
list_del_init(&reply->list);
qeth_put_reply(reply);
- spin_unlock_irqrestore(&card->lock, flags);
+ spin_unlock_irq(&card->lock);
qeth_release_buffer(channel, iob);
atomic_set(&channel->irq_pending, 0);
wake_up(&card->wait_q);
@@ -2189,9 +2183,9 @@ int qeth_send_control_data(struct qeth_c
time_err:
reply->rc = -ETIME;
- spin_lock_irqsave(&reply->card->lock, flags);
+ spin_lock_irq(&card->lock);
list_del_init(&reply->list);
- spin_unlock_irqrestore(&reply->card->lock, flags);
+ spin_unlock_irq(&card->lock);
atomic_inc(&reply->received);
rc = reply->rc;
qeth_put_reply(reply);
@@ -5771,7 +5765,6 @@ static int qeth_core_probe_device(struct
struct device *dev;
int rc;
enum qeth_discipline_id enforced_disc;
- unsigned long flags;
char dbf_name[DBF_NAME_LEN];
QETH_DBF_TEXT(SETUP, 2, "probedev");
@@ -5829,9 +5822,9 @@ static int qeth_core_probe_device(struct
break;
}
- write_lock_irqsave(&qeth_core_card_list.rwlock, flags);
+ write_lock_irq(&qeth_core_card_list.rwlock);
list_add_tail(&card->list, &qeth_core_card_list.list);
- write_unlock_irqrestore(&qeth_core_card_list.rwlock, flags);
+ write_unlock_irq(&qeth_core_card_list.rwlock);
return 0;
err_disc:
@@ -5847,7 +5840,6 @@ err_dev:
static void qeth_core_remove_device(struct ccwgroup_device *gdev)
{
- unsigned long flags;
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
QETH_DBF_TEXT(SETUP, 2, "removedv");
@@ -5857,9 +5849,9 @@ static void qeth_core_remove_device(stru
qeth_core_free_discipline(card);
}
- write_lock_irqsave(&qeth_core_card_list.rwlock, flags);
+ write_lock_irq(&qeth_core_card_list.rwlock);
list_del(&card->list);
- write_unlock_irqrestore(&qeth_core_card_list.rwlock, flags);
+ write_unlock_irq(&qeth_core_card_list.rwlock);
free_netdev(card->dev);
qeth_core_free_card(card);
dev_set_drvdata(&gdev->dev, NULL);
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -1209,7 +1209,6 @@ static int qeth_osn_send_control_data(st
struct qeth_cmd_buffer *iob)
{
struct qeth_channel *channel = iob->channel;
- unsigned long flags;
int rc = 0;
QETH_CARD_TEXT(card, 5, "osndctrd");
@@ -1218,10 +1217,10 @@ static int qeth_osn_send_control_data(st
atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
qeth_prepare_control_data(card, len, iob);
QETH_CARD_TEXT(card, 6, "osnoirqp");
- spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
+ spin_lock_irq(get_ccwdev_lock(channel->ccwdev));
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);
+ spin_unlock_irq(get_ccwdev_lock(channel->ccwdev));
if (rc) {
QETH_DBF_MESSAGE(2, "qeth_osn_send_control_data: "
"ccw_device_start rc = %i\n", rc);