Skip to content

Commit

Permalink
ibmvnic: Modify buffer size and number of queues on failover
Browse files Browse the repository at this point in the history
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 <jallen@linux.vnet.ibm.com>
Reviewed-by: Nathan Fontenot <nfont@linux.vnet.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
John Allen authored and David S. Miller committed Jan 22, 2018
1 parent b589513 commit 896d869
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 7 deletions.
45 changes: 38 additions & 7 deletions drivers/net/ethernet/ibm/ibmvnic.c
Original file line number Diff line number Diff line change
Expand Up @@ -410,14 +410,28 @@ 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++) {
rx_pool = &adapter->rx_pool[i];

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;

Expand All @@ -439,14 +453,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);
Expand All @@ -469,6 +481,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)
Expand All @@ -493,6 +506,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];

Expand Down Expand Up @@ -536,6 +551,8 @@ static int init_rx_pools(struct net_device *netdev)
rx_pool->next_free = 0;
}

adapter->num_active_rx_pools = rxadd_subcrqs;

return 0;
}

Expand Down Expand Up @@ -586,13 +603,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);
Expand All @@ -603,6 +619,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)
Expand All @@ -619,6 +636,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];

Expand Down Expand Up @@ -666,6 +685,8 @@ static int init_tx_pools(struct net_device *netdev)
tx_pool->producer_index = 0;
}

adapter->num_active_tx_pools = tx_subcrqs;

return 0;
}

Expand Down Expand Up @@ -1548,6 +1569,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;

Expand All @@ -1557,6 +1579,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)
Expand Down Expand Up @@ -1601,6 +1626,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)
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/ibm/ibmvnic.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 896d869

Please sign in to comment.