Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 031d4f12 authored by Satanand Burla's avatar Satanand Burla Committed by David S. Miller
Browse files

liquidio: allocate RX buffers in OOM conditions in PF and VF



Add workqueue that is periodically run to try to allocate RX buffers in OOM
conditions in PF and VF.

Signed-off-by: default avatarSatanand Burla <satananda.burla@cavium.com>
Signed-off-by: default avatarFelix Manlunas <felix.manlunas@cavium.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3426bd72
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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 −0
Original line number Diff line number Diff line
@@ -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 −0
Original line number Diff line number Diff line
@@ -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 −0
Original line number Diff line number Diff line
@@ -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 −0
Original line number Diff line number Diff line
@@ -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)
{
Loading