diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-09 17:04:10 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-09 17:04:10 -0700 |
commit | c18bb396d3d261ebbb4efbc05129c5d354c541e4 (patch) | |
tree | 058a1413dd34fe4e1d9a998a43d56f3358b93e36 /drivers/net/ethernet/ibm/ibmvnic.c | |
parent | fd3b36d275660c905da9900b078eea341847d5e4 (diff) | |
parent | a2ac99905f1ea8b15997a6ec39af69aa28a3653b (diff) | |
download | linux-c18bb396d3d261ebbb4efbc05129c5d354c541e4.tar.bz2 |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull networking fixes from David Miller:
1) The sockmap code has to free socket memory on close if there is
corked data, from John Fastabend.
2) Tunnel names coming from userspace need to be length validated. From
Eric Dumazet.
3) arp_filter() has to take VRFs properly into account, from Miguel
Fadon Perlines.
4) Fix oops in error path of tcf_bpf_init(), from Davide Caratti.
5) Missing idr_remove() in u32_delete_key(), from Cong Wang.
6) More syzbot stuff. Several use of uninitialized value fixes all
over, from Eric Dumazet.
7) Do not leak kernel memory to userspace in sctp, also from Eric
Dumazet.
8) Discard frames from unused ports in DSA, from Andrew Lunn.
9) Fix DMA mapping and reset/failover problems in ibmvnic, from Thomas
Falcon.
10) Do not access dp83640 PHY registers prematurely after reset, from
Esben Haabendal.
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (46 commits)
vhost-net: set packet weight of tx polling to 2 * vq size
net: thunderx: rework mac addresses list to u64 array
inetpeer: fix uninit-value in inet_getpeer
dp83640: Ensure against premature access to PHY registers after reset
devlink: convert occ_get op to separate registration
ARM: dts: ls1021a: Specify TBIPA register address
net/fsl_pq_mdio: Allow explicit speficition of TBIPA address
ibmvnic: Do not reset CRQ for Mobility driver resets
ibmvnic: Fix failover case for non-redundant configuration
ibmvnic: Fix reset scheduler error handling
ibmvnic: Zero used TX descriptor counter on reset
ibmvnic: Fix DMA mapping mistakes
tipc: use the right skb in tipc_sk_fill_sock_diag()
sctp: sctp_sockaddr_af must check minimal addr length for AF_INET6
net: dsa: Discard frames from unused ports
sctp: do not leak kernel memory to user space
soreuseport: initialise timewait reuseport field
ipv4: fix uninit-value in ip_route_output_key_hash_rcu()
dccp: initialize ireq->ir_mark
net: fix uninit-value in __hw_addr_add_ex()
...
Diffstat (limited to 'drivers/net/ethernet/ibm/ibmvnic.c')
-rw-r--r-- | drivers/net/ethernet/ibm/ibmvnic.c | 146 |
1 files changed, 97 insertions, 49 deletions
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index b492af6affc3..aad5658d79d5 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -118,6 +118,7 @@ static int init_sub_crq_irqs(struct ibmvnic_adapter *adapter); static int ibmvnic_init(struct ibmvnic_adapter *); static void release_crq_queue(struct ibmvnic_adapter *); static int __ibmvnic_set_mac(struct net_device *netdev, struct sockaddr *p); +static int init_crq_queue(struct ibmvnic_adapter *adapter); struct ibmvnic_stat { char name[ETH_GSTRING_LEN]; @@ -320,18 +321,16 @@ failure: dev_info(dev, "replenish pools failure\n"); pool->free_map[pool->next_free] = index; pool->rx_buff[index].skb = NULL; - if (!dma_mapping_error(dev, dma_addr)) - dma_unmap_single(dev, dma_addr, pool->buff_size, - DMA_FROM_DEVICE); dev_kfree_skb_any(skb); adapter->replenish_add_buff_failure++; atomic_add(buffers_added, &pool->available); - if (lpar_rc == H_CLOSED) { + if (lpar_rc == H_CLOSED || adapter->failover_pending) { /* Disable buffer pool replenishment and report carrier off if - * queue is closed. Firmware guarantees that a signal will - * be sent to the driver, triggering a reset. + * queue is closed or pending failover. + * Firmware guarantees that a signal will be sent to the + * driver, triggering a reset. */ deactivate_rx_pools(adapter); netif_carrier_off(adapter->netdev); @@ -1071,6 +1070,14 @@ static int ibmvnic_open(struct net_device *netdev) struct ibmvnic_adapter *adapter = netdev_priv(netdev); int rc; + /* If device failover is pending, just set device state and return. + * Device operation will be handled by reset routine. + */ + if (adapter->failover_pending) { + adapter->state = VNIC_OPEN; + return 0; + } + mutex_lock(&adapter->reset_lock); if (adapter->state != VNIC_CLOSED) { @@ -1218,7 +1225,6 @@ static int __ibmvnic_close(struct net_device *netdev) rc = set_link_state(adapter, IBMVNIC_LOGICAL_LNK_DN); if (rc) return rc; - ibmvnic_cleanup(netdev); adapter->state = VNIC_CLOSED; return 0; } @@ -1228,8 +1234,17 @@ static int ibmvnic_close(struct net_device *netdev) struct ibmvnic_adapter *adapter = netdev_priv(netdev); int rc; + /* If device failover is pending, just set device state and return. + * Device operation will be handled by reset routine. + */ + if (adapter->failover_pending) { + adapter->state = VNIC_CLOSED; + return 0; + } + mutex_lock(&adapter->reset_lock); rc = __ibmvnic_close(netdev); + ibmvnic_cleanup(netdev); mutex_unlock(&adapter->reset_lock); return rc; @@ -1562,8 +1577,9 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev) dev_kfree_skb_any(skb); tx_buff->skb = NULL; - if (lpar_rc == H_CLOSED) { - /* Disable TX and report carrier off if queue is closed. + if (lpar_rc == H_CLOSED || adapter->failover_pending) { + /* Disable TX and report carrier off if queue is closed + * or pending failover. * Firmware guarantees that a signal will be sent to the * driver, triggering a reset or some other action. */ @@ -1711,14 +1727,10 @@ static int do_reset(struct ibmvnic_adapter *adapter, old_num_rx_queues = adapter->req_rx_queues; old_num_tx_queues = adapter->req_tx_queues; - if (rwi->reset_reason == VNIC_RESET_MOBILITY) { - rc = ibmvnic_reenable_crq_queue(adapter); - if (rc) - return 0; - ibmvnic_cleanup(netdev); - } else if (rwi->reset_reason == VNIC_RESET_FAILOVER) { - ibmvnic_cleanup(netdev); - } else { + ibmvnic_cleanup(netdev); + + if (adapter->reset_reason != VNIC_RESET_MOBILITY && + adapter->reset_reason != VNIC_RESET_FAILOVER) { rc = __ibmvnic_close(netdev); if (rc) return rc; @@ -1737,6 +1749,23 @@ static int do_reset(struct ibmvnic_adapter *adapter, */ adapter->state = VNIC_PROBED; + if (adapter->wait_for_reset) { + rc = init_crq_queue(adapter); + } else if (adapter->reset_reason == VNIC_RESET_MOBILITY) { + rc = ibmvnic_reenable_crq_queue(adapter); + release_sub_crqs(adapter, 1); + } else { + rc = ibmvnic_reset_crq(adapter); + if (!rc) + rc = vio_enable_interrupts(adapter->vdev); + } + + if (rc) { + netdev_err(adapter->netdev, + "Couldn't initialize crq. rc=%d\n", rc); + return rc; + } + rc = ibmvnic_init(adapter); if (rc) return IBMVNIC_INIT_FAILED; @@ -1878,23 +1907,26 @@ static void __ibmvnic_reset(struct work_struct *work) mutex_unlock(&adapter->reset_lock); } -static void ibmvnic_reset(struct ibmvnic_adapter *adapter, - enum ibmvnic_reset_reason reason) +static int ibmvnic_reset(struct ibmvnic_adapter *adapter, + enum ibmvnic_reset_reason reason) { struct ibmvnic_rwi *rwi, *tmp; struct net_device *netdev = adapter->netdev; struct list_head *entry; + int ret; if (adapter->state == VNIC_REMOVING || - adapter->state == VNIC_REMOVED) { - netdev_dbg(netdev, "Adapter removing, skipping reset\n"); - return; + adapter->state == VNIC_REMOVED || + adapter->failover_pending) { + ret = EBUSY; + netdev_dbg(netdev, "Adapter removing or pending failover, skipping reset\n"); + goto err; } if (adapter->state == VNIC_PROBING) { netdev_warn(netdev, "Adapter reset during probe\n"); - adapter->init_done_rc = EAGAIN; - return; + ret = adapter->init_done_rc = EAGAIN; + goto err; } mutex_lock(&adapter->rwi_lock); @@ -1904,7 +1936,8 @@ static void ibmvnic_reset(struct ibmvnic_adapter *adapter, if (tmp->reset_reason == reason) { netdev_dbg(netdev, "Skipping matching reset\n"); mutex_unlock(&adapter->rwi_lock); - return; + ret = EBUSY; + goto err; } } @@ -1912,7 +1945,8 @@ static void ibmvnic_reset(struct ibmvnic_adapter *adapter, if (!rwi) { mutex_unlock(&adapter->rwi_lock); ibmvnic_close(netdev); - return; + ret = ENOMEM; + goto err; } rwi->reset_reason = reason; @@ -1921,6 +1955,12 @@ static void ibmvnic_reset(struct ibmvnic_adapter *adapter, netdev_dbg(adapter->netdev, "Scheduling reset (reason %d)\n", reason); schedule_work(&adapter->ibmvnic_reset); + + return 0; +err: + if (adapter->wait_for_reset) + adapter->wait_for_reset = false; + return -ret; } static void ibmvnic_tx_timeout(struct net_device *dev) @@ -2055,6 +2095,8 @@ static void ibmvnic_netpoll_controller(struct net_device *dev) static int wait_for_reset(struct ibmvnic_adapter *adapter) { + int rc, ret; + adapter->fallback.mtu = adapter->req_mtu; adapter->fallback.rx_queues = adapter->req_rx_queues; adapter->fallback.tx_queues = adapter->req_tx_queues; @@ -2062,11 +2104,15 @@ static int wait_for_reset(struct ibmvnic_adapter *adapter) adapter->fallback.tx_entries = adapter->req_tx_entries_per_subcrq; init_completion(&adapter->reset_done); - ibmvnic_reset(adapter, VNIC_RESET_CHANGE_PARAM); adapter->wait_for_reset = true; + rc = ibmvnic_reset(adapter, VNIC_RESET_CHANGE_PARAM); + if (rc) + return rc; wait_for_completion(&adapter->reset_done); + ret = 0; if (adapter->reset_done_rc) { + ret = -EIO; adapter->desired.mtu = adapter->fallback.mtu; adapter->desired.rx_queues = adapter->fallback.rx_queues; adapter->desired.tx_queues = adapter->fallback.tx_queues; @@ -2074,12 +2120,15 @@ static int wait_for_reset(struct ibmvnic_adapter *adapter) adapter->desired.tx_entries = adapter->fallback.tx_entries; init_completion(&adapter->reset_done); - ibmvnic_reset(adapter, VNIC_RESET_CHANGE_PARAM); + adapter->wait_for_reset = true; + rc = ibmvnic_reset(adapter, VNIC_RESET_CHANGE_PARAM); + if (rc) + return ret; wait_for_completion(&adapter->reset_done); } adapter->wait_for_reset = false; - return adapter->reset_done_rc; + return ret; } static int ibmvnic_change_mtu(struct net_device *netdev, int new_mtu) @@ -2364,6 +2413,7 @@ static int reset_one_sub_crq_queue(struct ibmvnic_adapter *adapter, } memset(scrq->msgs, 0, 4 * PAGE_SIZE); + atomic_set(&scrq->used, 0); scrq->cur = 0; rc = h_reg_sub_crq(adapter->vdev->unit_address, scrq->msg_token, @@ -2574,7 +2624,7 @@ static int ibmvnic_complete_tx(struct ibmvnic_adapter *adapter, union sub_crq *next; int index; int i, j; - u8 first; + u8 *first; restart_loop: while (pending_scrq(adapter, scrq)) { @@ -2605,11 +2655,12 @@ restart_loop: txbuff->data_dma[j] = 0; } /* if sub_crq was sent indirectly */ - first = txbuff->indir_arr[0].generic.first; - if (first == IBMVNIC_CRQ_CMD) { + first = &txbuff->indir_arr[0].generic.first; + if (*first == IBMVNIC_CRQ_CMD) { dma_unmap_single(dev, txbuff->indir_dma, sizeof(txbuff->indir_arr), DMA_TO_DEVICE); + *first = 0; } if (txbuff->last_frag) { @@ -3882,9 +3933,9 @@ static int handle_login_rsp(union ibmvnic_crq *login_rsp_crq, int i; dma_unmap_single(dev, adapter->login_buf_token, adapter->login_buf_sz, - DMA_BIDIRECTIONAL); + DMA_TO_DEVICE); dma_unmap_single(dev, adapter->login_rsp_buf_token, - adapter->login_rsp_buf_sz, DMA_BIDIRECTIONAL); + adapter->login_rsp_buf_sz, DMA_FROM_DEVICE); /* If the number of queues requested can't be allocated by the * server, the login response will return with code 1. We will need @@ -4144,7 +4195,9 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq, case IBMVNIC_CRQ_INIT: dev_info(dev, "Partner initialized\n"); adapter->from_passive_init = true; + adapter->failover_pending = false; complete(&adapter->init_done); + ibmvnic_reset(adapter, VNIC_RESET_FAILOVER); break; case IBMVNIC_CRQ_INIT_COMPLETE: dev_info(dev, "Partner initialization complete\n"); @@ -4161,7 +4214,7 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq, ibmvnic_reset(adapter, VNIC_RESET_MOBILITY); } else if (gen_crq->cmd == IBMVNIC_DEVICE_FAILOVER) { dev_info(dev, "Backing device failover detected\n"); - ibmvnic_reset(adapter, VNIC_RESET_FAILOVER); + adapter->failover_pending = true; } else { /* The adapter lost the connection */ dev_err(dev, "Virtual Adapter failed (rc=%d)\n", @@ -4461,19 +4514,6 @@ static int ibmvnic_init(struct ibmvnic_adapter *adapter) u64 old_num_rx_queues, old_num_tx_queues; int rc; - if (adapter->resetting && !adapter->wait_for_reset) { - rc = ibmvnic_reset_crq(adapter); - if (!rc) - rc = vio_enable_interrupts(adapter->vdev); - } else { - rc = init_crq_queue(adapter); - } - - if (rc) { - dev_err(dev, "Couldn't initialize crq. rc=%d\n", rc); - return rc; - } - adapter->from_passive_init = false; old_num_rx_queues = adapter->req_rx_queues; @@ -4498,7 +4538,8 @@ static int ibmvnic_init(struct ibmvnic_adapter *adapter) return -1; } - if (adapter->resetting && !adapter->wait_for_reset) { + if (adapter->resetting && !adapter->wait_for_reset && + adapter->reset_reason != VNIC_RESET_MOBILITY) { if (adapter->req_rx_queues != old_num_rx_queues || adapter->req_tx_queues != old_num_tx_queues) { release_sub_crqs(adapter, 0); @@ -4586,6 +4627,13 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id) adapter->mac_change_pending = false; do { + rc = init_crq_queue(adapter); + if (rc) { + dev_err(&dev->dev, "Couldn't initialize crq. rc=%d\n", + rc); + goto ibmvnic_init_fail; + } + rc = ibmvnic_init(adapter); if (rc && rc != EAGAIN) goto ibmvnic_init_fail; |