Skip to content

Commit

Permalink
Merge branch 'ibmvnic-reset-behavior-fixes'
Browse files Browse the repository at this point in the history
John Allen says:

====================
ibmvnic: Reset behavior fixes

This patchset fixes a number of issues related to ibmvnic reset uncovered
from testing new Power9 machines with Everglades adapters and the new
functionality to change mtu and other parameters in the driver.

Changes since v1:
-In patch 1/3, added the line to free the long term buffers before
allocating a new one. This change inadvertently uncovered the problem
that the number of queues can change after a failover as well. To fix
this, we check whether or not the number of queues has changed in
do_reset and if they have, we do a full release and init of the queues.
-In patch 1/3, added variables to the adapter struct to track how
many rx/tx pools have actually been allocated and modify the release
pools routines to use these values rather than the possibly incorrect
req_rx/tx_queues values.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Jan 22, 2018
2 parents b589513 + 69d08dc commit 18b0aff
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 15 deletions.
73 changes: 58 additions & 15 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 @@ -860,7 +881,7 @@ static int ibmvnic_get_vpd(struct ibmvnic_adapter *adapter)
if (adapter->vpd->buff)
len = adapter->vpd->len;

reinit_completion(&adapter->fw_done);
init_completion(&adapter->fw_done);
crq.get_vpd_size.first = IBMVNIC_CRQ_CMD;
crq.get_vpd_size.cmd = GET_VPD_SIZE;
ibmvnic_send_crq(adapter, &crq);
Expand Down Expand Up @@ -922,6 +943,13 @@ static int init_resources(struct ibmvnic_adapter *adapter)
if (!adapter->vpd)
return -ENOMEM;

/* Vital Product Data (VPD) */
rc = ibmvnic_get_vpd(adapter);
if (rc) {
netdev_err(netdev, "failed to initialize Vital Product Data (VPD)\n");
return rc;
}

adapter->map_id = 1;
adapter->napi = kcalloc(adapter->req_rx_queues,
sizeof(struct napi_struct), GFP_KERNEL);
Expand Down Expand Up @@ -995,7 +1023,7 @@ static int __ibmvnic_open(struct net_device *netdev)
static int ibmvnic_open(struct net_device *netdev)
{
struct ibmvnic_adapter *adapter = netdev_priv(netdev);
int rc, vpd;
int rc;

mutex_lock(&adapter->reset_lock);

Expand All @@ -1018,11 +1046,6 @@ static int ibmvnic_open(struct net_device *netdev)
rc = __ibmvnic_open(netdev);
netif_carrier_on(netdev);

/* Vital Product Data (VPD) */
vpd = ibmvnic_get_vpd(adapter);
if (vpd)
netdev_err(netdev, "failed to initialize Vital Product Data (VPD)\n");

mutex_unlock(&adapter->reset_lock);

return rc;
Expand Down Expand Up @@ -1548,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;

Expand All @@ -1557,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)
Expand Down Expand Up @@ -1601,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)
Expand Down Expand Up @@ -3592,7 +3625,17 @@ static void handle_request_cap_rsp(union ibmvnic_crq *crq,
*req_value,
(long int)be64_to_cpu(crq->request_capability_rsp.
number), name);
*req_value = be64_to_cpu(crq->request_capability_rsp.number);

if (be16_to_cpu(crq->request_capability_rsp.capability) ==
REQ_MTU) {
pr_err("mtu of %llu is not supported. Reverting.\n",
*req_value);
*req_value = adapter->fallback.mtu;
} else {
*req_value =
be64_to_cpu(crq->request_capability_rsp.number);
}

ibmvnic_send_req_caps(adapter, 1);
return;
default:
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 18b0aff

Please sign in to comment.