On 01/18/2018 04:26 PM, John Allen wrote:
> Using newer backing devices can cause the required padding at the end of
> buffer as well as the number of queues to change after a failover.
> Since we currently assume that these values never change, after a
> failover to a backing device with different capabilities, we can get
> errors from the vnic server, attempt to free long term buffers that are
> no longer there, or not free long term buffers that should be freed.
> 
> This patch resolves the issue by checking whether any of these values
> change, and if so perform the necessary re-allocations.
> 
> Signed-off-by: John Allen <jal...@linux.vnet.ibm.com>

Reviewed-by: Nathan Fontenot <nf...@linux.vnet.ibm.com>

> ---
> v2: Added the line to free the long term buff in reset rx pools which
> caused me to hit a couple of other problems. On a failover, the number
> of queues can also change which doesn't get updated in the current
> reset code. Added some extra logic in do reset to check for changed
> number of queues and added some logic to release pools to ensure that
> it is only releasing pools that were allocated in the init pools
> routines.
> ---
> diff --git a/drivers/net/ethernet/ibm/ibmvnic.c 
> b/drivers/net/ethernet/ibm/ibmvnic.c
> index 461014b7ccdd..12559c63c226 100644
> --- a/drivers/net/ethernet/ibm/ibmvnic.c
> +++ b/drivers/net/ethernet/ibm/ibmvnic.c
> @@ -411,6 +411,10 @@ static int reset_rx_pools(struct ibmvnic_adapter 
> *adapter)
>       struct ibmvnic_rx_pool *rx_pool;
>       int rx_scrqs;
>       int i, j, rc;
> +     u64 *size_array;
> +
> +     size_array = (u64 *)((u8 *)(adapter->login_rsp_buf) +
> +             be32_to_cpu(adapter->login_rsp_buf->off_rxadd_buff_size));
> 
>       rx_scrqs = be32_to_cpu(adapter->login_rsp_buf->num_rxadd_subcrqs);
>       for (i = 0; i < rx_scrqs; i++) {
> @@ -418,7 +422,17 @@ static int reset_rx_pools(struct ibmvnic_adapter 
> *adapter)
> 
>               netdev_dbg(adapter->netdev, "Re-setting rx_pool[%d]\n", i);
> 
> -             rc = reset_long_term_buff(adapter, &rx_pool->long_term_buff);
> +             if (rx_pool->buff_size != be64_to_cpu(size_array[i])) {
> +                     free_long_term_buff(adapter, &rx_pool->long_term_buff);
> +                     rx_pool->buff_size = be64_to_cpu(size_array[i]);
> +                     alloc_long_term_buff(adapter, &rx_pool->long_term_buff,
> +                                          rx_pool->size *
> +                                          rx_pool->buff_size);
> +             } else {
> +                     rc = reset_long_term_buff(adapter,
> +                                               &rx_pool->long_term_buff);
> +             }
> +
>               if (rc)
>                       return rc;
> 
> @@ -440,14 +454,12 @@ static int reset_rx_pools(struct ibmvnic_adapter 
> *adapter)
>  static void release_rx_pools(struct ibmvnic_adapter *adapter)
>  {
>       struct ibmvnic_rx_pool *rx_pool;
> -     int rx_scrqs;
>       int i, j;
> 
>       if (!adapter->rx_pool)
>               return;
> 
> -     rx_scrqs = be32_to_cpu(adapter->login_rsp_buf->num_rxadd_subcrqs);
> -     for (i = 0; i < rx_scrqs; i++) {
> +     for (i = 0; i < adapter->num_active_rx_pools; i++) {
>               rx_pool = &adapter->rx_pool[i];
> 
>               netdev_dbg(adapter->netdev, "Releasing rx_pool[%d]\n", i);
> @@ -470,6 +482,7 @@ static void release_rx_pools(struct ibmvnic_adapter 
> *adapter)
> 
>       kfree(adapter->rx_pool);
>       adapter->rx_pool = NULL;
> +     adapter->num_active_rx_pools = 0;
>  }
> 
>  static int init_rx_pools(struct net_device *netdev)
> @@ -494,6 +507,8 @@ static int init_rx_pools(struct net_device *netdev)
>               return -1;
>       }
> 
> +     adapter->num_active_rx_pools = 0;
> +
>       for (i = 0; i < rxadd_subcrqs; i++) {
>               rx_pool = &adapter->rx_pool[i];
> 
> @@ -537,6 +552,8 @@ static int init_rx_pools(struct net_device *netdev)
>               rx_pool->next_free = 0;
>       }
> 
> +     adapter->num_active_rx_pools = rxadd_subcrqs;
> +
>       return 0;
>  }
> 
> @@ -587,13 +604,12 @@ static void release_vpd_data(struct ibmvnic_adapter 
> *adapter)
>  static void release_tx_pools(struct ibmvnic_adapter *adapter)
>  {
>       struct ibmvnic_tx_pool *tx_pool;
> -     int i, tx_scrqs;
> +     int i;
> 
>       if (!adapter->tx_pool)
>               return;
> 
> -     tx_scrqs = be32_to_cpu(adapter->login_rsp_buf->num_txsubm_subcrqs);
> -     for (i = 0; i < tx_scrqs; i++) {
> +     for (i = 0; i < adapter->num_active_tx_pools; i++) {
>               netdev_dbg(adapter->netdev, "Releasing tx_pool[%d]\n", i);
>               tx_pool = &adapter->tx_pool[i];
>               kfree(tx_pool->tx_buff);
> @@ -604,6 +620,7 @@ static void release_tx_pools(struct ibmvnic_adapter 
> *adapter)
> 
>       kfree(adapter->tx_pool);
>       adapter->tx_pool = NULL;
> +     adapter->num_active_tx_pools = 0;
>  }
> 
>  static int init_tx_pools(struct net_device *netdev)
> @@ -620,6 +637,8 @@ static int init_tx_pools(struct net_device *netdev)
>       if (!adapter->tx_pool)
>               return -1;
> 
> +     adapter->num_active_tx_pools = 0;
> +
>       for (i = 0; i < tx_subcrqs; i++) {
>               tx_pool = &adapter->tx_pool[i];
> 
> @@ -667,6 +686,8 @@ static int init_tx_pools(struct net_device *netdev)
>               tx_pool->producer_index = 0;
>       }
> 
> +     adapter->num_active_tx_pools = tx_subcrqs;
> +
>       return 0;
>  }
> 
> @@ -1550,6 +1571,7 @@ static int ibmvnic_set_mac(struct net_device *netdev, 
> void *p)
>  static int do_reset(struct ibmvnic_adapter *adapter,
>                   struct ibmvnic_rwi *rwi, u32 reset_state)
>  {
> +     u64 old_num_rx_queues, old_num_tx_queues;
>       struct net_device *netdev = adapter->netdev;
>       int i, rc;
> 
> @@ -1559,6 +1581,9 @@ static int do_reset(struct ibmvnic_adapter *adapter,
>       netif_carrier_off(netdev);
>       adapter->reset_reason = rwi->reset_reason;
> 
> +     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)
> @@ -1603,6 +1628,12 @@ static int do_reset(struct ibmvnic_adapter *adapter,
>                       rc = init_resources(adapter);
>                       if (rc)
>                               return rc;
> +             } else if (adapter->req_rx_queues != old_num_rx_queues ||
> +                        adapter->req_tx_queues != old_num_tx_queues) {
> +                     release_rx_pools(adapter);
> +                     release_tx_pools(adapter);
> +                     init_rx_pools(netdev);
> +                     init_tx_pools(netdev);
>               } else {
>                       rc = reset_tx_pools(adapter);
>                       if (rc)
> diff --git a/drivers/net/ethernet/ibm/ibmvnic.h 
> b/drivers/net/ethernet/ibm/ibmvnic.h
> index 2df79fdd800b..fe21a6e2ddae 100644
> --- a/drivers/net/ethernet/ibm/ibmvnic.h
> +++ b/drivers/net/ethernet/ibm/ibmvnic.h
> @@ -1091,6 +1091,8 @@ struct ibmvnic_adapter {
>       u64 opt_rxba_entries_per_subcrq;
>       __be64 tx_rx_desc_req;
>       u8 map_id;
> +     u64 num_active_rx_pools;
> +     u64 num_active_tx_pools;
> 
>       struct tasklet_struct tasklet;
>       enum vnic_state state;
> 

Reply via email to