Skip to content

Commit

Permalink
Merge branch 'liquidio-Removed-droq-lock-from-Rx-path'
Browse files Browse the repository at this point in the history
Intiyaz Basha says:

====================
liquidio: Removed droq lock from Rx path

Series of patches for removing droq lock from Rx Path.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Sep 12, 2018
2 parents aad06d1 + 8bf6edc commit 82bcee4
Show file tree
Hide file tree
Showing 9 changed files with 140 additions and 109 deletions.
77 changes: 47 additions & 30 deletions drivers/net/ethernet/cavium/liquidio/lio_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -425,56 +425,73 @@ void octeon_pf_changed_vf_macaddr(struct octeon_device *oct, u8 *mac)
*/
}

void octeon_schedule_rxq_oom_work(struct octeon_device *oct,
struct octeon_droq *droq)
{
struct net_device *netdev = oct->props[0].netdev;
struct lio *lio = GET_LIO(netdev);
struct cavium_wq *wq = &lio->rxq_status_wq[droq->q_no];

queue_delayed_work(wq->wq, &wq->wk.work,
msecs_to_jiffies(LIO_OOM_POLL_INTERVAL_MS));
}

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;
int q_no = wk->ctxul;
struct octeon_droq *droq = oct->droq[q_no];

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));
if (!ifstate_check(lio, LIO_IFSTATE_RUNNING) || !droq)
return;

if (octeon_retry_droq_refill(droq))
octeon_schedule_rxq_oom_work(oct, droq);
}

int setup_rx_oom_poll_fn(struct net_device *netdev)
{
struct lio *lio = GET_LIO(netdev);
struct octeon_device *oct = lio->oct_dev;
struct cavium_wq *wq;
int q, q_no;

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;
for (q = 0; q < oct->num_oqs; q++) {
q_no = lio->linfo.rxpciq[q].s.q_no;
wq = &lio->rxq_status_wq[q_no];
wq->wq = alloc_workqueue("rxq-oom-status",
WQ_MEM_RECLAIM, 0);
if (!wq->wq) {
dev_err(&oct->pci_dev->dev, "unable to create cavium rxq oom status wq\n");
return -ENOMEM;
}

INIT_DELAYED_WORK(&wq->wk.work,
octnet_poll_check_rxq_oom_status);
wq->wk.ctxptr = lio;
wq->wk.ctxul = q_no;
}
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);
struct octeon_device *oct = lio->oct_dev;
struct cavium_wq *wq;
int q_no;

for (q_no = 0; q_no < oct->num_oqs; q_no++) {
wq = &lio->rxq_status_wq[q_no];
if (wq->wq) {
cancel_delayed_work_sync(&wq->wk.work);
flush_workqueue(wq->wq);
destroy_workqueue(wq->wq);
wq->wq = NULL;
}
}
}

Expand Down
7 changes: 7 additions & 0 deletions drivers/net/ethernet/cavium/liquidio/lio_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -1115,6 +1115,8 @@ static int lio_reset_queues(struct net_device *netdev, uint32_t num_qs)
* steps like updating sriov_info for the octeon device need to be done.
*/
if (queue_count_update) {
cleanup_rx_oom_poll_fn(netdev);

lio_delete_glists(lio);

/* Delete mbox for PF which is SRIOV disabled because sriov_info
Expand Down Expand Up @@ -1214,6 +1216,11 @@ static int lio_reset_queues(struct net_device *netdev, uint32_t num_qs)
return -1;
}

if (setup_rx_oom_poll_fn(netdev)) {
dev_err(&oct->pci_dev->dev, "lio_setup_rx_oom_poll_fn failed\n");
return 1;
}

/* Send firmware the information about new number of queues
* if the interface is a VF or a PF that is SRIOV enabled.
*/
Expand Down
14 changes: 13 additions & 1 deletion drivers/net/ethernet/cavium/liquidio/lio_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1239,8 +1239,10 @@ static void send_rx_ctrl_cmd(struct lio *lio, int start_stop)
static void liquidio_destroy_nic_device(struct octeon_device *oct, int ifidx)
{
struct net_device *netdev = oct->props[ifidx].netdev;
struct lio *lio;
struct octeon_device_priv *oct_priv =
(struct octeon_device_priv *)oct->priv;
struct napi_struct *napi, *n;
struct lio *lio;

if (!netdev) {
dev_err(&oct->pci_dev->dev, "%s No netdevice ptr for index %d\n",
Expand Down Expand Up @@ -1269,6 +1271,8 @@ static void liquidio_destroy_nic_device(struct octeon_device *oct, int ifidx)
list_for_each_entry_safe(napi, n, &netdev->napi_list, dev_list)
netif_napi_del(napi);

tasklet_enable(&oct_priv->droq_tasklet);

if (atomic_read(&lio->ifstate) & LIO_IFSTATE_REGISTERED)
unregister_netdev(netdev);

Expand Down Expand Up @@ -1805,9 +1809,13 @@ static int liquidio_open(struct net_device *netdev)
{
struct lio *lio = GET_LIO(netdev);
struct octeon_device *oct = lio->oct_dev;
struct octeon_device_priv *oct_priv =
(struct octeon_device_priv *)oct->priv;
struct napi_struct *napi, *n;

if (oct->props[lio->ifidx].napi_enabled == 0) {
tasklet_disable(&oct_priv->droq_tasklet);

list_for_each_entry_safe(napi, n, &netdev->napi_list, dev_list)
napi_enable(napi);

Expand Down Expand Up @@ -1861,6 +1869,8 @@ static int liquidio_stop(struct net_device *netdev)
{
struct lio *lio = GET_LIO(netdev);
struct octeon_device *oct = lio->oct_dev;
struct octeon_device_priv *oct_priv =
(struct octeon_device_priv *)oct->priv;
struct napi_struct *napi, *n;

ifstate_reset(lio, LIO_IFSTATE_RUNNING);
Expand Down Expand Up @@ -1907,6 +1917,8 @@ static int liquidio_stop(struct net_device *netdev)

if (OCTEON_CN23XX_PF(oct))
oct->droq[0]->ops.poll_mode = 0;

tasklet_enable(&oct_priv->droq_tasklet);
}

dev_info(&oct->pci_dev->dev, "%s interface is stopped\n", netdev->name);
Expand Down
16 changes: 16 additions & 0 deletions drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,8 @@ static void octeon_pci_flr(struct octeon_device *oct)
*/
static void octeon_destroy_resources(struct octeon_device *oct)
{
struct octeon_device_priv *oct_priv =
(struct octeon_device_priv *)oct->priv;
struct msix_entry *msix_entries;
int i;

Expand Down Expand Up @@ -587,6 +589,8 @@ static void octeon_destroy_resources(struct octeon_device *oct)
/* Nothing to be done here either */
break;
}

tasklet_kill(&oct_priv->droq_tasklet);
}

/**
Expand Down Expand Up @@ -652,6 +656,8 @@ static void send_rx_ctrl_cmd(struct lio *lio, int start_stop)
static void liquidio_destroy_nic_device(struct octeon_device *oct, int ifidx)
{
struct net_device *netdev = oct->props[ifidx].netdev;
struct octeon_device_priv *oct_priv =
(struct octeon_device_priv *)oct->priv;
struct napi_struct *napi, *n;
struct lio *lio;

Expand Down Expand Up @@ -681,6 +687,8 @@ static void liquidio_destroy_nic_device(struct octeon_device *oct, int ifidx)
list_for_each_entry_safe(napi, n, &netdev->napi_list, dev_list)
netif_napi_del(napi);

tasklet_enable(&oct_priv->droq_tasklet);

if (atomic_read(&lio->ifstate) & LIO_IFSTATE_REGISTERED)
unregister_netdev(netdev);

Expand Down Expand Up @@ -898,9 +906,13 @@ static int liquidio_open(struct net_device *netdev)
{
struct lio *lio = GET_LIO(netdev);
struct octeon_device *oct = lio->oct_dev;
struct octeon_device_priv *oct_priv =
(struct octeon_device_priv *)oct->priv;
struct napi_struct *napi, *n;

if (!oct->props[lio->ifidx].napi_enabled) {
tasklet_disable(&oct_priv->droq_tasklet);

list_for_each_entry_safe(napi, n, &netdev->napi_list, dev_list)
napi_enable(napi);

Expand Down Expand Up @@ -938,6 +950,8 @@ static int liquidio_stop(struct net_device *netdev)
{
struct lio *lio = GET_LIO(netdev);
struct octeon_device *oct = lio->oct_dev;
struct octeon_device_priv *oct_priv =
(struct octeon_device_priv *)oct->priv;
struct napi_struct *napi, *n;

/* tell Octeon to stop forwarding packets to host */
Expand Down Expand Up @@ -967,6 +981,8 @@ static int liquidio_stop(struct net_device *netdev)
oct->props[lio->ifidx].napi_enabled = 0;

oct->droq[0]->ops.poll_mode = 0;

tasklet_enable(&oct_priv->droq_tasklet);
}

cancel_delayed_work_sync(&lio->stats_wk.work);
Expand Down
4 changes: 0 additions & 4 deletions drivers/net/ethernet/cavium/liquidio/octeon_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -1440,12 +1440,8 @@ void lio_enable_irq(struct octeon_droq *droq, struct octeon_instr_queue *iq)
/* the whole thing needs to be atomic, ideally */
if (droq) {
pkts_pend = (u32)atomic_read(&droq->pkts_pending);
spin_lock_bh(&droq->lock);
writel(droq->pkt_count - pkts_pend, droq->pkts_sent_reg);
droq->pkt_count = pkts_pend;
/* this write needs to be flushed before we release the lock */
mmiowb();
spin_unlock_bh(&droq->lock);
oct = droq->oct_dev;
}
if (iq) {
Expand Down
Loading

0 comments on commit 82bcee4

Please sign in to comment.