* [patch 00/10] s390: network driver features and fixes for net-next
@ 2011-12-20 8:56 frank.blaschka
2011-12-20 8:56 ` [patch 01/10] [PATCH] af_iucv: support ancillary data with HS transport frank.blaschka
` (10 more replies)
0 siblings, 11 replies; 12+ messages in thread
From: frank.blaschka @ 2011-12-20 8:56 UTC (permalink / raw)
To: davem; +Cc: netdev, linux-s390
Hi Dave,
here are some s390 network driver features and fixes for net-next
shortlog:
Ursula Braun (8)
af_iucv: support ancillary data with HS transport
af_iucv: accelerate close for HS transport
af_iucv: release reference to HS device
af_iucv: remove unused timer infrastructure
af_iucv: get rid of state IUCV_SEVERED
qeth: suspicious rcu_dereference_check in recovery
qeth: forbid recovery during shutdown
netiucv: allow multiple interfaces to same peer
Frank Blaschka (1)
qeth: improve recovery during resource shortage
Einar Lueck (1)
qeth: recovery through asynchronous delivery
Thanks,
Frank
^ permalink raw reply [flat|nested] 12+ messages in thread
* [patch 01/10] [PATCH] af_iucv: support ancillary data with HS transport
2011-12-20 8:56 [patch 00/10] s390: network driver features and fixes for net-next frank.blaschka
@ 2011-12-20 8:56 ` frank.blaschka
2011-12-20 8:56 ` [patch 02/10] [PATCH] af_iucv: accelerate close for " frank.blaschka
` (9 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: frank.blaschka @ 2011-12-20 8:56 UTC (permalink / raw)
To: davem; +Cc: netdev, linux-s390, Ursula Braun
[-- Attachment #1: 600-af_iucv-ancillary-hs.diff --]
[-- Type: text/plain, Size: 670 bytes --]
From: Ursula Braun <ursula.braun@de.ibm.com>
The AF_IUCV address family offers support for ancillary data.
This patch enables usage of ancillary data with the new
HiperSockets transport.
Signed-off-by: Ursula Braun <ursula.braun@de.ibm.com>
Signed-off-by: Frank Blaschka <frank.blaschka@de.ibm.com>
---
net/iucv/af_iucv.c | 2 ++
1 file changed, 2 insertions(+)
--- a/net/iucv/af_iucv.c
+++ b/net/iucv/af_iucv.c
@@ -2209,6 +2209,8 @@ static int afiucv_hs_rcv(struct sk_buff
break;
case 0:
/* plain data frame */
+ memcpy(CB_TRGCLS(skb), &trans_hdr->iucv_hdr.class,
+ CB_TRGCLS_LEN);
err = afiucv_hs_callback_rx(sk, skb);
break;
default:
^ permalink raw reply [flat|nested] 12+ messages in thread
* [patch 02/10] [PATCH] af_iucv: accelerate close for HS transport
2011-12-20 8:56 [patch 00/10] s390: network driver features and fixes for net-next frank.blaschka
2011-12-20 8:56 ` [patch 01/10] [PATCH] af_iucv: support ancillary data with HS transport frank.blaschka
@ 2011-12-20 8:56 ` frank.blaschka
2011-12-20 8:56 ` [patch 03/10] [PATCH] af_iucv: release reference to HS device frank.blaschka
` (8 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: frank.blaschka @ 2011-12-20 8:56 UTC (permalink / raw)
To: davem; +Cc: netdev, linux-s390, Ursula Braun
[-- Attachment #1: 601-af_iucv-fast-close-hs.diff --]
[-- Type: text/plain, Size: 751 bytes --]
From: Ursula Braun <ursula.braun@de.ibm.com>
Closing an af_iucv socket may wait for confirmation of outstanding
send requests. This patch adds confirmation code for the new
HiperSockets transport.
Signed-off-by: Ursula Braun <ursula.braun@de.ibm.com>
Signed-off-by: Frank Blaschka <frank.blaschka@de.ibm.com>
---
net/iucv/af_iucv.c | 7 +++++++
1 file changed, 7 insertions(+)
--- a/net/iucv/af_iucv.c
+++ b/net/iucv/af_iucv.c
@@ -2293,6 +2293,13 @@ static void afiucv_hs_callback_txnotify(
}
spin_unlock_irqrestore(&list->lock, flags);
+ if (sk->sk_state == IUCV_CLOSING) {
+ if (skb_queue_empty(&iucv_sk(sk)->send_skb_q)) {
+ sk->sk_state = IUCV_CLOSED;
+ sk->sk_state_change(sk);
+ }
+ }
+
out_unlock:
bh_unlock_sock(sk);
}
^ permalink raw reply [flat|nested] 12+ messages in thread
* [patch 03/10] [PATCH] af_iucv: release reference to HS device
2011-12-20 8:56 [patch 00/10] s390: network driver features and fixes for net-next frank.blaschka
2011-12-20 8:56 ` [patch 01/10] [PATCH] af_iucv: support ancillary data with HS transport frank.blaschka
2011-12-20 8:56 ` [patch 02/10] [PATCH] af_iucv: accelerate close for " frank.blaschka
@ 2011-12-20 8:56 ` frank.blaschka
2011-12-20 8:56 ` [patch 04/10] [PATCH] af_iucv: remove unused timer infrastructure frank.blaschka
` (7 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: frank.blaschka @ 2011-12-20 8:56 UTC (permalink / raw)
To: davem; +Cc: netdev, linux-s390, Ursula Braun
[-- Attachment #1: 602-af_iucv-release-skb-hs.diff --]
[-- Type: text/plain, Size: 4314 bytes --]
From: Ursula Braun <ursula.braun@de.ibm.com>
For HiperSockets transport skbs sent are bound to one of the
available HiperSockets devices. Add missing release of reference to
a HiperSockets device before freeing an skb.
Signed-off-by: Ursula Braun <ursula.braun@de.ibm.com>
Signed-off-by: Frank Blaschka <frank.blaschka@de.ibm.com>
---
net/iucv/af_iucv.c | 37 ++++++++++++++++++++++++-------------
1 file changed, 24 insertions(+), 13 deletions(-)
--- a/net/iucv/af_iucv.c
+++ b/net/iucv/af_iucv.c
@@ -130,6 +130,17 @@ static inline void low_nmcpy(unsigned ch
memcpy(&dst[8], src, 8);
}
+static void iucv_skb_queue_purge(struct sk_buff_head *list)
+{
+ struct sk_buff *skb;
+
+ while ((skb = skb_dequeue(list)) != NULL) {
+ if (skb->dev)
+ dev_put(skb->dev);
+ kfree_skb(skb);
+ }
+}
+
static int afiucv_pm_prepare(struct device *dev)
{
#ifdef CONFIG_PM_DEBUG
@@ -164,7 +175,7 @@ static int afiucv_pm_freeze(struct devic
read_lock(&iucv_sk_list.lock);
sk_for_each(sk, node, &iucv_sk_list.head) {
iucv = iucv_sk(sk);
- skb_queue_purge(&iucv->send_skb_q);
+ iucv_skb_queue_purge(&iucv->send_skb_q);
skb_queue_purge(&iucv->backlog_skb_q);
switch (sk->sk_state) {
case IUCV_SEVERED:
@@ -366,9 +377,7 @@ static int afiucv_hs_send(struct iucv_me
if (imsg)
memcpy(&phs_hdr->iucv_hdr, imsg, sizeof(struct iucv_message));
- rcu_read_lock();
- skb->dev = dev_get_by_index_rcu(net, sock->sk_bound_dev_if);
- rcu_read_unlock();
+ skb->dev = dev_get_by_index(net, sock->sk_bound_dev_if);
if (!skb->dev)
return -ENODEV;
if (!(skb->dev->flags & IFF_UP))
@@ -388,6 +397,7 @@ static int afiucv_hs_send(struct iucv_me
err = dev_queue_xmit(skb);
if (err) {
skb_unlink(nskb, &iucv->send_skb_q);
+ dev_put(nskb->dev);
kfree_skb(nskb);
} else {
atomic_sub(confirm_recv, &iucv->msg_recv);
@@ -481,16 +491,14 @@ static void iucv_sock_close(struct sock
blen = sizeof(struct af_iucv_trans_hdr) + ETH_HLEN;
skb = sock_alloc_send_skb(sk, blen, 1, &err);
if (skb) {
- skb_reserve(skb,
- sizeof(struct af_iucv_trans_hdr) +
- ETH_HLEN);
+ skb_reserve(skb, blen);
err = afiucv_hs_send(NULL, sk, skb,
AF_IUCV_FLAG_FIN);
}
sk->sk_state = IUCV_DISCONN;
sk->sk_state_change(sk);
}
- case IUCV_DISCONN:
+ case IUCV_DISCONN: /* fall through */
sk->sk_state = IUCV_CLOSING;
sk->sk_state_change(sk);
@@ -520,7 +528,7 @@ static void iucv_sock_close(struct sock
sk->sk_err = ECONNRESET;
sk->sk_state_change(sk);
- skb_queue_purge(&iucv->send_skb_q);
+ iucv_skb_queue_purge(&iucv->send_skb_q);
skb_queue_purge(&iucv->backlog_skb_q);
break;
@@ -739,7 +747,7 @@ static int iucv_sock_bind(struct socket
if (!memcmp(dev->perm_addr, uid, 8)) {
memcpy(iucv->src_name, sa->siucv_name, 8);
memcpy(iucv->src_user_id, sa->siucv_user_id, 8);
- sock->sk->sk_bound_dev_if = dev->ifindex;
+ sk->sk_bound_dev_if = dev->ifindex;
sk->sk_state = IUCV_BOUND;
iucv->transport = AF_IUCV_TRANS_HIPER;
if (!iucv->msglimit)
@@ -1225,6 +1233,8 @@ release:
return len;
fail:
+ if (skb->dev)
+ dev_put(skb->dev);
kfree_skb(skb);
out:
release_sock(sk);
@@ -1441,9 +1451,7 @@ static int iucv_sock_recvmsg(struct kioc
ETH_HLEN;
sskb = sock_alloc_send_skb(sk, blen, 1, &err);
if (sskb) {
- skb_reserve(sskb,
- sizeof(struct af_iucv_trans_hdr)
- + ETH_HLEN);
+ skb_reserve(sskb, blen);
err = afiucv_hs_send(NULL, sk, sskb,
AF_IUCV_FLAG_WIN);
}
@@ -2261,6 +2269,7 @@ static void afiucv_hs_callback_txnotify(
case TX_NOTIFY_OK:
__skb_unlink(this, list);
iucv_sock_wake_msglim(sk);
+ dev_put(this->dev);
kfree_skb(this);
break;
case TX_NOTIFY_PENDING:
@@ -2271,6 +2280,7 @@ static void afiucv_hs_callback_txnotify(
atomic_dec(&iucv->pendings);
if (atomic_read(&iucv->pendings) <= 0)
iucv_sock_wake_msglim(sk);
+ dev_put(this->dev);
kfree_skb(this);
break;
case TX_NOTIFY_UNREACHABLE:
@@ -2279,6 +2289,7 @@ static void afiucv_hs_callback_txnotify(
case TX_NOTIFY_GENERALERROR:
case TX_NOTIFY_DELAYED_GENERALERROR:
__skb_unlink(this, list);
+ dev_put(this->dev);
kfree_skb(this);
if (!list_empty(&iucv->accept_q))
sk->sk_state = IUCV_SEVERED;
^ permalink raw reply [flat|nested] 12+ messages in thread
* [patch 04/10] [PATCH] af_iucv: remove unused timer infrastructure
2011-12-20 8:56 [patch 00/10] s390: network driver features and fixes for net-next frank.blaschka
` (2 preceding siblings ...)
2011-12-20 8:56 ` [patch 03/10] [PATCH] af_iucv: release reference to HS device frank.blaschka
@ 2011-12-20 8:56 ` frank.blaschka
2011-12-20 8:56 ` [patch 05/10] [PATCH] af_iucv: get rid of state IUCV_SEVERED frank.blaschka
` (6 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: frank.blaschka @ 2011-12-20 8:56 UTC (permalink / raw)
To: davem; +Cc: netdev, linux-s390, Ursula Braun
[-- Attachment #1: 604-af_iucv-rm-timer.diff --]
[-- Type: text/plain, Size: 1910 bytes --]
From: Ursula Braun <ursula.braun@de.ibm.com>
af_iucv contains timer infrastructure which is not exploited.
This patch removes the timer related code parts.
Signed-off-by: Ursula Braun <ursula.braun@de.ibm.com>
Signed-off-by: Frank Blaschka <frank.blaschka@de.ibm.com>
---
include/net/iucv/af_iucv.h | 1 -
net/iucv/af_iucv.c | 22 ----------------------
2 files changed, 23 deletions(-)
--- a/include/net/iucv/af_iucv.h
+++ b/include/net/iucv/af_iucv.h
@@ -146,7 +146,6 @@ unsigned int iucv_sock_poll(struct file
poll_table *wait);
void iucv_sock_link(struct iucv_sock_list *l, struct sock *s);
void iucv_sock_unlink(struct iucv_sock_list *l, struct sock *s);
-int iucv_sock_wait_cnt(struct sock *sk, unsigned long timeo);
void iucv_accept_enqueue(struct sock *parent, struct sock *sk);
void iucv_accept_unlink(struct sock *sk);
struct sock *iucv_accept_dequeue(struct sock *parent, struct socket *newsock);
--- a/net/iucv/af_iucv.c
+++ b/net/iucv/af_iucv.c
@@ -406,25 +406,6 @@ static int afiucv_hs_send(struct iucv_me
return err;
}
-/* Timers */
-static void iucv_sock_timeout(unsigned long arg)
-{
- struct sock *sk = (struct sock *)arg;
-
- bh_lock_sock(sk);
- sk->sk_err = ETIMEDOUT;
- sk->sk_state_change(sk);
- bh_unlock_sock(sk);
-
- iucv_sock_kill(sk);
- sock_put(sk);
-}
-
-static void iucv_sock_clear_timer(struct sock *sk)
-{
- sk_stop_timer(sk, &sk->sk_timer);
-}
-
static struct sock *__iucv_get_sock_by_name(char *nm)
{
struct sock *sk;
@@ -477,7 +458,6 @@ static void iucv_sock_close(struct sock
int err, blen;
struct sk_buff *skb;
- iucv_sock_clear_timer(sk);
lock_sock(sk);
switch (sk->sk_state) {
@@ -589,8 +569,6 @@ static struct sock *iucv_sock_alloc(stru
sk->sk_protocol = proto;
sk->sk_state = IUCV_OPEN;
- setup_timer(&sk->sk_timer, iucv_sock_timeout, (unsigned long)sk);
-
iucv_sock_link(&iucv_sk_list, sk);
return sk;
}
^ permalink raw reply [flat|nested] 12+ messages in thread
* [patch 05/10] [PATCH] af_iucv: get rid of state IUCV_SEVERED
2011-12-20 8:56 [patch 00/10] s390: network driver features and fixes for net-next frank.blaschka
` (3 preceding siblings ...)
2011-12-20 8:56 ` [patch 04/10] [PATCH] af_iucv: remove unused timer infrastructure frank.blaschka
@ 2011-12-20 8:56 ` frank.blaschka
2011-12-20 8:56 ` [patch 06/10] [PATCH] qeth: suspicious rcu_dereference_check in recovery frank.blaschka
` (5 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: frank.blaschka @ 2011-12-20 8:56 UTC (permalink / raw)
To: davem; +Cc: netdev, linux-s390, Ursula Braun
[-- Attachment #1: 605-af_iucv-rm-iucv-severed.diff --]
[-- Type: text/plain, Size: 3954 bytes --]
From: Ursula Braun <ursula.braun@de.ibm.com>
af_iucv differs unnecessarily between state IUCV_SEVERED and
IUCV_DISCONN. This patch removes state IUCV_SEVERED.
While simplifying af_iucv, this patch removes the 2nd invocation of
cpcmd as well.
Signed-off-by: Ursula Braun <ursula.braun@de.ibm.com>
Signed-off-by: Frank Blaschka <frank.blaschka@de.ibm.com>
---
include/net/iucv/af_iucv.h | 1 -
net/iucv/af_iucv.c | 35 ++++++++---------------------------
2 files changed, 8 insertions(+), 28 deletions(-)
--- a/include/net/iucv/af_iucv.h
+++ b/include/net/iucv/af_iucv.h
@@ -27,7 +27,6 @@ enum {
IUCV_OPEN,
IUCV_BOUND,
IUCV_LISTEN,
- IUCV_SEVERED,
IUCV_DISCONN,
IUCV_CLOSING,
IUCV_CLOSED
--- a/net/iucv/af_iucv.c
+++ b/net/iucv/af_iucv.c
@@ -178,7 +178,6 @@ static int afiucv_pm_freeze(struct devic
iucv_skb_queue_purge(&iucv->send_skb_q);
skb_queue_purge(&iucv->backlog_skb_q);
switch (sk->sk_state) {
- case IUCV_SEVERED:
case IUCV_DISCONN:
case IUCV_CLOSING:
case IUCV_CONNECTED:
@@ -223,7 +222,6 @@ static int afiucv_pm_restore_thaw(struct
sk->sk_state_change(sk);
break;
case IUCV_DISCONN:
- case IUCV_SEVERED:
case IUCV_CLOSING:
case IUCV_LISTEN:
case IUCV_BOUND:
@@ -661,16 +659,12 @@ struct sock *iucv_accept_dequeue(struct
}
if (sk->sk_state == IUCV_CONNECTED ||
- sk->sk_state == IUCV_SEVERED ||
- sk->sk_state == IUCV_DISCONN || /* due to PM restore */
+ sk->sk_state == IUCV_DISCONN ||
!newsock) {
iucv_accept_unlink(sk);
if (newsock)
sock_graft(sk, newsock);
- if (sk->sk_state == IUCV_SEVERED)
- sk->sk_state = IUCV_DISCONN;
-
release_sock(sk);
return sk;
}
@@ -760,16 +754,13 @@ done:
static int iucv_sock_autobind(struct sock *sk)
{
struct iucv_sock *iucv = iucv_sk(sk);
- char query_buffer[80];
char name[12];
int err = 0;
- /* Set the userid and name */
- cpcmd("QUERY USERID", query_buffer, sizeof(query_buffer), &err);
- if (unlikely(err))
+ if (unlikely(!pr_iucv))
return -EPROTO;
- memcpy(iucv->src_user_id, query_buffer, 8);
+ memcpy(iucv->src_user_id, iucv_userid, 8);
write_lock_bh(&iucv_sk_list.lock);
@@ -1345,7 +1336,7 @@ static int iucv_sock_recvmsg(struct kioc
int blen;
int err = 0;
- if ((sk->sk_state == IUCV_DISCONN || sk->sk_state == IUCV_SEVERED) &&
+ if ((sk->sk_state == IUCV_DISCONN) &&
skb_queue_empty(&iucv->backlog_skb_q) &&
skb_queue_empty(&sk->sk_receive_queue) &&
list_empty(&iucv->message_q.list))
@@ -1492,7 +1483,7 @@ unsigned int iucv_sock_poll(struct file
if (sk->sk_state == IUCV_CLOSED)
mask |= POLLHUP;
- if (sk->sk_state == IUCV_DISCONN || sk->sk_state == IUCV_SEVERED)
+ if (sk->sk_state == IUCV_DISCONN)
mask |= POLLIN;
if (sock_writeable(sk))
@@ -1519,7 +1510,6 @@ static int iucv_sock_shutdown(struct soc
switch (sk->sk_state) {
case IUCV_DISCONN:
case IUCV_CLOSING:
- case IUCV_SEVERED:
case IUCV_CLOSED:
err = -ENOTCONN;
goto fail;
@@ -1874,10 +1864,7 @@ static void iucv_callback_connrej(struct
{
struct sock *sk = path->private;
- if (!list_empty(&iucv_sk(sk)->accept_q))
- sk->sk_state = IUCV_SEVERED;
- else
- sk->sk_state = IUCV_DISCONN;
+ sk->sk_state = IUCV_DISCONN;
sk->sk_state_change(sk);
}
@@ -2037,10 +2024,7 @@ static int afiucv_hs_callback_fin(struct
/* other end of connection closed */
if (iucv) {
bh_lock_sock(sk);
- if (!list_empty(&iucv->accept_q))
- sk->sk_state = IUCV_SEVERED;
- else
- sk->sk_state = IUCV_DISCONN;
+ sk->sk_state = IUCV_DISCONN;
sk->sk_state_change(sk);
bh_unlock_sock(sk);
}
@@ -2269,10 +2253,7 @@ static void afiucv_hs_callback_txnotify(
__skb_unlink(this, list);
dev_put(this->dev);
kfree_skb(this);
- if (!list_empty(&iucv->accept_q))
- sk->sk_state = IUCV_SEVERED;
- else
- sk->sk_state = IUCV_DISCONN;
+ sk->sk_state = IUCV_DISCONN;
sk->sk_state_change(sk);
break;
}
^ permalink raw reply [flat|nested] 12+ messages in thread
* [patch 06/10] [PATCH] qeth: suspicious rcu_dereference_check in recovery
2011-12-20 8:56 [patch 00/10] s390: network driver features and fixes for net-next frank.blaschka
` (4 preceding siblings ...)
2011-12-20 8:56 ` [patch 05/10] [PATCH] af_iucv: get rid of state IUCV_SEVERED frank.blaschka
@ 2011-12-20 8:56 ` frank.blaschka
2011-12-20 8:56 ` [patch 07/10] [PATCH] qeth: forbid recovery during shutdown frank.blaschka
` (4 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: frank.blaschka @ 2011-12-20 8:56 UTC (permalink / raw)
To: davem; +Cc: netdev, linux-s390, Ursula Braun
[-- Attachment #1: 606-qeth-rtnl-lock.diff --]
[-- Type: text/plain, Size: 2297 bytes --]
From: Ursula Braun <ursula.braun@de.ibm.com>
qeth layer3 recovery invokes its set_multicast_list function, which
invokes function __vlan_find_dev_deep requiring rcu_read_lock or
rtnl lock. This causes kernel messages:
kernel: [ INFO: suspicious rcu_dereference_check() usage. ]
kernel: ---------------------------------------------------
kernel: net/8021q/vlan_core.c:70 invoked rcu_dereference_check() without protection!
kernel: stack backtrace:
kernel: CPU: 0 Not tainted 3.1.0 #9
kernel: Process qeth_recover (pid: 2078, task: 000000007e584680, ksp: 000000007e3e3930)
kernel: 000000007e3e3d08 000000007e3e3c88 0000000000000002 0000000000000000
kernel: 000000007e3e3d28 000000007e3e3ca0 000000007e3e3ca0 00000000005e77ce
kernel: 0000000000000000 0000000000000001 ffffffffffffffff 0000000000000001
kernel: 000000000000000d 000000000000000c 000000007e3e3cf0 0000000000000000
kernel: 0000000000000000 0000000000100a18 000000007e3e3c88 000000007e3e3cc8
kernel: Call Trace:
kernel: ([<0000000000100926>] show_trace+0xee/0x144)
kernel: [<00000000005d395c>] __vlan_find_dev_deep+0xb0/0x108
kernel: [<00000000004acd3a>] qeth_l3_set_multicast_list+0x976/0xe38
kernel: [<00000000004ae0f4>] __qeth_l3_set_online+0x75c/0x1498
kernel: [<00000000004aefec>] qeth_l3_recover+0xc4/0x1d0
kernel: [<0000000000185372>] kthread+0xa6/0xb0
kernel: [<00000000005ed4c6>] kernel_thread_starter+0x6/0xc
kernel: [<00000000005ed4c0>] kernel_thread_starter+0x0/0xc
The patch makes sure the rtnl lock is held once qeth recovery invokes
its set_multicast_list function.
Signed-off-by: Ursula Braun <ursula.braun@de.ibm.com>
Signed-off-by: Frank Blaschka <frank.blaschka@de.ibm.com>
---
drivers/s390/net/qeth_l3_main.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -3492,14 +3492,13 @@ contin:
else
netif_carrier_off(card->dev);
if (recover_flag == CARD_STATE_RECOVER) {
+ rtnl_lock();
if (recovery_mode)
__qeth_l3_open(card->dev);
- else {
- rtnl_lock();
+ else
dev_open(card->dev);
- rtnl_unlock();
- }
qeth_l3_set_multicast_list(card->dev);
+ rtnl_unlock();
}
/* let user_space know that device is online */
kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE);
^ permalink raw reply [flat|nested] 12+ messages in thread
* [patch 07/10] [PATCH] qeth: forbid recovery during shutdown
2011-12-20 8:56 [patch 00/10] s390: network driver features and fixes for net-next frank.blaschka
` (5 preceding siblings ...)
2011-12-20 8:56 ` [patch 06/10] [PATCH] qeth: suspicious rcu_dereference_check in recovery frank.blaschka
@ 2011-12-20 8:56 ` frank.blaschka
2011-12-20 8:56 ` [patch 08/10] [PATCH] netiucv: allow multiple interfaces to same peer frank.blaschka
` (3 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: frank.blaschka @ 2011-12-20 8:56 UTC (permalink / raw)
To: davem; +Cc: netdev, linux-s390, Ursula Braun
[-- Attachment #1: 607-qeth-recovery-shutdown.diff --]
[-- Type: text/plain, Size: 3459 bytes --]
From: Ursula Braun <ursula.braun@de.ibm.com>
A recovery does not make sense during shutdown and may even cause an
error like this:
qeth 0.0.f503: A recovery process has been started for the device
Badness at drivers/s390/cio/qdio_main.c:1156
Modules linked in: autofs4 sunrpc dm_multipath scsi_dh scsi_mod qeth_l3 ipv6 vmu
r qeth qdio ccwgroup ext3 jbd mbcache dasd_eckd_mod dasd_mod dm_mirror dm_region
_hash dm_log dm_mod [last unloaded: scsi_wait_scan]
CPU: 3 Not tainted 2.6.32-202.el6.s390x #1
Process qeth_recover (pid: 1498, task: 000000003efe2040, ksp: 000000003d5e3b80)
Krnl PSW : 0404200180000000 000003c000be6da8 (qdio_int_handler+0x88/0x43c [qdio]
)
R:0 T:1 IO:0 EX:0 Key:0 M:1 W:0 P:0 AS:0 CC:2 PM:0 EA:3
Krnl GPRS: ffffffffffff3bac 0000000000000005 0000000000000000 fffffffffffffff4
0000000000000000 000000000000000c 0000000000000000 000000003ca97000
0000000000000380 fffffffffffffff4 000000003f22d800 000000003f22c478
000003c000bdf000 000003c000bea270 000000003f447e10 000000003f447db0
Krnl Code: 000003c000be6d9a: c21f00000004 clfi %r1,4
000003c000be6da0: a7c40021 brc 12,3c000be6de2
000003c000be6da4: a7f40001 brc 15,3c000be6da6
>000003c000be6da8: e320a0080004 lg %r2,8(%r10)
000003c000be6dae: a7390003 lghi %r3,3
000003c000be6db2: a72b0178 aghi %r2,376
000003c000be6db6: a7490001 lghi %r4,1
000003c000be6dba: a7590000 lghi %r5,0
Call Trace:
([<000000000080ee80>] __per_cpu_offset+0x0/0x200)
[<00000000003d90e8>] ccw_device_call_handler+0x70/0xcc
[<00000000003d83a2>] ccw_device_irq+0x82/0x180
[<00000000003cc6a8>] do_IRQ+0x16c/0x1ec
[<0000000000118abe>] io_return+0x0/0x8
[<000003c000d04c74>] qeth_determine_capabilities+0x208/0x5cc [qeth]
([<000003c000d04c4a>] qeth_determine_capabilities+0x1de/0x5cc [qeth])
[<000003c000d0a6e0>] qeth_core_hardsetup_card+0x160/0x1258 [qeth]
[<000003c000f49f56>] __qeth_l3_set_online+0x132/0xb14 [qeth_l3]
[<000003c000f4ac70>] qeth_l3_recover+0x168/0x224 [qeth_l3]
[<000000000016e210>] kthread+0xa4/0xac
[<0000000000109c6e>] kernel_thread_starter+0x6/0xc
[<0000000000109c68>] kernel_thread_starter+0x0/0xc
The patch forbids start of a recovery once qeth shutdown is running.
Signed-off-by: Ursula Braun <ursula.braun@de.ibm.com>
Signed-off-by: Frank Blaschka <frank.blaschka@de.ibm.com>
---
drivers/s390/net/qeth_l2_main.c | 1 +
drivers/s390/net/qeth_l3_main.c | 1 +
2 files changed, 2 insertions(+)
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -1173,6 +1173,7 @@ static void __exit qeth_l2_exit(void)
static void qeth_l2_shutdown(struct ccwgroup_device *gdev)
{
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
+ qeth_set_allowed_threads(card, 0, 1);
if ((gdev->state == CCWGROUP_ONLINE) && card->info.hwtrap)
qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM);
qeth_qdio_clear_card(card, 0);
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -3598,6 +3598,7 @@ static int qeth_l3_recover(void *ptr)
static void qeth_l3_shutdown(struct ccwgroup_device *gdev)
{
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
+ qeth_set_allowed_threads(card, 0, 1);
if ((gdev->state == CCWGROUP_ONLINE) && card->info.hwtrap)
qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM);
qeth_qdio_clear_card(card, 0);
^ permalink raw reply [flat|nested] 12+ messages in thread
* [patch 08/10] [PATCH] netiucv: allow multiple interfaces to same peer
2011-12-20 8:56 [patch 00/10] s390: network driver features and fixes for net-next frank.blaschka
` (6 preceding siblings ...)
2011-12-20 8:56 ` [patch 07/10] [PATCH] qeth: forbid recovery during shutdown frank.blaschka
@ 2011-12-20 8:56 ` frank.blaschka
2011-12-20 8:56 ` [patch 09/10] [PATCH] qeth: improve recovery during resource shortage frank.blaschka
` (2 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: frank.blaschka @ 2011-12-20 8:56 UTC (permalink / raw)
To: davem; +Cc: netdev, linux-s390, Ursula Braun
[-- Attachment #1: 608-netiucv-multi-if-peer.diff --]
[-- Type: text/plain, Size: 15365 bytes --]
From: Ursula Braun <ursula.braun@de.ibm.com>
The NETIUCV device driver allows to connect a Linux guest on z/VM to
another z/VM guest based on the z/VM communication facility IUCV.
Multiple output paths to different guests are possible, as well as
multiple input paths from different guests.
With this feature, you can configure multiple point-to-point NETIUCV
interfaces between your Linux on System z instance and another z/VM
guest.
Signed-off-by: Ursula Braun <ursula.braun@de.ibm.com>
Signed-off-by: Frank Blaschka <frank.blaschka@de.ibm.com>
---
drivers/s390/net/netiucv.c | 217 +++++++++++++++++++++++++++------------------
1 file changed, 135 insertions(+), 82 deletions(-)
--- a/drivers/s390/net/netiucv.c
+++ b/drivers/s390/net/netiucv.c
@@ -63,6 +63,7 @@
#include <asm/io.h>
#include <asm/uaccess.h>
+#include <asm/ebcdic.h>
#include <net/iucv/iucv.h>
#include "fsm.h"
@@ -75,7 +76,7 @@ MODULE_DESCRIPTION ("Linux for S/390 IUC
* Debug Facility stuff
*/
#define IUCV_DBF_SETUP_NAME "iucv_setup"
-#define IUCV_DBF_SETUP_LEN 32
+#define IUCV_DBF_SETUP_LEN 64
#define IUCV_DBF_SETUP_PAGES 2
#define IUCV_DBF_SETUP_NR_AREAS 1
#define IUCV_DBF_SETUP_LEVEL 3
@@ -226,6 +227,7 @@ struct iucv_connection {
struct net_device *netdev;
struct connection_profile prof;
char userid[9];
+ char userdata[17];
};
/**
@@ -263,7 +265,7 @@ struct ll_header {
};
#define NETIUCV_HDRLEN (sizeof(struct ll_header))
-#define NETIUCV_BUFSIZE_MAX 32768
+#define NETIUCV_BUFSIZE_MAX 65537
#define NETIUCV_BUFSIZE_DEFAULT NETIUCV_BUFSIZE_MAX
#define NETIUCV_MTU_MAX (NETIUCV_BUFSIZE_MAX - NETIUCV_HDRLEN)
#define NETIUCV_MTU_DEFAULT 9216
@@ -288,7 +290,12 @@ static inline int netiucv_test_and_set_b
return test_and_set_bit(0, &priv->tbusy);
}
-static u8 iucvMagic[16] = {
+static u8 iucvMagic_ascii[16] = {
+ 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
+};
+
+static u8 iucvMagic_ebcdic[16] = {
0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40
};
@@ -301,18 +308,38 @@ static u8 iucvMagic[16] = {
*
* @returns The printable string (static data!!)
*/
-static char *netiucv_printname(char *name)
+static char *netiucv_printname(char *name, int len)
{
- static char tmp[9];
+ static char tmp[17];
char *p = tmp;
- memcpy(tmp, name, 8);
- tmp[8] = '\0';
- while (*p && (!isspace(*p)))
+ memcpy(tmp, name, len);
+ tmp[len] = '\0';
+ while (*p && ((p - tmp) < len) && (!isspace(*p)))
p++;
*p = '\0';
return tmp;
}
+static char *netiucv_printuser(struct iucv_connection *conn)
+{
+ static char tmp_uid[9];
+ static char tmp_udat[17];
+ static char buf[100];
+
+ if (memcmp(conn->userdata, iucvMagic_ebcdic, 16)) {
+ tmp_uid[8] = '\0';
+ tmp_udat[16] = '\0';
+ memcpy(tmp_uid, conn->userid, 8);
+ memcpy(tmp_uid, netiucv_printname(tmp_uid, 8), 8);
+ memcpy(tmp_udat, conn->userdata, 16);
+ EBCASC(tmp_udat, 16);
+ memcpy(tmp_udat, netiucv_printname(tmp_udat, 16), 16);
+ sprintf(buf, "%s.%s", tmp_uid, tmp_udat);
+ return buf;
+ } else
+ return netiucv_printname(conn->userid, 8);
+}
+
/**
* States of the interface statemachine.
*/
@@ -563,15 +590,18 @@ static int netiucv_callback_connreq(stru
{
struct iucv_connection *conn = path->private;
struct iucv_event ev;
+ static char tmp_user[9];
+ static char tmp_udat[17];
int rc;
- if (memcmp(iucvMagic, ipuser, 16))
- /* ipuser must match iucvMagic. */
- return -EINVAL;
rc = -EINVAL;
+ memcpy(tmp_user, netiucv_printname(ipvmid, 8), 8);
+ memcpy(tmp_udat, ipuser, 16);
+ EBCASC(tmp_udat, 16);
read_lock_bh(&iucv_connection_rwlock);
list_for_each_entry(conn, &iucv_connection_list, list) {
- if (strncmp(ipvmid, conn->userid, 8))
+ if (strncmp(ipvmid, conn->userid, 8) ||
+ strncmp(ipuser, conn->userdata, 16))
continue;
/* Found a matching connection for this path. */
conn->path = path;
@@ -580,6 +610,8 @@ static int netiucv_callback_connreq(stru
fsm_event(conn->fsm, CONN_EVENT_CONN_REQ, &ev);
rc = 0;
}
+ IUCV_DBF_TEXT_(setup, 2, "Connection requested for %s.%s\n",
+ tmp_user, netiucv_printname(tmp_udat, 16));
read_unlock_bh(&iucv_connection_rwlock);
return rc;
}
@@ -816,7 +848,7 @@ static void conn_action_connaccept(fsm_i
conn->path = path;
path->msglim = NETIUCV_QUEUELEN_DEFAULT;
path->flags = 0;
- rc = iucv_path_accept(path, &netiucv_handler, NULL, conn);
+ rc = iucv_path_accept(path, &netiucv_handler, conn->userdata , conn);
if (rc) {
IUCV_DBF_TEXT_(setup, 2, "rc %d from iucv_accept", rc);
return;
@@ -854,7 +886,7 @@ static void conn_action_conntimsev(fsm_i
IUCV_DBF_TEXT(trace, 3, __func__);
fsm_deltimer(&conn->timer);
- iucv_path_sever(conn->path, NULL);
+ iucv_path_sever(conn->path, conn->userdata);
fsm_newstate(fi, CONN_STATE_STARTWAIT);
}
@@ -867,9 +899,9 @@ static void conn_action_connsever(fsm_in
IUCV_DBF_TEXT(trace, 3, __func__);
fsm_deltimer(&conn->timer);
- iucv_path_sever(conn->path, NULL);
- dev_info(privptr->dev, "The peer interface of the IUCV device"
- " has closed the connection\n");
+ iucv_path_sever(conn->path, conn->userdata);
+ dev_info(privptr->dev, "The peer z/VM guest %s has closed the "
+ "connection\n", netiucv_printuser(conn));
IUCV_DBF_TEXT(data, 2,
"conn_action_connsever: Remote dropped connection\n");
fsm_newstate(fi, CONN_STATE_STARTWAIT);
@@ -886,8 +918,6 @@ static void conn_action_start(fsm_instan
IUCV_DBF_TEXT(trace, 3, __func__);
fsm_newstate(fi, CONN_STATE_STARTWAIT);
- IUCV_DBF_TEXT_(setup, 2, "%s('%s'): connecting ...\n",
- netdev->name, conn->userid);
/*
* We must set the state before calling iucv_connect because the
@@ -897,8 +927,11 @@ static void conn_action_start(fsm_instan
fsm_newstate(fi, CONN_STATE_SETUPWAIT);
conn->path = iucv_path_alloc(NETIUCV_QUEUELEN_DEFAULT, 0, GFP_KERNEL);
+ IUCV_DBF_TEXT_(setup, 2, "%s: connecting to %s ...\n",
+ netdev->name, netiucv_printuser(conn));
+
rc = iucv_path_connect(conn->path, &netiucv_handler, conn->userid,
- NULL, iucvMagic, conn);
+ NULL, conn->userdata, conn);
switch (rc) {
case 0:
netdev->tx_queue_len = conn->path->msglim;
@@ -908,13 +941,13 @@ static void conn_action_start(fsm_instan
case 11:
dev_warn(privptr->dev,
"The IUCV device failed to connect to z/VM guest %s\n",
- netiucv_printname(conn->userid));
+ netiucv_printname(conn->userid, 8));
fsm_newstate(fi, CONN_STATE_STARTWAIT);
break;
case 12:
dev_warn(privptr->dev,
"The IUCV device failed to connect to the peer on z/VM"
- " guest %s\n", netiucv_printname(conn->userid));
+ " guest %s\n", netiucv_printname(conn->userid, 8));
fsm_newstate(fi, CONN_STATE_STARTWAIT);
break;
case 13:
@@ -927,7 +960,7 @@ static void conn_action_start(fsm_instan
dev_err(privptr->dev,
"z/VM guest %s has too many IUCV connections"
" to connect with the IUCV device\n",
- netiucv_printname(conn->userid));
+ netiucv_printname(conn->userid, 8));
fsm_newstate(fi, CONN_STATE_CONNERR);
break;
case 15:
@@ -972,7 +1005,7 @@ static void conn_action_stop(fsm_instanc
netiucv_purge_skb_queue(&conn->collect_queue);
if (conn->path) {
IUCV_DBF_TEXT(trace, 5, "calling iucv_path_sever\n");
- iucv_path_sever(conn->path, iucvMagic);
+ iucv_path_sever(conn->path, conn->userdata);
kfree(conn->path);
conn->path = NULL;
}
@@ -1090,7 +1123,8 @@ dev_action_connup(fsm_instance *fi, int
fsm_newstate(fi, DEV_STATE_RUNNING);
dev_info(privptr->dev,
"The IUCV device has been connected"
- " successfully to %s\n", privptr->conn->userid);
+ " successfully to %s\n",
+ netiucv_printuser(privptr->conn));
IUCV_DBF_TEXT(setup, 3,
"connection is up and running\n");
break;
@@ -1452,45 +1486,72 @@ static ssize_t user_show(struct device *
struct netiucv_priv *priv = dev_get_drvdata(dev);
IUCV_DBF_TEXT(trace, 5, __func__);
- return sprintf(buf, "%s\n", netiucv_printname(priv->conn->userid));
+ return sprintf(buf, "%s\n", netiucv_printuser(priv->conn));
}
-static ssize_t user_write(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static int netiucv_check_user(const char *buf, size_t count, char *username,
+ char *userdata)
{
- struct netiucv_priv *priv = dev_get_drvdata(dev);
- struct net_device *ndev = priv->conn->netdev;
- char *p;
- char *tmp;
- char username[9];
- int i;
- struct iucv_connection *cp;
+ const char *p;
+ int i;
- IUCV_DBF_TEXT(trace, 3, __func__);
- if (count > 9) {
- IUCV_DBF_TEXT_(setup, 2,
- "%d is length of username\n", (int) count);
+ p = strchr(buf, '.');
+ if ((p && ((count > 26) ||
+ ((p - buf) > 8) ||
+ (buf + count - p > 18))) ||
+ (!p && (count > 9))) {
+ IUCV_DBF_TEXT(setup, 2, "conn_write: too long\n");
return -EINVAL;
}
- tmp = strsep((char **) &buf, "\n");
- for (i = 0, p = tmp; i < 8 && *p; i++, p++) {
- if (isalnum(*p) || (*p == '$')) {
- username[i]= toupper(*p);
+ for (i = 0, p = buf; i < 8 && *p && *p != '.'; i++, p++) {
+ if (isalnum(*p) || *p == '$') {
+ username[i] = toupper(*p);
continue;
}
- if (*p == '\n') {
+ if (*p == '\n')
/* trailing lf, grr */
break;
- }
IUCV_DBF_TEXT_(setup, 2,
- "username: invalid character %c\n", *p);
+ "conn_write: invalid character %02x\n", *p);
return -EINVAL;
}
while (i < 8)
username[i++] = ' ';
username[8] = '\0';
+ if (*p == '.') {
+ p++;
+ for (i = 0; i < 16 && *p; i++, p++) {
+ if (*p == '\n')
+ break;
+ userdata[i] = toupper(*p);
+ }
+ while (i > 0 && i < 16)
+ userdata[i++] = ' ';
+ } else
+ memcpy(userdata, iucvMagic_ascii, 16);
+ userdata[16] = '\0';
+ ASCEBC(userdata, 16);
+
+ return 0;
+}
+
+static ssize_t user_write(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct netiucv_priv *priv = dev_get_drvdata(dev);
+ struct net_device *ndev = priv->conn->netdev;
+ char username[9];
+ char userdata[17];
+ int rc;
+ struct iucv_connection *cp;
+
+ IUCV_DBF_TEXT(trace, 3, __func__);
+ rc = netiucv_check_user(buf, count, username, userdata);
+ if (rc)
+ return rc;
+
if (memcmp(username, priv->conn->userid, 9) &&
(ndev->flags & (IFF_UP | IFF_RUNNING))) {
/* username changed while the interface is active. */
@@ -1499,15 +1560,17 @@ static ssize_t user_write(struct device
}
read_lock_bh(&iucv_connection_rwlock);
list_for_each_entry(cp, &iucv_connection_list, list) {
- if (!strncmp(username, cp->userid, 9) && cp->netdev != ndev) {
+ if (!strncmp(username, cp->userid, 9) &&
+ !strncmp(userdata, cp->userdata, 17) && cp->netdev != ndev) {
read_unlock_bh(&iucv_connection_rwlock);
- IUCV_DBF_TEXT_(setup, 2, "user_write: Connection "
- "to %s already exists\n", username);
+ IUCV_DBF_TEXT_(setup, 2, "user_write: Connection to %s "
+ "already exists\n", netiucv_printuser(cp));
return -EEXIST;
}
}
read_unlock_bh(&iucv_connection_rwlock);
memcpy(priv->conn->userid, username, 9);
+ memcpy(priv->conn->userdata, userdata, 17);
return count;
}
@@ -1537,7 +1600,8 @@ static ssize_t buffer_write (struct devi
bs1 = simple_strtoul(buf, &e, 0);
if (e && (!isspace(*e))) {
- IUCV_DBF_TEXT_(setup, 2, "buffer_write: invalid char %c\n", *e);
+ IUCV_DBF_TEXT_(setup, 2, "buffer_write: invalid char %02x\n",
+ *e);
return -EINVAL;
}
if (bs1 > NETIUCV_BUFSIZE_MAX) {
@@ -1864,7 +1928,8 @@ static void netiucv_unregister_device(st
* Add it to the list of netiucv connections;
*/
static struct iucv_connection *netiucv_new_connection(struct net_device *dev,
- char *username)
+ char *username,
+ char *userdata)
{
struct iucv_connection *conn;
@@ -1893,6 +1958,8 @@ static struct iucv_connection *netiucv_n
fsm_settimer(conn->fsm, &conn->timer);
fsm_newstate(conn->fsm, CONN_STATE_INVALID);
+ if (userdata)
+ memcpy(conn->userdata, userdata, 17);
if (username) {
memcpy(conn->userid, username, 9);
fsm_newstate(conn->fsm, CONN_STATE_STOPPED);
@@ -1919,6 +1986,7 @@ out:
*/
static void netiucv_remove_connection(struct iucv_connection *conn)
{
+
IUCV_DBF_TEXT(trace, 3, __func__);
write_lock_bh(&iucv_connection_rwlock);
list_del_init(&conn->list);
@@ -1926,7 +1994,7 @@ static void netiucv_remove_connection(st
fsm_deltimer(&conn->timer);
netiucv_purge_skb_queue(&conn->collect_queue);
if (conn->path) {
- iucv_path_sever(conn->path, iucvMagic);
+ iucv_path_sever(conn->path, conn->userdata);
kfree(conn->path);
conn->path = NULL;
}
@@ -1985,7 +2053,7 @@ static void netiucv_setup_netdevice(stru
/**
* Allocate and initialize everything of a net device.
*/
-static struct net_device *netiucv_init_netdevice(char *username)
+static struct net_device *netiucv_init_netdevice(char *username, char *userdata)
{
struct netiucv_priv *privptr;
struct net_device *dev;
@@ -2004,7 +2072,7 @@ static struct net_device *netiucv_init_n
if (!privptr->fsm)
goto out_netdev;
- privptr->conn = netiucv_new_connection(dev, username);
+ privptr->conn = netiucv_new_connection(dev, username, userdata);
if (!privptr->conn) {
IUCV_DBF_TEXT(setup, 2, "NULL from netiucv_new_connection\n");
goto out_fsm;
@@ -2022,47 +2090,31 @@ out_netdev:
static ssize_t conn_write(struct device_driver *drv,
const char *buf, size_t count)
{
- const char *p;
char username[9];
- int i, rc;
+ char userdata[17];
+ int rc;
struct net_device *dev;
struct netiucv_priv *priv;
struct iucv_connection *cp;
IUCV_DBF_TEXT(trace, 3, __func__);
- if (count>9) {
- IUCV_DBF_TEXT(setup, 2, "conn_write: too long\n");
- return -EINVAL;
- }
-
- for (i = 0, p = buf; i < 8 && *p; i++, p++) {
- if (isalnum(*p) || *p == '$') {
- username[i] = toupper(*p);
- continue;
- }
- if (*p == '\n')
- /* trailing lf, grr */
- break;
- IUCV_DBF_TEXT_(setup, 2,
- "conn_write: invalid character %c\n", *p);
- return -EINVAL;
- }
- while (i < 8)
- username[i++] = ' ';
- username[8] = '\0';
+ rc = netiucv_check_user(buf, count, username, userdata);
+ if (rc)
+ return rc;
read_lock_bh(&iucv_connection_rwlock);
list_for_each_entry(cp, &iucv_connection_list, list) {
- if (!strncmp(username, cp->userid, 9)) {
+ if (!strncmp(username, cp->userid, 9) &&
+ !strncmp(userdata, cp->userdata, 17)) {
read_unlock_bh(&iucv_connection_rwlock);
- IUCV_DBF_TEXT_(setup, 2, "conn_write: Connection "
- "to %s already exists\n", username);
+ IUCV_DBF_TEXT_(setup, 2, "conn_write: Connection to %s "
+ "already exists\n", netiucv_printuser(cp));
return -EEXIST;
}
}
read_unlock_bh(&iucv_connection_rwlock);
- dev = netiucv_init_netdevice(username);
+ dev = netiucv_init_netdevice(username, userdata);
if (!dev) {
IUCV_DBF_TEXT(setup, 2, "NULL from netiucv_init_netdevice\n");
return -ENODEV;
@@ -2083,8 +2135,9 @@ static ssize_t conn_write(struct device_
if (rc)
goto out_unreg;
- dev_info(priv->dev, "The IUCV interface to %s has been"
- " established successfully\n", netiucv_printname(username));
+ dev_info(priv->dev, "The IUCV interface to %s has been established "
+ "successfully\n",
+ netiucv_printuser(priv->conn));
return count;
^ permalink raw reply [flat|nested] 12+ messages in thread
* [patch 09/10] [PATCH] qeth: improve recovery during resource shortage
2011-12-20 8:56 [patch 00/10] s390: network driver features and fixes for net-next frank.blaschka
` (7 preceding siblings ...)
2011-12-20 8:56 ` [patch 08/10] [PATCH] netiucv: allow multiple interfaces to same peer frank.blaschka
@ 2011-12-20 8:56 ` frank.blaschka
2011-12-20 8:56 ` [patch 10/10] [PATCH] qeth: recovery through asynchronous delivery frank.blaschka
2011-12-20 19:05 ` [patch 00/10] s390: network driver features and fixes for net-next David Miller
10 siblings, 0 replies; 12+ messages in thread
From: frank.blaschka @ 2011-12-20 8:56 UTC (permalink / raw)
To: davem; +Cc: netdev, linux-s390
[-- Attachment #1: 610-qeth-resource-shortage.diff --]
[-- Type: text/plain, Size: 1372 bytes --]
From: Frank Blaschka <frank.blaschka@de.ibm.com>
In case there are no system resources to run a recovery we have to clear
recovery bitmasks so a further automatic or manual driven recovery can
fix up the device.
Signed-off-by: Frank Blaschka <frank.blaschka@de.ibm.com>
---
drivers/s390/net/qeth_core_main.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -1329,6 +1329,7 @@ static int qeth_do_start_thread(struct q
static void qeth_start_kernel_thread(struct work_struct *work)
{
+ struct task_struct *ts;
struct qeth_card *card = container_of(work, struct qeth_card,
kernel_thread_starter);
QETH_CARD_TEXT(card , 2, "strthrd");
@@ -1336,9 +1337,15 @@ static void qeth_start_kernel_thread(str
if (card->read.state != CH_STATE_UP &&
card->write.state != CH_STATE_UP)
return;
- if (qeth_do_start_thread(card, QETH_RECOVER_THREAD))
- kthread_run(card->discipline.recover, (void *) card,
+ if (qeth_do_start_thread(card, QETH_RECOVER_THREAD)) {
+ ts = kthread_run(card->discipline.recover, (void *)card,
"qeth_recover");
+ if (IS_ERR(ts)) {
+ qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
+ qeth_clear_thread_running_bit(card,
+ QETH_RECOVER_THREAD);
+ }
+ }
}
static int qeth_setup_card(struct qeth_card *card)
^ permalink raw reply [flat|nested] 12+ messages in thread
* [patch 10/10] [PATCH] qeth: recovery through asynchronous delivery
2011-12-20 8:56 [patch 00/10] s390: network driver features and fixes for net-next frank.blaschka
` (8 preceding siblings ...)
2011-12-20 8:56 ` [patch 09/10] [PATCH] qeth: improve recovery during resource shortage frank.blaschka
@ 2011-12-20 8:56 ` frank.blaschka
2011-12-20 19:05 ` [patch 00/10] s390: network driver features and fixes for net-next David Miller
10 siblings, 0 replies; 12+ messages in thread
From: frank.blaschka @ 2011-12-20 8:56 UTC (permalink / raw)
To: davem; +Cc: netdev, linux-s390, Einar Lueck, Ursula Braun
[-- Attachment #1: 611-qeth-async-recovery.diff --]
[-- Type: text/plain, Size: 4423 bytes --]
From: Einar Lueck <elelueck@de.ibm.com>
If recovery is triggered in presence of pending asynchronous
deliveries of storage blocks we do a forced cleanup after
the corresponding tasklets are completely stopped and trigger
appropriate notifications for the correspondingerror state.
Signed-off-by: Einar Lueck <elelueck@de.ibm.com>
Signed-off-by: Ursula Braun <ursula.braun@de.ibm.com>
Signed-off-by: Frank Blaschka <frank.blaschka@de.ibm.com>
---
drivers/s390/net/qeth_core_main.c | 34 +++++++++++++++++++++++++++++-----
drivers/s390/net/qeth_l3_main.c | 5 +++++
2 files changed, 34 insertions(+), 5 deletions(-)
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -66,7 +66,7 @@ static void qeth_release_skbs(struct qet
static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
struct qeth_qdio_out_buffer *buf,
enum qeth_qdio_buffer_states newbufstate);
-
+static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *, int);
static inline const char *qeth_get_cardname(struct qeth_card *card)
{
@@ -363,6 +363,9 @@ static inline enum iucv_tx_notify qeth_c
static inline void qeth_cleanup_handled_pending(struct qeth_qdio_out_q *q,
int bidx, int forced_cleanup)
{
+ if (q->card->options.cq != QETH_CQ_ENABLED)
+ return;
+
if (q->bufs[bidx]->next_pending != NULL) {
struct qeth_qdio_out_buffer *head = q->bufs[bidx];
struct qeth_qdio_out_buffer *c = q->bufs[bidx]->next_pending;
@@ -390,6 +393,13 @@ static inline void qeth_cleanup_handled_
}
}
+ if (forced_cleanup && (atomic_read(&(q->bufs[bidx]->state)) ==
+ QETH_QDIO_BUF_HANDLED_DELAYED)) {
+ /* for recovery situations */
+ q->bufs[bidx]->aob = q->bufstates[bidx].aob;
+ qeth_init_qdio_out_buf(q, bidx);
+ QETH_CARD_TEXT(q->card, 2, "clprecov");
+ }
}
@@ -412,7 +422,6 @@ static inline void qeth_qdio_handle_aob(
notification = TX_NOTIFY_OK;
} else {
BUG_ON(atomic_read(&buffer->state) != QETH_QDIO_BUF_PENDING);
-
atomic_set(&buffer->state, QETH_QDIO_BUF_IN_CQ);
notification = TX_NOTIFY_DELAYED_OK;
}
@@ -425,7 +434,8 @@ static inline void qeth_qdio_handle_aob(
buffer->aob = NULL;
qeth_clear_output_buffer(buffer->q, buffer,
- QETH_QDIO_BUF_HANDLED_DELAYED);
+ QETH_QDIO_BUF_HANDLED_DELAYED);
+
/* from here on: do not touch buffer anymore */
qdio_release_aob(aob);
}
@@ -1113,11 +1123,25 @@ out:
static void qeth_release_skbs(struct qeth_qdio_out_buffer *buf)
{
struct sk_buff *skb;
+ struct iucv_sock *iucv;
+ int notify_general_error = 0;
+
+ if (atomic_read(&buf->state) == QETH_QDIO_BUF_PENDING)
+ notify_general_error = 1;
+
+ /* release may never happen from within CQ tasklet scope */
+ BUG_ON(atomic_read(&buf->state) == QETH_QDIO_BUF_IN_CQ);
skb = skb_dequeue(&buf->skb_list);
while (skb) {
QETH_CARD_TEXT(buf->q->card, 5, "skbr");
QETH_CARD_TEXT_(buf->q->card, 5, "%lx", (long) skb);
+ if (notify_general_error && skb->protocol == ETH_P_AF_IUCV) {
+ if (skb->sk) {
+ iucv = iucv_sk(skb->sk);
+ iucv->sk_txnotify(skb, TX_NOTIFY_GENERALERROR);
+ }
+ }
atomic_dec(&skb->users);
dev_kfree_skb_any(skb);
skb = skb_dequeue(&buf->skb_list);
@@ -1160,7 +1184,7 @@ static void qeth_clear_outq_buffers(stru
for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
if (!q->bufs[j])
continue;
- qeth_cleanup_handled_pending(q, j, free);
+ qeth_cleanup_handled_pending(q, j, 1);
qeth_clear_output_buffer(q, q->bufs[j], QETH_QDIO_BUF_EMPTY);
if (free) {
kmem_cache_free(qeth_qdio_outbuf_cache, q->bufs[j]);
@@ -1207,7 +1231,7 @@ static void qeth_free_qdio_buffers(struc
qeth_free_cq(card);
cancel_delayed_work_sync(&card->buffer_reclaim_work);
for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j)
- kfree_skb(card->qdio.in_q->bufs[j].rx_skb);
+ dev_kfree_skb_any(card->qdio.in_q->bufs[j].rx_skb);
kfree(card->qdio.in_q);
card->qdio.in_q = NULL;
/* inbound buffer pool */
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -3544,6 +3544,11 @@ static int __qeth_l3_set_offline(struct
card->info.hwtrap = 1;
}
qeth_l3_stop_card(card, recovery_mode);
+ if ((card->options.cq == QETH_CQ_ENABLED) && card->dev) {
+ rtnl_lock();
+ call_netdevice_notifiers(NETDEV_REBOOT, card->dev);
+ rtnl_unlock();
+ }
rc = ccw_device_set_offline(CARD_DDEV(card));
rc2 = ccw_device_set_offline(CARD_WDEV(card));
rc3 = ccw_device_set_offline(CARD_RDEV(card));
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [patch 00/10] s390: network driver features and fixes for net-next
2011-12-20 8:56 [patch 00/10] s390: network driver features and fixes for net-next frank.blaschka
` (9 preceding siblings ...)
2011-12-20 8:56 ` [patch 10/10] [PATCH] qeth: recovery through asynchronous delivery frank.blaschka
@ 2011-12-20 19:05 ` David Miller
10 siblings, 0 replies; 12+ messages in thread
From: David Miller @ 2011-12-20 19:05 UTC (permalink / raw)
To: frank.blaschka; +Cc: netdev, linux-s390
From: frank.blaschka@de.ibm.com
Date: Tue, 20 Dec 2011 09:56:26 +0100
> here are some s390 network driver features and fixes for net-next
Series applied, thanks.
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2011-12-20 19:05 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-12-20 8:56 [patch 00/10] s390: network driver features and fixes for net-next frank.blaschka
2011-12-20 8:56 ` [patch 01/10] [PATCH] af_iucv: support ancillary data with HS transport frank.blaschka
2011-12-20 8:56 ` [patch 02/10] [PATCH] af_iucv: accelerate close for " frank.blaschka
2011-12-20 8:56 ` [patch 03/10] [PATCH] af_iucv: release reference to HS device frank.blaschka
2011-12-20 8:56 ` [patch 04/10] [PATCH] af_iucv: remove unused timer infrastructure frank.blaschka
2011-12-20 8:56 ` [patch 05/10] [PATCH] af_iucv: get rid of state IUCV_SEVERED frank.blaschka
2011-12-20 8:56 ` [patch 06/10] [PATCH] qeth: suspicious rcu_dereference_check in recovery frank.blaschka
2011-12-20 8:56 ` [patch 07/10] [PATCH] qeth: forbid recovery during shutdown frank.blaschka
2011-12-20 8:56 ` [patch 08/10] [PATCH] netiucv: allow multiple interfaces to same peer frank.blaschka
2011-12-20 8:56 ` [patch 09/10] [PATCH] qeth: improve recovery during resource shortage frank.blaschka
2011-12-20 8:56 ` [patch 10/10] [PATCH] qeth: recovery through asynchronous delivery frank.blaschka
2011-12-20 19:05 ` [patch 00/10] s390: network driver features and fixes for net-next David Miller
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).