diff options
author | Sathya Perla <sathyap@serverengines.com> | 2009-03-20 09:56:20 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-03-20 09:56:20 +0300 |
commit | ea1dae11e0baca5d633207fe50fc3cd30a5d68ee (patch) | |
tree | e87606f10432ab66dd5d486939f49e1bce299f61 | |
parent | 170ebf85160dd128e1c4206cc197cce7d1424705 (diff) | |
download | linux-ea1dae11e0baca5d633207fe50fc3cd30a5d68ee.tar.xz |
be2net: replenish when posting to rx-queue is starved in out of mem conditions
This is a patch to replenish the rx-queue when it is in a starved
state (due to out-of-mem conditions)
Signed-off-by: Sathya Perla <sathyap@serverengines.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/benet/be.h | 1 | ||||
-rw-r--r-- | drivers/net/benet/be_main.c | 50 |
2 files changed, 30 insertions, 21 deletions
diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index 63d593d53153..f327be57ca96 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -194,6 +194,7 @@ struct be_adapter { struct be_eq_obj rx_eq; struct be_rx_obj rx_obj; u32 big_page_size; /* Compounded page size shared by rx wrbs */ + bool rx_post_starved; /* Zero rx frags have been posted to BE */ struct vlan_group *vlan_grp; u16 num_vlans; diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 897a63de5bdb..80fe1e055d91 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -273,26 +273,6 @@ static void be_rx_eqd_update(struct be_adapter *adapter) rx_eq->cur_eqd = eqd; } -static void be_worker(struct work_struct *work) -{ - struct be_adapter *adapter = - container_of(work, struct be_adapter, work.work); - int status; - - /* Check link */ - be_link_status_update(adapter); - - /* Get Stats */ - status = be_cmd_get_stats(&adapter->ctrl, &adapter->stats.cmd); - if (!status) - netdev_stats_update(adapter); - - /* Set EQ delay */ - be_rx_eqd_update(adapter); - - schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); -} - static struct net_device_stats *be_get_stats(struct net_device *dev) { struct be_adapter *adapter = netdev_priv(dev); @@ -900,8 +880,11 @@ static void be_post_rx_frags(struct be_adapter *adapter) page_info->last_page_user = true; if (posted) { - be_rxq_notify(&adapter->ctrl, rxq->id, posted); atomic_add(posted, &rxq->used); + be_rxq_notify(&adapter->ctrl, rxq->id, posted); + } else if (atomic_read(&rxq->used) == 0) { + /* Let be_worker replenish when memory is available */ + adapter->rx_post_starved = true; } return; @@ -1305,6 +1288,31 @@ int be_poll_tx(struct napi_struct *napi, int budget) return 1; } +static void be_worker(struct work_struct *work) +{ + struct be_adapter *adapter = + container_of(work, struct be_adapter, work.work); + int status; + + /* Check link */ + be_link_status_update(adapter); + + /* Get Stats */ + status = be_cmd_get_stats(&adapter->ctrl, &adapter->stats.cmd); + if (!status) + netdev_stats_update(adapter); + + /* Set EQ delay */ + be_rx_eqd_update(adapter); + + if (adapter->rx_post_starved) { + adapter->rx_post_starved = false; + be_post_rx_frags(adapter); + } + + schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); +} + static void be_msix_enable(struct be_adapter *adapter) { int i, status; |