Commit 49544935 authored by Igor Russkikh's avatar Igor Russkikh Committed by David S. Miller

net: aquantia: extract timer cb into work job

Service timer callback fetches statistics from FW and that may cause
a long delay in error cases. We also now need to use fw mutex
to prevent concurrent access to FW, thus - extract that logic
from timer callback into the job in the separate work queue.
Signed-off-by: default avatarNikita Danilov <ndanilov@aquantia.com>
Signed-off-by: default avatarIgor Russkikh <igor.russkikh@aquantia.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f5dce08a
...@@ -186,25 +186,34 @@ static irqreturn_t aq_linkstate_threaded_isr(int irq, void *private) ...@@ -186,25 +186,34 @@ static irqreturn_t aq_linkstate_threaded_isr(int irq, void *private)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static void aq_nic_service_timer_cb(struct timer_list *t) static void aq_nic_service_task(struct work_struct *work)
{ {
struct aq_nic_s *self = from_timer(self, t, service_timer); struct aq_nic_s *self = container_of(work, struct aq_nic_s,
int err = 0; service_task);
int err;
if (aq_utils_obj_test(&self->flags, AQ_NIC_FLAGS_IS_NOT_READY)) if (aq_utils_obj_test(&self->flags, AQ_NIC_FLAGS_IS_NOT_READY))
goto err_exit; return;
err = aq_nic_update_link_status(self); err = aq_nic_update_link_status(self);
if (err) if (err)
goto err_exit; return;
mutex_lock(&self->fwreq_mutex);
if (self->aq_fw_ops->update_stats) if (self->aq_fw_ops->update_stats)
self->aq_fw_ops->update_stats(self->aq_hw); self->aq_fw_ops->update_stats(self->aq_hw);
mutex_unlock(&self->fwreq_mutex);
aq_nic_update_ndev_stats(self); aq_nic_update_ndev_stats(self);
}
static void aq_nic_service_timer_cb(struct timer_list *t)
{
struct aq_nic_s *self = from_timer(self, t, service_timer);
err_exit:
mod_timer(&self->service_timer, jiffies + AQ_CFG_SERVICE_TIMER_INTERVAL); mod_timer(&self->service_timer, jiffies + AQ_CFG_SERVICE_TIMER_INTERVAL);
aq_ndev_schedule_work(&self->service_task);
} }
static void aq_nic_polling_timer_cb(struct timer_list *t) static void aq_nic_polling_timer_cb(struct timer_list *t)
...@@ -358,6 +367,9 @@ int aq_nic_start(struct aq_nic_s *self) ...@@ -358,6 +367,9 @@ int aq_nic_start(struct aq_nic_s *self)
err = aq_nic_update_interrupt_moderation_settings(self); err = aq_nic_update_interrupt_moderation_settings(self);
if (err) if (err)
goto err_exit; goto err_exit;
INIT_WORK(&self->service_task, aq_nic_service_task);
timer_setup(&self->service_timer, aq_nic_service_timer_cb, 0); timer_setup(&self->service_timer, aq_nic_service_timer_cb, 0);
aq_nic_service_timer_cb(&self->service_timer); aq_nic_service_timer_cb(&self->service_timer);
...@@ -910,6 +922,7 @@ int aq_nic_stop(struct aq_nic_s *self) ...@@ -910,6 +922,7 @@ int aq_nic_stop(struct aq_nic_s *self)
netif_carrier_off(self->ndev); netif_carrier_off(self->ndev);
del_timer_sync(&self->service_timer); del_timer_sync(&self->service_timer);
cancel_work_sync(&self->service_task);
self->aq_hw_ops->hw_irq_disable(self->aq_hw, AQ_CFG_IRQ_MASK); self->aq_hw_ops->hw_irq_disable(self->aq_hw, AQ_CFG_IRQ_MASK);
......
...@@ -93,6 +93,7 @@ struct aq_nic_s { ...@@ -93,6 +93,7 @@ struct aq_nic_s {
const struct aq_fw_ops *aq_fw_ops; const struct aq_fw_ops *aq_fw_ops;
struct aq_nic_cfg_s aq_nic_cfg; struct aq_nic_cfg_s aq_nic_cfg;
struct timer_list service_timer; struct timer_list service_timer;
struct work_struct service_task;
struct timer_list polling_timer; struct timer_list polling_timer;
struct aq_hw_link_status_s link_status; struct aq_hw_link_status_s link_status;
struct { struct {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment