mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-21 21:34:58 +08:00
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: Satanand Burla <satananda.burla@cavium.com> Signed-off-by: Felix Manlunas <felix.manlunas@cavium.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
3426bd7277
commit
031d4f1210
@ -43,6 +43,8 @@ struct octeon_cn23xx_pf {
|
|||||||
struct octeon_config *conf;
|
struct octeon_config *conf;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define CN23XX_SLI_DEF_BP 0x40
|
||||||
|
|
||||||
int setup_cn23xx_octeon_pf_device(struct octeon_device *oct);
|
int setup_cn23xx_octeon_pf_device(struct octeon_device *oct);
|
||||||
|
|
||||||
int validate_cn23xx_pf_config_info(struct octeon_device *oct,
|
int validate_cn23xx_pf_config_info(struct octeon_device *oct,
|
||||||
|
@ -26,6 +26,9 @@
|
|||||||
#include "octeon_main.h"
|
#include "octeon_main.h"
|
||||||
#include "octeon_network.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)
|
int liquidio_set_feature(struct net_device *netdev, int cmd, u16 param1)
|
||||||
{
|
{
|
||||||
struct lio *lio = GET_LIO(netdev);
|
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
|
* 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1673,6 +1673,8 @@ static void liquidio_destroy_nic_device(struct octeon_device *oct, int ifidx)
|
|||||||
|
|
||||||
cleanup_link_status_change_wq(netdev);
|
cleanup_link_status_change_wq(netdev);
|
||||||
|
|
||||||
|
cleanup_rx_oom_poll_fn(netdev);
|
||||||
|
|
||||||
delete_glists(lio);
|
delete_glists(lio);
|
||||||
|
|
||||||
free_netdev(netdev);
|
free_netdev(netdev);
|
||||||
@ -4147,6 +4149,9 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
|
|||||||
if (setup_link_status_change_wq(netdev))
|
if (setup_link_status_change_wq(netdev))
|
||||||
goto setup_nic_dev_fail;
|
goto setup_nic_dev_fail;
|
||||||
|
|
||||||
|
if (setup_rx_oom_poll_fn(netdev))
|
||||||
|
goto setup_nic_dev_fail;
|
||||||
|
|
||||||
/* Register the network device with the OS */
|
/* Register the network device with the OS */
|
||||||
if (register_netdev(netdev)) {
|
if (register_netdev(netdev)) {
|
||||||
dev_err(&octeon_dev->pci_dev->dev, "Device registration failed\n");
|
dev_err(&octeon_dev->pci_dev->dev, "Device registration failed\n");
|
||||||
|
@ -1155,6 +1155,8 @@ static void liquidio_destroy_nic_device(struct octeon_device *oct, int ifidx)
|
|||||||
if (atomic_read(&lio->ifstate) & LIO_IFSTATE_REGISTERED)
|
if (atomic_read(&lio->ifstate) & LIO_IFSTATE_REGISTERED)
|
||||||
unregister_netdev(netdev);
|
unregister_netdev(netdev);
|
||||||
|
|
||||||
|
cleanup_rx_oom_poll_fn(netdev);
|
||||||
|
|
||||||
cleanup_link_status_change_wq(netdev);
|
cleanup_link_status_change_wq(netdev);
|
||||||
|
|
||||||
delete_glists(lio);
|
delete_glists(lio);
|
||||||
@ -2995,6 +2997,9 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
|
|||||||
if (setup_link_status_change_wq(netdev))
|
if (setup_link_status_change_wq(netdev))
|
||||||
goto setup_nic_dev_fail;
|
goto setup_nic_dev_fail;
|
||||||
|
|
||||||
|
if (setup_rx_oom_poll_fn(netdev))
|
||||||
|
goto setup_nic_dev_fail;
|
||||||
|
|
||||||
/* Register the network device with the OS */
|
/* Register the network device with the OS */
|
||||||
if (register_netdev(netdev)) {
|
if (register_netdev(netdev)) {
|
||||||
dev_err(&octeon_dev->pci_dev->dev, "Device registration failed\n");
|
dev_err(&octeon_dev->pci_dev->dev, "Device registration failed\n");
|
||||||
|
@ -513,6 +513,32 @@ octeon_droq_refill(struct octeon_device *octeon_dev, struct octeon_droq *droq)
|
|||||||
return desc_refilled;
|
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
|
static inline u32
|
||||||
octeon_droq_get_bufcount(u32 buf_size, u32 total_len)
|
octeon_droq_get_bufcount(u32 buf_size, u32 total_len)
|
||||||
{
|
{
|
||||||
|
@ -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 octeon_process_droq_poll_cmd(struct octeon_device *oct, u32 q_no,
|
||||||
int cmd, u32 arg);
|
int cmd, u32 arg);
|
||||||
|
|
||||||
|
void octeon_droq_check_oom(struct octeon_droq *droq);
|
||||||
|
|
||||||
#endif /*__OCTEON_DROQ_H__ */
|
#endif /*__OCTEON_DROQ_H__ */
|
||||||
|
@ -129,6 +129,9 @@ struct lio {
|
|||||||
/* work queue for txq status */
|
/* work queue for txq status */
|
||||||
struct cavium_wq txq_status_wq;
|
struct cavium_wq txq_status_wq;
|
||||||
|
|
||||||
|
/* work queue for rxq oom status */
|
||||||
|
struct cavium_wq rxq_status_wq;
|
||||||
|
|
||||||
/* work queue for link status */
|
/* work queue for link status */
|
||||||
struct cavium_wq link_status_wq;
|
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 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
|
* \brief Link control command completion callback
|
||||||
* @param nctrl_ptr pointer to control packet structure
|
* @param nctrl_ptr pointer to control packet structure
|
||||||
|
Loading…
Reference in New Issue
Block a user