* [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).