Skip to content

Commit

Permalink
liquidio: allocate RX buffers in OOM conditions in PF and VF
Browse files Browse the repository at this point in the history
Add workqueue that is periodically run to try to allocate RX buffers in OOM
conditions in PF and VF.

Signed-off-by: Satanand Burla <satananda.burla@cavium.com>
Signed-off-by: Felix Manlunas <felix.manlunas@cavium.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Satanand Burla authored and David S. Miller committed Mar 23, 2017
1 parent 3426bd7 commit 031d4f1
Showing 7 changed files with 103 additions and 0 deletions.
2 changes: 2 additions & 0 deletions drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.h
Original file line number Diff line number Diff line change
@@ -43,6 +43,8 @@ struct octeon_cn23xx_pf {
struct octeon_config *conf;
};

#define CN23XX_SLI_DEF_BP 0x40

int setup_cn23xx_octeon_pf_device(struct octeon_device *oct);

int validate_cn23xx_pf_config_info(struct octeon_device *oct,
56 changes: 56 additions & 0 deletions drivers/net/ethernet/cavium/liquidio/lio_core.c
Original file line number Diff line number Diff line change
@@ -26,6 +26,9 @@
#include "octeon_main.h"
#include "octeon_network.h"

/* OOM task polling interval */
#define LIO_OOM_POLL_INTERVAL_MS 250

int liquidio_set_feature(struct net_device *netdev, int cmd, u16 param1)
{
struct lio *lio = GET_LIO(netdev);
@@ -293,3 +296,56 @@ void octeon_pf_changed_vf_macaddr(struct octeon_device *oct, u8 *mac)
* the PF did that already
*/
}

static void octnet_poll_check_rxq_oom_status(struct work_struct *work)
{
struct cavium_wk *wk = (struct cavium_wk *)work;
struct lio *lio = (struct lio *)wk->ctxptr;
struct octeon_device *oct = lio->oct_dev;
struct octeon_droq *droq;
int q, q_no = 0;

if (ifstate_check(lio, LIO_IFSTATE_RUNNING)) {
for (q = 0; q < lio->linfo.num_rxpciq; q++) {
q_no = lio->linfo.rxpciq[q].s.q_no;
droq = oct->droq[q_no];
if (!droq)
continue;
octeon_droq_check_oom(droq);
}
}
queue_delayed_work(lio->rxq_status_wq.wq,
&lio->rxq_status_wq.wk.work,
msecs_to_jiffies(LIO_OOM_POLL_INTERVAL_MS));
}

int setup_rx_oom_poll_fn(struct net_device *netdev)
{
struct lio *lio = GET_LIO(netdev);
struct octeon_device *oct = lio->oct_dev;

lio->rxq_status_wq.wq = alloc_workqueue("rxq-oom-status",
WQ_MEM_RECLAIM, 0);
if (!lio->rxq_status_wq.wq) {
dev_err(&oct->pci_dev->dev, "unable to create cavium rxq oom status wq\n");
return -ENOMEM;
}
INIT_DELAYED_WORK(&lio->rxq_status_wq.wk.work,
octnet_poll_check_rxq_oom_status);
lio->rxq_status_wq.wk.ctxptr = lio;
queue_delayed_work(lio->rxq_status_wq.wq,
&lio->rxq_status_wq.wk.work,
msecs_to_jiffies(LIO_OOM_POLL_INTERVAL_MS));
return 0;
}

void cleanup_rx_oom_poll_fn(struct net_device *netdev)
{
struct lio *lio = GET_LIO(netdev);

if (lio->rxq_status_wq.wq) {
cancel_delayed_work_sync(&lio->rxq_status_wq.wk.work);
flush_workqueue(lio->rxq_status_wq.wq);
destroy_workqueue(lio->rxq_status_wq.wq);
}
}
5 changes: 5 additions & 0 deletions drivers/net/ethernet/cavium/liquidio/lio_main.c
Original file line number Diff line number Diff line change
@@ -1673,6 +1673,8 @@ static void liquidio_destroy_nic_device(struct octeon_device *oct, int ifidx)

cleanup_link_status_change_wq(netdev);

cleanup_rx_oom_poll_fn(netdev);

delete_glists(lio);

free_netdev(netdev);
@@ -4147,6 +4149,9 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
if (setup_link_status_change_wq(netdev))
goto setup_nic_dev_fail;

if (setup_rx_oom_poll_fn(netdev))
goto setup_nic_dev_fail;

/* Register the network device with the OS */
if (register_netdev(netdev)) {
dev_err(&octeon_dev->pci_dev->dev, "Device registration failed\n");
5 changes: 5 additions & 0 deletions drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
Original file line number Diff line number Diff line change
@@ -1155,6 +1155,8 @@ static void liquidio_destroy_nic_device(struct octeon_device *oct, int ifidx)
if (atomic_read(&lio->ifstate) & LIO_IFSTATE_REGISTERED)
unregister_netdev(netdev);

cleanup_rx_oom_poll_fn(netdev);

cleanup_link_status_change_wq(netdev);

delete_glists(lio);
@@ -2995,6 +2997,9 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
if (setup_link_status_change_wq(netdev))
goto setup_nic_dev_fail;

if (setup_rx_oom_poll_fn(netdev))
goto setup_nic_dev_fail;

/* Register the network device with the OS */
if (register_netdev(netdev)) {
dev_err(&octeon_dev->pci_dev->dev, "Device registration failed\n");
26 changes: 26 additions & 0 deletions drivers/net/ethernet/cavium/liquidio/octeon_droq.c
Original file line number Diff line number Diff line change
@@ -513,6 +513,32 @@ octeon_droq_refill(struct octeon_device *octeon_dev, struct octeon_droq *droq)
return desc_refilled;
}

/** check if we can allocate packets to get out of oom.
* @param droq - Droq being checked.
* @return does not return anything
*/
void octeon_droq_check_oom(struct octeon_droq *droq)
{
int desc_refilled;
struct octeon_device *oct = droq->oct_dev;

if (readl(droq->pkts_credit_reg) <= CN23XX_SLI_DEF_BP) {
spin_lock_bh(&droq->lock);
desc_refilled = octeon_droq_refill(oct, droq);
if (desc_refilled) {
/* Flush the droq descriptor data to memory to be sure
* that when we update the credits the data in memory
* is accurate.
*/
wmb();
writel(desc_refilled, droq->pkts_credit_reg);
/* make sure mmio write completes */
mmiowb();
}
spin_unlock_bh(&droq->lock);
}
}

static inline u32
octeon_droq_get_bufcount(u32 buf_size, u32 total_len)
{
2 changes: 2 additions & 0 deletions drivers/net/ethernet/cavium/liquidio/octeon_droq.h
Original file line number Diff line number Diff line change
@@ -426,4 +426,6 @@ int octeon_droq_process_packets(struct octeon_device *oct,
int octeon_process_droq_poll_cmd(struct octeon_device *oct, u32 q_no,
int cmd, u32 arg);

void octeon_droq_check_oom(struct octeon_droq *droq);

#endif /*__OCTEON_DROQ_H__ */
7 changes: 7 additions & 0 deletions drivers/net/ethernet/cavium/liquidio/octeon_network.h
Original file line number Diff line number Diff line change
@@ -129,6 +129,9 @@ struct lio {
/* work queue for txq status */
struct cavium_wq txq_status_wq;

/* work queue for rxq oom status */
struct cavium_wq rxq_status_wq;

/* work queue for link status */
struct cavium_wq link_status_wq;

@@ -152,6 +155,10 @@ struct lio {
*/
int liquidio_set_feature(struct net_device *netdev, int cmd, u16 param1);

int setup_rx_oom_poll_fn(struct net_device *netdev);

void cleanup_rx_oom_poll_fn(struct net_device *netdev);

/**
* \brief Link control command completion callback
* @param nctrl_ptr pointer to control packet structure

0 comments on commit 031d4f1

Please sign in to comment.