| From foo@baz Tue Mar 6 19:02:12 PST 2018 |
| From: Julian Wiedmann <jwi@linux.vnet.ibm.com> |
| Date: Tue, 27 Feb 2018 18:58:13 +0100 |
| Subject: s390/qeth: fix IP removal on offline cards |
| |
| From: Julian Wiedmann <jwi@linux.vnet.ibm.com> |
| |
| |
| [ Upstream commit 98d823ab1fbdcb13abc25b420f9bb71bade42056 ] |
| |
| If the HW is not reachable, then none of the IPs in qeth's internal |
| table has been registered with the HW yet. So when deleting such an IP, |
| there's no need to stage it for deregistration - just drop it from |
| the table. |
| |
| This fixes the "add-delete-add" scenario on an offline card, where the |
| the second "add" merely increments the IP's use count. But as the IP is |
| still set to DISP_ADDR_DELETE from the previous "delete" step, |
| l3_recover_ip() won't register it with the HW when the card goes online. |
| |
| Fixes: 5f78e29ceebf ("qeth: optimize IP handling in rx_mode callback") |
| Signed-off-by: Julian Wiedmann <jwi@linux.vnet.ibm.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/s390/net/qeth_l3_main.c | 14 +++----------- |
| 1 file changed, 3 insertions(+), 11 deletions(-) |
| |
| --- a/drivers/s390/net/qeth_l3_main.c |
| +++ b/drivers/s390/net/qeth_l3_main.c |
| @@ -255,12 +255,8 @@ int qeth_l3_delete_ip(struct qeth_card * |
| if (addr->in_progress) |
| return -EINPROGRESS; |
| |
| - if (!qeth_card_hw_is_reachable(card)) { |
| - addr->disp_flag = QETH_DISP_ADDR_DELETE; |
| - return 0; |
| - } |
| - |
| - rc = qeth_l3_deregister_addr_entry(card, addr); |
| + if (qeth_card_hw_is_reachable(card)) |
| + rc = qeth_l3_deregister_addr_entry(card, addr); |
| |
| hash_del(&addr->hnode); |
| kfree(addr); |
| @@ -403,11 +399,7 @@ static void qeth_l3_recover_ip(struct qe |
| spin_lock_bh(&card->ip_lock); |
| |
| hash_for_each_safe(card->ip_htable, i, tmp, addr, hnode) { |
| - if (addr->disp_flag == QETH_DISP_ADDR_DELETE) { |
| - qeth_l3_deregister_addr_entry(card, addr); |
| - hash_del(&addr->hnode); |
| - kfree(addr); |
| - } else if (addr->disp_flag == QETH_DISP_ADDR_ADD) { |
| + if (addr->disp_flag == QETH_DISP_ADDR_ADD) { |
| if (addr->proto == QETH_PROT_IPV4) { |
| addr->in_progress = 1; |
| spin_unlock_bh(&card->ip_lock); |